openssl/lk: Adding openssl 1.0.0a to LK

This is the same openssl 1.0.0a in the external
folder of Android tree with Android.mk files.

Change-Id: Ie21f916d5925042c260f0640cfaec231f46cf74a
diff --git a/lib/openssl/ssl/Android.mk b/lib/openssl/ssl/Android.mk
new file mode 100644
index 0000000..fb9d34c
--- /dev/null
+++ b/lib/openssl/ssl/Android.mk
@@ -0,0 +1,75 @@
+LOCAL_PATH:= $(call my-dir)
+
+local_c_includes := \
+	external/openssl \
+	external/openssl/include \
+	external/openssl/crypto
+
+local_src_files:= \
+	s2_meth.c \
+	s2_srvr.c \
+	s2_clnt.c \
+	s2_lib.c \
+	s2_enc.c \
+	s2_pkt.c \
+	s3_meth.c \
+	s3_srvr.c \
+	s3_clnt.c \
+	s3_lib.c \
+	s3_enc.c \
+	s3_pkt.c \
+	s3_both.c \
+	s23_meth.c \
+	s23_srvr.c \
+	s23_clnt.c \
+	s23_lib.c \
+	s23_pkt.c \
+	t1_meth.c \
+	t1_srvr.c \
+	t1_clnt.c \
+	t1_lib.c \
+	t1_enc.c \
+	t1_reneg.c \
+	ssl_lib.c \
+	ssl_err2.c \
+	ssl_cert.c \
+	ssl_sess.c \
+	ssl_ciph.c \
+	ssl_stat.c \
+	ssl_rsa.c \
+	ssl_asn1.c \
+	ssl_txt.c \
+	ssl_algs.c \
+	bio_ssl.c \
+	ssl_err.c \
+	kssl.c
+
+include $(CLEAR_VARS)
+include $(LOCAL_PATH)/../android-config.mk
+LOCAL_SRC_FILES += $(local_src_files)
+LOCAL_C_INCLUDES += $(local_c_includes)
+LOCAL_SHARED_LIBRARIES += libcrypto
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE:= libssl
+include $(BUILD_SHARED_LIBRARY)
+
+ifeq ($(WITH_HOST_DALVIK),true)
+    include $(CLEAR_VARS)
+    include $(LOCAL_PATH)/../android-config.mk
+    LOCAL_SRC_FILES += $(local_src_files)
+    LOCAL_C_INCLUDES += $(local_c_includes)
+    LOCAL_SHARED_LIBRARIES += libcrypto
+    LOCAL_MODULE_TAGS := optional
+    LOCAL_MODULE:= libssl
+    include $(BUILD_HOST_SHARED_LIBRARY)
+endif
+
+# ssltest
+include $(CLEAR_VARS)
+include $(LOCAL_PATH)/../android-config.mk
+LOCAL_SRC_FILES:= ssltest.c
+LOCAL_C_INCLUDES += $(local_c_includes)
+LOCAL_SHARED_LIBRARIES := libssl libcrypto
+LOCAL_MODULE:= ssltest
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_EXECUTABLE)
diff --git a/lib/openssl/ssl/Makefile b/lib/openssl/ssl/Makefile
new file mode 100644
index 0000000..2b275fa
--- /dev/null
+++ b/lib/openssl/ssl/Makefile
@@ -0,0 +1,975 @@
+#
+# OpenSSL/ssl/Makefile
+#
+
+DIR=	ssl
+TOP=	..
+CC=	cc
+INCLUDES= -I../crypto -I$(TOP) -I../include $(KRB5_INCLUDES)
+CFLAG=-g
+MAKEFILE=	Makefile
+AR=		ar r
+# KRB5 stuff
+KRB5_INCLUDES=
+
+CFLAGS= $(INCLUDES) $(CFLAG)
+
+GENERAL=Makefile README ssl-lib.com install.com
+TEST=ssltest.c
+APPS=
+
+LIB=$(TOP)/libssl.a
+SHARED_LIB= libssl$(SHLIB_EXT)
+LIBSRC=	\
+	s2_meth.c   s2_srvr.c s2_clnt.c  s2_lib.c  s2_enc.c s2_pkt.c \
+	s3_meth.c   s3_srvr.c s3_clnt.c  s3_lib.c  s3_enc.c s3_pkt.c s3_both.c \
+	s23_meth.c s23_srvr.c s23_clnt.c s23_lib.c          s23_pkt.c \
+	t1_meth.c   t1_srvr.c t1_clnt.c  t1_lib.c  t1_enc.c \
+	d1_meth.c   d1_srvr.c d1_clnt.c  d1_lib.c  d1_pkt.c \
+	d1_both.c d1_enc.c \
+	ssl_lib.c ssl_err2.c ssl_cert.c ssl_sess.c \
+	ssl_ciph.c ssl_stat.c ssl_rsa.c \
+	ssl_asn1.c ssl_txt.c ssl_algs.c \
+	bio_ssl.c ssl_err.c kssl.c t1_reneg.c
+LIBOBJ= \
+	s2_meth.o  s2_srvr.o  s2_clnt.o  s2_lib.o  s2_enc.o s2_pkt.o \
+	s3_meth.o  s3_srvr.o  s3_clnt.o  s3_lib.o  s3_enc.o s3_pkt.o s3_both.o \
+	s23_meth.o s23_srvr.o s23_clnt.o s23_lib.o          s23_pkt.o \
+	t1_meth.o   t1_srvr.o t1_clnt.o  t1_lib.o  t1_enc.o \
+	d1_meth.o   d1_srvr.o d1_clnt.o  d1_lib.o  d1_pkt.o \
+	d1_both.o d1_enc.o \
+	ssl_lib.o ssl_err2.o ssl_cert.o ssl_sess.o \
+	ssl_ciph.o ssl_stat.o ssl_rsa.o \
+	ssl_asn1.o ssl_txt.o ssl_algs.o \
+	bio_ssl.o ssl_err.o kssl.o t1_reneg.o
+
+SRC= $(LIBSRC)
+
+EXHEADER= ssl.h ssl2.h ssl3.h ssl23.h tls1.h dtls1.h kssl.h
+HEADER=	$(EXHEADER) ssl_locl.h kssl_lcl.h
+
+ALL=    $(GENERAL) $(SRC) $(HEADER)
+
+top:
+	(cd ..; $(MAKE) DIRS=$(DIR) all)
+
+all:	shared
+
+lib:	$(LIBOBJ)
+	$(AR) $(LIB) $(LIBOBJ)
+	$(RANLIB) $(LIB) || echo Never mind.
+	@touch lib
+
+shared: lib
+	if [ -n "$(SHARED_LIBS)" ]; then \
+		(cd ..; $(MAKE) $(SHARED_LIB)); \
+	fi
+
+files:
+	$(PERL) $(TOP)/util/files.pl Makefile >> $(TOP)/MINFO
+
+links:
+	@$(PERL) $(TOP)/util/mklink.pl ../include/openssl $(EXHEADER)
+	@$(PERL) $(TOP)/util/mklink.pl ../test $(TEST)
+	@$(PERL) $(TOP)/util/mklink.pl ../apps $(APPS)
+
+install:
+	@[ -n "$(INSTALLTOP)" ] # should be set by top Makefile...
+	@headerlist="$(EXHEADER)"; for i in $$headerlist ; \
+	do  \
+	(cp $$i $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i; \
+	chmod 644 $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i ); \
+	done;
+
+tags:
+	ctags $(SRC)
+
+tests:
+
+lint:
+	lint -DLINT $(INCLUDES) $(SRC)>fluff
+
+depend:
+	@if [ -z "$(THIS)" ]; then \
+	    $(MAKE) -f $(TOP)/Makefile reflect THIS=$@; \
+	else \
+	    $(MAKEDEPEND) -- $(CFLAG) $(INCLUDES) $(DEPFLAG) -- $(PROGS) $(LIBSRC); \
+	fi
+
+dclean:
+	$(PERL) -pe 'if (/^# DO NOT DELETE THIS LINE/) {print; exit(0);}' $(MAKEFILE) >Makefile.new
+	mv -f Makefile.new $(MAKEFILE)
+
+clean:
+	rm -f *.o *.obj lib tags core .pure .nfs* *.old *.bak fluff
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
+
+bio_ssl.o: ../include/openssl/asn1.h ../include/openssl/bio.h
+bio_ssl.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+bio_ssl.o: ../include/openssl/crypto.h ../include/openssl/dtls1.h
+bio_ssl.o: ../include/openssl/e_os2.h ../include/openssl/ec.h
+bio_ssl.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h
+bio_ssl.o: ../include/openssl/err.h ../include/openssl/evp.h
+bio_ssl.o: ../include/openssl/hmac.h ../include/openssl/kssl.h
+bio_ssl.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h
+bio_ssl.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
+bio_ssl.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
+bio_ssl.o: ../include/openssl/pem.h ../include/openssl/pem2.h
+bio_ssl.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h
+bio_ssl.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+bio_ssl.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
+bio_ssl.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
+bio_ssl.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+bio_ssl.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+bio_ssl.o: ../include/openssl/x509_vfy.h bio_ssl.c
+d1_both.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+d1_both.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+d1_both.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+d1_both.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+d1_both.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+d1_both.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+d1_both.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+d1_both.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+d1_both.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+d1_both.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+d1_both.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+d1_both.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+d1_both.o: ../include/openssl/pqueue.h ../include/openssl/rand.h
+d1_both.o: ../include/openssl/rsa.h ../include/openssl/safestack.h
+d1_both.o: ../include/openssl/sha.h ../include/openssl/ssl.h
+d1_both.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h
+d1_both.o: ../include/openssl/ssl3.h ../include/openssl/stack.h
+d1_both.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h
+d1_both.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h d1_both.c
+d1_both.o: ssl_locl.h
+d1_clnt.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+d1_clnt.o: ../include/openssl/bn.h ../include/openssl/buffer.h
+d1_clnt.o: ../include/openssl/comp.h ../include/openssl/crypto.h
+d1_clnt.o: ../include/openssl/dh.h ../include/openssl/dsa.h
+d1_clnt.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+d1_clnt.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+d1_clnt.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+d1_clnt.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+d1_clnt.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+d1_clnt.o: ../include/openssl/md5.h ../include/openssl/obj_mac.h
+d1_clnt.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
+d1_clnt.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
+d1_clnt.o: ../include/openssl/pem.h ../include/openssl/pem2.h
+d1_clnt.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h
+d1_clnt.o: ../include/openssl/rand.h ../include/openssl/rsa.h
+d1_clnt.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+d1_clnt.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
+d1_clnt.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
+d1_clnt.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+d1_clnt.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+d1_clnt.o: ../include/openssl/x509_vfy.h d1_clnt.c kssl_lcl.h ssl_locl.h
+d1_enc.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+d1_enc.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+d1_enc.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+d1_enc.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+d1_enc.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+d1_enc.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+d1_enc.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+d1_enc.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+d1_enc.o: ../include/openssl/md5.h ../include/openssl/obj_mac.h
+d1_enc.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
+d1_enc.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
+d1_enc.o: ../include/openssl/pem.h ../include/openssl/pem2.h
+d1_enc.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h
+d1_enc.o: ../include/openssl/rand.h ../include/openssl/rsa.h
+d1_enc.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+d1_enc.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
+d1_enc.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
+d1_enc.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+d1_enc.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+d1_enc.o: ../include/openssl/x509_vfy.h d1_enc.c ssl_locl.h
+d1_lib.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+d1_lib.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+d1_lib.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+d1_lib.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+d1_lib.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+d1_lib.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+d1_lib.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+d1_lib.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+d1_lib.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+d1_lib.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+d1_lib.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+d1_lib.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+d1_lib.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h
+d1_lib.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+d1_lib.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
+d1_lib.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
+d1_lib.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+d1_lib.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+d1_lib.o: ../include/openssl/x509_vfy.h d1_lib.c ssl_locl.h
+d1_meth.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+d1_meth.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+d1_meth.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+d1_meth.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+d1_meth.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+d1_meth.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+d1_meth.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+d1_meth.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+d1_meth.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+d1_meth.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+d1_meth.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+d1_meth.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+d1_meth.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h
+d1_meth.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+d1_meth.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
+d1_meth.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
+d1_meth.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+d1_meth.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+d1_meth.o: ../include/openssl/x509_vfy.h d1_meth.c ssl_locl.h
+d1_pkt.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+d1_pkt.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+d1_pkt.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+d1_pkt.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+d1_pkt.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+d1_pkt.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+d1_pkt.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+d1_pkt.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+d1_pkt.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+d1_pkt.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+d1_pkt.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+d1_pkt.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+d1_pkt.o: ../include/openssl/pqueue.h ../include/openssl/rand.h
+d1_pkt.o: ../include/openssl/rsa.h ../include/openssl/safestack.h
+d1_pkt.o: ../include/openssl/sha.h ../include/openssl/ssl.h
+d1_pkt.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h
+d1_pkt.o: ../include/openssl/ssl3.h ../include/openssl/stack.h
+d1_pkt.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h
+d1_pkt.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h d1_pkt.c
+d1_pkt.o: ssl_locl.h
+d1_srvr.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+d1_srvr.o: ../include/openssl/bn.h ../include/openssl/buffer.h
+d1_srvr.o: ../include/openssl/comp.h ../include/openssl/crypto.h
+d1_srvr.o: ../include/openssl/dh.h ../include/openssl/dsa.h
+d1_srvr.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+d1_srvr.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+d1_srvr.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+d1_srvr.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+d1_srvr.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+d1_srvr.o: ../include/openssl/md5.h ../include/openssl/obj_mac.h
+d1_srvr.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
+d1_srvr.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
+d1_srvr.o: ../include/openssl/pem.h ../include/openssl/pem2.h
+d1_srvr.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h
+d1_srvr.o: ../include/openssl/rand.h ../include/openssl/rsa.h
+d1_srvr.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+d1_srvr.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
+d1_srvr.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
+d1_srvr.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+d1_srvr.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+d1_srvr.o: ../include/openssl/x509_vfy.h d1_srvr.c ssl_locl.h
+kssl.o: ../include/openssl/asn1.h ../include/openssl/bio.h
+kssl.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+kssl.o: ../include/openssl/crypto.h ../include/openssl/dtls1.h
+kssl.o: ../include/openssl/e_os2.h ../include/openssl/ec.h
+kssl.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h
+kssl.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+kssl.o: ../include/openssl/krb5_asn.h ../include/openssl/kssl.h
+kssl.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h
+kssl.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
+kssl.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
+kssl.o: ../include/openssl/pem.h ../include/openssl/pem2.h
+kssl.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h
+kssl.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+kssl.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
+kssl.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
+kssl.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+kssl.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+kssl.o: ../include/openssl/x509_vfy.h kssl.c kssl_lcl.h
+s23_clnt.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+s23_clnt.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+s23_clnt.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+s23_clnt.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+s23_clnt.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+s23_clnt.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+s23_clnt.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+s23_clnt.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+s23_clnt.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+s23_clnt.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+s23_clnt.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+s23_clnt.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+s23_clnt.o: ../include/openssl/pqueue.h ../include/openssl/rand.h
+s23_clnt.o: ../include/openssl/rsa.h ../include/openssl/safestack.h
+s23_clnt.o: ../include/openssl/sha.h ../include/openssl/ssl.h
+s23_clnt.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h
+s23_clnt.o: ../include/openssl/ssl3.h ../include/openssl/stack.h
+s23_clnt.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h
+s23_clnt.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h s23_clnt.c
+s23_clnt.o: ssl_locl.h
+s23_lib.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+s23_lib.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+s23_lib.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+s23_lib.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+s23_lib.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+s23_lib.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+s23_lib.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+s23_lib.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+s23_lib.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+s23_lib.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+s23_lib.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+s23_lib.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+s23_lib.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h
+s23_lib.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+s23_lib.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
+s23_lib.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
+s23_lib.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+s23_lib.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+s23_lib.o: ../include/openssl/x509_vfy.h s23_lib.c ssl_locl.h
+s23_meth.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+s23_meth.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+s23_meth.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+s23_meth.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+s23_meth.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+s23_meth.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+s23_meth.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+s23_meth.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+s23_meth.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+s23_meth.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+s23_meth.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+s23_meth.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+s23_meth.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h
+s23_meth.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+s23_meth.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
+s23_meth.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
+s23_meth.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+s23_meth.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+s23_meth.o: ../include/openssl/x509_vfy.h s23_meth.c ssl_locl.h
+s23_pkt.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+s23_pkt.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+s23_pkt.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+s23_pkt.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+s23_pkt.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+s23_pkt.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+s23_pkt.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+s23_pkt.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+s23_pkt.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+s23_pkt.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+s23_pkt.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+s23_pkt.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+s23_pkt.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h
+s23_pkt.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+s23_pkt.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
+s23_pkt.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
+s23_pkt.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+s23_pkt.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+s23_pkt.o: ../include/openssl/x509_vfy.h s23_pkt.c ssl_locl.h
+s23_srvr.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+s23_srvr.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+s23_srvr.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+s23_srvr.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+s23_srvr.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+s23_srvr.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+s23_srvr.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+s23_srvr.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+s23_srvr.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+s23_srvr.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+s23_srvr.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+s23_srvr.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+s23_srvr.o: ../include/openssl/pqueue.h ../include/openssl/rand.h
+s23_srvr.o: ../include/openssl/rsa.h ../include/openssl/safestack.h
+s23_srvr.o: ../include/openssl/sha.h ../include/openssl/ssl.h
+s23_srvr.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h
+s23_srvr.o: ../include/openssl/ssl3.h ../include/openssl/stack.h
+s23_srvr.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h
+s23_srvr.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h s23_srvr.c
+s23_srvr.o: ssl_locl.h
+s2_clnt.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+s2_clnt.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+s2_clnt.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+s2_clnt.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+s2_clnt.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+s2_clnt.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+s2_clnt.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+s2_clnt.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+s2_clnt.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+s2_clnt.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+s2_clnt.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+s2_clnt.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+s2_clnt.o: ../include/openssl/pqueue.h ../include/openssl/rand.h
+s2_clnt.o: ../include/openssl/rsa.h ../include/openssl/safestack.h
+s2_clnt.o: ../include/openssl/sha.h ../include/openssl/ssl.h
+s2_clnt.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h
+s2_clnt.o: ../include/openssl/ssl3.h ../include/openssl/stack.h
+s2_clnt.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h
+s2_clnt.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h s2_clnt.c
+s2_clnt.o: ssl_locl.h
+s2_enc.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+s2_enc.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+s2_enc.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+s2_enc.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+s2_enc.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+s2_enc.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+s2_enc.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+s2_enc.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+s2_enc.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+s2_enc.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+s2_enc.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+s2_enc.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+s2_enc.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h
+s2_enc.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+s2_enc.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
+s2_enc.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
+s2_enc.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+s2_enc.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+s2_enc.o: ../include/openssl/x509_vfy.h s2_enc.c ssl_locl.h
+s2_lib.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+s2_lib.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+s2_lib.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+s2_lib.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+s2_lib.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+s2_lib.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+s2_lib.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+s2_lib.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+s2_lib.o: ../include/openssl/md5.h ../include/openssl/obj_mac.h
+s2_lib.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
+s2_lib.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
+s2_lib.o: ../include/openssl/pem.h ../include/openssl/pem2.h
+s2_lib.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h
+s2_lib.o: ../include/openssl/rsa.h ../include/openssl/safestack.h
+s2_lib.o: ../include/openssl/sha.h ../include/openssl/ssl.h
+s2_lib.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h
+s2_lib.o: ../include/openssl/ssl3.h ../include/openssl/stack.h
+s2_lib.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h
+s2_lib.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h s2_lib.c
+s2_lib.o: ssl_locl.h
+s2_meth.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+s2_meth.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+s2_meth.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+s2_meth.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+s2_meth.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+s2_meth.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+s2_meth.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+s2_meth.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+s2_meth.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+s2_meth.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+s2_meth.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+s2_meth.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+s2_meth.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h
+s2_meth.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+s2_meth.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
+s2_meth.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
+s2_meth.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+s2_meth.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+s2_meth.o: ../include/openssl/x509_vfy.h s2_meth.c ssl_locl.h
+s2_pkt.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+s2_pkt.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+s2_pkt.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+s2_pkt.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+s2_pkt.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+s2_pkt.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+s2_pkt.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+s2_pkt.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+s2_pkt.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+s2_pkt.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+s2_pkt.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+s2_pkt.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+s2_pkt.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h
+s2_pkt.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+s2_pkt.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
+s2_pkt.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
+s2_pkt.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+s2_pkt.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+s2_pkt.o: ../include/openssl/x509_vfy.h s2_pkt.c ssl_locl.h
+s2_srvr.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+s2_srvr.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+s2_srvr.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+s2_srvr.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+s2_srvr.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+s2_srvr.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+s2_srvr.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+s2_srvr.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+s2_srvr.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+s2_srvr.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+s2_srvr.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+s2_srvr.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+s2_srvr.o: ../include/openssl/pqueue.h ../include/openssl/rand.h
+s2_srvr.o: ../include/openssl/rsa.h ../include/openssl/safestack.h
+s2_srvr.o: ../include/openssl/sha.h ../include/openssl/ssl.h
+s2_srvr.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h
+s2_srvr.o: ../include/openssl/ssl3.h ../include/openssl/stack.h
+s2_srvr.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h
+s2_srvr.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h s2_srvr.c
+s2_srvr.o: ssl_locl.h
+s3_both.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+s3_both.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+s3_both.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+s3_both.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+s3_both.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+s3_both.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+s3_both.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+s3_both.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+s3_both.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+s3_both.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+s3_both.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+s3_both.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+s3_both.o: ../include/openssl/pqueue.h ../include/openssl/rand.h
+s3_both.o: ../include/openssl/rsa.h ../include/openssl/safestack.h
+s3_both.o: ../include/openssl/sha.h ../include/openssl/ssl.h
+s3_both.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h
+s3_both.o: ../include/openssl/ssl3.h ../include/openssl/stack.h
+s3_both.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h
+s3_both.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h s3_both.c
+s3_both.o: ssl_locl.h
+s3_clnt.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+s3_clnt.o: ../include/openssl/bn.h ../include/openssl/buffer.h
+s3_clnt.o: ../include/openssl/comp.h ../include/openssl/crypto.h
+s3_clnt.o: ../include/openssl/dh.h ../include/openssl/dsa.h
+s3_clnt.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+s3_clnt.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+s3_clnt.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h
+s3_clnt.o: ../include/openssl/err.h ../include/openssl/evp.h
+s3_clnt.o: ../include/openssl/hmac.h ../include/openssl/kssl.h
+s3_clnt.o: ../include/openssl/lhash.h ../include/openssl/md5.h
+s3_clnt.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+s3_clnt.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+s3_clnt.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+s3_clnt.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+s3_clnt.o: ../include/openssl/pqueue.h ../include/openssl/rand.h
+s3_clnt.o: ../include/openssl/rsa.h ../include/openssl/safestack.h
+s3_clnt.o: ../include/openssl/sha.h ../include/openssl/ssl.h
+s3_clnt.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h
+s3_clnt.o: ../include/openssl/ssl3.h ../include/openssl/stack.h
+s3_clnt.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h
+s3_clnt.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h kssl_lcl.h
+s3_clnt.o: s3_clnt.c ssl_locl.h
+s3_enc.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+s3_enc.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+s3_enc.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+s3_enc.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+s3_enc.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+s3_enc.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+s3_enc.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+s3_enc.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+s3_enc.o: ../include/openssl/md5.h ../include/openssl/obj_mac.h
+s3_enc.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
+s3_enc.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
+s3_enc.o: ../include/openssl/pem.h ../include/openssl/pem2.h
+s3_enc.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h
+s3_enc.o: ../include/openssl/rsa.h ../include/openssl/safestack.h
+s3_enc.o: ../include/openssl/sha.h ../include/openssl/ssl.h
+s3_enc.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h
+s3_enc.o: ../include/openssl/ssl3.h ../include/openssl/stack.h
+s3_enc.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h
+s3_enc.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h s3_enc.c
+s3_enc.o: ssl_locl.h
+s3_lib.o: ../crypto/ec/ec_lcl.h ../e_os.h ../include/openssl/asn1.h
+s3_lib.o: ../include/openssl/bio.h ../include/openssl/bn.h
+s3_lib.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+s3_lib.o: ../include/openssl/crypto.h ../include/openssl/dh.h
+s3_lib.o: ../include/openssl/dsa.h ../include/openssl/dtls1.h
+s3_lib.o: ../include/openssl/e_os2.h ../include/openssl/ec.h
+s3_lib.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h
+s3_lib.o: ../include/openssl/err.h ../include/openssl/evp.h
+s3_lib.o: ../include/openssl/hmac.h ../include/openssl/kssl.h
+s3_lib.o: ../include/openssl/lhash.h ../include/openssl/md5.h
+s3_lib.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+s3_lib.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+s3_lib.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+s3_lib.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+s3_lib.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h
+s3_lib.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+s3_lib.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
+s3_lib.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
+s3_lib.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+s3_lib.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+s3_lib.o: ../include/openssl/x509_vfy.h kssl_lcl.h s3_lib.c ssl_locl.h
+s3_meth.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+s3_meth.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+s3_meth.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+s3_meth.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+s3_meth.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+s3_meth.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+s3_meth.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+s3_meth.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+s3_meth.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+s3_meth.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+s3_meth.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+s3_meth.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+s3_meth.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h
+s3_meth.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+s3_meth.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
+s3_meth.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
+s3_meth.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+s3_meth.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+s3_meth.o: ../include/openssl/x509_vfy.h s3_meth.c ssl_locl.h
+s3_pkt.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+s3_pkt.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+s3_pkt.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+s3_pkt.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+s3_pkt.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+s3_pkt.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+s3_pkt.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+s3_pkt.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+s3_pkt.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+s3_pkt.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+s3_pkt.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+s3_pkt.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+s3_pkt.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h
+s3_pkt.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+s3_pkt.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
+s3_pkt.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
+s3_pkt.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+s3_pkt.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+s3_pkt.o: ../include/openssl/x509_vfy.h s3_pkt.c ssl_locl.h
+s3_srvr.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+s3_srvr.o: ../include/openssl/bn.h ../include/openssl/buffer.h
+s3_srvr.o: ../include/openssl/comp.h ../include/openssl/crypto.h
+s3_srvr.o: ../include/openssl/dh.h ../include/openssl/dsa.h
+s3_srvr.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+s3_srvr.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+s3_srvr.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+s3_srvr.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+s3_srvr.o: ../include/openssl/krb5_asn.h ../include/openssl/kssl.h
+s3_srvr.o: ../include/openssl/lhash.h ../include/openssl/md5.h
+s3_srvr.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+s3_srvr.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+s3_srvr.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+s3_srvr.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+s3_srvr.o: ../include/openssl/pqueue.h ../include/openssl/rand.h
+s3_srvr.o: ../include/openssl/rsa.h ../include/openssl/safestack.h
+s3_srvr.o: ../include/openssl/sha.h ../include/openssl/ssl.h
+s3_srvr.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h
+s3_srvr.o: ../include/openssl/ssl3.h ../include/openssl/stack.h
+s3_srvr.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h
+s3_srvr.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h kssl_lcl.h
+s3_srvr.o: s3_srvr.c ssl_locl.h
+ssl_algs.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+ssl_algs.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+ssl_algs.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+ssl_algs.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+ssl_algs.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+ssl_algs.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+ssl_algs.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+ssl_algs.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+ssl_algs.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+ssl_algs.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+ssl_algs.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+ssl_algs.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+ssl_algs.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h
+ssl_algs.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+ssl_algs.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
+ssl_algs.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
+ssl_algs.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+ssl_algs.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+ssl_algs.o: ../include/openssl/x509_vfy.h ssl_algs.c ssl_locl.h
+ssl_asn1.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/asn1_mac.h
+ssl_asn1.o: ../include/openssl/bio.h ../include/openssl/buffer.h
+ssl_asn1.o: ../include/openssl/comp.h ../include/openssl/crypto.h
+ssl_asn1.o: ../include/openssl/dsa.h ../include/openssl/dtls1.h
+ssl_asn1.o: ../include/openssl/e_os2.h ../include/openssl/ec.h
+ssl_asn1.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h
+ssl_asn1.o: ../include/openssl/err.h ../include/openssl/evp.h
+ssl_asn1.o: ../include/openssl/hmac.h ../include/openssl/kssl.h
+ssl_asn1.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h
+ssl_asn1.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
+ssl_asn1.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
+ssl_asn1.o: ../include/openssl/pem.h ../include/openssl/pem2.h
+ssl_asn1.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h
+ssl_asn1.o: ../include/openssl/rsa.h ../include/openssl/safestack.h
+ssl_asn1.o: ../include/openssl/sha.h ../include/openssl/ssl.h
+ssl_asn1.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h
+ssl_asn1.o: ../include/openssl/ssl3.h ../include/openssl/stack.h
+ssl_asn1.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h
+ssl_asn1.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h ssl_asn1.c
+ssl_asn1.o: ssl_locl.h
+ssl_cert.o: ../crypto/o_dir.h ../e_os.h ../include/openssl/asn1.h
+ssl_cert.o: ../include/openssl/bio.h ../include/openssl/bn.h
+ssl_cert.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+ssl_cert.o: ../include/openssl/conf.h ../include/openssl/crypto.h
+ssl_cert.o: ../include/openssl/dh.h ../include/openssl/dsa.h
+ssl_cert.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+ssl_cert.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+ssl_cert.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+ssl_cert.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+ssl_cert.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+ssl_cert.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+ssl_cert.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+ssl_cert.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+ssl_cert.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+ssl_cert.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h
+ssl_cert.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+ssl_cert.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
+ssl_cert.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
+ssl_cert.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+ssl_cert.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+ssl_cert.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h
+ssl_cert.o: ssl_cert.c ssl_locl.h
+ssl_ciph.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+ssl_ciph.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+ssl_ciph.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+ssl_ciph.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+ssl_ciph.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+ssl_ciph.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h
+ssl_ciph.o: ../include/openssl/err.h ../include/openssl/evp.h
+ssl_ciph.o: ../include/openssl/hmac.h ../include/openssl/kssl.h
+ssl_ciph.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h
+ssl_ciph.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
+ssl_ciph.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
+ssl_ciph.o: ../include/openssl/pem.h ../include/openssl/pem2.h
+ssl_ciph.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h
+ssl_ciph.o: ../include/openssl/rsa.h ../include/openssl/safestack.h
+ssl_ciph.o: ../include/openssl/sha.h ../include/openssl/ssl.h
+ssl_ciph.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h
+ssl_ciph.o: ../include/openssl/ssl3.h ../include/openssl/stack.h
+ssl_ciph.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h
+ssl_ciph.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h ssl_ciph.c
+ssl_ciph.o: ssl_locl.h
+ssl_err.o: ../include/openssl/asn1.h ../include/openssl/bio.h
+ssl_err.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+ssl_err.o: ../include/openssl/crypto.h ../include/openssl/dtls1.h
+ssl_err.o: ../include/openssl/e_os2.h ../include/openssl/ec.h
+ssl_err.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h
+ssl_err.o: ../include/openssl/err.h ../include/openssl/evp.h
+ssl_err.o: ../include/openssl/hmac.h ../include/openssl/kssl.h
+ssl_err.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h
+ssl_err.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
+ssl_err.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
+ssl_err.o: ../include/openssl/pem.h ../include/openssl/pem2.h
+ssl_err.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h
+ssl_err.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+ssl_err.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
+ssl_err.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
+ssl_err.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+ssl_err.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+ssl_err.o: ../include/openssl/x509_vfy.h ssl_err.c
+ssl_err2.o: ../include/openssl/asn1.h ../include/openssl/bio.h
+ssl_err2.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+ssl_err2.o: ../include/openssl/crypto.h ../include/openssl/dtls1.h
+ssl_err2.o: ../include/openssl/e_os2.h ../include/openssl/ec.h
+ssl_err2.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h
+ssl_err2.o: ../include/openssl/err.h ../include/openssl/evp.h
+ssl_err2.o: ../include/openssl/hmac.h ../include/openssl/kssl.h
+ssl_err2.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h
+ssl_err2.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
+ssl_err2.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
+ssl_err2.o: ../include/openssl/pem.h ../include/openssl/pem2.h
+ssl_err2.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h
+ssl_err2.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+ssl_err2.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
+ssl_err2.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
+ssl_err2.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+ssl_err2.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+ssl_err2.o: ../include/openssl/x509_vfy.h ssl_err2.c
+ssl_lib.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+ssl_lib.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+ssl_lib.o: ../include/openssl/conf.h ../include/openssl/crypto.h
+ssl_lib.o: ../include/openssl/dh.h ../include/openssl/dsa.h
+ssl_lib.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+ssl_lib.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+ssl_lib.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h
+ssl_lib.o: ../include/openssl/err.h ../include/openssl/evp.h
+ssl_lib.o: ../include/openssl/hmac.h ../include/openssl/kssl.h
+ssl_lib.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h
+ssl_lib.o: ../include/openssl/objects.h ../include/openssl/ocsp.h
+ssl_lib.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+ssl_lib.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+ssl_lib.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+ssl_lib.o: ../include/openssl/pqueue.h ../include/openssl/rand.h
+ssl_lib.o: ../include/openssl/rsa.h ../include/openssl/safestack.h
+ssl_lib.o: ../include/openssl/sha.h ../include/openssl/ssl.h
+ssl_lib.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h
+ssl_lib.o: ../include/openssl/ssl3.h ../include/openssl/stack.h
+ssl_lib.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h
+ssl_lib.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h
+ssl_lib.o: ../include/openssl/x509v3.h kssl_lcl.h ssl_lib.c ssl_locl.h
+ssl_rsa.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+ssl_rsa.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+ssl_rsa.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+ssl_rsa.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+ssl_rsa.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+ssl_rsa.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+ssl_rsa.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+ssl_rsa.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+ssl_rsa.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+ssl_rsa.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+ssl_rsa.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+ssl_rsa.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+ssl_rsa.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h
+ssl_rsa.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+ssl_rsa.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
+ssl_rsa.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
+ssl_rsa.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+ssl_rsa.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+ssl_rsa.o: ../include/openssl/x509_vfy.h ssl_locl.h ssl_rsa.c
+ssl_sess.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+ssl_sess.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+ssl_sess.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+ssl_sess.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+ssl_sess.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+ssl_sess.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h
+ssl_sess.o: ../include/openssl/err.h ../include/openssl/evp.h
+ssl_sess.o: ../include/openssl/hmac.h ../include/openssl/kssl.h
+ssl_sess.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h
+ssl_sess.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
+ssl_sess.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
+ssl_sess.o: ../include/openssl/pem.h ../include/openssl/pem2.h
+ssl_sess.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h
+ssl_sess.o: ../include/openssl/rand.h ../include/openssl/rsa.h
+ssl_sess.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+ssl_sess.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
+ssl_sess.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
+ssl_sess.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+ssl_sess.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+ssl_sess.o: ../include/openssl/x509_vfy.h ssl_locl.h ssl_sess.c
+ssl_stat.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+ssl_stat.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+ssl_stat.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+ssl_stat.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+ssl_stat.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+ssl_stat.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+ssl_stat.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+ssl_stat.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+ssl_stat.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+ssl_stat.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+ssl_stat.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+ssl_stat.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+ssl_stat.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h
+ssl_stat.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+ssl_stat.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
+ssl_stat.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
+ssl_stat.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+ssl_stat.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+ssl_stat.o: ../include/openssl/x509_vfy.h ssl_locl.h ssl_stat.c
+ssl_txt.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+ssl_txt.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+ssl_txt.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+ssl_txt.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+ssl_txt.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+ssl_txt.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+ssl_txt.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+ssl_txt.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+ssl_txt.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+ssl_txt.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+ssl_txt.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+ssl_txt.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+ssl_txt.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h
+ssl_txt.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+ssl_txt.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
+ssl_txt.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
+ssl_txt.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+ssl_txt.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+ssl_txt.o: ../include/openssl/x509_vfy.h ssl_locl.h ssl_txt.c
+t1_clnt.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+t1_clnt.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+t1_clnt.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+t1_clnt.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+t1_clnt.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+t1_clnt.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+t1_clnt.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+t1_clnt.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+t1_clnt.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+t1_clnt.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+t1_clnt.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+t1_clnt.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+t1_clnt.o: ../include/openssl/pqueue.h ../include/openssl/rand.h
+t1_clnt.o: ../include/openssl/rsa.h ../include/openssl/safestack.h
+t1_clnt.o: ../include/openssl/sha.h ../include/openssl/ssl.h
+t1_clnt.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h
+t1_clnt.o: ../include/openssl/ssl3.h ../include/openssl/stack.h
+t1_clnt.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h
+t1_clnt.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h ssl_locl.h
+t1_clnt.o: t1_clnt.c
+t1_enc.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+t1_enc.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+t1_enc.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+t1_enc.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+t1_enc.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+t1_enc.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+t1_enc.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+t1_enc.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+t1_enc.o: ../include/openssl/md5.h ../include/openssl/obj_mac.h
+t1_enc.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
+t1_enc.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
+t1_enc.o: ../include/openssl/pem.h ../include/openssl/pem2.h
+t1_enc.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h
+t1_enc.o: ../include/openssl/rsa.h ../include/openssl/safestack.h
+t1_enc.o: ../include/openssl/sha.h ../include/openssl/ssl.h
+t1_enc.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h
+t1_enc.o: ../include/openssl/ssl3.h ../include/openssl/stack.h
+t1_enc.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h
+t1_enc.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h ssl_locl.h
+t1_enc.o: t1_enc.c
+t1_lib.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+t1_lib.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+t1_lib.o: ../include/openssl/conf.h ../include/openssl/crypto.h
+t1_lib.o: ../include/openssl/dsa.h ../include/openssl/dtls1.h
+t1_lib.o: ../include/openssl/e_os2.h ../include/openssl/ec.h
+t1_lib.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h
+t1_lib.o: ../include/openssl/err.h ../include/openssl/evp.h
+t1_lib.o: ../include/openssl/hmac.h ../include/openssl/kssl.h
+t1_lib.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h
+t1_lib.o: ../include/openssl/objects.h ../include/openssl/ocsp.h
+t1_lib.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+t1_lib.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+t1_lib.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+t1_lib.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h
+t1_lib.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+t1_lib.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
+t1_lib.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
+t1_lib.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+t1_lib.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+t1_lib.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h ssl_locl.h
+t1_lib.o: t1_lib.c
+t1_meth.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+t1_meth.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+t1_meth.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+t1_meth.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+t1_meth.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+t1_meth.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+t1_meth.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+t1_meth.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+t1_meth.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+t1_meth.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+t1_meth.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+t1_meth.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+t1_meth.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h
+t1_meth.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+t1_meth.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
+t1_meth.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
+t1_meth.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+t1_meth.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+t1_meth.o: ../include/openssl/x509_vfy.h ssl_locl.h t1_meth.c
+t1_reneg.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+t1_reneg.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+t1_reneg.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+t1_reneg.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+t1_reneg.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+t1_reneg.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+t1_reneg.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+t1_reneg.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+t1_reneg.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+t1_reneg.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+t1_reneg.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+t1_reneg.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+t1_reneg.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h
+t1_reneg.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+t1_reneg.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
+t1_reneg.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
+t1_reneg.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+t1_reneg.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+t1_reneg.o: ../include/openssl/x509_vfy.h ssl_locl.h t1_reneg.c
+t1_srvr.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+t1_srvr.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+t1_srvr.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
+t1_srvr.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+t1_srvr.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+t1_srvr.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+t1_srvr.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+t1_srvr.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+t1_srvr.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+t1_srvr.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+t1_srvr.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+t1_srvr.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+t1_srvr.o: ../include/openssl/pqueue.h ../include/openssl/rand.h
+t1_srvr.o: ../include/openssl/rsa.h ../include/openssl/safestack.h
+t1_srvr.o: ../include/openssl/sha.h ../include/openssl/ssl.h
+t1_srvr.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h
+t1_srvr.o: ../include/openssl/ssl3.h ../include/openssl/stack.h
+t1_srvr.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h
+t1_srvr.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h ssl_locl.h
+t1_srvr.o: t1_srvr.c
diff --git a/lib/openssl/ssl/bio_ssl.c b/lib/openssl/ssl/bio_ssl.c
new file mode 100644
index 0000000..af319af
--- /dev/null
+++ b/lib/openssl/ssl/bio_ssl.c
@@ -0,0 +1,599 @@
+/* ssl/bio_ssl.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <openssl/crypto.h>
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+
+static int ssl_write(BIO *h, const char *buf, int num);
+static int ssl_read(BIO *h, char *buf, int size);
+static int ssl_puts(BIO *h, const char *str);
+static long ssl_ctrl(BIO *h, int cmd, long arg1, void *arg2);
+static int ssl_new(BIO *h);
+static int ssl_free(BIO *data);
+static long ssl_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp);
+typedef struct bio_ssl_st
+	{
+	SSL *ssl; /* The ssl handle :-) */
+	/* re-negotiate every time the total number of bytes is this size */
+	int num_renegotiates;
+	unsigned long renegotiate_count;
+	unsigned long byte_count;
+	unsigned long renegotiate_timeout;
+	unsigned long last_time;
+	} BIO_SSL;
+
+static BIO_METHOD methods_sslp=
+	{
+	BIO_TYPE_SSL,"ssl",
+	ssl_write,
+	ssl_read,
+	ssl_puts,
+	NULL, /* ssl_gets, */
+	ssl_ctrl,
+	ssl_new,
+	ssl_free,
+	ssl_callback_ctrl,
+	};
+
+BIO_METHOD *BIO_f_ssl(void)
+	{
+	return(&methods_sslp);
+	}
+
+static int ssl_new(BIO *bi)
+	{
+	BIO_SSL *bs;
+
+	bs=(BIO_SSL *)OPENSSL_malloc(sizeof(BIO_SSL));
+	if (bs == NULL)
+		{
+		BIOerr(BIO_F_SSL_NEW,ERR_R_MALLOC_FAILURE);
+		return(0);
+		}
+	memset(bs,0,sizeof(BIO_SSL));
+	bi->init=0;
+	bi->ptr=(char *)bs;
+	bi->flags=0;
+	return(1);
+	}
+
+static int ssl_free(BIO *a)
+	{
+	BIO_SSL *bs;
+
+	if (a == NULL) return(0);
+	bs=(BIO_SSL *)a->ptr;
+	if (bs->ssl != NULL) SSL_shutdown(bs->ssl);
+	if (a->shutdown)
+		{
+		if (a->init && (bs->ssl != NULL))
+			SSL_free(bs->ssl);
+		a->init=0;
+		a->flags=0;
+		}
+	if (a->ptr != NULL)
+		OPENSSL_free(a->ptr);
+	return(1);
+	}
+	
+static int ssl_read(BIO *b, char *out, int outl)
+	{
+	int ret=1;
+	BIO_SSL *sb;
+	SSL *ssl;
+	int retry_reason=0;
+	int r=0;
+
+	if (out == NULL) return(0);
+	sb=(BIO_SSL *)b->ptr;
+	ssl=sb->ssl;
+
+	BIO_clear_retry_flags(b);
+
+#if 0
+	if (!SSL_is_init_finished(ssl))
+		{
+/*		ret=SSL_do_handshake(ssl); */
+		if (ret > 0)
+			{
+
+			outflags=(BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY);
+			ret= -1;
+			goto end;
+			}
+		}
+#endif
+/*	if (ret > 0) */
+	ret=SSL_read(ssl,out,outl);
+
+	switch (SSL_get_error(ssl,ret))
+		{
+	case SSL_ERROR_NONE:
+		if (ret <= 0) break;
+		if (sb->renegotiate_count > 0)
+			{
+			sb->byte_count+=ret;
+			if (sb->byte_count > sb->renegotiate_count)
+				{
+				sb->byte_count=0;
+				sb->num_renegotiates++;
+				SSL_renegotiate(ssl);
+				r=1;
+				}
+			}
+		if ((sb->renegotiate_timeout > 0) && (!r))
+			{
+			unsigned long tm;
+
+			tm=(unsigned long)time(NULL);
+			if (tm > sb->last_time+sb->renegotiate_timeout)
+				{
+				sb->last_time=tm;
+				sb->num_renegotiates++;
+				SSL_renegotiate(ssl);
+				}
+			}
+
+		break;
+	case SSL_ERROR_WANT_READ:
+		BIO_set_retry_read(b);
+		break;
+	case SSL_ERROR_WANT_WRITE:
+		BIO_set_retry_write(b);
+		break;
+	case SSL_ERROR_WANT_X509_LOOKUP:
+		BIO_set_retry_special(b);
+		retry_reason=BIO_RR_SSL_X509_LOOKUP;
+		break;
+	case SSL_ERROR_WANT_ACCEPT:
+		BIO_set_retry_special(b);
+		retry_reason=BIO_RR_ACCEPT;
+		break;
+	case SSL_ERROR_WANT_CONNECT:
+		BIO_set_retry_special(b);
+		retry_reason=BIO_RR_CONNECT;
+		break;
+	case SSL_ERROR_SYSCALL:
+	case SSL_ERROR_SSL:
+	case SSL_ERROR_ZERO_RETURN:
+	default:
+		break;
+		}
+
+	b->retry_reason=retry_reason;
+	return(ret);
+	}
+
+static int ssl_write(BIO *b, const char *out, int outl)
+	{
+	int ret,r=0;
+	int retry_reason=0;
+	SSL *ssl;
+	BIO_SSL *bs;
+
+	if (out == NULL) return(0);
+	bs=(BIO_SSL *)b->ptr;
+	ssl=bs->ssl;
+
+	BIO_clear_retry_flags(b);
+
+/*	ret=SSL_do_handshake(ssl);
+	if (ret > 0) */
+	ret=SSL_write(ssl,out,outl);
+
+	switch (SSL_get_error(ssl,ret))
+		{
+	case SSL_ERROR_NONE:
+		if (ret <= 0) break;
+		if (bs->renegotiate_count > 0)
+			{
+			bs->byte_count+=ret;
+			if (bs->byte_count > bs->renegotiate_count)
+				{
+				bs->byte_count=0;
+				bs->num_renegotiates++;
+				SSL_renegotiate(ssl);
+				r=1;
+				}
+			}
+		if ((bs->renegotiate_timeout > 0) && (!r))
+			{
+			unsigned long tm;
+
+			tm=(unsigned long)time(NULL);
+			if (tm > bs->last_time+bs->renegotiate_timeout)
+				{
+				bs->last_time=tm;
+				bs->num_renegotiates++;
+				SSL_renegotiate(ssl);
+				}
+			}
+		break;
+	case SSL_ERROR_WANT_WRITE:
+		BIO_set_retry_write(b);
+		break;
+	case SSL_ERROR_WANT_READ:
+		BIO_set_retry_read(b);
+		break;
+	case SSL_ERROR_WANT_X509_LOOKUP:
+		BIO_set_retry_special(b);
+		retry_reason=BIO_RR_SSL_X509_LOOKUP;
+		break;
+	case SSL_ERROR_WANT_CONNECT:
+		BIO_set_retry_special(b);
+		retry_reason=BIO_RR_CONNECT;
+	case SSL_ERROR_SYSCALL:
+	case SSL_ERROR_SSL:
+	default:
+		break;
+		}
+
+	b->retry_reason=retry_reason;
+	return(ret);
+	}
+
+static long ssl_ctrl(BIO *b, int cmd, long num, void *ptr)
+	{
+	SSL **sslp,*ssl;
+	BIO_SSL *bs;
+	BIO *dbio,*bio;
+	long ret=1;
+
+	bs=(BIO_SSL *)b->ptr;
+	ssl=bs->ssl;
+	if ((ssl == NULL)  && (cmd != BIO_C_SET_SSL))
+		return(0);
+	switch (cmd)
+		{
+	case BIO_CTRL_RESET:
+		SSL_shutdown(ssl);
+
+		if (ssl->handshake_func == ssl->method->ssl_connect)
+			SSL_set_connect_state(ssl);
+		else if (ssl->handshake_func == ssl->method->ssl_accept)
+			SSL_set_accept_state(ssl);
+
+		SSL_clear(ssl);
+
+		if (b->next_bio != NULL)
+			ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
+		else if (ssl->rbio != NULL)
+			ret=BIO_ctrl(ssl->rbio,cmd,num,ptr);
+		else
+			ret=1;
+		break;
+	case BIO_CTRL_INFO:
+		ret=0;
+		break;
+	case BIO_C_SSL_MODE:
+		if (num) /* client mode */
+			SSL_set_connect_state(ssl);
+		else
+			SSL_set_accept_state(ssl);
+		break;
+	case BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT:
+		ret=bs->renegotiate_timeout;
+		if (num < 60) num=5;
+		bs->renegotiate_timeout=(unsigned long)num;
+		bs->last_time=(unsigned long)time(NULL);
+		break;
+	case BIO_C_SET_SSL_RENEGOTIATE_BYTES:
+		ret=bs->renegotiate_count;
+		if ((long)num >=512)
+			bs->renegotiate_count=(unsigned long)num;
+		break;
+	case BIO_C_GET_SSL_NUM_RENEGOTIATES:
+		ret=bs->num_renegotiates;
+		break;
+	case BIO_C_SET_SSL:
+		if (ssl != NULL)
+			ssl_free(b);
+		b->shutdown=(int)num;
+		ssl=(SSL *)ptr;
+		((BIO_SSL *)b->ptr)->ssl=ssl;
+		bio=SSL_get_rbio(ssl);
+		if (bio != NULL)
+			{
+			if (b->next_bio != NULL)
+				BIO_push(bio,b->next_bio);
+			b->next_bio=bio;
+			CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO);
+			}
+		b->init=1;
+		break;
+	case BIO_C_GET_SSL:
+		if (ptr != NULL)
+			{
+			sslp=(SSL **)ptr;
+			*sslp=ssl;
+			}
+		else
+			ret=0;
+		break;
+	case BIO_CTRL_GET_CLOSE:
+		ret=b->shutdown;
+		break;
+	case BIO_CTRL_SET_CLOSE:
+		b->shutdown=(int)num;
+		break;
+	case BIO_CTRL_WPENDING:
+		ret=BIO_ctrl(ssl->wbio,cmd,num,ptr);
+		break;
+	case BIO_CTRL_PENDING:
+		ret=SSL_pending(ssl);
+		if (ret == 0)
+			ret=BIO_pending(ssl->rbio);
+		break;
+	case BIO_CTRL_FLUSH:
+		BIO_clear_retry_flags(b);
+		ret=BIO_ctrl(ssl->wbio,cmd,num,ptr);
+		BIO_copy_next_retry(b);
+		break;
+	case BIO_CTRL_PUSH:
+		if ((b->next_bio != NULL) && (b->next_bio != ssl->rbio))
+			{
+			SSL_set_bio(ssl,b->next_bio,b->next_bio);
+			CRYPTO_add(&b->next_bio->references,1,CRYPTO_LOCK_BIO);
+			}
+		break;
+	case BIO_CTRL_POP:
+		/* Only detach if we are the BIO explicitly being popped */
+		if (b == ptr)
+			{
+			/* Shouldn't happen in practice because the
+			 * rbio and wbio are the same when pushed.
+			 */
+			if (ssl->rbio != ssl->wbio)
+				BIO_free_all(ssl->wbio);
+			if (b->next_bio != NULL)
+				CRYPTO_add(&b->next_bio->references,-1,CRYPTO_LOCK_BIO);
+			ssl->wbio=NULL;
+			ssl->rbio=NULL;
+			}
+		break;
+	case BIO_C_DO_STATE_MACHINE:
+		BIO_clear_retry_flags(b);
+
+		b->retry_reason=0;
+		ret=(int)SSL_do_handshake(ssl);
+
+		switch (SSL_get_error(ssl,(int)ret))
+			{
+		case SSL_ERROR_WANT_READ:
+			BIO_set_flags(b,
+				BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY);
+			break;
+		case SSL_ERROR_WANT_WRITE:
+			BIO_set_flags(b,
+				BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY);
+			break;
+		case SSL_ERROR_WANT_CONNECT:
+			BIO_set_flags(b,
+				BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY);
+			b->retry_reason=b->next_bio->retry_reason;
+			break;
+		default:
+			break;
+			}
+		break;
+	case BIO_CTRL_DUP:
+		dbio=(BIO *)ptr;
+		if (((BIO_SSL *)dbio->ptr)->ssl != NULL)
+			SSL_free(((BIO_SSL *)dbio->ptr)->ssl);
+		((BIO_SSL *)dbio->ptr)->ssl=SSL_dup(ssl);
+		((BIO_SSL *)dbio->ptr)->renegotiate_count=
+			((BIO_SSL *)b->ptr)->renegotiate_count;
+		((BIO_SSL *)dbio->ptr)->byte_count=
+			((BIO_SSL *)b->ptr)->byte_count;
+		((BIO_SSL *)dbio->ptr)->renegotiate_timeout=
+			((BIO_SSL *)b->ptr)->renegotiate_timeout;
+		((BIO_SSL *)dbio->ptr)->last_time=
+			((BIO_SSL *)b->ptr)->last_time;
+		ret=(((BIO_SSL *)dbio->ptr)->ssl != NULL);
+		break;
+	case BIO_C_GET_FD:
+		ret=BIO_ctrl(ssl->rbio,cmd,num,ptr);
+		break;
+	case BIO_CTRL_SET_CALLBACK:
+		{
+#if 0 /* FIXME: Should this be used?  -- Richard Levitte */
+		SSLerr(SSL_F_SSL_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		ret = -1;
+#else
+		ret=0;
+#endif
+		}
+		break;
+	case BIO_CTRL_GET_CALLBACK:
+		{
+		void (**fptr)(const SSL *xssl,int type,int val);
+
+		fptr=(void (**)(const SSL *xssl,int type,int val))ptr;
+		*fptr=SSL_get_info_callback(ssl);
+		}
+		break;
+	default:
+		ret=BIO_ctrl(ssl->rbio,cmd,num,ptr);
+		break;
+		}
+	return(ret);
+	}
+
+static long ssl_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
+	{
+	SSL *ssl;
+	BIO_SSL *bs;
+	long ret=1;
+
+	bs=(BIO_SSL *)b->ptr;
+	ssl=bs->ssl;
+	switch (cmd)
+		{
+	case BIO_CTRL_SET_CALLBACK:
+		{
+		/* FIXME: setting this via a completely different prototype
+		   seems like a crap idea */
+		SSL_set_info_callback(ssl,(void (*)(const SSL *,int,int))fp);
+		}
+		break;
+	default:
+		ret=BIO_callback_ctrl(ssl->rbio,cmd,fp);
+		break;
+		}
+	return(ret);
+	}
+
+static int ssl_puts(BIO *bp, const char *str)
+	{
+	int n,ret;
+
+	n=strlen(str);
+	ret=BIO_write(bp,str,n);
+	return(ret);
+	}
+
+BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx)
+	{
+#ifndef OPENSSL_NO_SOCK
+	BIO *ret=NULL,*buf=NULL,*ssl=NULL;
+
+	if ((buf=BIO_new(BIO_f_buffer())) == NULL)
+		return(NULL);
+	if ((ssl=BIO_new_ssl_connect(ctx)) == NULL)
+		goto err;
+	if ((ret=BIO_push(buf,ssl)) == NULL)
+		goto err;
+	return(ret);
+err:
+	if (buf != NULL) BIO_free(buf);
+	if (ssl != NULL) BIO_free(ssl);
+#endif
+	return(NULL);
+	}
+
+BIO *BIO_new_ssl_connect(SSL_CTX *ctx)
+	{
+	BIO *ret=NULL,*con=NULL,*ssl=NULL;
+
+	if ((con=BIO_new(BIO_s_connect())) == NULL)
+		return(NULL);
+	if ((ssl=BIO_new_ssl(ctx,1)) == NULL)
+		goto err;
+	if ((ret=BIO_push(ssl,con)) == NULL)
+		goto err;
+	return(ret);
+err:
+	if (con != NULL) BIO_free(con);
+	return(NULL);
+	}
+
+BIO *BIO_new_ssl(SSL_CTX *ctx, int client)
+	{
+	BIO *ret;
+	SSL *ssl;
+
+	if ((ret=BIO_new(BIO_f_ssl())) == NULL)
+		return(NULL);
+	if ((ssl=SSL_new(ctx)) == NULL)
+		{
+		BIO_free(ret);
+		return(NULL);
+		}
+	if (client)
+		SSL_set_connect_state(ssl);
+	else
+		SSL_set_accept_state(ssl);
+		
+	BIO_set_ssl(ret,ssl,BIO_CLOSE);
+	return(ret);
+	}
+
+int BIO_ssl_copy_session_id(BIO *t, BIO *f)
+	{
+	t=BIO_find_type(t,BIO_TYPE_SSL);
+	f=BIO_find_type(f,BIO_TYPE_SSL);
+	if ((t == NULL) || (f == NULL))
+		return(0);
+	if (	(((BIO_SSL *)t->ptr)->ssl == NULL) || 
+		(((BIO_SSL *)f->ptr)->ssl == NULL))
+		return(0);
+	SSL_copy_session_id(((BIO_SSL *)t->ptr)->ssl,((BIO_SSL *)f->ptr)->ssl);
+	return(1);
+	}
+
+void BIO_ssl_shutdown(BIO *b)
+	{
+	SSL *s;
+
+	while (b != NULL)
+		{
+		if (b->method->type == BIO_TYPE_SSL)
+			{
+			s=((BIO_SSL *)b->ptr)->ssl;
+			SSL_shutdown(s);
+			break;
+			}
+		b=b->next_bio;
+		}
+	}
diff --git a/lib/openssl/ssl/d1_both.c b/lib/openssl/ssl/d1_both.c
new file mode 100644
index 0000000..4ce4064
--- /dev/null
+++ b/lib/openssl/ssl/d1_both.c
@@ -0,0 +1,1418 @@
+/* ssl/d1_both.c */
+/* 
+ * DTLS implementation written by Nagendra Modadugu
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.  
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <limits.h>
+#include <string.h>
+#include <stdio.h>
+#include "ssl_locl.h"
+#include <openssl/buffer.h>
+#include <openssl/rand.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+
+#define RSMBLY_BITMASK_SIZE(msg_len) (((msg_len) + 7) / 8)
+
+#define RSMBLY_BITMASK_MARK(bitmask, start, end) { \
+			if ((end) - (start) <= 8) { \
+				long ii; \
+				for (ii = (start); ii < (end); ii++) bitmask[((ii) >> 3)] |= (1 << ((ii) & 7)); \
+			} else { \
+				long ii; \
+				bitmask[((start) >> 3)] |= bitmask_start_values[((start) & 7)]; \
+				for (ii = (((start) >> 3) + 1); ii < ((((end) - 1)) >> 3); ii++) bitmask[ii] = 0xff; \
+				bitmask[(((end) - 1) >> 3)] |= bitmask_end_values[((end) & 7)]; \
+			} }
+
+#define RSMBLY_BITMASK_IS_COMPLETE(bitmask, msg_len, is_complete) { \
+			long ii; \
+			OPENSSL_assert((msg_len) > 0); \
+			is_complete = 1; \
+			if (bitmask[(((msg_len) - 1) >> 3)] != bitmask_end_values[((msg_len) & 7)]) is_complete = 0; \
+			if (is_complete) for (ii = (((msg_len) - 1) >> 3) - 1; ii >= 0 ; ii--) \
+				if (bitmask[ii] != 0xff) { is_complete = 0; break; } }
+
+#if 0
+#define RSMBLY_BITMASK_PRINT(bitmask, msg_len) { \
+			long ii; \
+			printf("bitmask: "); for (ii = 0; ii < (msg_len); ii++) \
+			printf("%d ", (bitmask[ii >> 3] & (1 << (ii & 7))) >> (ii & 7)); \
+			printf("\n"); }
+#endif
+
+static unsigned char bitmask_start_values[] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80};
+static unsigned char bitmask_end_values[]   = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f};
+
+/* XDTLS:  figure out the right values */
+static unsigned int g_probable_mtu[] = {1500 - 28, 512 - 28, 256 - 28};
+
+static unsigned int dtls1_min_mtu(void);
+static unsigned int dtls1_guess_mtu(unsigned int curr_mtu);
+static void dtls1_fix_message_header(SSL *s, unsigned long frag_off, 
+	unsigned long frag_len);
+static unsigned char *dtls1_write_message_header(SSL *s,
+	unsigned char *p);
+static void dtls1_set_message_header_int(SSL *s, unsigned char mt,
+	unsigned long len, unsigned short seq_num, unsigned long frag_off, 
+	unsigned long frag_len);
+static long dtls1_get_message_fragment(SSL *s, int st1, int stn, 
+	long max, int *ok);
+
+static hm_fragment *
+dtls1_hm_fragment_new(unsigned long frag_len, int reassembly)
+	{
+	hm_fragment *frag = NULL;
+	unsigned char *buf = NULL;
+	unsigned char *bitmask = NULL;
+
+	frag = (hm_fragment *)OPENSSL_malloc(sizeof(hm_fragment));
+	if ( frag == NULL)
+		return NULL;
+
+	if (frag_len)
+		{
+		buf = (unsigned char *)OPENSSL_malloc(frag_len);
+		if ( buf == NULL)
+			{
+			OPENSSL_free(frag);
+			return NULL;
+			}
+		}
+
+	/* zero length fragment gets zero frag->fragment */
+	frag->fragment = buf;
+
+	/* Initialize reassembly bitmask if necessary */
+	if (reassembly)
+		{
+		bitmask = (unsigned char *)OPENSSL_malloc(RSMBLY_BITMASK_SIZE(frag_len));
+		if (bitmask == NULL)
+			{
+			if (buf != NULL) OPENSSL_free(buf);
+			OPENSSL_free(frag);
+			return NULL;
+			}
+		memset(bitmask, 0, RSMBLY_BITMASK_SIZE(frag_len));
+		}
+
+	frag->reassembly = bitmask;
+
+	return frag;
+	}
+
+static void
+dtls1_hm_fragment_free(hm_fragment *frag)
+	{
+	if (frag->fragment) OPENSSL_free(frag->fragment);
+	if (frag->reassembly) OPENSSL_free(frag->reassembly);
+	OPENSSL_free(frag);
+	}
+
+/* send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC) */
+int dtls1_do_write(SSL *s, int type)
+	{
+	int ret;
+	int curr_mtu;
+	unsigned int len, frag_off, mac_size, blocksize;
+
+	/* AHA!  Figure out the MTU, and stick to the right size */
+	if ( ! (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU))
+		{
+		s->d1->mtu = 
+			BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
+
+		/* I've seen the kernel return bogus numbers when it doesn't know
+		 * (initial write), so just make sure we have a reasonable number */
+		if ( s->d1->mtu < dtls1_min_mtu())
+			{
+			s->d1->mtu = 0;
+			s->d1->mtu = dtls1_guess_mtu(s->d1->mtu);
+			BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SET_MTU, 
+				s->d1->mtu, NULL);
+			}
+		}
+#if 0 
+	mtu = s->d1->mtu;
+
+	fprintf(stderr, "using MTU = %d\n", mtu);
+
+	mtu -= (DTLS1_HM_HEADER_LENGTH + DTLS1_RT_HEADER_LENGTH);
+
+	curr_mtu = mtu - BIO_wpending(SSL_get_wbio(s));
+
+	if ( curr_mtu > 0)
+		mtu = curr_mtu;
+	else if ( ( ret = BIO_flush(SSL_get_wbio(s))) <= 0)
+		return ret;
+
+	if ( BIO_wpending(SSL_get_wbio(s)) + s->init_num >= mtu)
+		{
+		ret = BIO_flush(SSL_get_wbio(s));
+		if ( ret <= 0)
+			return ret;
+		mtu = s->d1->mtu - (DTLS1_HM_HEADER_LENGTH + DTLS1_RT_HEADER_LENGTH);
+		}
+
+	OPENSSL_assert(mtu > 0);  /* should have something reasonable now */
+
+#endif
+
+	if ( s->init_off == 0  && type == SSL3_RT_HANDSHAKE)
+		OPENSSL_assert(s->init_num == 
+			(int)s->d1->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH);
+
+	if (s->write_hash)
+		mac_size = EVP_MD_CTX_size(s->write_hash);
+	else
+		mac_size = 0;
+
+	if (s->enc_write_ctx && 
+		(EVP_CIPHER_mode( s->enc_write_ctx->cipher) & EVP_CIPH_CBC_MODE))
+		blocksize = 2 * EVP_CIPHER_block_size(s->enc_write_ctx->cipher);
+	else
+		blocksize = 0;
+
+	frag_off = 0;
+	while( s->init_num)
+		{
+		curr_mtu = s->d1->mtu - BIO_wpending(SSL_get_wbio(s)) - 
+			DTLS1_RT_HEADER_LENGTH - mac_size - blocksize;
+
+		if ( curr_mtu <= DTLS1_HM_HEADER_LENGTH)
+			{
+			/* grr.. we could get an error if MTU picked was wrong */
+			ret = BIO_flush(SSL_get_wbio(s));
+			if ( ret <= 0)
+				return ret;
+			curr_mtu = s->d1->mtu - DTLS1_RT_HEADER_LENGTH -
+				mac_size - blocksize;
+			}
+
+		if ( s->init_num > curr_mtu)
+			len = curr_mtu;
+		else
+			len = s->init_num;
+
+
+		/* XDTLS: this function is too long.  split out the CCS part */
+		if ( type == SSL3_RT_HANDSHAKE)
+			{
+			if ( s->init_off != 0)
+				{
+				OPENSSL_assert(s->init_off > DTLS1_HM_HEADER_LENGTH);
+				s->init_off -= DTLS1_HM_HEADER_LENGTH;
+				s->init_num += DTLS1_HM_HEADER_LENGTH;
+
+				/* write atleast DTLS1_HM_HEADER_LENGTH bytes */
+				if ( len <= DTLS1_HM_HEADER_LENGTH)  
+					len += DTLS1_HM_HEADER_LENGTH;
+				}
+
+			dtls1_fix_message_header(s, frag_off, 
+				len - DTLS1_HM_HEADER_LENGTH);
+
+			dtls1_write_message_header(s, (unsigned char *)&s->init_buf->data[s->init_off]);
+
+			OPENSSL_assert(len >= DTLS1_HM_HEADER_LENGTH);
+			}
+
+		ret=dtls1_write_bytes(s,type,&s->init_buf->data[s->init_off],
+			len);
+		if (ret < 0)
+			{
+			/* might need to update MTU here, but we don't know
+			 * which previous packet caused the failure -- so can't
+			 * really retransmit anything.  continue as if everything
+			 * is fine and wait for an alert to handle the
+			 * retransmit 
+			 */
+			if ( BIO_ctrl(SSL_get_wbio(s),
+				BIO_CTRL_DGRAM_MTU_EXCEEDED, 0, NULL) > 0 )
+				s->d1->mtu = BIO_ctrl(SSL_get_wbio(s),
+					BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
+			else
+				return(-1);
+			}
+		else
+			{
+
+			/* bad if this assert fails, only part of the handshake
+			 * message got sent.  but why would this happen? */
+			OPENSSL_assert(len == (unsigned int)ret);
+
+			if (type == SSL3_RT_HANDSHAKE && ! s->d1->retransmitting)
+				{
+				/* should not be done for 'Hello Request's, but in that case
+				 * we'll ignore the result anyway */
+				unsigned char *p = (unsigned char *)&s->init_buf->data[s->init_off];
+				const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
+				int xlen;
+
+				if (frag_off == 0 && s->version != DTLS1_BAD_VER)
+					{
+					/* reconstruct message header is if it
+					 * is being sent in single fragment */
+					*p++ = msg_hdr->type;
+					l2n3(msg_hdr->msg_len,p);
+					s2n (msg_hdr->seq,p);
+					l2n3(0,p);
+					l2n3(msg_hdr->msg_len,p);
+					p  -= DTLS1_HM_HEADER_LENGTH;
+					xlen = ret;
+					}
+				else
+					{
+					p  += DTLS1_HM_HEADER_LENGTH;
+					xlen = ret - DTLS1_HM_HEADER_LENGTH;
+					}
+
+				ssl3_finish_mac(s, p, xlen);
+				}
+
+			if (ret == s->init_num)
+				{
+				if (s->msg_callback)
+					s->msg_callback(1, s->version, type, s->init_buf->data, 
+						(size_t)(s->init_off + s->init_num), s, 
+						s->msg_callback_arg);
+
+				s->init_off = 0;  /* done writing this message */
+				s->init_num = 0;
+
+				return(1);
+				}
+			s->init_off+=ret;
+			s->init_num-=ret;
+			frag_off += (ret -= DTLS1_HM_HEADER_LENGTH);
+			}
+		}
+	return(0);
+	}
+
+
+/* Obtain handshake message of message type 'mt' (any if mt == -1),
+ * maximum acceptable body length 'max'.
+ * Read an entire handshake message.  Handshake messages arrive in
+ * fragments.
+ */
+long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
+	{
+	int i, al;
+	struct hm_header_st *msg_hdr;
+	unsigned char *p;
+	unsigned long msg_len;
+
+	/* s3->tmp is used to store messages that are unexpected, caused
+	 * by the absence of an optional handshake message */
+	if (s->s3->tmp.reuse_message)
+		{
+		s->s3->tmp.reuse_message=0;
+		if ((mt >= 0) && (s->s3->tmp.message_type != mt))
+			{
+			al=SSL_AD_UNEXPECTED_MESSAGE;
+			SSLerr(SSL_F_DTLS1_GET_MESSAGE,SSL_R_UNEXPECTED_MESSAGE);
+			goto f_err;
+			}
+		*ok=1;
+		s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
+		s->init_num = (int)s->s3->tmp.message_size;
+		return s->init_num;
+		}
+
+	msg_hdr = &s->d1->r_msg_hdr;
+	memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
+
+again:
+	i = dtls1_get_message_fragment(s, st1, stn, max, ok);
+	if ( i == DTLS1_HM_BAD_FRAGMENT ||
+		i == DTLS1_HM_FRAGMENT_RETRY)  /* bad fragment received */
+		goto again;
+	else if ( i <= 0 && !*ok)
+		return i;
+
+	p = (unsigned char *)s->init_buf->data;
+	msg_len = msg_hdr->msg_len;
+
+	/* reconstruct message header */
+	*(p++) = msg_hdr->type;
+	l2n3(msg_len,p);
+	s2n (msg_hdr->seq,p);
+	l2n3(0,p);
+	l2n3(msg_len,p);
+	if (s->version != DTLS1_BAD_VER) {
+		p       -= DTLS1_HM_HEADER_LENGTH;
+		msg_len += DTLS1_HM_HEADER_LENGTH;
+	}
+
+	ssl3_finish_mac(s, p, msg_len);
+	if (s->msg_callback)
+		s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
+			p, msg_len,
+			s, s->msg_callback_arg);
+
+	memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
+
+	s->d1->handshake_read_seq++;
+	/* we just read a handshake message from the other side:
+	 * this means that we don't need to retransmit of the
+	 * buffered messages.  
+	 * XDTLS: may be able clear out this
+	 * buffer a little sooner (i.e if an out-of-order
+	 * handshake message/record is received at the record
+	 * layer.  
+	 * XDTLS: exception is that the server needs to
+	 * know that change cipher spec and finished messages
+	 * have been received by the client before clearing this
+	 * buffer.  this can simply be done by waiting for the
+	 * first data  segment, but is there a better way?  */
+	dtls1_clear_record_buffer(s);
+
+	s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
+	return s->init_num;
+
+f_err:
+	ssl3_send_alert(s,SSL3_AL_FATAL,al);
+	*ok = 0;
+	return -1;
+	}
+
+
+static int dtls1_preprocess_fragment(SSL *s,struct hm_header_st *msg_hdr,int max)
+	{
+	size_t frag_off,frag_len,msg_len;
+
+	msg_len  = msg_hdr->msg_len;
+	frag_off = msg_hdr->frag_off;
+	frag_len = msg_hdr->frag_len;
+
+	/* sanity checking */
+	if ( (frag_off+frag_len) > msg_len)
+		{
+		SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
+		return SSL_AD_ILLEGAL_PARAMETER;
+		}
+
+	if ( (frag_off+frag_len) > (unsigned long)max)
+		{
+		SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
+		return SSL_AD_ILLEGAL_PARAMETER;
+		}
+
+	if ( s->d1->r_msg_hdr.frag_off == 0) /* first fragment */
+		{
+		/* msg_len is limited to 2^24, but is effectively checked
+		 * against max above */
+		if (!BUF_MEM_grow_clean(s->init_buf,msg_len+DTLS1_HM_HEADER_LENGTH))
+			{
+			SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,ERR_R_BUF_LIB);
+			return SSL_AD_INTERNAL_ERROR;
+			}
+
+		s->s3->tmp.message_size  = msg_len;
+		s->d1->r_msg_hdr.msg_len = msg_len;
+		s->s3->tmp.message_type  = msg_hdr->type;
+		s->d1->r_msg_hdr.type    = msg_hdr->type;
+		s->d1->r_msg_hdr.seq     = msg_hdr->seq;
+		}
+	else if (msg_len != s->d1->r_msg_hdr.msg_len)
+		{
+		/* They must be playing with us! BTW, failure to enforce
+		 * upper limit would open possibility for buffer overrun. */
+		SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
+		return SSL_AD_ILLEGAL_PARAMETER;
+		}
+
+	return 0; /* no error */
+	}
+
+
+static int
+dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok)
+	{
+	/* (0) check whether the desired fragment is available
+	 * if so:
+	 * (1) copy over the fragment to s->init_buf->data[]
+	 * (2) update s->init_num
+	 */
+	pitem *item;
+	hm_fragment *frag;
+	int al;
+
+	*ok = 0;
+	item = pqueue_peek(s->d1->buffered_messages);
+	if ( item == NULL)
+		return 0;
+
+	frag = (hm_fragment *)item->data;
+	
+	/* Don't return if reassembly still in progress */
+	if (frag->reassembly != NULL)
+		return 0;
+
+	if ( s->d1->handshake_read_seq == frag->msg_header.seq)
+		{
+		unsigned long frag_len = frag->msg_header.frag_len;
+		pqueue_pop(s->d1->buffered_messages);
+
+		al=dtls1_preprocess_fragment(s,&frag->msg_header,max);
+
+		if (al==0) /* no alert */
+			{
+			unsigned char *p = (unsigned char *)s->init_buf->data+DTLS1_HM_HEADER_LENGTH;
+			memcpy(&p[frag->msg_header.frag_off],
+				frag->fragment,frag->msg_header.frag_len);
+			}
+
+		dtls1_hm_fragment_free(frag);
+		pitem_free(item);
+
+		if (al==0)
+			{
+			*ok = 1;
+			return frag_len;
+			}
+
+		ssl3_send_alert(s,SSL3_AL_FATAL,al);
+		s->init_num = 0;
+		*ok = 0;
+		return -1;
+		}
+	else
+		return 0;
+	}
+
+
+static int
+dtls1_reassemble_fragment(SSL *s, struct hm_header_st* msg_hdr, int *ok)
+	{
+	hm_fragment *frag = NULL;
+	pitem *item = NULL;
+	int i = -1, is_complete;
+	unsigned char seq64be[8];
+	unsigned long frag_len = msg_hdr->frag_len, max_len;
+
+	if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len)
+		goto err;
+
+	/* Determine maximum allowed message size. Depends on (user set)
+	 * maximum certificate length, but 16k is minimum.
+	 */
+	if (DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH < s->max_cert_list)
+		max_len = s->max_cert_list;
+	else
+		max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
+
+	if ((msg_hdr->frag_off+frag_len) > max_len)
+		goto err;
+
+	/* Try to find item in queue */
+	memset(seq64be,0,sizeof(seq64be));
+	seq64be[6] = (unsigned char) (msg_hdr->seq>>8);
+	seq64be[7] = (unsigned char) msg_hdr->seq;
+	item = pqueue_find(s->d1->buffered_messages, seq64be);
+
+	if (item == NULL)
+		{
+		frag = dtls1_hm_fragment_new(msg_hdr->msg_len, 1);
+		if ( frag == NULL)
+			goto err;
+		memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
+		frag->msg_header.frag_len = frag->msg_header.msg_len;
+		frag->msg_header.frag_off = 0;
+		}
+	else
+		frag = (hm_fragment*) item->data;
+
+	/* If message is already reassembled, this must be a
+	 * retransmit and can be dropped.
+	 */
+	if (frag->reassembly == NULL)
+		{
+		unsigned char devnull [256];
+
+		while (frag_len)
+			{
+			i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
+				devnull,
+				frag_len>sizeof(devnull)?sizeof(devnull):frag_len,0);
+			if (i<=0) goto err;
+			frag_len -= i;
+			}
+		return DTLS1_HM_FRAGMENT_RETRY;
+		}
+
+	/* read the body of the fragment (header has already been read */
+	i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
+		frag->fragment + msg_hdr->frag_off,frag_len,0);
+	if (i<=0 || (unsigned long)i!=frag_len)
+		goto err;
+
+	RSMBLY_BITMASK_MARK(frag->reassembly, (long)msg_hdr->frag_off,
+	                    (long)(msg_hdr->frag_off + frag_len));
+
+	RSMBLY_BITMASK_IS_COMPLETE(frag->reassembly, (long)msg_hdr->msg_len,
+	                           is_complete);
+
+	if (is_complete)
+		{
+		OPENSSL_free(frag->reassembly);
+		frag->reassembly = NULL;
+		}
+
+	if (item == NULL)
+		{
+		memset(seq64be,0,sizeof(seq64be));
+		seq64be[6] = (unsigned char)(msg_hdr->seq>>8);
+		seq64be[7] = (unsigned char)(msg_hdr->seq);
+
+		item = pitem_new(seq64be, frag);
+		if (item == NULL)
+			{
+			goto err;
+			i = -1;
+			}
+
+		pqueue_insert(s->d1->buffered_messages, item);
+		}
+
+	return DTLS1_HM_FRAGMENT_RETRY;
+
+err:
+	if (frag != NULL) dtls1_hm_fragment_free(frag);
+	if (item != NULL) OPENSSL_free(item);
+	*ok = 0;
+	return i;
+	}
+
+
+static int
+dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok)
+{
+	int i=-1;
+	hm_fragment *frag = NULL;
+	pitem *item = NULL;
+	unsigned char seq64be[8];
+	unsigned long frag_len = msg_hdr->frag_len;
+
+	if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len)
+		goto err;
+
+	/* Try to find item in queue, to prevent duplicate entries */
+	memset(seq64be,0,sizeof(seq64be));
+	seq64be[6] = (unsigned char) (msg_hdr->seq>>8);
+	seq64be[7] = (unsigned char) msg_hdr->seq;
+	item = pqueue_find(s->d1->buffered_messages, seq64be);
+
+	/* If we already have an entry and this one is a fragment,
+	 * don't discard it and rather try to reassemble it.
+	 */
+	if (item != NULL && frag_len < msg_hdr->msg_len)
+		item = NULL;
+
+	/* Discard the message if sequence number was already there, is
+	 * too far in the future, already in the queue or if we received
+	 * a FINISHED before the SERVER_HELLO, which then must be a stale
+	 * retransmit.
+	 */
+	if (msg_hdr->seq <= s->d1->handshake_read_seq ||
+		msg_hdr->seq > s->d1->handshake_read_seq + 10 || item != NULL ||
+		(s->d1->handshake_read_seq == 0 && msg_hdr->type == SSL3_MT_FINISHED))
+		{
+		unsigned char devnull [256];
+
+		while (frag_len)
+			{
+			i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
+				devnull,
+				frag_len>sizeof(devnull)?sizeof(devnull):frag_len,0);
+			if (i<=0) goto err;
+			frag_len -= i;
+			}
+		}
+	else
+		{
+		if (frag_len && frag_len < msg_hdr->msg_len)
+			return dtls1_reassemble_fragment(s, msg_hdr, ok);
+
+		frag = dtls1_hm_fragment_new(frag_len, 0);
+		if ( frag == NULL)
+			goto err;
+
+		memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
+
+		if (frag_len)
+			{
+			/* read the body of the fragment (header has already been read */
+			i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
+				frag->fragment,frag_len,0);
+			if (i<=0 || (unsigned long)i!=frag_len)
+				goto err;
+			}
+
+		memset(seq64be,0,sizeof(seq64be));
+		seq64be[6] = (unsigned char)(msg_hdr->seq>>8);
+		seq64be[7] = (unsigned char)(msg_hdr->seq);
+
+		item = pitem_new(seq64be, frag);
+		if ( item == NULL)
+			goto err;
+
+		pqueue_insert(s->d1->buffered_messages, item);
+		}
+
+	return DTLS1_HM_FRAGMENT_RETRY;
+
+err:
+	if ( frag != NULL) dtls1_hm_fragment_free(frag);
+	if ( item != NULL) OPENSSL_free(item);
+	*ok = 0;
+	return i;
+	}
+
+
+static long
+dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok)
+	{
+	unsigned char wire[DTLS1_HM_HEADER_LENGTH];
+	unsigned long len, frag_off, frag_len;
+	int i,al;
+	struct hm_header_st msg_hdr;
+
+	/* see if we have the required fragment already */
+	if ((frag_len = dtls1_retrieve_buffered_fragment(s,max,ok)) || *ok)
+		{
+		if (*ok)	s->init_num = frag_len;
+		return frag_len;
+		}
+
+	/* read handshake message header */
+	i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,wire,
+		DTLS1_HM_HEADER_LENGTH, 0);
+	if (i <= 0) 	/* nbio, or an error */
+		{
+		s->rwstate=SSL_READING;
+		*ok = 0;
+		return i;
+		}
+	OPENSSL_assert(i == DTLS1_HM_HEADER_LENGTH);
+
+	/* parse the message fragment header */
+	dtls1_get_message_header(wire, &msg_hdr);
+
+	/* 
+	 * if this is a future (or stale) message it gets buffered
+	 * (or dropped)--no further processing at this time 
+	 */
+	if ( msg_hdr.seq != s->d1->handshake_read_seq)
+		return dtls1_process_out_of_seq_message(s, &msg_hdr, ok);
+
+	len = msg_hdr.msg_len;
+	frag_off = msg_hdr.frag_off;
+	frag_len = msg_hdr.frag_len;
+
+	if (frag_len && frag_len < len)
+		return dtls1_reassemble_fragment(s, &msg_hdr, ok);
+
+	if (!s->server && s->d1->r_msg_hdr.frag_off == 0 &&
+		wire[0] == SSL3_MT_HELLO_REQUEST)
+		{
+		/* The server may always send 'Hello Request' messages --
+		 * we are doing a handshake anyway now, so ignore them
+		 * if their format is correct. Does not count for
+		 * 'Finished' MAC. */
+		if (wire[1] == 0 && wire[2] == 0 && wire[3] == 0)
+			{
+			if (s->msg_callback)
+				s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, 
+					wire, DTLS1_HM_HEADER_LENGTH, s, 
+					s->msg_callback_arg);
+			
+			s->init_num = 0;
+			return dtls1_get_message_fragment(s, st1, stn,
+				max, ok);
+			}
+		else /* Incorrectly formated Hello request */
+			{
+			al=SSL_AD_UNEXPECTED_MESSAGE;
+			SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_UNEXPECTED_MESSAGE);
+			goto f_err;
+			}
+		}
+
+	if ((al=dtls1_preprocess_fragment(s,&msg_hdr,max)))
+		goto f_err;
+
+	/* XDTLS:  ressurect this when restart is in place */
+	s->state=stn;
+
+	if ( frag_len > 0)
+		{
+		unsigned char *p=(unsigned char *)s->init_buf->data+DTLS1_HM_HEADER_LENGTH;
+
+		i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
+			&p[frag_off],frag_len,0);
+		/* XDTLS:  fix this--message fragments cannot span multiple packets */
+		if (i <= 0)
+			{
+			s->rwstate=SSL_READING;
+			*ok = 0;
+			return i;
+			}
+		}
+	else
+		i = 0;
+
+	/* XDTLS:  an incorrectly formatted fragment should cause the 
+	 * handshake to fail */
+	OPENSSL_assert(i == (int)frag_len);
+
+	*ok = 1;
+
+	/* Note that s->init_num is *not* used as current offset in
+	 * s->init_buf->data, but as a counter summing up fragments'
+	 * lengths: as soon as they sum up to handshake packet
+	 * length, we assume we have got all the fragments. */
+	s->init_num = frag_len;
+	return frag_len;
+
+f_err:
+	ssl3_send_alert(s,SSL3_AL_FATAL,al);
+	s->init_num = 0;
+
+	*ok=0;
+	return(-1);
+	}
+
+int dtls1_send_finished(SSL *s, int a, int b, const char *sender, int slen)
+	{
+	unsigned char *p,*d;
+	int i;
+	unsigned long l;
+
+	if (s->state == a)
+		{
+		d=(unsigned char *)s->init_buf->data;
+		p= &(d[DTLS1_HM_HEADER_LENGTH]);
+
+		i=s->method->ssl3_enc->final_finish_mac(s,
+			sender,slen,s->s3->tmp.finish_md);
+		s->s3->tmp.finish_md_len = i;
+		memcpy(p, s->s3->tmp.finish_md, i);
+		p+=i;
+		l=i;
+
+	/* Copy the finished so we can use it for
+	 * renegotiation checks
+	 */
+	if(s->type == SSL_ST_CONNECT)
+		{
+		OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
+		memcpy(s->s3->previous_client_finished, 
+		       s->s3->tmp.finish_md, i);
+		s->s3->previous_client_finished_len=i;
+		}
+	else
+		{
+		OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
+		memcpy(s->s3->previous_server_finished, 
+		       s->s3->tmp.finish_md, i);
+		s->s3->previous_server_finished_len=i;
+		}
+
+#ifdef OPENSSL_SYS_WIN16
+		/* MSVC 1.5 does not clear the top bytes of the word unless
+		 * I do this.
+		 */
+		l&=0xffff;
+#endif
+
+		d = dtls1_set_message_header(s, d, SSL3_MT_FINISHED, l, 0, l);
+		s->init_num=(int)l+DTLS1_HM_HEADER_LENGTH;
+		s->init_off=0;
+
+		/* buffer the message to handle re-xmits */
+		dtls1_buffer_message(s, 0);
+
+		s->state=b;
+		}
+
+	/* SSL3_ST_SEND_xxxxxx_HELLO_B */
+	return(dtls1_do_write(s,SSL3_RT_HANDSHAKE));
+	}
+
+/* for these 2 messages, we need to
+ * ssl->enc_read_ctx			re-init
+ * ssl->s3->read_sequence		zero
+ * ssl->s3->read_mac_secret		re-init
+ * ssl->session->read_sym_enc		assign
+ * ssl->session->read_compression	assign
+ * ssl->session->read_hash		assign
+ */
+int dtls1_send_change_cipher_spec(SSL *s, int a, int b)
+	{ 
+	unsigned char *p;
+
+	if (s->state == a)
+		{
+		p=(unsigned char *)s->init_buf->data;
+		*p++=SSL3_MT_CCS;
+		s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
+		s->init_num=DTLS1_CCS_HEADER_LENGTH;
+
+		if (s->version == DTLS1_BAD_VER) {
+			s->d1->next_handshake_write_seq++;
+			s2n(s->d1->handshake_write_seq,p);
+			s->init_num+=2;
+		}
+
+		s->init_off=0;
+
+		dtls1_set_message_header_int(s, SSL3_MT_CCS, 0, 
+			s->d1->handshake_write_seq, 0, 0);
+
+		/* buffer the message to handle re-xmits */
+		dtls1_buffer_message(s, 1);
+
+		s->state=b;
+		}
+
+	/* SSL3_ST_CW_CHANGE_B */
+	return(dtls1_do_write(s,SSL3_RT_CHANGE_CIPHER_SPEC));
+	}
+
+static int dtls1_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x)
+	{
+	int n;
+	unsigned char *p;
+
+	n=i2d_X509(x,NULL);
+	if (!BUF_MEM_grow_clean(buf,(int)(n+(*l)+3)))
+		{
+		SSLerr(SSL_F_DTLS1_ADD_CERT_TO_BUF,ERR_R_BUF_LIB);
+		return 0;
+		}
+	p=(unsigned char *)&(buf->data[*l]);
+	l2n3(n,p);
+	i2d_X509(x,&p);
+	*l+=n+3;
+
+	return 1;
+	}
+unsigned long dtls1_output_cert_chain(SSL *s, X509 *x)
+	{
+	unsigned char *p;
+	int i;
+	unsigned long l= 3 + DTLS1_HM_HEADER_LENGTH;
+	BUF_MEM *buf;
+
+	/* TLSv1 sends a chain with nothing in it, instead of an alert */
+	buf=s->init_buf;
+	if (!BUF_MEM_grow_clean(buf,10))
+		{
+		SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB);
+		return(0);
+		}
+	if (x != NULL)
+		{
+		X509_STORE_CTX xs_ctx;
+
+		if (!X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,x,NULL))
+  			{
+  			SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_X509_LIB);
+  			return(0);
+  			}
+  
+		X509_verify_cert(&xs_ctx);
+		/* Don't leave errors in the queue */
+		ERR_clear_error();
+		for (i=0; i < sk_X509_num(xs_ctx.chain); i++)
+  			{
+			x = sk_X509_value(xs_ctx.chain, i);
+
+			if (!dtls1_add_cert_to_buf(buf, &l, x))
+  				{
+				X509_STORE_CTX_cleanup(&xs_ctx);
+				return 0;
+  				}
+  			}
+  		X509_STORE_CTX_cleanup(&xs_ctx);
+  		}
+  	/* Thawte special :-) */
+	for (i=0; i<sk_X509_num(s->ctx->extra_certs); i++)
+		{
+		x=sk_X509_value(s->ctx->extra_certs,i);
+		if (!dtls1_add_cert_to_buf(buf, &l, x))
+			return 0;
+		}
+
+	l-= (3 + DTLS1_HM_HEADER_LENGTH);
+
+	p=(unsigned char *)&(buf->data[DTLS1_HM_HEADER_LENGTH]);
+	l2n3(l,p);
+	l+=3;
+	p=(unsigned char *)&(buf->data[0]);
+	p = dtls1_set_message_header(s, p, SSL3_MT_CERTIFICATE, l, 0, l);
+
+	l+=DTLS1_HM_HEADER_LENGTH;
+	return(l);
+	}
+
+int dtls1_read_failed(SSL *s, int code)
+	{
+	if ( code > 0)
+		{
+		fprintf( stderr, "invalid state reached %s:%d", __FILE__, __LINE__);
+		return 1;
+		}
+
+	if (!dtls1_is_timer_expired(s))
+		{
+		/* not a timeout, none of our business, 
+		   let higher layers handle this.  in fact it's probably an error */
+		return code;
+		}
+
+	if ( ! SSL_in_init(s))  /* done, no need to send a retransmit */
+		{
+		BIO_set_flags(SSL_get_rbio(s), BIO_FLAGS_READ);
+		return code;
+		}
+
+#if 0 /* for now, each alert contains only one record number */
+	item = pqueue_peek(state->rcvd_records);
+	if ( item )
+		{
+		/* send an alert immediately for all the missing records */
+		}
+	else
+#endif
+
+#if 0  /* no more alert sending, just retransmit the last set of messages */
+	if ( state->timeout.read_timeouts >= DTLS1_TMO_READ_COUNT)
+		ssl3_send_alert(s,SSL3_AL_WARNING,
+			DTLS1_AD_MISSING_HANDSHAKE_MESSAGE);
+#endif
+
+	return dtls1_handle_timeout(s);
+	}
+
+int
+dtls1_get_queue_priority(unsigned short seq, int is_ccs)
+	{
+	/* The index of the retransmission queue actually is the message sequence number,
+	 * since the queue only contains messages of a single handshake. However, the
+	 * ChangeCipherSpec has no message sequence number and so using only the sequence
+	 * will result in the CCS and Finished having the same index. To prevent this,
+	 * the sequence number is multiplied by 2. In case of a CCS 1 is subtracted.
+	 * This does not only differ CSS and Finished, it also maintains the order of the
+	 * index (important for priority queues) and fits in the unsigned short variable.
+	 */	
+	return seq * 2 - is_ccs;
+	}
+
+int
+dtls1_retransmit_buffered_messages(SSL *s)
+	{
+	pqueue sent = s->d1->sent_messages;
+	piterator iter;
+	pitem *item;
+	hm_fragment *frag;
+	int found = 0;
+
+	iter = pqueue_iterator(sent);
+
+	for ( item = pqueue_next(&iter); item != NULL; item = pqueue_next(&iter))
+		{
+		frag = (hm_fragment *)item->data;
+			if ( dtls1_retransmit_message(s,
+				(unsigned short)dtls1_get_queue_priority(frag->msg_header.seq, frag->msg_header.is_ccs),
+				0, &found) <= 0 && found)
+			{
+			fprintf(stderr, "dtls1_retransmit_message() failed\n");
+			return -1;
+			}
+		}
+
+	return 1;
+	}
+
+int
+dtls1_buffer_message(SSL *s, int is_ccs)
+	{
+	pitem *item;
+	hm_fragment *frag;
+	unsigned char seq64be[8];
+
+	/* this function is called immediately after a message has 
+	 * been serialized */
+	OPENSSL_assert(s->init_off == 0);
+
+	frag = dtls1_hm_fragment_new(s->init_num, 0);
+
+	memcpy(frag->fragment, s->init_buf->data, s->init_num);
+
+	if ( is_ccs)
+		{
+		OPENSSL_assert(s->d1->w_msg_hdr.msg_len + 
+			       ((s->version==DTLS1_VERSION)?DTLS1_CCS_HEADER_LENGTH:3) == (unsigned int)s->init_num);
+		}
+	else
+		{
+		OPENSSL_assert(s->d1->w_msg_hdr.msg_len + 
+			DTLS1_HM_HEADER_LENGTH == (unsigned int)s->init_num);
+		}
+
+	frag->msg_header.msg_len = s->d1->w_msg_hdr.msg_len;
+	frag->msg_header.seq = s->d1->w_msg_hdr.seq;
+	frag->msg_header.type = s->d1->w_msg_hdr.type;
+	frag->msg_header.frag_off = 0;
+	frag->msg_header.frag_len = s->d1->w_msg_hdr.msg_len;
+	frag->msg_header.is_ccs = is_ccs;
+
+	/* save current state*/
+	frag->msg_header.saved_retransmit_state.enc_write_ctx = s->enc_write_ctx;
+	frag->msg_header.saved_retransmit_state.write_hash = s->write_hash;
+	frag->msg_header.saved_retransmit_state.compress = s->compress;
+	frag->msg_header.saved_retransmit_state.session = s->session;
+	frag->msg_header.saved_retransmit_state.epoch = s->d1->w_epoch;
+	
+	memset(seq64be,0,sizeof(seq64be));
+	seq64be[6] = (unsigned char)(dtls1_get_queue_priority(frag->msg_header.seq,
+														  frag->msg_header.is_ccs)>>8);
+	seq64be[7] = (unsigned char)(dtls1_get_queue_priority(frag->msg_header.seq,
+														  frag->msg_header.is_ccs));
+
+	item = pitem_new(seq64be, frag);
+	if ( item == NULL)
+		{
+		dtls1_hm_fragment_free(frag);
+		return 0;
+		}
+
+#if 0
+	fprintf( stderr, "buffered messge: \ttype = %xx\n", msg_buf->type);
+	fprintf( stderr, "\t\t\t\t\tlen = %d\n", msg_buf->len);
+	fprintf( stderr, "\t\t\t\t\tseq_num = %d\n", msg_buf->seq_num);
+#endif
+
+	pqueue_insert(s->d1->sent_messages, item);
+	return 1;
+	}
+
+int
+dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off,
+	int *found)
+	{
+	int ret;
+	/* XDTLS: for now assuming that read/writes are blocking */
+	pitem *item;
+	hm_fragment *frag ;
+	unsigned long header_length;
+	unsigned char seq64be[8];
+	struct dtls1_retransmit_state saved_state;
+	unsigned char save_write_sequence[8];
+
+	/*
+	  OPENSSL_assert(s->init_num == 0);
+	  OPENSSL_assert(s->init_off == 0);
+	 */
+
+	/* XDTLS:  the requested message ought to be found, otherwise error */
+	memset(seq64be,0,sizeof(seq64be));
+	seq64be[6] = (unsigned char)(seq>>8);
+	seq64be[7] = (unsigned char)seq;
+
+	item = pqueue_find(s->d1->sent_messages, seq64be);
+	if ( item == NULL)
+		{
+		fprintf(stderr, "retransmit:  message %d non-existant\n", seq);
+		*found = 0;
+		return 0;
+		}
+
+	*found = 1;
+	frag = (hm_fragment *)item->data;
+
+	if ( frag->msg_header.is_ccs)
+		header_length = DTLS1_CCS_HEADER_LENGTH;
+	else
+		header_length = DTLS1_HM_HEADER_LENGTH;
+
+	memcpy(s->init_buf->data, frag->fragment, 
+		frag->msg_header.msg_len + header_length);
+		s->init_num = frag->msg_header.msg_len + header_length;
+
+	dtls1_set_message_header_int(s, frag->msg_header.type, 
+		frag->msg_header.msg_len, frag->msg_header.seq, 0, 
+		frag->msg_header.frag_len);
+
+	/* save current state */
+	saved_state.enc_write_ctx = s->enc_write_ctx;
+	saved_state.write_hash = s->write_hash;
+	saved_state.compress = s->compress;
+	saved_state.session = s->session;
+	saved_state.epoch = s->d1->w_epoch;
+	saved_state.epoch = s->d1->w_epoch;
+	
+	s->d1->retransmitting = 1;
+	
+	/* restore state in which the message was originally sent */
+	s->enc_write_ctx = frag->msg_header.saved_retransmit_state.enc_write_ctx;
+	s->write_hash = frag->msg_header.saved_retransmit_state.write_hash;
+	s->compress = frag->msg_header.saved_retransmit_state.compress;
+	s->session = frag->msg_header.saved_retransmit_state.session;
+	s->d1->w_epoch = frag->msg_header.saved_retransmit_state.epoch;
+	
+	if (frag->msg_header.saved_retransmit_state.epoch == saved_state.epoch - 1)
+	{
+		memcpy(save_write_sequence, s->s3->write_sequence, sizeof(s->s3->write_sequence));
+		memcpy(s->s3->write_sequence, s->d1->last_write_sequence, sizeof(s->s3->write_sequence));
+	}
+	
+	ret = dtls1_do_write(s, frag->msg_header.is_ccs ? 
+						 SSL3_RT_CHANGE_CIPHER_SPEC : SSL3_RT_HANDSHAKE);
+	
+	/* restore current state */
+	s->enc_write_ctx = saved_state.enc_write_ctx;
+	s->write_hash = saved_state.write_hash;
+	s->compress = saved_state.compress;
+	s->session = saved_state.session;
+	s->d1->w_epoch = saved_state.epoch;
+	
+	if (frag->msg_header.saved_retransmit_state.epoch == saved_state.epoch - 1)
+	{
+		memcpy(s->d1->last_write_sequence, s->s3->write_sequence, sizeof(s->s3->write_sequence));
+		memcpy(s->s3->write_sequence, save_write_sequence, sizeof(s->s3->write_sequence));
+	}
+
+	s->d1->retransmitting = 0;
+
+	(void)BIO_flush(SSL_get_wbio(s));
+	return ret;
+	}
+
+/* call this function when the buffered messages are no longer needed */
+void
+dtls1_clear_record_buffer(SSL *s)
+	{
+	pitem *item;
+
+	for(item = pqueue_pop(s->d1->sent_messages);
+		item != NULL; item = pqueue_pop(s->d1->sent_messages))
+		{
+		dtls1_hm_fragment_free((hm_fragment *)item->data);
+		pitem_free(item);
+		}
+	}
+
+
+unsigned char *
+dtls1_set_message_header(SSL *s, unsigned char *p, unsigned char mt,
+			unsigned long len, unsigned long frag_off, unsigned long frag_len)
+	{
+	if ( frag_off == 0)
+		{
+		s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
+		s->d1->next_handshake_write_seq++;
+		}
+
+	dtls1_set_message_header_int(s, mt, len, s->d1->handshake_write_seq,
+		frag_off, frag_len);
+
+	return p += DTLS1_HM_HEADER_LENGTH;
+	}
+
+
+/* don't actually do the writing, wait till the MTU has been retrieved */
+static void
+dtls1_set_message_header_int(SSL *s, unsigned char mt,
+			    unsigned long len, unsigned short seq_num, unsigned long frag_off,
+			    unsigned long frag_len)
+	{
+	struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
+
+	msg_hdr->type = mt;
+	msg_hdr->msg_len = len;
+	msg_hdr->seq = seq_num;
+	msg_hdr->frag_off = frag_off;
+	msg_hdr->frag_len = frag_len;
+	}
+
+static void
+dtls1_fix_message_header(SSL *s, unsigned long frag_off,
+			unsigned long frag_len)
+	{
+	struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
+
+	msg_hdr->frag_off = frag_off;
+	msg_hdr->frag_len = frag_len;
+	}
+
+static unsigned char *
+dtls1_write_message_header(SSL *s, unsigned char *p)
+	{
+	struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
+
+	*p++ = msg_hdr->type;
+	l2n3(msg_hdr->msg_len, p);
+
+	s2n(msg_hdr->seq, p);
+	l2n3(msg_hdr->frag_off, p);
+	l2n3(msg_hdr->frag_len, p);
+
+	return p;
+	}
+
+static unsigned int 
+dtls1_min_mtu(void)
+	{
+	return (g_probable_mtu[(sizeof(g_probable_mtu) / 
+		sizeof(g_probable_mtu[0])) - 1]);
+	}
+
+static unsigned int 
+dtls1_guess_mtu(unsigned int curr_mtu)
+	{
+	unsigned int i;
+
+	if ( curr_mtu == 0 )
+		return g_probable_mtu[0] ;
+
+	for ( i = 0; i < sizeof(g_probable_mtu)/sizeof(g_probable_mtu[0]); i++)
+		if ( curr_mtu > g_probable_mtu[i])
+			return g_probable_mtu[i];
+
+	return curr_mtu;
+	}
+
+void
+dtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr)
+	{
+	memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
+	msg_hdr->type = *(data++);
+	n2l3(data, msg_hdr->msg_len);
+
+	n2s(data, msg_hdr->seq);
+	n2l3(data, msg_hdr->frag_off);
+	n2l3(data, msg_hdr->frag_len);
+	}
+
+void
+dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr)
+	{
+	memset(ccs_hdr, 0x00, sizeof(struct ccs_header_st));
+
+	ccs_hdr->type = *(data++);
+	}
diff --git a/lib/openssl/ssl/d1_clnt.c b/lib/openssl/ssl/d1_clnt.c
new file mode 100644
index 0000000..aabbef8
--- /dev/null
+++ b/lib/openssl/ssl/d1_clnt.c
@@ -0,0 +1,1540 @@
+/* ssl/d1_clnt.c */
+/* 
+ * DTLS implementation written by Nagendra Modadugu
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.  
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include "ssl_locl.h"
+#ifndef OPENSSL_NO_KRB5
+#include "kssl_lcl.h"
+#endif
+#include <openssl/buffer.h>
+#include <openssl/rand.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include <openssl/md5.h>
+#include <openssl/bn.h>
+#ifndef OPENSSL_NO_DH
+#include <openssl/dh.h>
+#endif
+
+static const SSL_METHOD *dtls1_get_client_method(int ver);
+static int dtls1_get_hello_verify(SSL *s);
+
+static const SSL_METHOD *dtls1_get_client_method(int ver)
+	{
+	if (ver == DTLS1_VERSION || ver == DTLS1_BAD_VER)
+		return(DTLSv1_client_method());
+	else
+		return(NULL);
+	}
+
+IMPLEMENT_dtls1_meth_func(DTLSv1_client_method,
+			ssl_undefined_function,
+			dtls1_connect,
+			dtls1_get_client_method)
+
+int dtls1_connect(SSL *s)
+	{
+	BUF_MEM *buf=NULL;
+	unsigned long Time=(unsigned long)time(NULL);
+	void (*cb)(const SSL *ssl,int type,int val)=NULL;
+	int ret= -1;
+	int new_state,state,skip=0;;
+
+	RAND_add(&Time,sizeof(Time),0);
+	ERR_clear_error();
+	clear_sys_error();
+
+	if (s->info_callback != NULL)
+		cb=s->info_callback;
+	else if (s->ctx->info_callback != NULL)
+		cb=s->ctx->info_callback;
+	
+	s->in_handshake++;
+	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); 
+
+	for (;;)
+		{
+		state=s->state;
+
+		switch(s->state)
+			{
+		case SSL_ST_RENEGOTIATE:
+			s->new_session=1;
+			s->state=SSL_ST_CONNECT;
+			s->ctx->stats.sess_connect_renegotiate++;
+			/* break */
+		case SSL_ST_BEFORE:
+		case SSL_ST_CONNECT:
+		case SSL_ST_BEFORE|SSL_ST_CONNECT:
+		case SSL_ST_OK|SSL_ST_CONNECT:
+
+			s->server=0;
+			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
+
+			if ((s->version & 0xff00 ) != (DTLS1_VERSION & 0xff00) &&
+			    (s->version & 0xff00 ) != (DTLS1_BAD_VER & 0xff00))
+				{
+				SSLerr(SSL_F_DTLS1_CONNECT, ERR_R_INTERNAL_ERROR);
+				ret = -1;
+				goto end;
+				}
+				
+			/* s->version=SSL3_VERSION; */
+			s->type=SSL_ST_CONNECT;
+
+			if (s->init_buf == NULL)
+				{
+				if ((buf=BUF_MEM_new()) == NULL)
+					{
+					ret= -1;
+					goto end;
+					}
+				if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH))
+					{
+					ret= -1;
+					goto end;
+					}
+				s->init_buf=buf;
+				buf=NULL;
+				}
+
+			if (!ssl3_setup_buffers(s)) { ret= -1; goto end; }
+
+			/* setup buffing BIO */
+			if (!ssl_init_wbio_buffer(s,0)) { ret= -1; goto end; }
+
+			/* don't push the buffering BIO quite yet */
+
+			s->state=SSL3_ST_CW_CLNT_HELLO_A;
+			s->ctx->stats.sess_connect++;
+			s->init_num=0;
+			/* mark client_random uninitialized */
+			memset(s->s3->client_random,0,sizeof(s->s3->client_random));
+			s->d1->send_cookie = 0;
+			s->hit = 0;
+			break;
+
+		case SSL3_ST_CW_CLNT_HELLO_A:
+		case SSL3_ST_CW_CLNT_HELLO_B:
+
+			s->shutdown=0;
+
+			/* every DTLS ClientHello resets Finished MAC */
+			ssl3_init_finished_mac(s);
+
+			dtls1_start_timer(s);
+			ret=dtls1_client_hello(s);
+			if (ret <= 0) goto end;
+
+			if ( s->d1->send_cookie)
+				{
+				s->state=SSL3_ST_CW_FLUSH;
+				s->s3->tmp.next_state=SSL3_ST_CR_SRVR_HELLO_A;
+				}
+			else
+				s->state=SSL3_ST_CR_SRVR_HELLO_A;
+
+			s->init_num=0;
+
+			/* turn on buffering for the next lot of output */
+			if (s->bbio != s->wbio)
+				s->wbio=BIO_push(s->bbio,s->wbio);
+
+			break;
+
+		case SSL3_ST_CR_SRVR_HELLO_A:
+		case SSL3_ST_CR_SRVR_HELLO_B:
+			ret=ssl3_get_server_hello(s);
+			if (ret <= 0) goto end;
+			else
+				{
+				dtls1_stop_timer(s);
+				if (s->hit)
+					s->state=SSL3_ST_CR_FINISHED_A;
+				else
+					s->state=DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A;
+				}
+			s->init_num=0;
+			break;
+
+		case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A:
+		case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B:
+
+			ret = dtls1_get_hello_verify(s);
+			if ( ret <= 0)
+				goto end;
+			dtls1_stop_timer(s);
+			if ( s->d1->send_cookie) /* start again, with a cookie */
+				s->state=SSL3_ST_CW_CLNT_HELLO_A;
+			else
+				s->state = SSL3_ST_CR_CERT_A;
+			s->init_num = 0;
+			break;
+
+		case SSL3_ST_CR_CERT_A:
+		case SSL3_ST_CR_CERT_B:
+#ifndef OPENSSL_NO_TLSEXT
+			ret=ssl3_check_finished(s);
+			if (ret <= 0) goto end;
+			if (ret == 2)
+				{
+				s->hit = 1;
+				if (s->tlsext_ticket_expected)
+					s->state=SSL3_ST_CR_SESSION_TICKET_A;
+				else
+					s->state=SSL3_ST_CR_FINISHED_A;
+				s->init_num=0;
+				break;
+				}
+#endif
+			/* Check if it is anon DH or PSK */
+			if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) &&
+			    !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
+				{
+				ret=ssl3_get_server_certificate(s);
+				if (ret <= 0) goto end;
+#ifndef OPENSSL_NO_TLSEXT
+				if (s->tlsext_status_expected)
+					s->state=SSL3_ST_CR_CERT_STATUS_A;
+				else
+					s->state=SSL3_ST_CR_KEY_EXCH_A;
+				}
+			else
+				{
+				skip = 1;
+				s->state=SSL3_ST_CR_KEY_EXCH_A;
+				}
+#else
+				}
+			else
+				skip=1;
+
+			s->state=SSL3_ST_CR_KEY_EXCH_A;
+#endif
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_CR_KEY_EXCH_A:
+		case SSL3_ST_CR_KEY_EXCH_B:
+			ret=ssl3_get_key_exchange(s);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_CR_CERT_REQ_A;
+			s->init_num=0;
+
+			/* at this point we check that we have the
+			 * required stuff from the server */
+			if (!ssl3_check_cert_and_algorithm(s))
+				{
+				ret= -1;
+				goto end;
+				}
+			break;
+
+		case SSL3_ST_CR_CERT_REQ_A:
+		case SSL3_ST_CR_CERT_REQ_B:
+			ret=ssl3_get_certificate_request(s);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_CR_SRVR_DONE_A;
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_CR_SRVR_DONE_A:
+		case SSL3_ST_CR_SRVR_DONE_B:
+			ret=ssl3_get_server_done(s);
+			if (ret <= 0) goto end;
+			if (s->s3->tmp.cert_req)
+				s->state=SSL3_ST_CW_CERT_A;
+			else
+				s->state=SSL3_ST_CW_KEY_EXCH_A;
+			s->init_num=0;
+
+			break;
+
+		case SSL3_ST_CW_CERT_A:
+		case SSL3_ST_CW_CERT_B:
+		case SSL3_ST_CW_CERT_C:
+		case SSL3_ST_CW_CERT_D:
+			dtls1_start_timer(s);
+			ret=dtls1_send_client_certificate(s);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_CW_KEY_EXCH_A;
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_CW_KEY_EXCH_A:
+		case SSL3_ST_CW_KEY_EXCH_B:
+			dtls1_start_timer(s);
+			ret=dtls1_send_client_key_exchange(s);
+			if (ret <= 0) goto end;
+			/* EAY EAY EAY need to check for DH fix cert
+			 * sent back */
+			/* For TLS, cert_req is set to 2, so a cert chain
+			 * of nothing is sent, but no verify packet is sent */
+			if (s->s3->tmp.cert_req == 1)
+				{
+				s->state=SSL3_ST_CW_CERT_VRFY_A;
+				}
+			else
+				{
+				s->state=SSL3_ST_CW_CHANGE_A;
+				s->s3->change_cipher_spec=0;
+				}
+
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_CW_CERT_VRFY_A:
+		case SSL3_ST_CW_CERT_VRFY_B:
+			dtls1_start_timer(s);
+			ret=dtls1_send_client_verify(s);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_CW_CHANGE_A;
+			s->init_num=0;
+			s->s3->change_cipher_spec=0;
+			break;
+
+		case SSL3_ST_CW_CHANGE_A:
+		case SSL3_ST_CW_CHANGE_B:
+			dtls1_start_timer(s);
+			ret=dtls1_send_change_cipher_spec(s,
+				SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_CW_FINISHED_A;
+			s->init_num=0;
+
+			s->session->cipher=s->s3->tmp.new_cipher;
+#ifdef OPENSSL_NO_COMP
+			s->session->compress_meth=0;
+#else
+			if (s->s3->tmp.new_compression == NULL)
+				s->session->compress_meth=0;
+			else
+				s->session->compress_meth=
+					s->s3->tmp.new_compression->id;
+#endif
+			if (!s->method->ssl3_enc->setup_key_block(s))
+				{
+				ret= -1;
+				goto end;
+				}
+
+			if (!s->method->ssl3_enc->change_cipher_state(s,
+				SSL3_CHANGE_CIPHER_CLIENT_WRITE))
+				{
+				ret= -1;
+				goto end;
+				}
+			
+			dtls1_reset_seq_numbers(s, SSL3_CC_WRITE);
+			break;
+
+		case SSL3_ST_CW_FINISHED_A:
+		case SSL3_ST_CW_FINISHED_B:
+			dtls1_start_timer(s);
+			ret=dtls1_send_finished(s,
+				SSL3_ST_CW_FINISHED_A,SSL3_ST_CW_FINISHED_B,
+				s->method->ssl3_enc->client_finished_label,
+				s->method->ssl3_enc->client_finished_label_len);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_CW_FLUSH;
+
+			/* clear flags */
+			s->s3->flags&= ~SSL3_FLAGS_POP_BUFFER;
+			if (s->hit)
+				{
+				s->s3->tmp.next_state=SSL_ST_OK;
+				if (s->s3->flags & SSL3_FLAGS_DELAY_CLIENT_FINISHED)
+					{
+					s->state=SSL_ST_OK;
+					s->s3->flags|=SSL3_FLAGS_POP_BUFFER;
+					s->s3->delay_buf_pop_ret=0;
+					}
+				}
+			else
+				{
+#ifndef OPENSSL_NO_TLSEXT
+				/* Allow NewSessionTicket if ticket expected */
+				if (s->tlsext_ticket_expected)
+					s->s3->tmp.next_state=SSL3_ST_CR_SESSION_TICKET_A;
+				else
+#endif
+				
+				s->s3->tmp.next_state=SSL3_ST_CR_FINISHED_A;
+				}
+			s->init_num=0;
+			break;
+
+#ifndef OPENSSL_NO_TLSEXT
+		case SSL3_ST_CR_SESSION_TICKET_A:
+		case SSL3_ST_CR_SESSION_TICKET_B:
+			ret=ssl3_get_new_session_ticket(s);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_CR_FINISHED_A;
+			s->init_num=0;
+		break;
+
+		case SSL3_ST_CR_CERT_STATUS_A:
+		case SSL3_ST_CR_CERT_STATUS_B:
+			ret=ssl3_get_cert_status(s);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_CR_KEY_EXCH_A;
+			s->init_num=0;
+		break;
+#endif
+
+		case SSL3_ST_CR_FINISHED_A:
+		case SSL3_ST_CR_FINISHED_B:
+			s->d1->change_cipher_spec_ok = 1;
+			ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A,
+				SSL3_ST_CR_FINISHED_B);
+			if (ret <= 0) goto end;
+			dtls1_stop_timer(s);
+
+			if (s->hit)
+				s->state=SSL3_ST_CW_CHANGE_A;
+			else
+				s->state=SSL_ST_OK;
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_CW_FLUSH:
+			s->rwstate=SSL_WRITING;
+			if (BIO_flush(s->wbio) <= 0)
+				{
+				ret= -1;
+				goto end;
+				}
+			s->rwstate=SSL_NOTHING;
+			s->state=s->s3->tmp.next_state;
+			break;
+
+		case SSL_ST_OK:
+			/* clean a few things up */
+			ssl3_cleanup_key_block(s);
+
+#if 0
+			if (s->init_buf != NULL)
+				{
+				BUF_MEM_free(s->init_buf);
+				s->init_buf=NULL;
+				}
+#endif
+
+			/* If we are not 'joining' the last two packets,
+			 * remove the buffering now */
+			if (!(s->s3->flags & SSL3_FLAGS_POP_BUFFER))
+				ssl_free_wbio_buffer(s);
+			/* else do it later in ssl3_write */
+
+			s->init_num=0;
+			s->new_session=0;
+
+			ssl_update_cache(s,SSL_SESS_CACHE_CLIENT);
+			if (s->hit) s->ctx->stats.sess_hit++;
+
+			ret=1;
+			/* s->server=0; */
+			s->handshake_func=dtls1_connect;
+			s->ctx->stats.sess_connect_good++;
+
+			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1);
+
+			/* done with handshaking */
+			s->d1->handshake_read_seq  = 0;
+			s->d1->next_handshake_write_seq = 0;
+			goto end;
+			/* break; */
+			
+		default:
+			SSLerr(SSL_F_DTLS1_CONNECT,SSL_R_UNKNOWN_STATE);
+			ret= -1;
+			goto end;
+			/* break; */
+			}
+
+		/* did we do anything */
+		if (!s->s3->tmp.reuse_message && !skip)
+			{
+			if (s->debug)
+				{
+				if ((ret=BIO_flush(s->wbio)) <= 0)
+					goto end;
+				}
+
+			if ((cb != NULL) && (s->state != state))
+				{
+				new_state=s->state;
+				s->state=state;
+				cb(s,SSL_CB_CONNECT_LOOP,1);
+				s->state=new_state;
+				}
+			}
+		skip=0;
+		}
+end:
+	s->in_handshake--;
+	if (buf != NULL)
+		BUF_MEM_free(buf);
+	if (cb != NULL)
+		cb(s,SSL_CB_CONNECT_EXIT,ret);
+	return(ret);
+	}
+
+int dtls1_client_hello(SSL *s)
+	{
+	unsigned char *buf;
+	unsigned char *p,*d;
+	unsigned int i,j;
+	unsigned long Time,l;
+	SSL_COMP *comp;
+
+	buf=(unsigned char *)s->init_buf->data;
+	if (s->state == SSL3_ST_CW_CLNT_HELLO_A)
+		{
+		SSL_SESSION *sess = s->session;
+		if ((s->session == NULL) ||
+			(s->session->ssl_version != s->version) ||
+#ifdef OPENSSL_NO_TLSEXT
+			!sess->session_id_length ||
+#else
+			(!sess->session_id_length && !sess->tlsext_tick) ||
+#endif
+			(s->session->not_resumable))
+			{
+		        if (!s->session_creation_enabled)
+				{
+				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
+				SSLerr(SSL_F_DTLS1_CLIENT_HELLO,SSL_R_SESSION_MAY_NOT_BE_CREATED);
+				goto err;
+				}
+			if (!ssl_get_new_session(s,0))
+				goto err;
+			}
+		/* else use the pre-loaded session */
+
+		p=s->s3->client_random;
+
+		/* if client_random is initialized, reuse it, we are
+		 * required to use same upon reply to HelloVerify */
+		for (i=0;p[i]=='\0' && i<sizeof(s->s3->client_random);i++) ;
+		if (i==sizeof(s->s3->client_random))
+			{
+			Time=(unsigned long)time(NULL);	/* Time */
+			l2n(Time,p);
+			RAND_pseudo_bytes(p,sizeof(s->s3->client_random)-4);
+			}
+
+		/* Do the message type and length last */
+		d=p= &(buf[DTLS1_HM_HEADER_LENGTH]);
+
+		*(p++)=s->version>>8;
+		*(p++)=s->version&0xff;
+		s->client_version=s->version;
+
+		/* Random stuff */
+		memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE);
+		p+=SSL3_RANDOM_SIZE;
+
+		/* Session ID */
+		if (s->new_session)
+			i=0;
+		else
+			i=s->session->session_id_length;
+		*(p++)=i;
+		if (i != 0)
+			{
+			if (i > sizeof s->session->session_id)
+				{
+				SSLerr(SSL_F_DTLS1_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+				goto err;
+				}
+			memcpy(p,s->session->session_id,i);
+			p+=i;
+			}
+		
+		/* cookie stuff */
+		if ( s->d1->cookie_len > sizeof(s->d1->cookie))
+			{
+			SSLerr(SSL_F_DTLS1_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+			goto err;
+			}
+		*(p++) = s->d1->cookie_len;
+		memcpy(p, s->d1->cookie, s->d1->cookie_len);
+		p += s->d1->cookie_len;
+
+		/* Ciphers supported */
+		i=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),&(p[2]),0);
+		if (i == 0)
+			{
+			SSLerr(SSL_F_DTLS1_CLIENT_HELLO,SSL_R_NO_CIPHERS_AVAILABLE);
+			goto err;
+			}
+		s2n(i,p);
+		p+=i;
+
+		/* COMPRESSION */
+		if (s->ctx->comp_methods == NULL)
+			j=0;
+		else
+			j=sk_SSL_COMP_num(s->ctx->comp_methods);
+		*(p++)=1+j;
+		for (i=0; i<j; i++)
+			{
+			comp=sk_SSL_COMP_value(s->ctx->comp_methods,i);
+			*(p++)=comp->id;
+			}
+		*(p++)=0; /* Add the NULL method */
+
+#ifndef OPENSSL_NO_TLSEXT
+		if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
+			{
+			SSLerr(SSL_F_DTLS1_CLIENT_HELLO,ERR_R_INTERNAL_ERROR);
+			goto err;
+			}
+#endif		
+
+		l=(p-d);
+		d=buf;
+
+		d = dtls1_set_message_header(s, d, SSL3_MT_CLIENT_HELLO, l, 0, l);
+
+		s->state=SSL3_ST_CW_CLNT_HELLO_B;
+		/* number of bytes to write */
+		s->init_num=p-buf;
+		s->init_off=0;
+
+		/* buffer the message to handle re-xmits */
+		dtls1_buffer_message(s, 0);
+		}
+
+	/* SSL3_ST_CW_CLNT_HELLO_B */
+	return(dtls1_do_write(s,SSL3_RT_HANDSHAKE));
+err:
+	return(-1);
+	}
+
+static int dtls1_get_hello_verify(SSL *s)
+	{
+	int n, al, ok = 0;
+	unsigned char *data;
+	unsigned int cookie_len;
+
+	n=s->method->ssl_get_message(s,
+		DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A,
+		DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B,
+		-1,
+		s->max_cert_list,
+		&ok);
+
+	if (!ok) return((int)n);
+
+	if (s->s3->tmp.message_type != DTLS1_MT_HELLO_VERIFY_REQUEST)
+		{
+		s->d1->send_cookie = 0;
+		s->s3->tmp.reuse_message=1;
+		return(1);
+		}
+
+	data = (unsigned char *)s->init_msg;
+
+	if ((data[0] != (s->version>>8)) || (data[1] != (s->version&0xff)))
+		{
+		SSLerr(SSL_F_DTLS1_GET_HELLO_VERIFY,SSL_R_WRONG_SSL_VERSION);
+		s->version=(s->version&0xff00)|data[1];
+		al = SSL_AD_PROTOCOL_VERSION;
+		goto f_err;
+		}
+	data+=2;
+
+	cookie_len = *(data++);
+	if ( cookie_len > sizeof(s->d1->cookie))
+		{
+		al=SSL_AD_ILLEGAL_PARAMETER;
+		goto f_err;
+		}
+
+	memcpy(s->d1->cookie, data, cookie_len);
+	s->d1->cookie_len = cookie_len;
+
+	s->d1->send_cookie = 1;
+	return 1;
+
+f_err:
+	ssl3_send_alert(s, SSL3_AL_FATAL, al);
+	return -1;
+	}
+
+int dtls1_send_client_key_exchange(SSL *s)
+	{
+	unsigned char *p,*d;
+	int n;
+	unsigned long alg_k;
+#ifndef OPENSSL_NO_RSA
+	unsigned char *q;
+	EVP_PKEY *pkey=NULL;
+#endif
+#ifndef OPENSSL_NO_KRB5
+        KSSL_ERR kssl_err;
+#endif /* OPENSSL_NO_KRB5 */
+#ifndef OPENSSL_NO_ECDH
+	EC_KEY *clnt_ecdh = NULL;
+	const EC_POINT *srvr_ecpoint = NULL;
+	EVP_PKEY *srvr_pub_pkey = NULL;
+	unsigned char *encodedPoint = NULL;
+	int encoded_pt_len = 0;
+	BN_CTX * bn_ctx = NULL;
+#endif
+
+	if (s->state == SSL3_ST_CW_KEY_EXCH_A)
+		{
+		d=(unsigned char *)s->init_buf->data;
+		p= &(d[DTLS1_HM_HEADER_LENGTH]);
+		
+		alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
+
+                /* Fool emacs indentation */
+                if (0) {}
+#ifndef OPENSSL_NO_RSA
+		else if (alg_k & SSL_kRSA)
+			{
+			RSA *rsa;
+			unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
+
+			if (s->session->sess_cert->peer_rsa_tmp != NULL)
+				rsa=s->session->sess_cert->peer_rsa_tmp;
+			else
+				{
+				pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
+				if ((pkey == NULL) ||
+					(pkey->type != EVP_PKEY_RSA) ||
+					(pkey->pkey.rsa == NULL))
+					{
+					SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+					goto err;
+					}
+				rsa=pkey->pkey.rsa;
+				EVP_PKEY_free(pkey);
+				}
+				
+			tmp_buf[0]=s->client_version>>8;
+			tmp_buf[1]=s->client_version&0xff;
+			if (RAND_bytes(&(tmp_buf[2]),sizeof tmp_buf-2) <= 0)
+					goto err;
+
+			s->session->master_key_length=sizeof tmp_buf;
+
+			q=p;
+			/* Fix buf for TLS and [incidentally] DTLS */
+			if (s->version > SSL3_VERSION)
+				p+=2;
+			n=RSA_public_encrypt(sizeof tmp_buf,
+				tmp_buf,p,rsa,RSA_PKCS1_PADDING);
+#ifdef PKCS1_CHECK
+			if (s->options & SSL_OP_PKCS1_CHECK_1) p[1]++;
+			if (s->options & SSL_OP_PKCS1_CHECK_2) tmp_buf[0]=0x70;
+#endif
+			if (n <= 0)
+				{
+				SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_ENCRYPT);
+				goto err;
+				}
+
+			/* Fix buf for TLS and [incidentally] DTLS */
+			if (s->version > SSL3_VERSION)
+				{
+				s2n(n,q);
+				n+=2;
+				}
+
+			s->session->master_key_length=
+				s->method->ssl3_enc->generate_master_secret(s,
+					s->session->master_key,
+					tmp_buf,sizeof tmp_buf);
+			OPENSSL_cleanse(tmp_buf,sizeof tmp_buf);
+			}
+#endif
+#ifndef OPENSSL_NO_KRB5
+		else if (alg_k & SSL_kKRB5)
+                        {
+                        krb5_error_code	krb5rc;
+                        KSSL_CTX	*kssl_ctx = s->kssl_ctx;
+                        /*  krb5_data	krb5_ap_req;  */
+                        krb5_data	*enc_ticket;
+                        krb5_data	authenticator, *authp = NULL;
+			EVP_CIPHER_CTX	ciph_ctx;
+			const EVP_CIPHER *enc = NULL;
+			unsigned char	iv[EVP_MAX_IV_LENGTH];
+			unsigned char	tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
+			unsigned char	epms[SSL_MAX_MASTER_KEY_LENGTH 
+						+ EVP_MAX_IV_LENGTH];
+			int 		padl, outl = sizeof(epms);
+
+			EVP_CIPHER_CTX_init(&ciph_ctx);
+
+#ifdef KSSL_DEBUG
+                        printf("ssl3_send_client_key_exchange(%lx & %lx)\n",
+                                alg_k, SSL_kKRB5);
+#endif	/* KSSL_DEBUG */
+
+			authp = NULL;
+#ifdef KRB5SENDAUTH
+			if (KRB5SENDAUTH)  authp = &authenticator;
+#endif	/* KRB5SENDAUTH */
+
+                        krb5rc = kssl_cget_tkt(kssl_ctx, &enc_ticket, authp,
+				&kssl_err);
+			enc = kssl_map_enc(kssl_ctx->enctype);
+                        if (enc == NULL)
+                            goto err;
+#ifdef KSSL_DEBUG
+                        {
+                        printf("kssl_cget_tkt rtn %d\n", krb5rc);
+                        if (krb5rc && kssl_err.text)
+			  printf("kssl_cget_tkt kssl_err=%s\n", kssl_err.text);
+                        }
+#endif	/* KSSL_DEBUG */
+
+                        if (krb5rc)
+                                {
+                                ssl3_send_alert(s,SSL3_AL_FATAL,
+						SSL_AD_HANDSHAKE_FAILURE);
+                                SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,
+						kssl_err.reason);
+                                goto err;
+                                }
+
+			/*  20010406 VRS - Earlier versions used KRB5 AP_REQ
+			**  in place of RFC 2712 KerberosWrapper, as in:
+			**
+                        **  Send ticket (copy to *p, set n = length)
+                        **  n = krb5_ap_req.length;
+                        **  memcpy(p, krb5_ap_req.data, krb5_ap_req.length);
+                        **  if (krb5_ap_req.data)  
+                        **    kssl_krb5_free_data_contents(NULL,&krb5_ap_req);
+                        **
+			**  Now using real RFC 2712 KerberosWrapper
+			**  (Thanks to Simon Wilkinson <sxw@sxw.org.uk>)
+			**  Note: 2712 "opaque" types are here replaced
+			**  with a 2-byte length followed by the value.
+			**  Example:
+			**  KerberosWrapper= xx xx asn1ticket 0 0 xx xx encpms
+			**  Where "xx xx" = length bytes.  Shown here with
+			**  optional authenticator omitted.
+			*/
+
+			/*  KerberosWrapper.Ticket		*/
+			s2n(enc_ticket->length,p);
+			memcpy(p, enc_ticket->data, enc_ticket->length);
+			p+= enc_ticket->length;
+			n = enc_ticket->length + 2;
+
+			/*  KerberosWrapper.Authenticator	*/
+			if (authp  &&  authp->length)  
+				{
+				s2n(authp->length,p);
+				memcpy(p, authp->data, authp->length);
+				p+= authp->length;
+				n+= authp->length + 2;
+				
+				free(authp->data);
+				authp->data = NULL;
+				authp->length = 0;
+				}
+			else
+				{
+				s2n(0,p);/*  null authenticator length	*/
+				n+=2;
+				}
+ 
+			if (RAND_bytes(tmp_buf,sizeof tmp_buf) <= 0)
+			    goto err;
+
+			/*  20010420 VRS.  Tried it this way; failed.
+			**	EVP_EncryptInit_ex(&ciph_ctx,enc, NULL,NULL);
+			**	EVP_CIPHER_CTX_set_key_length(&ciph_ctx,
+			**				kssl_ctx->length);
+			**	EVP_EncryptInit_ex(&ciph_ctx,NULL, key,iv);
+			*/
+
+			memset(iv, 0, sizeof iv);  /* per RFC 1510 */
+			EVP_EncryptInit_ex(&ciph_ctx,enc, NULL,
+				kssl_ctx->key,iv);
+			EVP_EncryptUpdate(&ciph_ctx,epms,&outl,tmp_buf,
+				sizeof tmp_buf);
+			EVP_EncryptFinal_ex(&ciph_ctx,&(epms[outl]),&padl);
+			outl += padl;
+			if (outl > (int)sizeof epms)
+				{
+				SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+				goto err;
+				}
+			EVP_CIPHER_CTX_cleanup(&ciph_ctx);
+
+			/*  KerberosWrapper.EncryptedPreMasterSecret	*/
+			s2n(outl,p);
+			memcpy(p, epms, outl);
+			p+=outl;
+			n+=outl + 2;
+
+                        s->session->master_key_length=
+                                s->method->ssl3_enc->generate_master_secret(s,
+					s->session->master_key,
+					tmp_buf, sizeof tmp_buf);
+
+			OPENSSL_cleanse(tmp_buf, sizeof tmp_buf);
+			OPENSSL_cleanse(epms, outl);
+                        }
+#endif
+#ifndef OPENSSL_NO_DH
+		else if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
+			{
+			DH *dh_srvr,*dh_clnt;
+
+			if (s->session->sess_cert->peer_dh_tmp != NULL)
+				dh_srvr=s->session->sess_cert->peer_dh_tmp;
+			else
+				{
+				/* we get them from the cert */
+				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
+				SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNABLE_TO_FIND_DH_PARAMETERS);
+				goto err;
+				}
+			
+			/* generate a new random key */
+			if ((dh_clnt=DHparams_dup(dh_srvr)) == NULL)
+				{
+				SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
+				goto err;
+				}
+			if (!DH_generate_key(dh_clnt))
+				{
+				SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
+				goto err;
+				}
+
+			/* use the 'p' output buffer for the DH key, but
+			 * make sure to clear it out afterwards */
+
+			n=DH_compute_key(p,dh_srvr->pub_key,dh_clnt);
+
+			if (n <= 0)
+				{
+				SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
+				goto err;
+				}
+
+			/* generate master key from the result */
+			s->session->master_key_length=
+				s->method->ssl3_enc->generate_master_secret(s,
+					s->session->master_key,p,n);
+			/* clean up */
+			memset(p,0,n);
+
+			/* send off the data */
+			n=BN_num_bytes(dh_clnt->pub_key);
+			s2n(n,p);
+			BN_bn2bin(dh_clnt->pub_key,p);
+			n+=2;
+
+			DH_free(dh_clnt);
+
+			/* perhaps clean things up a bit EAY EAY EAY EAY*/
+			}
+#endif
+#ifndef OPENSSL_NO_ECDH 
+		else if (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe))
+			{
+			const EC_GROUP *srvr_group = NULL;
+			EC_KEY *tkey;
+			int ecdh_clnt_cert = 0;
+			int field_size = 0;
+
+			/* Did we send out the client's
+			 * ECDH share for use in premaster
+			 * computation as part of client certificate?
+			 * If so, set ecdh_clnt_cert to 1.
+			 */
+			if ((alg_k & (SSL_kECDHr|SSL_kECDHe)) && (s->cert != NULL)) 
+				{
+				/* XXX: For now, we do not support client
+				 * authentication using ECDH certificates.
+				 * To add such support, one needs to add
+				 * code that checks for appropriate 
+				 * conditions and sets ecdh_clnt_cert to 1.
+				 * For example, the cert have an ECC
+				 * key on the same curve as the server's
+				 * and the key should be authorized for
+				 * key agreement.
+				 *
+				 * One also needs to add code in ssl3_connect
+				 * to skip sending the certificate verify
+				 * message.
+				 *
+				 * if ((s->cert->key->privatekey != NULL) &&
+				 *     (s->cert->key->privatekey->type ==
+				 *      EVP_PKEY_EC) && ...)
+				 * ecdh_clnt_cert = 1;
+				 */
+				}
+
+			if (s->session->sess_cert->peer_ecdh_tmp != NULL)
+				{
+				tkey = s->session->sess_cert->peer_ecdh_tmp;
+				}
+			else
+				{
+				/* Get the Server Public Key from Cert */
+				srvr_pub_pkey = X509_get_pubkey(s->session-> \
+				    sess_cert->peer_pkeys[SSL_PKEY_ECC].x509);
+				if ((srvr_pub_pkey == NULL) ||
+				    (srvr_pub_pkey->type != EVP_PKEY_EC) ||
+				    (srvr_pub_pkey->pkey.ec == NULL))
+					{
+					SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,
+					    ERR_R_INTERNAL_ERROR);
+					goto err;
+					}
+
+				tkey = srvr_pub_pkey->pkey.ec;
+				}
+
+			srvr_group   = EC_KEY_get0_group(tkey);
+			srvr_ecpoint = EC_KEY_get0_public_key(tkey);
+
+			if ((srvr_group == NULL) || (srvr_ecpoint == NULL))
+				{
+				SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,
+				    ERR_R_INTERNAL_ERROR);
+				goto err;
+				}
+
+			if ((clnt_ecdh=EC_KEY_new()) == NULL) 
+				{
+				SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
+				goto err;
+				}
+
+			if (!EC_KEY_set_group(clnt_ecdh, srvr_group))
+				{
+				SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_EC_LIB);
+				goto err;
+				}
+			if (ecdh_clnt_cert) 
+				{ 
+				/* Reuse key info from our certificate
+				 * We only need our private key to perform
+				 * the ECDH computation.
+				 */
+				const BIGNUM *priv_key;
+				tkey = s->cert->key->privatekey->pkey.ec;
+				priv_key = EC_KEY_get0_private_key(tkey);
+				if (priv_key == NULL)
+					{
+					SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
+					goto err;
+					}
+				if (!EC_KEY_set_private_key(clnt_ecdh, priv_key))
+					{
+					SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_EC_LIB);
+					goto err;
+					}
+				}
+			else 
+				{
+				/* Generate a new ECDH key pair */
+				if (!(EC_KEY_generate_key(clnt_ecdh)))
+					{
+					SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB);
+					goto err;
+					}
+				}
+
+			/* use the 'p' output buffer for the ECDH key, but
+			 * make sure to clear it out afterwards
+			 */
+
+			field_size = EC_GROUP_get_degree(srvr_group);
+			if (field_size <= 0)
+				{
+				SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, 
+				       ERR_R_ECDH_LIB);
+				goto err;
+				}
+			n=ECDH_compute_key(p, (field_size+7)/8, srvr_ecpoint, clnt_ecdh, NULL);
+			if (n <= 0)
+				{
+				SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, 
+				       ERR_R_ECDH_LIB);
+				goto err;
+				}
+
+			/* generate master key from the result */
+			s->session->master_key_length = s->method->ssl3_enc \
+			    -> generate_master_secret(s, 
+				s->session->master_key,
+				p, n);
+
+			memset(p, 0, n); /* clean up */
+
+			if (ecdh_clnt_cert) 
+				{
+				/* Send empty client key exch message */
+				n = 0;
+				}
+			else 
+				{
+				/* First check the size of encoding and
+				 * allocate memory accordingly.
+				 */
+				encoded_pt_len = 
+				    EC_POINT_point2oct(srvr_group, 
+					EC_KEY_get0_public_key(clnt_ecdh), 
+					POINT_CONVERSION_UNCOMPRESSED, 
+					NULL, 0, NULL);
+
+				encodedPoint = (unsigned char *) 
+				    OPENSSL_malloc(encoded_pt_len * 
+					sizeof(unsigned char)); 
+				bn_ctx = BN_CTX_new();
+				if ((encodedPoint == NULL) || 
+				    (bn_ctx == NULL)) 
+					{
+					SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
+					goto err;
+					}
+
+				/* Encode the public key */
+				n = EC_POINT_point2oct(srvr_group, 
+				    EC_KEY_get0_public_key(clnt_ecdh), 
+				    POINT_CONVERSION_UNCOMPRESSED, 
+				    encodedPoint, encoded_pt_len, bn_ctx);
+
+				*p = n; /* length of encoded point */
+				/* Encoded point will be copied here */
+				p += 1; 
+				/* copy the point */
+				memcpy((unsigned char *)p, encodedPoint, n);
+				/* increment n to account for length field */
+				n += 1; 
+				}
+
+			/* Free allocated memory */
+			BN_CTX_free(bn_ctx);
+			if (encodedPoint != NULL) OPENSSL_free(encodedPoint);
+			if (clnt_ecdh != NULL) 
+				 EC_KEY_free(clnt_ecdh);
+			EVP_PKEY_free(srvr_pub_pkey);
+			}
+#endif /* !OPENSSL_NO_ECDH */
+
+#ifndef OPENSSL_NO_PSK
+		else if (alg_k & SSL_kPSK)
+			{
+			char identity[PSK_MAX_IDENTITY_LEN];
+			unsigned char *t = NULL;
+			unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN*2+4];
+			unsigned int pre_ms_len = 0, psk_len = 0;
+			int psk_err = 1;
+
+			n = 0;
+			if (s->psk_client_callback == NULL)
+				{
+				SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,
+					SSL_R_PSK_NO_CLIENT_CB);
+				goto err;
+				}
+
+			psk_len = s->psk_client_callback(s, s->ctx->psk_identity_hint,
+				identity, PSK_MAX_IDENTITY_LEN,
+				psk_or_pre_ms, sizeof(psk_or_pre_ms));
+			if (psk_len > PSK_MAX_PSK_LEN)
+				{
+				SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,
+					ERR_R_INTERNAL_ERROR);
+				goto psk_err;
+				}
+			else if (psk_len == 0)
+				{
+				SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,
+					SSL_R_PSK_IDENTITY_NOT_FOUND);
+				goto psk_err;
+				}
+
+			/* create PSK pre_master_secret */
+			pre_ms_len = 2+psk_len+2+psk_len;
+			t = psk_or_pre_ms;
+			memmove(psk_or_pre_ms+psk_len+4, psk_or_pre_ms, psk_len);
+			s2n(psk_len, t);
+			memset(t, 0, psk_len);
+			t+=psk_len;
+			s2n(psk_len, t);
+
+			if (s->session->psk_identity_hint != NULL)
+				OPENSSL_free(s->session->psk_identity_hint);
+			s->session->psk_identity_hint = BUF_strdup(s->ctx->psk_identity_hint);
+			if (s->ctx->psk_identity_hint != NULL &&
+				s->session->psk_identity_hint == NULL)
+				{
+				SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,
+					ERR_R_MALLOC_FAILURE);
+				goto psk_err;
+				}
+
+			if (s->session->psk_identity != NULL)
+				OPENSSL_free(s->session->psk_identity);
+			s->session->psk_identity = BUF_strdup(identity);
+			if (s->session->psk_identity == NULL)
+				{
+				SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,
+					ERR_R_MALLOC_FAILURE);
+				goto psk_err;
+				}
+
+			s->session->master_key_length =
+				s->method->ssl3_enc->generate_master_secret(s,
+					s->session->master_key,
+					psk_or_pre_ms, pre_ms_len); 
+			n = strlen(identity);
+			s2n(n, p);
+			memcpy(p, identity, n);
+			n+=2;
+			psk_err = 0;
+		psk_err:
+			OPENSSL_cleanse(identity, PSK_MAX_IDENTITY_LEN);
+			OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms));
+			if (psk_err != 0)
+				{
+				ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+				goto err;
+				}
+			}
+#endif
+		else
+			{
+			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
+			SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+			goto err;
+			}
+		
+		d = dtls1_set_message_header(s, d,
+		SSL3_MT_CLIENT_KEY_EXCHANGE, n, 0, n);
+		/*
+		 *(d++)=SSL3_MT_CLIENT_KEY_EXCHANGE;
+		 l2n3(n,d);
+		 l2n(s->d1->handshake_write_seq,d);
+		 s->d1->handshake_write_seq++;
+		*/
+		
+		s->state=SSL3_ST_CW_KEY_EXCH_B;
+		/* number of bytes to write */
+		s->init_num=n+DTLS1_HM_HEADER_LENGTH;
+		s->init_off=0;
+
+		/* buffer the message to handle re-xmits */
+		dtls1_buffer_message(s, 0);
+		}
+	
+	/* SSL3_ST_CW_KEY_EXCH_B */
+	return(dtls1_do_write(s,SSL3_RT_HANDSHAKE));
+err:
+#ifndef OPENSSL_NO_ECDH
+	BN_CTX_free(bn_ctx);
+	if (encodedPoint != NULL) OPENSSL_free(encodedPoint);
+	if (clnt_ecdh != NULL) 
+		EC_KEY_free(clnt_ecdh);
+	EVP_PKEY_free(srvr_pub_pkey);
+#endif
+	return(-1);
+	}
+
+int dtls1_send_client_verify(SSL *s)
+	{
+	unsigned char *p,*d;
+	unsigned char data[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH];
+	EVP_PKEY *pkey;
+#ifndef OPENSSL_NO_RSA
+	unsigned u=0;
+#endif
+	unsigned long n;
+#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_ECDSA)
+	int j;
+#endif
+
+	if (s->state == SSL3_ST_CW_CERT_VRFY_A)
+		{
+		d=(unsigned char *)s->init_buf->data;
+		p= &(d[DTLS1_HM_HEADER_LENGTH]);
+		pkey=s->cert->key->privatekey;
+
+		s->method->ssl3_enc->cert_verify_mac(s,
+		NID_sha1,
+			&(data[MD5_DIGEST_LENGTH]));
+
+#ifndef OPENSSL_NO_RSA
+		if (pkey->type == EVP_PKEY_RSA)
+			{
+			s->method->ssl3_enc->cert_verify_mac(s,
+				NID_md5,
+				&(data[0]));
+			if (RSA_sign(NID_md5_sha1, data,
+					 MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH,
+					&(p[2]), &u, pkey->pkey.rsa) <= 0 )
+				{
+				SSLerr(SSL_F_DTLS1_SEND_CLIENT_VERIFY,ERR_R_RSA_LIB);
+				goto err;
+				}
+			s2n(u,p);
+			n=u+2;
+			}
+		else
+#endif
+#ifndef OPENSSL_NO_DSA
+			if (pkey->type == EVP_PKEY_DSA)
+			{
+			if (!DSA_sign(pkey->save_type,
+				&(data[MD5_DIGEST_LENGTH]),
+				SHA_DIGEST_LENGTH,&(p[2]),
+				(unsigned int *)&j,pkey->pkey.dsa))
+				{
+				SSLerr(SSL_F_DTLS1_SEND_CLIENT_VERIFY,ERR_R_DSA_LIB);
+				goto err;
+				}
+			s2n(j,p);
+			n=j+2;
+			}
+		else
+#endif
+#ifndef OPENSSL_NO_ECDSA
+			if (pkey->type == EVP_PKEY_EC)
+			{
+			if (!ECDSA_sign(pkey->save_type,
+				&(data[MD5_DIGEST_LENGTH]),
+				SHA_DIGEST_LENGTH,&(p[2]),
+				(unsigned int *)&j,pkey->pkey.ec))
+				{
+				SSLerr(SSL_F_DTLS1_SEND_CLIENT_VERIFY,
+				    ERR_R_ECDSA_LIB);
+				goto err;
+				}
+			s2n(j,p);
+			n=j+2;
+			}
+		else
+#endif
+			{
+			SSLerr(SSL_F_DTLS1_SEND_CLIENT_VERIFY,ERR_R_INTERNAL_ERROR);
+			goto err;
+			}
+
+		d = dtls1_set_message_header(s, d,
+			SSL3_MT_CERTIFICATE_VERIFY, n, 0, n) ;
+
+		s->init_num=(int)n+DTLS1_HM_HEADER_LENGTH;
+		s->init_off=0;
+
+		/* buffer the message to handle re-xmits */
+		dtls1_buffer_message(s, 0);
+
+		s->state = SSL3_ST_CW_CERT_VRFY_B;
+		}
+
+	/* s->state = SSL3_ST_CW_CERT_VRFY_B */
+	return(dtls1_do_write(s,SSL3_RT_HANDSHAKE));
+err:
+	return(-1);
+	}
+
+int dtls1_send_client_certificate(SSL *s)
+	{
+	X509 *x509=NULL;
+	EVP_PKEY *pkey=NULL;
+	int i;
+	unsigned long l;
+
+	if (s->state ==	SSL3_ST_CW_CERT_A)
+		{
+		if ((s->cert == NULL) ||
+			(s->cert->key->x509 == NULL) ||
+			(s->cert->key->privatekey == NULL))
+			s->state=SSL3_ST_CW_CERT_B;
+		else
+			s->state=SSL3_ST_CW_CERT_C;
+		}
+
+	/* We need to get a client cert */
+	if (s->state == SSL3_ST_CW_CERT_B)
+		{
+		/* If we get an error, we need to
+		 * ssl->rwstate=SSL_X509_LOOKUP; return(-1);
+		 * We then get retied later */
+		i=0;
+		i = ssl_do_client_cert_cb(s, &x509, &pkey);
+		if (i < 0)
+			{
+			s->rwstate=SSL_X509_LOOKUP;
+			return(-1);
+			}
+		s->rwstate=SSL_NOTHING;
+		if ((i == 1) && (pkey != NULL) && (x509 != NULL))
+			{
+			s->state=SSL3_ST_CW_CERT_B;
+			if (	!SSL_use_certificate(s,x509) ||
+				!SSL_use_PrivateKey(s,pkey))
+				i=0;
+			}
+		else if (i == 1)
+			{
+			i=0;
+			SSLerr(SSL_F_DTLS1_SEND_CLIENT_CERTIFICATE,SSL_R_BAD_DATA_RETURNED_BY_CALLBACK);
+			}
+
+		if (x509 != NULL) X509_free(x509);
+		if (pkey != NULL) EVP_PKEY_free(pkey);
+		if (i == 0)
+			{
+			if (s->version == SSL3_VERSION)
+				{
+				s->s3->tmp.cert_req=0;
+				ssl3_send_alert(s,SSL3_AL_WARNING,SSL_AD_NO_CERTIFICATE);
+				return(1);
+				}
+			else
+				{
+				s->s3->tmp.cert_req=2;
+				}
+			}
+
+		/* Ok, we have a cert */
+		s->state=SSL3_ST_CW_CERT_C;
+		}
+
+	if (s->state == SSL3_ST_CW_CERT_C)
+		{
+		s->state=SSL3_ST_CW_CERT_D;
+		l=dtls1_output_cert_chain(s,
+			(s->s3->tmp.cert_req == 2)?NULL:s->cert->key->x509);
+		s->init_num=(int)l;
+		s->init_off=0;
+
+		/* set header called by dtls1_output_cert_chain() */
+
+		/* buffer the message to handle re-xmits */
+		dtls1_buffer_message(s, 0);
+		}
+	/* SSL3_ST_CW_CERT_D */
+	return(dtls1_do_write(s,SSL3_RT_HANDSHAKE));
+	}
+
+
diff --git a/lib/openssl/ssl/d1_enc.c b/lib/openssl/ssl/d1_enc.c
new file mode 100644
index 0000000..8fa5734
--- /dev/null
+++ b/lib/openssl/ssl/d1_enc.c
@@ -0,0 +1,293 @@
+/* ssl/d1_enc.c */
+/* 
+ * DTLS implementation written by Nagendra Modadugu
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.  
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include "ssl_locl.h"
+#ifndef OPENSSL_NO_COMP
+#include <openssl/comp.h>
+#endif
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/md5.h>
+#include <openssl/rand.h>
+#ifdef KSSL_DEBUG
+#include <openssl/des.h>
+#endif
+
+int dtls1_enc(SSL *s, int send)
+	{
+	SSL3_RECORD *rec;
+	EVP_CIPHER_CTX *ds;
+	unsigned long l;
+	int bs,i,ii,j,k,n=0;
+	const EVP_CIPHER *enc;
+
+	if (send)
+		{
+		if (EVP_MD_CTX_md(s->write_hash))
+			{
+			n=EVP_MD_CTX_size(s->write_hash);
+			if (n < 0)
+				return -1;
+			}
+		ds=s->enc_write_ctx;
+		rec= &(s->s3->wrec);
+		if (s->enc_write_ctx == NULL)
+			enc=NULL;
+		else
+			{
+			enc=EVP_CIPHER_CTX_cipher(s->enc_write_ctx);
+			if ( rec->data != rec->input)
+				/* we can't write into the input stream */
+				fprintf(stderr, "%s:%d: rec->data != rec->input\n",
+					__FILE__, __LINE__);
+			else if ( EVP_CIPHER_block_size(ds->cipher) > 1)
+				{
+				if (RAND_bytes(rec->input, EVP_CIPHER_block_size(ds->cipher)) <= 0)
+					return -1;
+				}
+			}
+		}
+	else
+		{
+		if (EVP_MD_CTX_md(s->read_hash))
+			{
+			n=EVP_MD_CTX_size(s->read_hash);
+			if (n < 0)
+				return -1;
+			}
+		ds=s->enc_read_ctx;
+		rec= &(s->s3->rrec);
+		if (s->enc_read_ctx == NULL)
+			enc=NULL;
+		else
+			enc=EVP_CIPHER_CTX_cipher(s->enc_read_ctx);
+		}
+
+#ifdef KSSL_DEBUG
+	printf("dtls1_enc(%d)\n", send);
+#endif    /* KSSL_DEBUG */
+
+	if ((s->session == NULL) || (ds == NULL) ||
+		(enc == NULL))
+		{
+		memmove(rec->data,rec->input,rec->length);
+		rec->input=rec->data;
+		}
+	else
+		{
+		l=rec->length;
+		bs=EVP_CIPHER_block_size(ds->cipher);
+
+		if ((bs != 1) && send)
+			{
+			i=bs-((int)l%bs);
+
+			/* Add weird padding of upto 256 bytes */
+
+			/* we need to add 'i' padding bytes of value j */
+			j=i-1;
+			if (s->options & SSL_OP_TLS_BLOCK_PADDING_BUG)
+				{
+				if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG)
+					j++;
+				}
+			for (k=(int)l; k<(int)(l+i); k++)
+				rec->input[k]=j;
+			l+=i;
+			rec->length+=i;
+			}
+
+#ifdef KSSL_DEBUG
+		{
+                unsigned long ui;
+		printf("EVP_Cipher(ds=%p,rec->data=%p,rec->input=%p,l=%ld) ==>\n",
+                        ds,rec->data,rec->input,l);
+		printf("\tEVP_CIPHER_CTX: %d buf_len, %d key_len [%d %d], %d iv_len\n",
+                        ds->buf_len, ds->cipher->key_len,
+                        DES_KEY_SZ, DES_SCHEDULE_SZ,
+                        ds->cipher->iv_len);
+		printf("\t\tIV: ");
+		for (i=0; i<ds->cipher->iv_len; i++) printf("%02X", ds->iv[i]);
+		printf("\n");
+		printf("\trec->input=");
+		for (ui=0; ui<l; ui++) printf(" %02x", rec->input[ui]);
+		printf("\n");
+		}
+#endif	/* KSSL_DEBUG */
+
+		if (!send)
+			{
+			if (l == 0 || l%bs != 0)
+				{
+				SSLerr(SSL_F_DTLS1_ENC,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG);
+				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECRYPTION_FAILED);
+				return 0;
+				}
+			}
+		
+		EVP_Cipher(ds,rec->data,rec->input,l);
+
+#ifdef KSSL_DEBUG
+		{
+                unsigned long i;
+                printf("\trec->data=");
+		for (i=0; i<l; i++)
+                        printf(" %02x", rec->data[i]);  printf("\n");
+                }
+#endif	/* KSSL_DEBUG */
+
+		if ((bs != 1) && !send)
+			{
+			ii=i=rec->data[l-1]; /* padding_length */
+			i++;
+			if (s->options&SSL_OP_TLS_BLOCK_PADDING_BUG)
+				{
+				/* First packet is even in size, so check */
+				if ((memcmp(s->s3->read_sequence,
+					"\0\0\0\0\0\0\0\0",8) == 0) && !(ii & 1))
+					s->s3->flags|=TLS1_FLAGS_TLS_PADDING_BUG;
+				if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG)
+					i--;
+				}
+			/* TLS 1.0 does not bound the number of padding bytes by the block size.
+			 * All of them must have value 'padding_length'. */
+			if (i > (int)rec->length)
+				{
+				/* Incorrect padding. SSLerr() and ssl3_alert are done
+				 * by caller: we don't want to reveal whether this is
+				 * a decryption error or a MAC verification failure
+				 * (see http://www.openssl.org/~bodo/tls-cbc.txt) 
+				 */
+				return -1;
+				}
+			for (j=(int)(l-i); j<(int)l; j++)
+				{
+				if (rec->data[j] != ii)
+					{
+					/* Incorrect padding */
+					return -1;
+					}
+				}
+			rec->length-=i;
+
+			rec->data += bs;    /* skip the implicit IV */
+			rec->input += bs;
+			rec->length -= bs;
+			}
+		}
+	return(1);
+	}
+
diff --git a/lib/openssl/ssl/d1_lib.c b/lib/openssl/ssl/d1_lib.c
new file mode 100644
index 0000000..96b220e
--- /dev/null
+++ b/lib/openssl/ssl/d1_lib.c
@@ -0,0 +1,394 @@
+/* ssl/d1_lib.c */
+/* 
+ * DTLS implementation written by Nagendra Modadugu
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.  
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <stdio.h>
+#define USE_SOCKETS
+#include <openssl/objects.h>
+#include "ssl_locl.h"
+
+#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS)
+#include <sys/timeb.h>
+#endif
+
+static void get_current_time(struct timeval *t);
+const char dtls1_version_str[]="DTLSv1" OPENSSL_VERSION_PTEXT;
+int dtls1_listen(SSL *s, struct sockaddr *client);
+
+SSL3_ENC_METHOD DTLSv1_enc_data={
+    dtls1_enc,
+	tls1_mac,
+	tls1_setup_key_block,
+	tls1_generate_master_secret,
+	tls1_change_cipher_state,
+	tls1_final_finish_mac,
+	TLS1_FINISH_MAC_LENGTH,
+	tls1_cert_verify_mac,
+	TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE,
+	TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE,
+	tls1_alert_code,
+	};
+
+long dtls1_default_timeout(void)
+	{
+	/* 2 hours, the 24 hours mentioned in the DTLSv1 spec
+	 * is way too long for http, the cache would over fill */
+	return(60*60*2);
+	}
+
+int dtls1_new(SSL *s)
+	{
+	DTLS1_STATE *d1;
+
+	if (!ssl3_new(s)) return(0);
+	if ((d1=OPENSSL_malloc(sizeof *d1)) == NULL) return (0);
+	memset(d1,0, sizeof *d1);
+
+	/* d1->handshake_epoch=0; */
+
+	d1->unprocessed_rcds.q=pqueue_new();
+	d1->processed_rcds.q=pqueue_new();
+	d1->buffered_messages = pqueue_new();
+	d1->sent_messages=pqueue_new();
+	d1->buffered_app_data.q=pqueue_new();
+
+	if ( s->server)
+		{
+		d1->cookie_len = sizeof(s->d1->cookie);
+		}
+
+	if( ! d1->unprocessed_rcds.q || ! d1->processed_rcds.q 
+        || ! d1->buffered_messages || ! d1->sent_messages || ! d1->buffered_app_data.q)
+		{
+        if ( d1->unprocessed_rcds.q) pqueue_free(d1->unprocessed_rcds.q);
+        if ( d1->processed_rcds.q) pqueue_free(d1->processed_rcds.q);
+        if ( d1->buffered_messages) pqueue_free(d1->buffered_messages);
+		if ( d1->sent_messages) pqueue_free(d1->sent_messages);
+		if ( d1->buffered_app_data.q) pqueue_free(d1->buffered_app_data.q);
+		OPENSSL_free(d1);
+		return (0);
+		}
+
+	s->d1=d1;
+	s->method->ssl_clear(s);
+	return(1);
+	}
+
+void dtls1_free(SSL *s)
+	{
+    pitem *item = NULL;
+    hm_fragment *frag = NULL;
+
+	ssl3_free(s);
+
+    while( (item = pqueue_pop(s->d1->unprocessed_rcds.q)) != NULL)
+        {
+        OPENSSL_free(item->data);
+        pitem_free(item);
+        }
+    pqueue_free(s->d1->unprocessed_rcds.q);
+
+    while( (item = pqueue_pop(s->d1->processed_rcds.q)) != NULL)
+        {
+        OPENSSL_free(item->data);
+        pitem_free(item);
+        }
+    pqueue_free(s->d1->processed_rcds.q);
+
+    while( (item = pqueue_pop(s->d1->buffered_messages)) != NULL)
+        {
+        frag = (hm_fragment *)item->data;
+        OPENSSL_free(frag->fragment);
+        OPENSSL_free(frag);
+        pitem_free(item);
+        }
+    pqueue_free(s->d1->buffered_messages);
+
+    while ( (item = pqueue_pop(s->d1->sent_messages)) != NULL)
+        {
+        frag = (hm_fragment *)item->data;
+        OPENSSL_free(frag->fragment);
+        OPENSSL_free(frag);
+        pitem_free(item);
+        }
+	pqueue_free(s->d1->sent_messages);
+
+	while ( (item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL)
+		{
+		frag = (hm_fragment *)item->data;
+		OPENSSL_free(frag->fragment);
+		OPENSSL_free(frag);
+		pitem_free(item);
+		}
+	pqueue_free(s->d1->buffered_app_data.q);
+
+	OPENSSL_free(s->d1);
+	}
+
+void dtls1_clear(SSL *s)
+	{
+	ssl3_clear(s);
+	if (s->options & SSL_OP_CISCO_ANYCONNECT)
+		s->version=DTLS1_BAD_VER;
+	else
+		s->version=DTLS1_VERSION;
+	}
+
+long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg)
+	{
+	int ret=0;
+
+	switch (cmd)
+		{
+	case DTLS_CTRL_GET_TIMEOUT:
+		if (dtls1_get_timeout(s, (struct timeval*) parg) != NULL)
+			{
+			ret = 1;
+			}
+		break;
+	case DTLS_CTRL_HANDLE_TIMEOUT:
+		ret = dtls1_handle_timeout(s);
+		break;
+	case DTLS_CTRL_LISTEN:
+		ret = dtls1_listen(s, parg);
+		break;
+
+	default:
+		ret = ssl3_ctrl(s, cmd, larg, parg);
+		break;
+		}
+	return(ret);
+	}
+
+/*
+ * As it's impossible to use stream ciphers in "datagram" mode, this
+ * simple filter is designed to disengage them in DTLS. Unfortunately
+ * there is no universal way to identify stream SSL_CIPHER, so we have
+ * to explicitly list their SSL_* codes. Currently RC4 is the only one
+ * available, but if new ones emerge, they will have to be added...
+ */
+const SSL_CIPHER *dtls1_get_cipher(unsigned int u)
+	{
+	const SSL_CIPHER *ciph = ssl3_get_cipher(u);
+
+	if (ciph != NULL)
+		{
+		if (ciph->algorithm_enc == SSL_RC4)
+			return NULL;
+		}
+
+	return ciph;
+	}
+
+void dtls1_start_timer(SSL *s)
+	{
+	/* If timer is not set, initialize duration with 1 second */
+	if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0)
+		{
+		s->d1->timeout_duration = 1;
+		}
+	
+	/* Set timeout to current time */
+	get_current_time(&(s->d1->next_timeout));
+
+	/* Add duration to current time */
+	s->d1->next_timeout.tv_sec += s->d1->timeout_duration;
+	BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, &(s->d1->next_timeout));
+	}
+
+struct timeval* dtls1_get_timeout(SSL *s, struct timeval* timeleft)
+	{
+	struct timeval timenow;
+
+	/* If no timeout is set, just return NULL */
+	if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0)
+		{
+		return NULL;
+		}
+
+	/* Get current time */
+	get_current_time(&timenow);
+
+	/* If timer already expired, set remaining time to 0 */
+	if (s->d1->next_timeout.tv_sec < timenow.tv_sec ||
+		(s->d1->next_timeout.tv_sec == timenow.tv_sec &&
+		 s->d1->next_timeout.tv_usec <= timenow.tv_usec))
+		{
+		memset(timeleft, 0, sizeof(struct timeval));
+		return timeleft;
+		}
+
+	/* Calculate time left until timer expires */
+	memcpy(timeleft, &(s->d1->next_timeout), sizeof(struct timeval));
+	timeleft->tv_sec -= timenow.tv_sec;
+	timeleft->tv_usec -= timenow.tv_usec;
+	if (timeleft->tv_usec < 0)
+		{
+		timeleft->tv_sec--;
+		timeleft->tv_usec += 1000000;
+		}
+
+	/* If remaining time is less than 15 ms, set it to 0
+	 * to prevent issues because of small devergences with
+	 * socket timeouts.
+	 */
+	if (timeleft->tv_sec == 0 && timeleft->tv_usec < 15000)
+		{
+		memset(timeleft, 0, sizeof(struct timeval));
+		}
+	
+
+	return timeleft;
+	}
+
+int dtls1_is_timer_expired(SSL *s)
+	{
+	struct timeval timeleft;
+
+	/* Get time left until timeout, return false if no timer running */
+	if (dtls1_get_timeout(s, &timeleft) == NULL)
+		{
+		return 0;
+		}
+
+	/* Return false if timer is not expired yet */
+	if (timeleft.tv_sec > 0 || timeleft.tv_usec > 0)
+		{
+		return 0;
+		}
+
+	/* Timer expired, so return true */	
+	return 1;
+	}
+
+void dtls1_double_timeout(SSL *s)
+	{
+	s->d1->timeout_duration *= 2;
+	if (s->d1->timeout_duration > 60)
+		s->d1->timeout_duration = 60;
+	dtls1_start_timer(s);
+	}
+
+void dtls1_stop_timer(SSL *s)
+	{
+	/* Reset everything */
+	memset(&(s->d1->next_timeout), 0, sizeof(struct timeval));
+	s->d1->timeout_duration = 1;
+	BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, &(s->d1->next_timeout));
+	}
+
+int dtls1_handle_timeout(SSL *s)
+	{
+	DTLS1_STATE *state;
+
+	/* if no timer is expired, don't do anything */
+	if (!dtls1_is_timer_expired(s))
+		{
+		return 0;
+		}
+
+	dtls1_double_timeout(s);
+	state = s->d1;
+	state->timeout.num_alerts++;
+	if ( state->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT)
+		{
+		/* fail the connection, enough alerts have been sent */
+		SSLerr(SSL_F_DTLS1_HANDLE_TIMEOUT,SSL_R_READ_TIMEOUT_EXPIRED);
+		return 0;
+		}
+
+	state->timeout.read_timeouts++;
+	if ( state->timeout.read_timeouts > DTLS1_TMO_READ_COUNT)
+		{
+		state->timeout.read_timeouts = 1;
+		}
+
+	dtls1_start_timer(s);
+	return dtls1_retransmit_buffered_messages(s);
+	}
+
+static void get_current_time(struct timeval *t)
+{
+#ifdef OPENSSL_SYS_WIN32
+	struct _timeb tb;
+	_ftime(&tb);
+	t->tv_sec = (long)tb.time;
+	t->tv_usec = (long)tb.millitm * 1000;
+#elif defined(OPENSSL_SYS_VMS)
+	struct timeb tb;
+	ftime(&tb);
+	t->tv_sec = (long)tb.time;
+	t->tv_usec = (long)tb.millitm * 1000;
+#else
+	gettimeofday(t, NULL);
+#endif
+}
+
+int dtls1_listen(SSL *s, struct sockaddr *client)
+	{
+	int ret;
+
+	SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE);
+	s->d1->listen = 1;
+
+	ret = SSL_accept(s);
+	if (ret <= 0) return ret;
+	
+	(void) BIO_dgram_get_peer(SSL_get_rbio(s), client);
+	return 1;
+	}
diff --git a/lib/openssl/ssl/d1_meth.c b/lib/openssl/ssl/d1_meth.c
new file mode 100644
index 0000000..5c4004b
--- /dev/null
+++ b/lib/openssl/ssl/d1_meth.c
@@ -0,0 +1,77 @@
+/* ssl/d1_meth.h */
+/* 
+ * DTLS implementation written by Nagendra Modadugu
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.  
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <stdio.h>
+#include <openssl/objects.h>
+#include "ssl_locl.h"
+
+static const SSL_METHOD *dtls1_get_method(int ver);
+static const SSL_METHOD *dtls1_get_method(int ver)
+	{
+	if (ver == DTLS1_VERSION)
+		return(DTLSv1_method());
+	else
+		return(NULL);
+	}
+
+IMPLEMENT_dtls1_meth_func(DTLSv1_method,
+			dtls1_accept,
+			dtls1_connect,
+			dtls1_get_method)
+
diff --git a/lib/openssl/ssl/d1_pkt.c b/lib/openssl/ssl/d1_pkt.c
new file mode 100644
index 0000000..122eea1
--- /dev/null
+++ b/lib/openssl/ssl/d1_pkt.c
@@ -0,0 +1,1802 @@
+/* ssl/d1_pkt.c */
+/* 
+ * DTLS implementation written by Nagendra Modadugu
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.  
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#define USE_SOCKETS
+#include "ssl_locl.h"
+#include <openssl/evp.h>
+#include <openssl/buffer.h>
+#include <openssl/pqueue.h>
+#include <openssl/rand.h>
+
+/* mod 128 saturating subtract of two 64-bit values in big-endian order */
+static int satsub64be(const unsigned char *v1,const unsigned char *v2)
+{	int ret,sat,brw,i;
+
+	if (sizeof(long) == 8) do
+	{	const union { long one; char little; } is_endian = {1};
+		long l;
+
+		if (is_endian.little)			break;
+		/* not reached on little-endians */
+		/* following test is redundant, because input is
+		 * always aligned, but I take no chances... */
+		if (((size_t)v1|(size_t)v2)&0x7)	break;
+
+		l  = *((long *)v1);
+		l -= *((long *)v2);
+		if (l>128)		return 128;
+		else if (l<-128)	return -128;
+		else			return (int)l;
+	} while (0);
+
+	ret = (int)v1[7]-(int)v2[7];
+	sat = 0;
+	brw = ret>>8;	/* brw is either 0 or -1 */
+	if (ret & 0x80)
+	{	for (i=6;i>=0;i--)
+		{	brw += (int)v1[i]-(int)v2[i];
+			sat |= ~brw;
+			brw >>= 8;
+		}
+	}
+	else
+	{	for (i=6;i>=0;i--)
+		{	brw += (int)v1[i]-(int)v2[i];
+			sat |= brw;
+			brw >>= 8;
+		}
+	}
+	brw <<= 8;	/* brw is either 0 or -256 */
+
+	if (sat&0xff)	return brw | 0x80;
+	else		return brw + (ret&0xFF);
+}
+
+static int have_handshake_fragment(SSL *s, int type, unsigned char *buf, 
+	int len, int peek);
+static int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap);
+static void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap);
+static DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr, 
+    unsigned int *is_next_epoch);
+#if 0
+static int dtls1_record_needs_buffering(SSL *s, SSL3_RECORD *rr,
+	unsigned short *priority, unsigned long *offset);
+#endif
+static int dtls1_buffer_record(SSL *s, record_pqueue *q,
+	unsigned char *priority);
+static int dtls1_process_record(SSL *s);
+static void dtls1_clear_timeouts(SSL *s);
+
+/* copy buffered record into SSL structure */
+static int
+dtls1_copy_record(SSL *s, pitem *item)
+    {
+    DTLS1_RECORD_DATA *rdata;
+
+    rdata = (DTLS1_RECORD_DATA *)item->data;
+    
+    if (s->s3->rbuf.buf != NULL)
+        OPENSSL_free(s->s3->rbuf.buf);
+    
+    s->packet = rdata->packet;
+    s->packet_length = rdata->packet_length;
+    memcpy(&(s->s3->rbuf), &(rdata->rbuf), sizeof(SSL3_BUFFER));
+    memcpy(&(s->s3->rrec), &(rdata->rrec), sizeof(SSL3_RECORD));
+	
+	/* Set proper sequence number for mac calculation */
+	memcpy(&(s->s3->read_sequence[2]), &(rdata->packet[5]), 6);
+    
+    return(1);
+    }
+
+
+static int
+dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority)
+	{
+	DTLS1_RECORD_DATA *rdata;
+	pitem *item;
+
+	/* Limit the size of the queue to prevent DOS attacks */
+	if (pqueue_size(queue->q) >= 100)
+		return 0;
+		
+	rdata = OPENSSL_malloc(sizeof(DTLS1_RECORD_DATA));
+	item = pitem_new(priority, rdata);
+	if (rdata == NULL || item == NULL)
+		{
+		if (rdata != NULL) OPENSSL_free(rdata);
+		if (item != NULL) pitem_free(item);
+		
+		SSLerr(SSL_F_DTLS1_BUFFER_RECORD, ERR_R_INTERNAL_ERROR);
+		return(0);
+		}
+	
+	rdata->packet = s->packet;
+	rdata->packet_length = s->packet_length;
+	memcpy(&(rdata->rbuf), &(s->s3->rbuf), sizeof(SSL3_BUFFER));
+	memcpy(&(rdata->rrec), &(s->s3->rrec), sizeof(SSL3_RECORD));
+
+	item->data = rdata;
+
+	/* insert should not fail, since duplicates are dropped */
+	if (pqueue_insert(queue->q, item) == NULL)
+		{
+		OPENSSL_free(rdata);
+		pitem_free(item);
+		return(0);
+		}
+
+	s->packet = NULL;
+	s->packet_length = 0;
+	memset(&(s->s3->rbuf), 0, sizeof(SSL3_BUFFER));
+	memset(&(s->s3->rrec), 0, sizeof(SSL3_RECORD));
+	
+	if (!ssl3_setup_buffers(s))
+		{
+		SSLerr(SSL_F_DTLS1_BUFFER_RECORD, ERR_R_INTERNAL_ERROR);
+		OPENSSL_free(rdata);
+		pitem_free(item);
+		return(0);
+		}
+	
+	return(1);
+	}
+
+
+static int
+dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue)
+    {
+    pitem *item;
+
+    item = pqueue_pop(queue->q);
+    if (item)
+        {
+        dtls1_copy_record(s, item);
+
+        OPENSSL_free(item->data);
+		pitem_free(item);
+
+        return(1);
+        }
+
+    return(0);
+    }
+
+
+/* retrieve a buffered record that belongs to the new epoch, i.e., not processed 
+ * yet */
+#define dtls1_get_unprocessed_record(s) \
+                   dtls1_retrieve_buffered_record((s), \
+                   &((s)->d1->unprocessed_rcds))
+
+/* retrieve a buffered record that belongs to the current epoch, ie, processed */
+#define dtls1_get_processed_record(s) \
+                   dtls1_retrieve_buffered_record((s), \
+                   &((s)->d1->processed_rcds))
+
+static int
+dtls1_process_buffered_records(SSL *s)
+    {
+    pitem *item;
+    
+    item = pqueue_peek(s->d1->unprocessed_rcds.q);
+    if (item)
+        {
+        DTLS1_RECORD_DATA *rdata;
+        rdata = (DTLS1_RECORD_DATA *)item->data;
+        
+        /* Check if epoch is current. */
+        if (s->d1->unprocessed_rcds.epoch != s->d1->r_epoch)
+            return(1);  /* Nothing to do. */
+        
+        /* Process all the records. */
+        while (pqueue_peek(s->d1->unprocessed_rcds.q))
+            {
+            dtls1_get_unprocessed_record(s);
+            if ( ! dtls1_process_record(s))
+                return(0);
+            dtls1_buffer_record(s, &(s->d1->processed_rcds), 
+                s->s3->rrec.seq_num);
+            }
+        }
+
+    /* sync epoch numbers once all the unprocessed records 
+     * have been processed */
+    s->d1->processed_rcds.epoch = s->d1->r_epoch;
+    s->d1->unprocessed_rcds.epoch = s->d1->r_epoch + 1;
+
+    return(1);
+    }
+
+
+#if 0
+
+static int
+dtls1_get_buffered_record(SSL *s)
+	{
+	pitem *item;
+	PQ_64BIT priority = 
+		(((PQ_64BIT)s->d1->handshake_read_seq) << 32) | 
+		((PQ_64BIT)s->d1->r_msg_hdr.frag_off);
+	
+	if ( ! SSL_in_init(s))  /* if we're not (re)negotiating, 
+							   nothing buffered */
+		return 0;
+
+
+	item = pqueue_peek(s->d1->rcvd_records);
+	if (item && item->priority == priority)
+		{
+		/* Check if we've received the record of interest.  It must be
+		 * a handshake record, since data records as passed up without
+		 * buffering */
+		DTLS1_RECORD_DATA *rdata;
+		item = pqueue_pop(s->d1->rcvd_records);
+		rdata = (DTLS1_RECORD_DATA *)item->data;
+		
+		if (s->s3->rbuf.buf != NULL)
+			OPENSSL_free(s->s3->rbuf.buf);
+		
+		s->packet = rdata->packet;
+		s->packet_length = rdata->packet_length;
+		memcpy(&(s->s3->rbuf), &(rdata->rbuf), sizeof(SSL3_BUFFER));
+		memcpy(&(s->s3->rrec), &(rdata->rrec), sizeof(SSL3_RECORD));
+		
+		OPENSSL_free(item->data);
+		pitem_free(item);
+		
+		/* s->d1->next_expected_seq_num++; */
+		return(1);
+		}
+	
+	return 0;
+	}
+
+#endif
+
+static int
+dtls1_process_record(SSL *s)
+{
+	int i,al;
+	int clear=0;
+	int enc_err;
+	SSL_SESSION *sess;
+	SSL3_RECORD *rr;
+	unsigned int mac_size;
+	unsigned char md[EVP_MAX_MD_SIZE];
+
+
+	rr= &(s->s3->rrec);
+	sess = s->session;
+
+	/* At this point, s->packet_length == SSL3_RT_HEADER_LNGTH + rr->length,
+	 * and we have that many bytes in s->packet
+	 */
+	rr->input= &(s->packet[DTLS1_RT_HEADER_LENGTH]);
+
+	/* ok, we can now read from 's->packet' data into 'rr'
+	 * rr->input points at rr->length bytes, which
+	 * need to be copied into rr->data by either
+	 * the decryption or by the decompression
+	 * When the data is 'copied' into the rr->data buffer,
+	 * rr->input will be pointed at the new buffer */ 
+
+	/* We now have - encrypted [ MAC [ compressed [ plain ] ] ]
+	 * rr->length bytes of encrypted compressed stuff. */
+
+	/* check is not needed I believe */
+	if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH)
+		{
+		al=SSL_AD_RECORD_OVERFLOW;
+		SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
+		goto f_err;
+		}
+
+	/* decrypt in place in 'rr->input' */
+	rr->data=rr->input;
+
+	enc_err = s->method->ssl3_enc->enc(s,0);
+	if (enc_err <= 0)
+		{
+		if (enc_err == 0)
+			/* SSLerr() and ssl3_send_alert() have been called */
+			goto err;
+
+		/* otherwise enc_err == -1 */
+		goto err;
+		}
+
+#ifdef TLS_DEBUG
+printf("dec %d\n",rr->length);
+{ unsigned int z; for (z=0; z<rr->length; z++) printf("%02X%c",rr->data[z],((z+1)%16)?' ':'\n'); }
+printf("\n");
+#endif
+
+	/* r->length is now the compressed data plus mac */
+	if (	(sess == NULL) ||
+		(s->enc_read_ctx == NULL) ||
+		(s->read_hash == NULL))
+		clear=1;
+
+	if (!clear)
+		{
+		/* !clear => s->read_hash != NULL => mac_size != -1 */
+		int t;
+		t=EVP_MD_CTX_size(s->read_hash);
+		OPENSSL_assert(t >= 0);
+		mac_size=t;
+
+		if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+mac_size)
+			{
+#if 0 /* OK only for stream ciphers (then rr->length is visible from ciphertext anyway) */
+			al=SSL_AD_RECORD_OVERFLOW;
+			SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_PRE_MAC_LENGTH_TOO_LONG);
+			goto f_err;
+#else
+			goto err;
+#endif			
+			}
+		/* check the MAC for rr->input (it's in mac_size bytes at the tail) */
+		if (rr->length < mac_size)
+			{
+#if 0 /* OK only for stream ciphers */
+			al=SSL_AD_DECODE_ERROR;
+			SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_LENGTH_TOO_SHORT);
+			goto f_err;
+#else
+			goto err;
+#endif
+			}
+		rr->length-=mac_size;
+		i=s->method->ssl3_enc->mac(s,md,0);
+		if (i < 0 || memcmp(md,&(rr->data[rr->length]),mac_size) != 0)
+			{
+			goto err;
+			}
+		}
+
+	/* r->length is now just compressed */
+	if (s->expand != NULL)
+		{
+		if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH)
+			{
+			al=SSL_AD_RECORD_OVERFLOW;
+			SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_COMPRESSED_LENGTH_TOO_LONG);
+			goto f_err;
+			}
+		if (!ssl3_do_uncompress(s))
+			{
+			al=SSL_AD_DECOMPRESSION_FAILURE;
+			SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_BAD_DECOMPRESSION);
+			goto f_err;
+			}
+		}
+
+	if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH)
+		{
+		al=SSL_AD_RECORD_OVERFLOW;
+		SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_DATA_LENGTH_TOO_LONG);
+		goto f_err;
+		}
+
+	rr->off=0;
+	/* So at this point the following is true
+	 * ssl->s3->rrec.type 	is the type of record
+	 * ssl->s3->rrec.length	== number of bytes in record
+	 * ssl->s3->rrec.off	== offset to first valid byte
+	 * ssl->s3->rrec.data	== where to take bytes from, increment
+	 *			   after use :-).
+	 */
+
+	/* we have pulled in a full packet so zero things */
+	s->packet_length=0;
+	dtls1_record_bitmap_update(s, &(s->d1->bitmap));/* Mark receipt of record. */
+	return(1);
+
+f_err:
+	ssl3_send_alert(s,SSL3_AL_FATAL,al);
+err:
+	return(0);
+}
+
+
+/* Call this to get a new input record.
+ * It will return <= 0 if more data is needed, normally due to an error
+ * or non-blocking IO.
+ * When it finishes, one packet has been decoded and can be found in
+ * ssl->s3->rrec.type    - is the type of record
+ * ssl->s3->rrec.data, 	 - data
+ * ssl->s3->rrec.length, - number of bytes
+ */
+/* used only by dtls1_read_bytes */
+int dtls1_get_record(SSL *s)
+	{
+	int ssl_major,ssl_minor;
+	int i,n;
+	SSL3_RECORD *rr;
+	SSL_SESSION *sess;
+	unsigned char *p = NULL;
+	unsigned short version;
+	DTLS1_BITMAP *bitmap;
+	unsigned int is_next_epoch;
+
+	rr= &(s->s3->rrec);
+	sess=s->session;
+
+	/* The epoch may have changed.  If so, process all the
+	 * pending records.  This is a non-blocking operation. */
+	dtls1_process_buffered_records(s);
+
+	/* if we're renegotiating, then there may be buffered records */
+	if (dtls1_get_processed_record(s))
+		return 1;
+
+	/* get something from the wire */
+again:
+	/* check if we have the header */
+	if (	(s->rstate != SSL_ST_READ_BODY) ||
+		(s->packet_length < DTLS1_RT_HEADER_LENGTH)) 
+		{
+		n=ssl3_read_n(s, DTLS1_RT_HEADER_LENGTH, s->s3->rbuf.len, 0);
+		/* read timeout is handled by dtls1_read_bytes */
+		if (n <= 0) return(n); /* error or non-blocking */
+
+		/* this packet contained a partial record, dump it */
+		if (s->packet_length != DTLS1_RT_HEADER_LENGTH)
+			{
+			s->packet_length = 0;
+			goto again;
+			}
+
+		s->rstate=SSL_ST_READ_BODY;
+
+		p=s->packet;
+
+		/* Pull apart the header into the DTLS1_RECORD */
+		rr->type= *(p++);
+		ssl_major= *(p++);
+		ssl_minor= *(p++);
+		version=(ssl_major<<8)|ssl_minor;
+
+		/* sequence number is 64 bits, with top 2 bytes = epoch */ 
+		n2s(p,rr->epoch);
+
+		memcpy(&(s->s3->read_sequence[2]), p, 6);
+		p+=6;
+
+		n2s(p,rr->length);
+
+		/* Lets check version */
+		if (!s->first_packet)
+			{
+			if (version != s->version)
+				{
+				/* unexpected version, silently discard */
+				rr->length = 0;
+				s->packet_length = 0;
+				goto again;
+				}
+			}
+
+		if ((version & 0xff00) != (s->version & 0xff00))
+			{
+			/* wrong version, silently discard record */
+			rr->length = 0;
+			s->packet_length = 0;
+			goto again;
+			}
+
+		if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH)
+			{
+			/* record too long, silently discard it */
+			rr->length = 0;
+			s->packet_length = 0;
+			goto again;
+			}
+
+		/* If we receive a valid record larger than the current buffer size,
+		 * allocate some memory for it.
+		 */
+		if (rr->length > s->s3->rbuf.len - DTLS1_RT_HEADER_LENGTH)
+			{
+			unsigned char *pp;
+			unsigned int newlen = rr->length + DTLS1_RT_HEADER_LENGTH;
+			if ((pp=OPENSSL_realloc(s->s3->rbuf.buf, newlen))==NULL)
+				{
+				SSLerr(SSL_F_DTLS1_GET_RECORD,ERR_R_MALLOC_FAILURE);
+				return(-1);
+				}
+			p = pp + (p - s->s3->rbuf.buf);
+			s->s3->rbuf.buf=pp;
+			s->s3->rbuf.len=newlen;
+			s->packet= &(s->s3->rbuf.buf[0]);
+			}
+
+		/* now s->rstate == SSL_ST_READ_BODY */
+		}
+
+	/* s->rstate == SSL_ST_READ_BODY, get and decode the data */
+
+	if (rr->length > s->packet_length-DTLS1_RT_HEADER_LENGTH)
+		{
+		/* now s->packet_length == DTLS1_RT_HEADER_LENGTH */
+		i=rr->length;
+		n=ssl3_read_n(s,i,i,1);
+		if (n <= 0) return(n); /* error or non-blocking io */
+
+		/* this packet contained a partial record, dump it */
+		if ( n != i)
+			{
+			rr->length = 0;
+			s->packet_length = 0;
+			goto again;
+			}
+
+		/* now n == rr->length,
+		 * and s->packet_length == DTLS1_RT_HEADER_LENGTH + rr->length */
+		}
+	s->rstate=SSL_ST_READ_HEADER; /* set state for later operations */
+
+	/* match epochs.  NULL means the packet is dropped on the floor */
+	bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
+	if ( bitmap == NULL)
+		{
+		rr->length = 0;
+		s->packet_length = 0;  /* dump this record */
+		goto again;   /* get another record */
+		}
+
+	/* Check whether this is a repeat, or aged record.
+	 * Don't check if we're listening and this message is
+	 * a ClientHello. They can look as if they're replayed,
+	 * since they arrive from different connections and
+	 * would be dropped unnecessarily.
+	 */
+	if (!(s->d1->listen && rr->type == SSL3_RT_HANDSHAKE &&
+		*p == SSL3_MT_CLIENT_HELLO) &&
+		!dtls1_record_replay_check(s, bitmap))
+		{
+		rr->length = 0;
+		s->packet_length=0; /* dump this record */
+		goto again;     /* get another record */
+		}
+
+	/* just read a 0 length packet */
+	if (rr->length == 0) goto again;
+
+	/* If this record is from the next epoch (either HM or ALERT),
+	 * and a handshake is currently in progress, buffer it since it
+	 * cannot be processed at this time. */
+	if (is_next_epoch)
+		{
+		if (SSL_in_init(s) || s->in_handshake)
+			{
+			dtls1_buffer_record(s, &(s->d1->unprocessed_rcds), rr->seq_num);
+			}
+		rr->length = 0;
+		s->packet_length = 0;
+		goto again;
+		}
+
+	if (!dtls1_process_record(s))
+		{
+		rr->length = 0;
+		s->packet_length = 0;  /* dump this record */
+		goto again;   /* get another record */
+		}
+
+	dtls1_clear_timeouts(s);  /* done waiting */
+	return(1);
+
+	}
+
+/* Return up to 'len' payload bytes received in 'type' records.
+ * 'type' is one of the following:
+ *
+ *   -  SSL3_RT_HANDSHAKE (when ssl3_get_message calls us)
+ *   -  SSL3_RT_APPLICATION_DATA (when ssl3_read calls us)
+ *   -  0 (during a shutdown, no data has to be returned)
+ *
+ * If we don't have stored data to work from, read a SSL/TLS record first
+ * (possibly multiple records if we still don't have anything to return).
+ *
+ * This function must handle any surprises the peer may have for us, such as
+ * Alert records (e.g. close_notify), ChangeCipherSpec records (not really
+ * a surprise, but handled as if it were), or renegotiation requests.
+ * Also if record payloads contain fragments too small to process, we store
+ * them until there is enough for the respective protocol (the record protocol
+ * may use arbitrary fragmentation and even interleaving):
+ *     Change cipher spec protocol
+ *             just 1 byte needed, no need for keeping anything stored
+ *     Alert protocol
+ *             2 bytes needed (AlertLevel, AlertDescription)
+ *     Handshake protocol
+ *             4 bytes needed (HandshakeType, uint24 length) -- we just have
+ *             to detect unexpected Client Hello and Hello Request messages
+ *             here, anything else is handled by higher layers
+ *     Application data protocol
+ *             none of our business
+ */
+int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
+	{
+	int al,i,j,ret;
+	unsigned int n;
+	SSL3_RECORD *rr;
+	void (*cb)(const SSL *ssl,int type2,int val)=NULL;
+
+	if (s->s3->rbuf.buf == NULL) /* Not initialized yet */
+		if (!ssl3_setup_buffers(s))
+			return(-1);
+
+    /* XXX: check what the second '&& type' is about */
+	if ((type && (type != SSL3_RT_APPLICATION_DATA) && 
+		(type != SSL3_RT_HANDSHAKE) && type) ||
+	    (peek && (type != SSL3_RT_APPLICATION_DATA)))
+		{
+		SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR);
+		return -1;
+		}
+
+	/* check whether there's a handshake message (client hello?) waiting */
+	if ( (ret = have_handshake_fragment(s, type, buf, len, peek)))
+		return ret;
+
+	/* Now s->d1->handshake_fragment_len == 0 if type == SSL3_RT_HANDSHAKE. */
+
+	if (!s->in_handshake && SSL_in_init(s))
+		{
+		/* type == SSL3_RT_APPLICATION_DATA */
+		i=s->handshake_func(s);
+		if (i < 0) return(i);
+		if (i == 0)
+			{
+			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
+			return(-1);
+			}
+		}
+
+start:
+	s->rwstate=SSL_NOTHING;
+
+	/* s->s3->rrec.type	    - is the type of record
+	 * s->s3->rrec.data,    - data
+	 * s->s3->rrec.off,     - offset into 'data' for next read
+	 * s->s3->rrec.length,  - number of bytes. */
+	rr = &(s->s3->rrec);
+
+	/* We are not handshaking and have no data yet,
+	 * so process data buffered during the last handshake
+	 * in advance, if any.
+	 */
+	if (s->state == SSL_ST_OK && rr->length == 0)
+		{
+		pitem *item;
+		item = pqueue_pop(s->d1->buffered_app_data.q);
+		if (item)
+			{
+			dtls1_copy_record(s, item);
+
+			OPENSSL_free(item->data);
+			pitem_free(item);
+			}
+		}
+
+	/* Check for timeout */
+	if (dtls1_handle_timeout(s) > 0)
+		goto start;
+
+	/* get new packet if necessary */
+	if ((rr->length == 0) || (s->rstate == SSL_ST_READ_BODY))
+		{
+		ret=dtls1_get_record(s);
+		if (ret <= 0) 
+			{
+			ret = dtls1_read_failed(s, ret);
+			/* anything other than a timeout is an error */
+			if (ret <= 0)  
+				return(ret);
+			else
+				goto start;
+			}
+		}
+
+	/* we now have a packet which can be read and processed */
+
+	if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec,
+	                               * reset by ssl3_get_finished */
+		&& (rr->type != SSL3_RT_HANDSHAKE))
+		{
+		/* We now have application data between CCS and Finished.
+		 * Most likely the packets were reordered on their way, so
+		 * buffer the application data for later processing rather
+		 * than dropping the connection.
+		 */
+		dtls1_buffer_record(s, &(s->d1->buffered_app_data), rr->seq_num);
+		rr->length = 0;
+		goto start;
+		}
+
+	/* If the other end has shut down, throw anything we read away
+	 * (even in 'peek' mode) */
+	if (s->shutdown & SSL_RECEIVED_SHUTDOWN)
+		{
+		rr->length=0;
+		s->rwstate=SSL_NOTHING;
+		return(0);
+		}
+
+
+	if (type == rr->type) /* SSL3_RT_APPLICATION_DATA or SSL3_RT_HANDSHAKE */
+		{
+		/* make sure that we are not getting application data when we
+		 * are doing a handshake for the first time */
+		if (SSL_in_init(s) && (type == SSL3_RT_APPLICATION_DATA) &&
+			(s->enc_read_ctx == NULL))
+			{
+			al=SSL_AD_UNEXPECTED_MESSAGE;
+			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_APP_DATA_IN_HANDSHAKE);
+			goto f_err;
+			}
+
+		if (len <= 0) return(len);
+
+		if ((unsigned int)len > rr->length)
+			n = rr->length;
+		else
+			n = (unsigned int)len;
+
+		memcpy(buf,&(rr->data[rr->off]),n);
+		if (!peek)
+			{
+			rr->length-=n;
+			rr->off+=n;
+			if (rr->length == 0)
+				{
+				s->rstate=SSL_ST_READ_HEADER;
+				rr->off=0;
+				}
+			}
+		return(n);
+		}
+
+
+	/* If we get here, then type != rr->type; if we have a handshake
+	 * message, then it was unexpected (Hello Request or Client Hello). */
+
+	/* In case of record types for which we have 'fragment' storage,
+	 * fill that so that we can process the data at a fixed place.
+	 */
+		{
+		unsigned int k, dest_maxlen = 0;
+		unsigned char *dest = NULL;
+		unsigned int *dest_len = NULL;
+
+		if (rr->type == SSL3_RT_HANDSHAKE)
+			{
+			dest_maxlen = sizeof s->d1->handshake_fragment;
+			dest = s->d1->handshake_fragment;
+			dest_len = &s->d1->handshake_fragment_len;
+			}
+		else if (rr->type == SSL3_RT_ALERT)
+			{
+			dest_maxlen = sizeof(s->d1->alert_fragment);
+			dest = s->d1->alert_fragment;
+			dest_len = &s->d1->alert_fragment_len;
+			}
+		/* else it's a CCS message, or application data or wrong */
+		else if (rr->type != SSL3_RT_CHANGE_CIPHER_SPEC)
+			{
+			/* Application data while renegotiating
+			 * is allowed. Try again reading.
+			 */
+			if (rr->type == SSL3_RT_APPLICATION_DATA)
+				{
+				BIO *bio;
+				s->s3->in_read_app_data=2;
+				bio=SSL_get_rbio(s);
+				s->rwstate=SSL_READING;
+				BIO_clear_retry_flags(bio);
+				BIO_set_retry_read(bio);
+				return(-1);
+				}
+
+			/* Not certain if this is the right error handling */
+			al=SSL_AD_UNEXPECTED_MESSAGE;
+			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
+			goto f_err;
+			}
+
+		if (dest_maxlen > 0)
+			{
+            /* XDTLS:  In a pathalogical case, the Client Hello
+             *  may be fragmented--don't always expect dest_maxlen bytes */
+			if ( rr->length < dest_maxlen)
+				{
+#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
+				/*
+				 * for normal alerts rr->length is 2, while
+				 * dest_maxlen is 7 if we were to handle this
+				 * non-existing alert...
+				 */
+				FIX ME
+#endif
+				s->rstate=SSL_ST_READ_HEADER;
+				rr->length = 0;
+				goto start;
+				}
+
+			/* now move 'n' bytes: */
+			for ( k = 0; k < dest_maxlen; k++)
+				{
+				dest[k] = rr->data[rr->off++];
+				rr->length--;
+				}
+			*dest_len = dest_maxlen;
+			}
+		}
+
+	/* s->d1->handshake_fragment_len == 12  iff  rr->type == SSL3_RT_HANDSHAKE;
+	 * s->d1->alert_fragment_len == 7      iff  rr->type == SSL3_RT_ALERT.
+	 * (Possibly rr is 'empty' now, i.e. rr->length may be 0.) */
+
+	/* If we are a client, check for an incoming 'Hello Request': */
+	if ((!s->server) &&
+		(s->d1->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) &&
+		(s->d1->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) &&
+		(s->session != NULL) && (s->session->cipher != NULL))
+		{
+		s->d1->handshake_fragment_len = 0;
+
+		if ((s->d1->handshake_fragment[1] != 0) ||
+			(s->d1->handshake_fragment[2] != 0) ||
+			(s->d1->handshake_fragment[3] != 0))
+			{
+			al=SSL_AD_DECODE_ERROR;
+			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_BAD_HELLO_REQUEST);
+			goto err;
+			}
+
+		/* no need to check sequence number on HELLO REQUEST messages */
+
+		if (s->msg_callback)
+			s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, 
+				s->d1->handshake_fragment, 4, s, s->msg_callback_arg);
+
+		if (SSL_is_init_finished(s) &&
+			!(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) &&
+			!s->s3->renegotiate)
+			{
+			ssl3_renegotiate(s);
+			if (ssl3_renegotiate_check(s))
+				{
+				i=s->handshake_func(s);
+				if (i < 0) return(i);
+				if (i == 0)
+					{
+					SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
+					return(-1);
+					}
+
+				if (!(s->mode & SSL_MODE_AUTO_RETRY))
+					{
+					if (s->s3->rbuf.left == 0) /* no read-ahead left? */
+						{
+						BIO *bio;
+						/* In the case where we try to read application data,
+						 * but we trigger an SSL handshake, we return -1 with
+						 * the retry option set.  Otherwise renegotiation may
+						 * cause nasty problems in the blocking world */
+						s->rwstate=SSL_READING;
+						bio=SSL_get_rbio(s);
+						BIO_clear_retry_flags(bio);
+						BIO_set_retry_read(bio);
+						return(-1);
+						}
+					}
+				}
+			}
+		/* we either finished a handshake or ignored the request,
+		 * now try again to obtain the (application) data we were asked for */
+		goto start;
+		}
+
+	if (s->d1->alert_fragment_len >= DTLS1_AL_HEADER_LENGTH)
+		{
+		int alert_level = s->d1->alert_fragment[0];
+		int alert_descr = s->d1->alert_fragment[1];
+
+		s->d1->alert_fragment_len = 0;
+
+		if (s->msg_callback)
+			s->msg_callback(0, s->version, SSL3_RT_ALERT, 
+				s->d1->alert_fragment, 2, s, s->msg_callback_arg);
+
+		if (s->info_callback != NULL)
+			cb=s->info_callback;
+		else if (s->ctx->info_callback != NULL)
+			cb=s->ctx->info_callback;
+
+		if (cb != NULL)
+			{
+			j = (alert_level << 8) | alert_descr;
+			cb(s, SSL_CB_READ_ALERT, j);
+			}
+
+		if (alert_level == 1) /* warning */
+			{
+			s->s3->warn_alert = alert_descr;
+			if (alert_descr == SSL_AD_CLOSE_NOTIFY)
+				{
+				s->shutdown |= SSL_RECEIVED_SHUTDOWN;
+				return(0);
+				}
+#if 0
+            /* XXX: this is a possible improvement in the future */
+			/* now check if it's a missing record */
+			if (alert_descr == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE)
+				{
+				unsigned short seq;
+				unsigned int frag_off;
+				unsigned char *p = &(s->d1->alert_fragment[2]);
+
+				n2s(p, seq);
+				n2l3(p, frag_off);
+
+				dtls1_retransmit_message(s,
+										 dtls1_get_queue_priority(frag->msg_header.seq, 0),
+										 frag_off, &found);
+				if ( ! found  && SSL_in_init(s))
+					{
+					/* fprintf( stderr,"in init = %d\n", SSL_in_init(s)); */
+					/* requested a message not yet sent, 
+					   send an alert ourselves */
+					ssl3_send_alert(s,SSL3_AL_WARNING,
+						DTLS1_AD_MISSING_HANDSHAKE_MESSAGE);
+					}
+				}
+#endif
+			}
+		else if (alert_level == 2) /* fatal */
+			{
+			char tmp[16];
+
+			s->rwstate=SSL_NOTHING;
+			s->s3->fatal_alert = alert_descr;
+			SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_AD_REASON_OFFSET + alert_descr);
+			BIO_snprintf(tmp,sizeof tmp,"%d",alert_descr);
+			ERR_add_error_data(2,"SSL alert number ",tmp);
+			s->shutdown|=SSL_RECEIVED_SHUTDOWN;
+			SSL_CTX_remove_session(s->ctx,s->session);
+			return(0);
+			}
+		else
+			{
+			al=SSL_AD_ILLEGAL_PARAMETER;
+			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_UNKNOWN_ALERT_TYPE);
+			goto f_err;
+			}
+
+		goto start;
+		}
+
+	if (s->shutdown & SSL_SENT_SHUTDOWN) /* but we have not received a shutdown */
+		{
+		s->rwstate=SSL_NOTHING;
+		rr->length=0;
+		return(0);
+		}
+
+	if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC)
+		{
+		struct ccs_header_st ccs_hdr;
+		unsigned int ccs_hdr_len = DTLS1_CCS_HEADER_LENGTH;
+
+		dtls1_get_ccs_header(rr->data, &ccs_hdr);
+
+		if (s->version == DTLS1_BAD_VER)
+			ccs_hdr_len = 3;
+
+		/* 'Change Cipher Spec' is just a single byte, so we know
+		 * exactly what the record payload has to look like */
+		/* XDTLS: check that epoch is consistent */
+		if (	(rr->length != ccs_hdr_len) || 
+			(rr->off != 0) || (rr->data[0] != SSL3_MT_CCS))
+			{
+			i=SSL_AD_ILLEGAL_PARAMETER;
+			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC);
+			goto err;
+			}
+
+		rr->length=0;
+
+		if (s->msg_callback)
+			s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, 
+				rr->data, 1, s, s->msg_callback_arg);
+
+		/* We can't process a CCS now, because previous handshake
+		 * messages are still missing, so just drop it.
+		 */
+		if (!s->d1->change_cipher_spec_ok)
+			{
+			goto start;
+			}
+
+		s->d1->change_cipher_spec_ok = 0;
+
+		s->s3->change_cipher_spec=1;
+		if (!ssl3_do_change_cipher_spec(s))
+			goto err;
+
+		/* do this whenever CCS is processed */
+		dtls1_reset_seq_numbers(s, SSL3_CC_READ);
+
+		if (s->version == DTLS1_BAD_VER)
+			s->d1->handshake_read_seq++;
+
+		goto start;
+		}
+
+	/* Unexpected handshake message (Client Hello, or protocol violation) */
+	if ((s->d1->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) && 
+		!s->in_handshake)
+		{
+		struct hm_header_st msg_hdr;
+		
+		/* this may just be a stale retransmit */
+		dtls1_get_message_header(rr->data, &msg_hdr);
+		if( rr->epoch != s->d1->r_epoch)
+			{
+			rr->length = 0;
+			goto start;
+			}
+
+		/* If we are server, we may have a repeated FINISHED of the
+		 * client here, then retransmit our CCS and FINISHED.
+		 */
+		if (msg_hdr.type == SSL3_MT_FINISHED)
+			{
+			dtls1_retransmit_buffered_messages(s);
+			rr->length = 0;
+			goto start;
+			}
+
+		if (((s->state&SSL_ST_MASK) == SSL_ST_OK) &&
+			!(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS))
+			{
+#if 0 /* worked only because C operator preferences are not as expected (and
+       * because this is not really needed for clients except for detecting
+       * protocol violations): */
+			s->state=SSL_ST_BEFORE|(s->server)
+				?SSL_ST_ACCEPT
+				:SSL_ST_CONNECT;
+#else
+			s->state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT;
+#endif
+			s->new_session=1;
+			}
+		i=s->handshake_func(s);
+		if (i < 0) return(i);
+		if (i == 0)
+			{
+			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
+			return(-1);
+			}
+
+		if (!(s->mode & SSL_MODE_AUTO_RETRY))
+			{
+			if (s->s3->rbuf.left == 0) /* no read-ahead left? */
+				{
+				BIO *bio;
+				/* In the case where we try to read application data,
+				 * but we trigger an SSL handshake, we return -1 with
+				 * the retry option set.  Otherwise renegotiation may
+				 * cause nasty problems in the blocking world */
+				s->rwstate=SSL_READING;
+				bio=SSL_get_rbio(s);
+				BIO_clear_retry_flags(bio);
+				BIO_set_retry_read(bio);
+				return(-1);
+				}
+			}
+		goto start;
+		}
+
+	switch (rr->type)
+		{
+	default:
+#ifndef OPENSSL_NO_TLS
+		/* TLS just ignores unknown message types */
+		if (s->version == TLS1_VERSION)
+			{
+			rr->length = 0;
+			goto start;
+			}
+#endif
+		al=SSL_AD_UNEXPECTED_MESSAGE;
+		SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
+		goto f_err;
+	case SSL3_RT_CHANGE_CIPHER_SPEC:
+	case SSL3_RT_ALERT:
+	case SSL3_RT_HANDSHAKE:
+		/* we already handled all of these, with the possible exception
+		 * of SSL3_RT_HANDSHAKE when s->in_handshake is set, but that
+		 * should not happen when type != rr->type */
+		al=SSL_AD_UNEXPECTED_MESSAGE;
+		SSLerr(SSL_F_DTLS1_READ_BYTES,ERR_R_INTERNAL_ERROR);
+		goto f_err;
+	case SSL3_RT_APPLICATION_DATA:
+		/* At this point, we were expecting handshake data,
+		 * but have application data.  If the library was
+		 * running inside ssl3_read() (i.e. in_read_app_data
+		 * is set) and it makes sense to read application data
+		 * at this point (session renegotiation not yet started),
+		 * we will indulge it.
+		 */
+		if (s->s3->in_read_app_data &&
+			(s->s3->total_renegotiations != 0) &&
+			((
+				(s->state & SSL_ST_CONNECT) &&
+				(s->state >= SSL3_ST_CW_CLNT_HELLO_A) &&
+				(s->state <= SSL3_ST_CR_SRVR_HELLO_A)
+				) || (
+					(s->state & SSL_ST_ACCEPT) &&
+					(s->state <= SSL3_ST_SW_HELLO_REQ_A) &&
+					(s->state >= SSL3_ST_SR_CLNT_HELLO_A)
+					)
+				))
+			{
+			s->s3->in_read_app_data=2;
+			return(-1);
+			}
+		else
+			{
+			al=SSL_AD_UNEXPECTED_MESSAGE;
+			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
+			goto f_err;
+			}
+		}
+	/* not reached */
+
+f_err:
+	ssl3_send_alert(s,SSL3_AL_FATAL,al);
+err:
+	return(-1);
+	}
+
+int
+dtls1_write_app_data_bytes(SSL *s, int type, const void *buf_, int len)
+	{
+	int i;
+
+	if (SSL_in_init(s) && !s->in_handshake)
+		{
+		i=s->handshake_func(s);
+		if (i < 0) return(i);
+		if (i == 0)
+			{
+			SSLerr(SSL_F_DTLS1_WRITE_APP_DATA_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
+			return -1;
+			}
+		}
+
+	if (len > SSL3_RT_MAX_PLAIN_LENGTH)
+		{
+			SSLerr(SSL_F_DTLS1_WRITE_APP_DATA_BYTES,SSL_R_DTLS_MESSAGE_TOO_BIG);
+			return -1;
+		}
+
+	i = dtls1_write_bytes(s, type, buf_, len);
+	return i;
+	}
+
+
+	/* this only happens when a client hello is received and a handshake 
+	 * is started. */
+static int
+have_handshake_fragment(SSL *s, int type, unsigned char *buf, 
+	int len, int peek)
+	{
+	
+	if ((type == SSL3_RT_HANDSHAKE) && (s->d1->handshake_fragment_len > 0))
+		/* (partially) satisfy request from storage */
+		{
+		unsigned char *src = s->d1->handshake_fragment;
+		unsigned char *dst = buf;
+		unsigned int k,n;
+		
+		/* peek == 0 */
+		n = 0;
+		while ((len > 0) && (s->d1->handshake_fragment_len > 0))
+			{
+			*dst++ = *src++;
+			len--; s->d1->handshake_fragment_len--;
+			n++;
+			}
+		/* move any remaining fragment bytes: */
+		for (k = 0; k < s->d1->handshake_fragment_len; k++)
+			s->d1->handshake_fragment[k] = *src++;
+		return n;
+		}
+	
+	return 0;
+	}
+
+
+
+
+/* Call this to write data in records of type 'type'
+ * It will return <= 0 if not all data has been sent or non-blocking IO.
+ */
+int dtls1_write_bytes(SSL *s, int type, const void *buf, int len)
+	{
+	int i;
+
+	OPENSSL_assert(len <= SSL3_RT_MAX_PLAIN_LENGTH);
+	s->rwstate=SSL_NOTHING;
+	i=do_dtls1_write(s, type, buf, len, 0);
+	return i;
+	}
+
+int do_dtls1_write(SSL *s, int type, const unsigned char *buf, unsigned int len, int create_empty_fragment)
+	{
+	unsigned char *p,*pseq;
+	int i,mac_size,clear=0;
+	int prefix_len = 0;
+	SSL3_RECORD *wr;
+	SSL3_BUFFER *wb;
+	SSL_SESSION *sess;
+	int bs;
+	unsigned int len_with_overhead = len + SSL3_RT_DEFAULT_WRITE_OVERHEAD;
+
+	/* first check if there is a SSL3_BUFFER still being written
+	 * out.  This will happen with non blocking IO */
+	if (s->s3->wbuf.left != 0)
+		{
+		OPENSSL_assert(0); /* XDTLS:  want to see if we ever get here */
+		return(ssl3_write_pending(s,type,buf,len));
+		}
+
+	if (s->s3->wbuf.len < len_with_overhead)
+		{
+		if ((p=OPENSSL_realloc(s->s3->wbuf.buf, len_with_overhead)) == NULL) {
+			SSLerr(SSL_F_DO_DTLS1_WRITE,ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		s->s3->wbuf.buf = p;
+		s->s3->wbuf.len = len_with_overhead;
+		}
+
+	/* If we have an alert to send, lets send it */
+	if (s->s3->alert_dispatch)
+		{
+		i=s->method->ssl_dispatch_alert(s);
+		if (i <= 0)
+			return(i);
+		/* if it went, fall through and send more stuff */
+		}
+
+	if (len == 0 && !create_empty_fragment)
+		return 0;
+
+	wr= &(s->s3->wrec);
+	wb= &(s->s3->wbuf);
+	sess=s->session;
+
+	if (	(sess == NULL) ||
+		(s->enc_write_ctx == NULL) ||
+		(EVP_MD_CTX_md(s->write_hash) == NULL))
+		clear=1;
+
+	if (clear)
+		mac_size=0;
+	else
+		{
+		mac_size=EVP_MD_CTX_size(s->write_hash);
+		if (mac_size < 0)
+			goto err;
+		}
+
+	/* DTLS implements explicit IV, so no need for empty fragments */
+#if 0
+	/* 'create_empty_fragment' is true only when this function calls itself */
+	if (!clear && !create_empty_fragment && !s->s3->empty_fragment_done
+	    && SSL_version(s) != DTLS1_VERSION && SSL_version(s) != DTLS1_BAD_VER)
+		{
+		/* countermeasure against known-IV weakness in CBC ciphersuites
+		 * (see http://www.openssl.org/~bodo/tls-cbc.txt) 
+		 */
+
+		if (s->s3->need_empty_fragments && type == SSL3_RT_APPLICATION_DATA)
+			{
+			/* recursive function call with 'create_empty_fragment' set;
+			 * this prepares and buffers the data for an empty fragment
+			 * (these 'prefix_len' bytes are sent out later
+			 * together with the actual payload) */
+			prefix_len = s->method->do_ssl_write(s, type, buf, 0, 1);
+			if (prefix_len <= 0)
+				goto err;
+
+			if (s->s3->wbuf.len < (size_t)prefix_len + SSL3_RT_MAX_PACKET_SIZE)
+				{
+				/* insufficient space */
+				SSLerr(SSL_F_DO_DTLS1_WRITE, ERR_R_INTERNAL_ERROR);
+				goto err;
+				}
+			}
+		
+		s->s3->empty_fragment_done = 1;
+		}
+#endif
+	p = wb->buf + prefix_len;
+
+	/* write the header */
+
+	*(p++)=type&0xff;
+	wr->type=type;
+
+	*(p++)=(s->version>>8);
+	*(p++)=s->version&0xff;
+
+	/* field where we are to write out packet epoch, seq num and len */
+	pseq=p; 
+	p+=10;
+
+	/* lets setup the record stuff. */
+
+	/* Make space for the explicit IV in case of CBC.
+	 * (this is a bit of a boundary violation, but what the heck).
+	 */
+	if ( s->enc_write_ctx && 
+		(EVP_CIPHER_mode( s->enc_write_ctx->cipher ) & EVP_CIPH_CBC_MODE))
+		bs = EVP_CIPHER_block_size(s->enc_write_ctx->cipher);
+	else
+		bs = 0;
+
+	wr->data=p + bs;  /* make room for IV in case of CBC */
+	wr->length=(int)len;
+	wr->input=(unsigned char *)buf;
+
+	/* we now 'read' from wr->input, wr->length bytes into
+	 * wr->data */
+
+	/* first we compress */
+	if (s->compress != NULL)
+		{
+		if (!ssl3_do_compress(s))
+			{
+			SSLerr(SSL_F_DO_DTLS1_WRITE,SSL_R_COMPRESSION_FAILURE);
+			goto err;
+			}
+		}
+	else
+		{
+		memcpy(wr->data,wr->input,wr->length);
+		wr->input=wr->data;
+		}
+
+	/* we should still have the output to wr->data and the input
+	 * from wr->input.  Length should be wr->length.
+	 * wr->data still points in the wb->buf */
+
+	if (mac_size != 0)
+		{
+		if(s->method->ssl3_enc->mac(s,&(p[wr->length + bs]),1) < 0)
+			goto err;
+		wr->length+=mac_size;
+		}
+
+	/* this is true regardless of mac size */
+	wr->input=p;
+	wr->data=p;
+
+
+	/* ssl3_enc can only have an error on read */
+	if (bs)	/* bs != 0 in case of CBC */
+		{
+		RAND_pseudo_bytes(p,bs);
+		/* master IV and last CBC residue stand for
+		 * the rest of randomness */
+		wr->length += bs;
+		}
+
+	s->method->ssl3_enc->enc(s,1);
+
+	/* record length after mac and block padding */
+/*	if (type == SSL3_RT_APPLICATION_DATA ||
+	(type == SSL3_RT_ALERT && ! SSL_in_init(s))) */
+	
+	/* there's only one epoch between handshake and app data */
+	
+	s2n(s->d1->w_epoch, pseq);
+
+	/* XDTLS: ?? */
+/*	else
+	s2n(s->d1->handshake_epoch, pseq); */
+
+	memcpy(pseq, &(s->s3->write_sequence[2]), 6);
+	pseq+=6;
+	s2n(wr->length,pseq);
+
+	/* we should now have
+	 * wr->data pointing to the encrypted data, which is
+	 * wr->length long */
+	wr->type=type; /* not needed but helps for debugging */
+	wr->length+=DTLS1_RT_HEADER_LENGTH;
+
+#if 0  /* this is now done at the message layer */
+	/* buffer the record, making it easy to handle retransmits */
+	if ( type == SSL3_RT_HANDSHAKE || type == SSL3_RT_CHANGE_CIPHER_SPEC)
+		dtls1_buffer_record(s, wr->data, wr->length, 
+			*((PQ_64BIT *)&(s->s3->write_sequence[0])));
+#endif
+
+	ssl3_record_sequence_update(&(s->s3->write_sequence[0]));
+
+	if (create_empty_fragment)
+		{
+		/* we are in a recursive call;
+		 * just return the length, don't write out anything here
+		 */
+		return wr->length;
+		}
+
+	/* now let's set up wb */
+	wb->left = prefix_len + wr->length;
+	wb->offset = 0;
+
+	/* memorize arguments so that ssl3_write_pending can detect bad write retries later */
+	s->s3->wpend_tot=len;
+	s->s3->wpend_buf=buf;
+	s->s3->wpend_type=type;
+	s->s3->wpend_ret=len;
+
+	/* we now just need to write the buffer */
+	return ssl3_write_pending(s,type,buf,len);
+err:
+	return -1;
+	}
+
+
+
+static int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap)
+	{
+	int cmp;
+	unsigned int shift;
+	const unsigned char *seq = s->s3->read_sequence;
+
+	cmp = satsub64be(seq,bitmap->max_seq_num);
+	if (cmp > 0)
+		{
+		memcpy (s->s3->rrec.seq_num,seq,8);
+		return 1; /* this record in new */
+		}
+	shift = -cmp;
+	if (shift >= sizeof(bitmap->map)*8)
+		return 0; /* stale, outside the window */
+	else if (bitmap->map & (1UL<<shift))
+		return 0; /* record previously received */
+
+	memcpy (s->s3->rrec.seq_num,seq,8);
+	return 1;
+	}
+
+
+static void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap)
+	{
+	int cmp;
+	unsigned int shift;
+	const unsigned char *seq = s->s3->read_sequence;
+
+	cmp = satsub64be(seq,bitmap->max_seq_num);
+	if (cmp > 0)
+		{
+		shift = cmp;
+		if (shift < sizeof(bitmap->map)*8)
+			bitmap->map <<= shift, bitmap->map |= 1UL;
+		else
+			bitmap->map = 1UL;
+		memcpy(bitmap->max_seq_num,seq,8);
+		}
+	else	{
+		shift = -cmp;
+		if (shift < sizeof(bitmap->map)*8)
+			bitmap->map |= 1UL<<shift;
+		}
+	}
+
+
+int dtls1_dispatch_alert(SSL *s)
+	{
+	int i,j;
+	void (*cb)(const SSL *ssl,int type,int val)=NULL;
+	unsigned char buf[DTLS1_AL_HEADER_LENGTH];
+	unsigned char *ptr = &buf[0];
+
+	s->s3->alert_dispatch=0;
+
+	memset(buf, 0x00, sizeof(buf));
+	*ptr++ = s->s3->send_alert[0];
+	*ptr++ = s->s3->send_alert[1];
+
+#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
+	if (s->s3->send_alert[1] == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE)
+		{	
+		s2n(s->d1->handshake_read_seq, ptr);
+#if 0
+		if ( s->d1->r_msg_hdr.frag_off == 0)  /* waiting for a new msg */
+
+		else
+			s2n(s->d1->r_msg_hdr.seq, ptr); /* partial msg read */
+#endif
+
+#if 0
+		fprintf(stderr, "s->d1->handshake_read_seq = %d, s->d1->r_msg_hdr.seq = %d\n",s->d1->handshake_read_seq,s->d1->r_msg_hdr.seq);
+#endif
+		l2n3(s->d1->r_msg_hdr.frag_off, ptr);
+		}
+#endif
+
+	i = do_dtls1_write(s, SSL3_RT_ALERT, &buf[0], sizeof(buf), 0);
+	if (i <= 0)
+		{
+		s->s3->alert_dispatch=1;
+		/* fprintf( stderr, "not done with alert\n" ); */
+		}
+	else
+		{
+		if (s->s3->send_alert[0] == SSL3_AL_FATAL
+#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
+		    || s->s3->send_alert[1] == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
+#endif
+		    )
+			(void)BIO_flush(s->wbio);
+
+		if (s->msg_callback)
+			s->msg_callback(1, s->version, SSL3_RT_ALERT, s->s3->send_alert, 
+				2, s, s->msg_callback_arg);
+
+		if (s->info_callback != NULL)
+			cb=s->info_callback;
+		else if (s->ctx->info_callback != NULL)
+			cb=s->ctx->info_callback;
+
+		if (cb != NULL)
+			{
+			j=(s->s3->send_alert[0]<<8)|s->s3->send_alert[1];
+			cb(s,SSL_CB_WRITE_ALERT,j);
+			}
+		}
+	return(i);
+	}
+
+
+static DTLS1_BITMAP *
+dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr, unsigned int *is_next_epoch)
+    {
+    
+    *is_next_epoch = 0;
+
+    /* In current epoch, accept HM, CCS, DATA, & ALERT */
+    if (rr->epoch == s->d1->r_epoch)
+        return &s->d1->bitmap;
+
+    /* Only HM and ALERT messages can be from the next epoch */
+    else if (rr->epoch == (unsigned long)(s->d1->r_epoch + 1) &&
+        (rr->type == SSL3_RT_HANDSHAKE ||
+            rr->type == SSL3_RT_ALERT))
+        {
+        *is_next_epoch = 1;
+        return &s->d1->next_bitmap;
+        }
+
+    return NULL;
+    }
+
+#if 0
+static int
+dtls1_record_needs_buffering(SSL *s, SSL3_RECORD *rr, unsigned short *priority,
+	unsigned long *offset)
+	{
+
+	/* alerts are passed up immediately */
+	if ( rr->type == SSL3_RT_APPLICATION_DATA ||
+		rr->type == SSL3_RT_ALERT)
+		return 0;
+
+	/* Only need to buffer if a handshake is underway.
+	 * (this implies that Hello Request and Client Hello are passed up
+	 * immediately) */
+	if ( SSL_in_init(s))
+		{
+		unsigned char *data = rr->data;
+		/* need to extract the HM/CCS sequence number here */
+		if ( rr->type == SSL3_RT_HANDSHAKE ||
+			rr->type == SSL3_RT_CHANGE_CIPHER_SPEC)
+			{
+			unsigned short seq_num;
+			struct hm_header_st msg_hdr;
+			struct ccs_header_st ccs_hdr;
+
+			if ( rr->type == SSL3_RT_HANDSHAKE)
+				{
+				dtls1_get_message_header(data, &msg_hdr);
+				seq_num = msg_hdr.seq;
+				*offset = msg_hdr.frag_off;
+				}
+			else
+				{
+				dtls1_get_ccs_header(data, &ccs_hdr);
+				seq_num = ccs_hdr.seq;
+				*offset = 0;
+				}
+				
+			/* this is either a record we're waiting for, or a
+			 * retransmit of something we happened to previously 
+			 * receive (higher layers will drop the repeat silently */
+			if ( seq_num < s->d1->handshake_read_seq)
+				return 0;
+			if (rr->type == SSL3_RT_HANDSHAKE && 
+				seq_num == s->d1->handshake_read_seq &&
+				msg_hdr.frag_off < s->d1->r_msg_hdr.frag_off)
+				return 0;
+			else if ( seq_num == s->d1->handshake_read_seq &&
+				(rr->type == SSL3_RT_CHANGE_CIPHER_SPEC ||
+					msg_hdr.frag_off == s->d1->r_msg_hdr.frag_off))
+				return 0;
+			else
+				{
+				*priority = seq_num;
+				return 1;
+				}
+			}
+		else /* unknown record type */
+			return 0;
+		}
+
+	return 0;
+	}
+#endif
+
+void
+dtls1_reset_seq_numbers(SSL *s, int rw)
+	{
+	unsigned char *seq;
+	unsigned int seq_bytes = sizeof(s->s3->read_sequence);
+
+	if ( rw & SSL3_CC_READ)
+		{
+		seq = s->s3->read_sequence;
+		s->d1->r_epoch++;
+		memcpy(&(s->d1->bitmap), &(s->d1->next_bitmap), sizeof(DTLS1_BITMAP));
+		memset(&(s->d1->next_bitmap), 0x00, sizeof(DTLS1_BITMAP));
+		}
+	else
+		{
+		seq = s->s3->write_sequence;
+		memcpy(s->d1->last_write_sequence, seq, sizeof(s->s3->write_sequence));
+		s->d1->w_epoch++;
+		}
+
+	memset(seq, 0x00, seq_bytes);
+	}
+
+
+static void
+dtls1_clear_timeouts(SSL *s)
+	{
+	memset(&(s->d1->timeout), 0x00, sizeof(struct dtls1_timeout_st));
+	}
diff --git a/lib/openssl/ssl/d1_srvr.c b/lib/openssl/ssl/d1_srvr.c
new file mode 100644
index 0000000..301ceda
--- /dev/null
+++ b/lib/openssl/ssl/d1_srvr.c
@@ -0,0 +1,1551 @@
+/* ssl/d1_srvr.c */
+/* 
+ * DTLS implementation written by Nagendra Modadugu
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.  
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include "ssl_locl.h"
+#include <openssl/buffer.h>
+#include <openssl/rand.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+#include <openssl/md5.h>
+#include <openssl/bn.h>
+#ifndef OPENSSL_NO_DH
+#include <openssl/dh.h>
+#endif
+
+static const SSL_METHOD *dtls1_get_server_method(int ver);
+static int dtls1_send_hello_verify_request(SSL *s);
+
+static const SSL_METHOD *dtls1_get_server_method(int ver)
+	{
+	if (ver == DTLS1_VERSION)
+		return(DTLSv1_server_method());
+	else
+		return(NULL);
+	}
+
+IMPLEMENT_dtls1_meth_func(DTLSv1_server_method,
+			dtls1_accept,
+			ssl_undefined_function,
+			dtls1_get_server_method)
+
+int dtls1_accept(SSL *s)
+	{
+	BUF_MEM *buf;
+	unsigned long Time=(unsigned long)time(NULL);
+	void (*cb)(const SSL *ssl,int type,int val)=NULL;
+	unsigned long alg_k;
+	int ret= -1;
+	int new_state,state,skip=0;
+
+	RAND_add(&Time,sizeof(Time),0);
+	ERR_clear_error();
+	clear_sys_error();
+
+	if (s->info_callback != NULL)
+		cb=s->info_callback;
+	else if (s->ctx->info_callback != NULL)
+		cb=s->ctx->info_callback;
+
+	/* init things to blank */
+	s->in_handshake++;
+	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);
+
+	if (s->cert == NULL)
+		{
+		SSLerr(SSL_F_DTLS1_ACCEPT,SSL_R_NO_CERTIFICATE_SET);
+		return(-1);
+		}
+
+	for (;;)
+		{
+		state=s->state;
+
+		switch (s->state)
+			{
+		case SSL_ST_RENEGOTIATE:
+			s->new_session=1;
+			/* s->state=SSL_ST_ACCEPT; */
+
+		case SSL_ST_BEFORE:
+		case SSL_ST_ACCEPT:
+		case SSL_ST_BEFORE|SSL_ST_ACCEPT:
+		case SSL_ST_OK|SSL_ST_ACCEPT:
+
+			s->server=1;
+			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
+
+			if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00))
+				{
+				SSLerr(SSL_F_DTLS1_ACCEPT, ERR_R_INTERNAL_ERROR);
+				return -1;
+				}
+			s->type=SSL_ST_ACCEPT;
+
+			if (s->init_buf == NULL)
+				{
+				if ((buf=BUF_MEM_new()) == NULL)
+					{
+					ret= -1;
+					goto end;
+					}
+				if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH))
+					{
+					ret= -1;
+					goto end;
+					}
+				s->init_buf=buf;
+				}
+
+			if (!ssl3_setup_buffers(s))
+				{
+				ret= -1;
+				goto end;
+				}
+
+			s->init_num=0;
+
+			if (s->state != SSL_ST_RENEGOTIATE)
+				{
+				/* Ok, we now need to push on a buffering BIO so that
+				 * the output is sent in a way that TCP likes :-)
+				 */
+				if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; }
+
+				ssl3_init_finished_mac(s);
+				s->state=SSL3_ST_SR_CLNT_HELLO_A;
+				s->ctx->stats.sess_accept++;
+				}
+			else
+				{
+				/* s->state == SSL_ST_RENEGOTIATE,
+				 * we will just send a HelloRequest */
+				s->ctx->stats.sess_accept_renegotiate++;
+				s->state=SSL3_ST_SW_HELLO_REQ_A;
+				}
+
+			break;
+
+		case SSL3_ST_SW_HELLO_REQ_A:
+		case SSL3_ST_SW_HELLO_REQ_B:
+
+			s->shutdown=0;
+			dtls1_start_timer(s);
+			ret=dtls1_send_hello_request(s);
+			if (ret <= 0) goto end;
+			s->s3->tmp.next_state=SSL3_ST_SW_HELLO_REQ_C;
+			s->state=SSL3_ST_SW_FLUSH;
+			s->init_num=0;
+
+			ssl3_init_finished_mac(s);
+			break;
+
+		case SSL3_ST_SW_HELLO_REQ_C:
+			s->state=SSL_ST_OK;
+			break;
+
+		case SSL3_ST_SR_CLNT_HELLO_A:
+		case SSL3_ST_SR_CLNT_HELLO_B:
+		case SSL3_ST_SR_CLNT_HELLO_C:
+
+			s->shutdown=0;
+			ret=ssl3_get_client_hello(s);
+			if (ret <= 0) goto end;
+			dtls1_stop_timer(s);
+
+			if (ret == 1 && (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE))
+				s->state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A;
+			else
+				s->state = SSL3_ST_SW_SRVR_HELLO_A;
+
+			s->init_num=0;
+
+			/* If we're just listening, stop here */
+			if (s->d1->listen && s->state == SSL3_ST_SW_SRVR_HELLO_A)
+				{
+				ret = 2;
+				s->d1->listen = 0;
+				goto end;
+				}
+			
+			break;
+			
+		case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A:
+		case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B:
+
+			dtls1_start_timer(s);
+			ret = dtls1_send_hello_verify_request(s);
+			if ( ret <= 0) goto end;
+			s->state=SSL3_ST_SW_FLUSH;
+			s->s3->tmp.next_state=SSL3_ST_SR_CLNT_HELLO_A;
+
+			/* HelloVerifyRequest resets Finished MAC */
+			if (s->version != DTLS1_BAD_VER)
+				ssl3_init_finished_mac(s);
+			break;
+			
+		case SSL3_ST_SW_SRVR_HELLO_A:
+		case SSL3_ST_SW_SRVR_HELLO_B:
+			s->new_session = 2;
+			dtls1_start_timer(s);
+			ret=dtls1_send_server_hello(s);
+			if (ret <= 0) goto end;
+
+#ifndef OPENSSL_NO_TLSEXT
+			if (s->hit)
+				{
+				if (s->tlsext_ticket_expected)
+					s->state=SSL3_ST_SW_SESSION_TICKET_A;
+				else
+					s->state=SSL3_ST_SW_CHANGE_A;
+				}
+#else
+			if (s->hit)
+					s->state=SSL3_ST_SW_CHANGE_A;
+#endif
+			else
+				s->state=SSL3_ST_SW_CERT_A;
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_SW_CERT_A:
+		case SSL3_ST_SW_CERT_B:
+			/* Check if it is anon DH or normal PSK */
+			if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)
+				&& !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
+				{
+				dtls1_start_timer(s);
+				ret=dtls1_send_server_certificate(s);
+				if (ret <= 0) goto end;
+#ifndef OPENSSL_NO_TLSEXT
+				if (s->tlsext_status_expected)
+					s->state=SSL3_ST_SW_CERT_STATUS_A;
+				else
+					s->state=SSL3_ST_SW_KEY_EXCH_A;
+				}
+			else
+				{
+				skip = 1;
+				s->state=SSL3_ST_SW_KEY_EXCH_A;
+				}
+#else
+				}
+			else
+				skip=1;
+
+			s->state=SSL3_ST_SW_KEY_EXCH_A;
+#endif
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_SW_KEY_EXCH_A:
+		case SSL3_ST_SW_KEY_EXCH_B:
+			alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+
+			/* clear this, it may get reset by
+			 * send_server_key_exchange */
+			if ((s->options & SSL_OP_EPHEMERAL_RSA)
+#ifndef OPENSSL_NO_KRB5
+				&& !(alg_k & SSL_kKRB5)
+#endif /* OPENSSL_NO_KRB5 */
+				)
+				/* option SSL_OP_EPHEMERAL_RSA sends temporary RSA key
+				 * even when forbidden by protocol specs
+				 * (handshake may fail as clients are not required to
+				 * be able to handle this) */
+				s->s3->tmp.use_rsa_tmp=1;
+			else
+				s->s3->tmp.use_rsa_tmp=0;
+
+			/* only send if a DH key exchange or
+			 * RSA but we have a sign only certificate */
+			if (s->s3->tmp.use_rsa_tmp
+			/* PSK: send ServerKeyExchange if PSK identity
+			 * hint if provided */
+#ifndef OPENSSL_NO_PSK
+			    || ((alg_k & SSL_kPSK) && s->ctx->psk_identity_hint)
+#endif
+			    || (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
+			    || (alg_k & SSL_kEECDH)
+			    || ((alg_k & SSL_kRSA)
+				&& (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL
+				    || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher)
+					&& EVP_PKEY_size(s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)
+					)
+				    )
+				)
+			    )
+				{
+				dtls1_start_timer(s);
+				ret=dtls1_send_server_key_exchange(s);
+				if (ret <= 0) goto end;
+				}
+			else
+				skip=1;
+
+			s->state=SSL3_ST_SW_CERT_REQ_A;
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_SW_CERT_REQ_A:
+		case SSL3_ST_SW_CERT_REQ_B:
+			if (/* don't request cert unless asked for it: */
+				!(s->verify_mode & SSL_VERIFY_PEER) ||
+				/* if SSL_VERIFY_CLIENT_ONCE is set,
+				 * don't request cert during re-negotiation: */
+				((s->session->peer != NULL) &&
+				 (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) ||
+				/* never request cert in anonymous ciphersuites
+				 * (see section "Certificate request" in SSL 3 drafts
+				 * and in RFC 2246): */
+				((s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) &&
+				 /* ... except when the application insists on verification
+				  * (against the specs, but s3_clnt.c accepts this for SSL 3) */
+				 !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) ||
+				 /* never request cert in Kerberos ciphersuites */
+				(s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5)
+				/* With normal PSK Certificates and
+				 * Certificate Requests are omitted */
+				|| (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
+				{
+				/* no cert request */
+				skip=1;
+				s->s3->tmp.cert_request=0;
+				s->state=SSL3_ST_SW_SRVR_DONE_A;
+				}
+			else
+				{
+				s->s3->tmp.cert_request=1;
+				dtls1_start_timer(s);
+				ret=dtls1_send_certificate_request(s);
+				if (ret <= 0) goto end;
+#ifndef NETSCAPE_HANG_BUG
+				s->state=SSL3_ST_SW_SRVR_DONE_A;
+#else
+				s->state=SSL3_ST_SW_FLUSH;
+				s->s3->tmp.next_state=SSL3_ST_SR_CERT_A;
+#endif
+				s->init_num=0;
+				}
+			break;
+
+		case SSL3_ST_SW_SRVR_DONE_A:
+		case SSL3_ST_SW_SRVR_DONE_B:
+			dtls1_start_timer(s);
+			ret=dtls1_send_server_done(s);
+			if (ret <= 0) goto end;
+			s->s3->tmp.next_state=SSL3_ST_SR_CERT_A;
+			s->state=SSL3_ST_SW_FLUSH;
+			s->init_num=0;
+			break;
+		
+		case SSL3_ST_SW_FLUSH:
+			s->rwstate=SSL_WRITING;
+			if (BIO_flush(s->wbio) <= 0)
+				{
+				ret= -1;
+				goto end;
+				}
+			s->rwstate=SSL_NOTHING;
+			s->state=s->s3->tmp.next_state;
+			break;
+
+		case SSL3_ST_SR_CERT_A:
+		case SSL3_ST_SR_CERT_B:
+			/* Check for second client hello (MS SGC) */
+			ret = ssl3_check_client_hello(s);
+			if (ret <= 0)
+				goto end;
+			dtls1_stop_timer(s);
+			if (ret == 2)
+				s->state = SSL3_ST_SR_CLNT_HELLO_C;
+			else {
+				/* could be sent for a DH cert, even if we
+				 * have not asked for it :-) */
+				ret=ssl3_get_client_certificate(s);
+				if (ret <= 0) goto end;
+				dtls1_stop_timer(s);
+				s->init_num=0;
+				s->state=SSL3_ST_SR_KEY_EXCH_A;
+			}
+			break;
+
+		case SSL3_ST_SR_KEY_EXCH_A:
+		case SSL3_ST_SR_KEY_EXCH_B:
+			ret=ssl3_get_client_key_exchange(s);
+			if (ret <= 0) goto end;
+			dtls1_stop_timer(s);
+			s->state=SSL3_ST_SR_CERT_VRFY_A;
+			s->init_num=0;
+
+			if (ret == 2)
+				{
+				/* For the ECDH ciphersuites when
+				 * the client sends its ECDH pub key in
+				 * a certificate, the CertificateVerify
+				 * message is not sent.
+				 */
+				s->state=SSL3_ST_SR_FINISHED_A;
+				s->init_num = 0;
+				}
+			else
+				{
+				s->state=SSL3_ST_SR_CERT_VRFY_A;
+				s->init_num=0;
+
+				/* We need to get hashes here so if there is
+				 * a client cert, it can be verified */ 
+				s->method->ssl3_enc->cert_verify_mac(s,
+					NID_md5,
+					&(s->s3->tmp.cert_verify_md[0]));
+				s->method->ssl3_enc->cert_verify_mac(s,
+					NID_sha1,
+					&(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]));
+				}
+			break;
+
+		case SSL3_ST_SR_CERT_VRFY_A:
+		case SSL3_ST_SR_CERT_VRFY_B:
+
+			s->d1->change_cipher_spec_ok = 1;
+			/* we should decide if we expected this one */
+			ret=ssl3_get_cert_verify(s);
+			if (ret <= 0) goto end;
+			dtls1_stop_timer(s);
+
+			s->state=SSL3_ST_SR_FINISHED_A;
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_SR_FINISHED_A:
+		case SSL3_ST_SR_FINISHED_B:
+			s->d1->change_cipher_spec_ok = 1;
+			ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A,
+				SSL3_ST_SR_FINISHED_B);
+			if (ret <= 0) goto end;
+			dtls1_stop_timer(s);
+			if (s->hit)
+				s->state=SSL_ST_OK;
+#ifndef OPENSSL_NO_TLSEXT
+			else if (s->tlsext_ticket_expected)
+				s->state=SSL3_ST_SW_SESSION_TICKET_A;
+#endif
+			else
+				s->state=SSL3_ST_SW_CHANGE_A;
+			s->init_num=0;
+			break;
+
+#ifndef OPENSSL_NO_TLSEXT
+		case SSL3_ST_SW_SESSION_TICKET_A:
+		case SSL3_ST_SW_SESSION_TICKET_B:
+			ret=dtls1_send_newsession_ticket(s);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_SW_CHANGE_A;
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_SW_CERT_STATUS_A:
+		case SSL3_ST_SW_CERT_STATUS_B:
+			ret=ssl3_send_cert_status(s);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_SW_KEY_EXCH_A;
+			s->init_num=0;
+			break;
+
+#endif
+
+		case SSL3_ST_SW_CHANGE_A:
+		case SSL3_ST_SW_CHANGE_B:
+
+			s->session->cipher=s->s3->tmp.new_cipher;
+			if (!s->method->ssl3_enc->setup_key_block(s))
+				{ ret= -1; goto end; }
+
+			ret=dtls1_send_change_cipher_spec(s,
+				SSL3_ST_SW_CHANGE_A,SSL3_ST_SW_CHANGE_B);
+
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_SW_FINISHED_A;
+			s->init_num=0;
+
+			if (!s->method->ssl3_enc->change_cipher_state(s,
+				SSL3_CHANGE_CIPHER_SERVER_WRITE))
+				{
+				ret= -1;
+				goto end;
+				}
+
+			dtls1_reset_seq_numbers(s, SSL3_CC_WRITE);
+			break;
+
+		case SSL3_ST_SW_FINISHED_A:
+		case SSL3_ST_SW_FINISHED_B:
+			ret=dtls1_send_finished(s,
+				SSL3_ST_SW_FINISHED_A,SSL3_ST_SW_FINISHED_B,
+				s->method->ssl3_enc->server_finished_label,
+				s->method->ssl3_enc->server_finished_label_len);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_SW_FLUSH;
+			if (s->hit)
+				s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A;
+			else
+				s->s3->tmp.next_state=SSL_ST_OK;
+			s->init_num=0;
+			break;
+
+		case SSL_ST_OK:
+			/* clean a few things up */
+			ssl3_cleanup_key_block(s);
+
+#if 0
+			BUF_MEM_free(s->init_buf);
+			s->init_buf=NULL;
+#endif
+
+			/* remove buffering on output */
+			ssl_free_wbio_buffer(s);
+
+			s->init_num=0;
+
+			if (s->new_session == 2) /* skipped if we just sent a HelloRequest */
+				{
+				/* actually not necessarily a 'new' session unless
+				 * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */
+				
+				s->new_session=0;
+				
+				ssl_update_cache(s,SSL_SESS_CACHE_SERVER);
+				
+				s->ctx->stats.sess_accept_good++;
+				/* s->server=1; */
+				s->handshake_func=dtls1_accept;
+
+				if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1);
+				}
+			
+			ret = 1;
+
+			/* done handshaking, next message is client hello */
+			s->d1->handshake_read_seq = 0;
+			/* next message is server hello */
+			s->d1->handshake_write_seq = 0;
+			s->d1->next_handshake_write_seq = 0;
+			goto end;
+			/* break; */
+
+		default:
+			SSLerr(SSL_F_DTLS1_ACCEPT,SSL_R_UNKNOWN_STATE);
+			ret= -1;
+			goto end;
+			/* break; */
+			}
+		
+		if (!s->s3->tmp.reuse_message && !skip)
+			{
+			if (s->debug)
+				{
+				if ((ret=BIO_flush(s->wbio)) <= 0)
+					goto end;
+				}
+
+
+			if ((cb != NULL) && (s->state != state))
+				{
+				new_state=s->state;
+				s->state=state;
+				cb(s,SSL_CB_ACCEPT_LOOP,1);
+				s->state=new_state;
+				}
+			}
+		skip=0;
+		}
+end:
+	/* BIO_flush(s->wbio); */
+
+	s->in_handshake--;
+	if (cb != NULL)
+		cb(s,SSL_CB_ACCEPT_EXIT,ret);
+	return(ret);
+	}
+
+int dtls1_send_hello_request(SSL *s)
+	{
+	unsigned char *p;
+
+	if (s->state == SSL3_ST_SW_HELLO_REQ_A)
+		{
+		p=(unsigned char *)s->init_buf->data;
+		p = dtls1_set_message_header(s, p, SSL3_MT_HELLO_REQUEST, 0, 0, 0);
+
+		s->state=SSL3_ST_SW_HELLO_REQ_B;
+		/* number of bytes to write */
+		s->init_num=DTLS1_HM_HEADER_LENGTH;
+		s->init_off=0;
+
+		/* no need to buffer this message, since there are no retransmit 
+		 * requests for it */
+		}
+
+	/* SSL3_ST_SW_HELLO_REQ_B */
+	return(dtls1_do_write(s,SSL3_RT_HANDSHAKE));
+	}
+
+int dtls1_send_hello_verify_request(SSL *s)
+	{
+	unsigned int msg_len;
+	unsigned char *msg, *buf, *p;
+
+	if (s->state == DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A)
+		{
+		buf = (unsigned char *)s->init_buf->data;
+
+		msg = p = &(buf[DTLS1_HM_HEADER_LENGTH]);
+		*(p++) = s->version >> 8;
+		*(p++) = s->version & 0xFF;
+
+		if (s->ctx->app_gen_cookie_cb == NULL ||
+		     s->ctx->app_gen_cookie_cb(s, s->d1->cookie,
+			 &(s->d1->cookie_len)) == 0)
+			{
+			SSLerr(SSL_F_DTLS1_SEND_HELLO_VERIFY_REQUEST,ERR_R_INTERNAL_ERROR);
+			return 0;
+			}
+
+		*(p++) = (unsigned char) s->d1->cookie_len;
+		memcpy(p, s->d1->cookie, s->d1->cookie_len);
+		p += s->d1->cookie_len;
+		msg_len = p - msg;
+
+		dtls1_set_message_header(s, buf,
+			DTLS1_MT_HELLO_VERIFY_REQUEST, msg_len, 0, msg_len);
+
+		s->state=DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B;
+		/* number of bytes to write */
+		s->init_num=p-buf;
+		s->init_off=0;
+
+		/* buffer the message to handle re-xmits */
+		dtls1_buffer_message(s, 0);
+		}
+
+	/* s->state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B */
+	return(dtls1_do_write(s,SSL3_RT_HANDSHAKE));
+	}
+
+int dtls1_send_server_hello(SSL *s)
+	{
+	unsigned char *buf;
+	unsigned char *p,*d;
+	int i;
+	unsigned int sl;
+	unsigned long l,Time;
+
+	if (s->state == SSL3_ST_SW_SRVR_HELLO_A)
+		{
+		buf=(unsigned char *)s->init_buf->data;
+		p=s->s3->server_random;
+		Time=(unsigned long)time(NULL);			/* Time */
+		l2n(Time,p);
+		RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-sizeof(Time));
+		/* Do the message type and length last */
+		d=p= &(buf[DTLS1_HM_HEADER_LENGTH]);
+
+		*(p++)=s->version>>8;
+		*(p++)=s->version&0xff;
+
+		/* Random stuff */
+		memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE);
+		p+=SSL3_RANDOM_SIZE;
+
+		/* now in theory we have 3 options to sending back the
+		 * session id.  If it is a re-use, we send back the
+		 * old session-id, if it is a new session, we send
+		 * back the new session-id or we send back a 0 length
+		 * session-id if we want it to be single use.
+		 * Currently I will not implement the '0' length session-id
+		 * 12-Jan-98 - I'll now support the '0' length stuff.
+		 */
+		if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER))
+			s->session->session_id_length=0;
+
+		sl=s->session->session_id_length;
+		if (sl > sizeof s->session->session_id)
+			{
+			SSLerr(SSL_F_DTLS1_SEND_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
+			return -1;
+			}
+		*(p++)=sl;
+		memcpy(p,s->session->session_id,sl);
+		p+=sl;
+
+		/* put the cipher */
+		if (s->s3->tmp.new_cipher == NULL)
+			return -1;
+		i=ssl3_put_cipher_by_char(s->s3->tmp.new_cipher,p);
+		p+=i;
+
+		/* put the compression method */
+#ifdef OPENSSL_NO_COMP
+		*(p++)=0;
+#else
+		if (s->s3->tmp.new_compression == NULL)
+			*(p++)=0;
+		else
+			*(p++)=s->s3->tmp.new_compression->id;
+#endif
+
+#ifndef OPENSSL_NO_TLSEXT
+		if ((p = ssl_add_serverhello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
+			{
+			SSLerr(SSL_F_DTLS1_SEND_SERVER_HELLO,ERR_R_INTERNAL_ERROR);
+			return -1;
+			}
+#endif
+
+		/* do the header */
+		l=(p-d);
+		d=buf;
+
+		d = dtls1_set_message_header(s, d, SSL3_MT_SERVER_HELLO, l, 0, l);
+
+		s->state=SSL3_ST_SW_SRVR_HELLO_B;
+		/* number of bytes to write */
+		s->init_num=p-buf;
+		s->init_off=0;
+
+		/* buffer the message to handle re-xmits */
+		dtls1_buffer_message(s, 0);
+		}
+
+	/* SSL3_ST_SW_SRVR_HELLO_B */
+	return(dtls1_do_write(s,SSL3_RT_HANDSHAKE));
+	}
+
+int dtls1_send_server_done(SSL *s)
+	{
+	unsigned char *p;
+
+	if (s->state == SSL3_ST_SW_SRVR_DONE_A)
+		{
+		p=(unsigned char *)s->init_buf->data;
+
+		/* do the header */
+		p = dtls1_set_message_header(s, p, SSL3_MT_SERVER_DONE, 0, 0, 0);
+
+		s->state=SSL3_ST_SW_SRVR_DONE_B;
+		/* number of bytes to write */
+		s->init_num=DTLS1_HM_HEADER_LENGTH;
+		s->init_off=0;
+
+		/* buffer the message to handle re-xmits */
+		dtls1_buffer_message(s, 0);
+		}
+
+	/* SSL3_ST_SW_SRVR_DONE_B */
+	return(dtls1_do_write(s,SSL3_RT_HANDSHAKE));
+	}
+
+int dtls1_send_server_key_exchange(SSL *s)
+	{
+#ifndef OPENSSL_NO_RSA
+	unsigned char *q;
+	int j,num;
+	RSA *rsa;
+	unsigned char md_buf[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH];
+	unsigned int u;
+#endif
+#ifndef OPENSSL_NO_DH
+	DH *dh=NULL,*dhp;
+#endif
+#ifndef OPENSSL_NO_ECDH
+	EC_KEY *ecdh=NULL, *ecdhp;
+	unsigned char *encodedPoint = NULL;
+	int encodedlen = 0;
+	int curve_id = 0;
+	BN_CTX *bn_ctx = NULL; 
+#endif
+	EVP_PKEY *pkey;
+	unsigned char *p,*d;
+	int al,i;
+	unsigned long type;
+	int n;
+	CERT *cert;
+	BIGNUM *r[4];
+	int nr[4],kn;
+	BUF_MEM *buf;
+	EVP_MD_CTX md_ctx;
+
+	EVP_MD_CTX_init(&md_ctx);
+	if (s->state == SSL3_ST_SW_KEY_EXCH_A)
+		{
+		type=s->s3->tmp.new_cipher->algorithm_mkey;
+		cert=s->cert;
+
+		buf=s->init_buf;
+
+		r[0]=r[1]=r[2]=r[3]=NULL;
+		n=0;
+#ifndef OPENSSL_NO_RSA
+		if (type & SSL_kRSA)
+			{
+			rsa=cert->rsa_tmp;
+			if ((rsa == NULL) && (s->cert->rsa_tmp_cb != NULL))
+				{
+				rsa=s->cert->rsa_tmp_cb(s,
+				      SSL_C_IS_EXPORT(s->s3->tmp.new_cipher),
+				      SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher));
+				if(rsa == NULL)
+				{
+					al=SSL_AD_HANDSHAKE_FAILURE;
+					SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,SSL_R_ERROR_GENERATING_TMP_RSA_KEY);
+					goto f_err;
+				}
+				RSA_up_ref(rsa);
+				cert->rsa_tmp=rsa;
+				}
+			if (rsa == NULL)
+				{
+				al=SSL_AD_HANDSHAKE_FAILURE;
+				SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_RSA_KEY);
+				goto f_err;
+				}
+			r[0]=rsa->n;
+			r[1]=rsa->e;
+			s->s3->tmp.use_rsa_tmp=1;
+			}
+		else
+#endif
+#ifndef OPENSSL_NO_DH
+			if (type & SSL_kEDH)
+			{
+			dhp=cert->dh_tmp;
+			if ((dhp == NULL) && (s->cert->dh_tmp_cb != NULL))
+				dhp=s->cert->dh_tmp_cb(s,
+				      SSL_C_IS_EXPORT(s->s3->tmp.new_cipher),
+				      SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher));
+			if (dhp == NULL)
+				{
+				al=SSL_AD_HANDSHAKE_FAILURE;
+				SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_DH_KEY);
+				goto f_err;
+				}
+
+			if (s->s3->tmp.dh != NULL)
+				{
+				DH_free(dh);
+				SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+				goto err;
+				}
+
+			if ((dh=DHparams_dup(dhp)) == NULL)
+				{
+				SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_DH_LIB);
+				goto err;
+				}
+
+			s->s3->tmp.dh=dh;
+			if ((dhp->pub_key == NULL ||
+			     dhp->priv_key == NULL ||
+			     (s->options & SSL_OP_SINGLE_DH_USE)))
+				{
+				if(!DH_generate_key(dh))
+				    {
+				    SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,
+					   ERR_R_DH_LIB);
+				    goto err;
+				    }
+				}
+			else
+				{
+				dh->pub_key=BN_dup(dhp->pub_key);
+				dh->priv_key=BN_dup(dhp->priv_key);
+				if ((dh->pub_key == NULL) ||
+					(dh->priv_key == NULL))
+					{
+					SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_DH_LIB);
+					goto err;
+					}
+				}
+			r[0]=dh->p;
+			r[1]=dh->g;
+			r[2]=dh->pub_key;
+			}
+		else 
+#endif
+#ifndef OPENSSL_NO_ECDH
+			if (type & SSL_kEECDH)
+			{
+			const EC_GROUP *group;
+
+			ecdhp=cert->ecdh_tmp;
+			if ((ecdhp == NULL) && (s->cert->ecdh_tmp_cb != NULL))
+				{
+				ecdhp=s->cert->ecdh_tmp_cb(s,
+				      SSL_C_IS_EXPORT(s->s3->tmp.new_cipher),
+				      SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher));
+				}
+			if (ecdhp == NULL)
+				{
+				al=SSL_AD_HANDSHAKE_FAILURE;
+				SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_ECDH_KEY);
+				goto f_err;
+				}
+
+			if (s->s3->tmp.ecdh != NULL)
+				{
+				EC_KEY_free(s->s3->tmp.ecdh); 
+				SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+				goto err;
+				}
+
+			/* Duplicate the ECDH structure. */
+			if (ecdhp == NULL)
+				{
+				SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
+				goto err;
+				}
+			if (!EC_KEY_up_ref(ecdhp))
+				{
+				SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
+				goto err;
+				}
+			ecdh = ecdhp;
+
+			s->s3->tmp.ecdh=ecdh;
+			if ((EC_KEY_get0_public_key(ecdh) == NULL) ||
+			    (EC_KEY_get0_private_key(ecdh) == NULL) ||
+			    (s->options & SSL_OP_SINGLE_ECDH_USE))
+				{
+				if(!EC_KEY_generate_key(ecdh))
+				    {
+				    SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
+				    goto err;
+				    }
+				}
+
+			if (((group = EC_KEY_get0_group(ecdh)) == NULL) ||
+			    (EC_KEY_get0_public_key(ecdh)  == NULL) ||
+			    (EC_KEY_get0_private_key(ecdh) == NULL))
+				{
+				SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
+				goto err;
+				}
+
+			if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) &&
+			    (EC_GROUP_get_degree(group) > 163)) 
+				{
+				SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER);
+				goto err;
+				}
+
+			/* XXX: For now, we only support ephemeral ECDH
+			 * keys over named (not generic) curves. For 
+			 * supported named curves, curve_id is non-zero.
+			 */
+			if ((curve_id = 
+			    tls1_ec_nid2curve_id(EC_GROUP_get_curve_name(group)))
+			    == 0)
+				{
+				SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNSUPPORTED_ELLIPTIC_CURVE);
+				goto err;
+				}
+
+			/* Encode the public key.
+			 * First check the size of encoding and
+			 * allocate memory accordingly.
+			 */
+			encodedlen = EC_POINT_point2oct(group, 
+			    EC_KEY_get0_public_key(ecdh),
+			    POINT_CONVERSION_UNCOMPRESSED, 
+			    NULL, 0, NULL);
+
+			encodedPoint = (unsigned char *) 
+			    OPENSSL_malloc(encodedlen*sizeof(unsigned char)); 
+			bn_ctx = BN_CTX_new();
+			if ((encodedPoint == NULL) || (bn_ctx == NULL))
+				{
+				SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
+				goto err;
+				}
+
+
+			encodedlen = EC_POINT_point2oct(group, 
+			    EC_KEY_get0_public_key(ecdh), 
+			    POINT_CONVERSION_UNCOMPRESSED, 
+			    encodedPoint, encodedlen, bn_ctx);
+
+			if (encodedlen == 0) 
+				{
+				SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
+				goto err;
+				}
+
+			BN_CTX_free(bn_ctx);  bn_ctx=NULL;
+
+			/* XXX: For now, we only support named (not 
+			 * generic) curves in ECDH ephemeral key exchanges.
+			 * In this situation, we need four additional bytes
+			 * to encode the entire ServerECDHParams
+			 * structure. 
+			 */
+			n = 4 + encodedlen;
+
+			/* We'll generate the serverKeyExchange message
+			 * explicitly so we can set these to NULLs
+			 */
+			r[0]=NULL;
+			r[1]=NULL;
+			r[2]=NULL;
+			r[3]=NULL;
+			}
+		else 
+#endif /* !OPENSSL_NO_ECDH */
+#ifndef OPENSSL_NO_PSK
+			if (type & SSL_kPSK)
+				{
+				/* reserve size for record length and PSK identity hint*/
+				n+=2+strlen(s->ctx->psk_identity_hint);
+				}
+			else
+#endif /* !OPENSSL_NO_PSK */
+			{
+			al=SSL_AD_HANDSHAKE_FAILURE;
+			SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
+			goto f_err;
+			}
+		for (i=0; r[i] != NULL; i++)
+			{
+			nr[i]=BN_num_bytes(r[i]);
+			n+=2+nr[i];
+			}
+
+		if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)
+			&& !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
+			{
+			if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher))
+				== NULL)
+				{
+				al=SSL_AD_DECODE_ERROR;
+				goto f_err;
+				}
+			kn=EVP_PKEY_size(pkey);
+			}
+		else
+			{
+			pkey=NULL;
+			kn=0;
+			}
+
+		if (!BUF_MEM_grow_clean(buf,n+DTLS1_HM_HEADER_LENGTH+kn))
+			{
+			SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_BUF);
+			goto err;
+			}
+		d=(unsigned char *)s->init_buf->data;
+		p= &(d[DTLS1_HM_HEADER_LENGTH]);
+
+		for (i=0; r[i] != NULL; i++)
+			{
+			s2n(nr[i],p);
+			BN_bn2bin(r[i],p);
+			p+=nr[i];
+			}
+
+#ifndef OPENSSL_NO_ECDH
+		if (type & SSL_kEECDH) 
+			{
+			/* XXX: For now, we only support named (not generic) curves.
+			 * In this situation, the serverKeyExchange message has:
+			 * [1 byte CurveType], [2 byte CurveName]
+			 * [1 byte length of encoded point], followed by
+			 * the actual encoded point itself
+			 */
+			*p = NAMED_CURVE_TYPE;
+			p += 1;
+			*p = 0;
+			p += 1;
+			*p = curve_id;
+			p += 1;
+			*p = encodedlen;
+			p += 1;
+			memcpy((unsigned char*)p, 
+			    (unsigned char *)encodedPoint, 
+			    encodedlen);
+			OPENSSL_free(encodedPoint);
+			p += encodedlen;
+			}
+#endif
+
+#ifndef OPENSSL_NO_PSK
+		if (type & SSL_kPSK)
+			{
+			/* copy PSK identity hint */
+			s2n(strlen(s->ctx->psk_identity_hint), p); 
+			strncpy((char *)p, s->ctx->psk_identity_hint, strlen(s->ctx->psk_identity_hint));
+			p+=strlen(s->ctx->psk_identity_hint);
+			}
+#endif
+
+		/* not anonymous */
+		if (pkey != NULL)
+			{
+			/* n is the length of the params, they start at
+			 * &(d[DTLS1_HM_HEADER_LENGTH]) and p points to the space
+			 * at the end. */
+#ifndef OPENSSL_NO_RSA
+			if (pkey->type == EVP_PKEY_RSA)
+				{
+				q=md_buf;
+				j=0;
+				for (num=2; num > 0; num--)
+					{
+					EVP_DigestInit_ex(&md_ctx,(num == 2)
+						?s->ctx->md5:s->ctx->sha1, NULL);
+					EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
+					EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
+					EVP_DigestUpdate(&md_ctx,&(d[DTLS1_HM_HEADER_LENGTH]),n);
+					EVP_DigestFinal_ex(&md_ctx,q,
+						(unsigned int *)&i);
+					q+=i;
+					j+=i;
+					}
+				if (RSA_sign(NID_md5_sha1, md_buf, j,
+					&(p[2]), &u, pkey->pkey.rsa) <= 0)
+					{
+					SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_RSA);
+					goto err;
+					}
+				s2n(u,p);
+				n+=u+2;
+				}
+			else
+#endif
+#if !defined(OPENSSL_NO_DSA)
+				if (pkey->type == EVP_PKEY_DSA)
+				{
+				/* lets do DSS */
+				EVP_SignInit_ex(&md_ctx,EVP_dss1(), NULL);
+				EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
+				EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
+				EVP_SignUpdate(&md_ctx,&(d[DTLS1_HM_HEADER_LENGTH]),n);
+				if (!EVP_SignFinal(&md_ctx,&(p[2]),
+					(unsigned int *)&i,pkey))
+					{
+					SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_DSA);
+					goto err;
+					}
+				s2n(i,p);
+				n+=i+2;
+				}
+			else
+#endif
+#if !defined(OPENSSL_NO_ECDSA)
+				if (pkey->type == EVP_PKEY_EC)
+				{
+				/* let's do ECDSA */
+				EVP_SignInit_ex(&md_ctx,EVP_ecdsa(), NULL);
+				EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
+				EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
+				EVP_SignUpdate(&md_ctx,&(d[4]),n);
+				if (!EVP_SignFinal(&md_ctx,&(p[2]),
+					(unsigned int *)&i,pkey))
+					{
+					SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_ECDSA);
+					goto err;
+					}
+				s2n(i,p);
+				n+=i+2;
+				}
+			else
+#endif
+				{
+				/* Is this error check actually needed? */
+				al=SSL_AD_HANDSHAKE_FAILURE;
+				SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_PKEY_TYPE);
+				goto f_err;
+				}
+			}
+
+		d = dtls1_set_message_header(s, d,
+			SSL3_MT_SERVER_KEY_EXCHANGE, n, 0, n);
+
+		/* we should now have things packed up, so lets send
+		 * it off */
+		s->init_num=n+DTLS1_HM_HEADER_LENGTH;
+		s->init_off=0;
+
+		/* buffer the message to handle re-xmits */
+		dtls1_buffer_message(s, 0);
+		}
+
+	s->state = SSL3_ST_SW_KEY_EXCH_B;
+	EVP_MD_CTX_cleanup(&md_ctx);
+	return(dtls1_do_write(s,SSL3_RT_HANDSHAKE));
+f_err:
+	ssl3_send_alert(s,SSL3_AL_FATAL,al);
+err:
+#ifndef OPENSSL_NO_ECDH
+	if (encodedPoint != NULL) OPENSSL_free(encodedPoint);
+	BN_CTX_free(bn_ctx);
+#endif
+	EVP_MD_CTX_cleanup(&md_ctx);
+	return(-1);
+	}
+
+int dtls1_send_certificate_request(SSL *s)
+	{
+	unsigned char *p,*d;
+	int i,j,nl,off,n;
+	STACK_OF(X509_NAME) *sk=NULL;
+	X509_NAME *name;
+	BUF_MEM *buf;
+	unsigned int msg_len;
+
+	if (s->state == SSL3_ST_SW_CERT_REQ_A)
+		{
+		buf=s->init_buf;
+
+		d=p=(unsigned char *)&(buf->data[DTLS1_HM_HEADER_LENGTH]);
+
+		/* get the list of acceptable cert types */
+		p++;
+		n=ssl3_get_req_cert_type(s,p);
+		d[0]=n;
+		p+=n;
+		n++;
+
+		off=n;
+		p+=2;
+		n+=2;
+
+		sk=SSL_get_client_CA_list(s);
+		nl=0;
+		if (sk != NULL)
+			{
+			for (i=0; i<sk_X509_NAME_num(sk); i++)
+				{
+				name=sk_X509_NAME_value(sk,i);
+				j=i2d_X509_NAME(name,NULL);
+				if (!BUF_MEM_grow_clean(buf,DTLS1_HM_HEADER_LENGTH+n+j+2))
+					{
+					SSLerr(SSL_F_DTLS1_SEND_CERTIFICATE_REQUEST,ERR_R_BUF_LIB);
+					goto err;
+					}
+				p=(unsigned char *)&(buf->data[DTLS1_HM_HEADER_LENGTH+n]);
+				if (!(s->options & SSL_OP_NETSCAPE_CA_DN_BUG))
+					{
+					s2n(j,p);
+					i2d_X509_NAME(name,&p);
+					n+=2+j;
+					nl+=2+j;
+					}
+				else
+					{
+					d=p;
+					i2d_X509_NAME(name,&p);
+					j-=2; s2n(j,d); j+=2;
+					n+=j;
+					nl+=j;
+					}
+				}
+			}
+		/* else no CA names */
+		p=(unsigned char *)&(buf->data[DTLS1_HM_HEADER_LENGTH+off]);
+		s2n(nl,p);
+
+		d=(unsigned char *)buf->data;
+		*(d++)=SSL3_MT_CERTIFICATE_REQUEST;
+		l2n3(n,d);
+		s2n(s->d1->handshake_write_seq,d);
+		s->d1->handshake_write_seq++;
+
+		/* we should now have things packed up, so lets send
+		 * it off */
+
+		s->init_num=n+DTLS1_HM_HEADER_LENGTH;
+		s->init_off=0;
+#ifdef NETSCAPE_HANG_BUG
+/* XXX: what to do about this? */
+		p=(unsigned char *)s->init_buf->data + s->init_num;
+
+		/* do the header */
+		*(p++)=SSL3_MT_SERVER_DONE;
+		*(p++)=0;
+		*(p++)=0;
+		*(p++)=0;
+		s->init_num += 4;
+#endif
+
+		/* XDTLS:  set message header ? */
+		msg_len = s->init_num - DTLS1_HM_HEADER_LENGTH;
+		dtls1_set_message_header(s, (void *)s->init_buf->data,
+			SSL3_MT_CERTIFICATE_REQUEST, msg_len, 0, msg_len);
+
+		/* buffer the message to handle re-xmits */
+		dtls1_buffer_message(s, 0);
+
+		s->state = SSL3_ST_SW_CERT_REQ_B;
+		}
+
+	/* SSL3_ST_SW_CERT_REQ_B */
+	return(dtls1_do_write(s,SSL3_RT_HANDSHAKE));
+err:
+	return(-1);
+	}
+
+int dtls1_send_server_certificate(SSL *s)
+	{
+	unsigned long l;
+	X509 *x;
+
+	if (s->state == SSL3_ST_SW_CERT_A)
+		{
+		x=ssl_get_server_send_cert(s);
+		if (x == NULL)
+			{
+			/* VRS: allow null cert if auth == KRB5 */
+			if ((s->s3->tmp.new_cipher->algorithm_mkey != SSL_kKRB5) ||
+			    (s->s3->tmp.new_cipher->algorithm_auth != SSL_aKRB5))
+				{
+				SSLerr(SSL_F_DTLS1_SEND_SERVER_CERTIFICATE,ERR_R_INTERNAL_ERROR);
+				return(0);
+				}
+			}
+
+		l=dtls1_output_cert_chain(s,x);
+		s->state=SSL3_ST_SW_CERT_B;
+		s->init_num=(int)l;
+		s->init_off=0;
+
+		/* buffer the message to handle re-xmits */
+		dtls1_buffer_message(s, 0);
+		}
+
+	/* SSL3_ST_SW_CERT_B */
+	return(dtls1_do_write(s,SSL3_RT_HANDSHAKE));
+	}
+
+#ifndef OPENSSL_NO_TLSEXT
+int dtls1_send_newsession_ticket(SSL *s)
+	{
+	if (s->state == SSL3_ST_SW_SESSION_TICKET_A)
+		{
+		unsigned char *p, *senc, *macstart;
+		int len, slen;
+		unsigned int hlen, msg_len;
+		EVP_CIPHER_CTX ctx;
+		HMAC_CTX hctx;
+		SSL_CTX *tctx = s->initial_ctx;
+		unsigned char iv[EVP_MAX_IV_LENGTH];
+		unsigned char key_name[16];
+
+		/* get session encoding length */
+		slen = i2d_SSL_SESSION(s->session, NULL);
+		/* Some length values are 16 bits, so forget it if session is
+ 		 * too long
+ 		 */
+		if (slen > 0xFF00)
+			return -1;
+		/* Grow buffer if need be: the length calculation is as
+ 		 * follows 12 (DTLS handshake message header) +
+ 		 * 4 (ticket lifetime hint) + 2 (ticket length) +
+ 		 * 16 (key name) + max_iv_len (iv length) +
+ 		 * session_length + max_enc_block_size (max encrypted session
+ 		 * length) + max_md_size (HMAC).
+ 		 */
+		if (!BUF_MEM_grow(s->init_buf,
+			DTLS1_HM_HEADER_LENGTH + 22 + EVP_MAX_IV_LENGTH +
+			EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE + slen))
+			return -1;
+		senc = OPENSSL_malloc(slen);
+		if (!senc)
+			return -1;
+		p = senc;
+		i2d_SSL_SESSION(s->session, &p);
+
+		p=(unsigned char *)&(s->init_buf->data[DTLS1_HM_HEADER_LENGTH]);
+		EVP_CIPHER_CTX_init(&ctx);
+		HMAC_CTX_init(&hctx);
+		/* Initialize HMAC and cipher contexts. If callback present
+		 * it does all the work otherwise use generated values
+		 * from parent ctx.
+		 */
+		if (tctx->tlsext_ticket_key_cb)
+			{
+			if (tctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx,
+							 &hctx, 1) < 0)
+				{
+				OPENSSL_free(senc);
+				return -1;
+				}
+			}
+		else
+			{
+			RAND_pseudo_bytes(iv, 16);
+			EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
+					tctx->tlsext_tick_aes_key, iv);
+			HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16,
+					tlsext_tick_md(), NULL);
+			memcpy(key_name, tctx->tlsext_tick_key_name, 16);
+			}
+		l2n(s->session->tlsext_tick_lifetime_hint, p);
+		/* Skip ticket length for now */
+		p += 2;
+		/* Output key name */
+		macstart = p;
+		memcpy(p, key_name, 16);
+		p += 16;
+		/* output IV */
+		memcpy(p, iv, EVP_CIPHER_CTX_iv_length(&ctx));
+		p += EVP_CIPHER_CTX_iv_length(&ctx);
+		/* Encrypt session data */
+		EVP_EncryptUpdate(&ctx, p, &len, senc, slen);
+		p += len;
+		EVP_EncryptFinal(&ctx, p, &len);
+		p += len;
+		EVP_CIPHER_CTX_cleanup(&ctx);
+
+		HMAC_Update(&hctx, macstart, p - macstart);
+		HMAC_Final(&hctx, p, &hlen);
+		HMAC_CTX_cleanup(&hctx);
+
+		p += hlen;
+		/* Now write out lengths: p points to end of data written */
+		/* Total length */
+		len = p - (unsigned char *)(s->init_buf->data);
+		/* Ticket length */
+		p=(unsigned char *)&(s->init_buf->data[DTLS1_HM_HEADER_LENGTH]) + 4;
+		s2n(len - DTLS1_HM_HEADER_LENGTH - 6, p);
+
+		/* number of bytes to write */
+		s->init_num= len;
+		s->state=SSL3_ST_SW_SESSION_TICKET_B;
+		s->init_off=0;
+		OPENSSL_free(senc);
+
+		/* XDTLS:  set message header ? */
+		msg_len = s->init_num - DTLS1_HM_HEADER_LENGTH;
+		dtls1_set_message_header(s, (void *)s->init_buf->data,
+			SSL3_MT_NEWSESSION_TICKET, msg_len, 0, msg_len);
+
+		/* buffer the message to handle re-xmits */
+		dtls1_buffer_message(s, 0);
+		}
+
+	/* SSL3_ST_SW_SESSION_TICKET_B */
+	return(dtls1_do_write(s,SSL3_RT_HANDSHAKE));
+	}
+#endif
diff --git a/lib/openssl/ssl/dtls1.h b/lib/openssl/ssl/dtls1.h
new file mode 100644
index 0000000..2900d1d
--- /dev/null
+++ b/lib/openssl/ssl/dtls1.h
@@ -0,0 +1,267 @@
+/* ssl/dtls1.h */
+/* 
+ * DTLS implementation written by Nagendra Modadugu
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.  
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_DTLS1_H 
+#define HEADER_DTLS1_H 
+
+#include <openssl/buffer.h>
+#include <openssl/pqueue.h>
+#ifdef OPENSSL_SYS_VMS
+#include <resource.h>
+#include <sys/timeb.h>
+#endif
+#ifdef OPENSSL_SYS_WIN32
+/* Needed for struct timeval */
+#include <winsock.h>
+#elif defined(OPENSSL_SYS_NETWARE) && !defined(_WINSOCK2API_)
+#include <sys/timeval.h>
+#else
+#include <sys/time.h>
+#endif
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#define DTLS1_VERSION			0xFEFF
+#define DTLS1_BAD_VER			0x0100
+
+#if 0
+/* this alert description is not specified anywhere... */
+#define DTLS1_AD_MISSING_HANDSHAKE_MESSAGE    110
+#endif
+
+/* lengths of messages */
+#define DTLS1_COOKIE_LENGTH                     256
+
+#define DTLS1_RT_HEADER_LENGTH                  13
+
+#define DTLS1_HM_HEADER_LENGTH                  12
+
+#define DTLS1_HM_BAD_FRAGMENT                   -2
+#define DTLS1_HM_FRAGMENT_RETRY                 -3
+
+#define DTLS1_CCS_HEADER_LENGTH                  1
+
+#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
+#define DTLS1_AL_HEADER_LENGTH                   7
+#else
+#define DTLS1_AL_HEADER_LENGTH                   2
+#endif
+
+
+typedef struct dtls1_bitmap_st
+	{
+	unsigned long map;		/* track 32 packets on 32-bit systems
+					   and 64 - on 64-bit systems */
+	unsigned char max_seq_num[8];	/* max record number seen so far,
+					   64-bit value in big-endian
+					   encoding */
+	} DTLS1_BITMAP;
+
+struct dtls1_retransmit_state
+	{
+	EVP_CIPHER_CTX *enc_write_ctx;	/* cryptographic state */
+	EVP_MD_CTX *write_hash;			/* used for mac generation */
+#ifndef OPENSSL_NO_COMP
+	COMP_CTX *compress;				/* compression */
+#else
+	char *compress;	
+#endif
+	SSL_SESSION *session;
+	unsigned short epoch;
+	};
+
+struct hm_header_st
+	{
+	unsigned char type;
+	unsigned long msg_len;
+	unsigned short seq;
+	unsigned long frag_off;
+	unsigned long frag_len;
+	unsigned int is_ccs;
+	struct dtls1_retransmit_state saved_retransmit_state;
+	};
+
+struct ccs_header_st
+	{
+	unsigned char type;
+	unsigned short seq;
+	};
+
+struct dtls1_timeout_st
+	{
+	/* Number of read timeouts so far */
+	unsigned int read_timeouts;
+	
+	/* Number of write timeouts so far */
+	unsigned int write_timeouts;
+	
+	/* Number of alerts received so far */
+	unsigned int num_alerts;
+	};
+
+typedef struct record_pqueue_st
+	{
+	unsigned short epoch;
+	pqueue q;
+	} record_pqueue;
+
+typedef struct hm_fragment_st
+	{
+	struct hm_header_st msg_header;
+	unsigned char *fragment;
+	unsigned char *reassembly;
+	} hm_fragment;
+
+typedef struct dtls1_state_st
+	{
+	unsigned int send_cookie;
+	unsigned char cookie[DTLS1_COOKIE_LENGTH];
+	unsigned char rcvd_cookie[DTLS1_COOKIE_LENGTH];
+	unsigned int cookie_len;
+
+	/* 
+	 * The current data and handshake epoch.  This is initially
+	 * undefined, and starts at zero once the initial handshake is
+	 * completed 
+	 */
+	unsigned short r_epoch;
+	unsigned short w_epoch;
+
+	/* records being received in the current epoch */
+	DTLS1_BITMAP bitmap;
+
+	/* renegotiation starts a new set of sequence numbers */
+	DTLS1_BITMAP next_bitmap;
+
+	/* handshake message numbers */
+	unsigned short handshake_write_seq;
+	unsigned short next_handshake_write_seq;
+
+	unsigned short handshake_read_seq;
+
+	/* save last sequence number for retransmissions */
+	unsigned char last_write_sequence[8];
+
+	/* Received handshake records (processed and unprocessed) */
+	record_pqueue unprocessed_rcds;
+	record_pqueue processed_rcds;
+
+	/* Buffered handshake messages */
+	pqueue buffered_messages;
+
+	/* Buffered (sent) handshake records */
+	pqueue sent_messages;
+
+	/* Buffered application records.
+	 * Only for records between CCS and Finished
+	 * to prevent either protocol violation or
+	 * unnecessary message loss.
+	 */
+	record_pqueue buffered_app_data;
+
+	/* Is set when listening for new connections with dtls1_listen() */
+	unsigned int listen;
+
+	unsigned int mtu; /* max DTLS packet size */
+
+	struct hm_header_st w_msg_hdr;
+	struct hm_header_st r_msg_hdr;
+
+	struct dtls1_timeout_st timeout;
+
+	/* Indicates when the last handshake msg sent will timeout */
+	struct timeval next_timeout;
+
+	/* Timeout duration */
+	unsigned short timeout_duration;
+
+	/* storage for Alert/Handshake protocol data received but not
+	 * yet processed by ssl3_read_bytes: */
+	unsigned char alert_fragment[DTLS1_AL_HEADER_LENGTH];
+	unsigned int alert_fragment_len;
+	unsigned char handshake_fragment[DTLS1_HM_HEADER_LENGTH];
+	unsigned int handshake_fragment_len;
+
+	unsigned int retransmitting;
+	unsigned int change_cipher_spec_ok;
+
+	} DTLS1_STATE;
+
+typedef struct dtls1_record_data_st
+	{
+	unsigned char *packet;
+	unsigned int   packet_length;
+	SSL3_BUFFER    rbuf;
+	SSL3_RECORD    rrec;
+	} DTLS1_RECORD_DATA;
+
+
+/* Timeout multipliers (timeout slice is defined in apps/timeouts.h */
+#define DTLS1_TMO_READ_COUNT                      2
+#define DTLS1_TMO_WRITE_COUNT                     2
+
+#define DTLS1_TMO_ALERT_COUNT                     12
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
+
diff --git a/lib/openssl/ssl/install.com b/lib/openssl/ssl/install.com
new file mode 100644
index 0000000..7f56067
--- /dev/null
+++ b/lib/openssl/ssl/install.com
@@ -0,0 +1,90 @@
+$! INSTALL.COM -- Installs the files in a given directory tree
+$!
+$! Author: Richard Levitte <richard@levitte.org>
+$! Time of creation: 22-MAY-1998 10:13
+$!
+$! P1	root of the directory tree
+$!
+$	IF P1 .EQS. ""
+$	THEN
+$	    WRITE SYS$OUTPUT "First argument missing."
+$	    WRITE SYS$OUTPUT -
+		  "It should be the directory where you want things installed."
+$	    EXIT
+$	ENDIF
+$
+$	IF (F$GETSYI("CPU").LT.128)
+$	THEN
+$	    ARCH := VAX
+$	ELSE
+$	    ARCH = F$EDIT( F$GETSYI( "ARCH_NAME"), "UPCASE")
+$	    IF (ARCH .EQS. "") THEN ARCH = "UNK"
+$	ENDIF
+$
+$	ROOT = F$PARSE(P1,"[]A.;0",,,"SYNTAX_ONLY,NO_CONCEAL") - "A.;0"
+$	ROOT_DEV = F$PARSE(ROOT,,,"DEVICE","SYNTAX_ONLY")
+$	ROOT_DIR = F$PARSE(ROOT,,,"DIRECTORY","SYNTAX_ONLY") -
+		   - "[000000." - "][" - "[" - "]"
+$	ROOT = ROOT_DEV + "[" + ROOT_DIR
+$
+$	DEFINE/NOLOG WRK_SSLROOT 'ROOT'.] /TRANS=CONC
+$	DEFINE/NOLOG WRK_SSLXLIB WRK_SSLROOT:['ARCH'_LIB]
+$	DEFINE/NOLOG WRK_SSLINCLUDE WRK_SSLROOT:[INCLUDE]
+$	DEFINE/NOLOG WRK_SSLXEXE WRK_SSLROOT:['ARCH'_EXE]
+$
+$	IF F$PARSE("WRK_SSLROOT:[000000]") .EQS. "" THEN -
+	   CREATE/DIR/LOG WRK_SSLROOT:[000000]
+$	IF F$PARSE("WRK_SSLXLIB:") .EQS. "" THEN -
+	   CREATE/DIR/LOG WRK_SSLXLIB:
+$	IF F$PARSE("WRK_SSLINCLUDE:") .EQS. "" THEN -
+	   CREATE/DIR/LOG WRK_SSLINCLUDE:
+$	IF F$PARSE("WRK_SSLXEXE:") .EQS. "" THEN -
+	   CREATE/DIR/LOG WRK_SSLXEXE:
+$
+$	EXHEADER := ssl.h,ssl2.h,ssl3.h,ssl23.h,tls1.h,dtls1.h,kssl.h
+$	E_EXE := ssl_task
+$	LIBS := LIBSSL
+$
+$	XEXE_DIR := [-.'ARCH'.EXE.SSL]
+$
+$	COPY 'EXHEADER' WRK_SSLINCLUDE:/LOG
+$	SET FILE/PROT=WORLD:RE WRK_SSLINCLUDE:'EXHEADER'
+$
+$	I = 0
+$ LOOP_EXE: 
+$	E = F$EDIT(F$ELEMENT(I, ",", E_EXE),"TRIM")
+$	I = I + 1
+$	IF E .EQS. "," THEN GOTO LOOP_EXE_END
+$	SET NOON
+$	IF F$SEARCH(XEXE_DIR+E+".EXE") .NES. ""
+$	THEN
+$	  COPY 'XEXE_DIR''E'.EXE WRK_SSLXEXE:'E'.EXE/log
+$	  SET FILE/PROT=W:RE WRK_SSLXEXE:'E'.EXE
+$	ENDIF
+$	SET ON
+$	GOTO LOOP_EXE
+$ LOOP_EXE_END:
+$
+$	I = 0
+$ LOOP_LIB: 
+$	E = F$EDIT(F$ELEMENT(I, ",", LIBS),"TRIM")
+$	I = I + 1
+$	IF E .EQS. "," THEN GOTO LOOP_LIB_END
+$	SET NOON
+$! Object library.
+$	IF F$SEARCH(XEXE_DIR+E+".OLB") .NES. ""
+$	THEN
+$	  COPY 'XEXE_DIR''E'.OLB WRK_SSLXLIB:'E'.OLB/log
+$	  SET FILE/PROT=W:RE WRK_SSLXLIB:'E'.OLB
+$	ENDIF
+$! Shareable image.
+$	IF F$SEARCH(XEXE_DIR+E+".EXE") .NES. ""
+$	THEN
+$	  COPY 'XEXE_DIR''E'.EXE WRK_SSLXLIB:'E'.EXE/log
+$	  SET FILE/PROT=W:RE WRK_SSLXLIB:'E'.EXE
+$	ENDIF
+$	SET ON
+$	GOTO LOOP_LIB
+$ LOOP_LIB_END:
+$
+$	EXIT
diff --git a/lib/openssl/ssl/kssl.c b/lib/openssl/ssl/kssl.c
new file mode 100644
index 0000000..b820e37
--- /dev/null
+++ b/lib/openssl/ssl/kssl.c
@@ -0,0 +1,2205 @@
+/* ssl/kssl.c -*- mode: C; c-file-style: "eay" -*- */
+/* Written by Vern Staats <staatsvr@asc.hpc.mil> for the OpenSSL project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+
+/*  ssl/kssl.c  --  Routines to support (& debug) Kerberos5 auth for openssl
+**
+**  19990701	VRS 	Started.
+**  200011??	Jeffrey Altman, Richard Levitte
+**          		Generalized for Heimdal, Newer MIT, & Win32.
+**          		Integrated into main OpenSSL 0.9.7 snapshots.
+**  20010413	Simon Wilkinson, VRS
+**          		Real RFC2712 KerberosWrapper replaces AP_REQ.
+*/
+
+#include <openssl/opensslconf.h>
+
+#include <string.h>
+
+#define KRB5_PRIVATE	1
+
+#include <openssl/ssl.h>
+#include <openssl/evp.h>
+#include <openssl/objects.h>
+#include <openssl/krb5_asn.h>
+#include "kssl_lcl.h"
+
+#ifndef OPENSSL_NO_KRB5
+
+#ifndef ENOMEM
+#define ENOMEM KRB5KRB_ERR_GENERIC
+#endif
+
+/* 
+ * When OpenSSL is built on Windows, we do not want to require that
+ * the Kerberos DLLs be available in order for the OpenSSL DLLs to
+ * work.  Therefore, all Kerberos routines are loaded at run time
+ * and we do not link to a .LIB file.
+ */
+
+#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
+/* 
+ * The purpose of the following pre-processor statements is to provide
+ * compatibility with different releases of MIT Kerberos for Windows.
+ * All versions up to 1.2 used macros.  But macros do not allow for
+ * a binary compatible interface for DLLs.  Therefore, all macros are
+ * being replaced by function calls.  The following code will allow
+ * an OpenSSL DLL built on Windows to work whether or not the macro
+ * or function form of the routines are utilized.
+ */
+#ifdef  krb5_cc_get_principal
+#define NO_DEF_KRB5_CCACHE
+#undef  krb5_cc_get_principal
+#endif
+#define krb5_cc_get_principal    kssl_krb5_cc_get_principal
+
+#define krb5_free_data_contents  kssl_krb5_free_data_contents   
+#define krb5_free_context        kssl_krb5_free_context         
+#define krb5_auth_con_free       kssl_krb5_auth_con_free        
+#define krb5_free_principal      kssl_krb5_free_principal       
+#define krb5_mk_req_extended     kssl_krb5_mk_req_extended      
+#define krb5_get_credentials     kssl_krb5_get_credentials      
+#define krb5_cc_default          kssl_krb5_cc_default           
+#define krb5_sname_to_principal  kssl_krb5_sname_to_principal   
+#define krb5_init_context        kssl_krb5_init_context         
+#define krb5_free_ticket         kssl_krb5_free_ticket          
+#define krb5_rd_req              kssl_krb5_rd_req               
+#define krb5_kt_default          kssl_krb5_kt_default           
+#define krb5_kt_resolve          kssl_krb5_kt_resolve           
+/* macros in mit 1.2.2 and earlier; functions in mit 1.2.3 and greater */
+#ifndef krb5_kt_close
+#define krb5_kt_close            kssl_krb5_kt_close
+#endif /* krb5_kt_close */
+#ifndef krb5_kt_get_entry
+#define krb5_kt_get_entry        kssl_krb5_kt_get_entry
+#endif /* krb5_kt_get_entry */
+#define krb5_auth_con_init       kssl_krb5_auth_con_init        
+
+#define krb5_principal_compare   kssl_krb5_principal_compare
+#define krb5_decrypt_tkt_part    kssl_krb5_decrypt_tkt_part
+#define krb5_timeofday           kssl_krb5_timeofday
+#define krb5_rc_default          kssl_krb5_rc_default
+
+#ifdef krb5_rc_initialize
+#undef krb5_rc_initialize
+#endif
+#define krb5_rc_initialize   kssl_krb5_rc_initialize
+
+#ifdef krb5_rc_get_lifespan
+#undef krb5_rc_get_lifespan
+#endif
+#define krb5_rc_get_lifespan kssl_krb5_rc_get_lifespan
+
+#ifdef krb5_rc_destroy
+#undef krb5_rc_destroy
+#endif
+#define krb5_rc_destroy      kssl_krb5_rc_destroy
+
+#define valid_cksumtype      kssl_valid_cksumtype
+#define krb5_checksum_size   kssl_krb5_checksum_size
+#define krb5_kt_free_entry   kssl_krb5_kt_free_entry
+#define krb5_auth_con_setrcache  kssl_krb5_auth_con_setrcache
+#define krb5_auth_con_getrcache  kssl_krb5_auth_con_getrcache
+#define krb5_get_server_rcache   kssl_krb5_get_server_rcache
+
+/* Prototypes for built in stubs */
+void kssl_krb5_free_data_contents(krb5_context, krb5_data *);
+void kssl_krb5_free_principal(krb5_context, krb5_principal );
+krb5_error_code kssl_krb5_kt_resolve(krb5_context,
+                                     krb5_const char *,
+                                     krb5_keytab *);
+krb5_error_code kssl_krb5_kt_default(krb5_context,
+                                     krb5_keytab *);
+krb5_error_code kssl_krb5_free_ticket(krb5_context, krb5_ticket *);
+krb5_error_code kssl_krb5_rd_req(krb5_context, krb5_auth_context *, 
+                                 krb5_const krb5_data *,
+                                 krb5_const_principal, krb5_keytab, 
+                                 krb5_flags *,krb5_ticket **);
+
+krb5_boolean kssl_krb5_principal_compare(krb5_context, krb5_const_principal,
+                                         krb5_const_principal);
+krb5_error_code kssl_krb5_mk_req_extended(krb5_context,
+                                          krb5_auth_context  *,
+                                          krb5_const krb5_flags,
+                                          krb5_data  *,
+                                          krb5_creds  *,
+                                          krb5_data  * );
+krb5_error_code kssl_krb5_init_context(krb5_context *);
+void kssl_krb5_free_context(krb5_context);
+krb5_error_code kssl_krb5_cc_default(krb5_context,krb5_ccache  *);
+krb5_error_code kssl_krb5_sname_to_principal(krb5_context,
+                                             krb5_const char  *,
+                                             krb5_const char  *,
+                                             krb5_int32,
+                                             krb5_principal  *);
+krb5_error_code kssl_krb5_get_credentials(krb5_context,
+                                          krb5_const krb5_flags,
+                                          krb5_ccache,
+                                          krb5_creds  *,
+                                          krb5_creds  *  *);
+krb5_error_code kssl_krb5_auth_con_init(krb5_context,
+                                        krb5_auth_context  *);
+krb5_error_code kssl_krb5_cc_get_principal(krb5_context context, 
+                                           krb5_ccache cache,
+                                           krb5_principal *principal);
+krb5_error_code kssl_krb5_auth_con_free(krb5_context,krb5_auth_context);
+size_t kssl_krb5_checksum_size(krb5_context context,krb5_cksumtype ctype);
+krb5_boolean kssl_valid_cksumtype(krb5_cksumtype ctype);
+krb5_error_code krb5_kt_free_entry(krb5_context,krb5_keytab_entry FAR * );
+krb5_error_code kssl_krb5_auth_con_setrcache(krb5_context, 
+                                             krb5_auth_context, 
+                                             krb5_rcache);
+krb5_error_code kssl_krb5_get_server_rcache(krb5_context, 
+                                            krb5_const krb5_data *,
+                                            krb5_rcache *);
+krb5_error_code kssl_krb5_auth_con_getrcache(krb5_context, 
+                                             krb5_auth_context,
+                                             krb5_rcache *);
+
+/* Function pointers (almost all Kerberos functions are _stdcall) */
+static void (_stdcall *p_krb5_free_data_contents)(krb5_context, krb5_data *)
+	=NULL;
+static void (_stdcall *p_krb5_free_principal)(krb5_context, krb5_principal )
+	=NULL;
+static krb5_error_code(_stdcall *p_krb5_kt_resolve)
+			(krb5_context, krb5_const char *, krb5_keytab *)=NULL;
+static krb5_error_code (_stdcall *p_krb5_kt_default)(krb5_context,
+                                                     krb5_keytab *)=NULL;
+static krb5_error_code (_stdcall *p_krb5_free_ticket)(krb5_context, 
+                                                      krb5_ticket *)=NULL;
+static krb5_error_code (_stdcall *p_krb5_rd_req)(krb5_context, 
+                                                 krb5_auth_context *, 
+                                                 krb5_const krb5_data *,
+                                                 krb5_const_principal, 
+                                                 krb5_keytab, krb5_flags *,
+                                                 krb5_ticket **)=NULL;
+static krb5_error_code (_stdcall *p_krb5_mk_req_extended)
+			(krb5_context, krb5_auth_context *,
+			 krb5_const krb5_flags, krb5_data *, krb5_creds *,
+			 krb5_data * )=NULL;
+static krb5_error_code (_stdcall *p_krb5_init_context)(krb5_context *)=NULL;
+static void (_stdcall *p_krb5_free_context)(krb5_context)=NULL;
+static krb5_error_code (_stdcall *p_krb5_cc_default)(krb5_context,
+                                                     krb5_ccache  *)=NULL;
+static krb5_error_code (_stdcall *p_krb5_sname_to_principal)
+			(krb5_context, krb5_const char *, krb5_const char *,
+			 krb5_int32, krb5_principal *)=NULL;
+static krb5_error_code (_stdcall *p_krb5_get_credentials)
+			(krb5_context, krb5_const krb5_flags, krb5_ccache,
+			 krb5_creds *, krb5_creds **)=NULL;
+static krb5_error_code (_stdcall *p_krb5_auth_con_init)
+			(krb5_context, krb5_auth_context *)=NULL;
+static krb5_error_code (_stdcall *p_krb5_cc_get_principal)
+			(krb5_context context, krb5_ccache cache,
+			 krb5_principal *principal)=NULL;
+static krb5_error_code (_stdcall *p_krb5_auth_con_free)
+			(krb5_context, krb5_auth_context)=NULL;
+static krb5_error_code (_stdcall *p_krb5_decrypt_tkt_part)
+                        (krb5_context, krb5_const krb5_keyblock *,
+                                           krb5_ticket *)=NULL;
+static krb5_error_code (_stdcall *p_krb5_timeofday)
+                        (krb5_context context, krb5_int32 *timeret)=NULL;
+static krb5_error_code (_stdcall *p_krb5_rc_default)
+                        (krb5_context context, krb5_rcache *rc)=NULL;
+static krb5_error_code (_stdcall *p_krb5_rc_initialize)
+                        (krb5_context context, krb5_rcache rc,
+                                     krb5_deltat lifespan)=NULL;
+static krb5_error_code (_stdcall *p_krb5_rc_get_lifespan)
+                        (krb5_context context, krb5_rcache rc,
+                                       krb5_deltat *lifespan)=NULL;
+static krb5_error_code (_stdcall *p_krb5_rc_destroy)
+                        (krb5_context context, krb5_rcache rc)=NULL;
+static krb5_boolean (_stdcall *p_krb5_principal_compare)
+                     (krb5_context, krb5_const_principal, krb5_const_principal)=NULL;
+static size_t (_stdcall *p_krb5_checksum_size)(krb5_context context,krb5_cksumtype ctype)=NULL;
+static krb5_boolean (_stdcall *p_valid_cksumtype)(krb5_cksumtype ctype)=NULL;
+static krb5_error_code (_stdcall *p_krb5_kt_free_entry)
+                        (krb5_context,krb5_keytab_entry * )=NULL;
+static krb5_error_code (_stdcall * p_krb5_auth_con_setrcache)(krb5_context, 
+                                                               krb5_auth_context, 
+                                                               krb5_rcache)=NULL;
+static krb5_error_code (_stdcall * p_krb5_get_server_rcache)(krb5_context, 
+                                                              krb5_const krb5_data *, 
+                                                              krb5_rcache *)=NULL;
+static krb5_error_code (* p_krb5_auth_con_getrcache)(krb5_context, 
+                                                      krb5_auth_context,
+                                                      krb5_rcache *)=NULL;
+static krb5_error_code (_stdcall * p_krb5_kt_close)(krb5_context context, 
+                                                    krb5_keytab keytab)=NULL;
+static krb5_error_code (_stdcall * p_krb5_kt_get_entry)(krb5_context context, 
+                                                        krb5_keytab keytab,
+                       krb5_const_principal principal, krb5_kvno vno,
+                       krb5_enctype enctype, krb5_keytab_entry *entry)=NULL;
+static int krb5_loaded = 0;     /* only attempt to initialize func ptrs once */
+
+/* Function to Load the Kerberos 5 DLL and initialize function pointers */
+void
+load_krb5_dll(void)
+	{
+	HANDLE hKRB5_32;
+    
+	krb5_loaded++;
+	hKRB5_32 = LoadLibrary(TEXT("KRB5_32"));
+	if (!hKRB5_32)
+		return;
+
+	(FARPROC) p_krb5_free_data_contents =
+		GetProcAddress( hKRB5_32, "krb5_free_data_contents" );
+	(FARPROC) p_krb5_free_context =
+		GetProcAddress( hKRB5_32, "krb5_free_context" );
+	(FARPROC) p_krb5_auth_con_free =
+		GetProcAddress( hKRB5_32, "krb5_auth_con_free" );
+	(FARPROC) p_krb5_free_principal =
+		GetProcAddress( hKRB5_32, "krb5_free_principal" );
+	(FARPROC) p_krb5_mk_req_extended =
+		GetProcAddress( hKRB5_32, "krb5_mk_req_extended" );
+	(FARPROC) p_krb5_get_credentials =
+		GetProcAddress( hKRB5_32, "krb5_get_credentials" );
+	(FARPROC) p_krb5_cc_get_principal =
+		GetProcAddress( hKRB5_32, "krb5_cc_get_principal" );
+	(FARPROC) p_krb5_cc_default =
+		GetProcAddress( hKRB5_32, "krb5_cc_default" );
+	(FARPROC) p_krb5_sname_to_principal =
+		GetProcAddress( hKRB5_32, "krb5_sname_to_principal" );
+	(FARPROC) p_krb5_init_context =
+		GetProcAddress( hKRB5_32, "krb5_init_context" );
+	(FARPROC) p_krb5_free_ticket =
+		GetProcAddress( hKRB5_32, "krb5_free_ticket" );
+	(FARPROC) p_krb5_rd_req =
+		GetProcAddress( hKRB5_32, "krb5_rd_req" );
+	(FARPROC) p_krb5_principal_compare =
+		GetProcAddress( hKRB5_32, "krb5_principal_compare" );
+	(FARPROC) p_krb5_decrypt_tkt_part =
+		GetProcAddress( hKRB5_32, "krb5_decrypt_tkt_part" );
+	(FARPROC) p_krb5_timeofday =
+		GetProcAddress( hKRB5_32, "krb5_timeofday" );
+	(FARPROC) p_krb5_rc_default =
+		GetProcAddress( hKRB5_32, "krb5_rc_default" );
+	(FARPROC) p_krb5_rc_initialize =
+		GetProcAddress( hKRB5_32, "krb5_rc_initialize" );
+	(FARPROC) p_krb5_rc_get_lifespan =
+		GetProcAddress( hKRB5_32, "krb5_rc_get_lifespan" );
+	(FARPROC) p_krb5_rc_destroy =
+		GetProcAddress( hKRB5_32, "krb5_rc_destroy" );
+	(FARPROC) p_krb5_kt_default =
+		GetProcAddress( hKRB5_32, "krb5_kt_default" );
+	(FARPROC) p_krb5_kt_resolve =
+		GetProcAddress( hKRB5_32, "krb5_kt_resolve" );
+	(FARPROC) p_krb5_auth_con_init =
+		GetProcAddress( hKRB5_32, "krb5_auth_con_init" );
+        (FARPROC) p_valid_cksumtype =
+                GetProcAddress( hKRB5_32, "valid_cksumtype" );
+        (FARPROC) p_krb5_checksum_size =
+                GetProcAddress( hKRB5_32, "krb5_checksum_size" );
+        (FARPROC) p_krb5_kt_free_entry =
+                GetProcAddress( hKRB5_32, "krb5_kt_free_entry" );
+        (FARPROC) p_krb5_auth_con_setrcache =
+                GetProcAddress( hKRB5_32, "krb5_auth_con_setrcache" );
+        (FARPROC) p_krb5_get_server_rcache =
+                GetProcAddress( hKRB5_32, "krb5_get_server_rcache" );
+        (FARPROC) p_krb5_auth_con_getrcache =
+                GetProcAddress( hKRB5_32, "krb5_auth_con_getrcache" );
+        (FARPROC) p_krb5_kt_close =
+                GetProcAddress( hKRB5_32, "krb5_kt_close" );
+        (FARPROC) p_krb5_kt_get_entry =
+                GetProcAddress( hKRB5_32, "krb5_kt_get_entry" );
+	}
+
+/* Stubs for each function to be dynamicly loaded */
+void
+kssl_krb5_free_data_contents(krb5_context CO, krb5_data  * data)
+	{
+	if (!krb5_loaded)
+		load_krb5_dll();
+
+	if ( p_krb5_free_data_contents )
+		p_krb5_free_data_contents(CO,data);
+	}
+
+krb5_error_code
+kssl_krb5_mk_req_extended (krb5_context CO,
+                          krb5_auth_context  * pACO,
+                          krb5_const krb5_flags F,
+                          krb5_data  * pD1,
+                          krb5_creds  * pC,
+                          krb5_data  * pD2)
+	{
+	if (!krb5_loaded)
+		load_krb5_dll();
+
+	if ( p_krb5_mk_req_extended )
+		return(p_krb5_mk_req_extended(CO,pACO,F,pD1,pC,pD2));
+	else
+		return KRB5KRB_ERR_GENERIC;
+	}
+krb5_error_code
+kssl_krb5_auth_con_init(krb5_context CO,
+                       krb5_auth_context  * pACO)
+	{
+	if (!krb5_loaded)
+		load_krb5_dll();
+
+	if ( p_krb5_auth_con_init )
+		return(p_krb5_auth_con_init(CO,pACO));
+	else
+		return KRB5KRB_ERR_GENERIC;
+	}
+krb5_error_code
+kssl_krb5_auth_con_free (krb5_context CO,
+                        krb5_auth_context ACO)
+	{
+	if (!krb5_loaded)
+		load_krb5_dll();
+
+	if ( p_krb5_auth_con_free )
+		return(p_krb5_auth_con_free(CO,ACO));
+	else
+		return KRB5KRB_ERR_GENERIC;
+	}
+krb5_error_code
+kssl_krb5_get_credentials(krb5_context CO,
+                         krb5_const krb5_flags F,
+                         krb5_ccache CC,
+                         krb5_creds  * pCR,
+                         krb5_creds  ** ppCR)
+	{
+	if (!krb5_loaded)
+		load_krb5_dll();
+
+	if ( p_krb5_get_credentials )
+		return(p_krb5_get_credentials(CO,F,CC,pCR,ppCR));
+	else
+		return KRB5KRB_ERR_GENERIC;
+	}
+krb5_error_code
+kssl_krb5_sname_to_principal(krb5_context CO,
+                            krb5_const char  * pC1,
+                            krb5_const char  * pC2,
+                            krb5_int32 I,
+                            krb5_principal  * pPR)
+	{
+	if (!krb5_loaded)
+		load_krb5_dll();
+
+	if ( p_krb5_sname_to_principal )
+		return(p_krb5_sname_to_principal(CO,pC1,pC2,I,pPR));
+	else
+		return KRB5KRB_ERR_GENERIC;
+	}
+
+krb5_error_code
+kssl_krb5_cc_default(krb5_context CO,
+                    krb5_ccache  * pCC)
+	{
+	if (!krb5_loaded)
+		load_krb5_dll();
+
+	if ( p_krb5_cc_default )
+		return(p_krb5_cc_default(CO,pCC));
+	else
+		return KRB5KRB_ERR_GENERIC;
+	}
+
+krb5_error_code
+kssl_krb5_init_context(krb5_context * pCO)
+	{
+	if (!krb5_loaded)
+		load_krb5_dll();
+
+	if ( p_krb5_init_context )
+		return(p_krb5_init_context(pCO));
+	else
+		return KRB5KRB_ERR_GENERIC;
+	}
+
+void
+kssl_krb5_free_context(krb5_context CO)
+	{
+	if (!krb5_loaded)
+		load_krb5_dll();
+
+	if ( p_krb5_free_context )
+		p_krb5_free_context(CO);
+	}
+
+void
+kssl_krb5_free_principal(krb5_context c, krb5_principal p)
+	{
+	if (!krb5_loaded)
+		load_krb5_dll();
+
+	if ( p_krb5_free_principal )
+		p_krb5_free_principal(c,p);
+	}
+
+krb5_error_code
+kssl_krb5_kt_resolve(krb5_context con,
+                    krb5_const char * sz,
+                    krb5_keytab * kt)
+	{
+	if (!krb5_loaded)
+		load_krb5_dll();
+
+	if ( p_krb5_kt_resolve )
+		return(p_krb5_kt_resolve(con,sz,kt));
+	else
+		return KRB5KRB_ERR_GENERIC;
+	}
+
+krb5_error_code
+kssl_krb5_kt_default(krb5_context con,
+                    krb5_keytab * kt)
+	{
+	if (!krb5_loaded)
+		load_krb5_dll();
+
+	if ( p_krb5_kt_default )
+		return(p_krb5_kt_default(con,kt));
+	else
+		return KRB5KRB_ERR_GENERIC;
+	}
+
+krb5_error_code
+kssl_krb5_free_ticket(krb5_context con,
+                     krb5_ticket * kt)
+	{
+	if (!krb5_loaded)
+		load_krb5_dll();
+
+	if ( p_krb5_free_ticket )
+		return(p_krb5_free_ticket(con,kt));
+	else
+		return KRB5KRB_ERR_GENERIC;
+	}
+
+krb5_error_code
+kssl_krb5_rd_req(krb5_context con, krb5_auth_context * pacon,
+                krb5_const krb5_data * data,
+                krb5_const_principal princ, krb5_keytab keytab,
+                krb5_flags * flags, krb5_ticket ** pptkt)
+	{
+	if (!krb5_loaded)
+		load_krb5_dll();
+
+	if ( p_krb5_rd_req )
+		return(p_krb5_rd_req(con,pacon,data,princ,keytab,flags,pptkt));
+	else
+		return KRB5KRB_ERR_GENERIC;
+	}
+
+krb5_boolean
+krb5_principal_compare(krb5_context con, krb5_const_principal princ1,
+                krb5_const_principal princ2)
+	{
+	if (!krb5_loaded)
+		load_krb5_dll();
+
+	if ( p_krb5_principal_compare )
+		return(p_krb5_principal_compare(con,princ1,princ2));
+	else
+		return KRB5KRB_ERR_GENERIC;
+	}
+
+krb5_error_code
+krb5_decrypt_tkt_part(krb5_context con, krb5_const krb5_keyblock *keys,
+                krb5_ticket *ticket)
+	{
+	if (!krb5_loaded)
+		load_krb5_dll();
+
+	if ( p_krb5_decrypt_tkt_part )
+		return(p_krb5_decrypt_tkt_part(con,keys,ticket));
+	else
+		return KRB5KRB_ERR_GENERIC;
+	}
+
+krb5_error_code
+krb5_timeofday(krb5_context con, krb5_int32 *timeret)
+	{
+	if (!krb5_loaded)
+		load_krb5_dll();
+
+	if ( p_krb5_timeofday )
+		return(p_krb5_timeofday(con,timeret));
+	else
+		return KRB5KRB_ERR_GENERIC;
+	}
+
+krb5_error_code
+krb5_rc_default(krb5_context con, krb5_rcache *rc)
+	{
+	if (!krb5_loaded)
+		load_krb5_dll();
+
+	if ( p_krb5_rc_default )
+		return(p_krb5_rc_default(con,rc));
+	else
+		return KRB5KRB_ERR_GENERIC;
+	}
+
+krb5_error_code
+krb5_rc_initialize(krb5_context con, krb5_rcache rc, krb5_deltat lifespan)
+	{
+	if (!krb5_loaded)
+		load_krb5_dll();
+
+	if ( p_krb5_rc_initialize )
+		return(p_krb5_rc_initialize(con, rc, lifespan));
+	else
+		return KRB5KRB_ERR_GENERIC;
+	}
+
+krb5_error_code
+krb5_rc_get_lifespan(krb5_context con, krb5_rcache rc, krb5_deltat *lifespanp)
+	{
+	if (!krb5_loaded)
+		load_krb5_dll();
+
+	if ( p_krb5_rc_get_lifespan )
+		return(p_krb5_rc_get_lifespan(con, rc, lifespanp));
+	else
+		return KRB5KRB_ERR_GENERIC;
+	}
+
+krb5_error_code
+krb5_rc_destroy(krb5_context con, krb5_rcache rc)
+	{
+	if (!krb5_loaded)
+		load_krb5_dll();
+
+	if ( p_krb5_rc_destroy )
+		return(p_krb5_rc_destroy(con, rc));
+	else
+		return KRB5KRB_ERR_GENERIC;
+	}
+
+size_t 
+krb5_checksum_size(krb5_context context,krb5_cksumtype ctype)
+        {
+        if (!krb5_loaded)
+                load_krb5_dll();
+
+        if ( p_krb5_checksum_size )
+                return(p_krb5_checksum_size(context, ctype));
+        else
+                return KRB5KRB_ERR_GENERIC;
+        }
+
+krb5_boolean 
+valid_cksumtype(krb5_cksumtype ctype)
+        {
+        if (!krb5_loaded)
+                load_krb5_dll();
+
+        if ( p_valid_cksumtype )
+                return(p_valid_cksumtype(ctype));
+        else
+                return KRB5KRB_ERR_GENERIC;
+        }
+
+krb5_error_code 
+krb5_kt_free_entry(krb5_context con,krb5_keytab_entry * entry)
+        {
+        if (!krb5_loaded)
+                load_krb5_dll();
+
+        if ( p_krb5_kt_free_entry )
+                return(p_krb5_kt_free_entry(con,entry));
+        else
+                return KRB5KRB_ERR_GENERIC;
+        }
+                 
+/* Structure definitions  */
+#ifndef NO_DEF_KRB5_CCACHE
+#ifndef krb5_x
+#define krb5_x(ptr,args) ((ptr)?((*(ptr)) args):(abort(),1))
+#define krb5_xc(ptr,args) ((ptr)?((*(ptr)) args):(abort(),(char*)0))
+#endif 
+
+typedef	krb5_pointer	krb5_cc_cursor;	/* cursor for sequential lookup */
+
+typedef struct _krb5_ccache
+	{
+	krb5_magic magic;
+	struct _krb5_cc_ops FAR *ops;
+	krb5_pointer data;
+	} *krb5_ccache;
+
+typedef struct _krb5_cc_ops
+	{
+	krb5_magic magic;
+	char  *prefix;
+	char  * (KRB5_CALLCONV *get_name)
+		(krb5_context, krb5_ccache);
+	krb5_error_code (KRB5_CALLCONV *resolve)
+		(krb5_context, krb5_ccache  *, const char  *);
+	krb5_error_code (KRB5_CALLCONV *gen_new)
+		(krb5_context, krb5_ccache  *);
+	krb5_error_code (KRB5_CALLCONV *init)
+		(krb5_context, krb5_ccache, krb5_principal);
+	krb5_error_code (KRB5_CALLCONV *destroy)
+		(krb5_context, krb5_ccache);
+	krb5_error_code (KRB5_CALLCONV *close)
+		(krb5_context, krb5_ccache);
+	krb5_error_code (KRB5_CALLCONV *store)
+		(krb5_context, krb5_ccache, krb5_creds  *);
+	krb5_error_code (KRB5_CALLCONV *retrieve)
+		(krb5_context, krb5_ccache,
+		krb5_flags, krb5_creds  *, krb5_creds  *);
+	krb5_error_code (KRB5_CALLCONV *get_princ)
+		(krb5_context, krb5_ccache, krb5_principal  *);
+	krb5_error_code (KRB5_CALLCONV *get_first)
+		(krb5_context, krb5_ccache, krb5_cc_cursor  *);
+	krb5_error_code (KRB5_CALLCONV *get_next)
+		(krb5_context, krb5_ccache,
+		krb5_cc_cursor  *, krb5_creds  *);
+	krb5_error_code (KRB5_CALLCONV *end_get)
+		(krb5_context, krb5_ccache, krb5_cc_cursor  *);
+	krb5_error_code (KRB5_CALLCONV *remove_cred)
+		(krb5_context, krb5_ccache,
+		krb5_flags, krb5_creds  *);
+	krb5_error_code (KRB5_CALLCONV *set_flags)
+		(krb5_context, krb5_ccache, krb5_flags);
+	} krb5_cc_ops;
+#endif /* NO_DEF_KRB5_CCACHE */
+
+krb5_error_code 
+kssl_krb5_cc_get_principal
+    (krb5_context context, krb5_ccache cache,
+      krb5_principal *principal)
+	{
+	if ( p_krb5_cc_get_principal )
+		return(p_krb5_cc_get_principal(context,cache,principal));
+	else
+		return(krb5_x
+			((cache)->ops->get_princ,(context, cache, principal)));
+	}
+
+krb5_error_code
+kssl_krb5_auth_con_setrcache(krb5_context con, krb5_auth_context acon,
+                             krb5_rcache rcache)
+        {
+        if ( p_krb5_auth_con_setrcache )
+                 return(p_krb5_auth_con_setrcache(con,acon,rcache));
+        else
+                 return KRB5KRB_ERR_GENERIC;
+        }
+
+krb5_error_code
+kssl_krb5_get_server_rcache(krb5_context con, krb5_const krb5_data * data,
+                            krb5_rcache * rcache) 
+        {
+	if ( p_krb5_get_server_rcache )
+		return(p_krb5_get_server_rcache(con,data,rcache));
+	else
+		return KRB5KRB_ERR_GENERIC;
+        }
+
+krb5_error_code
+kssl_krb5_auth_con_getrcache(krb5_context con, krb5_auth_context acon,
+                             krb5_rcache * prcache)
+        {
+	if ( p_krb5_auth_con_getrcache )
+		return(p_krb5_auth_con_getrcache(con,acon, prcache));
+	else
+		return KRB5KRB_ERR_GENERIC;
+	}
+ 
+krb5_error_code
+kssl_krb5_kt_close(krb5_context context, krb5_keytab keytab)
+	{
+	if ( p_krb5_kt_close )
+		return(p_krb5_kt_close(context,keytab));
+	else 
+		return KRB5KRB_ERR_GENERIC;
+	}
+
+krb5_error_code
+kssl_krb5_kt_get_entry(krb5_context context, krb5_keytab keytab,
+                       krb5_const_principal principal, krb5_kvno vno,
+                       krb5_enctype enctype, krb5_keytab_entry *entry)
+	{
+	if ( p_krb5_kt_get_entry )
+		return(p_krb5_kt_get_entry(context,keytab,principal,vno,enctype,entry));
+	else
+		return KRB5KRB_ERR_GENERIC;
+        }
+#endif  /* OPENSSL_SYS_WINDOWS || OPENSSL_SYS_WIN32 */
+
+
+/* memory allocation functions for non-temporary storage
+ * (e.g. stuff that gets saved into the kssl context) */
+static void* kssl_calloc(size_t nmemb, size_t size)
+{
+	void* p;
+	
+	p=OPENSSL_malloc(nmemb*size);
+	if (p){
+		memset(p, 0, nmemb*size);
+	}
+	return p;
+}
+
+#define kssl_malloc(size) OPENSSL_malloc((size))
+#define kssl_realloc(ptr, size) OPENSSL_realloc(ptr, size)
+#define kssl_free(ptr) OPENSSL_free((ptr))
+
+
+char
+*kstring(char *string)
+        {
+        static char	*null = "[NULL]";
+
+	return ((string == NULL)? null: string);
+        }
+
+/*	Given KRB5 enctype (basically DES or 3DES),
+**	return closest match openssl EVP_ encryption algorithm.
+**	Return NULL for unknown or problematic (krb5_dk_encrypt) enctypes.
+**	Assume ENCTYPE_*_RAW (krb5_raw_encrypt) are OK.
+*/
+const EVP_CIPHER *
+kssl_map_enc(krb5_enctype enctype)
+        {
+	switch (enctype)
+		{
+	case ENCTYPE_DES_HMAC_SHA1:		/*    EVP_des_cbc();       */
+	case ENCTYPE_DES_CBC_CRC:
+	case ENCTYPE_DES_CBC_MD4:
+	case ENCTYPE_DES_CBC_MD5:
+	case ENCTYPE_DES_CBC_RAW:
+				return EVP_des_cbc();
+				break;
+	case ENCTYPE_DES3_CBC_SHA1:		/*    EVP_des_ede3_cbc();  */
+	case ENCTYPE_DES3_CBC_SHA:
+	case ENCTYPE_DES3_CBC_RAW:
+				return EVP_des_ede3_cbc();
+				break;
+	default:                return NULL;
+				break;
+		}
+	}
+
+
+/*	Return true:1 if p "looks like" the start of the real authenticator
+**	described in kssl_skip_confound() below.  The ASN.1 pattern is
+**	"62 xx 30 yy" (APPLICATION-2, SEQUENCE), where xx-yy =~ 2, and
+**	xx and yy are possibly multi-byte length fields.
+*/
+static int 	kssl_test_confound(unsigned char *p)
+	{
+	int 	len = 2;
+	int 	xx = 0, yy = 0;
+
+	if (*p++ != 0x62)  return 0;
+	if (*p > 0x82)  return 0;
+	switch(*p)  {
+		case 0x82:  p++;          xx = (*p++ << 8);  xx += *p++;  break;
+		case 0x81:  p++;          xx =  *p++;  break;
+		case 0x80:  return 0;
+		default:    xx = *p++;  break;
+		}
+	if (*p++ != 0x30)  return 0;
+	if (*p > 0x82)  return 0;
+	switch(*p)  {
+		case 0x82:  p++; len+=2;  yy = (*p++ << 8);  yy += *p++;  break;
+		case 0x81:  p++; len++;   yy =  *p++;  break;
+		case 0x80:  return 0;
+		default:    yy = *p++;  break;
+		}
+
+	return (xx - len == yy)? 1: 0;
+	}
+
+/*	Allocate, fill, and return cksumlens array of checksum lengths.
+**	This array holds just the unique elements from the krb5_cksumarray[].
+**	array[n] == 0 signals end of data.
+**
+**      The krb5_cksumarray[] was an internal variable that has since been
+**      replaced by a more general method for storing the data.  It should
+**      not be used.  Instead we use real API calls and make a guess for 
+**      what the highest assigned CKSUMTYPE_ constant is.  As of 1.2.2
+**      it is 0x000c (CKSUMTYPE_HMAC_SHA1_DES3).  So we will use 0x0010.
+*/
+static size_t  *populate_cksumlens(void)
+	{
+	int 		i, j, n;
+	static size_t 	*cklens = NULL;
+
+#ifdef KRB5_MIT_OLD11
+	n = krb5_max_cksum;
+#else
+	n = 0x0010;
+#endif	/* KRB5_MIT_OLD11 */
+ 
+#ifdef KRB5CHECKAUTH
+	if (!cklens && !(cklens = (size_t *) calloc(sizeof(int),n+1)))  return NULL;
+
+	for (i=0; i < n; i++)  {
+		if (!valid_cksumtype(i))  continue;	/*  array has holes  */
+		for (j=0; j < n; j++)  {
+			if (cklens[j] == 0)  {
+				cklens[j] = krb5_checksum_size(NULL,i);
+				break;		/*  krb5 elem was new: add   */
+				}
+			if (cklens[j] == krb5_checksum_size(NULL,i))  {
+				break;		/*  ignore duplicate elements */
+				}
+			}
+		}
+#endif	/* KRB5CHECKAUTH */
+
+	return cklens;
+	}
+
+/*	Return pointer to start of real authenticator within authenticator, or
+**	return NULL on error.
+**	Decrypted authenticator looks like this:
+**		[0 or 8 byte confounder] [4-24 byte checksum] [real authent'r]
+**	This hackery wouldn't be necessary if MIT KRB5 1.0.6 had the
+**	krb5_auth_con_getcksumtype() function advertised in its krb5.h.
+*/
+unsigned char	*kssl_skip_confound(krb5_enctype etype, unsigned char *a)
+	{
+	int 		i, conlen;
+	size_t		cklen;
+	static size_t 	*cksumlens = NULL;
+	unsigned char	*test_auth;
+
+	conlen = (etype)? 8: 0;
+
+	if (!cksumlens  &&  !(cksumlens = populate_cksumlens()))  return NULL;
+	for (i=0; (cklen = cksumlens[i]) != 0; i++)
+		{
+		test_auth = a + conlen + cklen;
+		if (kssl_test_confound(test_auth))  return test_auth;
+		}
+
+	return NULL;
+	}
+
+
+/*	Set kssl_err error info when reason text is a simple string
+**		kssl_err = struct { int reason; char text[KSSL_ERR_MAX+1]; }
+*/
+void
+kssl_err_set(KSSL_ERR *kssl_err, int reason, char *text)
+        {
+	if (kssl_err == NULL)  return;
+
+	kssl_err->reason = reason;
+	BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, "%s", text);
+	return;
+        }
+
+
+/*	Display contents of krb5_data struct, for debugging
+*/
+void
+print_krb5_data(char *label, krb5_data *kdata)
+        {
+	int i;
+
+	printf("%s[%d] ", label, kdata->length);
+	for (i=0; i < (int)kdata->length; i++)
+                {
+		if (0 &&  isprint((int) kdata->data[i]))
+                        printf(	"%c ",  kdata->data[i]);
+		else
+                        printf(	"%02x ", (unsigned char) kdata->data[i]);
+		}
+	printf("\n");
+        }
+
+
+/*	Display contents of krb5_authdata struct, for debugging
+*/
+void
+print_krb5_authdata(char *label, krb5_authdata **adata)
+        {
+	if (adata == NULL)
+                {
+		printf("%s, authdata==0\n", label);
+		return;
+		}
+	printf("%s [%p]\n", label, (void *)adata);
+#if 0
+	{
+        int 	i;
+	printf("%s[at%d:%d] ", label, adata->ad_type, adata->length);
+	for (i=0; i < adata->length; i++)
+                {
+                printf((isprint(adata->contents[i]))? "%c ": "%02x",
+                        adata->contents[i]);
+		}
+	printf("\n");
+	}
+#endif
+	}
+
+
+/*	Display contents of krb5_keyblock struct, for debugging
+*/
+void
+print_krb5_keyblock(char *label, krb5_keyblock *keyblk)
+        {
+	int i;
+
+	if (keyblk == NULL)
+                {
+		printf("%s, keyblk==0\n", label);
+		return;
+		}
+#ifdef KRB5_HEIMDAL
+	printf("%s\n\t[et%d:%d]: ", label, keyblk->keytype,
+					   keyblk->keyvalue->length);
+	for (i=0; i < (int)keyblk->keyvalue->length; i++)
+                {
+		printf("%02x",(unsigned char *)(keyblk->keyvalue->contents)[i]);
+		}
+	printf("\n");
+#else
+	printf("%s\n\t[et%d:%d]: ", label, keyblk->enctype, keyblk->length);
+	for (i=0; i < (int)keyblk->length; i++)
+                {
+		printf("%02x",keyblk->contents[i]);
+		}
+	printf("\n");
+#endif
+        }
+
+
+/*	Display contents of krb5_principal_data struct, for debugging
+**	(krb5_principal is typedef'd == krb5_principal_data *)
+*/
+static void
+print_krb5_princ(char *label, krb5_principal_data *princ)
+        {
+	int i, ui, uj;
+
+	printf("%s principal Realm: ", label);
+	if (princ == NULL)  return;
+	for (ui=0; ui < (int)princ->realm.length; ui++)  putchar(princ->realm.data[ui]);
+	printf(" (nametype %d) has %d strings:\n", princ->type,princ->length);
+	for (i=0; i < (int)princ->length; i++)
+                {
+		printf("\t%d [%d]: ", i, princ->data[i].length);
+		for (uj=0; uj < (int)princ->data[i].length; uj++)  {
+			putchar(princ->data[i].data[uj]);
+			}
+		printf("\n");
+		}
+	return;
+        }
+
+
+/*	Given krb5 service (typically "kssl") and hostname in kssl_ctx,
+**	Return encrypted Kerberos ticket for service @ hostname.
+**	If authenp is non-NULL, also return encrypted authenticator,
+**	whose data should be freed by caller.
+**	(Originally was: Create Kerberos AP_REQ message for SSL Client.)
+**
+**	19990628	VRS 	Started; Returns Kerberos AP_REQ message.
+**	20010409	VRS 	Modified for RFC2712; Returns enc tkt.
+**	20010606	VRS 	May also return optional authenticator.
+*/
+krb5_error_code
+kssl_cget_tkt(	/* UPDATE */	KSSL_CTX *kssl_ctx,
+                /* OUT    */	krb5_data **enc_ticketp,
+                /* UPDATE */	krb5_data *authenp,
+                /* OUT    */	KSSL_ERR *kssl_err)
+	{
+	krb5_error_code		krb5rc = KRB5KRB_ERR_GENERIC;
+	krb5_context		krb5context = NULL;
+	krb5_auth_context	krb5auth_context = NULL;
+	krb5_ccache 		krb5ccdef = NULL;
+	krb5_creds		krb5creds, *krb5credsp = NULL;
+	krb5_data		krb5_app_req;
+
+	kssl_err_set(kssl_err, 0, "");
+	memset((char *)&krb5creds, 0, sizeof(krb5creds));
+
+	if (!kssl_ctx)
+                {
+		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
+                        "No kssl_ctx defined.\n");
+		goto err;
+		}
+	else if (!kssl_ctx->service_host)
+                {
+		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
+                        "kssl_ctx service_host undefined.\n");
+		goto err;
+		}
+
+	if ((krb5rc = krb5_init_context(&krb5context)) != 0)
+                {
+		BIO_snprintf(kssl_err->text,KSSL_ERR_MAX,
+                        "krb5_init_context() fails: %d\n", krb5rc);
+		kssl_err->reason = SSL_R_KRB5_C_INIT;
+		goto err;
+		}
+
+	if ((krb5rc = krb5_sname_to_principal(krb5context,
+                kssl_ctx->service_host,
+                (kssl_ctx->service_name)? kssl_ctx->service_name: KRB5SVC,
+                KRB5_NT_SRV_HST, &krb5creds.server)) != 0)
+                {
+		BIO_snprintf(kssl_err->text,KSSL_ERR_MAX,
+                        "krb5_sname_to_principal() fails for %s/%s\n",
+                        kssl_ctx->service_host,
+                        (kssl_ctx->service_name)? kssl_ctx->service_name:
+						  KRB5SVC);
+		kssl_err->reason = SSL_R_KRB5_C_INIT;
+		goto err;
+		}
+
+	if ((krb5rc = krb5_cc_default(krb5context, &krb5ccdef)) != 0)
+                {
+		kssl_err_set(kssl_err, SSL_R_KRB5_C_CC_PRINC,
+                        "krb5_cc_default fails.\n");
+		goto err;
+		}
+
+	if ((krb5rc = krb5_cc_get_principal(krb5context, krb5ccdef,
+                &krb5creds.client)) != 0)
+                {
+		kssl_err_set(kssl_err, SSL_R_KRB5_C_CC_PRINC,
+                        "krb5_cc_get_principal() fails.\n");
+		goto err;
+		}
+
+	if ((krb5rc = krb5_get_credentials(krb5context, 0, krb5ccdef,
+                &krb5creds, &krb5credsp)) != 0)
+                {
+		kssl_err_set(kssl_err, SSL_R_KRB5_C_GET_CRED,
+                        "krb5_get_credentials() fails.\n");
+		goto err;
+		}
+
+	*enc_ticketp = &krb5credsp->ticket;
+#ifdef KRB5_HEIMDAL
+	kssl_ctx->enctype = krb5credsp->session.keytype;
+#else
+	kssl_ctx->enctype = krb5credsp->keyblock.enctype;
+#endif
+
+	krb5rc = KRB5KRB_ERR_GENERIC;
+	/*	caller should free data of krb5_app_req  */
+	/*  20010406 VRS deleted for real KerberosWrapper
+	**  20010605 VRS reinstated to offer Authenticator to KerberosWrapper
+	*/
+	krb5_app_req.length = 0;
+	if (authenp)
+                {
+		krb5_data	krb5in_data;
+		const unsigned char	*p;
+		long		arlen;
+		KRB5_APREQBODY	*ap_req;
+
+		authenp->length = 0;
+		krb5in_data.data = NULL;
+		krb5in_data.length = 0;
+		if ((krb5rc = krb5_mk_req_extended(krb5context,
+			&krb5auth_context, 0, &krb5in_data, krb5credsp,
+			&krb5_app_req)) != 0)
+			{
+			kssl_err_set(kssl_err, SSL_R_KRB5_C_MK_REQ,
+				"krb5_mk_req_extended() fails.\n");
+			goto err;
+			}
+
+		arlen = krb5_app_req.length;
+		p = (unsigned char *)krb5_app_req.data;
+		ap_req = (KRB5_APREQBODY *) d2i_KRB5_APREQ(NULL, &p, arlen);
+		if (ap_req)
+			{
+			authenp->length = i2d_KRB5_ENCDATA(
+					ap_req->authenticator, NULL);
+			if (authenp->length  && 
+				(authenp->data = malloc(authenp->length)))
+				{
+				unsigned char	*adp = (unsigned char *)authenp->data;
+				authenp->length = i2d_KRB5_ENCDATA(
+						ap_req->authenticator, &adp);
+				}
+			}
+
+		if (ap_req)  KRB5_APREQ_free((KRB5_APREQ *) ap_req);
+		if (krb5_app_req.length)  
+                        kssl_krb5_free_data_contents(krb5context,&krb5_app_req);
+		}
+#ifdef KRB5_HEIMDAL
+	if (kssl_ctx_setkey(kssl_ctx, &krb5credsp->session))
+                {
+		kssl_err_set(kssl_err, SSL_R_KRB5_C_INIT,
+                        "kssl_ctx_setkey() fails.\n");
+		}
+#else
+	if (kssl_ctx_setkey(kssl_ctx, &krb5credsp->keyblock))
+                {
+		kssl_err_set(kssl_err, SSL_R_KRB5_C_INIT,
+                        "kssl_ctx_setkey() fails.\n");
+		}
+#endif
+	else	krb5rc = 0;
+
+ err:
+#ifdef KSSL_DEBUG
+	kssl_ctx_show(kssl_ctx);
+#endif	/* KSSL_DEBUG */
+
+	if (krb5creds.client)	krb5_free_principal(krb5context,
+							krb5creds.client);
+	if (krb5creds.server)	krb5_free_principal(krb5context,
+							krb5creds.server);
+	if (krb5auth_context)	krb5_auth_con_free(krb5context,
+							krb5auth_context);
+	if (krb5context)	krb5_free_context(krb5context);
+	return (krb5rc);
+	}
+
+
+/*  Given d2i_-decoded asn1ticket, allocate and return a new krb5_ticket.
+**  Return Kerberos error code and kssl_err struct on error.
+**  Allocates krb5_ticket and krb5_principal; caller should free these.
+**
+**	20010410	VRS	Implemented krb5_decode_ticket() as
+**				old_krb5_decode_ticket(). Missing from MIT1.0.6.
+**	20010615	VRS 	Re-cast as openssl/asn1 d2i_*() functions.
+**				Re-used some of the old krb5_decode_ticket()
+**				code here.  This tkt should alloc/free just
+**				like the real thing.
+*/
+static krb5_error_code
+kssl_TKT2tkt(	/* IN     */	krb5_context	krb5context,
+		/* IN     */	KRB5_TKTBODY	*asn1ticket,
+		/* OUT    */	krb5_ticket	**krb5ticket,
+		/* OUT    */	KSSL_ERR *kssl_err  )
+        {
+        krb5_error_code			krb5rc = KRB5KRB_ERR_GENERIC;
+	krb5_ticket 			*new5ticket = NULL;
+	ASN1_GENERALSTRING		*gstr_svc, *gstr_host;
+
+	*krb5ticket = NULL;
+
+	if (asn1ticket == NULL  ||  asn1ticket->realm == NULL  ||
+		asn1ticket->sname == NULL  || 
+		sk_ASN1_GENERALSTRING_num(asn1ticket->sname->namestring) < 2)
+		{
+		BIO_snprintf(kssl_err->text, KSSL_ERR_MAX,
+			"Null field in asn1ticket.\n");
+		kssl_err->reason = SSL_R_KRB5_S_RD_REQ;
+		return KRB5KRB_ERR_GENERIC;
+		}
+
+	if ((new5ticket = (krb5_ticket *) calloc(1, sizeof(krb5_ticket)))==NULL)
+		{
+		BIO_snprintf(kssl_err->text, KSSL_ERR_MAX,
+			"Unable to allocate new krb5_ticket.\n");
+		kssl_err->reason = SSL_R_KRB5_S_RD_REQ;
+		return ENOMEM;		/*  or  KRB5KRB_ERR_GENERIC;	*/
+		}
+
+	gstr_svc  = sk_ASN1_GENERALSTRING_value(asn1ticket->sname->namestring, 0);
+	gstr_host = sk_ASN1_GENERALSTRING_value(asn1ticket->sname->namestring, 1);
+
+	if ((krb5rc = kssl_build_principal_2(krb5context,
+			&new5ticket->server,
+			asn1ticket->realm->length, (char *)asn1ticket->realm->data,
+			gstr_svc->length,  (char *)gstr_svc->data,
+			gstr_host->length, (char *)gstr_host->data)) != 0)
+		{
+		free(new5ticket);
+		BIO_snprintf(kssl_err->text, KSSL_ERR_MAX,
+			"Error building ticket server principal.\n");
+		kssl_err->reason = SSL_R_KRB5_S_RD_REQ;
+		return krb5rc;		/*  or  KRB5KRB_ERR_GENERIC;	*/
+		}
+
+	krb5_princ_type(krb5context, new5ticket->server) =
+			asn1ticket->sname->nametype->data[0];
+	new5ticket->enc_part.enctype = asn1ticket->encdata->etype->data[0];
+	new5ticket->enc_part.kvno = asn1ticket->encdata->kvno->data[0];
+	new5ticket->enc_part.ciphertext.length =
+			asn1ticket->encdata->cipher->length;
+	if ((new5ticket->enc_part.ciphertext.data =
+		calloc(1, asn1ticket->encdata->cipher->length)) == NULL)
+		{
+		free(new5ticket);
+		BIO_snprintf(kssl_err->text, KSSL_ERR_MAX,
+			"Error allocating cipher in krb5ticket.\n");
+		kssl_err->reason = SSL_R_KRB5_S_RD_REQ;
+		return KRB5KRB_ERR_GENERIC;
+		}
+	else
+		{
+		memcpy(new5ticket->enc_part.ciphertext.data,
+			asn1ticket->encdata->cipher->data,
+			asn1ticket->encdata->cipher->length);
+		}
+
+	*krb5ticket = new5ticket;
+	return 0;
+	}
+
+
+/*	Given krb5 service name in KSSL_CTX *kssl_ctx (typically "kssl"),
+**		and krb5 AP_REQ message & message length,
+**	Return Kerberos session key and client principle
+**		to SSL Server in KSSL_CTX *kssl_ctx.
+**
+**	19990702	VRS 	Started.
+*/
+krb5_error_code
+kssl_sget_tkt(	/* UPDATE */	KSSL_CTX		*kssl_ctx,
+		/* IN     */	krb5_data		*indata,
+		/* OUT    */	krb5_ticket_times	*ttimes,
+		/* OUT    */	KSSL_ERR		*kssl_err  )
+        {
+        krb5_error_code			krb5rc = KRB5KRB_ERR_GENERIC;
+        static krb5_context		krb5context = NULL;
+	static krb5_auth_context	krb5auth_context = NULL;
+	krb5_ticket 			*krb5ticket = NULL;
+	KRB5_TKTBODY 			*asn1ticket = NULL;
+	const unsigned char		*p;
+	krb5_keytab 			krb5keytab = NULL;
+	krb5_keytab_entry		kt_entry;
+	krb5_principal			krb5server;
+        krb5_rcache                     rcache = NULL;
+
+	kssl_err_set(kssl_err, 0, "");
+
+	if (!kssl_ctx)
+                {
+		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
+			"No kssl_ctx defined.\n");
+		goto err;
+		}
+
+#ifdef KSSL_DEBUG
+	printf("in kssl_sget_tkt(%s)\n", kstring(kssl_ctx->service_name));
+#endif	/* KSSL_DEBUG */
+
+	if (!krb5context  &&  (krb5rc = krb5_init_context(&krb5context)))
+                {
+		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
+                        "krb5_init_context() fails.\n");
+		goto err;
+		}
+	if (krb5auth_context  &&
+		(krb5rc = krb5_auth_con_free(krb5context, krb5auth_context)))
+                {
+		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
+                        "krb5_auth_con_free() fails.\n");
+		goto err;
+		}
+	else  krb5auth_context = NULL;
+	if (!krb5auth_context  &&
+		(krb5rc = krb5_auth_con_init(krb5context, &krb5auth_context)))
+                {
+		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
+                        "krb5_auth_con_init() fails.\n");
+		goto err;
+		}
+
+ 
+	if ((krb5rc = krb5_auth_con_getrcache(krb5context, krb5auth_context,
+		&rcache)))
+		{
+ 		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
+			"krb5_auth_con_getrcache() fails.\n");
+ 		goto err;
+		}
+ 
+	if ((krb5rc = krb5_sname_to_principal(krb5context, NULL,
+                (kssl_ctx->service_name)? kssl_ctx->service_name: KRB5SVC,
+                KRB5_NT_SRV_HST, &krb5server)) != 0)
+                {
+		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
+                        "krb5_sname_to_principal() fails.\n");
+		goto err;
+		}
+
+	if (rcache == NULL) 
+                {
+                if ((krb5rc = krb5_get_server_rcache(krb5context,
+			krb5_princ_component(krb5context, krb5server, 0),
+			&rcache)))
+                        {
+		        kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
+                                "krb5_get_server_rcache() fails.\n");
+                  	goto err;
+                        }
+                }
+
+        if ((krb5rc = krb5_auth_con_setrcache(krb5context, krb5auth_context, rcache)))
+                {
+                kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
+			"krb5_auth_con_setrcache() fails.\n");
+                goto err;
+                }
+
+
+	/*	kssl_ctx->keytab_file == NULL ==> use Kerberos default
+	*/
+	if (kssl_ctx->keytab_file)
+		{
+		krb5rc = krb5_kt_resolve(krb5context, kssl_ctx->keytab_file,
+                        &krb5keytab);
+		if (krb5rc)
+			{
+			kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
+				"krb5_kt_resolve() fails.\n");
+			goto err;
+			}
+		}
+	else
+		{
+                krb5rc = krb5_kt_default(krb5context,&krb5keytab);
+                if (krb5rc)
+			{
+			kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 
+				"krb5_kt_default() fails.\n");
+			goto err;
+			}
+		}
+
+	/*	Actual Kerberos5 krb5_recvauth() has initial conversation here
+	**	o	check KRB5_SENDAUTH_BADAUTHVERS
+	**		unless KRB5_RECVAUTH_SKIP_VERSION
+	**	o	check KRB5_SENDAUTH_BADAPPLVERS
+	**	o	send "0" msg if all OK
+	*/
+
+	/*  20010411 was using AP_REQ instead of true KerberosWrapper
+	**
+	**  if ((krb5rc = krb5_rd_req(krb5context, &krb5auth_context,
+	**			&krb5in_data, krb5server, krb5keytab,
+	**			&ap_option, &krb5ticket)) != 0)  { Error }
+	*/
+
+	p = (unsigned char *)indata->data;
+	if ((asn1ticket = (KRB5_TKTBODY *) d2i_KRB5_TICKET(NULL, &p,
+						(long) indata->length)) == NULL)
+		{
+		BIO_snprintf(kssl_err->text, KSSL_ERR_MAX,
+			"d2i_KRB5_TICKET() ASN.1 decode failure.\n");
+		kssl_err->reason = SSL_R_KRB5_S_RD_REQ;
+		goto err;
+		}
+	
+	/* Was:  krb5rc = krb5_decode_ticket(krb5in_data,&krb5ticket)) != 0) */
+	if ((krb5rc = kssl_TKT2tkt(krb5context, asn1ticket, &krb5ticket,
+					kssl_err)) != 0)
+		{
+		BIO_snprintf(kssl_err->text, KSSL_ERR_MAX,
+			"Error converting ASN.1 ticket to krb5_ticket.\n");
+		kssl_err->reason = SSL_R_KRB5_S_RD_REQ;
+		goto err;
+		}
+
+	if (! krb5_principal_compare(krb5context, krb5server,
+						  krb5ticket->server))  {
+		krb5rc = KRB5_PRINC_NOMATCH;
+		BIO_snprintf(kssl_err->text, KSSL_ERR_MAX,
+			"server principal != ticket principal\n");
+		kssl_err->reason = SSL_R_KRB5_S_RD_REQ;
+		goto err;
+		}
+	if ((krb5rc = krb5_kt_get_entry(krb5context, krb5keytab,
+			krb5ticket->server, krb5ticket->enc_part.kvno,
+			krb5ticket->enc_part.enctype, &kt_entry)) != 0)  {
+		BIO_snprintf(kssl_err->text, KSSL_ERR_MAX,
+			"krb5_kt_get_entry() fails with %x.\n", krb5rc);
+		kssl_err->reason = SSL_R_KRB5_S_RD_REQ;
+		goto err;
+		}
+	if ((krb5rc = krb5_decrypt_tkt_part(krb5context, &kt_entry.key,
+			krb5ticket)) != 0)  {
+		BIO_snprintf(kssl_err->text, KSSL_ERR_MAX,
+			"krb5_decrypt_tkt_part() failed.\n");
+		kssl_err->reason = SSL_R_KRB5_S_RD_REQ;
+		goto err;
+		}
+	else  {
+		krb5_kt_free_entry(krb5context, &kt_entry);
+#ifdef KSSL_DEBUG
+		{
+		int i; krb5_address **paddr = krb5ticket->enc_part2->caddrs;
+		printf("Decrypted ticket fields:\n");
+		printf("\tflags: %X, transit-type: %X",
+			krb5ticket->enc_part2->flags,
+			krb5ticket->enc_part2->transited.tr_type);
+		print_krb5_data("\ttransit-data: ",
+			&(krb5ticket->enc_part2->transited.tr_contents));
+		printf("\tcaddrs: %p, authdata: %p\n",
+			krb5ticket->enc_part2->caddrs,
+			krb5ticket->enc_part2->authorization_data);
+		if (paddr)
+			{
+			printf("\tcaddrs:\n");
+			for (i=0; paddr[i] != NULL; i++)
+				{
+				krb5_data d;
+				d.length=paddr[i]->length;
+				d.data=paddr[i]->contents;
+				print_krb5_data("\t\tIP: ", &d);
+				}
+			}
+		printf("\tstart/auth/end times: %d / %d / %d\n",
+			krb5ticket->enc_part2->times.starttime,
+			krb5ticket->enc_part2->times.authtime,
+			krb5ticket->enc_part2->times.endtime);
+		}
+#endif	/* KSSL_DEBUG */
+		}
+
+	krb5rc = KRB5_NO_TKT_SUPPLIED;
+	if (!krb5ticket  ||	!krb5ticket->enc_part2  ||
+                !krb5ticket->enc_part2->client  ||
+                !krb5ticket->enc_part2->client->data  ||
+                !krb5ticket->enc_part2->session)
+                {
+                kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET,
+                        "bad ticket from krb5_rd_req.\n");
+		}
+	else if (kssl_ctx_setprinc(kssl_ctx, KSSL_CLIENT,
+		 &krb5ticket->enc_part2->client->realm,
+		 krb5ticket->enc_part2->client->data,
+		 krb5ticket->enc_part2->client->length))
+                {
+		kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET,
+                        "kssl_ctx_setprinc() fails.\n");
+		}
+	else if (kssl_ctx_setkey(kssl_ctx, krb5ticket->enc_part2->session))
+                {
+		kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET,
+                        "kssl_ctx_setkey() fails.\n");
+		}
+	else if (krb5ticket->enc_part2->flags & TKT_FLG_INVALID)
+                {
+		krb5rc = KRB5KRB_AP_ERR_TKT_INVALID;
+                kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET,
+                        "invalid ticket from krb5_rd_req.\n");
+		}
+	else	krb5rc = 0;
+
+	kssl_ctx->enctype	= krb5ticket->enc_part.enctype;
+	ttimes->authtime	= krb5ticket->enc_part2->times.authtime;
+	ttimes->starttime	= krb5ticket->enc_part2->times.starttime;
+	ttimes->endtime 	= krb5ticket->enc_part2->times.endtime;
+	ttimes->renew_till	= krb5ticket->enc_part2->times.renew_till;
+
+ err:
+#ifdef KSSL_DEBUG
+	kssl_ctx_show(kssl_ctx);
+#endif	/* KSSL_DEBUG */
+
+	if (asn1ticket) 	KRB5_TICKET_free((KRB5_TICKET *) asn1ticket);
+        if (krb5keytab)         krb5_kt_close(krb5context, krb5keytab);
+	if (krb5ticket) 	krb5_free_ticket(krb5context, krb5ticket);
+	if (krb5server) 	krb5_free_principal(krb5context, krb5server);
+	return (krb5rc);
+        }
+
+
+/*	Allocate & return a new kssl_ctx struct.
+*/
+KSSL_CTX	*
+kssl_ctx_new(void)
+        {
+	return ((KSSL_CTX *) kssl_calloc(1, sizeof(KSSL_CTX)));
+        }
+
+
+/*	Frees a kssl_ctx struct and any allocated memory it holds.
+**	Returns NULL.
+*/
+KSSL_CTX	*
+kssl_ctx_free(KSSL_CTX *kssl_ctx)
+        {
+	if (kssl_ctx == NULL)  return kssl_ctx;
+
+	if (kssl_ctx->key)  		OPENSSL_cleanse(kssl_ctx->key,
+							      kssl_ctx->length);
+	if (kssl_ctx->key)  		kssl_free(kssl_ctx->key);
+	if (kssl_ctx->client_princ) 	kssl_free(kssl_ctx->client_princ);
+	if (kssl_ctx->service_host) 	kssl_free(kssl_ctx->service_host);
+	if (kssl_ctx->service_name) 	kssl_free(kssl_ctx->service_name);
+	if (kssl_ctx->keytab_file) 	kssl_free(kssl_ctx->keytab_file);
+
+	kssl_free(kssl_ctx);
+	return (KSSL_CTX *) NULL;
+        }
+
+
+/*	Given an array of (krb5_data *) entity (and optional realm),
+**	set the plain (char *) client_princ or service_host member
+**	of the kssl_ctx struct.
+*/
+krb5_error_code
+kssl_ctx_setprinc(KSSL_CTX *kssl_ctx, int which,
+        krb5_data *realm, krb5_data *entity, int nentities)
+        {
+	char	**princ;
+	int 	length;
+	int i;
+
+	if (kssl_ctx == NULL  ||  entity == NULL)  return KSSL_CTX_ERR;
+
+	switch (which)
+                {
+        case KSSL_CLIENT:	princ = &kssl_ctx->client_princ;	break;
+        case KSSL_SERVER:	princ = &kssl_ctx->service_host;	break;
+        default:		return KSSL_CTX_ERR;			break;
+		}
+	if (*princ)  kssl_free(*princ);
+
+	/* Add up all the entity->lengths */
+	length = 0;
+	for (i=0; i < nentities; i++)
+		{
+		length += entity[i].length;
+		}
+	/* Add in space for the '/' character(s) (if any) */
+	length += nentities-1;
+	/* Space for the ('@'+realm+NULL | NULL) */
+	length += ((realm)? realm->length + 2: 1);
+
+	if ((*princ = kssl_calloc(1, length)) == NULL)
+		return KSSL_CTX_ERR;
+	else
+		{
+		for (i = 0; i < nentities; i++)
+			{
+			strncat(*princ, entity[i].data, entity[i].length);
+			if (i < nentities-1)
+				{
+				strcat (*princ, "/");
+				}
+			}
+		if (realm)
+                        {
+			strcat (*princ, "@");
+			(void) strncat(*princ, realm->data, realm->length);
+			}
+		}
+
+	return KSSL_CTX_OK;
+        }
+
+
+/*	Set one of the plain (char *) string members of the kssl_ctx struct.
+**	Default values should be:
+**		which == KSSL_SERVICE	=>	"khost" (KRB5SVC)
+**		which == KSSL_KEYTAB	=>	"/etc/krb5.keytab" (KRB5KEYTAB)
+*/
+krb5_error_code
+kssl_ctx_setstring(KSSL_CTX *kssl_ctx, int which, char *text)
+        {
+	char	**string;
+
+	if (!kssl_ctx)  return KSSL_CTX_ERR;
+
+	switch (which)
+                {
+        case KSSL_SERVICE:	string = &kssl_ctx->service_name;	break;
+        case KSSL_SERVER:	string = &kssl_ctx->service_host;	break;
+        case KSSL_CLIENT:	string = &kssl_ctx->client_princ;	break;
+        case KSSL_KEYTAB:	string = &kssl_ctx->keytab_file;	break;
+        default:		return KSSL_CTX_ERR;			break;
+		}
+	if (*string)  kssl_free(*string);
+
+	if (!text)
+                {
+		*string = '\0';
+		return KSSL_CTX_OK;
+		}
+
+	if ((*string = kssl_calloc(1, strlen(text) + 1)) == NULL)
+		return KSSL_CTX_ERR;
+	else
+		strcpy(*string, text);
+
+	return KSSL_CTX_OK;
+        }
+
+
+/*	Copy the Kerberos session key from a (krb5_keyblock *) to a kssl_ctx
+**	struct.  Clear kssl_ctx->key if Kerberos session key is NULL.
+*/
+krb5_error_code
+kssl_ctx_setkey(KSSL_CTX *kssl_ctx, krb5_keyblock *session)
+        {
+	int 		length;
+	krb5_enctype	enctype;
+	krb5_octet FAR	*contents = NULL;
+
+	if (!kssl_ctx)  return KSSL_CTX_ERR;
+
+	if (kssl_ctx->key)
+                {
+		OPENSSL_cleanse(kssl_ctx->key, kssl_ctx->length);
+		kssl_free(kssl_ctx->key);
+		}
+
+	if (session)
+                {
+
+#ifdef KRB5_HEIMDAL
+		length = session->keyvalue->length;
+		enctype = session->keytype;
+		contents = session->keyvalue->contents;
+#else
+		length = session->length;
+		enctype = session->enctype;
+		contents = session->contents;
+#endif
+		kssl_ctx->enctype = enctype;
+		kssl_ctx->length  = length;
+		}
+	else
+                {
+		kssl_ctx->enctype = ENCTYPE_UNKNOWN;
+		kssl_ctx->length  = 0;
+		return KSSL_CTX_OK;
+		}
+
+	if ((kssl_ctx->key =
+                (krb5_octet FAR *) kssl_calloc(1, kssl_ctx->length)) == NULL)
+                {
+		kssl_ctx->length  = 0;
+		return KSSL_CTX_ERR;
+		}
+	else
+		memcpy(kssl_ctx->key, contents, length);
+
+	return KSSL_CTX_OK;
+        }
+
+
+/*	Display contents of kssl_ctx struct
+*/
+void
+kssl_ctx_show(KSSL_CTX *kssl_ctx)
+        {
+	int 	i;
+
+	printf("kssl_ctx: ");
+	if (kssl_ctx == NULL)
+                {
+		printf("NULL\n");
+		return;
+		}
+	else
+		printf("%p\n", (void *)kssl_ctx);
+
+	printf("\tservice:\t%s\n",
+                (kssl_ctx->service_name)? kssl_ctx->service_name: "NULL");
+	printf("\tclient:\t%s\n",
+                (kssl_ctx->client_princ)? kssl_ctx->client_princ: "NULL");
+	printf("\tserver:\t%s\n",
+                (kssl_ctx->service_host)? kssl_ctx->service_host: "NULL");
+	printf("\tkeytab:\t%s\n",
+                (kssl_ctx->keytab_file)? kssl_ctx->keytab_file: "NULL");
+	printf("\tkey [%d:%d]:\t",
+                kssl_ctx->enctype, kssl_ctx->length);
+
+	for (i=0; i < kssl_ctx->length  &&  kssl_ctx->key; i++)
+                {
+		printf("%02x", kssl_ctx->key[i]);
+		}
+	printf("\n");
+	return;
+        }
+
+    int 
+    kssl_keytab_is_available(KSSL_CTX *kssl_ctx)
+{
+    krb5_context		krb5context = NULL;
+    krb5_keytab 		krb5keytab = NULL;
+    krb5_keytab_entry           entry;
+    krb5_principal              princ = NULL;
+    krb5_error_code  		krb5rc = KRB5KRB_ERR_GENERIC;
+    int rc = 0;
+
+    if ((krb5rc = krb5_init_context(&krb5context)))
+        return(0);
+
+    /*	kssl_ctx->keytab_file == NULL ==> use Kerberos default
+    */
+    if (kssl_ctx->keytab_file)
+    {
+        krb5rc = krb5_kt_resolve(krb5context, kssl_ctx->keytab_file,
+                                  &krb5keytab);
+        if (krb5rc)
+            goto exit;
+    }
+    else
+    {
+        krb5rc = krb5_kt_default(krb5context,&krb5keytab);
+        if (krb5rc)
+            goto exit;
+    }
+
+    /* the host key we are looking for */
+    krb5rc = krb5_sname_to_principal(krb5context, NULL, 
+                                     kssl_ctx->service_name ? kssl_ctx->service_name: KRB5SVC,
+                                     KRB5_NT_SRV_HST, &princ);
+
+    if (krb5rc)
+	goto exit;
+
+    krb5rc = krb5_kt_get_entry(krb5context, krb5keytab, 
+                                princ,
+                                0 /* IGNORE_VNO */,
+                                0 /* IGNORE_ENCTYPE */,
+                                &entry);
+    if ( krb5rc == KRB5_KT_NOTFOUND ) {
+        rc = 1;
+        goto exit;
+    } else if ( krb5rc )
+        goto exit;
+    
+    krb5_kt_free_entry(krb5context, &entry);
+    rc = 1;
+
+  exit:
+    if (krb5keytab)     krb5_kt_close(krb5context, krb5keytab);
+    if (princ)          krb5_free_principal(krb5context, princ);
+    if (krb5context)	krb5_free_context(krb5context);
+    return(rc);
+}
+
+int 
+kssl_tgt_is_available(KSSL_CTX *kssl_ctx)
+        {
+        krb5_error_code		krb5rc = KRB5KRB_ERR_GENERIC;
+        krb5_context		krb5context = NULL;
+        krb5_ccache 		krb5ccdef = NULL;
+        krb5_creds		krb5creds, *krb5credsp = NULL;
+        int                     rc = 0;
+
+        memset((char *)&krb5creds, 0, sizeof(krb5creds));
+
+        if (!kssl_ctx)
+            return(0);
+
+        if (!kssl_ctx->service_host)
+            return(0);
+
+        if ((krb5rc = krb5_init_context(&krb5context)) != 0)
+            goto err;
+
+        if ((krb5rc = krb5_sname_to_principal(krb5context,
+                                              kssl_ctx->service_host,
+                                              (kssl_ctx->service_name)? kssl_ctx->service_name: KRB5SVC,
+                                              KRB5_NT_SRV_HST, &krb5creds.server)) != 0)
+            goto err;
+
+        if ((krb5rc = krb5_cc_default(krb5context, &krb5ccdef)) != 0)
+            goto err;
+
+        if ((krb5rc = krb5_cc_get_principal(krb5context, krb5ccdef,
+                                             &krb5creds.client)) != 0)
+            goto err;
+
+        if ((krb5rc = krb5_get_credentials(krb5context, 0, krb5ccdef,
+                                            &krb5creds, &krb5credsp)) != 0)
+            goto err;
+
+        rc = 1;
+
+      err:
+#ifdef KSSL_DEBUG
+	kssl_ctx_show(kssl_ctx);
+#endif	/* KSSL_DEBUG */
+
+	if (krb5creds.client)	krb5_free_principal(krb5context, krb5creds.client);
+	if (krb5creds.server)	krb5_free_principal(krb5context, krb5creds.server);
+	if (krb5context)	krb5_free_context(krb5context);
+        return(rc);
+	}
+
+#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_WIN32)
+void kssl_krb5_free_data_contents(krb5_context context, krb5_data *data)
+	{
+#ifdef KRB5_HEIMDAL
+	data->length = 0;
+        if (data->data)
+            free(data->data);
+#elif defined(KRB5_MIT_OLD11)
+	if (data->data)  {
+		krb5_xfree(data->data);
+		data->data = 0;
+		}
+#else
+	krb5_free_data_contents(NULL, data);
+#endif
+	}
+#endif /* !OPENSSL_SYS_WINDOWS && !OPENSSL_SYS_WIN32 */
+
+
+/*  Given pointers to KerberosTime and struct tm structs, convert the
+**  KerberosTime string to struct tm.  Note that KerberosTime is a
+**  ASN1_GENERALIZEDTIME value, constrained to GMT with no fractional
+**  seconds as defined in RFC 1510.
+**  Return pointer to the (partially) filled in struct tm on success,
+**  return NULL on failure.
+*/
+static struct tm *k_gmtime(ASN1_GENERALIZEDTIME *gtime, struct tm *k_tm)
+	{
+	char 		c, *p;
+
+	if (!k_tm)  return NULL;
+	if (gtime == NULL  ||  gtime->length < 14)  return NULL;
+	if (gtime->data == NULL)  return NULL;
+
+	p = (char *)&gtime->data[14];
+
+	c = *p;	 *p = '\0';  p -= 2;  k_tm->tm_sec  = atoi(p);      *(p+2) = c;
+	c = *p;	 *p = '\0';  p -= 2;  k_tm->tm_min  = atoi(p);      *(p+2) = c;
+	c = *p;	 *p = '\0';  p -= 2;  k_tm->tm_hour = atoi(p);      *(p+2) = c;
+	c = *p;	 *p = '\0';  p -= 2;  k_tm->tm_mday = atoi(p);      *(p+2) = c;
+	c = *p;	 *p = '\0';  p -= 2;  k_tm->tm_mon  = atoi(p)-1;    *(p+2) = c;
+	c = *p;	 *p = '\0';  p -= 4;  k_tm->tm_year = atoi(p)-1900; *(p+4) = c;
+
+	return k_tm;
+	}
+
+
+/*  Helper function for kssl_validate_times().
+**  We need context->clockskew, but krb5_context is an opaque struct.
+**  So we try to sneek the clockskew out through the replay cache.
+**	If that fails just return a likely default (300 seconds).
+*/
+static krb5_deltat get_rc_clockskew(krb5_context context)
+	{
+	krb5_rcache 	rc;
+	krb5_deltat 	clockskew;
+
+	if (krb5_rc_default(context, &rc))  return KSSL_CLOCKSKEW;
+	if (krb5_rc_initialize(context, rc, 0))  return KSSL_CLOCKSKEW;
+	if (krb5_rc_get_lifespan(context, rc, &clockskew))  {
+		clockskew = KSSL_CLOCKSKEW;
+		}
+	(void) krb5_rc_destroy(context, rc);
+	return clockskew;
+	}
+
+
+/*  kssl_validate_times() combines (and more importantly exposes)
+**  the MIT KRB5 internal function krb5_validate_times() and the
+**  in_clock_skew() macro.  The authenticator client time is checked
+**  to be within clockskew secs of the current time and the current
+**  time is checked to be within the ticket start and expire times.
+**  Either check may be omitted by supplying a NULL value.
+**  Returns 0 for valid times, SSL_R_KRB5* error codes otherwise.
+**  See Also: (Kerberos source)/krb5/lib/krb5/krb/valid_times.c
+**  20010420 VRS
+*/
+krb5_error_code  kssl_validate_times(	krb5_timestamp atime,
+					krb5_ticket_times *ttimes)
+	{
+	krb5_deltat 	skew;
+	krb5_timestamp	start, now;
+	krb5_error_code	rc;
+	krb5_context	context;
+
+	if ((rc = krb5_init_context(&context)))	 return SSL_R_KRB5_S_BAD_TICKET;
+	skew = get_rc_clockskew(context); 
+	if ((rc = krb5_timeofday(context,&now))) return SSL_R_KRB5_S_BAD_TICKET;
+	krb5_free_context(context);
+
+	if (atime  &&  labs(atime - now) >= skew)  return SSL_R_KRB5_S_TKT_SKEW;
+
+	if (! ttimes)  return 0;
+
+	start = (ttimes->starttime != 0)? ttimes->starttime: ttimes->authtime;
+	if (start - now > skew)  return SSL_R_KRB5_S_TKT_NYV;
+	if ((now - ttimes->endtime) > skew)  return SSL_R_KRB5_S_TKT_EXPIRED;
+
+#ifdef KSSL_DEBUG
+	printf("kssl_validate_times: %d |<-  | %d - %d | < %d  ->| %d\n",
+		start, atime, now, skew, ttimes->endtime);
+#endif	/* KSSL_DEBUG */
+
+	return 0;
+	}
+
+
+/*  Decode and decrypt given DER-encoded authenticator, then pass
+**  authenticator ctime back in *atimep (or 0 if time unavailable).
+**  Returns krb5_error_code and kssl_err on error.  A NULL 
+**  authenticator (authentp->length == 0) is not considered an error.
+**  Note that kssl_check_authent() makes use of the KRB5 session key;
+**  you must call kssl_sget_tkt() to get the key before calling this routine.
+*/
+krb5_error_code  kssl_check_authent(
+			/* IN     */	KSSL_CTX	*kssl_ctx,
+                        /* IN     */   	krb5_data	*authentp,
+			/* OUT    */	krb5_timestamp	*atimep,
+			/* OUT    */    KSSL_ERR	*kssl_err  )
+	{
+        krb5_error_code		krb5rc = 0;
+	KRB5_ENCDATA		*dec_authent = NULL;
+	KRB5_AUTHENTBODY	*auth = NULL;
+	krb5_enctype		enctype;
+	EVP_CIPHER_CTX		ciph_ctx;
+	const EVP_CIPHER	*enc = NULL;
+	unsigned char		iv[EVP_MAX_IV_LENGTH];
+	const unsigned char	*p;
+	unsigned char		*unenc_authent;
+	int 			outl, unencbufsize;
+	struct tm		tm_time, *tm_l, *tm_g;
+	time_t			now, tl, tg, tr, tz_offset;
+
+	EVP_CIPHER_CTX_init(&ciph_ctx);
+	*atimep = 0;
+	kssl_err_set(kssl_err, 0, "");
+
+#ifndef KRB5CHECKAUTH
+	authentp = NULL;
+#else
+#if	KRB5CHECKAUTH == 0
+	authentp = NULL;
+#endif
+#endif	/* KRB5CHECKAUTH */
+
+	if (authentp == NULL  ||  authentp->length == 0)  return 0;
+
+#ifdef KSSL_DEBUG
+        {
+        unsigned int ui;
+	printf("kssl_check_authent: authenticator[%d]:\n",authentp->length);
+	p = authentp->data; 
+	for (ui=0; ui < authentp->length; ui++)  printf("%02x ",p[ui]);
+	printf("\n");
+        }
+#endif	/* KSSL_DEBUG */
+
+	unencbufsize = 2 * authentp->length;
+	if ((unenc_authent = calloc(1, unencbufsize)) == NULL)
+		{
+		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
+			"Unable to allocate authenticator buffer.\n");
+		krb5rc = KRB5KRB_ERR_GENERIC;
+		goto err;
+		}
+
+	p = (unsigned char *)authentp->data;
+	if ((dec_authent = d2i_KRB5_ENCDATA(NULL, &p,
+					(long) authentp->length)) == NULL) 
+		{
+		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
+                        "Error decoding authenticator.\n");
+		krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+		goto err;
+		}
+
+	enctype = dec_authent->etype->data[0];	/* should = kssl_ctx->enctype */
+#if !defined(KRB5_MIT_OLD11)
+            switch ( enctype ) {
+            case ENCTYPE_DES3_CBC_SHA1:		/*    EVP_des_ede3_cbc();  */
+            case ENCTYPE_DES3_CBC_SHA:
+            case ENCTYPE_DES3_CBC_RAW:
+                krb5rc = 0;                     /* Skip, can't handle derived keys */
+                goto err;
+            }
+#endif
+	enc = kssl_map_enc(enctype);
+	memset(iv, 0, sizeof iv);       /* per RFC 1510 */
+
+	if (enc == NULL)
+		{
+		/*  Disable kssl_check_authent for ENCTYPE_DES3_CBC_SHA1.
+		**  This enctype indicates the authenticator was encrypted
+		**  using key-usage derived keys which openssl cannot decrypt.
+		*/
+		goto err;
+		}
+
+        if (!EVP_CipherInit(&ciph_ctx,enc,kssl_ctx->key,iv,0))
+                {
+                kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
+                        "EVP_CipherInit error decrypting authenticator.\n");
+                krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+                goto err;
+                }
+        outl = dec_authent->cipher->length;
+        if (!EVP_Cipher(&ciph_ctx,unenc_authent,dec_authent->cipher->data,outl))
+                {
+                kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
+                        "EVP_Cipher error decrypting authenticator.\n");
+                krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+                goto err;
+                }
+        EVP_CIPHER_CTX_cleanup(&ciph_ctx);
+
+#ifdef KSSL_DEBUG
+	{
+	int padl;
+	printf("kssl_check_authent: decrypted authenticator[%d] =\n", outl);
+	for (padl=0; padl < outl; padl++) printf("%02x ",unenc_authent[padl]);
+	printf("\n");
+	}
+#endif	/* KSSL_DEBUG */
+
+	if ((p = kssl_skip_confound(enctype, unenc_authent)) == NULL)
+		{
+		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
+                        "confounded by authenticator.\n");
+		krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+		goto err;
+		}
+	outl -= p - unenc_authent;
+
+	if ((auth = (KRB5_AUTHENTBODY *) d2i_KRB5_AUTHENT(NULL, &p,
+							  (long) outl))==NULL)
+		{
+		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
+                        "Error decoding authenticator body.\n");
+		krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+		goto err;
+		}
+
+	memset(&tm_time,0,sizeof(struct tm));
+	if (k_gmtime(auth->ctime, &tm_time)  &&
+		((tr = mktime(&tm_time)) != (time_t)(-1)))
+ 		{
+ 		now  = time(&now);
+ 		tm_l = localtime(&now); 	tl = mktime(tm_l);
+ 		tm_g = gmtime(&now);		tg = mktime(tm_g);
+ 		tz_offset = tg - tl;
+
+		*atimep = (krb5_timestamp)(tr - tz_offset);
+ 		}
+
+#ifdef KSSL_DEBUG
+	printf("kssl_check_authent: returns %d for client time ", *atimep);
+	if (auth && auth->ctime && auth->ctime->length && auth->ctime->data)
+		printf("%.*s\n", auth->ctime->length, auth->ctime->data);
+	else	printf("NULL\n");
+#endif	/* KSSL_DEBUG */
+
+ err:
+	if (auth)		KRB5_AUTHENT_free((KRB5_AUTHENT *) auth);
+	if (dec_authent)	KRB5_ENCDATA_free(dec_authent);
+	if (unenc_authent)	free(unenc_authent);
+	EVP_CIPHER_CTX_cleanup(&ciph_ctx);
+	return krb5rc;
+	}
+
+
+/*  Replaces krb5_build_principal_ext(), with varargs length == 2 (svc, host),
+**  because I dont't know how to stub varargs.
+**  Returns krb5_error_code == ENOMEM on alloc error, otherwise
+**  passes back newly constructed principal, which should be freed by caller.
+*/
+krb5_error_code  kssl_build_principal_2(
+			/* UPDATE */	krb5_context	context,
+			/* OUT    */	krb5_principal	*princ,
+			/* IN     */	int rlen,  const char *realm,
+			/* IN	  */	int slen,  const char *svc,
+			/* IN	  */	int hlen,  const char *host)
+	{
+	krb5_data		*p_data = NULL;
+	krb5_principal		new_p = NULL;
+        char			*new_r = NULL;
+
+	if ((p_data = (krb5_data *) calloc(2, sizeof(krb5_data))) == NULL  ||
+	    (new_p = (krb5_principal) calloc(1, sizeof(krb5_principal_data)))
+			== NULL)  goto err;
+	new_p->length = 2;
+	new_p->data = p_data;
+
+	if ((new_r = calloc(1, rlen + 1)) == NULL)  goto err;
+	memcpy(new_r, realm, rlen);
+	krb5_princ_set_realm_length(context, new_p, rlen);
+	krb5_princ_set_realm_data(context, new_p, new_r);
+
+	if ((new_p->data[0].data = calloc(1, slen + 1)) == NULL)  goto err;
+	memcpy(new_p->data[0].data, svc, slen);
+	new_p->data[0].length = slen;
+
+	if ((new_p->data[1].data = calloc(1, hlen + 1)) == NULL)  goto err;
+	memcpy(new_p->data[1].data, host, hlen);
+	new_p->data[1].length = hlen;
+	
+	krb5_princ_type(context, new_p) = KRB5_NT_UNKNOWN;
+	*princ = new_p;
+	return 0;
+
+ err:
+	if (new_p  &&  new_p[0].data)	free(new_p[0].data);
+	if (new_p  &&  new_p[1].data)	free(new_p[1].data);
+	if (new_p)	free(new_p);
+	if (new_r)	free(new_r);
+	return ENOMEM;
+	}
+
+
+#else /* !OPENSSL_NO_KRB5 */
+
+#if defined(PEDANTIC) || defined(OPENSSL_SYS_VMS)
+static void *dummy=&dummy;
+#endif
+
+#endif	/* !OPENSSL_NO_KRB5	*/
+
diff --git a/lib/openssl/ssl/kssl.h b/lib/openssl/ssl/kssl.h
new file mode 100644
index 0000000..a3d20e1
--- /dev/null
+++ b/lib/openssl/ssl/kssl.h
@@ -0,0 +1,179 @@
+/* ssl/kssl.h -*- mode: C; c-file-style: "eay" -*- */
+/* Written by Vern Staats <staatsvr@asc.hpc.mil> for the OpenSSL project 2000.
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/*
+**	19990701	VRS 	Started.
+*/
+
+#ifndef	KSSL_H
+#define	KSSL_H
+
+#include <openssl/opensslconf.h>
+
+#ifndef OPENSSL_NO_KRB5
+
+#include <stdio.h>
+#include <ctype.h>
+#include <krb5.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/*
+**	Depending on which KRB5 implementation used, some types from
+**	the other may be missing.  Resolve that here and now
+*/
+#ifdef KRB5_HEIMDAL
+typedef unsigned char krb5_octet;
+#define FAR
+#else
+
+#ifndef FAR
+#define FAR
+#endif
+
+#endif
+
+/*	Uncomment this to debug kssl problems or
+**	to trace usage of the Kerberos session key
+**
+**	#define		KSSL_DEBUG
+*/
+
+#ifndef	KRB5SVC
+#define KRB5SVC	"host"
+#endif
+
+#ifndef	KRB5KEYTAB
+#define KRB5KEYTAB	"/etc/krb5.keytab"
+#endif
+
+#ifndef KRB5SENDAUTH
+#define KRB5SENDAUTH	1
+#endif
+
+#ifndef KRB5CHECKAUTH
+#define KRB5CHECKAUTH	1
+#endif
+
+#ifndef KSSL_CLOCKSKEW
+#define	KSSL_CLOCKSKEW	300;
+#endif
+
+#define	KSSL_ERR_MAX	255
+typedef struct kssl_err_st  {
+	int  reason;
+	char text[KSSL_ERR_MAX+1];
+	} KSSL_ERR;
+
+
+/*	Context for passing
+**		(1) Kerberos session key to SSL, and
+**		(2)	Config data between application and SSL lib
+*/
+typedef struct kssl_ctx_st
+        {
+                                /*	used by:    disposition:            */
+	char *service_name;	/*	C,S	    default ok (kssl)       */
+	char *service_host;	/*	C	    input, REQUIRED         */
+	char *client_princ;	/*	S	    output from krb5 ticket */
+	char *keytab_file;	/*      S	    NULL (/etc/krb5.keytab) */
+	char *cred_cache;	/*	C	    NULL (default)          */
+	krb5_enctype enctype;
+	int length;
+	krb5_octet FAR *key;
+	} KSSL_CTX;
+
+#define	KSSL_CLIENT 	1
+#define KSSL_SERVER 	2
+#define	KSSL_SERVICE	3
+#define	KSSL_KEYTAB 	4
+
+#define KSSL_CTX_OK 	0
+#define KSSL_CTX_ERR	1
+#define KSSL_NOMEM	2
+
+/* Public (for use by applications that use OpenSSL with Kerberos 5 support */
+krb5_error_code kssl_ctx_setstring(KSSL_CTX *kssl_ctx, int which, char *text);
+KSSL_CTX *kssl_ctx_new(void);
+KSSL_CTX *kssl_ctx_free(KSSL_CTX *kssl_ctx);
+void kssl_ctx_show(KSSL_CTX *kssl_ctx);
+krb5_error_code kssl_ctx_setprinc(KSSL_CTX *kssl_ctx, int which,
+        krb5_data *realm, krb5_data *entity, int nentities);
+krb5_error_code	kssl_cget_tkt(KSSL_CTX *kssl_ctx,  krb5_data **enc_tktp,
+        krb5_data *authenp, KSSL_ERR *kssl_err);
+krb5_error_code	kssl_sget_tkt(KSSL_CTX *kssl_ctx,  krb5_data *indata,
+        krb5_ticket_times *ttimes, KSSL_ERR *kssl_err);
+krb5_error_code kssl_ctx_setkey(KSSL_CTX *kssl_ctx, krb5_keyblock *session);
+void	kssl_err_set(KSSL_ERR *kssl_err, int reason, char *text);
+void kssl_krb5_free_data_contents(krb5_context context, krb5_data *data);
+krb5_error_code  kssl_build_principal_2(krb5_context context,
+			krb5_principal *princ, int rlen, const char *realm,
+			int slen, const char *svc, int hlen, const char *host);
+krb5_error_code  kssl_validate_times(krb5_timestamp atime,
+					krb5_ticket_times *ttimes);
+krb5_error_code  kssl_check_authent(KSSL_CTX *kssl_ctx, krb5_data *authentp,
+			            krb5_timestamp *atimep, KSSL_ERR *kssl_err);
+unsigned char	*kssl_skip_confound(krb5_enctype enctype, unsigned char *authn);
+
+#ifdef  __cplusplus
+}
+#endif
+#endif	/* OPENSSL_NO_KRB5	*/
+#endif	/* KSSL_H 	*/
diff --git a/lib/openssl/ssl/kssl_lcl.h b/lib/openssl/ssl/kssl_lcl.h
new file mode 100644
index 0000000..c039c91
--- /dev/null
+++ b/lib/openssl/ssl/kssl_lcl.h
@@ -0,0 +1,87 @@
+/* ssl/kssl.h -*- mode: C; c-file-style: "eay" -*- */
+/* Written by Vern Staats <staatsvr@asc.hpc.mil> for the OpenSSL project 2000.
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef	KSSL_LCL_H
+#define	KSSL_LCL_H
+
+#include <openssl/kssl.h>
+
+#ifndef OPENSSL_NO_KRB5
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* Private (internal to OpenSSL) */
+void print_krb5_data(char *label, krb5_data *kdata);
+void print_krb5_authdata(char *label, krb5_authdata **adata);
+void print_krb5_keyblock(char *label, krb5_keyblock *keyblk);
+
+char *kstring(char *string);
+char *knumber(int len, krb5_octet *contents);
+
+const EVP_CIPHER *kssl_map_enc(krb5_enctype enctype);
+
+int kssl_keytab_is_available(KSSL_CTX *kssl_ctx);
+int kssl_tgt_is_available(KSSL_CTX *kssl_ctx);
+
+#ifdef  __cplusplus
+}
+#endif
+#endif	/* OPENSSL_NO_KRB5	*/
+#endif	/* KSSL_LCL_H 	*/
diff --git a/lib/openssl/ssl/s23_clnt.c b/lib/openssl/ssl/s23_clnt.c
new file mode 100644
index 0000000..f41fe3a
--- /dev/null
+++ b/lib/openssl/ssl/s23_clnt.c
@@ -0,0 +1,703 @@
+/* ssl/s23_clnt.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <stdio.h>
+#include "ssl_locl.h"
+#include <openssl/buffer.h>
+#include <openssl/rand.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+
+static const SSL_METHOD *ssl23_get_client_method(int ver);
+static int ssl23_client_hello(SSL *s);
+static int ssl23_get_server_hello(SSL *s);
+static const SSL_METHOD *ssl23_get_client_method(int ver)
+	{
+#ifndef OPENSSL_NO_SSL2
+	if (ver == SSL2_VERSION)
+		return(SSLv2_client_method());
+#endif
+	if (ver == SSL3_VERSION)
+		return(SSLv3_client_method());
+	else if (ver == TLS1_VERSION)
+		return(TLSv1_client_method());
+	else
+		return(NULL);
+	}
+
+IMPLEMENT_ssl23_meth_func(SSLv23_client_method,
+			ssl_undefined_function,
+			ssl23_connect,
+			ssl23_get_client_method)
+
+int ssl23_connect(SSL *s)
+	{
+	BUF_MEM *buf=NULL;
+	unsigned long Time=(unsigned long)time(NULL);
+	void (*cb)(const SSL *ssl,int type,int val)=NULL;
+	int ret= -1;
+	int new_state,state;
+
+	RAND_add(&Time,sizeof(Time),0);
+	ERR_clear_error();
+	clear_sys_error();
+
+	if (s->info_callback != NULL)
+		cb=s->info_callback;
+	else if (s->ctx->info_callback != NULL)
+		cb=s->ctx->info_callback;
+	
+	s->in_handshake++;
+	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); 
+
+	for (;;)
+		{
+		state=s->state;
+
+		switch(s->state)
+			{
+		case SSL_ST_BEFORE:
+		case SSL_ST_CONNECT:
+		case SSL_ST_BEFORE|SSL_ST_CONNECT:
+		case SSL_ST_OK|SSL_ST_CONNECT:
+
+			if (s->session != NULL)
+				{
+				SSLerr(SSL_F_SSL23_CONNECT,SSL_R_SSL23_DOING_SESSION_ID_REUSE);
+				ret= -1;
+				goto end;
+				}
+			s->server=0;
+			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
+
+			/* s->version=TLS1_VERSION; */
+			s->type=SSL_ST_CONNECT;
+
+			if (s->init_buf == NULL)
+				{
+				if ((buf=BUF_MEM_new()) == NULL)
+					{
+					ret= -1;
+					goto end;
+					}
+				if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH))
+					{
+					ret= -1;
+					goto end;
+					}
+				s->init_buf=buf;
+				buf=NULL;
+				}
+
+			if (!ssl3_setup_buffers(s)) { ret= -1; goto end; }
+
+			ssl3_init_finished_mac(s);
+
+			s->state=SSL23_ST_CW_CLNT_HELLO_A;
+			s->ctx->stats.sess_connect++;
+			s->init_num=0;
+			break;
+
+		case SSL23_ST_CW_CLNT_HELLO_A:
+		case SSL23_ST_CW_CLNT_HELLO_B:
+
+			s->shutdown=0;
+			ret=ssl23_client_hello(s);
+			if (ret <= 0) goto end;
+			s->state=SSL23_ST_CR_SRVR_HELLO_A;
+			s->init_num=0;
+
+			break;
+
+		case SSL23_ST_CR_SRVR_HELLO_A:
+		case SSL23_ST_CR_SRVR_HELLO_B:
+			ret=ssl23_get_server_hello(s);
+			if (ret >= 0) cb=NULL;
+			goto end;
+			/* break; */
+
+		default:
+			SSLerr(SSL_F_SSL23_CONNECT,SSL_R_UNKNOWN_STATE);
+			ret= -1;
+			goto end;
+			/* break; */
+			}
+
+		if (s->debug) { (void)BIO_flush(s->wbio); }
+
+		if ((cb != NULL) && (s->state != state))
+			{
+			new_state=s->state;
+			s->state=state;
+			cb(s,SSL_CB_CONNECT_LOOP,1);
+			s->state=new_state;
+			}
+		}
+end:
+	s->in_handshake--;
+	if (buf != NULL)
+		BUF_MEM_free(buf);
+	if (cb != NULL)
+		cb(s,SSL_CB_CONNECT_EXIT,ret);
+	return(ret);
+	}
+
+static int ssl23_no_ssl2_ciphers(SSL *s)
+	{
+	SSL_CIPHER *cipher;
+	STACK_OF(SSL_CIPHER) *ciphers;
+	int i;
+	ciphers = SSL_get_ciphers(s);
+	for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++)
+		{
+		cipher = sk_SSL_CIPHER_value(ciphers, i);
+		if (cipher->algorithm_ssl == SSL_SSLV2)
+			return 0;
+		}
+	return 1;
+	}
+
+static int ssl23_client_hello(SSL *s)
+	{
+	unsigned char *buf;
+	unsigned char *p,*d;
+	int i,ch_len;
+	unsigned long Time,l;
+	int ssl2_compat;
+	int version = 0, version_major, version_minor;
+#ifndef OPENSSL_NO_COMP
+	int j;
+	SSL_COMP *comp;
+#endif
+	int ret;
+
+	ssl2_compat = (s->options & SSL_OP_NO_SSLv2) ? 0 : 1;
+
+	if (ssl2_compat && ssl23_no_ssl2_ciphers(s))
+		ssl2_compat = 0;
+
+	if (!(s->options & SSL_OP_NO_TLSv1))
+		{
+		version = TLS1_VERSION;
+		}
+	else if (!(s->options & SSL_OP_NO_SSLv3))
+		{
+		version = SSL3_VERSION;
+		}
+	else if (!(s->options & SSL_OP_NO_SSLv2))
+		{
+		version = SSL2_VERSION;
+		}
+#ifndef OPENSSL_NO_TLSEXT
+	if (version != SSL2_VERSION)
+		{
+		/* have to disable SSL 2.0 compatibility if we need TLS extensions */
+
+		if (s->tlsext_hostname != NULL)
+			ssl2_compat = 0;
+		if (s->tlsext_status_type != -1)
+			ssl2_compat = 0;
+#ifdef TLSEXT_TYPE_opaque_prf_input
+		if (s->ctx->tlsext_opaque_prf_input_callback != 0 || s->tlsext_opaque_prf_input != NULL)
+			ssl2_compat = 0;
+#endif
+		}
+#endif
+
+	buf=(unsigned char *)s->init_buf->data;
+	if (s->state == SSL23_ST_CW_CLNT_HELLO_A)
+		{
+#if 0
+		/* don't reuse session-id's */
+		if (!ssl_get_new_session(s,0))
+			{
+			return(-1);
+			}
+#endif
+
+		p=s->s3->client_random;
+		Time=(unsigned long)time(NULL);		/* Time */
+		l2n(Time,p);
+		if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
+			return -1;
+
+		if (version == TLS1_VERSION)
+			{
+			version_major = TLS1_VERSION_MAJOR;
+			version_minor = TLS1_VERSION_MINOR;
+			}
+		else if (version == SSL3_VERSION)
+			{
+			version_major = SSL3_VERSION_MAJOR;
+			version_minor = SSL3_VERSION_MINOR;
+			}
+		else if (version == SSL2_VERSION)
+			{
+			version_major = SSL2_VERSION_MAJOR;
+			version_minor = SSL2_VERSION_MINOR;
+			}
+		else
+			{
+			SSLerr(SSL_F_SSL23_CLIENT_HELLO,SSL_R_NO_PROTOCOLS_AVAILABLE);
+			return(-1);
+			}
+
+		s->client_version = version;
+
+		if (ssl2_compat)
+			{
+			/* create SSL 2.0 compatible Client Hello */
+
+			/* two byte record header will be written last */
+			d = &(buf[2]);
+			p = d + 9; /* leave space for message type, version, individual length fields */
+
+			*(d++) = SSL2_MT_CLIENT_HELLO;
+			*(d++) = version_major;
+			*(d++) = version_minor;
+			
+			/* Ciphers supported */
+			i=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),p,0);
+			if (i == 0)
+				{
+				/* no ciphers */
+				SSLerr(SSL_F_SSL23_CLIENT_HELLO,SSL_R_NO_CIPHERS_AVAILABLE);
+				return -1;
+				}
+			s2n(i,d);
+			p+=i;
+			
+			/* put in the session-id length (zero since there is no reuse) */
+#if 0
+			s->session->session_id_length=0;
+#endif
+			s2n(0,d);
+
+			if (s->options & SSL_OP_NETSCAPE_CHALLENGE_BUG)
+				ch_len=SSL2_CHALLENGE_LENGTH;
+			else
+				ch_len=SSL2_MAX_CHALLENGE_LENGTH;
+
+			/* write out sslv2 challenge */
+			/* Note that ch_len must be <= SSL3_RANDOM_SIZE (32),
+			   because it is one of SSL2_MAX_CHALLENGE_LENGTH (32)
+			   or SSL2_MAX_CHALLENGE_LENGTH (16), but leave the
+			   check in for futurproofing */
+			if (SSL3_RANDOM_SIZE < ch_len)
+				i=SSL3_RANDOM_SIZE;
+			else
+				i=ch_len;
+			s2n(i,d);
+			memset(&(s->s3->client_random[0]),0,SSL3_RANDOM_SIZE);
+			if (RAND_pseudo_bytes(&(s->s3->client_random[SSL3_RANDOM_SIZE-i]),i) <= 0)
+				return -1;
+
+			memcpy(p,&(s->s3->client_random[SSL3_RANDOM_SIZE-i]),i);
+			p+=i;
+
+			i= p- &(buf[2]);
+			buf[0]=((i>>8)&0xff)|0x80;
+			buf[1]=(i&0xff);
+
+			/* number of bytes to write */
+			s->init_num=i+2;
+			s->init_off=0;
+
+			ssl3_finish_mac(s,&(buf[2]),i);
+			}
+		else
+			{
+			/* create Client Hello in SSL 3.0/TLS 1.0 format */
+
+			/* do the record header (5 bytes) and handshake message header (4 bytes) last */
+			d = p = &(buf[9]);
+			
+			*(p++) = version_major;
+			*(p++) = version_minor;
+
+			/* Random stuff */
+			memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE);
+			p += SSL3_RANDOM_SIZE;
+
+			/* Session ID (zero since there is no reuse) */
+			*(p++) = 0;
+
+			/* Ciphers supported (using SSL 3.0/TLS 1.0 format) */
+			i=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),&(p[2]),ssl3_put_cipher_by_char);
+			if (i == 0)
+				{
+				SSLerr(SSL_F_SSL23_CLIENT_HELLO,SSL_R_NO_CIPHERS_AVAILABLE);
+				return -1;
+				}
+			s2n(i,p);
+			p+=i;
+
+			/* COMPRESSION */
+#ifdef OPENSSL_NO_COMP
+			*(p++)=1;
+#else
+			if ((s->options & SSL_OP_NO_COMPRESSION)
+						|| !s->ctx->comp_methods)
+				j=0;
+			else
+				j=sk_SSL_COMP_num(s->ctx->comp_methods);
+			*(p++)=1+j;
+			for (i=0; i<j; i++)
+				{
+				comp=sk_SSL_COMP_value(s->ctx->comp_methods,i);
+				*(p++)=comp->id;
+				}
+#endif
+			*(p++)=0; /* Add the NULL method */
+
+#ifndef OPENSSL_NO_TLSEXT
+			/* TLS extensions*/
+			if (ssl_prepare_clienthello_tlsext(s) <= 0)
+				{
+				SSLerr(SSL_F_SSL23_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
+				return -1;
+				}
+			if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
+				{
+				SSLerr(SSL_F_SSL23_CLIENT_HELLO,ERR_R_INTERNAL_ERROR);
+				return -1;
+				}
+#endif
+			
+			l = p-d;
+
+			/* fill in 4-byte handshake header */
+			d=&(buf[5]);
+			*(d++)=SSL3_MT_CLIENT_HELLO;
+			l2n3(l,d);
+
+			l += 4;
+
+			if (l > SSL3_RT_MAX_PLAIN_LENGTH)
+				{
+				SSLerr(SSL_F_SSL23_CLIENT_HELLO,ERR_R_INTERNAL_ERROR);
+				return -1;
+				}
+			
+			/* fill in 5-byte record header */
+			d=buf;
+			*(d++) = SSL3_RT_HANDSHAKE;
+			*(d++) = version_major;
+			*(d++) = version_minor; /* arguably we should send the *lowest* suported version here
+			                         * (indicating, e.g., TLS 1.0 in "SSL 3.0 format") */
+			s2n((int)l,d);
+
+			/* number of bytes to write */
+			s->init_num=p-buf;
+			s->init_off=0;
+
+			ssl3_finish_mac(s,&(buf[5]), s->init_num - 5);
+			}
+
+		s->state=SSL23_ST_CW_CLNT_HELLO_B;
+		s->init_off=0;
+		}
+
+	/* SSL3_ST_CW_CLNT_HELLO_B */
+	ret = ssl23_write_bytes(s);
+
+	if ((ret >= 2) && s->msg_callback)
+		{
+		/* Client Hello has been sent; tell msg_callback */
+
+		if (ssl2_compat)
+			s->msg_callback(1, SSL2_VERSION, 0, s->init_buf->data+2, ret-2, s, s->msg_callback_arg);
+		else
+			s->msg_callback(1, version, SSL3_RT_HANDSHAKE, s->init_buf->data+5, ret-5, s, s->msg_callback_arg);
+		}
+
+	return ret;
+	}
+
+static int ssl23_get_server_hello(SSL *s)
+	{
+	char buf[8];
+	unsigned char *p;
+	int i;
+	int n;
+
+	n=ssl23_read_bytes(s,7);
+
+	if (n != 7) return(n);
+	p=s->packet;
+
+	memcpy(buf,p,n);
+
+	if ((p[0] & 0x80) && (p[2] == SSL2_MT_SERVER_HELLO) &&
+		(p[5] == 0x00) && (p[6] == 0x02))
+		{
+#ifdef OPENSSL_NO_SSL2
+		SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_PROTOCOL);
+		goto err;
+#else
+		/* we are talking sslv2 */
+		/* we need to clean up the SSLv3 setup and put in the
+		 * sslv2 stuff. */
+		int ch_len;
+
+		if (s->options & SSL_OP_NO_SSLv2)
+			{
+			SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_PROTOCOL);
+			goto err;
+			}
+		if (s->s2 == NULL)
+			{
+			if (!ssl2_new(s))
+				goto err;
+			}
+		else
+			ssl2_clear(s);
+
+		if (s->options & SSL_OP_NETSCAPE_CHALLENGE_BUG)
+			ch_len=SSL2_CHALLENGE_LENGTH;
+		else
+			ch_len=SSL2_MAX_CHALLENGE_LENGTH;
+
+		/* write out sslv2 challenge */
+		/* Note that ch_len must be <= SSL3_RANDOM_SIZE (32), because
+		   it is one of SSL2_MAX_CHALLENGE_LENGTH (32) or
+		   SSL2_MAX_CHALLENGE_LENGTH (16), but leave the check in for
+		   futurproofing */
+		i=(SSL3_RANDOM_SIZE < ch_len)
+			?SSL3_RANDOM_SIZE:ch_len;
+		s->s2->challenge_length=i;
+		memcpy(s->s2->challenge,
+			&(s->s3->client_random[SSL3_RANDOM_SIZE-i]),i);
+
+		if (s->s3 != NULL) ssl3_free(s);
+
+		if (!BUF_MEM_grow_clean(s->init_buf,
+			SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER))
+			{
+			SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,ERR_R_BUF_LIB);
+			goto err;
+			}
+
+		s->state=SSL2_ST_GET_SERVER_HELLO_A;
+		if (!(s->client_version == SSL2_VERSION))
+			/* use special padding (SSL 3.0 draft/RFC 2246, App. E.2) */
+			s->s2->ssl2_rollback=1;
+
+		/* setup the 7 bytes we have read so we get them from
+		 * the sslv2 buffer */
+		s->rstate=SSL_ST_READ_HEADER;
+		s->packet_length=n;
+		s->packet= &(s->s2->rbuf[0]);
+		memcpy(s->packet,buf,n);
+		s->s2->rbuf_left=n;
+		s->s2->rbuf_offs=0;
+
+		/* we have already written one */
+		s->s2->write_sequence=1;
+
+		s->method=SSLv2_client_method();
+		s->handshake_func=s->method->ssl_connect;
+#endif
+		}
+	else if (p[1] == SSL3_VERSION_MAJOR &&
+	         (p[2] == SSL3_VERSION_MINOR || p[2] == TLS1_VERSION_MINOR) &&
+	         ((p[0] == SSL3_RT_HANDSHAKE && p[5] == SSL3_MT_SERVER_HELLO) ||
+	          (p[0] == SSL3_RT_ALERT && p[3] == 0 && p[4] == 2)))
+		{
+		/* we have sslv3 or tls1 (server hello or alert) */
+
+		if ((p[2] == SSL3_VERSION_MINOR) &&
+			!(s->options & SSL_OP_NO_SSLv3))
+			{
+			s->version=SSL3_VERSION;
+			s->method=SSLv3_client_method();
+			}
+		else if ((p[2] == TLS1_VERSION_MINOR) &&
+			!(s->options & SSL_OP_NO_TLSv1))
+			{
+			s->version=TLS1_VERSION;
+			s->method=TLSv1_client_method();
+			}
+		else
+			{
+			SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_PROTOCOL);
+			goto err;
+			}
+
+		if (p[0] == SSL3_RT_ALERT && p[5] != SSL3_AL_WARNING)
+			{
+			/* fatal alert */
+
+			void (*cb)(const SSL *ssl,int type,int val)=NULL;
+			int j;
+
+			if (s->info_callback != NULL)
+				cb=s->info_callback;
+			else if (s->ctx->info_callback != NULL)
+				cb=s->ctx->info_callback;
+ 
+			i=p[5];
+			if (cb != NULL)
+				{
+				j=(i<<8)|p[6];
+				cb(s,SSL_CB_READ_ALERT,j);
+				}
+			
+			if (s->msg_callback)
+				s->msg_callback(0, s->version, SSL3_RT_ALERT, p+5, 2, s, s->msg_callback_arg);
+
+			s->rwstate=SSL_NOTHING;
+			SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_AD_REASON_OFFSET+p[6]);
+			goto err;
+			}
+
+		if (!ssl_init_wbio_buffer(s,1)) goto err;
+
+		/* we are in this state */
+		s->state=SSL3_ST_CR_SRVR_HELLO_A;
+
+		/* put the 7 bytes we have read into the input buffer
+		 * for SSLv3 */
+		s->rstate=SSL_ST_READ_HEADER;
+		s->packet_length=n;
+		if (s->s3->rbuf.buf == NULL)
+			if (!ssl3_setup_read_buffer(s))
+				goto err;
+		s->packet= &(s->s3->rbuf.buf[0]);
+		memcpy(s->packet,buf,n);
+		s->s3->rbuf.left=n;
+		s->s3->rbuf.offset=0;
+
+		s->handshake_func=s->method->ssl_connect;
+		}
+	else
+		{
+		SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_UNKNOWN_PROTOCOL);
+		goto err;
+		}
+	s->init_num=0;
+
+	/* Since, if we are sending a ssl23 client hello, we are not
+	 * reusing a session-id */
+        if (!s->session_creation_enabled)
+		{
+		if (!(s->client_version == SSL2_VERSION))
+			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
+		SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_SESSION_MAY_NOT_BE_CREATED);
+		goto err;
+		}
+	if (!ssl_get_new_session(s,0))
+		goto err;
+
+	return(SSL_connect(s));
+err:
+	return(-1);
+	}
diff --git a/lib/openssl/ssl/s23_lib.c b/lib/openssl/ssl/s23_lib.c
new file mode 100644
index 0000000..e3fce53
--- /dev/null
+++ b/lib/openssl/ssl/s23_lib.c
@@ -0,0 +1,194 @@
+/* ssl/s23_lib.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include <openssl/objects.h>
+#include "ssl_locl.h"
+
+long ssl23_default_timeout(void)
+	{
+	return(300);
+	}
+
+int ssl23_num_ciphers(void)
+	{
+	return(ssl3_num_ciphers()
+#ifndef OPENSSL_NO_SSL2
+	       + ssl2_num_ciphers()
+#endif
+	    );
+	}
+
+const SSL_CIPHER *ssl23_get_cipher(unsigned int u)
+	{
+	unsigned int uu=ssl3_num_ciphers();
+
+	if (u < uu)
+		return(ssl3_get_cipher(u));
+	else
+#ifndef OPENSSL_NO_SSL2
+		return(ssl2_get_cipher(u-uu));
+#else
+		return(NULL);
+#endif
+	}
+
+/* This function needs to check if the ciphers required are actually
+ * available */
+const SSL_CIPHER *ssl23_get_cipher_by_char(const unsigned char *p)
+	{
+	SSL_CIPHER c;
+	const SSL_CIPHER *cp;
+	unsigned long id;
+	int n;
+
+	n=ssl3_num_ciphers();
+	id=0x03000000|((unsigned long)p[0]<<16L)|
+		((unsigned long)p[1]<<8L)|(unsigned long)p[2];
+	c.id=id;
+	cp=ssl3_get_cipher_by_char(p);
+#ifndef OPENSSL_NO_SSL2
+	if (cp == NULL)
+		cp=ssl2_get_cipher_by_char(p);
+#endif
+	return(cp);
+	}
+
+int ssl23_put_cipher_by_char(const SSL_CIPHER *c, unsigned char *p)
+	{
+	long l;
+
+	/* We can write SSLv2 and SSLv3 ciphers */
+	if (p != NULL)
+		{
+		l=c->id;
+		p[0]=((unsigned char)(l>>16L))&0xFF;
+		p[1]=((unsigned char)(l>> 8L))&0xFF;
+		p[2]=((unsigned char)(l     ))&0xFF;
+		}
+	return(3);
+	}
+
+int ssl23_read(SSL *s, void *buf, int len)
+	{
+	int n;
+
+	clear_sys_error();
+	if (SSL_in_init(s) && (!s->in_handshake))
+		{
+		n=s->handshake_func(s);
+		if (n < 0) return(n);
+		if (n == 0)
+			{
+			SSLerr(SSL_F_SSL23_READ,SSL_R_SSL_HANDSHAKE_FAILURE);
+			return(-1);
+			}
+		return(SSL_read(s,buf,len));
+		}
+	else
+		{
+		ssl_undefined_function(s);
+		return(-1);
+		}
+	}
+
+int ssl23_peek(SSL *s, void *buf, int len)
+	{
+	int n;
+
+	clear_sys_error();
+	if (SSL_in_init(s) && (!s->in_handshake))
+		{
+		n=s->handshake_func(s);
+		if (n < 0) return(n);
+		if (n == 0)
+			{
+			SSLerr(SSL_F_SSL23_PEEK,SSL_R_SSL_HANDSHAKE_FAILURE);
+			return(-1);
+			}
+		return(SSL_peek(s,buf,len));
+		}
+	else
+		{
+		ssl_undefined_function(s);
+		return(-1);
+		}
+	}
+
+int ssl23_write(SSL *s, const void *buf, int len)
+	{
+	int n;
+
+	clear_sys_error();
+	if (SSL_in_init(s) && (!s->in_handshake))
+		{
+		n=s->handshake_func(s);
+		if (n < 0) return(n);
+		if (n == 0)
+			{
+			SSLerr(SSL_F_SSL23_WRITE,SSL_R_SSL_HANDSHAKE_FAILURE);
+			return(-1);
+			}
+		return(SSL_write(s,buf,len));
+		}
+	else
+		{
+		ssl_undefined_function(s);
+		return(-1);
+		}
+	}
diff --git a/lib/openssl/ssl/s23_meth.c b/lib/openssl/ssl/s23_meth.c
new file mode 100644
index 0000000..c6099ef
--- /dev/null
+++ b/lib/openssl/ssl/s23_meth.c
@@ -0,0 +1,88 @@
+/* ssl/s23_meth.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include <openssl/objects.h>
+#include "ssl_locl.h"
+
+static const SSL_METHOD *ssl23_get_method(int ver);
+static const SSL_METHOD *ssl23_get_method(int ver)
+	{
+#ifndef OPENSSL_NO_SSL2
+	if (ver == SSL2_VERSION)
+		return(SSLv2_method());
+	else
+#endif
+#ifndef OPENSSL_NO_SSL3
+	if (ver == SSL3_VERSION)
+		return(SSLv3_method());
+	else
+#endif
+#ifndef OPENSSL_NO_TLS1
+	if (ver == TLS1_VERSION)
+		return(TLSv1_method());
+	else
+#endif
+		return(NULL);
+	}
+
+IMPLEMENT_ssl23_meth_func(SSLv23_method,
+			ssl23_accept,
+			ssl23_connect,
+			ssl23_get_method)
+
diff --git a/lib/openssl/ssl/s23_pkt.c b/lib/openssl/ssl/s23_pkt.c
new file mode 100644
index 0000000..4ca6a1b
--- /dev/null
+++ b/lib/openssl/ssl/s23_pkt.c
@@ -0,0 +1,117 @@
+/* ssl/s23_pkt.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#define USE_SOCKETS
+#include "ssl_locl.h"
+#include <openssl/evp.h>
+#include <openssl/buffer.h>
+
+int ssl23_write_bytes(SSL *s)
+	{
+	int i,num,tot;
+	char *buf;
+
+	buf=s->init_buf->data;
+	tot=s->init_off;
+	num=s->init_num;
+	for (;;)
+		{
+		s->rwstate=SSL_WRITING;
+		i=BIO_write(s->wbio,&(buf[tot]),num);
+		if (i <= 0)
+			{
+			s->init_off=tot;
+			s->init_num=num;
+			return(i);
+			}
+		s->rwstate=SSL_NOTHING;
+		if (i == num) return(tot+i);
+
+		num-=i;
+		tot+=i;
+		}
+	}
+
+/* return regularly only when we have read (at least) 'n' bytes */
+int ssl23_read_bytes(SSL *s, int n)
+	{
+	unsigned char *p;
+	int j;
+
+	if (s->packet_length < (unsigned int)n)
+		{
+		p=s->packet;
+
+		for (;;)
+			{
+			s->rwstate=SSL_READING;
+			j=BIO_read(s->rbio,(char *)&(p[s->packet_length]),
+				n-s->packet_length);
+			if (j <= 0)
+				return(j);
+			s->rwstate=SSL_NOTHING;
+			s->packet_length+=j;
+			if (s->packet_length >= (unsigned int)n)
+				return(s->packet_length);
+			}
+		}
+	return(n);
+	}
+
diff --git a/lib/openssl/ssl/s23_srvr.c b/lib/openssl/ssl/s23_srvr.c
new file mode 100644
index 0000000..e22879c
--- /dev/null
+++ b/lib/openssl/ssl/s23_srvr.c
@@ -0,0 +1,599 @@
+/* ssl/s23_srvr.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <stdio.h>
+#include "ssl_locl.h"
+#include <openssl/buffer.h>
+#include <openssl/rand.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+
+static const SSL_METHOD *ssl23_get_server_method(int ver);
+int ssl23_get_client_hello(SSL *s);
+static const SSL_METHOD *ssl23_get_server_method(int ver)
+	{
+#ifndef OPENSSL_NO_SSL2
+	if (ver == SSL2_VERSION)
+		return(SSLv2_server_method());
+#endif
+	if (ver == SSL3_VERSION)
+		return(SSLv3_server_method());
+	else if (ver == TLS1_VERSION)
+		return(TLSv1_server_method());
+	else
+		return(NULL);
+	}
+
+IMPLEMENT_ssl23_meth_func(SSLv23_server_method,
+			ssl23_accept,
+			ssl_undefined_function,
+			ssl23_get_server_method)
+
+int ssl23_accept(SSL *s)
+	{
+	BUF_MEM *buf;
+	unsigned long Time=(unsigned long)time(NULL);
+	void (*cb)(const SSL *ssl,int type,int val)=NULL;
+	int ret= -1;
+	int new_state,state;
+
+	RAND_add(&Time,sizeof(Time),0);
+	ERR_clear_error();
+	clear_sys_error();
+
+	if (s->info_callback != NULL)
+		cb=s->info_callback;
+	else if (s->ctx->info_callback != NULL)
+		cb=s->ctx->info_callback;
+	
+	s->in_handshake++;
+	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); 
+
+	for (;;)
+		{
+		state=s->state;
+
+		switch(s->state)
+			{
+		case SSL_ST_BEFORE:
+		case SSL_ST_ACCEPT:
+		case SSL_ST_BEFORE|SSL_ST_ACCEPT:
+		case SSL_ST_OK|SSL_ST_ACCEPT:
+
+			s->server=1;
+			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
+
+			/* s->version=SSL3_VERSION; */
+			s->type=SSL_ST_ACCEPT;
+
+			if (s->init_buf == NULL)
+				{
+				if ((buf=BUF_MEM_new()) == NULL)
+					{
+					ret= -1;
+					goto end;
+					}
+				if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH))
+					{
+					ret= -1;
+					goto end;
+					}
+				s->init_buf=buf;
+				}
+
+			ssl3_init_finished_mac(s);
+
+			s->state=SSL23_ST_SR_CLNT_HELLO_A;
+			s->ctx->stats.sess_accept++;
+			s->init_num=0;
+			break;
+
+		case SSL23_ST_SR_CLNT_HELLO_A:
+		case SSL23_ST_SR_CLNT_HELLO_B:
+
+			s->shutdown=0;
+			ret=ssl23_get_client_hello(s);
+			if (ret >= 0) cb=NULL;
+			goto end;
+			/* break; */
+
+		default:
+			SSLerr(SSL_F_SSL23_ACCEPT,SSL_R_UNKNOWN_STATE);
+			ret= -1;
+			goto end;
+			/* break; */
+			}
+
+		if ((cb != NULL) && (s->state != state))
+			{
+			new_state=s->state;
+			s->state=state;
+			cb(s,SSL_CB_ACCEPT_LOOP,1);
+			s->state=new_state;
+			}
+		}
+end:
+	s->in_handshake--;
+	if (cb != NULL)
+		cb(s,SSL_CB_ACCEPT_EXIT,ret);
+	return(ret);
+	}
+
+
+int ssl23_get_client_hello(SSL *s)
+	{
+	char buf_space[11]; /* Request this many bytes in initial read.
+	                     * We can detect SSL 3.0/TLS 1.0 Client Hellos
+	                     * ('type == 3') correctly only when the following
+	                     * is in a single record, which is not guaranteed by
+	                     * the protocol specification:
+	                     * Byte  Content
+	                     *  0     type            \
+	                     *  1/2   version          > record header
+	                     *  3/4   length          /
+	                     *  5     msg_type        \
+	                     *  6-8   length           > Client Hello message
+	                     *  9/10  client_version  /
+	                     */
+	char *buf= &(buf_space[0]);
+	unsigned char *p,*d,*d_len,*dd;
+	unsigned int i;
+	unsigned int csl,sil,cl;
+	int n=0,j;
+	int type=0;
+	int v[2];
+
+	if (s->state ==	SSL23_ST_SR_CLNT_HELLO_A)
+		{
+		/* read the initial header */
+		v[0]=v[1]=0;
+
+		if (!ssl3_setup_buffers(s)) goto err;
+
+		n=ssl23_read_bytes(s, sizeof buf_space);
+		if (n != sizeof buf_space) return(n); /* n == -1 || n == 0 */
+
+		p=s->packet;
+
+		memcpy(buf,p,n);
+
+		if ((p[0] & 0x80) && (p[2] == SSL2_MT_CLIENT_HELLO))
+			{
+			/*
+			 * SSLv2 header
+			 */
+			if ((p[3] == 0x00) && (p[4] == 0x02))
+				{
+				v[0]=p[3]; v[1]=p[4];
+				/* SSLv2 */
+				if (!(s->options & SSL_OP_NO_SSLv2))
+					type=1;
+				}
+			else if (p[3] == SSL3_VERSION_MAJOR)
+				{
+				v[0]=p[3]; v[1]=p[4];
+				/* SSLv3/TLSv1 */
+				if (p[4] >= TLS1_VERSION_MINOR)
+					{
+					if (!(s->options & SSL_OP_NO_TLSv1))
+						{
+						s->version=TLS1_VERSION;
+						/* type=2; */ /* done later to survive restarts */
+						s->state=SSL23_ST_SR_CLNT_HELLO_B;
+						}
+					else if (!(s->options & SSL_OP_NO_SSLv3))
+						{
+						s->version=SSL3_VERSION;
+						/* type=2; */
+						s->state=SSL23_ST_SR_CLNT_HELLO_B;
+						}
+					else if (!(s->options & SSL_OP_NO_SSLv2))
+						{
+						type=1;
+						}
+					}
+				else if (!(s->options & SSL_OP_NO_SSLv3))
+					{
+					s->version=SSL3_VERSION;
+					/* type=2; */
+					s->state=SSL23_ST_SR_CLNT_HELLO_B;
+					}
+				else if (!(s->options & SSL_OP_NO_SSLv2))
+					type=1;
+
+				}
+			}
+		else if ((p[0] == SSL3_RT_HANDSHAKE) &&
+			 (p[1] == SSL3_VERSION_MAJOR) &&
+			 (p[5] == SSL3_MT_CLIENT_HELLO) &&
+			 ((p[3] == 0 && p[4] < 5 /* silly record length? */)
+				|| (p[9] >= p[1])))
+			{
+			/*
+			 * SSLv3 or tls1 header
+			 */
+			
+			v[0]=p[1]; /* major version (= SSL3_VERSION_MAJOR) */
+			/* We must look at client_version inside the Client Hello message
+			 * to get the correct minor version.
+			 * However if we have only a pathologically small fragment of the
+			 * Client Hello message, this would be difficult, and we'd have
+			 * to read more records to find out.
+			 * No known SSL 3.0 client fragments ClientHello like this,
+			 * so we simply assume TLS 1.0 to avoid protocol version downgrade
+			 * attacks. */
+			if (p[3] == 0 && p[4] < 6)
+				{
+#if 0
+				SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_TOO_SMALL);
+				goto err;
+#else
+				v[1] = TLS1_VERSION_MINOR;
+#endif
+				}
+			/* if major version number > 3 set minor to a value
+			 * which will use the highest version 3 we support.
+			 * If TLS 2.0 ever appears we will need to revise
+			 * this....
+			 */
+			else if (p[9] > SSL3_VERSION_MAJOR)
+				v[1]=0xff;
+			else
+				v[1]=p[10]; /* minor version according to client_version */
+			if (v[1] >= TLS1_VERSION_MINOR)
+				{
+				if (!(s->options & SSL_OP_NO_TLSv1))
+					{
+					s->version=TLS1_VERSION;
+					type=3;
+					}
+				else if (!(s->options & SSL_OP_NO_SSLv3))
+					{
+					s->version=SSL3_VERSION;
+					type=3;
+					}
+				}
+			else
+				{
+				/* client requests SSL 3.0 */
+				if (!(s->options & SSL_OP_NO_SSLv3))
+					{
+					s->version=SSL3_VERSION;
+					type=3;
+					}
+				else if (!(s->options & SSL_OP_NO_TLSv1))
+					{
+					/* we won't be able to use TLS of course,
+					 * but this will send an appropriate alert */
+					s->version=TLS1_VERSION;
+					type=3;
+					}
+				}
+			}
+		else if ((strncmp("GET ", (char *)p,4) == 0) ||
+			 (strncmp("POST ",(char *)p,5) == 0) ||
+			 (strncmp("HEAD ",(char *)p,5) == 0) ||
+			 (strncmp("PUT ", (char *)p,4) == 0))
+			{
+			SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_HTTP_REQUEST);
+			goto err;
+			}
+		else if (strncmp("CONNECT",(char *)p,7) == 0)
+			{
+			SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_HTTPS_PROXY_REQUEST);
+			goto err;
+			}
+		}
+
+	if (s->state == SSL23_ST_SR_CLNT_HELLO_B)
+		{
+		/* we have SSLv3/TLSv1 in an SSLv2 header
+		 * (other cases skip this state) */
+
+		type=2;
+		p=s->packet;
+		v[0] = p[3]; /* == SSL3_VERSION_MAJOR */
+		v[1] = p[4];
+
+/* The SSL2 protocol allows n to be larger, just pick
+ * a reasonable buffer size. */
+#if SSL3_RT_DEFAULT_PACKET_SIZE < 1024*4 - SSL3_RT_DEFAULT_WRITE_OVERHEAD
+#error "SSL3_RT_DEFAULT_PACKET_SIZE is too small."
+#endif
+		n=((p[0]&0x7f)<<8)|p[1];
+		if (n > SSL3_RT_DEFAULT_PACKET_SIZE - 2)
+			{
+			SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_TOO_LARGE);
+			goto err;
+			}
+
+		j=ssl23_read_bytes(s,n+2);
+		if (j <= 0) return(j);
+
+		ssl3_finish_mac(s, s->packet+2, s->packet_length-2);
+		if (s->msg_callback)
+			s->msg_callback(0, SSL2_VERSION, 0, s->packet+2, s->packet_length-2, s, s->msg_callback_arg); /* CLIENT-HELLO */
+
+		p=s->packet;
+		p+=5;
+		n2s(p,csl);
+		n2s(p,sil);
+		n2s(p,cl);
+		d=(unsigned char *)s->init_buf->data;
+		if ((csl+sil+cl+11) != s->packet_length) /* We can't have TLS extensions in SSL 2.0 format
+		                                          * Client Hello, can we? Error condition should be
+		                                          * '>' otherweise */
+			{
+			SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_LENGTH_MISMATCH);
+			goto err;
+			}
+
+		/* record header: msg_type ... */
+		*(d++) = SSL3_MT_CLIENT_HELLO;
+		/* ... and length (actual value will be written later) */
+		d_len = d;
+		d += 3;
+
+		/* client_version */
+		*(d++) = SSL3_VERSION_MAJOR; /* == v[0] */
+		*(d++) = v[1];
+
+		/* lets populate the random area */
+		/* get the challenge_length */
+		i=(cl > SSL3_RANDOM_SIZE)?SSL3_RANDOM_SIZE:cl;
+		memset(d,0,SSL3_RANDOM_SIZE);
+		memcpy(&(d[SSL3_RANDOM_SIZE-i]),&(p[csl+sil]),i);
+		d+=SSL3_RANDOM_SIZE;
+
+		/* no session-id reuse */
+		*(d++)=0;
+
+		/* ciphers */
+		j=0;
+		dd=d;
+		d+=2;
+		for (i=0; i<csl; i+=3)
+			{
+			if (p[i] != 0) continue;
+			*(d++)=p[i+1];
+			*(d++)=p[i+2];
+			j+=2;
+			}
+		s2n(j,dd);
+
+		/* COMPRESSION */
+		*(d++)=1;
+		*(d++)=0;
+		
+#if 0
+                /* copy any remaining data with may be extensions */
+	        p = p+csl+sil+cl;
+		while (p <  s->packet+s->packet_length)
+			{
+			*(d++)=*(p++);
+			}
+#endif
+
+		i = (d-(unsigned char *)s->init_buf->data) - 4;
+		l2n3((long)i, d_len);
+
+		/* get the data reused from the init_buf */
+		s->s3->tmp.reuse_message=1;
+		s->s3->tmp.message_type=SSL3_MT_CLIENT_HELLO;
+		s->s3->tmp.message_size=i;
+		}
+
+	/* imaginary new state (for program structure): */
+	/* s->state = SSL23_SR_CLNT_HELLO_C */
+
+	if (type == 1)
+		{
+#ifdef OPENSSL_NO_SSL2
+		SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_UNSUPPORTED_PROTOCOL);
+		goto err;
+#else
+		/* we are talking sslv2 */
+		/* we need to clean up the SSLv3/TLSv1 setup and put in the
+		 * sslv2 stuff. */
+
+		if (s->s2 == NULL)
+			{
+			if (!ssl2_new(s))
+				goto err;
+			}
+		else
+			ssl2_clear(s);
+
+		if (s->s3 != NULL) ssl3_free(s);
+
+		if (!BUF_MEM_grow_clean(s->init_buf,
+			SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER))
+			{
+			goto err;
+			}
+
+		s->state=SSL2_ST_GET_CLIENT_HELLO_A;
+		if (s->options & SSL_OP_NO_TLSv1 && s->options & SSL_OP_NO_SSLv3)
+			s->s2->ssl2_rollback=0;
+		else
+			/* reject SSL 2.0 session if client supports SSL 3.0 or TLS 1.0
+			 * (SSL 3.0 draft/RFC 2246, App. E.2) */
+			s->s2->ssl2_rollback=1;
+
+		/* setup the n bytes we have read so we get them from
+		 * the sslv2 buffer */
+		s->rstate=SSL_ST_READ_HEADER;
+		s->packet_length=n;
+		s->packet= &(s->s2->rbuf[0]);
+		memcpy(s->packet,buf,n);
+		s->s2->rbuf_left=n;
+		s->s2->rbuf_offs=0;
+
+		s->method=SSLv2_server_method();
+		s->handshake_func=s->method->ssl_accept;
+#endif
+		}
+
+	if ((type == 2) || (type == 3))
+		{
+		/* we have SSLv3/TLSv1 (type 2: SSL2 style, type 3: SSL3/TLS style) */
+
+		if (!ssl_init_wbio_buffer(s,1)) goto err;
+
+		/* we are in this state */
+		s->state=SSL3_ST_SR_CLNT_HELLO_A;
+
+		if (type == 3)
+			{
+			/* put the 'n' bytes we have read into the input buffer
+			 * for SSLv3 */
+			s->rstate=SSL_ST_READ_HEADER;
+			s->packet_length=n;
+			if (s->s3->rbuf.buf == NULL)
+				if (!ssl3_setup_read_buffer(s))
+					goto err;
+
+			s->packet= &(s->s3->rbuf.buf[0]);
+			memcpy(s->packet,buf,n);
+			s->s3->rbuf.left=n;
+			s->s3->rbuf.offset=0;
+			}
+		else
+			{
+			s->packet_length=0;
+			s->s3->rbuf.left=0;
+			s->s3->rbuf.offset=0;
+			}
+
+		if (s->version == TLS1_VERSION)
+			s->method = TLSv1_server_method();
+		else
+			s->method = SSLv3_server_method();
+#if 0 /* ssl3_get_client_hello does this */
+		s->client_version=(v[0]<<8)|v[1];
+#endif
+		s->handshake_func=s->method->ssl_accept;
+		}
+	
+	if ((type < 1) || (type > 3))
+		{
+		/* bad, very bad */
+		SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_UNKNOWN_PROTOCOL);
+		goto err;
+		}
+	s->init_num=0;
+
+	if (buf != buf_space) OPENSSL_free(buf);
+	return(SSL_accept(s));
+err:
+	if (buf != buf_space) OPENSSL_free(buf);
+	return(-1);
+	}
diff --git a/lib/openssl/ssl/s2_clnt.c b/lib/openssl/ssl/s2_clnt.c
new file mode 100644
index 0000000..00ac158
--- /dev/null
+++ b/lib/openssl/ssl/s2_clnt.c
@@ -0,0 +1,1125 @@
+/* ssl/s2_clnt.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include "ssl_locl.h"
+#ifndef OPENSSL_NO_SSL2
+#include <stdio.h>
+#include <openssl/rand.h>
+#include <openssl/buffer.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+
+static const SSL_METHOD *ssl2_get_client_method(int ver);
+static int get_server_finished(SSL *s);
+static int get_server_verify(SSL *s);
+static int get_server_hello(SSL *s);
+static int client_hello(SSL *s); 
+static int client_master_key(SSL *s);
+static int client_finished(SSL *s);
+static int client_certificate(SSL *s);
+static int ssl_rsa_public_encrypt(SESS_CERT *sc, int len, unsigned char *from,
+	unsigned char *to,int padding);
+#define BREAK	break
+
+static const SSL_METHOD *ssl2_get_client_method(int ver)
+	{
+	if (ver == SSL2_VERSION)
+		return(SSLv2_client_method());
+	else
+		return(NULL);
+	}
+
+IMPLEMENT_ssl2_meth_func(SSLv2_client_method,
+			ssl_undefined_function,
+			ssl2_connect,
+			ssl2_get_client_method)
+
+int ssl2_connect(SSL *s)
+	{
+	unsigned long l=(unsigned long)time(NULL);
+	BUF_MEM *buf=NULL;
+	int ret= -1;
+	void (*cb)(const SSL *ssl,int type,int val)=NULL;
+	int new_state,state;
+
+	RAND_add(&l,sizeof(l),0);
+	ERR_clear_error();
+	clear_sys_error();
+
+	if (s->info_callback != NULL)
+		cb=s->info_callback;
+	else if (s->ctx->info_callback != NULL)
+		cb=s->ctx->info_callback;
+
+	/* init things to blank */
+	s->in_handshake++;
+	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);
+
+	for (;;)
+		{
+		state=s->state;
+
+		switch (s->state)
+			{
+		case SSL_ST_BEFORE:
+		case SSL_ST_CONNECT:
+		case SSL_ST_BEFORE|SSL_ST_CONNECT:
+		case SSL_ST_OK|SSL_ST_CONNECT:
+
+			s->server=0;
+			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
+
+			s->version=SSL2_VERSION;
+			s->type=SSL_ST_CONNECT;
+
+			buf=s->init_buf;
+			if ((buf == NULL) && ((buf=BUF_MEM_new()) == NULL))
+				{
+				ret= -1;
+				goto end;
+				}
+			if (!BUF_MEM_grow(buf,
+				SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER))
+				{
+				if (buf == s->init_buf)
+					buf=NULL;
+				ret= -1;
+				goto end;
+				}
+			s->init_buf=buf;
+			buf=NULL;
+			s->init_num=0;
+			s->state=SSL2_ST_SEND_CLIENT_HELLO_A;
+			s->ctx->stats.sess_connect++;
+			s->handshake_func=ssl2_connect;
+			BREAK;
+
+		case SSL2_ST_SEND_CLIENT_HELLO_A:
+		case SSL2_ST_SEND_CLIENT_HELLO_B:
+			s->shutdown=0;
+			ret=client_hello(s);
+			if (ret <= 0) goto end;
+			s->init_num=0;
+			s->state=SSL2_ST_GET_SERVER_HELLO_A;
+			BREAK;
+		
+		case SSL2_ST_GET_SERVER_HELLO_A:
+		case SSL2_ST_GET_SERVER_HELLO_B:
+			ret=get_server_hello(s);
+			if (ret <= 0) goto end;
+			s->init_num=0;
+			if (!s->hit) /* new session */
+				{
+				s->state=SSL2_ST_SEND_CLIENT_MASTER_KEY_A;
+				BREAK; 
+				}
+			else
+				{
+				s->state=SSL2_ST_CLIENT_START_ENCRYPTION;
+				break;
+				}
+	
+		case SSL2_ST_SEND_CLIENT_MASTER_KEY_A:
+		case SSL2_ST_SEND_CLIENT_MASTER_KEY_B:
+			ret=client_master_key(s);
+			if (ret <= 0) goto end;
+			s->init_num=0;
+			s->state=SSL2_ST_CLIENT_START_ENCRYPTION;
+			break;
+
+		case SSL2_ST_CLIENT_START_ENCRYPTION:
+			/* Ok, we now have all the stuff needed to
+			 * start encrypting, so lets fire it up :-) */
+			if (!ssl2_enc_init(s,1))
+				{
+				ret= -1;
+				goto end;
+				}
+			s->s2->clear_text=0;
+			s->state=SSL2_ST_SEND_CLIENT_FINISHED_A;
+			break;
+
+		case SSL2_ST_SEND_CLIENT_FINISHED_A:
+		case SSL2_ST_SEND_CLIENT_FINISHED_B:
+			ret=client_finished(s);
+			if (ret <= 0) goto end;
+			s->init_num=0;
+			s->state=SSL2_ST_GET_SERVER_VERIFY_A;
+			break;
+
+		case SSL2_ST_GET_SERVER_VERIFY_A:
+		case SSL2_ST_GET_SERVER_VERIFY_B:
+			ret=get_server_verify(s);
+			if (ret <= 0) goto end;
+			s->init_num=0;
+			s->state=SSL2_ST_GET_SERVER_FINISHED_A;
+			break;
+
+		case SSL2_ST_GET_SERVER_FINISHED_A:
+		case SSL2_ST_GET_SERVER_FINISHED_B:
+			ret=get_server_finished(s);
+			if (ret <= 0) goto end;
+			break;
+
+		case SSL2_ST_SEND_CLIENT_CERTIFICATE_A:
+		case SSL2_ST_SEND_CLIENT_CERTIFICATE_B:
+		case SSL2_ST_SEND_CLIENT_CERTIFICATE_C:
+		case SSL2_ST_SEND_CLIENT_CERTIFICATE_D:
+		case SSL2_ST_X509_GET_CLIENT_CERTIFICATE:
+			ret=client_certificate(s);
+			if (ret <= 0) goto end;
+			s->init_num=0;
+			s->state=SSL2_ST_GET_SERVER_FINISHED_A;
+			break;
+
+		case SSL_ST_OK:
+			if (s->init_buf != NULL)
+				{
+				BUF_MEM_free(s->init_buf);
+				s->init_buf=NULL;
+				}
+			s->init_num=0;
+		/*	ERR_clear_error();*/
+
+			/* If we want to cache session-ids in the client
+			 * and we successfully add the session-id to the
+			 * cache, and there is a callback, then pass it out.
+			 * 26/11/96 - eay - only add if not a re-used session.
+			 */
+
+			ssl_update_cache(s,SSL_SESS_CACHE_CLIENT);
+			if (s->hit) s->ctx->stats.sess_hit++;
+
+			ret=1;
+			/* s->server=0; */
+			s->ctx->stats.sess_connect_good++;
+
+			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1);
+
+			goto end;
+			/* break; */
+		default:
+			SSLerr(SSL_F_SSL2_CONNECT,SSL_R_UNKNOWN_STATE);
+			return(-1);
+			/* break; */
+			}
+
+		if ((cb != NULL) && (s->state != state))
+			{
+			new_state=s->state;
+			s->state=state;
+			cb(s,SSL_CB_CONNECT_LOOP,1);
+			s->state=new_state;
+			}
+		}
+end:
+	s->in_handshake--;
+	if (buf != NULL)
+		BUF_MEM_free(buf);
+	if (cb != NULL) 
+		cb(s,SSL_CB_CONNECT_EXIT,ret);
+	return(ret);
+	}
+
+static int get_server_hello(SSL *s)
+	{
+	unsigned char *buf;
+	unsigned char *p;
+	int i,j;
+	unsigned long len;
+	STACK_OF(SSL_CIPHER) *sk=NULL,*cl, *prio, *allow;
+
+	buf=(unsigned char *)s->init_buf->data;
+	p=buf;
+	if (s->state == SSL2_ST_GET_SERVER_HELLO_A)
+		{
+		i=ssl2_read(s,(char *)&(buf[s->init_num]),11-s->init_num);
+		if (i < (11-s->init_num)) 
+			return(ssl2_part_read(s,SSL_F_GET_SERVER_HELLO,i));
+		s->init_num = 11;
+
+		if (*(p++) != SSL2_MT_SERVER_HELLO)
+			{
+			if (p[-1] != SSL2_MT_ERROR)
+				{
+				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+				SSLerr(SSL_F_GET_SERVER_HELLO,
+					SSL_R_READ_WRONG_PACKET_TYPE);
+				}
+			else
+				SSLerr(SSL_F_GET_SERVER_HELLO,
+					SSL_R_PEER_ERROR);
+			return(-1);
+			}
+#ifdef __APPLE_CC__
+		/* The Rhapsody 5.5 (a.k.a. MacOS X) compiler bug
+		 * workaround. <appro@fy.chalmers.se> */
+		s->hit=(i=*(p++))?1:0;
+#else
+		s->hit=(*(p++))?1:0;
+#endif
+		s->s2->tmp.cert_type= *(p++);
+		n2s(p,i);
+		if (i < s->version) s->version=i;
+		n2s(p,i); s->s2->tmp.cert_length=i;
+		n2s(p,i); s->s2->tmp.csl=i;
+		n2s(p,i); s->s2->tmp.conn_id_length=i;
+		s->state=SSL2_ST_GET_SERVER_HELLO_B;
+		}
+
+	/* SSL2_ST_GET_SERVER_HELLO_B */
+	len = 11 + (unsigned long)s->s2->tmp.cert_length + (unsigned long)s->s2->tmp.csl + (unsigned long)s->s2->tmp.conn_id_length;
+	if (len > SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER)
+		{
+		SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_MESSAGE_TOO_LONG);
+		return -1;
+		}
+	j = (int)len - s->init_num;
+	i = ssl2_read(s,(char *)&(buf[s->init_num]),j);
+	if (i != j) return(ssl2_part_read(s,SSL_F_GET_SERVER_HELLO,i));
+	if (s->msg_callback)
+		s->msg_callback(0, s->version, 0, buf, (size_t)len, s, s->msg_callback_arg); /* SERVER-HELLO */
+
+	/* things are looking good */
+
+	p = buf + 11;
+	if (s->hit)
+		{
+		if (s->s2->tmp.cert_length != 0) 
+			{
+			SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_REUSE_CERT_LENGTH_NOT_ZERO);
+			return(-1);
+			}
+		if (s->s2->tmp.cert_type != 0)
+			{
+			if (!(s->options &
+				SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG))
+				{
+				SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_REUSE_CERT_TYPE_NOT_ZERO);
+				return(-1);
+				}
+			}
+		if (s->s2->tmp.csl != 0)
+			{
+			SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_REUSE_CIPHER_LIST_NOT_ZERO);
+			return(-1);
+			}
+		}
+	else
+		{
+#ifdef undef
+		/* very bad */
+		memset(s->session->session_id,0,
+			SSL_MAX_SSL_SESSION_ID_LENGTH_IN_BYTES);
+		s->session->session_id_length=0;
+		*/
+#endif
+
+		/* we need to do this in case we were trying to reuse a 
+		 * client session but others are already reusing it.
+		 * If this was a new 'blank' session ID, the session-id
+		 * length will still be 0 */
+		if (s->session->session_id_length > 0)
+			{
+			if (!ssl_get_new_session(s,0))
+				{
+				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+				return(-1);
+				}
+			}
+
+		if (ssl2_set_certificate(s,s->s2->tmp.cert_type,
+			s->s2->tmp.cert_length,p) <= 0)
+			{
+			ssl2_return_error(s,SSL2_PE_BAD_CERTIFICATE);
+			return(-1);
+			}
+		p+=s->s2->tmp.cert_length;
+
+		if (s->s2->tmp.csl == 0)
+			{
+			ssl2_return_error(s,SSL2_PE_NO_CIPHER);
+			SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_NO_CIPHER_LIST);
+			return(-1);
+			}
+
+		/* We have just received a list of ciphers back from the
+		 * server.  We need to get the ones that match, then select
+		 * the one we want the most :-). */
+
+		/* load the ciphers */
+		sk=ssl_bytes_to_cipher_list(s,p,s->s2->tmp.csl,
+					    &s->session->ciphers);
+		p+=s->s2->tmp.csl;
+		if (sk == NULL)
+			{
+			ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+			SSLerr(SSL_F_GET_SERVER_HELLO,ERR_R_MALLOC_FAILURE);
+			return(-1);
+			}
+
+		(void)sk_SSL_CIPHER_set_cmp_func(sk,ssl_cipher_ptr_id_cmp);
+
+		/* get the array of ciphers we will accept */
+		cl=SSL_get_ciphers(s);
+		(void)sk_SSL_CIPHER_set_cmp_func(cl,ssl_cipher_ptr_id_cmp);
+
+		/*
+		 * If server preference flag set, choose the first
+		 * (highest priority) cipher the server sends, otherwise
+		 * client preference has priority.
+		 */
+		if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE)
+		    {
+		    prio = sk;
+		    allow = cl;
+		    }
+		else
+		    {
+		    prio = cl;
+		    allow = sk;
+		    }
+		/* In theory we could have ciphers sent back that we
+		 * don't want to use but that does not matter since we
+		 * will check against the list we originally sent and
+		 * for performance reasons we should not bother to match
+		 * the two lists up just to check. */
+		for (i=0; i<sk_SSL_CIPHER_num(prio); i++)
+			{
+			if (sk_SSL_CIPHER_find(allow,
+					     sk_SSL_CIPHER_value(prio,i)) >= 0)
+				break;
+			}
+
+		if (i >= sk_SSL_CIPHER_num(prio))
+			{
+			ssl2_return_error(s,SSL2_PE_NO_CIPHER);
+			SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_NO_CIPHER_MATCH);
+			return(-1);
+			}
+		s->session->cipher=sk_SSL_CIPHER_value(prio,i);
+
+
+		if (s->session->peer != NULL) /* can't happen*/
+			{
+			ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
+			SSLerr(SSL_F_GET_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
+			return(-1);
+			}
+
+		s->session->peer = s->session->sess_cert->peer_key->x509;
+		/* peer_key->x509 has been set by ssl2_set_certificate. */
+		CRYPTO_add(&s->session->peer->references, 1, CRYPTO_LOCK_X509);
+		}
+
+	if (s->session->sess_cert == NULL 
+      || s->session->peer != s->session->sess_cert->peer_key->x509)
+		/* can't happen */
+		{
+		ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
+		SSLerr(SSL_F_GET_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
+		return(-1);
+		}
+		
+	s->s2->conn_id_length=s->s2->tmp.conn_id_length;
+	if (s->s2->conn_id_length > sizeof s->s2->conn_id)
+		{
+		ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
+		SSLerr(SSL_F_GET_SERVER_HELLO, SSL_R_SSL2_CONNECTION_ID_TOO_LONG);
+		return -1;
+		}
+	memcpy(s->s2->conn_id,p,s->s2->tmp.conn_id_length);
+	return(1);
+	}
+
+static int client_hello(SSL *s)
+	{
+	unsigned char *buf;
+	unsigned char *p,*d;
+/*	CIPHER **cipher;*/
+	int i,n,j;
+
+	buf=(unsigned char *)s->init_buf->data;
+	if (s->state == SSL2_ST_SEND_CLIENT_HELLO_A)
+		{
+		if ((s->session == NULL) ||
+			(s->session->ssl_version != s->version))
+			{
+			if (!ssl_get_new_session(s,0))
+				{
+				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+				return(-1);
+				}
+			}
+		/* else use the pre-loaded session */
+
+		p=buf;					/* header */
+		d=p+9;					/* data section */
+		*(p++)=SSL2_MT_CLIENT_HELLO;		/* type */
+		s2n(SSL2_VERSION,p);			/* version */
+		n=j=0;
+
+		n=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),d,0);
+		d+=n;
+
+		if (n == 0)
+			{
+			SSLerr(SSL_F_CLIENT_HELLO,SSL_R_NO_CIPHERS_AVAILABLE);
+			return(-1);
+			}
+
+		s2n(n,p);			/* cipher spec num bytes */
+
+		if ((s->session->session_id_length > 0) &&
+			(s->session->session_id_length <=
+			SSL2_MAX_SSL_SESSION_ID_LENGTH))
+			{
+			i=s->session->session_id_length;
+			s2n(i,p);		/* session id length */
+			memcpy(d,s->session->session_id,(unsigned int)i);
+			d+=i;
+			}
+		else
+			{
+			s2n(0,p);
+			}
+
+		s->s2->challenge_length=SSL2_CHALLENGE_LENGTH;
+		s2n(SSL2_CHALLENGE_LENGTH,p);		/* challenge length */
+		/*challenge id data*/
+		if (RAND_pseudo_bytes(s->s2->challenge,SSL2_CHALLENGE_LENGTH) <= 0)
+			return -1;
+		memcpy(d,s->s2->challenge,SSL2_CHALLENGE_LENGTH);
+		d+=SSL2_CHALLENGE_LENGTH;
+
+		s->state=SSL2_ST_SEND_CLIENT_HELLO_B;
+		s->init_num=d-buf;
+		s->init_off=0;
+		}
+	/* SSL2_ST_SEND_CLIENT_HELLO_B */
+	return(ssl2_do_write(s));
+	}
+
+static int client_master_key(SSL *s)
+	{
+	unsigned char *buf;
+	unsigned char *p,*d;
+	int clear,enc,karg,i;
+	SSL_SESSION *sess;
+	const EVP_CIPHER *c;
+	const EVP_MD *md;
+
+	buf=(unsigned char *)s->init_buf->data;
+	if (s->state == SSL2_ST_SEND_CLIENT_MASTER_KEY_A)
+		{
+
+		if (!ssl_cipher_get_evp(s->session,&c,&md,NULL,NULL,NULL))
+			{
+			ssl2_return_error(s,SSL2_PE_NO_CIPHER);
+			SSLerr(SSL_F_CLIENT_MASTER_KEY,SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS);
+			return(-1);
+			}
+		sess=s->session;
+		p=buf;
+		d=p+10;
+		*(p++)=SSL2_MT_CLIENT_MASTER_KEY;/* type */
+
+		i=ssl_put_cipher_by_char(s,sess->cipher,p);
+		p+=i;
+
+		/* make key_arg data */
+		i=EVP_CIPHER_iv_length(c);
+		sess->key_arg_length=i;
+		if (i > SSL_MAX_KEY_ARG_LENGTH)
+			{
+			ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
+			SSLerr(SSL_F_CLIENT_MASTER_KEY, ERR_R_INTERNAL_ERROR);
+			return -1;
+			}
+		if (i > 0)
+			if (RAND_pseudo_bytes(sess->key_arg,i) <= 0)
+				return -1;
+
+		/* make a master key */
+		i=EVP_CIPHER_key_length(c);
+		sess->master_key_length=i;
+		if (i > 0)
+			{
+			if (i > (int)sizeof(sess->master_key))
+				{
+				ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
+				SSLerr(SSL_F_CLIENT_MASTER_KEY, ERR_R_INTERNAL_ERROR);
+				return -1;
+				}
+			if (RAND_bytes(sess->master_key,i) <= 0)
+				{
+				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+				return(-1);
+				}
+			}
+
+		if (sess->cipher->algorithm2 & SSL2_CF_8_BYTE_ENC)
+			enc=8;
+		else if (SSL_C_IS_EXPORT(sess->cipher))
+			enc=5;
+		else
+			enc=i;
+
+		if ((int)i < enc)
+			{
+			ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+			SSLerr(SSL_F_CLIENT_MASTER_KEY,SSL_R_CIPHER_TABLE_SRC_ERROR);
+			return(-1);
+			}
+		clear=i-enc;
+		s2n(clear,p);
+		memcpy(d,sess->master_key,(unsigned int)clear);
+		d+=clear;
+
+		enc=ssl_rsa_public_encrypt(sess->sess_cert,enc,
+			&(sess->master_key[clear]),d,
+			(s->s2->ssl2_rollback)?RSA_SSLV23_PADDING:RSA_PKCS1_PADDING);
+		if (enc <= 0)
+			{
+			ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+			SSLerr(SSL_F_CLIENT_MASTER_KEY,SSL_R_PUBLIC_KEY_ENCRYPT_ERROR);
+			return(-1);
+			}
+#ifdef PKCS1_CHECK
+		if (s->options & SSL_OP_PKCS1_CHECK_1) d[1]++;
+		if (s->options & SSL_OP_PKCS1_CHECK_2)
+			sess->master_key[clear]++;
+#endif
+		s2n(enc,p);
+		d+=enc;
+		karg=sess->key_arg_length;	
+		s2n(karg,p); /* key arg size */
+		if (karg > (int)sizeof(sess->key_arg))
+			{
+			ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+			SSLerr(SSL_F_CLIENT_MASTER_KEY, ERR_R_INTERNAL_ERROR);
+			return -1;
+			}
+		memcpy(d,sess->key_arg,(unsigned int)karg);
+		d+=karg;
+
+		s->state=SSL2_ST_SEND_CLIENT_MASTER_KEY_B;
+		s->init_num=d-buf;
+		s->init_off=0;
+		}
+
+	/* SSL2_ST_SEND_CLIENT_MASTER_KEY_B */
+	return(ssl2_do_write(s));
+	}
+
+static int client_finished(SSL *s)
+	{
+	unsigned char *p;
+
+	if (s->state == SSL2_ST_SEND_CLIENT_FINISHED_A)
+		{
+		p=(unsigned char *)s->init_buf->data;
+		*(p++)=SSL2_MT_CLIENT_FINISHED;
+		if (s->s2->conn_id_length > sizeof s->s2->conn_id)
+			{
+			SSLerr(SSL_F_CLIENT_FINISHED, ERR_R_INTERNAL_ERROR);
+			return -1;
+			}
+		memcpy(p,s->s2->conn_id,(unsigned int)s->s2->conn_id_length);
+
+		s->state=SSL2_ST_SEND_CLIENT_FINISHED_B;
+		s->init_num=s->s2->conn_id_length+1;
+		s->init_off=0;
+		}
+	return(ssl2_do_write(s));
+	}
+
+/* read the data and then respond */
+static int client_certificate(SSL *s)
+	{
+	unsigned char *buf;
+	unsigned char *p,*d;
+	int i;
+	unsigned int n;
+	int cert_ch_len;
+	unsigned char *cert_ch;
+
+	buf=(unsigned char *)s->init_buf->data;
+
+	/* We have a cert associated with the SSL, so attach it to
+	 * the session if it does not have one */
+
+	if (s->state == SSL2_ST_SEND_CLIENT_CERTIFICATE_A)
+		{
+		i=ssl2_read(s,(char *)&(buf[s->init_num]),
+			SSL2_MAX_CERT_CHALLENGE_LENGTH+2-s->init_num);
+		if (i<(SSL2_MIN_CERT_CHALLENGE_LENGTH+2-s->init_num))
+			return(ssl2_part_read(s,SSL_F_CLIENT_CERTIFICATE,i));
+		s->init_num += i;
+		if (s->msg_callback)
+			s->msg_callback(0, s->version, 0, buf, (size_t)s->init_num, s, s->msg_callback_arg); /* REQUEST-CERTIFICATE */
+
+		/* type=buf[0]; */
+		/* type eq x509 */
+		if (buf[1] != SSL2_AT_MD5_WITH_RSA_ENCRYPTION)
+			{
+			ssl2_return_error(s,SSL2_PE_UNSUPPORTED_CERTIFICATE_TYPE);
+			SSLerr(SSL_F_CLIENT_CERTIFICATE,SSL_R_BAD_AUTHENTICATION_TYPE);
+			return(-1);
+			}
+
+		if ((s->cert == NULL) ||
+			(s->cert->key->x509 == NULL) ||
+			(s->cert->key->privatekey == NULL))
+			{
+			s->state=SSL2_ST_X509_GET_CLIENT_CERTIFICATE;
+			}
+		else
+			s->state=SSL2_ST_SEND_CLIENT_CERTIFICATE_C;
+		}
+
+	cert_ch = buf + 2;
+	cert_ch_len = s->init_num - 2;
+
+	if (s->state == SSL2_ST_X509_GET_CLIENT_CERTIFICATE)
+		{
+		X509 *x509=NULL;
+		EVP_PKEY *pkey=NULL;
+
+		/* If we get an error we need to
+		 * ssl->rwstate=SSL_X509_LOOKUP;
+		 * return(error);
+		 * We should then be retried when things are ok and we
+		 * can get a cert or not */
+
+		i=0;
+		if (s->ctx->client_cert_cb != NULL)
+			{
+			i=s->ctx->client_cert_cb(s,&(x509),&(pkey));
+			}
+
+		if (i < 0)
+			{
+			s->rwstate=SSL_X509_LOOKUP;
+			return(-1);
+			}
+		s->rwstate=SSL_NOTHING;
+
+		if ((i == 1) && (pkey != NULL) && (x509 != NULL))
+			{
+			s->state=SSL2_ST_SEND_CLIENT_CERTIFICATE_C;
+			if (	!SSL_use_certificate(s,x509) || 
+				!SSL_use_PrivateKey(s,pkey))
+				{
+				i=0;
+				}
+			X509_free(x509);
+			EVP_PKEY_free(pkey);
+			}
+		else if (i == 1)
+			{
+			if (x509 != NULL) X509_free(x509);
+			if (pkey != NULL) EVP_PKEY_free(pkey);
+			SSLerr(SSL_F_CLIENT_CERTIFICATE,SSL_R_BAD_DATA_RETURNED_BY_CALLBACK);
+			i=0;
+			}
+
+		if (i == 0)
+			{
+			/* We have no client certificate to respond with
+			 * so send the correct error message back */
+			s->state=SSL2_ST_SEND_CLIENT_CERTIFICATE_B;
+			p=buf;
+			*(p++)=SSL2_MT_ERROR;
+			s2n(SSL2_PE_NO_CERTIFICATE,p);
+			s->init_off=0;
+			s->init_num=3;
+			/* Write is done at the end */
+			}
+		}
+
+	if (s->state == SSL2_ST_SEND_CLIENT_CERTIFICATE_B)
+		{
+		return(ssl2_do_write(s));
+		}
+
+	if (s->state == SSL2_ST_SEND_CLIENT_CERTIFICATE_C)
+		{
+		EVP_MD_CTX ctx;
+
+		/* ok, now we calculate the checksum
+		 * do it first so we can reuse buf :-) */
+		p=buf;
+		EVP_MD_CTX_init(&ctx);
+		EVP_SignInit_ex(&ctx,s->ctx->rsa_md5, NULL);
+		EVP_SignUpdate(&ctx,s->s2->key_material,
+			       s->s2->key_material_length);
+		EVP_SignUpdate(&ctx,cert_ch,(unsigned int)cert_ch_len);
+		i=i2d_X509(s->session->sess_cert->peer_key->x509,&p);
+		/* Don't update the signature if it fails - FIXME: probably should handle this better */
+		if(i > 0)
+			EVP_SignUpdate(&ctx,buf,(unsigned int)i);
+
+		p=buf;
+		d=p+6;
+		*(p++)=SSL2_MT_CLIENT_CERTIFICATE;
+		*(p++)=SSL2_CT_X509_CERTIFICATE;
+		n=i2d_X509(s->cert->key->x509,&d);
+		s2n(n,p);
+
+		if (!EVP_SignFinal(&ctx,d,&n,s->cert->key->privatekey))
+			{
+			/* this is not good.  If things have failed it
+			 * means there so something wrong with the key.
+			 * We will continue with a 0 length signature
+			 */
+			}
+		EVP_MD_CTX_cleanup(&ctx);
+		s2n(n,p);
+		d+=n;
+
+		s->state=SSL2_ST_SEND_CLIENT_CERTIFICATE_D;
+		s->init_num=d-buf;
+		s->init_off=0;
+		}
+	/* if (s->state == SSL2_ST_SEND_CLIENT_CERTIFICATE_D) */
+	return(ssl2_do_write(s));
+	}
+
+static int get_server_verify(SSL *s)
+	{
+	unsigned char *p;
+	int i, n, len;
+
+	p=(unsigned char *)s->init_buf->data;
+	if (s->state == SSL2_ST_GET_SERVER_VERIFY_A)
+		{
+		i=ssl2_read(s,(char *)&(p[s->init_num]),1-s->init_num);
+		if (i < (1-s->init_num)) 
+			return(ssl2_part_read(s,SSL_F_GET_SERVER_VERIFY,i));
+		s->init_num += i;
+
+		s->state= SSL2_ST_GET_SERVER_VERIFY_B;
+		if (*p != SSL2_MT_SERVER_VERIFY)
+			{
+			if (p[0] != SSL2_MT_ERROR)
+				{
+				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+				SSLerr(SSL_F_GET_SERVER_VERIFY,
+					SSL_R_READ_WRONG_PACKET_TYPE);
+				}
+			else
+				{
+				SSLerr(SSL_F_GET_SERVER_VERIFY,SSL_R_PEER_ERROR);
+				/* try to read the error message */
+				i=ssl2_read(s,(char *)&(p[s->init_num]),3-s->init_num);
+				return ssl2_part_read(s,SSL_F_GET_SERVER_VERIFY,i);
+				}
+			return(-1);
+			}
+		}
+	
+	p=(unsigned char *)s->init_buf->data;
+	len = 1 + s->s2->challenge_length;
+	n =  len - s->init_num;
+	i = ssl2_read(s,(char *)&(p[s->init_num]),n);
+	if (i < n)
+		return(ssl2_part_read(s,SSL_F_GET_SERVER_VERIFY,i));
+	if (s->msg_callback)
+		s->msg_callback(0, s->version, 0, p, len, s, s->msg_callback_arg); /* SERVER-VERIFY */
+	p += 1;
+
+	if (memcmp(p,s->s2->challenge,s->s2->challenge_length) != 0)
+		{
+		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+		SSLerr(SSL_F_GET_SERVER_VERIFY,SSL_R_CHALLENGE_IS_DIFFERENT);
+		return(-1);
+		}
+	return(1);
+	}
+
+static int get_server_finished(SSL *s)
+	{
+	unsigned char *buf;
+	unsigned char *p;
+	int i, n, len;
+
+	buf=(unsigned char *)s->init_buf->data;
+	p=buf;
+	if (s->state == SSL2_ST_GET_SERVER_FINISHED_A)
+		{
+		i=ssl2_read(s,(char *)&(buf[s->init_num]),1-s->init_num);
+		if (i < (1-s->init_num))
+			return(ssl2_part_read(s,SSL_F_GET_SERVER_FINISHED,i));
+		s->init_num += i;
+
+		if (*p == SSL2_MT_REQUEST_CERTIFICATE)
+			{
+			s->state=SSL2_ST_SEND_CLIENT_CERTIFICATE_A;
+			return(1);
+			}
+		else if (*p != SSL2_MT_SERVER_FINISHED)
+			{
+			if (p[0] != SSL2_MT_ERROR)
+				{
+				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+				SSLerr(SSL_F_GET_SERVER_FINISHED,SSL_R_READ_WRONG_PACKET_TYPE);
+				}
+			else
+				{
+				SSLerr(SSL_F_GET_SERVER_FINISHED,SSL_R_PEER_ERROR);
+				/* try to read the error message */
+				i=ssl2_read(s,(char *)&(p[s->init_num]),3-s->init_num);
+				return ssl2_part_read(s,SSL_F_GET_SERVER_VERIFY,i);
+				}
+			return(-1);
+			}
+		s->state=SSL2_ST_GET_SERVER_FINISHED_B;
+		}
+
+	len = 1 + SSL2_SSL_SESSION_ID_LENGTH;
+	n = len - s->init_num;
+	i = ssl2_read(s,(char *)&(buf[s->init_num]), n);
+	if (i < n) /* XXX could be shorter than SSL2_SSL_SESSION_ID_LENGTH, that's the maximum */
+		return(ssl2_part_read(s,SSL_F_GET_SERVER_FINISHED,i));
+	s->init_num += i;
+	if (s->msg_callback)
+		s->msg_callback(0, s->version, 0, buf, (size_t)s->init_num, s, s->msg_callback_arg); /* SERVER-FINISHED */
+
+	if (!s->hit) /* new session */
+		{
+		/* new session-id */
+		/* Make sure we were not trying to re-use an old SSL_SESSION
+		 * or bad things can happen */
+		/* ZZZZZZZZZZZZZ */
+		s->session->session_id_length=SSL2_SSL_SESSION_ID_LENGTH;
+		memcpy(s->session->session_id,p+1,SSL2_SSL_SESSION_ID_LENGTH);
+		}
+	else
+		{
+		if (!(s->options & SSL_OP_MICROSOFT_SESS_ID_BUG))
+			{
+			if ((s->session->session_id_length > sizeof s->session->session_id)
+			    || (0 != memcmp(buf + 1, s->session->session_id,
+			                    (unsigned int)s->session->session_id_length)))
+				{
+				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+				SSLerr(SSL_F_GET_SERVER_FINISHED,SSL_R_SSL_SESSION_ID_IS_DIFFERENT);
+				return(-1);
+				}
+			}
+		}
+	s->state = SSL_ST_OK;
+	return(1);
+	}
+
+/* loads in the certificate from the server */
+int ssl2_set_certificate(SSL *s, int type, int len, const unsigned char *data)
+	{
+	STACK_OF(X509) *sk=NULL;
+	EVP_PKEY *pkey=NULL;
+	SESS_CERT *sc=NULL;
+	int i;
+	X509 *x509=NULL;
+	int ret=0;
+	
+	x509=d2i_X509(NULL,&data,(long)len);
+	if (x509 == NULL)
+		{
+		SSLerr(SSL_F_SSL2_SET_CERTIFICATE,ERR_R_X509_LIB);
+		goto err;
+		}
+
+	if ((sk=sk_X509_new_null()) == NULL || !sk_X509_push(sk,x509))
+		{
+		SSLerr(SSL_F_SSL2_SET_CERTIFICATE,ERR_R_MALLOC_FAILURE);
+		goto err;
+		}
+
+	i=ssl_verify_cert_chain(s,sk);
+		
+	if ((s->verify_mode != SSL_VERIFY_NONE) && (i <= 0))
+		{
+		SSLerr(SSL_F_SSL2_SET_CERTIFICATE,SSL_R_CERTIFICATE_VERIFY_FAILED);
+		goto err;
+		}
+	ERR_clear_error(); /* but we keep s->verify_result */
+	s->session->verify_result = s->verify_result;
+
+	/* server's cert for this session */
+	sc=ssl_sess_cert_new();
+	if (sc == NULL)
+		{
+		ret= -1;
+		goto err;
+		}
+	if (s->session->sess_cert) ssl_sess_cert_free(s->session->sess_cert);
+	s->session->sess_cert=sc;
+
+	sc->peer_pkeys[SSL_PKEY_RSA_ENC].x509=x509;
+	sc->peer_key= &(sc->peer_pkeys[SSL_PKEY_RSA_ENC]);
+
+	pkey=X509_get_pubkey(x509);
+	x509=NULL;
+	if (pkey == NULL)
+		{
+		SSLerr(SSL_F_SSL2_SET_CERTIFICATE,SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY);
+		goto err;
+		}
+	if (pkey->type != EVP_PKEY_RSA)
+		{
+		SSLerr(SSL_F_SSL2_SET_CERTIFICATE,SSL_R_PUBLIC_KEY_NOT_RSA);
+		goto err;
+		}
+
+	if (!ssl_set_peer_cert_type(sc,SSL2_CT_X509_CERTIFICATE))
+		goto err;
+	ret=1;
+err:
+	sk_X509_free(sk);
+	X509_free(x509);
+	EVP_PKEY_free(pkey);
+	return(ret);
+	}
+
+static int ssl_rsa_public_encrypt(SESS_CERT *sc, int len, unsigned char *from,
+	     unsigned char *to, int padding)
+	{
+	EVP_PKEY *pkey=NULL;
+	int i= -1;
+
+	if ((sc == NULL) || (sc->peer_key->x509 == NULL) ||
+		((pkey=X509_get_pubkey(sc->peer_key->x509)) == NULL))
+		{
+		SSLerr(SSL_F_SSL_RSA_PUBLIC_ENCRYPT,SSL_R_NO_PUBLICKEY);
+		return(-1);
+		}
+	if (pkey->type != EVP_PKEY_RSA)
+		{
+		SSLerr(SSL_F_SSL_RSA_PUBLIC_ENCRYPT,SSL_R_PUBLIC_KEY_IS_NOT_RSA);
+		goto end;
+		}
+
+	/* we have the public key */
+	i=RSA_public_encrypt(len,from,to,pkey->pkey.rsa,padding);
+	if (i < 0)
+		SSLerr(SSL_F_SSL_RSA_PUBLIC_ENCRYPT,ERR_R_RSA_LIB);
+end:
+	EVP_PKEY_free(pkey);
+	return(i);
+	}
+#else /* !OPENSSL_NO_SSL2 */
+
+# if PEDANTIC
+static void *dummy=&dummy;
+# endif
+
+#endif
diff --git a/lib/openssl/ssl/s2_enc.c b/lib/openssl/ssl/s2_enc.c
new file mode 100644
index 0000000..ff3395f
--- /dev/null
+++ b/lib/openssl/ssl/s2_enc.c
@@ -0,0 +1,193 @@
+/* ssl/s2_enc.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include "ssl_locl.h"
+#ifndef OPENSSL_NO_SSL2
+#include <stdio.h>
+
+int ssl2_enc_init(SSL *s, int client)
+	{
+	/* Max number of bytes needed */
+	EVP_CIPHER_CTX *rs,*ws;
+	const EVP_CIPHER *c;
+	const EVP_MD *md;
+	int num;
+
+	if (!ssl_cipher_get_evp(s->session,&c,&md,NULL,NULL,NULL))
+		{
+		ssl2_return_error(s,SSL2_PE_NO_CIPHER);
+		SSLerr(SSL_F_SSL2_ENC_INIT,SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS);
+		return(0);
+		}
+	ssl_replace_hash(&s->read_hash,md);
+	ssl_replace_hash(&s->write_hash,md);
+
+	if ((s->enc_read_ctx == NULL) &&
+		((s->enc_read_ctx=(EVP_CIPHER_CTX *)
+		OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL))
+		goto err;
+
+	/* make sure it's intialized in case the malloc for enc_write_ctx fails
+	 * and we exit with an error */
+	rs= s->enc_read_ctx;
+	EVP_CIPHER_CTX_init(rs);
+
+	if ((s->enc_write_ctx == NULL) &&
+		((s->enc_write_ctx=(EVP_CIPHER_CTX *)
+		OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL))
+		goto err;
+
+	ws= s->enc_write_ctx;
+	EVP_CIPHER_CTX_init(ws);
+
+	num=c->key_len;
+	s->s2->key_material_length=num*2;
+	OPENSSL_assert(s->s2->key_material_length <= sizeof s->s2->key_material);
+
+	if (ssl2_generate_key_material(s) <= 0)
+		return 0;
+
+	OPENSSL_assert(c->iv_len <= (int)sizeof(s->session->key_arg));
+	EVP_EncryptInit_ex(ws,c,NULL,&(s->s2->key_material[(client)?num:0]),
+		s->session->key_arg);
+	EVP_DecryptInit_ex(rs,c,NULL,&(s->s2->key_material[(client)?0:num]),
+		s->session->key_arg);
+	s->s2->read_key=  &(s->s2->key_material[(client)?0:num]);
+	s->s2->write_key= &(s->s2->key_material[(client)?num:0]);
+	return(1);
+err:
+	SSLerr(SSL_F_SSL2_ENC_INIT,ERR_R_MALLOC_FAILURE);
+	return(0);
+	}
+
+/* read/writes from s->s2->mac_data using length for encrypt and 
+ * decrypt.  It sets s->s2->padding and s->[rw]length
+ * if we are encrypting */
+void ssl2_enc(SSL *s, int send)
+	{
+	EVP_CIPHER_CTX *ds;
+	unsigned long l;
+	int bs;
+
+	if (send)
+		{
+		ds=s->enc_write_ctx;
+		l=s->s2->wlength;
+		}
+	else
+		{
+		ds=s->enc_read_ctx;
+		l=s->s2->rlength;
+		}
+
+	/* check for NULL cipher */
+	if (ds == NULL) return;
+
+
+	bs=ds->cipher->block_size;
+	/* This should be using (bs-1) and bs instead of 7 and 8, but
+	 * what the hell. */
+	if (bs == 8)
+		l=(l+7)/8*8;
+
+	EVP_Cipher(ds,s->s2->mac_data,s->s2->mac_data,l);
+	}
+
+void ssl2_mac(SSL *s, unsigned char *md, int send)
+	{
+	EVP_MD_CTX c;
+	unsigned char sequence[4],*p,*sec,*act;
+	unsigned long seq;
+	unsigned int len;
+
+	if (send)
+		{
+		seq=s->s2->write_sequence;
+		sec=s->s2->write_key;
+		len=s->s2->wact_data_length;
+		act=s->s2->wact_data;
+		}
+	else
+		{
+		seq=s->s2->read_sequence;
+		sec=s->s2->read_key;
+		len=s->s2->ract_data_length;
+		act=s->s2->ract_data;
+		}
+
+	p= &(sequence[0]);
+	l2n(seq,p);
+
+	/* There has to be a MAC algorithm. */
+	EVP_MD_CTX_init(&c);
+	EVP_MD_CTX_copy(&c, s->read_hash);
+	EVP_DigestUpdate(&c,sec,
+		EVP_CIPHER_CTX_key_length(s->enc_read_ctx));
+	EVP_DigestUpdate(&c,act,len); 
+	/* the above line also does the pad data */
+	EVP_DigestUpdate(&c,sequence,4); 
+	EVP_DigestFinal_ex(&c,md,NULL);
+	EVP_MD_CTX_cleanup(&c);
+	}
+#else /* !OPENSSL_NO_SSL2 */
+
+# if PEDANTIC
+static void *dummy=&dummy;
+# endif
+
+#endif
diff --git a/lib/openssl/ssl/s2_lib.c b/lib/openssl/ssl/s2_lib.c
new file mode 100644
index 0000000..9914604
--- /dev/null
+++ b/lib/openssl/ssl/s2_lib.c
@@ -0,0 +1,556 @@
+/* ssl/s2_lib.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include "ssl_locl.h"
+#ifndef OPENSSL_NO_SSL2
+#include <stdio.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include <openssl/md5.h>
+
+const char ssl2_version_str[]="SSLv2" OPENSSL_VERSION_PTEXT;
+
+#define SSL2_NUM_CIPHERS (sizeof(ssl2_ciphers)/sizeof(SSL_CIPHER))
+
+/* list of available SSLv2 ciphers (sorted by id) */
+OPENSSL_GLOBAL const SSL_CIPHER ssl2_ciphers[]={
+#if 0
+/* NULL_WITH_MD5 v3 */
+	{
+	1,
+	SSL2_TXT_NULL_WITH_MD5,
+	SSL2_CK_NULL_WITH_MD5,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_eNULL,
+	SSL_MD5,
+	SSL_SSLV2,
+	SSL_EXPORT|SSL_EXP40|SSL_STRONG_NONE,
+	0,
+	0,
+	0,
+	},
+#endif
+
+/* RC4_128_WITH_MD5 */
+	{
+	1,
+	SSL2_TXT_RC4_128_WITH_MD5,
+	SSL2_CK_RC4_128_WITH_MD5,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_RC4,
+	SSL_MD5,
+	SSL_SSLV2,
+	SSL_NOT_EXP|SSL_MEDIUM,
+	0,
+	128,
+	128,
+	},
+
+/* RC4_128_EXPORT40_WITH_MD5 */
+	{
+	1,
+	SSL2_TXT_RC4_128_EXPORT40_WITH_MD5,
+	SSL2_CK_RC4_128_EXPORT40_WITH_MD5,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_RC4,
+	SSL_MD5,
+	SSL_SSLV2,
+	SSL_EXPORT|SSL_EXP40,
+	SSL2_CF_5_BYTE_ENC,
+	40,
+	128,
+	},
+
+/* RC2_128_CBC_WITH_MD5 */
+	{
+	1,
+	SSL2_TXT_RC2_128_CBC_WITH_MD5,
+	SSL2_CK_RC2_128_CBC_WITH_MD5,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_RC2,
+	SSL_MD5,
+	SSL_SSLV2,
+	SSL_NOT_EXP|SSL_MEDIUM,
+	0,
+	128,
+	128,
+	},
+
+/* RC2_128_CBC_EXPORT40_WITH_MD5 */
+	{
+	1,
+	SSL2_TXT_RC2_128_CBC_EXPORT40_WITH_MD5,
+	SSL2_CK_RC2_128_CBC_EXPORT40_WITH_MD5,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_RC2,
+	SSL_MD5,
+	SSL_SSLV2,
+	SSL_EXPORT|SSL_EXP40,
+	SSL2_CF_5_BYTE_ENC,
+	40,
+	128,
+	},
+
+#ifndef OPENSSL_NO_IDEA
+/* IDEA_128_CBC_WITH_MD5 */
+	{
+	1,
+	SSL2_TXT_IDEA_128_CBC_WITH_MD5,
+	SSL2_CK_IDEA_128_CBC_WITH_MD5,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_IDEA,
+	SSL_MD5,
+	SSL_SSLV2,
+	SSL_NOT_EXP|SSL_MEDIUM,
+	0,
+	128,
+	128,
+	},
+#endif
+
+/* DES_64_CBC_WITH_MD5 */
+	{
+	1,
+	SSL2_TXT_DES_64_CBC_WITH_MD5,
+	SSL2_CK_DES_64_CBC_WITH_MD5,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_DES,
+	SSL_MD5,
+	SSL_SSLV2,
+	SSL_NOT_EXP|SSL_LOW,
+	0,
+	56,
+	56,
+	},
+
+/* DES_192_EDE3_CBC_WITH_MD5 */
+	{
+	1,
+	SSL2_TXT_DES_192_EDE3_CBC_WITH_MD5,
+	SSL2_CK_DES_192_EDE3_CBC_WITH_MD5,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_3DES,
+	SSL_MD5,
+	SSL_SSLV2,
+	SSL_NOT_EXP|SSL_HIGH,
+	0,
+	168,
+	168,
+	},
+
+#if 0
+/* RC4_64_WITH_MD5 */
+	{
+	1,
+	SSL2_TXT_RC4_64_WITH_MD5,
+	SSL2_CK_RC4_64_WITH_MD5,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_RC4,
+	SSL_MD5,
+	SSL_SSLV2,
+	SSL_NOT_EXP|SSL_LOW,
+	SSL2_CF_8_BYTE_ENC,
+	64,
+	64,
+	},
+#endif
+
+#if 0
+/* NULL SSLeay (testing) */
+	{	
+	0,
+	SSL2_TXT_NULL,
+	SSL2_CK_NULL,
+	0,
+	0,
+	0,
+	0,
+	SSL_SSLV2,
+	SSL_STRONG_NONE,
+	0,
+	0,
+	0,
+	},
+#endif
+
+/* end of list :-) */
+	};
+
+long ssl2_default_timeout(void)
+	{
+	return(300);
+	}
+
+int ssl2_num_ciphers(void)
+	{
+	return(SSL2_NUM_CIPHERS);
+	}
+
+const SSL_CIPHER *ssl2_get_cipher(unsigned int u)
+	{
+	if (u < SSL2_NUM_CIPHERS)
+		return(&(ssl2_ciphers[SSL2_NUM_CIPHERS-1-u]));
+	else
+		return(NULL);
+	}
+
+int ssl2_pending(const SSL *s)
+	{
+	return SSL_in_init(s) ? 0 : s->s2->ract_data_length;
+	}
+
+int ssl2_new(SSL *s)
+	{
+	SSL2_STATE *s2;
+
+	if ((s2=OPENSSL_malloc(sizeof *s2)) == NULL) goto err;
+	memset(s2,0,sizeof *s2);
+
+#if SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER + 3 > SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER + 2
+#  error "assertion failed"
+#endif
+
+	if ((s2->rbuf=OPENSSL_malloc(
+		SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER+2)) == NULL) goto err;
+	/* wbuf needs one byte more because when using two-byte headers,
+	 * we leave the first byte unused in do_ssl_write (s2_pkt.c) */
+	if ((s2->wbuf=OPENSSL_malloc(
+		SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER+3)) == NULL) goto err;
+	s->s2=s2;
+
+	ssl2_clear(s);
+	return(1);
+err:
+	if (s2 != NULL)
+		{
+		if (s2->wbuf != NULL) OPENSSL_free(s2->wbuf);
+		if (s2->rbuf != NULL) OPENSSL_free(s2->rbuf);
+		OPENSSL_free(s2);
+		}
+	return(0);
+	}
+
+void ssl2_free(SSL *s)
+	{
+	SSL2_STATE *s2;
+
+	if(s == NULL)
+	    return;
+
+	s2=s->s2;
+	if (s2->rbuf != NULL) OPENSSL_free(s2->rbuf);
+	if (s2->wbuf != NULL) OPENSSL_free(s2->wbuf);
+	OPENSSL_cleanse(s2,sizeof *s2);
+	OPENSSL_free(s2);
+	s->s2=NULL;
+	}
+
+void ssl2_clear(SSL *s)
+	{
+	SSL2_STATE *s2;
+	unsigned char *rbuf,*wbuf;
+
+	s2=s->s2;
+
+	rbuf=s2->rbuf;
+	wbuf=s2->wbuf;
+
+	memset(s2,0,sizeof *s2);
+
+	s2->rbuf=rbuf;
+	s2->wbuf=wbuf;
+	s2->clear_text=1;
+	s->packet=s2->rbuf;
+	s->version=SSL2_VERSION;
+	s->packet_length=0;
+	}
+
+long ssl2_ctrl(SSL *s, int cmd, long larg, void *parg)
+	{
+	int ret=0;
+
+	switch(cmd)
+		{
+	case SSL_CTRL_GET_SESSION_REUSED:
+		ret=s->hit;
+		break;
+	default:
+		break;
+		}
+	return(ret);
+	}
+
+long ssl2_callback_ctrl(SSL *s, int cmd, void (*fp)(void))
+	{
+	return(0);
+	}
+
+long ssl2_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
+	{
+	return(0);
+	}
+
+long ssl2_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp)(void))
+	{
+	return(0);
+	}
+
+/* This function needs to check if the ciphers required are actually
+ * available */
+const SSL_CIPHER *ssl2_get_cipher_by_char(const unsigned char *p)
+	{
+	SSL_CIPHER c;
+	const SSL_CIPHER *cp;
+	unsigned long id;
+
+	id=0x02000000L|((unsigned long)p[0]<<16L)|
+		((unsigned long)p[1]<<8L)|(unsigned long)p[2];
+	c.id=id;
+	cp = OBJ_bsearch_ssl_cipher_id(&c, ssl2_ciphers, SSL2_NUM_CIPHERS);
+	if ((cp == NULL) || (cp->valid == 0))
+		return NULL;
+	else
+		return cp;
+	}
+
+int ssl2_put_cipher_by_char(const SSL_CIPHER *c, unsigned char *p)
+	{
+	long l;
+
+	if (p != NULL)
+		{
+		l=c->id;
+		if ((l & 0xff000000) != 0x02000000) return(0);
+		p[0]=((unsigned char)(l>>16L))&0xFF;
+		p[1]=((unsigned char)(l>> 8L))&0xFF;
+		p[2]=((unsigned char)(l     ))&0xFF;
+		}
+	return(3);
+	}
+
+int ssl2_generate_key_material(SSL *s)
+	{
+	unsigned int i;
+	EVP_MD_CTX ctx;
+	unsigned char *km;
+	unsigned char c='0';
+	const EVP_MD *md5;
+	int md_size;
+
+	md5 = EVP_md5();
+
+#ifdef CHARSET_EBCDIC
+	c = os_toascii['0']; /* Must be an ASCII '0', not EBCDIC '0',
+				see SSLv2 docu */
+#endif
+	EVP_MD_CTX_init(&ctx);
+	km=s->s2->key_material;
+
+ 	if (s->session->master_key_length < 0 ||
+			s->session->master_key_length > (int)sizeof(s->session->master_key))
+ 		{
+ 		SSLerr(SSL_F_SSL2_GENERATE_KEY_MATERIAL, ERR_R_INTERNAL_ERROR);
+ 		return 0;
+ 		}
+	md_size = EVP_MD_size(md5);
+	if (md_size < 0)
+	    return 0;
+	for (i=0; i<s->s2->key_material_length; i += md_size)
+		{
+		if (((km - s->s2->key_material) + md_size) >
+				(int)sizeof(s->s2->key_material))
+			{
+			/* EVP_DigestFinal_ex() below would write beyond buffer */
+			SSLerr(SSL_F_SSL2_GENERATE_KEY_MATERIAL, ERR_R_INTERNAL_ERROR);
+			return 0;
+			}
+
+		EVP_DigestInit_ex(&ctx, md5, NULL);
+
+		OPENSSL_assert(s->session->master_key_length >= 0
+		    && s->session->master_key_length
+		    < (int)sizeof(s->session->master_key));
+		EVP_DigestUpdate(&ctx,s->session->master_key,s->session->master_key_length);
+		EVP_DigestUpdate(&ctx,&c,1);
+		c++;
+		EVP_DigestUpdate(&ctx,s->s2->challenge,s->s2->challenge_length);
+		EVP_DigestUpdate(&ctx,s->s2->conn_id,s->s2->conn_id_length);
+		EVP_DigestFinal_ex(&ctx,km,NULL);
+		km += md_size;
+		}
+
+	EVP_MD_CTX_cleanup(&ctx);
+	return 1;
+	}
+
+void ssl2_return_error(SSL *s, int err)
+	{
+	if (!s->error)
+		{
+		s->error=3;
+		s->error_code=err;
+
+		ssl2_write_error(s);
+		}
+	}
+
+
+void ssl2_write_error(SSL *s)
+	{
+	unsigned char buf[3];
+	int i,error;
+
+	buf[0]=SSL2_MT_ERROR;
+	buf[1]=(s->error_code>>8)&0xff;
+	buf[2]=(s->error_code)&0xff;
+
+/*	state=s->rwstate;*/
+
+	error=s->error; /* number of bytes left to write */
+	s->error=0;
+	OPENSSL_assert(error >= 0 && error <= (int)sizeof(buf));
+	i=ssl2_write(s,&(buf[3-error]),error);
+
+/*	if (i == error) s->rwstate=state; */
+
+	if (i < 0)
+		s->error=error;
+	else
+		{
+		s->error=error-i;
+
+		if (s->error == 0)
+			if (s->msg_callback)
+				s->msg_callback(1, s->version, 0, buf, 3, s, s->msg_callback_arg); /* ERROR */
+		}
+	}
+
+int ssl2_shutdown(SSL *s)
+	{
+	s->shutdown=(SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
+	return(1);
+	}
+#else /* !OPENSSL_NO_SSL2 */
+
+# if PEDANTIC
+static void *dummy=&dummy;
+# endif
+
+#endif
diff --git a/lib/openssl/ssl/s2_meth.c b/lib/openssl/ssl/s2_meth.c
new file mode 100644
index 0000000..f0e8ca5
--- /dev/null
+++ b/lib/openssl/ssl/s2_meth.c
@@ -0,0 +1,84 @@
+/* ssl/s2_meth.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include "ssl_locl.h"
+#ifndef OPENSSL_NO_SSL2
+#include <stdio.h>
+#include <openssl/objects.h>
+
+static const SSL_METHOD *ssl2_get_method(int ver);
+static const SSL_METHOD *ssl2_get_method(int ver)
+	{
+	if (ver == SSL2_VERSION)
+		return(SSLv2_method());
+	else
+		return(NULL);
+	}
+
+IMPLEMENT_ssl2_meth_func(SSLv2_method,
+			 ssl2_accept,
+			 ssl2_connect,
+			 ssl2_get_method)
+
+#else /* !OPENSSL_NO_SSL2 */
+
+# if PEDANTIC
+static void *dummy=&dummy;
+# endif
+
+#endif
diff --git a/lib/openssl/ssl/s2_pkt.c b/lib/openssl/ssl/s2_pkt.c
new file mode 100644
index 0000000..ac963b2
--- /dev/null
+++ b/lib/openssl/ssl/s2_pkt.c
@@ -0,0 +1,744 @@
+/* ssl/s2_pkt.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include "ssl_locl.h"
+#ifndef OPENSSL_NO_SSL2
+#include <stdio.h>
+#include <errno.h>
+#define USE_SOCKETS
+
+static int read_n(SSL *s,unsigned int n,unsigned int max,unsigned int extend);
+static int n_do_ssl_write(SSL *s, const unsigned char *buf, unsigned int len);
+static int write_pending(SSL *s, const unsigned char *buf, unsigned int len);
+static int ssl_mt_error(int n);
+
+
+/* SSL 2.0 imlementation for SSL_read/SSL_peek -
+ * This routine will return 0 to len bytes, decrypted etc if required.
+ */
+static int ssl2_read_internal(SSL *s, void *buf, int len, int peek)
+	{
+	int n;
+	unsigned char mac[MAX_MAC_SIZE];
+	unsigned char *p;
+	int i;
+	int mac_size;
+
+ ssl2_read_again:
+	if (SSL_in_init(s) && !s->in_handshake)
+		{
+		n=s->handshake_func(s);
+		if (n < 0) return(n);
+		if (n == 0)
+			{
+			SSLerr(SSL_F_SSL2_READ_INTERNAL,SSL_R_SSL_HANDSHAKE_FAILURE);
+			return(-1);
+			}
+		}
+
+	clear_sys_error();
+	s->rwstate=SSL_NOTHING;
+	if (len <= 0) return(len);
+
+	if (s->s2->ract_data_length != 0) /* read from buffer */
+		{
+		if (len > s->s2->ract_data_length)
+			n=s->s2->ract_data_length;
+		else
+			n=len;
+
+		memcpy(buf,s->s2->ract_data,(unsigned int)n);
+		if (!peek)
+			{
+			s->s2->ract_data_length-=n;
+			s->s2->ract_data+=n;
+			if (s->s2->ract_data_length == 0)
+				s->rstate=SSL_ST_READ_HEADER;
+			}
+
+		return(n);
+		}
+
+	/* s->s2->ract_data_length == 0
+	 * 
+	 * Fill the buffer, then goto ssl2_read_again.
+	 */
+
+	if (s->rstate == SSL_ST_READ_HEADER)
+		{
+		if (s->first_packet)
+			{
+			n=read_n(s,5,SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER+2,0);
+			if (n <= 0) return(n); /* error or non-blocking */
+			s->first_packet=0;
+			p=s->packet;
+			if (!((p[0] & 0x80) && (
+				(p[2] == SSL2_MT_CLIENT_HELLO) ||
+				(p[2] == SSL2_MT_SERVER_HELLO))))
+				{
+				SSLerr(SSL_F_SSL2_READ_INTERNAL,SSL_R_NON_SSLV2_INITIAL_PACKET);
+				return(-1);
+				}
+			}
+		else
+			{
+			n=read_n(s,2,SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER+2,0);
+			if (n <= 0) return(n); /* error or non-blocking */
+			}
+		/* part read stuff */
+
+		s->rstate=SSL_ST_READ_BODY;
+		p=s->packet;
+		/* Do header */
+		/*s->s2->padding=0;*/
+		s->s2->escape=0;
+		s->s2->rlength=(((unsigned int)p[0])<<8)|((unsigned int)p[1]);
+		if ((p[0] & TWO_BYTE_BIT))		/* Two byte header? */
+			{
+			s->s2->three_byte_header=0;
+			s->s2->rlength&=TWO_BYTE_MASK;	
+			}
+		else
+			{
+			s->s2->three_byte_header=1;
+			s->s2->rlength&=THREE_BYTE_MASK;
+
+			/* security >s2->escape */
+			s->s2->escape=((p[0] & SEC_ESC_BIT))?1:0;
+			}
+		}
+
+	if (s->rstate == SSL_ST_READ_BODY)
+		{
+		n=s->s2->rlength+2+s->s2->three_byte_header;
+		if (n > (int)s->packet_length)
+			{
+			n-=s->packet_length;
+			i=read_n(s,(unsigned int)n,(unsigned int)n,1);
+			if (i <= 0) return(i); /* ERROR */
+			}
+
+		p= &(s->packet[2]);
+		s->rstate=SSL_ST_READ_HEADER;
+		if (s->s2->three_byte_header)
+			s->s2->padding= *(p++);
+		else	s->s2->padding=0;
+
+		/* Data portion */
+		if (s->s2->clear_text)
+			{
+			mac_size = 0;
+			s->s2->mac_data=p;
+			s->s2->ract_data=p;
+			if (s->s2->padding)
+				{
+				SSLerr(SSL_F_SSL2_READ_INTERNAL,SSL_R_ILLEGAL_PADDING);
+				return(-1);
+				}
+			}
+		else
+			{
+			mac_size=EVP_MD_CTX_size(s->read_hash);
+			if (mac_size < 0)
+				return -1;
+			OPENSSL_assert(mac_size <= MAX_MAC_SIZE);
+			s->s2->mac_data=p;
+			s->s2->ract_data= &p[mac_size];
+			if (s->s2->padding + mac_size > s->s2->rlength)
+				{
+				SSLerr(SSL_F_SSL2_READ_INTERNAL,SSL_R_ILLEGAL_PADDING);
+				return(-1);
+				}
+			}
+
+		s->s2->ract_data_length=s->s2->rlength;
+		/* added a check for length > max_size in case
+		 * encryption was not turned on yet due to an error */
+		if ((!s->s2->clear_text) &&
+			(s->s2->rlength >= (unsigned int)mac_size))
+			{
+			ssl2_enc(s,0);
+			s->s2->ract_data_length-=mac_size;
+			ssl2_mac(s,mac,0);
+			s->s2->ract_data_length-=s->s2->padding;
+			if (	(memcmp(mac,s->s2->mac_data,
+				(unsigned int)mac_size) != 0) ||
+				(s->s2->rlength%EVP_CIPHER_CTX_block_size(s->enc_read_ctx) != 0))
+				{
+				SSLerr(SSL_F_SSL2_READ_INTERNAL,SSL_R_BAD_MAC_DECODE);
+				return(-1);
+				}
+			}
+		INC32(s->s2->read_sequence); /* expect next number */
+		/* s->s2->ract_data is now available for processing */
+
+		/* Possibly the packet that we just read had 0 actual data bytes.
+		 * (SSLeay/OpenSSL itself never sends such packets; see ssl2_write.)
+		 * In this case, returning 0 would be interpreted by the caller
+		 * as indicating EOF, so it's not a good idea.  Instead, we just
+		 * continue reading; thus ssl2_read_internal may have to process
+		 * multiple packets before it can return.
+		 *
+		 * [Note that using select() for blocking sockets *never* guarantees
+		 * that the next SSL_read will not block -- the available
+		 * data may contain incomplete packets, and except for SSL 2,
+		 * renegotiation can confuse things even more.] */
+
+		goto ssl2_read_again; /* This should really be
+		                       * "return ssl2_read(s,buf,len)",
+		                       * but that would allow for
+		                       * denial-of-service attacks if a
+		                       * C compiler is used that does not
+		                       * recognize end-recursion. */
+		}
+	else
+		{
+		SSLerr(SSL_F_SSL2_READ_INTERNAL,SSL_R_BAD_STATE);
+			return(-1);
+		}
+	}
+
+int ssl2_read(SSL *s, void *buf, int len)
+	{
+	return ssl2_read_internal(s, buf, len, 0);
+	}
+
+int ssl2_peek(SSL *s, void *buf, int len)
+	{
+	return ssl2_read_internal(s, buf, len, 1);
+	}
+
+static int read_n(SSL *s, unsigned int n, unsigned int max,
+	     unsigned int extend)
+	{
+	int i,off,newb;
+
+	/* if there is stuff still in the buffer from a previous read,
+	 * and there is more than we want, take some. */
+	if (s->s2->rbuf_left >= (int)n)
+		{
+		if (extend)
+			s->packet_length+=n;
+		else
+			{
+			s->packet= &(s->s2->rbuf[s->s2->rbuf_offs]);
+			s->packet_length=n;
+			}
+		s->s2->rbuf_left-=n;
+		s->s2->rbuf_offs+=n;
+		return(n);
+		}
+
+	if (!s->read_ahead) max=n;
+	if (max > (unsigned int)(SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER+2))
+		max=SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER+2;
+	
+
+	/* Else we want more than we have.
+	 * First, if there is some left or we want to extend */
+	off=0;
+	if ((s->s2->rbuf_left != 0) || ((s->packet_length != 0) && extend))
+		{
+		newb=s->s2->rbuf_left;
+		if (extend)
+			{
+			off=s->packet_length;
+			if (s->packet != s->s2->rbuf)
+				memcpy(s->s2->rbuf,s->packet,
+					(unsigned int)newb+off);
+			}
+		else if (s->s2->rbuf_offs != 0)
+			{
+			memcpy(s->s2->rbuf,&(s->s2->rbuf[s->s2->rbuf_offs]),
+				(unsigned int)newb);
+			s->s2->rbuf_offs=0;
+			}
+		s->s2->rbuf_left=0;
+		}
+	else
+		newb=0;
+
+	/* off is the offset to start writing too.
+	 * r->s2->rbuf_offs is the 'unread data', now 0. 
+	 * newb is the number of new bytes so far
+	 */
+	s->packet=s->s2->rbuf;
+	while (newb < (int)n)
+		{
+		clear_sys_error();
+		if (s->rbio != NULL)
+			{
+			s->rwstate=SSL_READING;
+			i=BIO_read(s->rbio,(char *)&(s->s2->rbuf[off+newb]),
+				max-newb);
+			}
+		else
+			{
+			SSLerr(SSL_F_READ_N,SSL_R_READ_BIO_NOT_SET);
+			i= -1;
+			}
+#ifdef PKT_DEBUG
+		if (s->debug & 0x01) sleep(1);
+#endif
+		if (i <= 0)
+			{
+			s->s2->rbuf_left+=newb;
+			return(i);
+			}
+		newb+=i;
+		}
+
+	/* record unread data */
+	if (newb > (int)n)
+		{
+		s->s2->rbuf_offs=n+off;
+		s->s2->rbuf_left=newb-n;
+		}
+	else
+		{
+		s->s2->rbuf_offs=0;
+		s->s2->rbuf_left=0;
+		}
+	if (extend)
+		s->packet_length+=n;
+	else
+		s->packet_length=n;
+	s->rwstate=SSL_NOTHING;
+	return(n);
+	}
+
+int ssl2_write(SSL *s, const void *_buf, int len)
+	{
+	const unsigned char *buf=_buf;
+	unsigned int n,tot;
+	int i;
+
+	if (SSL_in_init(s) && !s->in_handshake)
+		{
+		i=s->handshake_func(s);
+		if (i < 0) return(i);
+		if (i == 0)
+			{
+			SSLerr(SSL_F_SSL2_WRITE,SSL_R_SSL_HANDSHAKE_FAILURE);
+			return(-1);
+			}
+		}
+
+	if (s->error)
+		{
+		ssl2_write_error(s);
+		if (s->error)
+			return(-1);
+		}
+
+	clear_sys_error();
+	s->rwstate=SSL_NOTHING;
+	if (len <= 0) return(len);
+
+	tot=s->s2->wnum;
+	s->s2->wnum=0;
+
+	n=(len-tot);
+	for (;;)
+		{
+		i=n_do_ssl_write(s,&(buf[tot]),n);
+		if (i <= 0)
+			{
+			s->s2->wnum=tot;
+			return(i);
+			}
+		if ((i == (int)n) ||
+			(s->mode & SSL_MODE_ENABLE_PARTIAL_WRITE))
+			{
+			return(tot+i);
+			}
+		
+		n-=i;
+		tot+=i;
+		}
+	}
+
+static int write_pending(SSL *s, const unsigned char *buf, unsigned int len)
+	{
+	int i;
+
+	/* s->s2->wpend_len != 0 MUST be true. */
+
+	/* check that they have given us the same buffer to
+	 * write */
+	if ((s->s2->wpend_tot > (int)len) ||
+		((s->s2->wpend_buf != buf) &&
+		 !(s->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)))
+		{
+		SSLerr(SSL_F_WRITE_PENDING,SSL_R_BAD_WRITE_RETRY);
+		return(-1);
+		}
+
+	for (;;)
+		{
+		clear_sys_error();
+		if (s->wbio != NULL)
+			{
+			s->rwstate=SSL_WRITING;
+			i=BIO_write(s->wbio,
+				(char *)&(s->s2->write_ptr[s->s2->wpend_off]),
+				(unsigned int)s->s2->wpend_len);
+			}
+		else
+			{
+			SSLerr(SSL_F_WRITE_PENDING,SSL_R_WRITE_BIO_NOT_SET);
+			i= -1;
+			}
+#ifdef PKT_DEBUG
+		if (s->debug & 0x01) sleep(1);
+#endif
+		if (i == s->s2->wpend_len)
+			{
+			s->s2->wpend_len=0;
+			s->rwstate=SSL_NOTHING;
+			return(s->s2->wpend_ret);
+			}
+		else if (i <= 0)
+			return(i);
+		s->s2->wpend_off+=i;
+		s->s2->wpend_len-=i;
+		}
+	}
+
+static int n_do_ssl_write(SSL *s, const unsigned char *buf, unsigned int len)
+	{
+	unsigned int j,k,olen,p,bs;
+	int mac_size;
+	register unsigned char *pp;
+
+	olen=len;
+
+	/* first check if there is data from an encryption waiting to
+	 * be sent - it must be sent because the other end is waiting.
+	 * This will happen with non-blocking IO.  We print it and then
+	 * return.
+	 */
+	if (s->s2->wpend_len != 0) return(write_pending(s,buf,len));
+
+	/* set mac_size to mac size */
+	if (s->s2->clear_text)
+		mac_size=0;
+	else
+		{
+		mac_size=EVP_MD_CTX_size(s->write_hash);
+		if (mac_size < 0)
+			return -1;
+		}
+
+	/* lets set the pad p */
+	if (s->s2->clear_text)
+		{
+		if (len > SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER)
+			len=SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER;
+		p=0;
+		s->s2->three_byte_header=0;
+		/* len=len; */
+		}
+	else
+		{
+		bs=EVP_CIPHER_CTX_block_size(s->enc_read_ctx);
+		j=len+mac_size;
+		/* Two-byte headers allow for a larger record length than
+		 * three-byte headers, but we can't use them if we need
+		 * padding or if we have to set the escape bit. */
+		if ((j > SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER) &&
+			(!s->s2->escape))
+			{
+			if (j > SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER)
+				j=SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER;
+			/* set k to the max number of bytes with 2
+			 * byte header */
+			k=j-(j%bs);
+			/* how many data bytes? */
+			len=k-mac_size; 
+			s->s2->three_byte_header=0;
+			p=0;
+			}
+		else if ((bs <= 1) && (!s->s2->escape))
+			{
+			/* j <= SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER, thus
+			 * j < SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER */
+			s->s2->three_byte_header=0;
+			p=0;
+			}
+		else /* we may have to use a 3 byte header */
+			{
+			/* If s->s2->escape is not set, then
+			 * j <= SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER, and thus
+			 * j < SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER. */
+			p=(j%bs);
+			p=(p == 0)?0:(bs-p);
+			if (s->s2->escape)
+				{
+				s->s2->three_byte_header=1;
+				if (j > SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER)
+					j=SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER;
+				}
+			else
+				s->s2->three_byte_header=(p == 0)?0:1;
+			}
+		}
+
+	/* Now
+	 *      j <= SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER
+	 * holds, and if s->s2->three_byte_header is set, then even
+	 *      j <= SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER.
+	 */
+
+	/* mac_size is the number of MAC bytes
+	 * len is the number of data bytes we are going to send
+	 * p is the number of padding bytes
+	 * (if it is a two-byte header, then p == 0) */
+
+	s->s2->wlength=len;
+	s->s2->padding=p;
+	s->s2->mac_data= &(s->s2->wbuf[3]);
+	s->s2->wact_data= &(s->s2->wbuf[3+mac_size]);
+	/* we copy the data into s->s2->wbuf */
+	memcpy(s->s2->wact_data,buf,len);
+	if (p)
+		memset(&(s->s2->wact_data[len]),0,p); /* arbitrary padding */
+
+	if (!s->s2->clear_text)
+		{
+		s->s2->wact_data_length=len+p;
+		ssl2_mac(s,s->s2->mac_data,1);
+		s->s2->wlength+=p+mac_size;
+		ssl2_enc(s,1);
+		}
+
+	/* package up the header */
+	s->s2->wpend_len=s->s2->wlength;
+	if (s->s2->three_byte_header) /* 3 byte header */
+		{
+		pp=s->s2->mac_data;
+		pp-=3;
+		pp[0]=(s->s2->wlength>>8)&(THREE_BYTE_MASK>>8);
+		if (s->s2->escape) pp[0]|=SEC_ESC_BIT;
+		pp[1]=s->s2->wlength&0xff;
+		pp[2]=s->s2->padding;
+		s->s2->wpend_len+=3;
+		}
+	else
+		{
+		pp=s->s2->mac_data;
+		pp-=2;
+		pp[0]=((s->s2->wlength>>8)&(TWO_BYTE_MASK>>8))|TWO_BYTE_BIT;
+		pp[1]=s->s2->wlength&0xff;
+		s->s2->wpend_len+=2;
+		}
+	s->s2->write_ptr=pp;
+	
+	INC32(s->s2->write_sequence); /* expect next number */
+
+	/* lets try to actually write the data */
+	s->s2->wpend_tot=olen;
+	s->s2->wpend_buf=buf;
+
+	s->s2->wpend_ret=len;
+
+	s->s2->wpend_off=0;
+	return(write_pending(s,buf,olen));
+	}
+
+int ssl2_part_read(SSL *s, unsigned long f, int i)
+	{
+	unsigned char *p;
+	int j;
+
+	if (i < 0)
+		{
+		/* ssl2_return_error(s); */
+		/* for non-blocking io,
+		 * this is not necessarily fatal */
+		return(i);
+		}
+	else
+		{
+		s->init_num+=i;
+
+		/* Check for error.  While there are recoverable errors,
+		 * this function is not called when those must be expected;
+		 * any error detected here is fatal. */
+		if (s->init_num >= 3)
+			{
+			p=(unsigned char *)s->init_buf->data;
+			if (p[0] == SSL2_MT_ERROR)
+				{
+				j=(p[1]<<8)|p[2];
+				SSLerr((int)f,ssl_mt_error(j));
+				s->init_num -= 3;
+				if (s->init_num > 0)
+					memmove(p, p+3, s->init_num);
+				}
+			}
+
+		/* If it's not an error message, we have some error anyway --
+		 * the message was shorter than expected.  This too is treated
+		 * as fatal (at least if SSL_get_error is asked for its opinion). */
+		return(0);
+		}
+	}
+
+int ssl2_do_write(SSL *s)
+	{
+	int ret;
+
+	ret=ssl2_write(s,&s->init_buf->data[s->init_off],s->init_num);
+	if (ret == s->init_num)
+		{
+		if (s->msg_callback)
+			s->msg_callback(1, s->version, 0, s->init_buf->data, (size_t)(s->init_off + s->init_num), s, s->msg_callback_arg);
+		return(1);
+		}
+	if (ret < 0)
+		return(-1);
+	s->init_off+=ret;
+	s->init_num-=ret;
+	return(0);
+	}
+
+static int ssl_mt_error(int n)
+	{
+	int ret;
+
+	switch (n)
+		{
+	case SSL2_PE_NO_CIPHER:
+		ret=SSL_R_PEER_ERROR_NO_CIPHER;
+		break;
+	case SSL2_PE_NO_CERTIFICATE:
+		ret=SSL_R_PEER_ERROR_NO_CERTIFICATE;
+		break;
+	case SSL2_PE_BAD_CERTIFICATE:
+		ret=SSL_R_PEER_ERROR_CERTIFICATE;
+		break;
+	case SSL2_PE_UNSUPPORTED_CERTIFICATE_TYPE:
+		ret=SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE;
+		break;
+	default:
+		ret=SSL_R_UNKNOWN_REMOTE_ERROR_TYPE;
+		break;
+		}
+	return(ret);
+	}
+#else /* !OPENSSL_NO_SSL2 */
+
+# if PEDANTIC
+static void *dummy=&dummy;
+# endif
+
+#endif
diff --git a/lib/openssl/ssl/s2_srvr.c b/lib/openssl/ssl/s2_srvr.c
new file mode 100644
index 0000000..1434e73
--- /dev/null
+++ b/lib/openssl/ssl/s2_srvr.c
@@ -0,0 +1,1143 @@
+/* ssl/s2_srvr.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include "ssl_locl.h"
+#ifndef OPENSSL_NO_SSL2
+#include <stdio.h>
+#include <openssl/bio.h>
+#include <openssl/rand.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+
+static const SSL_METHOD *ssl2_get_server_method(int ver);
+static int get_client_master_key(SSL *s);
+static int get_client_hello(SSL *s);
+static int server_hello(SSL *s); 
+static int get_client_finished(SSL *s);
+static int server_verify(SSL *s);
+static int server_finish(SSL *s);
+static int request_certificate(SSL *s);
+static int ssl_rsa_private_decrypt(CERT *c, int len, unsigned char *from,
+	unsigned char *to,int padding);
+#define BREAK	break
+
+static const SSL_METHOD *ssl2_get_server_method(int ver)
+	{
+	if (ver == SSL2_VERSION)
+		return(SSLv2_server_method());
+	else
+		return(NULL);
+	}
+
+IMPLEMENT_ssl2_meth_func(SSLv2_server_method,
+			ssl2_accept,
+			ssl_undefined_function,
+			ssl2_get_server_method)
+
+int ssl2_accept(SSL *s)
+	{
+	unsigned long l=(unsigned long)time(NULL);
+	BUF_MEM *buf=NULL;
+	int ret= -1;
+	long num1;
+	void (*cb)(const SSL *ssl,int type,int val)=NULL;
+	int new_state,state;
+
+	RAND_add(&l,sizeof(l),0);
+	ERR_clear_error();
+	clear_sys_error();
+
+	if (s->info_callback != NULL)
+		cb=s->info_callback;
+	else if (s->ctx->info_callback != NULL)
+		cb=s->ctx->info_callback;
+
+	/* init things to blank */
+	s->in_handshake++;
+	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);
+
+	if (s->cert == NULL)
+		{
+		SSLerr(SSL_F_SSL2_ACCEPT,SSL_R_NO_CERTIFICATE_SET);
+		return(-1);
+		}
+
+	clear_sys_error();
+	for (;;)
+		{
+		state=s->state;
+
+		switch (s->state)
+			{
+		case SSL_ST_BEFORE:
+		case SSL_ST_ACCEPT:
+		case SSL_ST_BEFORE|SSL_ST_ACCEPT:
+		case SSL_ST_OK|SSL_ST_ACCEPT:
+
+			s->server=1;
+			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
+
+			s->version=SSL2_VERSION;
+			s->type=SSL_ST_ACCEPT;
+
+			buf=s->init_buf;
+			if ((buf == NULL) && ((buf=BUF_MEM_new()) == NULL))
+				{ ret= -1; goto end; }
+			if (!BUF_MEM_grow(buf,(int)
+				SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER))
+				{ ret= -1; goto end; }
+			s->init_buf=buf;
+			s->init_num=0;
+			s->ctx->stats.sess_accept++;
+			s->handshake_func=ssl2_accept;
+			s->state=SSL2_ST_GET_CLIENT_HELLO_A;
+			BREAK;
+
+		case SSL2_ST_GET_CLIENT_HELLO_A:
+		case SSL2_ST_GET_CLIENT_HELLO_B:
+		case SSL2_ST_GET_CLIENT_HELLO_C:
+			s->shutdown=0;
+			ret=get_client_hello(s);
+			if (ret <= 0) goto end;
+			s->init_num=0;
+			s->state=SSL2_ST_SEND_SERVER_HELLO_A;
+			BREAK;
+
+		case SSL2_ST_SEND_SERVER_HELLO_A:
+		case SSL2_ST_SEND_SERVER_HELLO_B:
+			ret=server_hello(s);
+			if (ret <= 0) goto end;
+			s->init_num=0;
+			if (!s->hit)
+				{
+				s->state=SSL2_ST_GET_CLIENT_MASTER_KEY_A;
+				BREAK;
+				}
+			else
+				{
+				s->state=SSL2_ST_SERVER_START_ENCRYPTION;
+				BREAK;
+				}
+		case SSL2_ST_GET_CLIENT_MASTER_KEY_A:
+		case SSL2_ST_GET_CLIENT_MASTER_KEY_B:
+			ret=get_client_master_key(s);
+			if (ret <= 0) goto end;
+			s->init_num=0;
+			s->state=SSL2_ST_SERVER_START_ENCRYPTION;
+			BREAK;
+
+		case SSL2_ST_SERVER_START_ENCRYPTION:
+			/* Ok we how have sent all the stuff needed to
+			 * start encrypting, the next packet back will
+			 * be encrypted. */
+			if (!ssl2_enc_init(s,0))
+				{ ret= -1; goto end; }
+			s->s2->clear_text=0;
+			s->state=SSL2_ST_SEND_SERVER_VERIFY_A;
+			BREAK;
+
+		case SSL2_ST_SEND_SERVER_VERIFY_A:
+		case SSL2_ST_SEND_SERVER_VERIFY_B:
+			ret=server_verify(s);
+			if (ret <= 0) goto end;
+			s->init_num=0;
+			if (s->hit)
+				{
+				/* If we are in here, we have been
+				 * buffering the output, so we need to
+				 * flush it and remove buffering from
+				 * future traffic */
+				s->state=SSL2_ST_SEND_SERVER_VERIFY_C;
+				BREAK;
+				}
+			else
+				{
+				s->state=SSL2_ST_GET_CLIENT_FINISHED_A;
+				break;
+				}
+
+ 		case SSL2_ST_SEND_SERVER_VERIFY_C:
+ 			/* get the number of bytes to write */
+ 			num1=BIO_ctrl(s->wbio,BIO_CTRL_INFO,0,NULL);
+ 			if (num1 > 0)
+ 				{
+				s->rwstate=SSL_WRITING;
+ 				num1=BIO_flush(s->wbio);
+ 				if (num1 <= 0) { ret= -1; goto end; }
+				s->rwstate=SSL_NOTHING;
+				}
+
+ 			/* flushed and now remove buffering */
+ 			s->wbio=BIO_pop(s->wbio);
+
+ 			s->state=SSL2_ST_GET_CLIENT_FINISHED_A;
+  			BREAK;
+
+		case SSL2_ST_GET_CLIENT_FINISHED_A:
+		case SSL2_ST_GET_CLIENT_FINISHED_B:
+			ret=get_client_finished(s);
+			if (ret <= 0)
+				goto end;
+			s->init_num=0;
+			s->state=SSL2_ST_SEND_REQUEST_CERTIFICATE_A;
+			BREAK;
+
+		case SSL2_ST_SEND_REQUEST_CERTIFICATE_A:
+		case SSL2_ST_SEND_REQUEST_CERTIFICATE_B:
+		case SSL2_ST_SEND_REQUEST_CERTIFICATE_C:
+		case SSL2_ST_SEND_REQUEST_CERTIFICATE_D:
+			/* don't do a 'request certificate' if we
+			 * don't want to, or we already have one, and
+			 * we only want to do it once. */
+			if (!(s->verify_mode & SSL_VERIFY_PEER) ||
+				((s->session->peer != NULL) &&
+				(s->verify_mode & SSL_VERIFY_CLIENT_ONCE)))
+				{
+				s->state=SSL2_ST_SEND_SERVER_FINISHED_A;
+				break;
+				}
+			else
+				{
+				ret=request_certificate(s);
+				if (ret <= 0) goto end;
+				s->init_num=0;
+				s->state=SSL2_ST_SEND_SERVER_FINISHED_A;
+				}
+			BREAK;
+
+		case SSL2_ST_SEND_SERVER_FINISHED_A:
+		case SSL2_ST_SEND_SERVER_FINISHED_B:
+			ret=server_finish(s);
+			if (ret <= 0) goto end;
+			s->init_num=0;
+			s->state=SSL_ST_OK;
+			break;
+
+		case SSL_ST_OK:
+			BUF_MEM_free(s->init_buf);
+			ssl_free_wbio_buffer(s);
+			s->init_buf=NULL;
+			s->init_num=0;
+		/*	ERR_clear_error();*/
+
+			ssl_update_cache(s,SSL_SESS_CACHE_SERVER);
+
+			s->ctx->stats.sess_accept_good++;
+			/* s->server=1; */
+			ret=1;
+
+			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1);
+
+			goto end;
+			/* BREAK; */
+
+		default:
+			SSLerr(SSL_F_SSL2_ACCEPT,SSL_R_UNKNOWN_STATE);
+			ret= -1;
+			goto end;
+			/* BREAK; */
+			}
+		
+		if ((cb != NULL) && (s->state != state))
+			{
+			new_state=s->state;
+			s->state=state;
+			cb(s,SSL_CB_ACCEPT_LOOP,1);
+			s->state=new_state;
+			}
+		}
+end:
+	s->in_handshake--;
+	if (cb != NULL)
+		cb(s,SSL_CB_ACCEPT_EXIT,ret);
+	return(ret);
+	}
+
+static int get_client_master_key(SSL *s)
+	{
+	int is_export,i,n,keya,ek;
+	unsigned long len;
+	unsigned char *p;
+	const SSL_CIPHER *cp;
+	const EVP_CIPHER *c;
+	const EVP_MD *md;
+
+	p=(unsigned char *)s->init_buf->data;
+	if (s->state == SSL2_ST_GET_CLIENT_MASTER_KEY_A)
+		{
+		i=ssl2_read(s,(char *)&(p[s->init_num]),10-s->init_num);
+
+		if (i < (10-s->init_num))
+			return(ssl2_part_read(s,SSL_F_GET_CLIENT_MASTER_KEY,i));
+		s->init_num = 10;
+
+		if (*(p++) != SSL2_MT_CLIENT_MASTER_KEY)
+			{
+			if (p[-1] != SSL2_MT_ERROR)
+				{
+				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+				SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_READ_WRONG_PACKET_TYPE);
+				}
+			else
+				SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, SSL_R_PEER_ERROR);
+			return(-1);
+			}
+
+		cp=ssl2_get_cipher_by_char(p);
+		if (cp == NULL)
+			{
+			ssl2_return_error(s,SSL2_PE_NO_CIPHER);
+			SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, SSL_R_NO_CIPHER_MATCH);
+			return(-1);
+			}
+		s->session->cipher= cp;
+
+		p+=3;
+		n2s(p,i); s->s2->tmp.clear=i;
+		n2s(p,i); s->s2->tmp.enc=i;
+		n2s(p,i); s->session->key_arg_length=i;
+		if(s->session->key_arg_length > SSL_MAX_KEY_ARG_LENGTH)
+			{
+			ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+			SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, SSL_R_KEY_ARG_TOO_LONG);
+			return -1;
+			}
+		s->state=SSL2_ST_GET_CLIENT_MASTER_KEY_B;
+		}
+
+	/* SSL2_ST_GET_CLIENT_MASTER_KEY_B */
+	p=(unsigned char *)s->init_buf->data;
+	if (s->init_buf->length < SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER)
+		{
+		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+		SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, ERR_R_INTERNAL_ERROR);
+		return -1;
+		}
+	keya=s->session->key_arg_length;
+	len = 10 + (unsigned long)s->s2->tmp.clear + (unsigned long)s->s2->tmp.enc + (unsigned long)keya;
+	if (len > SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER)
+		{
+		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+		SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_MESSAGE_TOO_LONG);
+		return -1;
+		}
+	n = (int)len - s->init_num;
+	i = ssl2_read(s,(char *)&(p[s->init_num]),n);
+	if (i != n) return(ssl2_part_read(s,SSL_F_GET_CLIENT_MASTER_KEY,i));
+	if (s->msg_callback)
+		s->msg_callback(0, s->version, 0, p, (size_t)len, s, s->msg_callback_arg); /* CLIENT-MASTER-KEY */
+	p += 10;
+
+	memcpy(s->session->key_arg,&(p[s->s2->tmp.clear+s->s2->tmp.enc]),
+		(unsigned int)keya);
+
+	if (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL)
+		{
+		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+		SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_NO_PRIVATEKEY);
+		return(-1);
+		}
+	i=ssl_rsa_private_decrypt(s->cert,s->s2->tmp.enc,
+		&(p[s->s2->tmp.clear]),&(p[s->s2->tmp.clear]),
+		(s->s2->ssl2_rollback)?RSA_SSLV23_PADDING:RSA_PKCS1_PADDING);
+
+	is_export=SSL_C_IS_EXPORT(s->session->cipher);
+	
+	if (!ssl_cipher_get_evp(s->session,&c,&md,NULL,NULL,NULL))
+		{
+		ssl2_return_error(s,SSL2_PE_NO_CIPHER);
+		SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS);
+		return(0);
+		}
+
+	if (s->session->cipher->algorithm2 & SSL2_CF_8_BYTE_ENC)
+		{
+		is_export=1;
+		ek=8;
+		}
+	else
+		ek=5;
+
+	/* bad decrypt */
+#if 1
+	/* If a bad decrypt, continue with protocol but with a
+	 * random master secret (Bleichenbacher attack) */
+	if ((i < 0) ||
+		((!is_export && (i != EVP_CIPHER_key_length(c)))
+		|| (is_export && ((i != ek) || (s->s2->tmp.clear+(unsigned int)i !=
+			(unsigned int)EVP_CIPHER_key_length(c))))))
+		{
+		ERR_clear_error();
+		if (is_export)
+			i=ek;
+		else
+			i=EVP_CIPHER_key_length(c);
+		if (RAND_pseudo_bytes(p,i) <= 0)
+			return 0;
+		}
+#else
+	if (i < 0)
+		{
+		error=1;
+		SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_BAD_RSA_DECRYPT);
+		}
+	/* incorrect number of key bytes for non export cipher */
+	else if ((!is_export && (i != EVP_CIPHER_key_length(c)))
+		|| (is_export && ((i != ek) || (s->s2->tmp.clear+i !=
+			EVP_CIPHER_key_length(c)))))
+		{
+		error=1;
+		SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_WRONG_NUMBER_OF_KEY_BITS);
+		}
+	if (error)
+		{
+		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+		return(-1);
+		}
+#endif
+
+	if (is_export) i+=s->s2->tmp.clear;
+
+	if (i > SSL_MAX_MASTER_KEY_LENGTH)
+		{
+		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+		SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, ERR_R_INTERNAL_ERROR);
+		return -1;
+		}
+	s->session->master_key_length=i;
+	memcpy(s->session->master_key,p,(unsigned int)i);
+	return(1);
+	}
+
+static int get_client_hello(SSL *s)
+	{
+	int i,n;
+	unsigned long len;
+	unsigned char *p;
+	STACK_OF(SSL_CIPHER) *cs; /* a stack of SSL_CIPHERS */
+	STACK_OF(SSL_CIPHER) *cl; /* the ones we want to use */
+	STACK_OF(SSL_CIPHER) *prio, *allow;
+	int z;
+
+	/* This is a bit of a hack to check for the correct packet
+	 * type the first time round. */
+	if (s->state == SSL2_ST_GET_CLIENT_HELLO_A)
+		{
+		s->first_packet=1;
+		s->state=SSL2_ST_GET_CLIENT_HELLO_B;
+		}
+
+	p=(unsigned char *)s->init_buf->data;
+	if (s->state == SSL2_ST_GET_CLIENT_HELLO_B)
+		{
+		i=ssl2_read(s,(char *)&(p[s->init_num]),9-s->init_num);
+		if (i < (9-s->init_num)) 
+			return(ssl2_part_read(s,SSL_F_GET_CLIENT_HELLO,i));
+		s->init_num = 9;
+	
+		if (*(p++) != SSL2_MT_CLIENT_HELLO)
+			{
+			if (p[-1] != SSL2_MT_ERROR)
+				{
+				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+				SSLerr(SSL_F_GET_CLIENT_HELLO,SSL_R_READ_WRONG_PACKET_TYPE);
+				}
+			else
+				SSLerr(SSL_F_GET_CLIENT_HELLO,SSL_R_PEER_ERROR);
+			return(-1);
+			}
+		n2s(p,i);
+		if (i < s->version) s->version=i;
+		n2s(p,i); s->s2->tmp.cipher_spec_length=i;
+		n2s(p,i); s->s2->tmp.session_id_length=i;
+		n2s(p,i); s->s2->challenge_length=i;
+		if (	(i < SSL2_MIN_CHALLENGE_LENGTH) ||
+			(i > SSL2_MAX_CHALLENGE_LENGTH))
+			{
+			ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+			SSLerr(SSL_F_GET_CLIENT_HELLO,SSL_R_INVALID_CHALLENGE_LENGTH);
+			return(-1);
+			}
+		s->state=SSL2_ST_GET_CLIENT_HELLO_C;
+		}
+
+	/* SSL2_ST_GET_CLIENT_HELLO_C */
+	p=(unsigned char *)s->init_buf->data;
+	len = 9 + (unsigned long)s->s2->tmp.cipher_spec_length + (unsigned long)s->s2->challenge_length + (unsigned long)s->s2->tmp.session_id_length;
+	if (len > SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER)
+		{
+		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+		SSLerr(SSL_F_GET_CLIENT_HELLO,SSL_R_MESSAGE_TOO_LONG);
+		return -1;
+		}
+	n = (int)len - s->init_num;
+	i = ssl2_read(s,(char *)&(p[s->init_num]),n);
+	if (i != n) return(ssl2_part_read(s,SSL_F_GET_CLIENT_HELLO,i));
+	if (s->msg_callback)
+		s->msg_callback(0, s->version, 0, p, (size_t)len, s, s->msg_callback_arg); /* CLIENT-HELLO */
+	p += 9;
+
+	/* get session-id before cipher stuff so we can get out session
+	 * structure if it is cached */
+	/* session-id */
+	if ((s->s2->tmp.session_id_length != 0) && 
+		(s->s2->tmp.session_id_length != SSL2_SSL_SESSION_ID_LENGTH))
+		{
+		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+		SSLerr(SSL_F_GET_CLIENT_HELLO,SSL_R_BAD_SSL_SESSION_ID_LENGTH);
+		return(-1);
+		}
+
+	if (s->s2->tmp.session_id_length == 0)
+		{
+		if (!ssl_get_new_session(s,1))
+			{
+			ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+			return(-1);
+			}
+		}
+	else
+		{
+		i=ssl_get_prev_session(s,&(p[s->s2->tmp.cipher_spec_length]),
+			s->s2->tmp.session_id_length, NULL);
+		if (i == 1)
+			{ /* previous session */
+			s->hit=1;
+			}
+		else if (i == -1)
+			{
+			ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+			return(-1);
+			}
+		else
+			{
+			if (s->cert == NULL)
+				{
+				ssl2_return_error(s,SSL2_PE_NO_CERTIFICATE);
+				SSLerr(SSL_F_GET_CLIENT_HELLO,SSL_R_NO_CERTIFICATE_SET);
+				return(-1);
+				}
+
+			if (!ssl_get_new_session(s,1))
+				{
+				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+				return(-1);
+				}
+			}
+		}
+
+	if (!s->hit)
+		{
+		cs=ssl_bytes_to_cipher_list(s,p,s->s2->tmp.cipher_spec_length,
+			&s->session->ciphers);
+		if (cs == NULL) goto mem_err;
+
+		cl=SSL_get_ciphers(s);
+
+		if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE)
+		    {
+		    prio=sk_SSL_CIPHER_dup(cl);
+		    if (prio == NULL) goto mem_err;
+		    allow = cs;
+		    }
+		else
+		    {
+		    prio = cs;
+		    allow = cl;
+		    }
+		for (z=0; z<sk_SSL_CIPHER_num(prio); z++)
+			{
+			if (sk_SSL_CIPHER_find(allow,sk_SSL_CIPHER_value(prio,z)) < 0)
+				{
+				(void)sk_SSL_CIPHER_delete(prio,z);
+				z--;
+				}
+			}
+		if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE)
+		    {
+		    sk_SSL_CIPHER_free(s->session->ciphers);
+		    s->session->ciphers = prio;
+		    }
+		/* s->session->ciphers should now have a list of
+		 * ciphers that are on both the client and server.
+		 * This list is ordered by the order the client sent
+		 * the ciphers or in the order of the server's preference
+		 * if SSL_OP_CIPHER_SERVER_PREFERENCE was set.
+		 */
+		}
+	p+=s->s2->tmp.cipher_spec_length;
+	/* done cipher selection */
+
+	/* session id extracted already */
+	p+=s->s2->tmp.session_id_length;
+
+	/* challenge */
+	if (s->s2->challenge_length > sizeof s->s2->challenge)
+		{
+		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+		SSLerr(SSL_F_GET_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+		return -1;
+		}
+	memcpy(s->s2->challenge,p,(unsigned int)s->s2->challenge_length);
+	return(1);
+mem_err:
+	SSLerr(SSL_F_GET_CLIENT_HELLO,ERR_R_MALLOC_FAILURE);
+	return(0);
+	}
+
+static int server_hello(SSL *s)
+	{
+	unsigned char *p,*d;
+	int n,hit;
+	STACK_OF(SSL_CIPHER) *sk;
+
+	p=(unsigned char *)s->init_buf->data;
+	if (s->state == SSL2_ST_SEND_SERVER_HELLO_A)
+		{
+		d=p+11;
+		*(p++)=SSL2_MT_SERVER_HELLO;		/* type */
+		hit=s->hit;
+		*(p++)=(unsigned char)hit;
+#if 1
+		if (!hit)
+			{
+			if (s->session->sess_cert != NULL)
+				/* This can't really happen because get_client_hello
+				 * has called ssl_get_new_session, which does not set
+				 * sess_cert. */
+				ssl_sess_cert_free(s->session->sess_cert);
+			s->session->sess_cert = ssl_sess_cert_new();
+			if (s->session->sess_cert == NULL)
+				{
+				SSLerr(SSL_F_SERVER_HELLO, ERR_R_MALLOC_FAILURE);
+				return(-1);
+				}
+			}
+		/* If 'hit' is set, then s->sess_cert may be non-NULL or NULL,
+		 * depending on whether it survived in the internal cache
+		 * or was retrieved from an external cache.
+		 * If it is NULL, we cannot put any useful data in it anyway,
+		 * so we don't touch it.
+		 */
+
+#else /* That's what used to be done when cert_st and sess_cert_st were
+	   * the same. */
+		if (!hit)
+			{			/* else add cert to session */
+			CRYPTO_add(&s->cert->references,1,CRYPTO_LOCK_SSL_CERT);
+			if (s->session->sess_cert != NULL)
+				ssl_cert_free(s->session->sess_cert);
+			s->session->sess_cert=s->cert;		
+			}
+		else	/* We have a session id-cache hit, if the
+			 * session-id has no certificate listed against
+			 * the 'cert' structure, grab the 'old' one
+			 * listed against the SSL connection */
+			{
+			if (s->session->sess_cert == NULL)
+				{
+				CRYPTO_add(&s->cert->references,1,
+					CRYPTO_LOCK_SSL_CERT);
+				s->session->sess_cert=s->cert;
+				}
+			}
+#endif
+
+		if (s->cert == NULL)
+			{
+			ssl2_return_error(s,SSL2_PE_NO_CERTIFICATE);
+			SSLerr(SSL_F_SERVER_HELLO,SSL_R_NO_CERTIFICATE_SPECIFIED);
+			return(-1);
+			}
+
+		if (hit)
+			{
+			*(p++)=0;		/* no certificate type */
+			s2n(s->version,p);	/* version */
+			s2n(0,p);		/* cert len */
+			s2n(0,p);		/* ciphers len */
+			}
+		else
+			{
+			/* EAY EAY */
+			/* put certificate type */
+			*(p++)=SSL2_CT_X509_CERTIFICATE;
+			s2n(s->version,p);	/* version */
+			n=i2d_X509(s->cert->pkeys[SSL_PKEY_RSA_ENC].x509,NULL);
+			s2n(n,p);		/* certificate length */
+			i2d_X509(s->cert->pkeys[SSL_PKEY_RSA_ENC].x509,&d);
+			n=0;
+			
+			/* lets send out the ciphers we like in the
+			 * prefered order */
+			sk= s->session->ciphers;
+			n=ssl_cipher_list_to_bytes(s,s->session->ciphers,d,0);
+			d+=n;
+			s2n(n,p);		/* add cipher length */
+			}
+
+		/* make and send conn_id */
+		s2n(SSL2_CONNECTION_ID_LENGTH,p);	/* add conn_id length */
+		s->s2->conn_id_length=SSL2_CONNECTION_ID_LENGTH;
+		if (RAND_pseudo_bytes(s->s2->conn_id,(int)s->s2->conn_id_length) <= 0)
+			return -1;
+		memcpy(d,s->s2->conn_id,SSL2_CONNECTION_ID_LENGTH);
+		d+=SSL2_CONNECTION_ID_LENGTH;
+
+		s->state=SSL2_ST_SEND_SERVER_HELLO_B;
+		s->init_num=d-(unsigned char *)s->init_buf->data;
+		s->init_off=0;
+		}
+	/* SSL2_ST_SEND_SERVER_HELLO_B */
+ 	/* If we are using TCP/IP, the performance is bad if we do 2
+ 	 * writes without a read between them.  This occurs when
+ 	 * Session-id reuse is used, so I will put in a buffering module
+ 	 */
+ 	if (s->hit)
+ 		{
+		if (!ssl_init_wbio_buffer(s,1)) return(-1);
+ 		}
+ 
+	return(ssl2_do_write(s));
+	}
+
+static int get_client_finished(SSL *s)
+	{
+	unsigned char *p;
+	int i, n;
+	unsigned long len;
+
+	p=(unsigned char *)s->init_buf->data;
+	if (s->state == SSL2_ST_GET_CLIENT_FINISHED_A)
+		{
+		i=ssl2_read(s,(char *)&(p[s->init_num]),1-s->init_num);
+		if (i < 1-s->init_num)
+			return(ssl2_part_read(s,SSL_F_GET_CLIENT_FINISHED,i));
+		s->init_num += i;
+
+		if (*p != SSL2_MT_CLIENT_FINISHED)
+			{
+			if (*p != SSL2_MT_ERROR)
+				{
+				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+				SSLerr(SSL_F_GET_CLIENT_FINISHED,SSL_R_READ_WRONG_PACKET_TYPE);
+				}
+			else
+				{
+				SSLerr(SSL_F_GET_CLIENT_FINISHED,SSL_R_PEER_ERROR);
+				/* try to read the error message */
+				i=ssl2_read(s,(char *)&(p[s->init_num]),3-s->init_num);
+				return ssl2_part_read(s,SSL_F_GET_SERVER_VERIFY,i);
+				}
+			return(-1);
+			}
+		s->state=SSL2_ST_GET_CLIENT_FINISHED_B;
+		}
+
+	/* SSL2_ST_GET_CLIENT_FINISHED_B */
+	if (s->s2->conn_id_length > sizeof s->s2->conn_id)
+		{
+		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+		SSLerr(SSL_F_GET_CLIENT_FINISHED, ERR_R_INTERNAL_ERROR);
+		return -1;
+		}
+	len = 1 + (unsigned long)s->s2->conn_id_length;
+	n = (int)len - s->init_num;
+	i = ssl2_read(s,(char *)&(p[s->init_num]),n);
+	if (i < n)
+		{
+		return(ssl2_part_read(s,SSL_F_GET_CLIENT_FINISHED,i));
+		}
+	if (s->msg_callback)
+		s->msg_callback(0, s->version, 0, p, len, s, s->msg_callback_arg); /* CLIENT-FINISHED */
+	p += 1;
+	if (memcmp(p,s->s2->conn_id,s->s2->conn_id_length) != 0)
+		{
+		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+		SSLerr(SSL_F_GET_CLIENT_FINISHED,SSL_R_CONNECTION_ID_IS_DIFFERENT);
+		return(-1);
+		}
+	return(1);
+	}
+
+static int server_verify(SSL *s)
+	{
+	unsigned char *p;
+
+	if (s->state == SSL2_ST_SEND_SERVER_VERIFY_A)
+		{
+		p=(unsigned char *)s->init_buf->data;
+		*(p++)=SSL2_MT_SERVER_VERIFY;
+		if (s->s2->challenge_length > sizeof s->s2->challenge)
+			{
+			SSLerr(SSL_F_SERVER_VERIFY, ERR_R_INTERNAL_ERROR);
+			return -1;
+			}
+		memcpy(p,s->s2->challenge,(unsigned int)s->s2->challenge_length);
+		/* p+=s->s2->challenge_length; */
+
+		s->state=SSL2_ST_SEND_SERVER_VERIFY_B;
+		s->init_num=s->s2->challenge_length+1;
+		s->init_off=0;
+		}
+	return(ssl2_do_write(s));
+	}
+
+static int server_finish(SSL *s)
+	{
+	unsigned char *p;
+
+	if (s->state == SSL2_ST_SEND_SERVER_FINISHED_A)
+		{
+		p=(unsigned char *)s->init_buf->data;
+		*(p++)=SSL2_MT_SERVER_FINISHED;
+
+		if (s->session->session_id_length > sizeof s->session->session_id)
+			{
+			SSLerr(SSL_F_SERVER_FINISH, ERR_R_INTERNAL_ERROR);
+			return -1;
+			}
+		memcpy(p,s->session->session_id, (unsigned int)s->session->session_id_length);
+		/* p+=s->session->session_id_length; */
+
+		s->state=SSL2_ST_SEND_SERVER_FINISHED_B;
+		s->init_num=s->session->session_id_length+1;
+		s->init_off=0;
+		}
+
+	/* SSL2_ST_SEND_SERVER_FINISHED_B */
+	return(ssl2_do_write(s));
+	}
+
+/* send the request and check the response */
+static int request_certificate(SSL *s)
+	{
+	const unsigned char *cp;
+	unsigned char *p,*p2,*buf2;
+	unsigned char *ccd;
+	int i,j,ctype,ret= -1;
+	unsigned long len;
+	X509 *x509=NULL;
+	STACK_OF(X509) *sk=NULL;
+
+	ccd=s->s2->tmp.ccl;
+	if (s->state == SSL2_ST_SEND_REQUEST_CERTIFICATE_A)
+		{
+		p=(unsigned char *)s->init_buf->data;
+		*(p++)=SSL2_MT_REQUEST_CERTIFICATE;
+		*(p++)=SSL2_AT_MD5_WITH_RSA_ENCRYPTION;
+		if (RAND_pseudo_bytes(ccd,SSL2_MIN_CERT_CHALLENGE_LENGTH) <= 0)
+			return -1;
+		memcpy(p,ccd,SSL2_MIN_CERT_CHALLENGE_LENGTH);
+
+		s->state=SSL2_ST_SEND_REQUEST_CERTIFICATE_B;
+		s->init_num=SSL2_MIN_CERT_CHALLENGE_LENGTH+2;
+		s->init_off=0;
+		}
+
+	if (s->state == SSL2_ST_SEND_REQUEST_CERTIFICATE_B)
+		{
+		i=ssl2_do_write(s);
+		if (i <= 0)
+			{
+			ret=i;
+			goto end;
+			}
+
+		s->init_num=0;
+		s->state=SSL2_ST_SEND_REQUEST_CERTIFICATE_C;
+		}
+
+	if (s->state == SSL2_ST_SEND_REQUEST_CERTIFICATE_C)
+		{
+		p=(unsigned char *)s->init_buf->data;
+		i=ssl2_read(s,(char *)&(p[s->init_num]),6-s->init_num); /* try to read 6 octets ... */
+		if (i < 3-s->init_num) /* ... but don't call ssl2_part_read now if we got at least 3
+		                        * (probably NO-CERTIFICATE-ERROR) */
+			{
+			ret=ssl2_part_read(s,SSL_F_REQUEST_CERTIFICATE,i);
+			goto end;
+			}
+		s->init_num += i;
+
+		if ((s->init_num >= 3) && (p[0] == SSL2_MT_ERROR))
+			{
+			n2s(p,i);
+			if (i != SSL2_PE_NO_CERTIFICATE)
+				{
+				/* not the error message we expected -- let ssl2_part_read handle it */
+				s->init_num -= 3;
+				ret = ssl2_part_read(s,SSL_F_REQUEST_CERTIFICATE, 3);
+				goto end;
+				}
+
+			if (s->msg_callback)
+				s->msg_callback(0, s->version, 0, p, 3, s, s->msg_callback_arg); /* ERROR */
+
+			/* this is the one place where we can recover from an SSL 2.0 error */
+
+			if (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)
+				{
+				ssl2_return_error(s,SSL2_PE_BAD_CERTIFICATE);
+				SSLerr(SSL_F_REQUEST_CERTIFICATE,SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
+				goto end;
+				}
+			ret=1;
+			goto end;
+			}
+		if ((*(p++) != SSL2_MT_CLIENT_CERTIFICATE) || (s->init_num < 6))
+			{
+			ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+			SSLerr(SSL_F_REQUEST_CERTIFICATE,SSL_R_SHORT_READ);
+			goto end;
+			}
+		if (s->init_num != 6)
+			{
+			SSLerr(SSL_F_REQUEST_CERTIFICATE, ERR_R_INTERNAL_ERROR);
+			goto end;
+			}
+		
+		/* ok we have a response */
+		/* certificate type, there is only one right now. */
+		ctype= *(p++);
+		if (ctype != SSL2_AT_MD5_WITH_RSA_ENCRYPTION)
+			{
+			ssl2_return_error(s,SSL2_PE_UNSUPPORTED_CERTIFICATE_TYPE);
+			SSLerr(SSL_F_REQUEST_CERTIFICATE,SSL_R_BAD_RESPONSE_ARGUMENT);
+			goto end;
+			}
+		n2s(p,i); s->s2->tmp.clen=i;
+		n2s(p,i); s->s2->tmp.rlen=i;
+		s->state=SSL2_ST_SEND_REQUEST_CERTIFICATE_D;
+		}
+
+	/* SSL2_ST_SEND_REQUEST_CERTIFICATE_D */
+	p=(unsigned char *)s->init_buf->data;
+	len = 6 + (unsigned long)s->s2->tmp.clen + (unsigned long)s->s2->tmp.rlen;
+	if (len > SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER)
+		{
+		SSLerr(SSL_F_REQUEST_CERTIFICATE,SSL_R_MESSAGE_TOO_LONG);
+		goto end;
+		}
+	j = (int)len - s->init_num;
+	i = ssl2_read(s,(char *)&(p[s->init_num]),j);
+	if (i < j) 
+		{
+		ret=ssl2_part_read(s,SSL_F_REQUEST_CERTIFICATE,i);
+		goto end;
+		}
+	if (s->msg_callback)
+		s->msg_callback(0, s->version, 0, p, len, s, s->msg_callback_arg); /* CLIENT-CERTIFICATE */
+	p += 6;
+
+	cp = p;
+	x509=(X509 *)d2i_X509(NULL,&cp,(long)s->s2->tmp.clen);
+	if (x509 == NULL)
+		{
+		SSLerr(SSL_F_REQUEST_CERTIFICATE,ERR_R_X509_LIB);
+		goto msg_end;
+		}
+
+	if (((sk=sk_X509_new_null()) == NULL) || (!sk_X509_push(sk,x509)))
+		{
+		SSLerr(SSL_F_REQUEST_CERTIFICATE,ERR_R_MALLOC_FAILURE);
+		goto msg_end;
+		}
+
+	i=ssl_verify_cert_chain(s,sk);
+
+	if (i > 0)	/* we like the packet, now check the chksum */
+		{
+		EVP_MD_CTX ctx;
+		EVP_PKEY *pkey=NULL;
+
+		EVP_MD_CTX_init(&ctx);
+		EVP_VerifyInit_ex(&ctx,s->ctx->rsa_md5, NULL);
+		EVP_VerifyUpdate(&ctx,s->s2->key_material,
+				 s->s2->key_material_length);
+		EVP_VerifyUpdate(&ctx,ccd,SSL2_MIN_CERT_CHALLENGE_LENGTH);
+
+		i=i2d_X509(s->cert->pkeys[SSL_PKEY_RSA_ENC].x509,NULL);
+		buf2=OPENSSL_malloc((unsigned int)i);
+		if (buf2 == NULL)
+			{
+			SSLerr(SSL_F_REQUEST_CERTIFICATE,ERR_R_MALLOC_FAILURE);
+			goto msg_end;
+			}
+		p2=buf2;
+		i=i2d_X509(s->cert->pkeys[SSL_PKEY_RSA_ENC].x509,&p2);
+		EVP_VerifyUpdate(&ctx,buf2,(unsigned int)i);
+		OPENSSL_free(buf2);
+
+		pkey=X509_get_pubkey(x509);
+		if (pkey == NULL) goto end;
+		i=EVP_VerifyFinal(&ctx,cp,s->s2->tmp.rlen,pkey);
+		EVP_PKEY_free(pkey);
+		EVP_MD_CTX_cleanup(&ctx);
+
+		if (i > 0)
+			{
+			if (s->session->peer != NULL)
+				X509_free(s->session->peer);
+			s->session->peer=x509;
+			CRYPTO_add(&x509->references,1,CRYPTO_LOCK_X509);
+			s->session->verify_result = s->verify_result;
+			ret=1;
+			goto end;
+			}
+		else
+			{
+			SSLerr(SSL_F_REQUEST_CERTIFICATE,SSL_R_BAD_CHECKSUM);
+			goto msg_end;
+			}
+		}
+	else
+		{
+msg_end:
+		ssl2_return_error(s,SSL2_PE_BAD_CERTIFICATE);
+		}
+end:
+	sk_X509_free(sk);
+	X509_free(x509);
+	return(ret);
+	}
+
+static int ssl_rsa_private_decrypt(CERT *c, int len, unsigned char *from,
+	     unsigned char *to, int padding)
+	{
+	RSA *rsa;
+	int i;
+
+	if ((c == NULL) || (c->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL))
+		{
+		SSLerr(SSL_F_SSL_RSA_PRIVATE_DECRYPT,SSL_R_NO_PRIVATEKEY);
+		return(-1);
+		}
+	if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey->type != EVP_PKEY_RSA)
+		{
+		SSLerr(SSL_F_SSL_RSA_PRIVATE_DECRYPT,SSL_R_PUBLIC_KEY_IS_NOT_RSA);
+		return(-1);
+		}
+	rsa=c->pkeys[SSL_PKEY_RSA_ENC].privatekey->pkey.rsa;
+
+	/* we have the public key */
+	i=RSA_private_decrypt(len,from,to,rsa,padding);
+	if (i < 0)
+		SSLerr(SSL_F_SSL_RSA_PRIVATE_DECRYPT,ERR_R_RSA_LIB);
+	return(i);
+	}
+#else /* !OPENSSL_NO_SSL2 */
+
+# if PEDANTIC
+static void *dummy=&dummy;
+# endif
+
+#endif
diff --git a/lib/openssl/ssl/s3_both.c b/lib/openssl/ssl/s3_both.c
new file mode 100644
index 0000000..06d5b2c
--- /dev/null
+++ b/lib/openssl/ssl/s3_both.c
@@ -0,0 +1,833 @@
+/* ssl/s3_both.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECC cipher suite support in OpenSSL originally developed by 
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#include <limits.h>
+#include <string.h>
+#include <stdio.h>
+#include "ssl_locl.h"
+#include <openssl/buffer.h>
+#include <openssl/rand.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+
+/* send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC) */
+int ssl3_do_write(SSL *s, int type)
+	{
+	int ret;
+
+	ret=ssl3_write_bytes(s,type,&s->init_buf->data[s->init_off],
+	                     s->init_num);
+	if (ret < 0) return(-1);
+	if (type == SSL3_RT_HANDSHAKE)
+		/* should not be done for 'Hello Request's, but in that case
+		 * we'll ignore the result anyway */
+		ssl3_finish_mac(s,(unsigned char *)&s->init_buf->data[s->init_off],ret);
+	
+	if (ret == s->init_num)
+		{
+		if (s->msg_callback)
+			s->msg_callback(1, s->version, type, s->init_buf->data, (size_t)(s->init_off + s->init_num), s, s->msg_callback_arg);
+		return(1);
+		}
+	s->init_off+=ret;
+	s->init_num-=ret;
+	return(0);
+	}
+
+int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen)
+	{
+	unsigned char *p,*d;
+	int i;
+	unsigned long l;
+
+	if (s->state == a)
+		{
+		d=(unsigned char *)s->init_buf->data;
+		p= &(d[4]);
+
+		i=s->method->ssl3_enc->final_finish_mac(s,
+			sender,slen,s->s3->tmp.finish_md);
+		s->s3->tmp.finish_md_len = i;
+		memcpy(p, s->s3->tmp.finish_md, i);
+		p+=i;
+		l=i;
+
+                /* Copy the finished so we can use it for
+                   renegotiation checks */
+                if(s->type == SSL_ST_CONNECT)
+                        {
+                         OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
+                         memcpy(s->s3->previous_client_finished, 
+                             s->s3->tmp.finish_md, i);
+                         s->s3->previous_client_finished_len=i;
+                        }
+                else
+                        {
+                        OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
+                        memcpy(s->s3->previous_server_finished, 
+                            s->s3->tmp.finish_md, i);
+                        s->s3->previous_server_finished_len=i;
+                        }
+
+#ifdef OPENSSL_SYS_WIN16
+		/* MSVC 1.5 does not clear the top bytes of the word unless
+		 * I do this.
+		 */
+		l&=0xffff;
+#endif
+
+		*(d++)=SSL3_MT_FINISHED;
+		l2n3(l,d);
+		s->init_num=(int)l+4;
+		s->init_off=0;
+
+		s->state=b;
+		}
+
+	/* SSL3_ST_SEND_xxxxxx_HELLO_B */
+	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+	}
+
+int ssl3_get_finished(SSL *s, int a, int b)
+	{
+	int al,i,ok;
+	long n;
+	unsigned char *p;
+
+	/* the mac has already been generated when we received the
+	 * change cipher spec message and is in s->s3->tmp.peer_finish_md
+	 */ 
+
+	n=s->method->ssl_get_message(s,
+		a,
+		b,
+		SSL3_MT_FINISHED,
+		64, /* should actually be 36+4 :-) */
+		&ok);
+
+	if (!ok) return((int)n);
+
+	/* If this occurs, we have missed a message */
+	if (!s->s3->change_cipher_spec)
+		{
+		al=SSL_AD_UNEXPECTED_MESSAGE;
+		SSLerr(SSL_F_SSL3_GET_FINISHED,SSL_R_GOT_A_FIN_BEFORE_A_CCS);
+		goto f_err;
+		}
+	s->s3->change_cipher_spec=0;
+
+	p = (unsigned char *)s->init_msg;
+	i = s->s3->tmp.peer_finish_md_len;
+
+	if (i != n)
+		{
+		al=SSL_AD_DECODE_ERROR;
+		SSLerr(SSL_F_SSL3_GET_FINISHED,SSL_R_BAD_DIGEST_LENGTH);
+		goto f_err;
+		}
+
+	if (memcmp(p, s->s3->tmp.peer_finish_md, i) != 0)
+		{
+		al=SSL_AD_DECRYPT_ERROR;
+		SSLerr(SSL_F_SSL3_GET_FINISHED,SSL_R_DIGEST_CHECK_FAILED);
+		goto f_err;
+		}
+
+        /* Copy the finished so we can use it for
+           renegotiation checks */
+        if(s->type == SSL_ST_ACCEPT)
+                {
+                OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
+                memcpy(s->s3->previous_client_finished, 
+                    s->s3->tmp.peer_finish_md, i);
+                s->s3->previous_client_finished_len=i;
+                }
+        else
+                {
+                OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
+                memcpy(s->s3->previous_server_finished, 
+                    s->s3->tmp.peer_finish_md, i);
+                s->s3->previous_server_finished_len=i;
+                }
+
+	return(1);
+f_err:
+	ssl3_send_alert(s,SSL3_AL_FATAL,al);
+	return(0);
+	}
+
+/* for these 2 messages, we need to
+ * ssl->enc_read_ctx			re-init
+ * ssl->s3->read_sequence		zero
+ * ssl->s3->read_mac_secret		re-init
+ * ssl->session->read_sym_enc		assign
+ * ssl->session->read_compression	assign
+ * ssl->session->read_hash		assign
+ */
+int ssl3_send_change_cipher_spec(SSL *s, int a, int b)
+	{ 
+	unsigned char *p;
+
+	if (s->state == a)
+		{
+		p=(unsigned char *)s->init_buf->data;
+		*p=SSL3_MT_CCS;
+		s->init_num=1;
+		s->init_off=0;
+
+		s->state=b;
+		}
+
+	/* SSL3_ST_CW_CHANGE_B */
+	return(ssl3_do_write(s,SSL3_RT_CHANGE_CIPHER_SPEC));
+	}
+
+static int ssl3_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x)
+	{
+	int n;
+	unsigned char *p;
+
+	n=i2d_X509(x,NULL);
+	if (!BUF_MEM_grow_clean(buf,(int)(n+(*l)+3)))
+		{
+		SSLerr(SSL_F_SSL3_ADD_CERT_TO_BUF,ERR_R_BUF_LIB);
+		return(-1);
+		}
+	p=(unsigned char *)&(buf->data[*l]);
+	l2n3(n,p);
+	i2d_X509(x,&p);
+	*l+=n+3;
+
+	return(0);
+	}
+
+unsigned long ssl3_output_cert_chain(SSL *s, X509 *x)
+	{
+	unsigned char *p;
+	int i;
+	unsigned long l=7;
+	BUF_MEM *buf;
+	int no_chain;
+	STACK_OF(X509) *cert_chain;
+
+	cert_chain = SSL_get_certificate_chain(s, x);
+
+	if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || s->ctx->extra_certs || cert_chain)
+		no_chain = 1;
+	else
+		no_chain = 0;
+
+	/* TLSv1 sends a chain with nothing in it, instead of an alert */
+	buf=s->init_buf;
+	if (!BUF_MEM_grow_clean(buf,10))
+		{
+		SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB);
+		return(0);
+		}
+	if (x != NULL)
+		{
+		if (no_chain)
+			{
+			if (ssl3_add_cert_to_buf(buf, &l, x))
+				return(0);
+			}
+		else
+			{
+			X509_STORE_CTX xs_ctx;
+
+			if (!X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,x,NULL))
+				{
+				SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN,ERR_R_X509_LIB);
+				return(0);
+				}
+			X509_verify_cert(&xs_ctx);
+			/* Don't leave errors in the queue */
+			ERR_clear_error();
+			for (i=0; i < sk_X509_num(xs_ctx.chain); i++)
+				{
+				x = sk_X509_value(xs_ctx.chain, i);
+
+				if (ssl3_add_cert_to_buf(buf, &l, x))
+					{
+					X509_STORE_CTX_cleanup(&xs_ctx);
+					return 0;
+					}
+				}
+			X509_STORE_CTX_cleanup(&xs_ctx);
+			}
+		}
+	/* Thawte special :-) */
+	for (i=0; i<sk_X509_num(s->ctx->extra_certs); i++)
+		{
+		x=sk_X509_value(s->ctx->extra_certs,i);
+		if (ssl3_add_cert_to_buf(buf, &l, x))
+			return(0);
+		}
+
+	for (i=0; i<sk_X509_num(cert_chain); i++)
+		if (ssl3_add_cert_to_buf(buf, &l, sk_X509_value(cert_chain,i)))
+			return(0);
+
+	l-=7;
+	p=(unsigned char *)&(buf->data[4]);
+	l2n3(l,p);
+	l+=3;
+	p=(unsigned char *)&(buf->data[0]);
+	*(p++)=SSL3_MT_CERTIFICATE;
+	l2n3(l,p);
+	l+=4;
+	return(l);
+	}
+
+/* Obtain handshake message of message type 'mt' (any if mt == -1),
+ * maximum acceptable body length 'max'.
+ * The first four bytes (msg_type and length) are read in state 'st1',
+ * the body is read in state 'stn'.
+ */
+long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
+	{
+	unsigned char *p;
+	unsigned long l;
+	long n;
+	int i,al;
+
+	if (s->s3->tmp.reuse_message)
+		{
+		s->s3->tmp.reuse_message=0;
+		if ((mt >= 0) && (s->s3->tmp.message_type != mt))
+			{
+			al=SSL_AD_UNEXPECTED_MESSAGE;
+			SSLerr(SSL_F_SSL3_GET_MESSAGE,SSL_R_UNEXPECTED_MESSAGE);
+			goto f_err;
+			}
+		*ok=1;
+		s->init_msg = s->init_buf->data + 4;
+		s->init_num = (int)s->s3->tmp.message_size;
+		return s->init_num;
+		}
+
+	p=(unsigned char *)s->init_buf->data;
+
+	if (s->state == st1) /* s->init_num < 4 */
+		{
+		int skip_message;
+
+		do
+			{
+			while (s->init_num < 4)
+				{
+				i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
+					&p[s->init_num],4 - s->init_num, 0);
+				if (i <= 0)
+					{
+					s->rwstate=SSL_READING;
+					*ok = 0;
+					return i;
+					}
+				s->init_num+=i;
+				}
+			
+			skip_message = 0;
+			if (!s->server)
+				if (p[0] == SSL3_MT_HELLO_REQUEST)
+					/* The server may always send 'Hello Request' messages --
+					 * we are doing a handshake anyway now, so ignore them
+					 * if their format is correct. Does not count for
+					 * 'Finished' MAC. */
+					if (p[1] == 0 && p[2] == 0 &&p[3] == 0)
+						{
+						s->init_num = 0;
+						skip_message = 1;
+
+						if (s->msg_callback)
+							s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, p, 4, s, s->msg_callback_arg);
+						}
+			}
+		while (skip_message);
+
+		/* s->init_num == 4 */
+
+		if ((mt >= 0) && (*p != mt))
+			{
+			al=SSL_AD_UNEXPECTED_MESSAGE;
+			SSLerr(SSL_F_SSL3_GET_MESSAGE,SSL_R_UNEXPECTED_MESSAGE);
+			goto f_err;
+			}
+		if ((mt < 0) && (*p == SSL3_MT_CLIENT_HELLO) &&
+					(st1 == SSL3_ST_SR_CERT_A) &&
+					(stn == SSL3_ST_SR_CERT_B))
+			{
+			/* At this point we have got an MS SGC second client
+			 * hello (maybe we should always allow the client to
+			 * start a new handshake?). We need to restart the mac.
+			 * Don't increment {num,total}_renegotiations because
+			 * we have not completed the handshake. */
+			ssl3_init_finished_mac(s);
+			}
+
+		s->s3->tmp.message_type= *(p++);
+
+		n2l3(p,l);
+		if (l > (unsigned long)max)
+			{
+			al=SSL_AD_ILLEGAL_PARAMETER;
+			SSLerr(SSL_F_SSL3_GET_MESSAGE,SSL_R_EXCESSIVE_MESSAGE_SIZE);
+			goto f_err;
+			}
+		if (l > (INT_MAX-4)) /* BUF_MEM_grow takes an 'int' parameter */
+			{
+			al=SSL_AD_ILLEGAL_PARAMETER;
+			SSLerr(SSL_F_SSL3_GET_MESSAGE,SSL_R_EXCESSIVE_MESSAGE_SIZE);
+			goto f_err;
+			}
+		if (l && !BUF_MEM_grow_clean(s->init_buf,(int)l+4))
+			{
+			SSLerr(SSL_F_SSL3_GET_MESSAGE,ERR_R_BUF_LIB);
+			goto err;
+			}
+		s->s3->tmp.message_size=l;
+		s->state=stn;
+
+		s->init_msg = s->init_buf->data + 4;
+		s->init_num = 0;
+		}
+
+	/* next state (stn) */
+	p = s->init_msg;
+	n = s->s3->tmp.message_size - s->init_num;
+	while (n > 0)
+		{
+		i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,&p[s->init_num],n,0);
+		if (i <= 0)
+			{
+			s->rwstate=SSL_READING;
+			*ok = 0;
+			return i;
+			}
+		s->init_num += i;
+		n -= i;
+		}
+	ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, s->init_num + 4);
+	if (s->msg_callback)
+		s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data, (size_t)s->init_num + 4, s, s->msg_callback_arg);
+	*ok=1;
+	return s->init_num;
+f_err:
+	ssl3_send_alert(s,SSL3_AL_FATAL,al);
+err:
+	*ok=0;
+	return(-1);
+	}
+
+int ssl_cert_type(X509 *x, EVP_PKEY *pkey)
+	{
+	EVP_PKEY *pk;
+	int ret= -1,i;
+
+	if (pkey == NULL)
+		pk=X509_get_pubkey(x);
+	else
+		pk=pkey;
+	if (pk == NULL) goto err;
+
+	i=pk->type;
+	if (i == EVP_PKEY_RSA)
+		{
+		ret=SSL_PKEY_RSA_ENC;
+		}
+	else if (i == EVP_PKEY_DSA)
+		{
+		ret=SSL_PKEY_DSA_SIGN;
+		}
+#ifndef OPENSSL_NO_EC
+	else if (i == EVP_PKEY_EC)
+		{
+		ret = SSL_PKEY_ECC;
+		}	
+#endif
+	else if (i == NID_id_GostR3410_94 || i == NID_id_GostR3410_94_cc) 
+		{
+		ret = SSL_PKEY_GOST94;
+		}
+	else if (i == NID_id_GostR3410_2001 || i == NID_id_GostR3410_2001_cc) 
+		{
+		ret = SSL_PKEY_GOST01;
+		}
+err:
+	if(!pkey) EVP_PKEY_free(pk);
+	return(ret);
+	}
+
+int ssl_verify_alarm_type(long type)
+	{
+	int al;
+
+	switch(type)
+		{
+	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
+	case X509_V_ERR_UNABLE_TO_GET_CRL:
+	case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER:
+		al=SSL_AD_UNKNOWN_CA;
+		break;
+	case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
+	case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
+	case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
+	case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
+	case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
+	case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
+	case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
+	case X509_V_ERR_CERT_NOT_YET_VALID:
+	case X509_V_ERR_CRL_NOT_YET_VALID:
+	case X509_V_ERR_CERT_UNTRUSTED:
+	case X509_V_ERR_CERT_REJECTED:
+		al=SSL_AD_BAD_CERTIFICATE;
+		break;
+	case X509_V_ERR_CERT_SIGNATURE_FAILURE:
+	case X509_V_ERR_CRL_SIGNATURE_FAILURE:
+		al=SSL_AD_DECRYPT_ERROR;
+		break;
+	case X509_V_ERR_CERT_HAS_EXPIRED:
+	case X509_V_ERR_CRL_HAS_EXPIRED:
+		al=SSL_AD_CERTIFICATE_EXPIRED;
+		break;
+	case X509_V_ERR_CERT_REVOKED:
+		al=SSL_AD_CERTIFICATE_REVOKED;
+		break;
+	case X509_V_ERR_OUT_OF_MEM:
+		al=SSL_AD_INTERNAL_ERROR;
+		break;
+	case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
+	case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
+	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
+	case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
+	case X509_V_ERR_CERT_CHAIN_TOO_LONG:
+	case X509_V_ERR_PATH_LENGTH_EXCEEDED:
+	case X509_V_ERR_INVALID_CA:
+		al=SSL_AD_UNKNOWN_CA;
+		break;
+	case X509_V_ERR_APPLICATION_VERIFICATION:
+		al=SSL_AD_HANDSHAKE_FAILURE;
+		break;
+	case X509_V_ERR_INVALID_PURPOSE:
+		al=SSL_AD_UNSUPPORTED_CERTIFICATE;
+		break;
+	default:
+		al=SSL_AD_CERTIFICATE_UNKNOWN;
+		break;
+		}
+	return(al);
+	}
+
+#ifndef OPENSSL_NO_BUF_FREELISTS
+/* On some platforms, malloc() performance is bad enough that you can't just
+ * free() and malloc() buffers all the time, so we need to use freelists from
+ * unused buffers.  Currently, each freelist holds memory chunks of only a
+ * given size (list->chunklen); other sized chunks are freed and malloced.
+ * This doesn't help much if you're using many different SSL option settings
+ * with a given context.  (The options affecting buffer size are
+ * max_send_fragment, read buffer vs write buffer,
+ * SSL_OP_MICROSOFT_BIG_WRITE_BUFFER, SSL_OP_NO_COMPRESSION, and
+ * SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS.)  Using a separate freelist for every
+ * possible size is not an option, since max_send_fragment can take on many
+ * different values.
+ *
+ * If you are on a platform with a slow malloc(), and you're using SSL
+ * connections with many different settings for these options, and you need to
+ * use the SSL_MOD_RELEASE_BUFFERS feature, you have a few options:
+ *    - Link against a faster malloc implementation.
+ *    - Use a separate SSL_CTX for each option set.
+ *    - Improve this code.
+ */
+static void *
+freelist_extract(SSL_CTX *ctx, int for_read, int sz)
+	{
+	SSL3_BUF_FREELIST *list;
+	SSL3_BUF_FREELIST_ENTRY *ent = NULL;
+	void *result = NULL;
+
+	CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
+	list = for_read ? ctx->rbuf_freelist : ctx->wbuf_freelist;
+	if (list != NULL && sz == (int)list->chunklen)
+		ent = list->head;
+	if (ent != NULL)
+		{
+		list->head = ent->next;
+		result = ent;
+		if (--list->len == 0)
+			list->chunklen = 0;
+		}
+	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
+	if (!result)
+		result = OPENSSL_malloc(sz);
+	return result;
+}
+
+static void
+freelist_insert(SSL_CTX *ctx, int for_read, size_t sz, void *mem)
+	{
+	SSL3_BUF_FREELIST *list;
+	SSL3_BUF_FREELIST_ENTRY *ent;
+
+	CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
+	list = for_read ? ctx->rbuf_freelist : ctx->wbuf_freelist;
+	if (list != NULL &&
+	    (sz == list->chunklen || list->chunklen == 0) &&
+	    list->len < ctx->freelist_max_len &&
+	    sz >= sizeof(*ent))
+		{
+		list->chunklen = sz;
+		ent = mem;
+		ent->next = list->head;
+		list->head = ent;
+		++list->len;
+		mem = NULL;
+		}
+
+	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
+	if (mem)
+		OPENSSL_free(mem);
+	}
+#else
+#define freelist_extract(c,fr,sz) OPENSSL_malloc(sz)
+#define freelist_insert(c,fr,sz,m) OPENSSL_free(m)
+#endif
+
+int ssl3_setup_read_buffer(SSL *s)
+	{
+	unsigned char *p;
+	size_t len,align=0,headerlen;
+	
+	if (SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER)
+		headerlen = DTLS1_RT_HEADER_LENGTH;
+	else
+		headerlen = SSL3_RT_HEADER_LENGTH;
+
+#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
+	align = (-SSL3_RT_HEADER_LENGTH)&(SSL3_ALIGN_PAYLOAD-1);
+#endif
+
+	if (s->s3->rbuf.buf == NULL)
+		{
+		if (SSL_get_mode(s) & SSL_MODE_SMALL_BUFFERS)
+			{
+			len = SSL3_RT_DEFAULT_PACKET_SIZE;
+			}
+  		else
+			{
+			len = SSL3_RT_MAX_PLAIN_LENGTH
+				+ SSL3_RT_MAX_ENCRYPTED_OVERHEAD
+				+ headerlen + align;
+			if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER)
+				{
+				s->s3->init_extra = 1;
+				len += SSL3_RT_MAX_EXTRA;
+				}
+			}
+#ifndef OPENSSL_NO_COMP
+		if (!(s->options & SSL_OP_NO_COMPRESSION))
+			len += SSL3_RT_MAX_COMPRESSED_OVERHEAD;
+#endif
+		if ((p=freelist_extract(s->ctx, 1, len)) == NULL)
+			goto err;
+		s->s3->rbuf.buf = p;
+		s->s3->rbuf.len = len;
+		}
+
+	s->packet= &(s->s3->rbuf.buf[0]);
+	return 1;
+
+err:
+	SSLerr(SSL_F_SSL3_SETUP_READ_BUFFER,ERR_R_MALLOC_FAILURE);
+	return 0;
+	}
+
+int ssl3_setup_write_buffer(SSL *s)
+	{
+	unsigned char *p;
+	size_t len,align=0,headerlen;
+
+	if (SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER)
+		headerlen = DTLS1_RT_HEADER_LENGTH + 1;
+	else
+		headerlen = SSL3_RT_HEADER_LENGTH;
+
+#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
+	align = (-SSL3_RT_HEADER_LENGTH)&(SSL3_ALIGN_PAYLOAD-1);
+#endif
+
+	if (s->s3->wbuf.buf == NULL)
+		{
+		if (SSL_get_mode(s) & SSL_MODE_SMALL_BUFFERS)
+			{
+			len = SSL3_RT_DEFAULT_PACKET_SIZE;
+			}
+  		else
+			{
+			len = s->max_send_fragment;
+			}
+		len += 0
+			+ SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD
+			+ headerlen + align;
+#ifndef OPENSSL_NO_COMP
+		if (!(s->options & SSL_OP_NO_COMPRESSION))
+			len += SSL3_RT_MAX_COMPRESSED_OVERHEAD;
+#endif
+		if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS))
+			len += headerlen + align
+				+ SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD;
+		if ((p=freelist_extract(s->ctx, 0, len)) == NULL)
+			goto err;
+		s->s3->wbuf.buf = p;
+		s->s3->wbuf.len = len;
+		}
+
+	return 1;
+
+err:
+	SSLerr(SSL_F_SSL3_SETUP_WRITE_BUFFER,ERR_R_MALLOC_FAILURE);
+	return 0;
+	}
+
+
+int ssl3_setup_buffers(SSL *s)
+	{
+	if (!ssl3_setup_read_buffer(s))
+		return 0;
+	if (!ssl3_setup_write_buffer(s))
+		return 0;
+	return 1;
+	}
+
+int ssl3_release_write_buffer(SSL *s)
+	{
+	if (s->s3->wbuf.buf != NULL)
+		{
+		freelist_insert(s->ctx, 0, s->s3->wbuf.len, s->s3->wbuf.buf);
+		s->s3->wbuf.buf = NULL;
+		}
+	return 1;
+	}
+
+int ssl3_release_read_buffer(SSL *s)
+	{
+	if (s->s3->rbuf.buf != NULL)
+		{
+		freelist_insert(s->ctx, 1, s->s3->rbuf.len, s->s3->rbuf.buf);
+		s->s3->rbuf.buf = NULL;
+		}
+	return 1;
+	}
diff --git a/lib/openssl/ssl/s3_clnt.c b/lib/openssl/ssl/s3_clnt.c
new file mode 100644
index 0000000..0fffb8e
--- /dev/null
+++ b/lib/openssl/ssl/s3_clnt.c
@@ -0,0 +1,3103 @@
+/* ssl/s3_clnt.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * Portions of the attached software ("Contribution") are developed by 
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the OpenSSL open source
+ * license provided above.
+ *
+ * ECC cipher suite support in OpenSSL originally written by
+ * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
+ *
+ */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#include <stdio.h>
+#include "ssl_locl.h"
+#include "kssl_lcl.h"
+#include <openssl/buffer.h>
+#include <openssl/rand.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include <openssl/md5.h>
+#ifndef OPENSSL_NO_DH
+#include <openssl/dh.h>
+#endif
+#include <openssl/bn.h>
+#ifndef OPENSSL_NO_ENGINE
+#include <openssl/engine.h>
+#endif
+
+static const SSL_METHOD *ssl3_get_client_method(int ver);
+static int ca_dn_cmp(const X509_NAME * const *a,const X509_NAME * const *b);
+
+static const SSL_METHOD *ssl3_get_client_method(int ver)
+	{
+	if (ver == SSL3_VERSION)
+		return(SSLv3_client_method());
+	else
+		return(NULL);
+	}
+
+IMPLEMENT_ssl3_meth_func(SSLv3_client_method,
+			ssl_undefined_function,
+			ssl3_connect,
+			ssl3_get_client_method)
+
+int ssl3_connect(SSL *s)
+	{
+	BUF_MEM *buf=NULL;
+	unsigned long Time=(unsigned long)time(NULL);
+	void (*cb)(const SSL *ssl,int type,int val)=NULL;
+	int ret= -1;
+	int new_state,state,skip=0;
+
+	RAND_add(&Time,sizeof(Time),0);
+	ERR_clear_error();
+	clear_sys_error();
+
+	if (s->info_callback != NULL)
+		cb=s->info_callback;
+	else if (s->ctx->info_callback != NULL)
+		cb=s->ctx->info_callback;
+	
+	s->in_handshake++;
+	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); 
+#if 0	/* Send app data in separate packet, otherwise, some particular site
+	 * (only one site so far) closes the socket.
+	 * Note: there is a very small chance that two TCP packets
+	 * could be arriving at server combined into a single TCP packet,
+	 * then trigger that site to break. We haven't encounter that though.
+	 */
+	if (SSL_get_mode(s) & SSL_MODE_HANDSHAKE_CUTTHROUGH)
+		{
+		/* Send app data along with CCS/Finished */
+		s->s3->flags |= SSL3_FLAGS_DELAY_CLIENT_FINISHED;
+		}
+#endif
+
+	for (;;)
+		{
+		state=s->state;
+
+		switch(s->state)
+			{
+		case SSL_ST_RENEGOTIATE:
+			s->new_session=1;
+			s->state=SSL_ST_CONNECT;
+			s->ctx->stats.sess_connect_renegotiate++;
+			/* break */
+		case SSL_ST_BEFORE:
+		case SSL_ST_CONNECT:
+		case SSL_ST_BEFORE|SSL_ST_CONNECT:
+		case SSL_ST_OK|SSL_ST_CONNECT:
+
+			s->server=0;
+			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
+
+			if ((s->version & 0xff00 ) != 0x0300)
+				{
+				SSLerr(SSL_F_SSL3_CONNECT, ERR_R_INTERNAL_ERROR);
+				ret = -1;
+				goto end;
+				}
+				
+			/* s->version=SSL3_VERSION; */
+			s->type=SSL_ST_CONNECT;
+
+			if (s->init_buf == NULL)
+				{
+				if ((buf=BUF_MEM_new()) == NULL)
+					{
+					ret= -1;
+					goto end;
+					}
+				if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH))
+					{
+					ret= -1;
+					goto end;
+					}
+				s->init_buf=buf;
+				buf=NULL;
+				}
+
+			if (!ssl3_setup_buffers(s)) { ret= -1; goto end; }
+
+			/* setup buffing BIO */
+			if (!ssl_init_wbio_buffer(s,0)) { ret= -1; goto end; }
+
+			/* don't push the buffering BIO quite yet */
+
+			ssl3_init_finished_mac(s);
+
+			s->state=SSL3_ST_CW_CLNT_HELLO_A;
+			s->ctx->stats.sess_connect++;
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_CW_CLNT_HELLO_A:
+		case SSL3_ST_CW_CLNT_HELLO_B:
+
+			s->shutdown=0;
+			ret=ssl3_client_hello(s);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_CR_SRVR_HELLO_A;
+			s->init_num=0;
+
+			/* turn on buffering for the next lot of output */
+			if (s->bbio != s->wbio)
+				s->wbio=BIO_push(s->bbio,s->wbio);
+
+			break;
+
+		case SSL3_ST_CR_SRVR_HELLO_A:
+		case SSL3_ST_CR_SRVR_HELLO_B:
+			ret=ssl3_get_server_hello(s);
+			if (ret <= 0) goto end;
+
+			if (s->hit)
+				s->state=SSL3_ST_CR_FINISHED_A;
+			else
+				s->state=SSL3_ST_CR_CERT_A;
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_CR_CERT_A:
+		case SSL3_ST_CR_CERT_B:
+#ifndef OPENSSL_NO_TLSEXT
+			ret=ssl3_check_finished(s);
+			if (ret <= 0) goto end;
+			if (ret == 2)
+				{
+				s->hit = 1;
+				if (s->tlsext_ticket_expected)
+					s->state=SSL3_ST_CR_SESSION_TICKET_A;
+				else
+					s->state=SSL3_ST_CR_FINISHED_A;
+				s->init_num=0;
+				break;
+				}
+#endif
+			/* Check if it is anon DH/ECDH */
+			/* or PSK */
+			if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) &&
+			    !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
+				{
+				ret=ssl3_get_server_certificate(s);
+				if (ret <= 0) goto end;
+#ifndef OPENSSL_NO_TLSEXT
+				if (s->tlsext_status_expected)
+					s->state=SSL3_ST_CR_CERT_STATUS_A;
+				else
+					s->state=SSL3_ST_CR_KEY_EXCH_A;
+				}
+			else
+				{
+				skip = 1;
+				s->state=SSL3_ST_CR_KEY_EXCH_A;
+				}
+#else
+				}
+			else
+				skip=1;
+
+			s->state=SSL3_ST_CR_KEY_EXCH_A;
+#endif
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_CR_KEY_EXCH_A:
+		case SSL3_ST_CR_KEY_EXCH_B:
+			ret=ssl3_get_key_exchange(s);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_CR_CERT_REQ_A;
+			s->init_num=0;
+
+			/* at this point we check that we have the
+			 * required stuff from the server */
+			if (!ssl3_check_cert_and_algorithm(s))
+				{
+				ret= -1;
+				goto end;
+				}
+			break;
+
+		case SSL3_ST_CR_CERT_REQ_A:
+		case SSL3_ST_CR_CERT_REQ_B:
+			ret=ssl3_get_certificate_request(s);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_CR_SRVR_DONE_A;
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_CR_SRVR_DONE_A:
+		case SSL3_ST_CR_SRVR_DONE_B:
+			ret=ssl3_get_server_done(s);
+			if (ret <= 0) goto end;
+			if (s->s3->tmp.cert_req)
+				s->state=SSL3_ST_CW_CERT_A;
+			else
+				s->state=SSL3_ST_CW_KEY_EXCH_A;
+			s->init_num=0;
+
+			break;
+
+		case SSL3_ST_CW_CERT_A:
+		case SSL3_ST_CW_CERT_B:
+		case SSL3_ST_CW_CERT_C:
+		case SSL3_ST_CW_CERT_D:
+			ret=ssl3_send_client_certificate(s);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_CW_KEY_EXCH_A;
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_CW_KEY_EXCH_A:
+		case SSL3_ST_CW_KEY_EXCH_B:
+			ret=ssl3_send_client_key_exchange(s);
+			if (ret <= 0) goto end;
+			/* EAY EAY EAY need to check for DH fix cert
+			 * sent back */
+			/* For TLS, cert_req is set to 2, so a cert chain
+			 * of nothing is sent, but no verify packet is sent */
+			/* XXX: For now, we do not support client 
+			 * authentication in ECDH cipher suites with
+			 * ECDH (rather than ECDSA) certificates.
+			 * We need to skip the certificate verify 
+			 * message when client's ECDH public key is sent 
+			 * inside the client certificate.
+			 */
+			if (s->s3->tmp.cert_req == 1)
+				{
+				s->state=SSL3_ST_CW_CERT_VRFY_A;
+				}
+			else
+				{
+				s->state=SSL3_ST_CW_CHANGE_A;
+				s->s3->change_cipher_spec=0;
+				}
+			if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY)
+				{
+				s->state=SSL3_ST_CW_CHANGE_A;
+				s->s3->change_cipher_spec=0;
+				}
+
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_CW_CERT_VRFY_A:
+		case SSL3_ST_CW_CERT_VRFY_B:
+			ret=ssl3_send_client_verify(s);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_CW_CHANGE_A;
+			s->init_num=0;
+			s->s3->change_cipher_spec=0;
+			break;
+
+		case SSL3_ST_CW_CHANGE_A:
+		case SSL3_ST_CW_CHANGE_B:
+			ret=ssl3_send_change_cipher_spec(s,
+				SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_CW_FINISHED_A;
+			s->init_num=0;
+
+			s->session->cipher=s->s3->tmp.new_cipher;
+#ifdef OPENSSL_NO_COMP
+			s->session->compress_meth=0;
+#else
+			if (s->s3->tmp.new_compression == NULL)
+				s->session->compress_meth=0;
+			else
+				s->session->compress_meth=
+					s->s3->tmp.new_compression->id;
+#endif
+			if (!s->method->ssl3_enc->setup_key_block(s))
+				{
+				ret= -1;
+				goto end;
+				}
+
+			if (!s->method->ssl3_enc->change_cipher_state(s,
+				SSL3_CHANGE_CIPHER_CLIENT_WRITE))
+				{
+				ret= -1;
+				goto end;
+				}
+
+			break;
+
+		case SSL3_ST_CW_FINISHED_A:
+		case SSL3_ST_CW_FINISHED_B:
+			ret=ssl3_send_finished(s,
+				SSL3_ST_CW_FINISHED_A,SSL3_ST_CW_FINISHED_B,
+				s->method->ssl3_enc->client_finished_label,
+				s->method->ssl3_enc->client_finished_label_len);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_CW_FLUSH;
+
+			/* clear flags */
+			s->s3->flags&= ~SSL3_FLAGS_POP_BUFFER;
+			if (s->hit)
+				{
+				s->s3->tmp.next_state=SSL_ST_OK;
+				if (s->s3->flags & SSL3_FLAGS_DELAY_CLIENT_FINISHED)
+					{
+					s->state=SSL_ST_OK;
+					s->s3->flags|=SSL3_FLAGS_POP_BUFFER;
+					s->s3->delay_buf_pop_ret=0;
+					}
+				}
+			else
+				{
+				if ((SSL_get_mode(s) & SSL_MODE_HANDSHAKE_CUTTHROUGH) && SSL_get_cipher_bits(s, NULL) >= 128
+				    && s->s3->previous_server_finished_len == 0 /* no cutthrough on renegotiation (would complicate the state machine) */
+				   )
+					{
+					if (s->s3->flags & SSL3_FLAGS_DELAY_CLIENT_FINISHED)
+						{
+						s->state=SSL3_ST_CUTTHROUGH_COMPLETE;
+						s->s3->flags|=SSL3_FLAGS_POP_BUFFER;
+						s->s3->delay_buf_pop_ret=0;
+						}
+					else
+						{
+						s->s3->tmp.next_state=SSL3_ST_CUTTHROUGH_COMPLETE;
+						}
+					}
+				else
+					{
+#ifndef OPENSSL_NO_TLSEXT
+					/* Allow NewSessionTicket if ticket expected */
+					if (s->tlsext_ticket_expected)
+						s->s3->tmp.next_state=SSL3_ST_CR_SESSION_TICKET_A;
+					else
+#endif
+						s->s3->tmp.next_state=SSL3_ST_CR_FINISHED_A;
+					}
+				}
+			s->init_num=0;
+			break;
+
+#ifndef OPENSSL_NO_TLSEXT
+		case SSL3_ST_CR_SESSION_TICKET_A:
+		case SSL3_ST_CR_SESSION_TICKET_B:
+			ret=ssl3_get_new_session_ticket(s);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_CR_FINISHED_A;
+			s->init_num=0;
+		break;
+
+		case SSL3_ST_CR_CERT_STATUS_A:
+		case SSL3_ST_CR_CERT_STATUS_B:
+			ret=ssl3_get_cert_status(s);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_CR_KEY_EXCH_A;
+			s->init_num=0;
+		break;
+#endif
+
+		case SSL3_ST_CR_FINISHED_A:
+		case SSL3_ST_CR_FINISHED_B:
+
+			ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A,
+				SSL3_ST_CR_FINISHED_B);
+			if (ret <= 0) goto end;
+
+			if (s->hit)
+				s->state=SSL3_ST_CW_CHANGE_A;
+			else
+				s->state=SSL_ST_OK;
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_CW_FLUSH:
+			s->rwstate=SSL_WRITING;
+			if (BIO_flush(s->wbio) <= 0)
+				{
+				ret= -1;
+				goto end;
+				}
+			s->rwstate=SSL_NOTHING;
+			s->state=s->s3->tmp.next_state;
+			break;
+
+		case SSL3_ST_CUTTHROUGH_COMPLETE:
+#ifndef OPENSSL_NO_TLSEXT
+			/* Allow NewSessionTicket if ticket expected */
+			if (s->tlsext_ticket_expected)
+				s->state=SSL3_ST_CR_SESSION_TICKET_A;
+			else
+#endif
+				s->state=SSL3_ST_CR_FINISHED_A;
+
+			/* SSL_write() will take care of flushing buffered data if
+			 * DELAY_CLIENT_FINISHED is set.
+			 */
+			if (!(s->s3->flags & SSL3_FLAGS_DELAY_CLIENT_FINISHED))
+				ssl_free_wbio_buffer(s);
+			ret = 1;
+			goto end;
+			/* break; */
+
+		case SSL_ST_OK:
+			/* clean a few things up */
+			ssl3_cleanup_key_block(s);
+
+			if (s->init_buf != NULL)
+				{
+				BUF_MEM_free(s->init_buf);
+				s->init_buf=NULL;
+				}
+
+			/* If we are not 'joining' the last two packets,
+			 * remove the buffering now */
+			if (!(s->s3->flags & SSL3_FLAGS_POP_BUFFER))
+				ssl_free_wbio_buffer(s);
+			/* else do it later in ssl3_write */
+
+			s->init_num=0;
+			s->new_session=0;
+
+			ssl_update_cache(s,SSL_SESS_CACHE_CLIENT);
+			if (s->hit) s->ctx->stats.sess_hit++;
+
+			ret=1;
+			/* s->server=0; */
+			s->handshake_func=ssl3_connect;
+			s->ctx->stats.sess_connect_good++;
+
+			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1);
+
+			goto end;
+			/* break; */
+			
+		default:
+			SSLerr(SSL_F_SSL3_CONNECT,SSL_R_UNKNOWN_STATE);
+			ret= -1;
+			goto end;
+			/* break; */
+			}
+
+		/* did we do anything */
+		if (!s->s3->tmp.reuse_message && !skip)
+			{
+			if (s->debug)
+				{
+				if ((ret=BIO_flush(s->wbio)) <= 0)
+					goto end;
+				}
+
+			if ((cb != NULL) && (s->state != state))
+				{
+				new_state=s->state;
+				s->state=state;
+				cb(s,SSL_CB_CONNECT_LOOP,1);
+				s->state=new_state;
+				}
+			}
+		skip=0;
+		}
+end:
+	s->in_handshake--;
+	if (buf != NULL)
+		BUF_MEM_free(buf);
+	if (cb != NULL)
+		cb(s,SSL_CB_CONNECT_EXIT,ret);
+	return(ret);
+	}
+
+
+int ssl3_client_hello(SSL *s)
+	{
+	unsigned char *buf;
+	unsigned char *p,*d;
+	int i;
+	unsigned long Time,l;
+#ifndef OPENSSL_NO_COMP
+	int j;
+	SSL_COMP *comp;
+#endif
+
+	buf=(unsigned char *)s->init_buf->data;
+	if (s->state == SSL3_ST_CW_CLNT_HELLO_A)
+		{
+		SSL_SESSION *sess = s->session;
+		if ((sess == NULL) ||
+			(sess->ssl_version != s->version) ||
+#ifdef OPENSSL_NO_TLSEXT
+			!sess->session_id_length ||
+#else
+			(!sess->session_id_length && !sess->tlsext_tick) ||
+#endif
+			(sess->not_resumable))
+			{
+		        if (!s->session_creation_enabled)
+				{
+				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
+				SSLerr(SSL_F_SSL3_CLIENT_HELLO,SSL_R_SESSION_MAY_NOT_BE_CREATED);
+				goto err;
+				}
+			if (!ssl_get_new_session(s,0))
+				goto err;
+			}
+		/* else use the pre-loaded session */
+
+		p=s->s3->client_random;
+		Time=(unsigned long)time(NULL);			/* Time */
+		l2n(Time,p);
+		if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
+			goto err;
+
+		/* Do the message type and length last */
+		d=p= &(buf[4]);
+
+		*(p++)=s->version>>8;
+		*(p++)=s->version&0xff;
+		s->client_version=s->version;
+
+		/* Random stuff */
+		memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE);
+		p+=SSL3_RANDOM_SIZE;
+
+		/* Session ID */
+		if (s->new_session)
+			i=0;
+		else
+			i=s->session->session_id_length;
+		*(p++)=i;
+		if (i != 0)
+			{
+			if (i > (int)sizeof(s->session->session_id))
+				{
+				SSLerr(SSL_F_SSL3_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+				goto err;
+				}
+			memcpy(p,s->session->session_id,i);
+			p+=i;
+			}
+		
+		/* Ciphers supported */
+		i=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),&(p[2]),0);
+		if (i == 0)
+			{
+			SSLerr(SSL_F_SSL3_CLIENT_HELLO,SSL_R_NO_CIPHERS_AVAILABLE);
+			goto err;
+			}
+		s2n(i,p);
+		p+=i;
+
+		/* COMPRESSION */
+#ifdef OPENSSL_NO_COMP
+		*(p++)=1;
+#else
+
+		if ((s->options & SSL_OP_NO_COMPRESSION)
+					|| !s->ctx->comp_methods)
+			j=0;
+		else
+			j=sk_SSL_COMP_num(s->ctx->comp_methods);
+		*(p++)=1+j;
+		for (i=0; i<j; i++)
+			{
+			comp=sk_SSL_COMP_value(s->ctx->comp_methods,i);
+			*(p++)=comp->id;
+			}
+#endif
+		*(p++)=0; /* Add the NULL method */
+
+#ifndef OPENSSL_NO_TLSEXT
+		/* TLS extensions*/
+		if (ssl_prepare_clienthello_tlsext(s) <= 0)
+			{
+			SSLerr(SSL_F_SSL3_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
+			goto err;
+			}
+		if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
+			{
+			SSLerr(SSL_F_SSL3_CLIENT_HELLO,ERR_R_INTERNAL_ERROR);
+			goto err;
+			}
+#endif
+		
+		l=(p-d);
+		d=buf;
+		*(d++)=SSL3_MT_CLIENT_HELLO;
+		l2n3(l,d);
+
+		s->state=SSL3_ST_CW_CLNT_HELLO_B;
+		/* number of bytes to write */
+		s->init_num=p-buf;
+		s->init_off=0;
+		}
+
+	/* SSL3_ST_CW_CLNT_HELLO_B */
+	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+err:
+	return(-1);
+	}
+
+int ssl3_get_server_hello(SSL *s)
+	{
+	STACK_OF(SSL_CIPHER) *sk;
+	const SSL_CIPHER *c;
+	unsigned char *p,*d;
+	int i,al,ok;
+	unsigned int j;
+	long n;
+#ifndef OPENSSL_NO_COMP
+	SSL_COMP *comp;
+#endif
+
+	n=s->method->ssl_get_message(s,
+		SSL3_ST_CR_SRVR_HELLO_A,
+		SSL3_ST_CR_SRVR_HELLO_B,
+		-1,
+		20000, /* ?? */
+		&ok);
+
+	if (!ok) return((int)n);
+
+	if ( SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER)
+		{
+		if ( s->s3->tmp.message_type == DTLS1_MT_HELLO_VERIFY_REQUEST)
+			{
+			if ( s->d1->send_cookie == 0)
+				{
+				s->s3->tmp.reuse_message = 1;
+				return 1;
+				}
+			else /* already sent a cookie */
+				{
+				al=SSL_AD_UNEXPECTED_MESSAGE;
+				SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_BAD_MESSAGE_TYPE);
+				goto f_err;
+				}
+			}
+		}
+	
+	if ( s->s3->tmp.message_type != SSL3_MT_SERVER_HELLO)
+		{
+		al=SSL_AD_UNEXPECTED_MESSAGE;
+		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_BAD_MESSAGE_TYPE);
+		goto f_err;
+		}
+
+	d=p=(unsigned char *)s->init_msg;
+
+	if ((p[0] != (s->version>>8)) || (p[1] != (s->version&0xff)))
+		{
+		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_SSL_VERSION);
+		s->version=(s->version&0xff00)|p[1];
+		al=SSL_AD_PROTOCOL_VERSION;
+		goto f_err;
+		}
+	p+=2;
+
+	/* load the server hello data */
+	/* load the server random */
+	memcpy(s->s3->server_random,p,SSL3_RANDOM_SIZE);
+	p+=SSL3_RANDOM_SIZE;
+
+	/* get the session-id */
+	j= *(p++);
+
+	if ((j > sizeof s->session->session_id) || (j > SSL3_SESSION_ID_SIZE))
+		{
+		al=SSL_AD_ILLEGAL_PARAMETER;
+		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_SSL3_SESSION_ID_TOO_LONG);
+		goto f_err;
+		}
+
+#ifndef OPENSSL_NO_TLSEXT
+	/* check if we want to resume the session based on external pre-shared secret */
+	if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
+		{
+		SSL_CIPHER *pref_cipher=NULL;
+		s->session->master_key_length=sizeof(s->session->master_key);
+		if (s->tls_session_secret_cb(s, s->session->master_key,
+					     &s->session->master_key_length,
+					     NULL, &pref_cipher,
+					     s->tls_session_secret_cb_arg))
+			{
+			s->session->cipher = pref_cipher ?
+				pref_cipher : ssl_get_cipher_by_char(s, p+j);
+			}
+		}
+#endif /* OPENSSL_NO_TLSEXT */
+
+	if (j != 0 && j == s->session->session_id_length
+	    && memcmp(p,s->session->session_id,j) == 0)
+	    {
+	    if(s->sid_ctx_length != s->session->sid_ctx_length
+	       || memcmp(s->session->sid_ctx,s->sid_ctx,s->sid_ctx_length))
+		{
+		/* actually a client application bug */
+		al=SSL_AD_ILLEGAL_PARAMETER;
+		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
+		goto f_err;
+		}
+	    s->hit=1;
+	    }
+	else	/* a miss or crap from the other end */
+		{
+		/* If we were trying for session-id reuse, make a new
+		 * SSL_SESSION so we don't stuff up other people */
+		s->hit=0;
+		if (s->session->session_id_length > 0)
+			{
+		        if (!s->session_creation_enabled)
+				{
+				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
+				SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_SESSION_MAY_NOT_BE_CREATED);
+				goto err;
+				}
+			if (!ssl_get_new_session(s,0))
+				{
+				al=SSL_AD_INTERNAL_ERROR;
+				goto f_err;
+				}
+			}
+		s->session->session_id_length=j;
+		memcpy(s->session->session_id,p,j); /* j could be 0 */
+		}
+	p+=j;
+	c=ssl_get_cipher_by_char(s,p);
+	if (c == NULL)
+		{
+		/* unknown cipher */
+		al=SSL_AD_ILLEGAL_PARAMETER;
+		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNKNOWN_CIPHER_RETURNED);
+		goto f_err;
+		}
+	p+=ssl_put_cipher_by_char(s,NULL,NULL);
+
+	sk=ssl_get_ciphers_by_id(s);
+	i=sk_SSL_CIPHER_find(sk,c);
+	if (i < 0)
+		{
+		/* we did not say we would use this cipher */
+		al=SSL_AD_ILLEGAL_PARAMETER;
+		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_CIPHER_RETURNED);
+		goto f_err;
+		}
+
+	/* Depending on the session caching (internal/external), the cipher
+	   and/or cipher_id values may not be set. Make sure that
+	   cipher_id is set and use it for comparison. */
+	if (s->session->cipher)
+		s->session->cipher_id = s->session->cipher->id;
+	if (s->hit && (s->session->cipher_id != c->id))
+		{
+		if (!(s->options &
+			SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG))
+			{
+			al=SSL_AD_ILLEGAL_PARAMETER;
+			SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED);
+			goto f_err;
+			}
+		}
+	s->s3->tmp.new_cipher=c;
+	if (!ssl3_digest_cached_records(s))
+		goto f_err;
+
+	/* lets get the compression algorithm */
+	/* COMPRESSION */
+#ifdef OPENSSL_NO_COMP
+	if (*(p++) != 0)
+		{
+		al=SSL_AD_ILLEGAL_PARAMETER;
+		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
+		goto f_err;
+		}
+	/* If compression is disabled we'd better not try to resume a session
+	 * using compression.
+	 */
+	if (s->session->compress_meth != 0)
+		{
+		al=SSL_AD_INTERNAL_ERROR;
+		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_INCONSISTENT_COMPRESSION);
+		goto f_err;
+		}
+#else
+	j= *(p++);
+	if (s->hit && j != s->session->compress_meth)
+		{
+		al=SSL_AD_ILLEGAL_PARAMETER;
+		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED);
+		goto f_err;
+		}
+	if (j == 0)
+		comp=NULL;
+	else if (s->options & SSL_OP_NO_COMPRESSION)
+		{
+		al=SSL_AD_ILLEGAL_PARAMETER;
+		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_COMPRESSION_DISABLED);
+		goto f_err;
+		}
+	else
+		comp=ssl3_comp_find(s->ctx->comp_methods,j);
+	
+	if ((j != 0) && (comp == NULL))
+		{
+		al=SSL_AD_ILLEGAL_PARAMETER;
+		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
+		goto f_err;
+		}
+	else
+		{
+		s->s3->tmp.new_compression=comp;
+		}
+#endif
+
+#ifndef OPENSSL_NO_TLSEXT
+	/* TLS extensions*/
+	if (s->version >= SSL3_VERSION)
+		{
+		if (!ssl_parse_serverhello_tlsext(s,&p,d,n, &al))
+			{
+			/* 'al' set by ssl_parse_serverhello_tlsext */
+			SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_PARSE_TLSEXT);
+			goto f_err; 
+			}
+		if (ssl_check_serverhello_tlsext(s) <= 0)
+			{
+			SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_SERVERHELLO_TLSEXT);
+				goto err;
+			}
+		}
+#endif
+
+	if (p != (d+n))
+		{
+		/* wrong packet length */
+		al=SSL_AD_DECODE_ERROR;
+		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_BAD_PACKET_LENGTH);
+		goto err;
+		}
+
+	return(1);
+f_err:
+	ssl3_send_alert(s,SSL3_AL_FATAL,al);
+err:
+	return(-1);
+	}
+
+int ssl3_get_server_certificate(SSL *s)
+	{
+	int al,i,ok,ret= -1;
+	unsigned long n,nc,llen,l;
+	X509 *x=NULL;
+	const unsigned char *q,*p;
+	unsigned char *d;
+	STACK_OF(X509) *sk=NULL;
+	SESS_CERT *sc;
+	EVP_PKEY *pkey=NULL;
+	int need_cert = 1; /* VRS: 0=> will allow null cert if auth == KRB5 */
+
+	n=s->method->ssl_get_message(s,
+		SSL3_ST_CR_CERT_A,
+		SSL3_ST_CR_CERT_B,
+		-1,
+		s->max_cert_list,
+		&ok);
+
+	if (!ok) return((int)n);
+
+	if ((s->s3->tmp.message_type == SSL3_MT_SERVER_KEY_EXCHANGE) ||
+		((s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5) && 
+		(s->s3->tmp.message_type == SSL3_MT_SERVER_DONE)))
+		{
+		s->s3->tmp.reuse_message=1;
+		return(1);
+		}
+
+	if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE)
+		{
+		al=SSL_AD_UNEXPECTED_MESSAGE;
+		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_BAD_MESSAGE_TYPE);
+		goto f_err;
+		}
+	p=d=(unsigned char *)s->init_msg;
+
+	if ((sk=sk_X509_new_null()) == NULL)
+		{
+		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,ERR_R_MALLOC_FAILURE);
+		goto err;
+		}
+
+	n2l3(p,llen);
+	if (llen+3 != n)
+		{
+		al=SSL_AD_DECODE_ERROR;
+		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_LENGTH_MISMATCH);
+		goto f_err;
+		}
+	for (nc=0; nc<llen; )
+		{
+		n2l3(p,l);
+		if ((l+nc+3) > llen)
+			{
+			al=SSL_AD_DECODE_ERROR;
+			SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH);
+			goto f_err;
+			}
+
+		q=p;
+		x=d2i_X509(NULL,&q,l);
+		if (x == NULL)
+			{
+			al=SSL_AD_BAD_CERTIFICATE;
+			SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,ERR_R_ASN1_LIB);
+			goto f_err;
+			}
+		if (q != (p+l))
+			{
+			al=SSL_AD_DECODE_ERROR;
+			SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH);
+			goto f_err;
+			}
+		if (!sk_X509_push(sk,x))
+			{
+			SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+		x=NULL;
+		nc+=l+3;
+		p=q;
+		}
+
+	i=ssl_verify_cert_chain(s,sk);
+	if ((s->verify_mode != SSL_VERIFY_NONE) && (i <= 0)
+#ifndef OPENSSL_NO_KRB5
+	    && !((s->s3->tmp.new_cipher->algorithm_mkey & SSL_kKRB5) &&
+		 (s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5))
+#endif /* OPENSSL_NO_KRB5 */
+		)
+		{
+		al=ssl_verify_alarm_type(s->verify_result);
+		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_CERTIFICATE_VERIFY_FAILED);
+		goto f_err; 
+		}
+	ERR_clear_error(); /* but we keep s->verify_result */
+
+	sc=ssl_sess_cert_new();
+	if (sc == NULL) goto err;
+
+	if (s->session->sess_cert) ssl_sess_cert_free(s->session->sess_cert);
+	s->session->sess_cert=sc;
+
+	sc->cert_chain=sk;
+	/* Inconsistency alert: cert_chain does include the peer's
+	 * certificate, which we don't include in s3_srvr.c */
+	x=sk_X509_value(sk,0);
+	sk=NULL;
+ 	/* VRS 19990621: possible memory leak; sk=null ==> !sk_pop_free() @end*/
+
+	pkey=X509_get_pubkey(x);
+
+	/* VRS: allow null cert if auth == KRB5 */
+	need_cert = ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_kKRB5) &&
+	            (s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5))
+	            ? 0 : 1;
+
+#ifdef KSSL_DEBUG
+	printf("pkey,x = %p, %p\n", pkey,x);
+	printf("ssl_cert_type(x,pkey) = %d\n", ssl_cert_type(x,pkey));
+	printf("cipher, alg, nc = %s, %lx, %lx, %d\n", s->s3->tmp.new_cipher->name,
+		s->s3->tmp.new_cipher->algorithm_mkey, s->s3->tmp.new_cipher->algorithm_auth, need_cert);
+#endif    /* KSSL_DEBUG */
+
+	if (need_cert && ((pkey == NULL) || EVP_PKEY_missing_parameters(pkey)))
+		{
+		x=NULL;
+		al=SSL3_AL_FATAL;
+		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,
+			SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS);
+		goto f_err;
+		}
+
+	i=ssl_cert_type(x,pkey);
+	if (need_cert && i < 0)
+		{
+		x=NULL;
+		al=SSL3_AL_FATAL;
+		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,
+			SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+		goto f_err;
+		}
+
+	if (need_cert)
+		{
+		sc->peer_cert_type=i;
+		CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509);
+		/* Why would the following ever happen?
+		 * We just created sc a couple of lines ago. */
+		if (sc->peer_pkeys[i].x509 != NULL)
+			X509_free(sc->peer_pkeys[i].x509);
+		sc->peer_pkeys[i].x509=x;
+		sc->peer_key= &(sc->peer_pkeys[i]);
+
+		if (s->session->peer != NULL)
+			X509_free(s->session->peer);
+		CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509);
+		s->session->peer=x;
+		}
+	else
+		{
+		sc->peer_cert_type=i;
+		sc->peer_key= NULL;
+
+		if (s->session->peer != NULL)
+			X509_free(s->session->peer);
+		s->session->peer=NULL;
+		}
+	s->session->verify_result = s->verify_result;
+
+	x=NULL;
+	ret=1;
+
+	if (0)
+		{
+f_err:
+		ssl3_send_alert(s,SSL3_AL_FATAL,al);
+		}
+err:
+	EVP_PKEY_free(pkey);
+	X509_free(x);
+	sk_X509_pop_free(sk,X509_free);
+	return(ret);
+	}
+
+int ssl3_get_key_exchange(SSL *s)
+	{
+#ifndef OPENSSL_NO_RSA
+	unsigned char *q,md_buf[EVP_MAX_MD_SIZE*2];
+#endif
+	EVP_MD_CTX md_ctx;
+	unsigned char *param,*p;
+	int al,i,j,param_len,ok;
+	long n,alg_k,alg_a;
+	EVP_PKEY *pkey=NULL;
+#ifndef OPENSSL_NO_RSA
+	RSA *rsa=NULL;
+#endif
+#ifndef OPENSSL_NO_DH
+	DH *dh=NULL;
+#endif
+#ifndef OPENSSL_NO_ECDH
+	EC_KEY *ecdh = NULL;
+	BN_CTX *bn_ctx = NULL;
+	EC_POINT *srvr_ecpoint = NULL;
+	int curve_nid = 0;
+	int encoded_pt_len = 0;
+#endif
+
+	/* use same message size as in ssl3_get_certificate_request()
+	 * as ServerKeyExchange message may be skipped */
+	n=s->method->ssl_get_message(s,
+		SSL3_ST_CR_KEY_EXCH_A,
+		SSL3_ST_CR_KEY_EXCH_B,
+		-1,
+		s->max_cert_list,
+		&ok);
+	if (!ok) return((int)n);
+
+	if (s->s3->tmp.message_type != SSL3_MT_SERVER_KEY_EXCHANGE)
+		{
+#ifndef OPENSSL_NO_PSK
+		/* In plain PSK ciphersuite, ServerKeyExchange can be
+		   omitted if no identity hint is sent. Set
+		   session->sess_cert anyway to avoid problems
+		   later.*/
+		if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)
+			{
+			s->session->sess_cert=ssl_sess_cert_new();
+			if (s->ctx->psk_identity_hint)
+				OPENSSL_free(s->ctx->psk_identity_hint);
+			s->ctx->psk_identity_hint = NULL;
+			}
+#endif
+		s->s3->tmp.reuse_message=1;
+		return(1);
+		}
+
+	param=p=(unsigned char *)s->init_msg;
+	if (s->session->sess_cert != NULL)
+		{
+#ifndef OPENSSL_NO_RSA
+		if (s->session->sess_cert->peer_rsa_tmp != NULL)
+			{
+			RSA_free(s->session->sess_cert->peer_rsa_tmp);
+			s->session->sess_cert->peer_rsa_tmp=NULL;
+			}
+#endif
+#ifndef OPENSSL_NO_DH
+		if (s->session->sess_cert->peer_dh_tmp)
+			{
+			DH_free(s->session->sess_cert->peer_dh_tmp);
+			s->session->sess_cert->peer_dh_tmp=NULL;
+			}
+#endif
+#ifndef OPENSSL_NO_ECDH
+		if (s->session->sess_cert->peer_ecdh_tmp)
+			{
+			EC_KEY_free(s->session->sess_cert->peer_ecdh_tmp);
+			s->session->sess_cert->peer_ecdh_tmp=NULL;
+			}
+#endif
+		}
+	else
+		{
+		s->session->sess_cert=ssl_sess_cert_new();
+		}
+
+	param_len=0;
+	alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
+	alg_a=s->s3->tmp.new_cipher->algorithm_auth;
+	EVP_MD_CTX_init(&md_ctx);
+
+#ifndef OPENSSL_NO_PSK
+	if (alg_k & SSL_kPSK)
+		{
+		char tmp_id_hint[PSK_MAX_IDENTITY_LEN+1];
+
+		al=SSL_AD_HANDSHAKE_FAILURE;
+		n2s(p,i);
+		param_len=i+2;
+		/* Store PSK identity hint for later use, hint is used
+		 * in ssl3_send_client_key_exchange.  Assume that the
+		 * maximum length of a PSK identity hint can be as
+		 * long as the maximum length of a PSK identity. */
+		if (i > PSK_MAX_IDENTITY_LEN)
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+				SSL_R_DATA_LENGTH_TOO_LONG);
+			goto f_err;
+			}
+		if (param_len > n)
+			{
+			al=SSL_AD_DECODE_ERROR;
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+				SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH);
+			goto f_err;
+			}
+		/* If received PSK identity hint contains NULL
+		 * characters, the hint is truncated from the first
+		 * NULL. p may not be ending with NULL, so create a
+		 * NULL-terminated string. */
+		memcpy(tmp_id_hint, p, i);
+		memset(tmp_id_hint+i, 0, PSK_MAX_IDENTITY_LEN+1-i);
+		if (s->ctx->psk_identity_hint != NULL)
+			OPENSSL_free(s->ctx->psk_identity_hint);
+		s->ctx->psk_identity_hint = BUF_strdup(tmp_id_hint);
+		if (s->ctx->psk_identity_hint == NULL)
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
+			goto f_err;
+			}	   
+
+		p+=i;
+		n-=param_len;
+		}
+	else
+#endif /* !OPENSSL_NO_PSK */
+#ifndef OPENSSL_NO_RSA
+	if (alg_k & SSL_kRSA)
+		{
+		if ((rsa=RSA_new()) == NULL)
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+		n2s(p,i);
+		param_len=i+2;
+		if (param_len > n)
+			{
+			al=SSL_AD_DECODE_ERROR;
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_RSA_MODULUS_LENGTH);
+			goto f_err;
+			}
+		if (!(rsa->n=BN_bin2bn(p,i,rsa->n)))
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
+			goto err;
+			}
+		p+=i;
+
+		n2s(p,i);
+		param_len+=i+2;
+		if (param_len > n)
+			{
+			al=SSL_AD_DECODE_ERROR;
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_RSA_E_LENGTH);
+			goto f_err;
+			}
+		if (!(rsa->e=BN_bin2bn(p,i,rsa->e)))
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
+			goto err;
+			}
+		p+=i;
+		n-=param_len;
+
+		/* this should be because we are using an export cipher */
+		if (alg_a & SSL_aRSA)
+			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
+		else
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+			goto err;
+			}
+		s->session->sess_cert->peer_rsa_tmp=rsa;
+		rsa=NULL;
+		}
+#else /* OPENSSL_NO_RSA */
+	if (0)
+		;
+#endif
+#ifndef OPENSSL_NO_DH
+	else if (alg_k & SSL_kEDH)
+		{
+		if ((dh=DH_new()) == NULL)
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_DH_LIB);
+			goto err;
+			}
+		n2s(p,i);
+		param_len=i+2;
+		if (param_len > n)
+			{
+			al=SSL_AD_DECODE_ERROR;
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_DH_P_LENGTH);
+			goto f_err;
+			}
+		if (!(dh->p=BN_bin2bn(p,i,NULL)))
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
+			goto err;
+			}
+		p+=i;
+
+		n2s(p,i);
+		param_len+=i+2;
+		if (param_len > n)
+			{
+			al=SSL_AD_DECODE_ERROR;
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_DH_G_LENGTH);
+			goto f_err;
+			}
+		if (!(dh->g=BN_bin2bn(p,i,NULL)))
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
+			goto err;
+			}
+		p+=i;
+
+		n2s(p,i);
+		param_len+=i+2;
+		if (param_len > n)
+			{
+			al=SSL_AD_DECODE_ERROR;
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_DH_PUB_KEY_LENGTH);
+			goto f_err;
+			}
+		if (!(dh->pub_key=BN_bin2bn(p,i,NULL)))
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
+			goto err;
+			}
+		p+=i;
+		n-=param_len;
+
+#ifndef OPENSSL_NO_RSA
+		if (alg_a & SSL_aRSA)
+			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
+#else
+		if (0)
+			;
+#endif
+#ifndef OPENSSL_NO_DSA
+		else if (alg_a & SSL_aDSS)
+			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_DSA_SIGN].x509);
+#endif
+		/* else anonymous DH, so no certificate or pkey. */
+
+		s->session->sess_cert->peer_dh_tmp=dh;
+		dh=NULL;
+		}
+	else if ((alg_k & SSL_kDHr) || (alg_k & SSL_kDHd))
+		{
+		al=SSL_AD_ILLEGAL_PARAMETER;
+		SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER);
+		goto f_err;
+		}
+#endif /* !OPENSSL_NO_DH */
+
+#ifndef OPENSSL_NO_ECDH
+	else if (alg_k & SSL_kEECDH)
+		{
+		EC_GROUP *ngroup;
+		const EC_GROUP *group;
+
+		if ((ecdh=EC_KEY_new()) == NULL)
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+
+		/* Extract elliptic curve parameters and the
+		 * server's ephemeral ECDH public key.
+		 * Keep accumulating lengths of various components in
+		 * param_len and make sure it never exceeds n.
+		 */
+
+		/* XXX: For now we only support named (not generic) curves
+		 * and the ECParameters in this case is just three bytes.
+		 */
+		param_len=3;
+		if ((param_len > n) ||
+		    (*p != NAMED_CURVE_TYPE) || 
+		    ((curve_nid = tls1_ec_curve_id2nid(*(p + 2))) == 0)) 
+			{
+			al=SSL_AD_INTERNAL_ERROR;
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
+			goto f_err;
+			}
+
+		ngroup = EC_GROUP_new_by_curve_name(curve_nid);
+		if (ngroup == NULL)
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_EC_LIB);
+			goto err;
+			}
+		if (EC_KEY_set_group(ecdh, ngroup) == 0)
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_EC_LIB);
+			goto err;
+			}
+		EC_GROUP_free(ngroup);
+
+		group = EC_KEY_get0_group(ecdh);
+
+		if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) &&
+		    (EC_GROUP_get_degree(group) > 163))
+			{
+			al=SSL_AD_EXPORT_RESTRICTION;
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER);
+			goto f_err;
+			}
+
+		p+=3;
+
+		/* Next, get the encoded ECPoint */
+		if (((srvr_ecpoint = EC_POINT_new(group)) == NULL) ||
+		    ((bn_ctx = BN_CTX_new()) == NULL))
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+
+		encoded_pt_len = *p;  /* length of encoded point */
+		p+=1;
+		param_len += (1 + encoded_pt_len);
+		if ((param_len > n) ||
+		    (EC_POINT_oct2point(group, srvr_ecpoint, 
+			p, encoded_pt_len, bn_ctx) == 0))
+			{
+			al=SSL_AD_DECODE_ERROR;
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_ECPOINT);
+			goto f_err;
+			}
+
+		n-=param_len;
+		p+=encoded_pt_len;
+
+		/* The ECC/TLS specification does not mention
+		 * the use of DSA to sign ECParameters in the server
+		 * key exchange message. We do support RSA and ECDSA.
+		 */
+		if (0) ;
+#ifndef OPENSSL_NO_RSA
+		else if (alg_a & SSL_aRSA)
+			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
+#endif
+#ifndef OPENSSL_NO_ECDSA
+		else if (alg_a & SSL_aECDSA)
+			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_ECC].x509);
+#endif
+		/* else anonymous ECDH, so no certificate or pkey. */
+		EC_KEY_set_public_key(ecdh, srvr_ecpoint);
+		s->session->sess_cert->peer_ecdh_tmp=ecdh;
+		ecdh=NULL;
+		BN_CTX_free(bn_ctx);
+		EC_POINT_free(srvr_ecpoint);
+		srvr_ecpoint = NULL;
+		}
+	else if (alg_k)
+		{
+		al=SSL_AD_UNEXPECTED_MESSAGE;
+		SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
+		goto f_err;
+		}
+#endif /* !OPENSSL_NO_ECDH */
+
+
+	/* p points to the next byte, there are 'n' bytes left */
+
+	/* if it was signed, check the signature */
+	if (pkey != NULL)
+		{
+		n2s(p,i);
+		n-=2;
+		j=EVP_PKEY_size(pkey);
+
+		if ((i != n) || (n > j) || (n <= 0))
+			{
+			/* wrong packet length */
+			al=SSL_AD_DECODE_ERROR;
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_WRONG_SIGNATURE_LENGTH);
+			goto f_err;
+			}
+
+#ifndef OPENSSL_NO_RSA
+		if (pkey->type == EVP_PKEY_RSA)
+			{
+			int num;
+
+			j=0;
+			q=md_buf;
+			for (num=2; num > 0; num--)
+				{
+				EVP_DigestInit_ex(&md_ctx,(num == 2)
+					?s->ctx->md5:s->ctx->sha1, NULL);
+				EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
+				EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
+				EVP_DigestUpdate(&md_ctx,param,param_len);
+				EVP_DigestFinal_ex(&md_ctx,q,(unsigned int *)&i);
+				q+=i;
+				j+=i;
+				}
+			i=RSA_verify(NID_md5_sha1, md_buf, j, p, n,
+								pkey->pkey.rsa);
+			if (i < 0)
+				{
+				al=SSL_AD_DECRYPT_ERROR;
+				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_RSA_DECRYPT);
+				goto f_err;
+				}
+			if (i == 0)
+				{
+				/* bad signature */
+				al=SSL_AD_DECRYPT_ERROR;
+				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SIGNATURE);
+				goto f_err;
+				}
+			}
+		else
+#endif
+#ifndef OPENSSL_NO_DSA
+			if (pkey->type == EVP_PKEY_DSA)
+			{
+			/* lets do DSS */
+			EVP_VerifyInit_ex(&md_ctx,EVP_dss1(), NULL);
+			EVP_VerifyUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
+			EVP_VerifyUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
+			EVP_VerifyUpdate(&md_ctx,param,param_len);
+			if (EVP_VerifyFinal(&md_ctx,p,(int)n,pkey) <= 0)
+				{
+				/* bad signature */
+				al=SSL_AD_DECRYPT_ERROR;
+				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SIGNATURE);
+				goto f_err;
+				}
+			}
+		else
+#endif
+#ifndef OPENSSL_NO_ECDSA
+			if (pkey->type == EVP_PKEY_EC)
+			{
+			/* let's do ECDSA */
+			EVP_VerifyInit_ex(&md_ctx,EVP_ecdsa(), NULL);
+			EVP_VerifyUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
+			EVP_VerifyUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
+			EVP_VerifyUpdate(&md_ctx,param,param_len);
+			if (EVP_VerifyFinal(&md_ctx,p,(int)n,pkey) <= 0)
+				{
+				/* bad signature */
+				al=SSL_AD_DECRYPT_ERROR;
+				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SIGNATURE);
+				goto f_err;
+				}
+			}
+		else
+#endif
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+			goto err;
+			}
+		}
+	else
+		{
+		if (!(alg_a & SSL_aNULL) && !(alg_k & SSL_kPSK))
+			/* aNULL or kPSK do not need public keys */
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+			goto err;
+			}
+		/* still data left over */
+		if (n != 0)
+			{
+			al=SSL_AD_DECODE_ERROR;
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_EXTRA_DATA_IN_MESSAGE);
+			goto f_err;
+			}
+		}
+	EVP_PKEY_free(pkey);
+	EVP_MD_CTX_cleanup(&md_ctx);
+	return(1);
+f_err:
+	ssl3_send_alert(s,SSL3_AL_FATAL,al);
+err:
+	EVP_PKEY_free(pkey);
+#ifndef OPENSSL_NO_RSA
+	if (rsa != NULL)
+		RSA_free(rsa);
+#endif
+#ifndef OPENSSL_NO_DH
+	if (dh != NULL)
+		DH_free(dh);
+#endif
+#ifndef OPENSSL_NO_ECDH
+	BN_CTX_free(bn_ctx);
+	EC_POINT_free(srvr_ecpoint);
+	if (ecdh != NULL)
+		EC_KEY_free(ecdh);
+#endif
+	EVP_MD_CTX_cleanup(&md_ctx);
+	return(-1);
+	}
+
+int ssl3_get_certificate_request(SSL *s)
+	{
+	int ok,ret=0;
+	unsigned long n,nc,l;
+	unsigned int llen,ctype_num,i;
+	X509_NAME *xn=NULL;
+	const unsigned char *p,*q;
+	unsigned char *d;
+	STACK_OF(X509_NAME) *ca_sk=NULL;
+
+	n=s->method->ssl_get_message(s,
+		SSL3_ST_CR_CERT_REQ_A,
+		SSL3_ST_CR_CERT_REQ_B,
+		-1,
+		s->max_cert_list,
+		&ok);
+
+	if (!ok) return((int)n);
+
+	s->s3->tmp.cert_req=0;
+
+	if (s->s3->tmp.message_type == SSL3_MT_SERVER_DONE)
+		{
+		s->s3->tmp.reuse_message=1;
+		return(1);
+		}
+
+	if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE_REQUEST)
+		{
+		ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
+		SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_WRONG_MESSAGE_TYPE);
+		goto err;
+		}
+
+	/* TLS does not like anon-DH with client cert */
+	if (s->version > SSL3_VERSION)
+		{
+		if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)
+			{
+			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
+			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER);
+			goto err;
+			}
+		}
+
+	p=d=(unsigned char *)s->init_msg;
+
+	if ((ca_sk=sk_X509_NAME_new(ca_dn_cmp)) == NULL)
+		{
+		SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,ERR_R_MALLOC_FAILURE);
+		goto err;
+		}
+
+	/* get the certificate types */
+	ctype_num= *(p++);
+	if (ctype_num > SSL3_CT_NUMBER)
+		ctype_num=SSL3_CT_NUMBER;
+	for (i=0; i<ctype_num; i++)
+		s->s3->tmp.ctype[i]= p[i];
+	p+=ctype_num;
+
+	/* get the CA RDNs */
+	n2s(p,llen);
+#if 0
+{
+FILE *out;
+out=fopen("/tmp/vsign.der","w");
+fwrite(p,1,llen,out);
+fclose(out);
+}
+#endif
+
+	if ((llen+ctype_num+2+1) != n)
+		{
+		ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
+		SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_LENGTH_MISMATCH);
+		goto err;
+		}
+
+	for (nc=0; nc<llen; )
+		{
+		n2s(p,l);
+		if ((l+nc+2) > llen)
+			{
+			if ((s->options & SSL_OP_NETSCAPE_CA_DN_BUG))
+				goto cont; /* netscape bugs */
+			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
+			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_CA_DN_TOO_LONG);
+			goto err;
+			}
+
+		q=p;
+
+		if ((xn=d2i_X509_NAME(NULL,&q,l)) == NULL)
+			{
+			/* If netscape tolerance is on, ignore errors */
+			if (s->options & SSL_OP_NETSCAPE_CA_DN_BUG)
+				goto cont;
+			else
+				{
+				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
+				SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,ERR_R_ASN1_LIB);
+				goto err;
+				}
+			}
+
+		if (q != (p+l))
+			{
+			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
+			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_CA_DN_LENGTH_MISMATCH);
+			goto err;
+			}
+		if (!sk_X509_NAME_push(ca_sk,xn))
+			{
+			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+
+		p+=l;
+		nc+=l+2;
+		}
+
+	if (0)
+		{
+cont:
+		ERR_clear_error();
+		}
+
+	/* we should setup a certificate to return.... */
+	s->s3->tmp.cert_req=1;
+	s->s3->tmp.ctype_num=ctype_num;
+	if (s->s3->tmp.ca_names != NULL)
+		sk_X509_NAME_pop_free(s->s3->tmp.ca_names,X509_NAME_free);
+	s->s3->tmp.ca_names=ca_sk;
+	ca_sk=NULL;
+
+	ret=1;
+err:
+	if (ca_sk != NULL) sk_X509_NAME_pop_free(ca_sk,X509_NAME_free);
+	return(ret);
+	}
+
+static int ca_dn_cmp(const X509_NAME * const *a, const X509_NAME * const *b)
+	{
+	return(X509_NAME_cmp(*a,*b));
+	}
+#ifndef OPENSSL_NO_TLSEXT
+int ssl3_get_new_session_ticket(SSL *s)
+	{
+	int ok,al,ret=0, ticklen;
+	long n;
+	const unsigned char *p;
+	unsigned char *d;
+
+	n=s->method->ssl_get_message(s,
+		SSL3_ST_CR_SESSION_TICKET_A,
+		SSL3_ST_CR_SESSION_TICKET_B,
+		-1,
+		16384,
+		&ok);
+
+	if (!ok)
+		return((int)n);
+
+	if (s->s3->tmp.message_type == SSL3_MT_FINISHED)
+		{
+		s->s3->tmp.reuse_message=1;
+		return(1);
+		}
+	if (s->s3->tmp.message_type != SSL3_MT_NEWSESSION_TICKET)
+		{
+		al=SSL_AD_UNEXPECTED_MESSAGE;
+		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_BAD_MESSAGE_TYPE);
+		goto f_err;
+		}
+	if (n < 6)
+		{
+		/* need at least ticket_lifetime_hint + ticket length */
+		al = SSL3_AL_FATAL,SSL_AD_DECODE_ERROR;
+		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_LENGTH_MISMATCH);
+		goto f_err;
+		}
+
+	p=d=(unsigned char *)s->init_msg;
+	n2l(p, s->session->tlsext_tick_lifetime_hint);
+	n2s(p, ticklen);
+	/* ticket_lifetime_hint + ticket_length + ticket */
+	if (ticklen + 6 != n)
+		{
+		al = SSL3_AL_FATAL,SSL_AD_DECODE_ERROR;
+		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_LENGTH_MISMATCH);
+		goto f_err;
+		}
+	if (s->session->tlsext_tick)
+		{
+		OPENSSL_free(s->session->tlsext_tick);
+		s->session->tlsext_ticklen = 0;
+		}
+	s->session->tlsext_tick = OPENSSL_malloc(ticklen);
+	if (!s->session->tlsext_tick)
+		{
+		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,ERR_R_MALLOC_FAILURE);
+		goto err;
+		}
+	memcpy(s->session->tlsext_tick, p, ticklen);
+	s->session->tlsext_ticklen = ticklen;
+	/* There are two ways to detect a resumed ticket sesion.
+	 * One is to set an appropriate session ID and then the server
+	 * must return a match in ServerHello. This allows the normal
+	 * client session ID matching to work and we know much 
+	 * earlier that the ticket has been accepted.
+	 * 
+	 * The other way is to set zero length session ID when the
+	 * ticket is presented and rely on the handshake to determine
+	 * session resumption.
+	 *
+	 * We choose the former approach because this fits in with
+	 * assumptions elsewhere in OpenSSL. The session ID is set
+	 * to the SHA256 (or SHA1 is SHA256 is disabled) hash of the
+	 * ticket.
+	 */ 
+	EVP_Digest(p, ticklen,
+			s->session->session_id, &s->session->session_id_length,
+#ifndef OPENSSL_NO_SHA256
+							EVP_sha256(), NULL);
+#else
+							EVP_sha1(), NULL);
+#endif
+	ret=1;
+	return(ret);
+f_err:
+	ssl3_send_alert(s,SSL3_AL_FATAL,al);
+err:
+	return(-1);
+	}
+
+int ssl3_get_cert_status(SSL *s)
+	{
+	int ok, al;
+	unsigned long resplen,n;
+	const unsigned char *p;
+
+	n=s->method->ssl_get_message(s,
+		SSL3_ST_CR_CERT_STATUS_A,
+		SSL3_ST_CR_CERT_STATUS_B,
+		SSL3_MT_CERTIFICATE_STATUS,
+		16384,
+		&ok);
+
+	if (!ok) return((int)n);
+	if (n < 4)
+		{
+		/* need at least status type + length */
+		al = SSL_AD_DECODE_ERROR;
+		SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_LENGTH_MISMATCH);
+		goto f_err;
+		}
+	p = (unsigned char *)s->init_msg;
+	if (*p++ != TLSEXT_STATUSTYPE_ocsp)
+		{
+		al = SSL_AD_DECODE_ERROR;
+		SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_UNSUPPORTED_STATUS_TYPE);
+		goto f_err;
+		}
+	n2l3(p, resplen);
+	if (resplen + 4 != n)
+		{
+		al = SSL_AD_DECODE_ERROR;
+		SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_LENGTH_MISMATCH);
+		goto f_err;
+		}
+	if (s->tlsext_ocsp_resp)
+		OPENSSL_free(s->tlsext_ocsp_resp);
+	s->tlsext_ocsp_resp = BUF_memdup(p, resplen);
+	if (!s->tlsext_ocsp_resp)
+		{
+		al = SSL_AD_INTERNAL_ERROR;
+		SSLerr(SSL_F_SSL3_GET_CERT_STATUS,ERR_R_MALLOC_FAILURE);
+		goto f_err;
+		}
+	s->tlsext_ocsp_resplen = resplen;
+	if (s->ctx->tlsext_status_cb)
+		{
+		int ret;
+		ret = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
+		if (ret == 0)
+			{
+			al = SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE;
+			SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_INVALID_STATUS_RESPONSE);
+			goto f_err;
+			}
+		if (ret < 0)
+			{
+			al = SSL_AD_INTERNAL_ERROR;
+			SSLerr(SSL_F_SSL3_GET_CERT_STATUS,ERR_R_MALLOC_FAILURE);
+			goto f_err;
+			}
+		}
+	return 1;
+f_err:
+	ssl3_send_alert(s,SSL3_AL_FATAL,al);
+	return(-1);
+	}
+#endif
+
+int ssl3_get_server_done(SSL *s)
+	{
+	int ok,ret=0;
+	long n;
+
+	n=s->method->ssl_get_message(s,
+		SSL3_ST_CR_SRVR_DONE_A,
+		SSL3_ST_CR_SRVR_DONE_B,
+		SSL3_MT_SERVER_DONE,
+		30, /* should be very small, like 0 :-) */
+		&ok);
+
+	if (!ok) return((int)n);
+	if (n > 0)
+		{
+		/* should contain no data */
+		ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
+		SSLerr(SSL_F_SSL3_GET_SERVER_DONE,SSL_R_LENGTH_MISMATCH);
+		return -1;
+		}
+	ret=1;
+	return(ret);
+	}
+
+
+int ssl3_send_client_key_exchange(SSL *s)
+	{
+	unsigned char *p,*d;
+	int n;
+	unsigned long alg_k;
+#ifndef OPENSSL_NO_RSA
+	unsigned char *q;
+	EVP_PKEY *pkey=NULL;
+#endif
+#ifndef OPENSSL_NO_KRB5
+	KSSL_ERR kssl_err;
+#endif /* OPENSSL_NO_KRB5 */
+#ifndef OPENSSL_NO_ECDH
+	EC_KEY *clnt_ecdh = NULL;
+	const EC_POINT *srvr_ecpoint = NULL;
+	EVP_PKEY *srvr_pub_pkey = NULL;
+	unsigned char *encodedPoint = NULL;
+	int encoded_pt_len = 0;
+	BN_CTX * bn_ctx = NULL;
+#endif
+
+	if (s->state == SSL3_ST_CW_KEY_EXCH_A)
+		{
+		d=(unsigned char *)s->init_buf->data;
+		p= &(d[4]);
+
+		alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
+
+		/* Fool emacs indentation */
+		if (0) {}
+#ifndef OPENSSL_NO_RSA
+		else if (alg_k & SSL_kRSA)
+			{
+			RSA *rsa;
+			unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
+
+			if (s->session->sess_cert->peer_rsa_tmp != NULL)
+				rsa=s->session->sess_cert->peer_rsa_tmp;
+			else
+				{
+				pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
+				if ((pkey == NULL) ||
+					(pkey->type != EVP_PKEY_RSA) ||
+					(pkey->pkey.rsa == NULL))
+					{
+					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+					goto err;
+					}
+				rsa=pkey->pkey.rsa;
+				EVP_PKEY_free(pkey);
+				}
+				
+			tmp_buf[0]=s->client_version>>8;
+			tmp_buf[1]=s->client_version&0xff;
+			if (RAND_bytes(&(tmp_buf[2]),sizeof tmp_buf-2) <= 0)
+					goto err;
+
+			s->session->master_key_length=sizeof tmp_buf;
+
+			q=p;
+			/* Fix buf for TLS and beyond */
+			if (s->version > SSL3_VERSION)
+				p+=2;
+			n=RSA_public_encrypt(sizeof tmp_buf,
+				tmp_buf,p,rsa,RSA_PKCS1_PADDING);
+#ifdef PKCS1_CHECK
+			if (s->options & SSL_OP_PKCS1_CHECK_1) p[1]++;
+			if (s->options & SSL_OP_PKCS1_CHECK_2) tmp_buf[0]=0x70;
+#endif
+			if (n <= 0)
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_ENCRYPT);
+				goto err;
+				}
+
+			/* Fix buf for TLS and beyond */
+			if (s->version > SSL3_VERSION)
+				{
+				s2n(n,q);
+				n+=2;
+				}
+
+			s->session->master_key_length=
+				s->method->ssl3_enc->generate_master_secret(s,
+					s->session->master_key,
+					tmp_buf,sizeof tmp_buf);
+			OPENSSL_cleanse(tmp_buf,sizeof tmp_buf);
+			}
+#endif
+#ifndef OPENSSL_NO_KRB5
+		else if (alg_k & SSL_kKRB5)
+			{
+			krb5_error_code	krb5rc;
+			KSSL_CTX	*kssl_ctx = s->kssl_ctx;
+			/*  krb5_data	krb5_ap_req;  */
+			krb5_data	*enc_ticket;
+			krb5_data	authenticator, *authp = NULL;
+			EVP_CIPHER_CTX	ciph_ctx;
+			const EVP_CIPHER *enc = NULL;
+			unsigned char	iv[EVP_MAX_IV_LENGTH];
+			unsigned char	tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
+			unsigned char	epms[SSL_MAX_MASTER_KEY_LENGTH 
+						+ EVP_MAX_IV_LENGTH];
+			int 		padl, outl = sizeof(epms);
+
+			EVP_CIPHER_CTX_init(&ciph_ctx);
+
+#ifdef KSSL_DEBUG
+			printf("ssl3_send_client_key_exchange(%lx & %lx)\n",
+				alg_k, SSL_kKRB5);
+#endif	/* KSSL_DEBUG */
+
+			authp = NULL;
+#ifdef KRB5SENDAUTH
+			if (KRB5SENDAUTH)  authp = &authenticator;
+#endif	/* KRB5SENDAUTH */
+
+			krb5rc = kssl_cget_tkt(kssl_ctx, &enc_ticket, authp,
+				&kssl_err);
+			enc = kssl_map_enc(kssl_ctx->enctype);
+			if (enc == NULL)
+			    goto err;
+#ifdef KSSL_DEBUG
+			{
+			printf("kssl_cget_tkt rtn %d\n", krb5rc);
+			if (krb5rc && kssl_err.text)
+			  printf("kssl_cget_tkt kssl_err=%s\n", kssl_err.text);
+			}
+#endif	/* KSSL_DEBUG */
+
+			if (krb5rc)
+				{
+				ssl3_send_alert(s,SSL3_AL_FATAL,
+						SSL_AD_HANDSHAKE_FAILURE);
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+						kssl_err.reason);
+				goto err;
+				}
+
+			/*  20010406 VRS - Earlier versions used KRB5 AP_REQ
+			**  in place of RFC 2712 KerberosWrapper, as in:
+			**
+			**  Send ticket (copy to *p, set n = length)
+			**  n = krb5_ap_req.length;
+			**  memcpy(p, krb5_ap_req.data, krb5_ap_req.length);
+			**  if (krb5_ap_req.data)  
+			**    kssl_krb5_free_data_contents(NULL,&krb5_ap_req);
+			**
+			**  Now using real RFC 2712 KerberosWrapper
+			**  (Thanks to Simon Wilkinson <sxw@sxw.org.uk>)
+			**  Note: 2712 "opaque" types are here replaced
+			**  with a 2-byte length followed by the value.
+			**  Example:
+			**  KerberosWrapper= xx xx asn1ticket 0 0 xx xx encpms
+			**  Where "xx xx" = length bytes.  Shown here with
+			**  optional authenticator omitted.
+			*/
+
+			/*  KerberosWrapper.Ticket		*/
+			s2n(enc_ticket->length,p);
+			memcpy(p, enc_ticket->data, enc_ticket->length);
+			p+= enc_ticket->length;
+			n = enc_ticket->length + 2;
+
+			/*  KerberosWrapper.Authenticator	*/
+			if (authp  &&  authp->length)  
+				{
+				s2n(authp->length,p);
+				memcpy(p, authp->data, authp->length);
+				p+= authp->length;
+				n+= authp->length + 2;
+				
+				free(authp->data);
+				authp->data = NULL;
+				authp->length = 0;
+				}
+			else
+				{
+				s2n(0,p);/*  null authenticator length	*/
+				n+=2;
+				}
+ 
+			    tmp_buf[0]=s->client_version>>8;
+			    tmp_buf[1]=s->client_version&0xff;
+			    if (RAND_bytes(&(tmp_buf[2]),sizeof tmp_buf-2) <= 0)
+				goto err;
+
+			/*  20010420 VRS.  Tried it this way; failed.
+			**	EVP_EncryptInit_ex(&ciph_ctx,enc, NULL,NULL);
+			**	EVP_CIPHER_CTX_set_key_length(&ciph_ctx,
+			**				kssl_ctx->length);
+			**	EVP_EncryptInit_ex(&ciph_ctx,NULL, key,iv);
+			*/
+
+			memset(iv, 0, sizeof iv);  /* per RFC 1510 */
+			EVP_EncryptInit_ex(&ciph_ctx,enc, NULL,
+				kssl_ctx->key,iv);
+			EVP_EncryptUpdate(&ciph_ctx,epms,&outl,tmp_buf,
+				sizeof tmp_buf);
+			EVP_EncryptFinal_ex(&ciph_ctx,&(epms[outl]),&padl);
+			outl += padl;
+			if (outl > (int)sizeof epms)
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+				goto err;
+				}
+			EVP_CIPHER_CTX_cleanup(&ciph_ctx);
+
+			/*  KerberosWrapper.EncryptedPreMasterSecret	*/
+			s2n(outl,p);
+			memcpy(p, epms, outl);
+			p+=outl;
+			n+=outl + 2;
+
+			s->session->master_key_length=
+				s->method->ssl3_enc->generate_master_secret(s,
+					s->session->master_key,
+					tmp_buf, sizeof tmp_buf);
+
+			OPENSSL_cleanse(tmp_buf, sizeof tmp_buf);
+			OPENSSL_cleanse(epms, outl);
+			}
+#endif
+#ifndef OPENSSL_NO_DH
+		else if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
+			{
+			DH *dh_srvr,*dh_clnt;
+
+			if (s->session->sess_cert == NULL) 
+				{
+				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
+				goto err;
+				}
+
+			if (s->session->sess_cert->peer_dh_tmp != NULL)
+				dh_srvr=s->session->sess_cert->peer_dh_tmp;
+			else
+				{
+				/* we get them from the cert */
+				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNABLE_TO_FIND_DH_PARAMETERS);
+				goto err;
+				}
+			
+			/* generate a new random key */
+			if ((dh_clnt=DHparams_dup(dh_srvr)) == NULL)
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
+				goto err;
+				}
+			if (!DH_generate_key(dh_clnt))
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
+				goto err;
+				}
+
+			/* use the 'p' output buffer for the DH key, but
+			 * make sure to clear it out afterwards */
+
+			n=DH_compute_key(p,dh_srvr->pub_key,dh_clnt);
+
+			if (n <= 0)
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
+				goto err;
+				}
+
+			/* generate master key from the result */
+			s->session->master_key_length=
+				s->method->ssl3_enc->generate_master_secret(s,
+					s->session->master_key,p,n);
+			/* clean up */
+			memset(p,0,n);
+
+			/* send off the data */
+			n=BN_num_bytes(dh_clnt->pub_key);
+			s2n(n,p);
+			BN_bn2bin(dh_clnt->pub_key,p);
+			n+=2;
+
+			DH_free(dh_clnt);
+
+			/* perhaps clean things up a bit EAY EAY EAY EAY*/
+			}
+#endif
+
+#ifndef OPENSSL_NO_ECDH 
+		else if (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe))
+			{
+			const EC_GROUP *srvr_group = NULL;
+			EC_KEY *tkey;
+			int ecdh_clnt_cert = 0;
+			int field_size = 0;
+
+			/* Did we send out the client's
+			 * ECDH share for use in premaster
+			 * computation as part of client certificate?
+			 * If so, set ecdh_clnt_cert to 1.
+			 */
+			if ((alg_k & (SSL_kECDHr|SSL_kECDHe)) && (s->cert != NULL)) 
+				{
+				/* XXX: For now, we do not support client
+				 * authentication using ECDH certificates.
+				 * To add such support, one needs to add
+				 * code that checks for appropriate 
+				 * conditions and sets ecdh_clnt_cert to 1.
+				 * For example, the cert have an ECC
+				 * key on the same curve as the server's
+				 * and the key should be authorized for
+				 * key agreement.
+				 *
+				 * One also needs to add code in ssl3_connect
+				 * to skip sending the certificate verify
+				 * message.
+				 *
+				 * if ((s->cert->key->privatekey != NULL) &&
+				 *     (s->cert->key->privatekey->type ==
+				 *      EVP_PKEY_EC) && ...)
+				 * ecdh_clnt_cert = 1;
+				 */
+				}
+
+			if (s->session->sess_cert->peer_ecdh_tmp != NULL)
+				{
+				tkey = s->session->sess_cert->peer_ecdh_tmp;
+				}
+			else
+				{
+				/* Get the Server Public Key from Cert */
+				srvr_pub_pkey = X509_get_pubkey(s->session-> \
+				    sess_cert->peer_pkeys[SSL_PKEY_ECC].x509);
+				if ((srvr_pub_pkey == NULL) ||
+				    (srvr_pub_pkey->type != EVP_PKEY_EC) ||
+				    (srvr_pub_pkey->pkey.ec == NULL))
+					{
+					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+					    ERR_R_INTERNAL_ERROR);
+					goto err;
+					}
+
+				tkey = srvr_pub_pkey->pkey.ec;
+				}
+
+			srvr_group   = EC_KEY_get0_group(tkey);
+			srvr_ecpoint = EC_KEY_get0_public_key(tkey);
+
+			if ((srvr_group == NULL) || (srvr_ecpoint == NULL))
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+				    ERR_R_INTERNAL_ERROR);
+				goto err;
+				}
+
+			if ((clnt_ecdh=EC_KEY_new()) == NULL) 
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
+				goto err;
+				}
+
+			if (!EC_KEY_set_group(clnt_ecdh, srvr_group))
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_EC_LIB);
+				goto err;
+				}
+			if (ecdh_clnt_cert) 
+				{ 
+				/* Reuse key info from our certificate
+				 * We only need our private key to perform
+				 * the ECDH computation.
+				 */
+				const BIGNUM *priv_key;
+				tkey = s->cert->key->privatekey->pkey.ec;
+				priv_key = EC_KEY_get0_private_key(tkey);
+				if (priv_key == NULL)
+					{
+					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
+					goto err;
+					}
+				if (!EC_KEY_set_private_key(clnt_ecdh, priv_key))
+					{
+					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_EC_LIB);
+					goto err;
+					}
+				}
+			else 
+				{
+				/* Generate a new ECDH key pair */
+				if (!(EC_KEY_generate_key(clnt_ecdh)))
+					{
+					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB);
+					goto err;
+					}
+				}
+
+			/* use the 'p' output buffer for the ECDH key, but
+			 * make sure to clear it out afterwards
+			 */
+
+			field_size = EC_GROUP_get_degree(srvr_group);
+			if (field_size <= 0)
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, 
+				       ERR_R_ECDH_LIB);
+				goto err;
+				}
+			n=ECDH_compute_key(p, (field_size+7)/8, srvr_ecpoint, clnt_ecdh, NULL);
+			if (n <= 0)
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, 
+				       ERR_R_ECDH_LIB);
+				goto err;
+				}
+
+			/* generate master key from the result */
+			s->session->master_key_length = s->method->ssl3_enc \
+			    -> generate_master_secret(s, 
+				s->session->master_key,
+				p, n);
+
+			memset(p, 0, n); /* clean up */
+
+			if (ecdh_clnt_cert) 
+				{
+				/* Send empty client key exch message */
+				n = 0;
+				}
+			else 
+				{
+				/* First check the size of encoding and
+				 * allocate memory accordingly.
+				 */
+				encoded_pt_len = 
+				    EC_POINT_point2oct(srvr_group, 
+					EC_KEY_get0_public_key(clnt_ecdh), 
+					POINT_CONVERSION_UNCOMPRESSED, 
+					NULL, 0, NULL);
+
+				encodedPoint = (unsigned char *) 
+				    OPENSSL_malloc(encoded_pt_len * 
+					sizeof(unsigned char)); 
+				bn_ctx = BN_CTX_new();
+				if ((encodedPoint == NULL) || 
+				    (bn_ctx == NULL)) 
+					{
+					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
+					goto err;
+					}
+
+				/* Encode the public key */
+				n = EC_POINT_point2oct(srvr_group, 
+				    EC_KEY_get0_public_key(clnt_ecdh), 
+				    POINT_CONVERSION_UNCOMPRESSED, 
+				    encodedPoint, encoded_pt_len, bn_ctx);
+
+				*p = n; /* length of encoded point */
+				/* Encoded point will be copied here */
+				p += 1; 
+				/* copy the point */
+				memcpy((unsigned char *)p, encodedPoint, n);
+				/* increment n to account for length field */
+				n += 1; 
+				}
+
+			/* Free allocated memory */
+			BN_CTX_free(bn_ctx);
+			if (encodedPoint != NULL) OPENSSL_free(encodedPoint);
+			if (clnt_ecdh != NULL) 
+				 EC_KEY_free(clnt_ecdh);
+			EVP_PKEY_free(srvr_pub_pkey);
+			}
+#endif /* !OPENSSL_NO_ECDH */
+		else if (alg_k & SSL_kGOST) 
+			{
+			/* GOST key exchange message creation */
+			EVP_PKEY_CTX *pkey_ctx;
+			X509 *peer_cert; 
+			size_t msglen;
+			unsigned int md_len;
+			int keytype;
+			unsigned char premaster_secret[32],shared_ukm[32], tmp[256];
+			EVP_MD_CTX *ukm_hash;
+			EVP_PKEY *pub_key;
+
+			/* Get server sertificate PKEY and create ctx from it */
+			peer_cert=s->session->sess_cert->peer_pkeys[(keytype=SSL_PKEY_GOST01)].x509;
+			if (!peer_cert) 
+				peer_cert=s->session->sess_cert->peer_pkeys[(keytype=SSL_PKEY_GOST94)].x509;
+			if (!peer_cert)		{
+					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
+					goto err;
+				}	
+				
+			pkey_ctx=EVP_PKEY_CTX_new(pub_key=X509_get_pubkey(peer_cert),NULL);
+			/* If we have send a certificate, and certificate key
+
+			 * parameters match those of server certificate, use
+			 * certificate key for key exchange
+			 */
+
+			 /* Otherwise, generate ephemeral key pair */
+					
+			EVP_PKEY_encrypt_init(pkey_ctx);
+			  /* Generate session key */	
+		    RAND_bytes(premaster_secret,32);
+			/* If we have client certificate, use its secret as peer key */
+			if (s->s3->tmp.cert_req && s->cert->key->privatekey) {
+				if (EVP_PKEY_derive_set_peer(pkey_ctx,s->cert->key->privatekey) <=0) {
+					/* If there was an error - just ignore it. Ephemeral key
+					* would be used
+					*/
+					ERR_clear_error();
+				}
+			}			
+			/* Compute shared IV and store it in algorithm-specific
+			 * context data */
+			ukm_hash = EVP_MD_CTX_create();
+			EVP_DigestInit(ukm_hash,EVP_get_digestbynid(NID_id_GostR3411_94));
+			EVP_DigestUpdate(ukm_hash,s->s3->client_random,SSL3_RANDOM_SIZE);
+			EVP_DigestUpdate(ukm_hash,s->s3->server_random,SSL3_RANDOM_SIZE);
+			EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len);
+			EVP_MD_CTX_destroy(ukm_hash);
+			if (EVP_PKEY_CTX_ctrl(pkey_ctx,-1,EVP_PKEY_OP_ENCRYPT,EVP_PKEY_CTRL_SET_IV,
+				8,shared_ukm)<0) {
+					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+						SSL_R_LIBRARY_BUG);
+					goto err;
+				}	
+			/* Make GOST keytransport blob message */
+			/*Encapsulate it into sequence */
+			*(p++)=V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED;
+			msglen=255;
+			if (EVP_PKEY_encrypt(pkey_ctx,tmp,&msglen,premaster_secret,32)<0) {
+			SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+					SSL_R_LIBRARY_BUG);
+				goto err;
+			}
+			if (msglen >= 0x80)
+				{
+				*(p++)=0x81;
+				*(p++)= msglen & 0xff;
+				n=msglen+3;
+				}
+			else
+				{
+				*(p++)= msglen & 0xff;
+				n=msglen+2;
+				}
+			memcpy(p, tmp, msglen);
+			/* Check if pubkey from client certificate was used */
+			if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, NULL) > 0)
+				{
+				/* Set flag "skip certificate verify" */
+				s->s3->flags |= TLS1_FLAGS_SKIP_CERT_VERIFY;
+				}
+			EVP_PKEY_CTX_free(pkey_ctx);
+			s->session->master_key_length=
+				s->method->ssl3_enc->generate_master_secret(s,
+					s->session->master_key,premaster_secret,32);
+			EVP_PKEY_free(pub_key);
+
+			}
+#ifndef OPENSSL_NO_PSK
+		else if (alg_k & SSL_kPSK)
+			{
+			char identity[PSK_MAX_IDENTITY_LEN];
+			unsigned char *t = NULL;
+			unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN*2+4];
+			unsigned int pre_ms_len = 0, psk_len = 0;
+			int psk_err = 1;
+
+			n = 0;
+			if (s->psk_client_callback == NULL)
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+					SSL_R_PSK_NO_CLIENT_CB);
+				goto err;
+				}
+
+			psk_len = s->psk_client_callback(s, s->ctx->psk_identity_hint,
+				identity, PSK_MAX_IDENTITY_LEN,
+				psk_or_pre_ms, sizeof(psk_or_pre_ms));
+			if (psk_len > PSK_MAX_PSK_LEN)
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+					ERR_R_INTERNAL_ERROR);
+				goto psk_err;
+				}
+			else if (psk_len == 0)
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+					SSL_R_PSK_IDENTITY_NOT_FOUND);
+				goto psk_err;
+				}
+
+			/* create PSK pre_master_secret */
+			pre_ms_len = 2+psk_len+2+psk_len;
+			t = psk_or_pre_ms;
+			memmove(psk_or_pre_ms+psk_len+4, psk_or_pre_ms, psk_len);
+			s2n(psk_len, t);
+			memset(t, 0, psk_len);
+			t+=psk_len;
+			s2n(psk_len, t);
+
+			if (s->session->psk_identity_hint != NULL)
+				OPENSSL_free(s->session->psk_identity_hint);
+			s->session->psk_identity_hint = BUF_strdup(s->ctx->psk_identity_hint);
+			if (s->ctx->psk_identity_hint != NULL &&
+				s->session->psk_identity_hint == NULL)
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+					ERR_R_MALLOC_FAILURE);
+				goto psk_err;
+				}
+
+			if (s->session->psk_identity != NULL)
+				OPENSSL_free(s->session->psk_identity);
+			s->session->psk_identity = BUF_strdup(identity);
+			if (s->session->psk_identity == NULL)
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+					ERR_R_MALLOC_FAILURE);
+				goto psk_err;
+				}
+
+			s->session->master_key_length =
+				s->method->ssl3_enc->generate_master_secret(s,
+					s->session->master_key,
+					psk_or_pre_ms, pre_ms_len); 
+			n = strlen(identity);
+			s2n(n, p);
+			memcpy(p, identity, n);
+			n+=2;
+			psk_err = 0;
+		psk_err:
+			OPENSSL_cleanse(identity, PSK_MAX_IDENTITY_LEN);
+			OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms));
+			if (psk_err != 0)
+				{
+				ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+				goto err;
+				}
+			}
+#endif
+		else
+			{
+			ssl3_send_alert(s, SSL3_AL_FATAL,
+			    SSL_AD_HANDSHAKE_FAILURE);
+			SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+			    ERR_R_INTERNAL_ERROR);
+			goto err;
+			}
+		
+		*(d++)=SSL3_MT_CLIENT_KEY_EXCHANGE;
+		l2n3(n,d);
+
+		s->state=SSL3_ST_CW_KEY_EXCH_B;
+		/* number of bytes to write */
+		s->init_num=n+4;
+		s->init_off=0;
+		}
+
+	/* SSL3_ST_CW_KEY_EXCH_B */
+	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+err:
+#ifndef OPENSSL_NO_ECDH
+	BN_CTX_free(bn_ctx);
+	if (encodedPoint != NULL) OPENSSL_free(encodedPoint);
+	if (clnt_ecdh != NULL) 
+		EC_KEY_free(clnt_ecdh);
+	EVP_PKEY_free(srvr_pub_pkey);
+#endif
+	return(-1);
+	}
+
+int ssl3_send_client_verify(SSL *s)
+	{
+	unsigned char *p,*d;
+	unsigned char data[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH];
+	EVP_PKEY *pkey;
+	EVP_PKEY_CTX *pctx=NULL;
+#ifndef OPENSSL_NO_RSA
+	unsigned u=0;
+#endif
+	unsigned long n;
+	int j;
+
+	if (s->state == SSL3_ST_CW_CERT_VRFY_A)
+		{
+		d=(unsigned char *)s->init_buf->data;
+		p= &(d[4]);
+		pkey=s->cert->key->privatekey;
+/* Create context from key and test if sha1 is allowed as digest */
+		pctx = EVP_PKEY_CTX_new(pkey,NULL);
+		EVP_PKEY_sign_init(pctx);
+		if (EVP_PKEY_CTX_set_signature_md(pctx, EVP_sha1())>0)
+			{
+			s->method->ssl3_enc->cert_verify_mac(s,
+						NID_sha1,
+						&(data[MD5_DIGEST_LENGTH]));
+			}
+		else
+			{
+			ERR_clear_error();
+			}
+#ifndef OPENSSL_NO_RSA
+		if (pkey->type == EVP_PKEY_RSA)
+			{
+			s->method->ssl3_enc->cert_verify_mac(s,
+				NID_md5,
+			 	&(data[0]));
+			if (RSA_sign(NID_md5_sha1, data,
+					 MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH,
+					&(p[2]), &u, pkey->pkey.rsa) <= 0 )
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_RSA_LIB);
+				goto err;
+				}
+			s2n(u,p);
+			n=u+2;
+			}
+		else
+#endif
+#ifndef OPENSSL_NO_DSA
+			if (pkey->type == EVP_PKEY_DSA)
+			{
+			if (!DSA_sign(pkey->save_type,
+				&(data[MD5_DIGEST_LENGTH]),
+				SHA_DIGEST_LENGTH,&(p[2]),
+				(unsigned int *)&j,pkey->pkey.dsa))
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_DSA_LIB);
+				goto err;
+				}
+			s2n(j,p);
+			n=j+2;
+			}
+		else
+#endif
+#ifndef OPENSSL_NO_ECDSA
+			if (pkey->type == EVP_PKEY_EC)
+			{
+			if (!ECDSA_sign(pkey->save_type,
+				&(data[MD5_DIGEST_LENGTH]),
+				SHA_DIGEST_LENGTH,&(p[2]),
+				(unsigned int *)&j,pkey->pkey.ec))
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,
+				    ERR_R_ECDSA_LIB);
+				goto err;
+				}
+			s2n(j,p);
+			n=j+2;
+			}
+		else
+#endif
+		if (pkey->type == NID_id_GostR3410_94 || pkey->type == NID_id_GostR3410_2001) 
+		{
+		unsigned char signbuf[64];
+		int i;
+		size_t sigsize=64;
+		s->method->ssl3_enc->cert_verify_mac(s,
+			NID_id_GostR3411_94,
+			data);
+		if (EVP_PKEY_sign(pctx, signbuf, &sigsize, data, 32) <= 0) {
+			SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,
+			ERR_R_INTERNAL_ERROR);
+			goto err;
+		}
+		for (i=63,j=0; i>=0; j++, i--) {
+			p[2+j]=signbuf[i];
+		}	
+		s2n(j,p);
+		n=j+2;
+		}
+		else
+		{
+			SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_INTERNAL_ERROR);
+			goto err;
+		}
+		*(d++)=SSL3_MT_CERTIFICATE_VERIFY;
+		l2n3(n,d);
+
+		s->state=SSL3_ST_CW_CERT_VRFY_B;
+		s->init_num=(int)n+4;
+		s->init_off=0;
+		}
+	EVP_PKEY_CTX_free(pctx);
+	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+err:
+	EVP_PKEY_CTX_free(pctx);
+	return(-1);
+	}
+
+int ssl3_send_client_certificate(SSL *s)
+	{
+	X509 *x509=NULL;
+	EVP_PKEY *pkey=NULL;
+	int i;
+	unsigned long l;
+
+	if (s->state ==	SSL3_ST_CW_CERT_A)
+		{
+		if ((s->cert == NULL) ||
+			(s->cert->key->x509 == NULL) ||
+			(s->cert->key->privatekey == NULL))
+			s->state=SSL3_ST_CW_CERT_B;
+		else
+			s->state=SSL3_ST_CW_CERT_C;
+		}
+
+	/* We need to get a client cert */
+	if (s->state == SSL3_ST_CW_CERT_B)
+		{
+		/* If we get an error, we need to
+		 * ssl->rwstate=SSL_X509_LOOKUP; return(-1);
+		 * We then get retied later */
+		i=0;
+		i = ssl_do_client_cert_cb(s, &x509, &pkey);
+		if (i < 0)
+			{
+			s->rwstate=SSL_X509_LOOKUP;
+			return(-1);
+			}
+		s->rwstate=SSL_NOTHING;
+		if ((i == 1) && (pkey != NULL) && (x509 != NULL))
+			{
+			s->state=SSL3_ST_CW_CERT_B;
+			if (	!SSL_use_certificate(s,x509) ||
+				!SSL_use_PrivateKey(s,pkey))
+				i=0;
+			}
+		else if (i == 1)
+			{
+			i=0;
+			SSLerr(SSL_F_SSL3_SEND_CLIENT_CERTIFICATE,SSL_R_BAD_DATA_RETURNED_BY_CALLBACK);
+			}
+
+		if (x509 != NULL) X509_free(x509);
+		if (pkey != NULL) EVP_PKEY_free(pkey);
+		if (i == 0)
+			{
+			if (s->version == SSL3_VERSION)
+				{
+				s->s3->tmp.cert_req=0;
+				ssl3_send_alert(s,SSL3_AL_WARNING,SSL_AD_NO_CERTIFICATE);
+				return(1);
+				}
+			else
+				{
+				s->s3->tmp.cert_req=2;
+				}
+			}
+
+		/* Ok, we have a cert */
+		s->state=SSL3_ST_CW_CERT_C;
+		}
+
+	if (s->state == SSL3_ST_CW_CERT_C)
+		{
+		s->state=SSL3_ST_CW_CERT_D;
+		l=ssl3_output_cert_chain(s,
+			(s->s3->tmp.cert_req == 2)?NULL:s->cert->key->x509);
+		s->init_num=(int)l;
+		s->init_off=0;
+		}
+	/* SSL3_ST_CW_CERT_D */
+	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+	}
+
+#define has_bits(i,m)	(((i)&(m)) == (m))
+
+int ssl3_check_cert_and_algorithm(SSL *s)
+	{
+	int i,idx;
+	long alg_k,alg_a;
+	EVP_PKEY *pkey=NULL;
+	SESS_CERT *sc;
+#ifndef OPENSSL_NO_RSA
+	RSA *rsa;
+#endif
+#ifndef OPENSSL_NO_DH
+	DH *dh;
+#endif
+
+	alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
+	alg_a=s->s3->tmp.new_cipher->algorithm_auth;
+
+	/* we don't have a certificate */
+	if ((alg_a & (SSL_aDH|SSL_aNULL|SSL_aKRB5)) || (alg_k & SSL_kPSK))
+		return(1);
+
+	sc=s->session->sess_cert;
+	if (sc == NULL)
+		{
+		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,ERR_R_INTERNAL_ERROR);
+		goto err;
+		}
+
+#ifndef OPENSSL_NO_RSA
+	rsa=s->session->sess_cert->peer_rsa_tmp;
+#endif
+#ifndef OPENSSL_NO_DH
+	dh=s->session->sess_cert->peer_dh_tmp;
+#endif
+
+	/* This is the passed certificate */
+
+	idx=sc->peer_cert_type;
+#ifndef OPENSSL_NO_ECDH
+	if (idx == SSL_PKEY_ECC)
+		{
+		if (ssl_check_srvr_ecc_cert_and_alg(sc->peer_pkeys[idx].x509,
+		    s->s3->tmp.new_cipher) == 0) 
+			{ /* check failed */
+			SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_BAD_ECC_CERT);
+			goto f_err;
+			}
+		else 
+			{
+			return 1;
+			}
+		}
+#endif
+	pkey=X509_get_pubkey(sc->peer_pkeys[idx].x509);
+	i=X509_certificate_type(sc->peer_pkeys[idx].x509,pkey);
+	EVP_PKEY_free(pkey);
+
+	
+	/* Check that we have a certificate if we require one */
+	if ((alg_a & SSL_aRSA) && !has_bits(i,EVP_PK_RSA|EVP_PKT_SIGN))
+		{
+		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_RSA_SIGNING_CERT);
+		goto f_err;
+		}
+#ifndef OPENSSL_NO_DSA
+	else if ((alg_a & SSL_aDSS) && !has_bits(i,EVP_PK_DSA|EVP_PKT_SIGN))
+		{
+		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DSA_SIGNING_CERT);
+		goto f_err;
+		}
+#endif
+#ifndef OPENSSL_NO_RSA
+	if ((alg_k & SSL_kRSA) &&
+		!(has_bits(i,EVP_PK_RSA|EVP_PKT_ENC) || (rsa != NULL)))
+		{
+		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_RSA_ENCRYPTING_CERT);
+		goto f_err;
+		}
+#endif
+#ifndef OPENSSL_NO_DH
+	if ((alg_k & SSL_kEDH) &&
+		!(has_bits(i,EVP_PK_DH|EVP_PKT_EXCH) || (dh != NULL)))
+		{
+		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_KEY);
+		goto f_err;
+		}
+	else if ((alg_k & SSL_kDHr) && !has_bits(i,EVP_PK_DH|EVP_PKS_RSA))
+		{
+		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_RSA_CERT);
+		goto f_err;
+		}
+#ifndef OPENSSL_NO_DSA
+	else if ((alg_k & SSL_kDHd) && !has_bits(i,EVP_PK_DH|EVP_PKS_DSA))
+		{
+		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_DSA_CERT);
+		goto f_err;
+		}
+#endif
+#endif
+
+	if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && !has_bits(i,EVP_PKT_EXP))
+		{
+#ifndef OPENSSL_NO_RSA
+		if (alg_k & SSL_kRSA)
+			{
+			if (rsa == NULL
+			    || RSA_size(rsa)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher))
+				{
+				SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_EXPORT_TMP_RSA_KEY);
+				goto f_err;
+				}
+			}
+		else
+#endif
+#ifndef OPENSSL_NO_DH
+			if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
+			    {
+			    if (dh == NULL
+				|| DH_size(dh)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher))
+				{
+				SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_EXPORT_TMP_DH_KEY);
+				goto f_err;
+				}
+			}
+		else
+#endif
+			{
+			SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
+			goto f_err;
+			}
+		}
+	return(1);
+f_err:
+	ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
+err:
+	return(0);
+	}
+
+/* Check to see if handshake is full or resumed. Usually this is just a
+ * case of checking to see if a cache hit has occurred. In the case of
+ * session tickets we have to check the next message to be sure.
+ */
+
+#ifndef OPENSSL_NO_TLSEXT
+int ssl3_check_finished(SSL *s)
+	{
+	int ok;
+	long n;
+	/* If we have no ticket it cannot be a resumed session. */
+	if (!s->session->tlsext_tick)
+		return 1;
+	/* this function is called when we really expect a Certificate
+	 * message, so permit appropriate message length */
+	n=s->method->ssl_get_message(s,
+		SSL3_ST_CR_CERT_A,
+		SSL3_ST_CR_CERT_B,
+		-1,
+		s->max_cert_list,
+		&ok);
+	if (!ok) return((int)n);
+	s->s3->tmp.reuse_message = 1;
+	if ((s->s3->tmp.message_type == SSL3_MT_FINISHED)
+		|| (s->s3->tmp.message_type == SSL3_MT_NEWSESSION_TICKET))
+		return 2;
+
+	return 1;
+	}
+#endif
+
+int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey)
+	{
+	int i = 0;
+#ifndef OPENSSL_NO_ENGINE
+	if (s->ctx->client_cert_engine)
+		{
+		i = ENGINE_load_ssl_client_cert(s->ctx->client_cert_engine, s,
+						SSL_get_client_CA_list(s),
+						px509, ppkey, NULL, NULL, NULL);
+		if (i != 0)
+			return i;
+		}
+#endif
+	if (s->ctx->client_cert_cb)
+		i = s->ctx->client_cert_cb(s,px509,ppkey);
+	return i;
+	}
diff --git a/lib/openssl/ssl/s3_enc.c b/lib/openssl/ssl/s3_enc.c
new file mode 100644
index 0000000..3d7aec9
--- /dev/null
+++ b/lib/openssl/ssl/s3_enc.c
@@ -0,0 +1,847 @@
+/* ssl/s3_enc.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#include <stdio.h>
+#include "ssl_locl.h"
+#include <openssl/evp.h>
+#include <openssl/md5.h>
+
+static unsigned char ssl3_pad_1[48]={
+	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 unsigned char ssl3_pad_2[48]={
+	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 };
+static int ssl3_handshake_mac(SSL *s, int md_nid,
+	const char *sender, int len, unsigned char *p);
+static int ssl3_generate_key_block(SSL *s, unsigned char *km, int num)
+	{
+	EVP_MD_CTX m5;
+	EVP_MD_CTX s1;
+	unsigned char buf[16],smd[SHA_DIGEST_LENGTH];
+	unsigned char c='A';
+	unsigned int i,j,k;
+
+#ifdef CHARSET_EBCDIC
+	c = os_toascii[c]; /*'A' in ASCII */
+#endif
+	k=0;
+	EVP_MD_CTX_init(&m5);
+	EVP_MD_CTX_init(&s1);
+	for (i=0; (int)i<num; i+=MD5_DIGEST_LENGTH)
+		{
+		k++;
+		if (k > sizeof buf)
+			{
+			/* bug: 'buf' is too small for this ciphersuite */
+			SSLerr(SSL_F_SSL3_GENERATE_KEY_BLOCK, ERR_R_INTERNAL_ERROR);
+			return 0;
+			}
+		
+		for (j=0; j<k; j++)
+			buf[j]=c;
+		c++;
+		EVP_DigestInit_ex(&s1,EVP_sha1(), NULL);
+		EVP_DigestUpdate(&s1,buf,k);
+		EVP_DigestUpdate(&s1,s->session->master_key,
+			s->session->master_key_length);
+		EVP_DigestUpdate(&s1,s->s3->server_random,SSL3_RANDOM_SIZE);
+		EVP_DigestUpdate(&s1,s->s3->client_random,SSL3_RANDOM_SIZE);
+		EVP_DigestFinal_ex(&s1,smd,NULL);
+
+		EVP_DigestInit_ex(&m5,EVP_md5(), NULL);
+		EVP_DigestUpdate(&m5,s->session->master_key,
+			s->session->master_key_length);
+		EVP_DigestUpdate(&m5,smd,SHA_DIGEST_LENGTH);
+		if ((int)(i+MD5_DIGEST_LENGTH) > num)
+			{
+			EVP_DigestFinal_ex(&m5,smd,NULL);
+			memcpy(km,smd,(num-i));
+			}
+		else
+			EVP_DigestFinal_ex(&m5,km,NULL);
+
+		km+=MD5_DIGEST_LENGTH;
+		}
+	OPENSSL_cleanse(smd,SHA_DIGEST_LENGTH);
+	EVP_MD_CTX_cleanup(&m5);
+	EVP_MD_CTX_cleanup(&s1);
+	return 1;
+	}
+
+int ssl3_change_cipher_state(SSL *s, int which)
+	{
+	unsigned char *p,*key_block,*mac_secret;
+	unsigned char exp_key[EVP_MAX_KEY_LENGTH];
+	unsigned char exp_iv[EVP_MAX_IV_LENGTH];
+	unsigned char *ms,*key,*iv,*er1,*er2;
+	EVP_CIPHER_CTX *dd;
+	const EVP_CIPHER *c;
+#ifndef OPENSSL_NO_COMP
+	COMP_METHOD *comp;
+#endif
+	const EVP_MD *m;
+	EVP_MD_CTX md;
+	int is_exp,n,i,j,k,cl;
+	int reuse_dd = 0;
+
+	is_exp=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher);
+	c=s->s3->tmp.new_sym_enc;
+	m=s->s3->tmp.new_hash;
+	/* m == NULL will lead to a crash later */
+	OPENSSL_assert(m);
+#ifndef OPENSSL_NO_COMP
+	if (s->s3->tmp.new_compression == NULL)
+		comp=NULL;
+	else
+		comp=s->s3->tmp.new_compression->method;
+#endif
+	key_block=s->s3->tmp.key_block;
+
+	if (which & SSL3_CC_READ)
+		{
+		if (s->enc_read_ctx != NULL)
+			reuse_dd = 1;
+		else if ((s->enc_read_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL)
+			goto err;
+		else
+			/* make sure it's intialized in case we exit later with an error */
+			EVP_CIPHER_CTX_init(s->enc_read_ctx);
+		dd= s->enc_read_ctx;
+
+		ssl_replace_hash(&s->read_hash,m);
+#ifndef OPENSSL_NO_COMP
+		/* COMPRESS */
+		if (s->expand != NULL)
+			{
+			COMP_CTX_free(s->expand);
+			s->expand=NULL;
+			}
+		if (comp != NULL)
+			{
+			s->expand=COMP_CTX_new(comp);
+			if (s->expand == NULL)
+				{
+				SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR);
+				goto err2;
+				}
+			if (s->s3->rrec.comp == NULL)
+				s->s3->rrec.comp=(unsigned char *)
+					OPENSSL_malloc(SSL3_RT_MAX_PLAIN_LENGTH);
+			if (s->s3->rrec.comp == NULL)
+				goto err;
+			}
+#endif
+		memset(&(s->s3->read_sequence[0]),0,8);
+		mac_secret= &(s->s3->read_mac_secret[0]);
+		}
+	else
+		{
+		if (s->enc_write_ctx != NULL)
+			reuse_dd = 1;
+		else if ((s->enc_write_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL)
+			goto err;
+		else
+			/* make sure it's intialized in case we exit later with an error */
+			EVP_CIPHER_CTX_init(s->enc_write_ctx);
+		dd= s->enc_write_ctx;
+		ssl_replace_hash(&s->write_hash,m);
+#ifndef OPENSSL_NO_COMP
+		/* COMPRESS */
+		if (s->compress != NULL)
+			{
+			COMP_CTX_free(s->compress);
+			s->compress=NULL;
+			}
+		if (comp != NULL)
+			{
+			s->compress=COMP_CTX_new(comp);
+			if (s->compress == NULL)
+				{
+				SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR);
+				goto err2;
+				}
+			}
+#endif
+		memset(&(s->s3->write_sequence[0]),0,8);
+		mac_secret= &(s->s3->write_mac_secret[0]);
+		}
+
+	if (reuse_dd)
+		EVP_CIPHER_CTX_cleanup(dd);
+
+	p=s->s3->tmp.key_block;
+	i=EVP_MD_size(m);
+	if (i < 0)
+		goto err2;
+	cl=EVP_CIPHER_key_length(c);
+	j=is_exp ? (cl < SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher) ?
+		 cl : SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher)) : cl;
+	/* Was j=(is_exp)?5:EVP_CIPHER_key_length(c); */
+	k=EVP_CIPHER_iv_length(c);
+	if (	(which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) ||
+		(which == SSL3_CHANGE_CIPHER_SERVER_READ))
+		{
+		ms=  &(p[ 0]); n=i+i;
+		key= &(p[ n]); n+=j+j;
+		iv=  &(p[ n]); n+=k+k;
+		er1= &(s->s3->client_random[0]);
+		er2= &(s->s3->server_random[0]);
+		}
+	else
+		{
+		n=i;
+		ms=  &(p[ n]); n+=i+j;
+		key= &(p[ n]); n+=j+k;
+		iv=  &(p[ n]); n+=k;
+		er1= &(s->s3->server_random[0]);
+		er2= &(s->s3->client_random[0]);
+		}
+
+	if (n > s->s3->tmp.key_block_length)
+		{
+		SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE,ERR_R_INTERNAL_ERROR);
+		goto err2;
+		}
+
+	EVP_MD_CTX_init(&md);
+	memcpy(mac_secret,ms,i);
+	if (is_exp)
+		{
+		/* In here I set both the read and write key/iv to the
+		 * same value since only the correct one will be used :-).
+		 */
+		EVP_DigestInit_ex(&md,EVP_md5(), NULL);
+		EVP_DigestUpdate(&md,key,j);
+		EVP_DigestUpdate(&md,er1,SSL3_RANDOM_SIZE);
+		EVP_DigestUpdate(&md,er2,SSL3_RANDOM_SIZE);
+		EVP_DigestFinal_ex(&md,&(exp_key[0]),NULL);
+		key= &(exp_key[0]);
+
+		if (k > 0)
+			{
+			EVP_DigestInit_ex(&md,EVP_md5(), NULL);
+			EVP_DigestUpdate(&md,er1,SSL3_RANDOM_SIZE);
+			EVP_DigestUpdate(&md,er2,SSL3_RANDOM_SIZE);
+			EVP_DigestFinal_ex(&md,&(exp_iv[0]),NULL);
+			iv= &(exp_iv[0]);
+			}
+		}
+
+	s->session->key_arg_length=0;
+
+	EVP_CipherInit_ex(dd,c,NULL,key,iv,(which & SSL3_CC_WRITE));
+
+	OPENSSL_cleanse(&(exp_key[0]),sizeof(exp_key));
+	OPENSSL_cleanse(&(exp_iv[0]),sizeof(exp_iv));
+	EVP_MD_CTX_cleanup(&md);
+	return(1);
+err:
+	SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE,ERR_R_MALLOC_FAILURE);
+err2:
+	return(0);
+	}
+
+int ssl3_setup_key_block(SSL *s)
+	{
+	unsigned char *p;
+	const EVP_CIPHER *c;
+	const EVP_MD *hash;
+	int num;
+	int ret = 0;
+	SSL_COMP *comp;
+
+	if (s->s3->tmp.key_block_length != 0)
+		return(1);
+
+	if (!ssl_cipher_get_evp(s->session,&c,&hash,NULL,NULL,&comp))
+		{
+		SSLerr(SSL_F_SSL3_SETUP_KEY_BLOCK,SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
+		return(0);
+		}
+
+	s->s3->tmp.new_sym_enc=c;
+	s->s3->tmp.new_hash=hash;
+#ifdef OPENSSL_NO_COMP
+	s->s3->tmp.new_compression=NULL;
+#else
+	s->s3->tmp.new_compression=comp;
+#endif
+
+	num=EVP_MD_size(hash);
+	if (num < 0)
+		return 0;
+
+	num=EVP_CIPHER_key_length(c)+num+EVP_CIPHER_iv_length(c);
+	num*=2;
+
+	ssl3_cleanup_key_block(s);
+
+	if ((p=OPENSSL_malloc(num)) == NULL)
+		goto err;
+
+	s->s3->tmp.key_block_length=num;
+	s->s3->tmp.key_block=p;
+
+	ret = ssl3_generate_key_block(s,p,num);
+
+	if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS))
+		{
+		/* enable vulnerability countermeasure for CBC ciphers with
+		 * known-IV problem (http://www.openssl.org/~bodo/tls-cbc.txt)
+		 */
+		s->s3->need_empty_fragments = 1;
+
+		if (s->session->cipher != NULL)
+			{
+			if (s->session->cipher->algorithm_enc == SSL_eNULL)
+				s->s3->need_empty_fragments = 0;
+			
+#ifndef OPENSSL_NO_RC4
+			if (s->session->cipher->algorithm_enc == SSL_RC4)
+				s->s3->need_empty_fragments = 0;
+#endif
+			}
+		}
+
+	return ret;
+		
+err:
+	SSLerr(SSL_F_SSL3_SETUP_KEY_BLOCK,ERR_R_MALLOC_FAILURE);
+	return(0);
+	}
+
+void ssl3_cleanup_key_block(SSL *s)
+	{
+	if (s->s3->tmp.key_block != NULL)
+		{
+		OPENSSL_cleanse(s->s3->tmp.key_block,
+			s->s3->tmp.key_block_length);
+		OPENSSL_free(s->s3->tmp.key_block);
+		s->s3->tmp.key_block=NULL;
+		}
+	s->s3->tmp.key_block_length=0;
+	}
+
+int ssl3_enc(SSL *s, int send)
+	{
+	SSL3_RECORD *rec;
+	EVP_CIPHER_CTX *ds;
+	unsigned long l;
+	int bs,i;
+	const EVP_CIPHER *enc;
+
+	if (send)
+		{
+		ds=s->enc_write_ctx;
+		rec= &(s->s3->wrec);
+		if (s->enc_write_ctx == NULL)
+			enc=NULL;
+		else
+			enc=EVP_CIPHER_CTX_cipher(s->enc_write_ctx);
+		}
+	else
+		{
+		ds=s->enc_read_ctx;
+		rec= &(s->s3->rrec);
+		if (s->enc_read_ctx == NULL)
+			enc=NULL;
+		else
+			enc=EVP_CIPHER_CTX_cipher(s->enc_read_ctx);
+		}
+
+	if ((s->session == NULL) || (ds == NULL) ||
+		(enc == NULL))
+		{
+		memmove(rec->data,rec->input,rec->length);
+		rec->input=rec->data;
+		}
+	else
+		{
+		l=rec->length;
+		bs=EVP_CIPHER_block_size(ds->cipher);
+
+		/* COMPRESS */
+
+		if ((bs != 1) && send)
+			{
+			i=bs-((int)l%bs);
+
+			/* we need to add 'i-1' padding bytes */
+			l+=i;
+			rec->length+=i;
+			rec->input[l-1]=(i-1);
+			}
+		
+		if (!send)
+			{
+			if (l == 0 || l%bs != 0)
+				{
+				SSLerr(SSL_F_SSL3_ENC,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG);
+				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECRYPTION_FAILED);
+				return 0;
+				}
+			/* otherwise, rec->length >= bs */
+			}
+		
+		EVP_Cipher(ds,rec->data,rec->input,l);
+
+		if ((bs != 1) && !send)
+			{
+			i=rec->data[l-1]+1;
+			/* SSL 3.0 bounds the number of padding bytes by the block size;
+			 * padding bytes (except the last one) are arbitrary */
+			if (i > bs)
+				{
+				/* Incorrect padding. SSLerr() and ssl3_alert are done
+				 * by caller: we don't want to reveal whether this is
+				 * a decryption error or a MAC verification failure
+				 * (see http://www.openssl.org/~bodo/tls-cbc.txt) */
+				return -1;
+				}
+			/* now i <= bs <= rec->length */
+			rec->length-=i;
+			}
+		}
+	return(1);
+	}
+
+void ssl3_init_finished_mac(SSL *s)
+	{
+	if (s->s3->handshake_buffer) BIO_free(s->s3->handshake_buffer);
+	if (s->s3->handshake_dgst) ssl3_free_digest_list(s);
+    s->s3->handshake_buffer=BIO_new(BIO_s_mem());	
+	(void)BIO_set_close(s->s3->handshake_buffer,BIO_CLOSE);
+	}
+
+void ssl3_free_digest_list(SSL *s) 
+	{
+	int i;
+	if (!s->s3->handshake_dgst) return;
+	for (i=0;i<SSL_MAX_DIGEST;i++) 
+		{
+		if (s->s3->handshake_dgst[i])
+			EVP_MD_CTX_destroy(s->s3->handshake_dgst[i]);
+		}
+	OPENSSL_free(s->s3->handshake_dgst);
+	s->s3->handshake_dgst=NULL;
+	}	
+		
+
+
+void ssl3_finish_mac(SSL *s, const unsigned char *buf, int len)
+	{
+	if (s->s3->handshake_buffer) 
+		{
+		BIO_write (s->s3->handshake_buffer,(void *)buf,len);
+		} 
+	else 
+		{
+		int i;
+		for (i=0;i< SSL_MAX_DIGEST;i++) 
+			{
+			if (s->s3->handshake_dgst[i]!= NULL)
+			EVP_DigestUpdate(s->s3->handshake_dgst[i],buf,len);
+			}
+		}	
+	}
+
+int ssl3_digest_cached_records(SSL *s)
+	{
+	int i;
+	long mask;
+	const EVP_MD *md;
+	long hdatalen;
+	void *hdata;
+
+	/* Allocate handshake_dgst array */
+	ssl3_free_digest_list(s);
+	s->s3->handshake_dgst = OPENSSL_malloc(SSL_MAX_DIGEST * sizeof(EVP_MD_CTX *));
+	memset(s->s3->handshake_dgst,0,SSL_MAX_DIGEST *sizeof(EVP_MD_CTX *));
+	hdatalen = BIO_get_mem_data(s->s3->handshake_buffer,&hdata);
+	if (hdatalen <= 0)
+		{
+		SSLerr(SSL_F_SSL3_DIGEST_CACHED_RECORDS, SSL_R_BAD_HANDSHAKE_LENGTH);
+		return 0;
+		}
+
+	/* Loop through bitso of algorithm2 field and create MD_CTX-es */
+	for (i=0;ssl_get_handshake_digest(i,&mask,&md); i++) 
+		{
+		if ((mask & s->s3->tmp.new_cipher->algorithm2) && md) 
+			{
+			s->s3->handshake_dgst[i]=EVP_MD_CTX_create();
+			EVP_DigestInit_ex(s->s3->handshake_dgst[i],md,NULL);
+			EVP_DigestUpdate(s->s3->handshake_dgst[i],hdata,hdatalen);
+			} 
+		else 
+			{	
+			s->s3->handshake_dgst[i]=NULL;
+			}
+		}
+	/* Free handshake_buffer BIO */
+	BIO_free(s->s3->handshake_buffer);
+	s->s3->handshake_buffer = NULL;
+
+	return 1;
+	}
+
+int ssl3_cert_verify_mac(SSL *s, int md_nid, unsigned char *p)
+	{
+	return(ssl3_handshake_mac(s,md_nid,NULL,0,p));
+	}
+int ssl3_final_finish_mac(SSL *s, 
+	     const char *sender, int len, unsigned char *p)
+	{
+	int ret;
+	ret=ssl3_handshake_mac(s,NID_md5,sender,len,p);
+	p+=ret;
+	ret+=ssl3_handshake_mac(s,NID_sha1,sender,len,p);
+	return(ret);
+	}
+static int ssl3_handshake_mac(SSL *s, int md_nid,
+	     const char *sender, int len, unsigned char *p)
+	{
+	unsigned int ret;
+	int npad,n;
+	unsigned int i;
+	unsigned char md_buf[EVP_MAX_MD_SIZE];
+	EVP_MD_CTX ctx,*d=NULL;
+
+	if (s->s3->handshake_buffer) 
+		if (!ssl3_digest_cached_records(s))
+			return 0;
+
+	/* Search for digest of specified type in the handshake_dgst
+	 * array*/
+	for (i=0;i<SSL_MAX_DIGEST;i++) 
+		{
+		  if (s->s3->handshake_dgst[i]&&EVP_MD_CTX_type(s->s3->handshake_dgst[i])==md_nid) 
+		  	{
+		  	d=s->s3->handshake_dgst[i];
+			break;
+			}
+		}
+	if (!d) {
+		SSLerr(SSL_F_SSL3_HANDSHAKE_MAC,SSL_R_NO_REQUIRED_DIGEST);
+		return 0;
+	}	
+	EVP_MD_CTX_init(&ctx);
+	EVP_MD_CTX_copy_ex(&ctx,d);
+	n=EVP_MD_CTX_size(&ctx);
+	if (n < 0)
+		return 0;
+
+	npad=(48/n)*n;
+	if (sender != NULL)
+		EVP_DigestUpdate(&ctx,sender,len);
+	EVP_DigestUpdate(&ctx,s->session->master_key,
+		s->session->master_key_length);
+	EVP_DigestUpdate(&ctx,ssl3_pad_1,npad);
+	EVP_DigestFinal_ex(&ctx,md_buf,&i);
+
+	EVP_DigestInit_ex(&ctx,EVP_MD_CTX_md(&ctx), NULL);
+	EVP_DigestUpdate(&ctx,s->session->master_key,
+		s->session->master_key_length);
+	EVP_DigestUpdate(&ctx,ssl3_pad_2,npad);
+	EVP_DigestUpdate(&ctx,md_buf,i);
+	EVP_DigestFinal_ex(&ctx,p,&ret);
+
+	EVP_MD_CTX_cleanup(&ctx);
+
+	return((int)ret);
+	}
+
+int n_ssl3_mac(SSL *ssl, unsigned char *md, int send)
+	{
+	SSL3_RECORD *rec;
+	unsigned char *mac_sec,*seq;
+	EVP_MD_CTX md_ctx;
+	const EVP_MD_CTX *hash;
+	unsigned char *p,rec_char;
+	unsigned int md_size;
+	int npad;
+	int t;
+
+	if (send)
+		{
+		rec= &(ssl->s3->wrec);
+		mac_sec= &(ssl->s3->write_mac_secret[0]);
+		seq= &(ssl->s3->write_sequence[0]);
+		hash=ssl->write_hash;
+		}
+	else
+		{
+		rec= &(ssl->s3->rrec);
+		mac_sec= &(ssl->s3->read_mac_secret[0]);
+		seq= &(ssl->s3->read_sequence[0]);
+		hash=ssl->read_hash;
+		}
+
+	t=EVP_MD_CTX_size(hash);
+	if (t < 0)
+		return -1;
+	md_size=t;
+	npad=(48/md_size)*md_size;
+
+	/* Chop the digest off the end :-) */
+	EVP_MD_CTX_init(&md_ctx);
+
+	EVP_MD_CTX_copy_ex( &md_ctx,hash);
+	EVP_DigestUpdate(&md_ctx,mac_sec,md_size);
+	EVP_DigestUpdate(&md_ctx,ssl3_pad_1,npad);
+	EVP_DigestUpdate(&md_ctx,seq,8);
+	rec_char=rec->type;
+	EVP_DigestUpdate(&md_ctx,&rec_char,1);
+	p=md;
+	s2n(rec->length,p);
+	EVP_DigestUpdate(&md_ctx,md,2);
+	EVP_DigestUpdate(&md_ctx,rec->input,rec->length);
+	EVP_DigestFinal_ex( &md_ctx,md,NULL);
+
+	EVP_MD_CTX_copy_ex( &md_ctx,hash);
+	EVP_DigestUpdate(&md_ctx,mac_sec,md_size);
+	EVP_DigestUpdate(&md_ctx,ssl3_pad_2,npad);
+	EVP_DigestUpdate(&md_ctx,md,md_size);
+	EVP_DigestFinal_ex( &md_ctx,md,&md_size);
+
+	EVP_MD_CTX_cleanup(&md_ctx);
+
+	ssl3_record_sequence_update(seq);
+	return(md_size);
+	}
+
+void ssl3_record_sequence_update(unsigned char *seq)
+	{
+	int i;
+
+	for (i=7; i>=0; i--)
+		{
+		++seq[i];
+		if (seq[i] != 0) break; 
+		}
+	}
+
+int ssl3_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
+	     int len)
+	{
+	static const unsigned char *salt[3]={
+#ifndef CHARSET_EBCDIC
+		(const unsigned char *)"A",
+		(const unsigned char *)"BB",
+		(const unsigned char *)"CCC",
+#else
+		(const unsigned char *)"\x41",
+		(const unsigned char *)"\x42\x42",
+		(const unsigned char *)"\x43\x43\x43",
+#endif
+		};
+	unsigned char buf[EVP_MAX_MD_SIZE];
+	EVP_MD_CTX ctx;
+	int i,ret=0;
+	unsigned int n;
+
+	EVP_MD_CTX_init(&ctx);
+	for (i=0; i<3; i++)
+		{
+		EVP_DigestInit_ex(&ctx,s->ctx->sha1, NULL);
+		EVP_DigestUpdate(&ctx,salt[i],strlen((const char *)salt[i]));
+		EVP_DigestUpdate(&ctx,p,len);
+		EVP_DigestUpdate(&ctx,&(s->s3->client_random[0]),
+			SSL3_RANDOM_SIZE);
+		EVP_DigestUpdate(&ctx,&(s->s3->server_random[0]),
+			SSL3_RANDOM_SIZE);
+		EVP_DigestFinal_ex(&ctx,buf,&n);
+
+		EVP_DigestInit_ex(&ctx,s->ctx->md5, NULL);
+		EVP_DigestUpdate(&ctx,p,len);
+		EVP_DigestUpdate(&ctx,buf,n);
+		EVP_DigestFinal_ex(&ctx,out,&n);
+		out+=n;
+		ret+=n;
+		}
+	EVP_MD_CTX_cleanup(&ctx);
+	return(ret);
+	}
+
+int ssl3_alert_code(int code)
+	{
+	switch (code)
+		{
+	case SSL_AD_CLOSE_NOTIFY:	return(SSL3_AD_CLOSE_NOTIFY);
+	case SSL_AD_UNEXPECTED_MESSAGE:	return(SSL3_AD_UNEXPECTED_MESSAGE);
+	case SSL_AD_BAD_RECORD_MAC:	return(SSL3_AD_BAD_RECORD_MAC);
+	case SSL_AD_DECRYPTION_FAILED:	return(SSL3_AD_BAD_RECORD_MAC);
+	case SSL_AD_RECORD_OVERFLOW:	return(SSL3_AD_BAD_RECORD_MAC);
+	case SSL_AD_DECOMPRESSION_FAILURE:return(SSL3_AD_DECOMPRESSION_FAILURE);
+	case SSL_AD_HANDSHAKE_FAILURE:	return(SSL3_AD_HANDSHAKE_FAILURE);
+	case SSL_AD_NO_CERTIFICATE:	return(SSL3_AD_NO_CERTIFICATE);
+	case SSL_AD_BAD_CERTIFICATE:	return(SSL3_AD_BAD_CERTIFICATE);
+	case SSL_AD_UNSUPPORTED_CERTIFICATE:return(SSL3_AD_UNSUPPORTED_CERTIFICATE);
+	case SSL_AD_CERTIFICATE_REVOKED:return(SSL3_AD_CERTIFICATE_REVOKED);
+	case SSL_AD_CERTIFICATE_EXPIRED:return(SSL3_AD_CERTIFICATE_EXPIRED);
+	case SSL_AD_CERTIFICATE_UNKNOWN:return(SSL3_AD_CERTIFICATE_UNKNOWN);
+	case SSL_AD_ILLEGAL_PARAMETER:	return(SSL3_AD_ILLEGAL_PARAMETER);
+	case SSL_AD_UNKNOWN_CA:		return(SSL3_AD_BAD_CERTIFICATE);
+	case SSL_AD_ACCESS_DENIED:	return(SSL3_AD_HANDSHAKE_FAILURE);
+	case SSL_AD_DECODE_ERROR:	return(SSL3_AD_HANDSHAKE_FAILURE);
+	case SSL_AD_DECRYPT_ERROR:	return(SSL3_AD_HANDSHAKE_FAILURE);
+	case SSL_AD_EXPORT_RESTRICTION:	return(SSL3_AD_HANDSHAKE_FAILURE);
+	case SSL_AD_PROTOCOL_VERSION:	return(SSL3_AD_HANDSHAKE_FAILURE);
+	case SSL_AD_INSUFFICIENT_SECURITY:return(SSL3_AD_HANDSHAKE_FAILURE);
+	case SSL_AD_INTERNAL_ERROR:	return(SSL3_AD_HANDSHAKE_FAILURE);
+	case SSL_AD_USER_CANCELLED:	return(SSL3_AD_HANDSHAKE_FAILURE);
+	case SSL_AD_NO_RENEGOTIATION:	return(-1); /* Don't send it :-) */
+	case SSL_AD_UNSUPPORTED_EXTENSION: return(SSL3_AD_HANDSHAKE_FAILURE);
+	case SSL_AD_CERTIFICATE_UNOBTAINABLE: return(SSL3_AD_HANDSHAKE_FAILURE);
+	case SSL_AD_UNRECOGNIZED_NAME:	return(SSL3_AD_HANDSHAKE_FAILURE);
+	case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE: return(SSL3_AD_HANDSHAKE_FAILURE);
+	case SSL_AD_BAD_CERTIFICATE_HASH_VALUE: return(SSL3_AD_HANDSHAKE_FAILURE);
+	case SSL_AD_UNKNOWN_PSK_IDENTITY:return(TLS1_AD_UNKNOWN_PSK_IDENTITY);
+	default:			return(-1);
+		}
+	}
+
diff --git a/lib/openssl/ssl/s3_lib.c b/lib/openssl/ssl/s3_lib.c
new file mode 100644
index 0000000..e3edba8
--- /dev/null
+++ b/lib/openssl/ssl/s3_lib.c
@@ -0,0 +1,3342 @@
+/* ssl/s3_lib.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * Portions of the attached software ("Contribution") are developed by 
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the OpenSSL open source
+ * license provided above.
+ *
+ * ECC cipher suite support in OpenSSL originally written by
+ * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
+ *
+ */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#include <stdio.h>
+#include <openssl/objects.h>
+#include "ssl_locl.h"
+#include "kssl_lcl.h"
+#ifndef OPENSSL_NO_TLSEXT
+#ifndef OPENSSL_NO_EC
+#include "../crypto/ec/ec_lcl.h"
+#endif /* OPENSSL_NO_EC */
+#endif /* OPENSSL_NO_TLSEXT */
+#include <openssl/md5.h>
+#ifndef OPENSSL_NO_DH
+#include <openssl/dh.h>
+#endif
+
+const char ssl3_version_str[]="SSLv3" OPENSSL_VERSION_PTEXT;
+
+#define SSL3_NUM_CIPHERS	(sizeof(ssl3_ciphers)/sizeof(SSL_CIPHER))
+
+/* list of available SSLv3 ciphers (sorted by id) */
+OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
+
+/* The RSA ciphers */
+/* Cipher 01 */
+	{
+	1,
+	SSL3_TXT_RSA_NULL_MD5,
+	SSL3_CK_RSA_NULL_MD5,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_eNULL,
+	SSL_MD5,
+	SSL_SSLV3,
+	SSL_NOT_EXP|SSL_STRONG_NONE,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	0,
+	0,
+	},
+
+/* Cipher 02 */
+	{
+	1,
+	SSL3_TXT_RSA_NULL_SHA,
+	SSL3_CK_RSA_NULL_SHA,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_eNULL,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_NOT_EXP|SSL_STRONG_NONE|SSL_FIPS,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	0,
+	0,
+	},
+
+/* Cipher 03 */
+	{
+	1,
+	SSL3_TXT_RSA_RC4_40_MD5,
+	SSL3_CK_RSA_RC4_40_MD5,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_RC4,
+	SSL_MD5,
+	SSL_SSLV3,
+	SSL_EXPORT|SSL_EXP40,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	40,
+	128,
+	},
+
+/* Cipher 04 */
+	{
+	1,
+	SSL3_TXT_RSA_RC4_128_MD5,
+	SSL3_CK_RSA_RC4_128_MD5,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_RC4,
+	SSL_MD5,
+	SSL_SSLV3,
+	SSL_NOT_EXP|SSL_MEDIUM,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+/* Cipher 05 */
+	{
+	1,
+	SSL3_TXT_RSA_RC4_128_SHA,
+	SSL3_CK_RSA_RC4_128_SHA,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_RC4,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_NOT_EXP|SSL_MEDIUM,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+/* Cipher 06 */
+	{
+	1,
+	SSL3_TXT_RSA_RC2_40_MD5,
+	SSL3_CK_RSA_RC2_40_MD5,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_RC2,
+	SSL_MD5,
+	SSL_SSLV3,
+	SSL_EXPORT|SSL_EXP40,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	40,
+	128,
+	},
+
+/* Cipher 07 */
+#ifndef OPENSSL_NO_IDEA
+	{
+	1,
+	SSL3_TXT_RSA_IDEA_128_SHA,
+	SSL3_CK_RSA_IDEA_128_SHA,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_IDEA,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_NOT_EXP|SSL_MEDIUM,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+#endif
+
+/* Cipher 08 */
+	{
+	1,
+	SSL3_TXT_RSA_DES_40_CBC_SHA,
+	SSL3_CK_RSA_DES_40_CBC_SHA,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_DES,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_EXPORT|SSL_EXP40,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	40,
+	56,
+	},
+
+/* Cipher 09 */
+	{
+	1,
+	SSL3_TXT_RSA_DES_64_CBC_SHA,
+	SSL3_CK_RSA_DES_64_CBC_SHA,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_DES,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_NOT_EXP|SSL_LOW,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	56,
+	56,
+	},
+
+/* Cipher 0A */
+	{
+	1,
+	SSL3_TXT_RSA_DES_192_CBC3_SHA,
+	SSL3_CK_RSA_DES_192_CBC3_SHA,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_3DES,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	168,
+	168,
+	},
+
+/* The DH ciphers */
+/* Cipher 0B */
+	{
+	0,
+	SSL3_TXT_DH_DSS_DES_40_CBC_SHA,
+	SSL3_CK_DH_DSS_DES_40_CBC_SHA,
+	SSL_kDHd,
+	SSL_aDH,
+	SSL_DES,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_EXPORT|SSL_EXP40,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	40,
+	56,
+	},
+
+/* Cipher 0C */
+	{
+	0, /* not implemented (non-ephemeral DH) */
+	SSL3_TXT_DH_DSS_DES_64_CBC_SHA,
+	SSL3_CK_DH_DSS_DES_64_CBC_SHA,
+	SSL_kDHd,
+	SSL_aDH,
+	SSL_DES,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_NOT_EXP|SSL_LOW,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	56,
+	56,
+	},
+
+/* Cipher 0D */
+	{
+	0, /* not implemented (non-ephemeral DH) */
+	SSL3_TXT_DH_DSS_DES_192_CBC3_SHA,
+	SSL3_CK_DH_DSS_DES_192_CBC3_SHA,
+	SSL_kDHd,
+	SSL_aDH,
+	SSL_3DES,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	168,
+	168,
+	},
+
+/* Cipher 0E */
+	{
+	0, /* not implemented (non-ephemeral DH) */
+	SSL3_TXT_DH_RSA_DES_40_CBC_SHA,
+	SSL3_CK_DH_RSA_DES_40_CBC_SHA,
+	SSL_kDHr,
+	SSL_aDH,
+	SSL_DES,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_EXPORT|SSL_EXP40,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	40,
+	56,
+	},
+
+/* Cipher 0F */
+	{
+	0, /* not implemented (non-ephemeral DH) */
+	SSL3_TXT_DH_RSA_DES_64_CBC_SHA,
+	SSL3_CK_DH_RSA_DES_64_CBC_SHA,
+	SSL_kDHr,
+	SSL_aDH,
+	SSL_DES,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_NOT_EXP|SSL_LOW,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	56,
+	56,
+	},
+
+/* Cipher 10 */
+	{
+	0, /* not implemented (non-ephemeral DH) */
+	SSL3_TXT_DH_RSA_DES_192_CBC3_SHA,
+	SSL3_CK_DH_RSA_DES_192_CBC3_SHA,
+	SSL_kDHr,
+	SSL_aDH,
+	SSL_3DES,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	168,
+	168,
+	},
+
+/* The Ephemeral DH ciphers */
+/* Cipher 11 */
+	{
+	1,
+	SSL3_TXT_EDH_DSS_DES_40_CBC_SHA,
+	SSL3_CK_EDH_DSS_DES_40_CBC_SHA,
+	SSL_kEDH,
+	SSL_aDSS,
+	SSL_DES,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_EXPORT|SSL_EXP40,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	40,
+	56,
+	},
+
+/* Cipher 12 */
+	{
+	1,
+	SSL3_TXT_EDH_DSS_DES_64_CBC_SHA,
+	SSL3_CK_EDH_DSS_DES_64_CBC_SHA,
+	SSL_kEDH,
+	SSL_aDSS,
+	SSL_DES,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_NOT_EXP|SSL_LOW,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	56,
+	56,
+	},
+
+/* Cipher 13 */
+	{
+	1,
+	SSL3_TXT_EDH_DSS_DES_192_CBC3_SHA,
+	SSL3_CK_EDH_DSS_DES_192_CBC3_SHA,
+	SSL_kEDH,
+	SSL_aDSS,
+	SSL_3DES,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	168,
+	168,
+	},
+
+/* Cipher 14 */
+	{
+	1,
+	SSL3_TXT_EDH_RSA_DES_40_CBC_SHA,
+	SSL3_CK_EDH_RSA_DES_40_CBC_SHA,
+	SSL_kEDH,
+	SSL_aRSA,
+	SSL_DES,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_EXPORT|SSL_EXP40,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	40,
+	56,
+	},
+
+/* Cipher 15 */
+	{
+	1,
+	SSL3_TXT_EDH_RSA_DES_64_CBC_SHA,
+	SSL3_CK_EDH_RSA_DES_64_CBC_SHA,
+	SSL_kEDH,
+	SSL_aRSA,
+	SSL_DES,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_NOT_EXP|SSL_LOW,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	56,
+	56,
+	},
+
+/* Cipher 16 */
+	{
+	1,
+	SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA,
+	SSL3_CK_EDH_RSA_DES_192_CBC3_SHA,
+	SSL_kEDH,
+	SSL_aRSA,
+	SSL_3DES,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	168,
+	168,
+	},
+
+/* Cipher 17 */
+	{
+	1,
+	SSL3_TXT_ADH_RC4_40_MD5,
+	SSL3_CK_ADH_RC4_40_MD5,
+	SSL_kEDH,
+	SSL_aNULL,
+	SSL_RC4,
+	SSL_MD5,
+	SSL_SSLV3,
+	SSL_EXPORT|SSL_EXP40,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	40,
+	128,
+	},
+
+/* Cipher 18 */
+	{
+	1,
+	SSL3_TXT_ADH_RC4_128_MD5,
+	SSL3_CK_ADH_RC4_128_MD5,
+	SSL_kEDH,
+	SSL_aNULL,
+	SSL_RC4,
+	SSL_MD5,
+	SSL_SSLV3,
+	SSL_NOT_EXP|SSL_MEDIUM,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+/* Cipher 19 */
+	{
+	1,
+	SSL3_TXT_ADH_DES_40_CBC_SHA,
+	SSL3_CK_ADH_DES_40_CBC_SHA,
+	SSL_kEDH,
+	SSL_aNULL,
+	SSL_DES,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_EXPORT|SSL_EXP40,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	40,
+	128,
+	},
+
+/* Cipher 1A */
+	{
+	1,
+	SSL3_TXT_ADH_DES_64_CBC_SHA,
+	SSL3_CK_ADH_DES_64_CBC_SHA,
+	SSL_kEDH,
+	SSL_aNULL,
+	SSL_DES,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_NOT_EXP|SSL_LOW,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	56,
+	56,
+	},
+
+/* Cipher 1B */
+	{
+	1,
+	SSL3_TXT_ADH_DES_192_CBC_SHA,
+	SSL3_CK_ADH_DES_192_CBC_SHA,
+	SSL_kEDH,
+	SSL_aNULL,
+	SSL_3DES,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	168,
+	168,
+	},
+
+/* Fortezza ciphersuite from SSL 3.0 spec */
+#if 0
+/* Cipher 1C */
+	{
+	0,
+	SSL3_TXT_FZA_DMS_NULL_SHA,
+	SSL3_CK_FZA_DMS_NULL_SHA,
+	SSL_kFZA,
+	SSL_aFZA,
+	SSL_eNULL,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_NOT_EXP|SSL_STRONG_NONE,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	0,
+	0,
+	},
+
+/* Cipher 1D */
+	{
+	0,
+	SSL3_TXT_FZA_DMS_FZA_SHA,
+	SSL3_CK_FZA_DMS_FZA_SHA,
+	SSL_kFZA,
+	SSL_aFZA,
+	SSL_eFZA,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_NOT_EXP|SSL_STRONG_NONE,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	0,
+	0,
+	},
+
+/* Cipher 1E */
+	{
+	0,
+	SSL3_TXT_FZA_DMS_RC4_SHA,
+	SSL3_CK_FZA_DMS_RC4_SHA,
+	SSL_kFZA,
+	SSL_aFZA,
+	SSL_RC4,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_NOT_EXP|SSL_MEDIUM,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+#endif
+
+#ifndef OPENSSL_NO_KRB5
+/* The Kerberos ciphers*/
+/* Cipher 1E */
+	{
+	1,
+	SSL3_TXT_KRB5_DES_64_CBC_SHA,
+	SSL3_CK_KRB5_DES_64_CBC_SHA,
+	SSL_kKRB5,
+	SSL_aKRB5,
+	SSL_DES,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_NOT_EXP|SSL_LOW,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	56,
+	56,
+	},
+
+/* Cipher 1F */
+	{
+	1,
+	SSL3_TXT_KRB5_DES_192_CBC3_SHA,
+	SSL3_CK_KRB5_DES_192_CBC3_SHA,
+	SSL_kKRB5,
+	SSL_aKRB5,
+	SSL_3DES,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	168,
+	168,
+	},
+
+/* Cipher 20 */
+	{
+	1,
+	SSL3_TXT_KRB5_RC4_128_SHA,
+	SSL3_CK_KRB5_RC4_128_SHA,
+	SSL_kKRB5,
+	SSL_aKRB5,
+	SSL_RC4,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_NOT_EXP|SSL_MEDIUM,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+/* Cipher 21 */
+	{
+	1,
+	SSL3_TXT_KRB5_IDEA_128_CBC_SHA,
+	SSL3_CK_KRB5_IDEA_128_CBC_SHA,
+	SSL_kKRB5,
+	SSL_aKRB5,
+	SSL_IDEA,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_NOT_EXP|SSL_MEDIUM,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+/* Cipher 22 */
+	{
+	1,
+	SSL3_TXT_KRB5_DES_64_CBC_MD5,
+	SSL3_CK_KRB5_DES_64_CBC_MD5,
+	SSL_kKRB5,
+	SSL_aKRB5,
+	SSL_DES,
+	SSL_MD5,
+	SSL_SSLV3,
+	SSL_NOT_EXP|SSL_LOW,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	56,
+	56,
+	},
+
+/* Cipher 23 */
+	{
+	1,
+	SSL3_TXT_KRB5_DES_192_CBC3_MD5,
+	SSL3_CK_KRB5_DES_192_CBC3_MD5,
+	SSL_kKRB5,
+	SSL_aKRB5,
+	SSL_3DES,
+	SSL_MD5,
+	SSL_SSLV3,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	168,
+	168,
+	},
+
+/* Cipher 24 */
+	{
+	1,
+	SSL3_TXT_KRB5_RC4_128_MD5,
+	SSL3_CK_KRB5_RC4_128_MD5,
+	SSL_kKRB5,
+	SSL_aKRB5,
+	SSL_RC4,
+	SSL_MD5,
+	SSL_SSLV3,
+	SSL_NOT_EXP|SSL_MEDIUM,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+/* Cipher 25 */
+	{
+	1,
+	SSL3_TXT_KRB5_IDEA_128_CBC_MD5,
+	SSL3_CK_KRB5_IDEA_128_CBC_MD5,
+	SSL_kKRB5,
+	SSL_aKRB5,
+	SSL_IDEA,
+	SSL_MD5,
+	SSL_SSLV3,
+	SSL_NOT_EXP|SSL_MEDIUM,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+/* Cipher 26 */
+	{
+	1,
+	SSL3_TXT_KRB5_DES_40_CBC_SHA,
+	SSL3_CK_KRB5_DES_40_CBC_SHA,
+	SSL_kKRB5,
+	SSL_aKRB5,
+	SSL_DES,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_EXPORT|SSL_EXP40,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	40,
+	56,
+	},
+
+/* Cipher 27 */
+	{
+	1,
+	SSL3_TXT_KRB5_RC2_40_CBC_SHA,
+	SSL3_CK_KRB5_RC2_40_CBC_SHA,
+	SSL_kKRB5,
+	SSL_aKRB5,
+	SSL_RC2,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_EXPORT|SSL_EXP40,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	40,
+	128,
+	},
+
+/* Cipher 28 */
+	{
+	1,
+	SSL3_TXT_KRB5_RC4_40_SHA,
+	SSL3_CK_KRB5_RC4_40_SHA,
+	SSL_kKRB5,
+	SSL_aKRB5,
+	SSL_RC4,
+	SSL_SHA1,
+	SSL_SSLV3,
+	SSL_EXPORT|SSL_EXP40,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	40,
+	128,
+	},
+
+/* Cipher 29 */
+	{
+	1,
+	SSL3_TXT_KRB5_DES_40_CBC_MD5,
+	SSL3_CK_KRB5_DES_40_CBC_MD5,
+	SSL_kKRB5,
+	SSL_aKRB5,
+	SSL_DES,
+	SSL_MD5,
+	SSL_SSLV3,
+	SSL_EXPORT|SSL_EXP40,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	40,
+	56,
+	},
+
+/* Cipher 2A */
+	{
+	1,
+	SSL3_TXT_KRB5_RC2_40_CBC_MD5,
+	SSL3_CK_KRB5_RC2_40_CBC_MD5,
+	SSL_kKRB5,
+	SSL_aKRB5,
+	SSL_RC2,
+	SSL_MD5,
+	SSL_SSLV3,
+	SSL_EXPORT|SSL_EXP40,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	40,
+	128,
+	},
+
+/* Cipher 2B */
+	{
+	1,
+	SSL3_TXT_KRB5_RC4_40_MD5,
+	SSL3_CK_KRB5_RC4_40_MD5,
+	SSL_kKRB5,
+	SSL_aKRB5,
+	SSL_RC4,
+	SSL_MD5,
+	SSL_SSLV3,
+	SSL_EXPORT|SSL_EXP40,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	40,
+	128,
+	},
+#endif	/* OPENSSL_NO_KRB5 */
+
+/* New AES ciphersuites */
+/* Cipher 2F */
+	{
+	1,
+	TLS1_TXT_RSA_WITH_AES_128_SHA,
+	TLS1_CK_RSA_WITH_AES_128_SHA,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_AES128,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+/* Cipher 30 */
+	{
+	0,
+	TLS1_TXT_DH_DSS_WITH_AES_128_SHA,
+	TLS1_CK_DH_DSS_WITH_AES_128_SHA,
+	SSL_kDHd,
+	SSL_aDH,
+	SSL_AES128,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+/* Cipher 31 */
+	{
+	0,
+	TLS1_TXT_DH_RSA_WITH_AES_128_SHA,
+	TLS1_CK_DH_RSA_WITH_AES_128_SHA,
+	SSL_kDHr,
+	SSL_aDH,
+	SSL_AES128,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+/* Cipher 32 */
+	{
+	1,
+	TLS1_TXT_DHE_DSS_WITH_AES_128_SHA,
+	TLS1_CK_DHE_DSS_WITH_AES_128_SHA,
+	SSL_kEDH,
+	SSL_aDSS,
+	SSL_AES128,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+/* Cipher 33 */
+	{
+	1,
+	TLS1_TXT_DHE_RSA_WITH_AES_128_SHA,
+	TLS1_CK_DHE_RSA_WITH_AES_128_SHA,
+	SSL_kEDH,
+	SSL_aRSA,
+	SSL_AES128,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+/* Cipher 34 */
+	{
+	1,
+	TLS1_TXT_ADH_WITH_AES_128_SHA,
+	TLS1_CK_ADH_WITH_AES_128_SHA,
+	SSL_kEDH,
+	SSL_aNULL,
+	SSL_AES128,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+/* Cipher 35 */
+	{
+	1,
+	TLS1_TXT_RSA_WITH_AES_256_SHA,
+	TLS1_CK_RSA_WITH_AES_256_SHA,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_AES256,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	256,
+	256,
+	},
+/* Cipher 36 */
+	{
+	0,
+	TLS1_TXT_DH_DSS_WITH_AES_256_SHA,
+	TLS1_CK_DH_DSS_WITH_AES_256_SHA,
+	SSL_kDHd,
+	SSL_aDH,
+	SSL_AES256,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	256,
+	256,
+	},
+
+/* Cipher 37 */
+	{
+	0, /* not implemented (non-ephemeral DH) */
+	TLS1_TXT_DH_RSA_WITH_AES_256_SHA,
+	TLS1_CK_DH_RSA_WITH_AES_256_SHA,
+	SSL_kDHr,
+	SSL_aDH,
+	SSL_AES256,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	256,
+	256,
+	},
+
+/* Cipher 38 */
+	{
+	1,
+	TLS1_TXT_DHE_DSS_WITH_AES_256_SHA,
+	TLS1_CK_DHE_DSS_WITH_AES_256_SHA,
+	SSL_kEDH,
+	SSL_aDSS,
+	SSL_AES256,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	256,
+	256,
+	},
+
+/* Cipher 39 */
+	{
+	1,
+	TLS1_TXT_DHE_RSA_WITH_AES_256_SHA,
+	TLS1_CK_DHE_RSA_WITH_AES_256_SHA,
+	SSL_kEDH,
+	SSL_aRSA,
+	SSL_AES256,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	256,
+	256,
+	},
+
+	/* Cipher 3A */
+	{
+	1,
+	TLS1_TXT_ADH_WITH_AES_256_SHA,
+	TLS1_CK_ADH_WITH_AES_256_SHA,
+	SSL_kEDH,
+	SSL_aNULL,
+	SSL_AES256,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	256,
+	256,
+	},
+
+#ifndef OPENSSL_NO_CAMELLIA
+	/* Camellia ciphersuites from RFC4132 (128-bit portion) */
+
+	/* Cipher 41 */
+	{
+	1,
+	TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA,
+	TLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_CAMELLIA128,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+	/* Cipher 42 */
+	{
+	0, /* not implemented (non-ephemeral DH) */
+	TLS1_TXT_DH_DSS_WITH_CAMELLIA_128_CBC_SHA,
+	TLS1_CK_DH_DSS_WITH_CAMELLIA_128_CBC_SHA,
+	SSL_kDHd,
+	SSL_aDH,
+	SSL_CAMELLIA128,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+	/* Cipher 43 */
+	{
+	0, /* not implemented (non-ephemeral DH) */
+	TLS1_TXT_DH_RSA_WITH_CAMELLIA_128_CBC_SHA,
+	TLS1_CK_DH_RSA_WITH_CAMELLIA_128_CBC_SHA,
+	SSL_kDHr,
+	SSL_aDH,
+	SSL_CAMELLIA128,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+	/* Cipher 44 */
+	{
+	1,
+	TLS1_TXT_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA,
+	TLS1_CK_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA,
+	SSL_kEDH,
+	SSL_aDSS,
+	SSL_CAMELLIA128,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+	/* Cipher 45 */
+	{
+	1,
+	TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
+	TLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
+	SSL_kEDH,
+	SSL_aRSA,
+	SSL_CAMELLIA128,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+	/* Cipher 46 */
+	{
+	1,
+	TLS1_TXT_ADH_WITH_CAMELLIA_128_CBC_SHA,
+	TLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA,
+	SSL_kEDH,
+	SSL_aNULL,
+	SSL_CAMELLIA128,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+#endif /* OPENSSL_NO_CAMELLIA */
+
+#if TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES
+	/* New TLS Export CipherSuites from expired ID */
+#if 0
+	/* Cipher 60 */
+	{
+	1,
+	TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_MD5,
+	TLS1_CK_RSA_EXPORT1024_WITH_RC4_56_MD5,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_RC4,
+	SSL_MD5,
+	SSL_TLSV1,
+	SSL_EXPORT|SSL_EXP56,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	56,
+	128,
+	},
+
+	/* Cipher 61 */
+	{
+	1,
+	TLS1_TXT_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5,
+	TLS1_CK_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_RC2,
+	SSL_MD5,
+	SSL_TLSV1,
+	SSL_EXPORT|SSL_EXP56,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	56,
+	128,
+	},
+#endif
+
+	/* Cipher 62 */
+	{
+	1,
+	TLS1_TXT_RSA_EXPORT1024_WITH_DES_CBC_SHA,
+	TLS1_CK_RSA_EXPORT1024_WITH_DES_CBC_SHA,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_DES,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_EXPORT|SSL_EXP56,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	56,
+	56,
+	},
+
+	/* Cipher 63 */
+	{
+	1,
+	TLS1_TXT_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA,
+	TLS1_CK_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA,
+	SSL_kEDH,
+	SSL_aDSS,
+	SSL_DES,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_EXPORT|SSL_EXP56,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	56,
+	56,
+	},
+
+	/* Cipher 64 */
+	{
+	1,
+	TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_SHA,
+	TLS1_CK_RSA_EXPORT1024_WITH_RC4_56_SHA,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_RC4,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_EXPORT|SSL_EXP56,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	56,
+	128,
+	},
+
+	/* Cipher 65 */
+	{
+	1,
+	TLS1_TXT_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA,
+	TLS1_CK_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA,
+	SSL_kEDH,
+	SSL_aDSS,
+	SSL_RC4,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_EXPORT|SSL_EXP56,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	56,
+	128,
+	},
+
+	/* Cipher 66 */
+	{
+	1,
+	TLS1_TXT_DHE_DSS_WITH_RC4_128_SHA,
+	TLS1_CK_DHE_DSS_WITH_RC4_128_SHA,
+	SSL_kEDH,
+	SSL_aDSS,
+	SSL_RC4,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_MEDIUM,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+#endif
+	{
+	1,
+	"GOST94-GOST89-GOST89",
+	0x3000080,
+	SSL_kGOST,
+	SSL_aGOST94,
+	SSL_eGOST2814789CNT,
+	SSL_GOST89MAC,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_GOST94|TLS1_PRF_GOST94|TLS1_STREAM_MAC,
+	256,
+	256
+	},
+	{
+	1,
+	"GOST2001-GOST89-GOST89",
+	0x3000081,
+	SSL_kGOST,
+	SSL_aGOST01,
+	SSL_eGOST2814789CNT,
+	SSL_GOST89MAC,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_GOST94|TLS1_PRF_GOST94|TLS1_STREAM_MAC,
+	256,
+	256
+	},
+	{
+	1,
+	"GOST94-NULL-GOST94",
+	0x3000082,
+	SSL_kGOST,
+	SSL_aGOST94,
+	SSL_eNULL,
+	SSL_GOST94,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_STRONG_NONE,
+	SSL_HANDSHAKE_MAC_GOST94|TLS1_PRF_GOST94,
+	0,
+	0
+	},
+	{
+	1,
+	"GOST2001-NULL-GOST94",
+	0x3000083,
+	SSL_kGOST,
+	SSL_aGOST01,
+	SSL_eNULL,
+	SSL_GOST94,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_STRONG_NONE,
+	SSL_HANDSHAKE_MAC_GOST94|TLS1_PRF_GOST94,
+	0,
+	0
+	},
+
+#ifndef OPENSSL_NO_CAMELLIA
+	/* Camellia ciphersuites from RFC4132 (256-bit portion) */
+
+	/* Cipher 84 */
+	{
+	1,
+	TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA,
+	TLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_CAMELLIA256,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	256,
+	256,
+	},
+	/* Cipher 85 */
+	{
+	0, /* not implemented (non-ephemeral DH) */
+	TLS1_TXT_DH_DSS_WITH_CAMELLIA_256_CBC_SHA,
+	TLS1_CK_DH_DSS_WITH_CAMELLIA_256_CBC_SHA,
+	SSL_kDHd,
+	SSL_aDH,
+	SSL_CAMELLIA256,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	256,
+	256,
+	},
+
+	/* Cipher 86 */
+	{
+	0, /* not implemented (non-ephemeral DH) */
+	TLS1_TXT_DH_RSA_WITH_CAMELLIA_256_CBC_SHA,
+	TLS1_CK_DH_RSA_WITH_CAMELLIA_256_CBC_SHA,
+	SSL_kDHr,
+	SSL_aDH,
+	SSL_CAMELLIA256,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	256,
+	256,
+	},
+
+	/* Cipher 87 */
+	{
+	1,
+	TLS1_TXT_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA,
+	TLS1_CK_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA,
+	SSL_kEDH,
+	SSL_aDSS,
+	SSL_CAMELLIA256,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	256,
+	256,
+	},
+
+	/* Cipher 88 */
+	{
+	1,
+	TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
+	TLS1_CK_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
+	SSL_kEDH,
+	SSL_aRSA,
+	SSL_CAMELLIA256,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	256,
+	256,
+	},
+
+	/* Cipher 89 */
+	{
+	1,
+	TLS1_TXT_ADH_WITH_CAMELLIA_256_CBC_SHA,
+	TLS1_CK_ADH_WITH_CAMELLIA_256_CBC_SHA,
+	SSL_kEDH,
+	SSL_aNULL,
+	SSL_CAMELLIA256,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	256,
+	256,
+	},
+#endif /* OPENSSL_NO_CAMELLIA */
+
+#ifndef OPENSSL_NO_PSK
+	/* Cipher 8A */
+	{
+	1,
+	TLS1_TXT_PSK_WITH_RC4_128_SHA,
+	TLS1_CK_PSK_WITH_RC4_128_SHA,
+	SSL_kPSK,
+	SSL_aPSK,
+	SSL_RC4,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_MEDIUM,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+	/* Cipher 8B */
+	{
+	1,
+	TLS1_TXT_PSK_WITH_3DES_EDE_CBC_SHA,
+	TLS1_CK_PSK_WITH_3DES_EDE_CBC_SHA,
+	SSL_kPSK,
+	SSL_aPSK,
+	SSL_3DES,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	168,
+	168,
+	},
+
+	/* Cipher 8C */
+	{
+	1,
+	TLS1_TXT_PSK_WITH_AES_128_CBC_SHA,
+	TLS1_CK_PSK_WITH_AES_128_CBC_SHA,
+	SSL_kPSK,
+	SSL_aPSK,
+	SSL_AES128,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+	/* Cipher 8D */
+	{
+	1,
+	TLS1_TXT_PSK_WITH_AES_256_CBC_SHA,
+	TLS1_CK_PSK_WITH_AES_256_CBC_SHA,
+	SSL_kPSK,
+	SSL_aPSK,
+	SSL_AES256,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	256,
+	256,
+	},
+#endif  /* OPENSSL_NO_PSK */
+
+#ifndef OPENSSL_NO_SEED
+	/* SEED ciphersuites from RFC4162 */
+
+	/* Cipher 96 */
+	{
+	1,
+	TLS1_TXT_RSA_WITH_SEED_SHA,
+	TLS1_CK_RSA_WITH_SEED_SHA,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_SEED,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_MEDIUM,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+	/* Cipher 97 */
+	{
+	0, /* not implemented (non-ephemeral DH) */
+	TLS1_TXT_DH_DSS_WITH_SEED_SHA,
+	TLS1_CK_DH_DSS_WITH_SEED_SHA,
+	SSL_kDHd,
+	SSL_aDH,
+	SSL_SEED,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_MEDIUM,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+	/* Cipher 98 */
+	{
+	0, /* not implemented (non-ephemeral DH) */
+	TLS1_TXT_DH_RSA_WITH_SEED_SHA,
+	TLS1_CK_DH_RSA_WITH_SEED_SHA,
+	SSL_kDHr,
+	SSL_aDH,
+	SSL_SEED,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_MEDIUM,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+	/* Cipher 99 */
+	{
+	1,
+	TLS1_TXT_DHE_DSS_WITH_SEED_SHA,
+	TLS1_CK_DHE_DSS_WITH_SEED_SHA,
+	SSL_kEDH,
+	SSL_aDSS,
+	SSL_SEED,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_MEDIUM,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+	/* Cipher 9A */
+	{
+	1,
+	TLS1_TXT_DHE_RSA_WITH_SEED_SHA,
+	TLS1_CK_DHE_RSA_WITH_SEED_SHA,
+	SSL_kEDH,
+	SSL_aRSA,
+	SSL_SEED,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_MEDIUM,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+	/* Cipher 9B */
+	{
+	1,
+	TLS1_TXT_ADH_WITH_SEED_SHA,
+	TLS1_CK_ADH_WITH_SEED_SHA,
+	SSL_kEDH,
+	SSL_aNULL,
+	SSL_SEED,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_MEDIUM,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+#endif /* OPENSSL_NO_SEED */
+
+#ifndef OPENSSL_NO_ECDH
+	/* Cipher C001 */
+	{
+	1,
+	TLS1_TXT_ECDH_ECDSA_WITH_NULL_SHA,
+	TLS1_CK_ECDH_ECDSA_WITH_NULL_SHA,
+	SSL_kECDHe,
+	SSL_aECDH,
+	SSL_eNULL,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_STRONG_NONE,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	0,
+	0,
+	},
+
+	/* Cipher C002 */
+	{
+	1,
+	TLS1_TXT_ECDH_ECDSA_WITH_RC4_128_SHA,
+	TLS1_CK_ECDH_ECDSA_WITH_RC4_128_SHA,
+	SSL_kECDHe,
+	SSL_aECDH,
+	SSL_RC4,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_MEDIUM,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+	/* Cipher C003 */
+	{
+	1,
+	TLS1_TXT_ECDH_ECDSA_WITH_DES_192_CBC3_SHA,
+	TLS1_CK_ECDH_ECDSA_WITH_DES_192_CBC3_SHA,
+	SSL_kECDHe,
+	SSL_aECDH,
+	SSL_3DES,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	168,
+	168,
+	},
+
+	/* Cipher C004 */
+	{
+	1,
+	TLS1_TXT_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
+	TLS1_CK_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
+	SSL_kECDHe,
+	SSL_aECDH,
+	SSL_AES128,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+	/* Cipher C005 */
+	{
+	1,
+	TLS1_TXT_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
+	TLS1_CK_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
+	SSL_kECDHe,
+	SSL_aECDH,
+	SSL_AES256,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	256,
+	256,
+	},
+
+	/* Cipher C006 */
+	{
+	1,
+	TLS1_TXT_ECDHE_ECDSA_WITH_NULL_SHA,
+	TLS1_CK_ECDHE_ECDSA_WITH_NULL_SHA,
+	SSL_kEECDH,
+	SSL_aECDSA,
+	SSL_eNULL,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_STRONG_NONE,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	0,
+	0,
+	},
+
+	/* Cipher C007 */
+	{
+	1,
+	TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA,
+	TLS1_CK_ECDHE_ECDSA_WITH_RC4_128_SHA,
+	SSL_kEECDH,
+	SSL_aECDSA,
+	SSL_RC4,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_MEDIUM,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+	/* Cipher C008 */
+	{
+	1,
+	TLS1_TXT_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA,
+	TLS1_CK_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA,
+	SSL_kEECDH,
+	SSL_aECDSA,
+	SSL_3DES,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	168,
+	168,
+	},
+
+	/* Cipher C009 */
+	{
+	1,
+	TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+	TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+	SSL_kEECDH,
+	SSL_aECDSA,
+	SSL_AES128,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+	/* Cipher C00A */
+	{
+	1,
+	TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+	TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+	SSL_kEECDH,
+	SSL_aECDSA,
+	SSL_AES256,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	256,
+	256,
+	},
+
+	/* Cipher C00B */
+	{
+	1,
+	TLS1_TXT_ECDH_RSA_WITH_NULL_SHA,
+	TLS1_CK_ECDH_RSA_WITH_NULL_SHA,
+	SSL_kECDHr,
+	SSL_aECDH,
+	SSL_eNULL,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_STRONG_NONE,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	0,
+	0,
+	},
+
+	/* Cipher C00C */
+	{
+	1,
+	TLS1_TXT_ECDH_RSA_WITH_RC4_128_SHA,
+	TLS1_CK_ECDH_RSA_WITH_RC4_128_SHA,
+	SSL_kECDHr,
+	SSL_aECDH,
+	SSL_RC4,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_MEDIUM,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+	/* Cipher C00D */
+	{
+	1,
+	TLS1_TXT_ECDH_RSA_WITH_DES_192_CBC3_SHA,
+	TLS1_CK_ECDH_RSA_WITH_DES_192_CBC3_SHA,
+	SSL_kECDHr,
+	SSL_aECDH,
+	SSL_3DES,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	168,
+	168,
+	},
+
+	/* Cipher C00E */
+	{
+	1,
+	TLS1_TXT_ECDH_RSA_WITH_AES_128_CBC_SHA,
+	TLS1_CK_ECDH_RSA_WITH_AES_128_CBC_SHA,
+	SSL_kECDHr,
+	SSL_aECDH,
+	SSL_AES128,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+	/* Cipher C00F */
+	{
+	1,
+	TLS1_TXT_ECDH_RSA_WITH_AES_256_CBC_SHA,
+	TLS1_CK_ECDH_RSA_WITH_AES_256_CBC_SHA,
+	SSL_kECDHr,
+	SSL_aECDH,
+	SSL_AES256,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	256,
+	256,
+	},
+
+	/* Cipher C010 */
+	{
+	1,
+	TLS1_TXT_ECDHE_RSA_WITH_NULL_SHA,
+	TLS1_CK_ECDHE_RSA_WITH_NULL_SHA,
+	SSL_kEECDH,
+	SSL_aRSA,
+	SSL_eNULL,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_STRONG_NONE,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	0,
+	0,
+	},
+
+	/* Cipher C011 */
+	{
+	1,
+	TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA,
+	TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA,
+	SSL_kEECDH,
+	SSL_aRSA,
+	SSL_RC4,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_MEDIUM,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+	/* Cipher C012 */
+	{
+	1,
+	TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA,
+	TLS1_CK_ECDHE_RSA_WITH_DES_192_CBC3_SHA,
+	SSL_kEECDH,
+	SSL_aRSA,
+	SSL_3DES,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	168,
+	168,
+	},
+
+	/* Cipher C013 */
+	{
+	1,
+	TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+	TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+	SSL_kEECDH,
+	SSL_aRSA,
+	SSL_AES128,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+	/* Cipher C014 */
+	{
+	1,
+	TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+	TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+	SSL_kEECDH,
+	SSL_aRSA,
+	SSL_AES256,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	256,
+	256,
+	},
+
+	/* Cipher C015 */
+	{
+	1,
+	TLS1_TXT_ECDH_anon_WITH_NULL_SHA,
+	TLS1_CK_ECDH_anon_WITH_NULL_SHA,
+	SSL_kEECDH,
+	SSL_aNULL,
+	SSL_eNULL,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_STRONG_NONE,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	0,
+	0,
+	},
+
+	/* Cipher C016 */
+	{
+	1,
+	TLS1_TXT_ECDH_anon_WITH_RC4_128_SHA,
+	TLS1_CK_ECDH_anon_WITH_RC4_128_SHA,
+	SSL_kEECDH,
+	SSL_aNULL,
+	SSL_RC4,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_MEDIUM,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+	/* Cipher C017 */
+	{
+	1,
+	TLS1_TXT_ECDH_anon_WITH_DES_192_CBC3_SHA,
+	TLS1_CK_ECDH_anon_WITH_DES_192_CBC3_SHA,
+	SSL_kEECDH,
+	SSL_aNULL,
+	SSL_3DES,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	168,
+	168,
+	},
+
+	/* Cipher C018 */
+	{
+	1,
+	TLS1_TXT_ECDH_anon_WITH_AES_128_CBC_SHA,
+	TLS1_CK_ECDH_anon_WITH_AES_128_CBC_SHA,
+	SSL_kEECDH,
+	SSL_aNULL,
+	SSL_AES128,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+	/* Cipher C019 */
+	{
+	1,
+	TLS1_TXT_ECDH_anon_WITH_AES_256_CBC_SHA,
+	TLS1_CK_ECDH_anon_WITH_AES_256_CBC_SHA,
+	SSL_kEECDH,
+	SSL_aNULL,
+	SSL_AES256,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	256,
+	256,
+	},
+#endif	/* OPENSSL_NO_ECDH */
+
+#ifdef TEMP_GOST_TLS
+/* Cipher FF00 */
+	{
+	1,
+	"GOST-MD5",
+	0x0300ff00,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_eGOST2814789CNT,
+	SSL_MD5,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	256,
+	256,
+	},
+	{
+	1,
+	"GOST-GOST94",
+	0x0300ff01,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_eGOST2814789CNT,
+	SSL_GOST94,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	256,
+	256
+	},
+	{
+	1,
+	"GOST-GOST89MAC",
+	0x0300ff02,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_eGOST2814789CNT,
+	SSL_GOST89MAC,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	256,
+	256
+	},
+	{
+	1,
+	"GOST-GOST89STREAM",
+	0x0300ff03,
+	SSL_kRSA,
+	SSL_aRSA,
+	SSL_eGOST2814789CNT,
+	SSL_GOST89MAC,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF|TLS1_STREAM_MAC,
+	256,
+	256
+	},
+#endif
+
+/* end of list */
+	};
+
+SSL3_ENC_METHOD SSLv3_enc_data={
+	ssl3_enc,
+	n_ssl3_mac,
+	ssl3_setup_key_block,
+	ssl3_generate_master_secret,
+	ssl3_change_cipher_state,
+	ssl3_final_finish_mac,
+	MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH,
+	ssl3_cert_verify_mac,
+	SSL3_MD_CLIENT_FINISHED_CONST,4,
+	SSL3_MD_SERVER_FINISHED_CONST,4,
+	ssl3_alert_code,
+	};
+
+long ssl3_default_timeout(void)
+	{
+	/* 2 hours, the 24 hours mentioned in the SSLv3 spec
+	 * is way too long for http, the cache would over fill */
+	return(60*60*2);
+	}
+
+int ssl3_num_ciphers(void)
+	{
+	return(SSL3_NUM_CIPHERS);
+	}
+
+const SSL_CIPHER *ssl3_get_cipher(unsigned int u)
+	{
+	if (u < SSL3_NUM_CIPHERS)
+		return(&(ssl3_ciphers[SSL3_NUM_CIPHERS-1-u]));
+	else
+		return(NULL);
+	}
+
+int ssl3_pending(const SSL *s)
+	{
+	if (s->rstate == SSL_ST_READ_BODY)
+		return 0;
+	
+	return (s->s3->rrec.type == SSL3_RT_APPLICATION_DATA) ? s->s3->rrec.length : 0;
+	}
+
+int ssl3_new(SSL *s)
+	{
+	SSL3_STATE *s3;
+
+	if ((s3=OPENSSL_malloc(sizeof *s3)) == NULL) goto err;
+	memset(s3,0,sizeof *s3);
+	memset(s3->rrec.seq_num,0,sizeof(s3->rrec.seq_num));
+	memset(s3->wrec.seq_num,0,sizeof(s3->wrec.seq_num));
+
+	s->s3=s3;
+
+	s->method->ssl_clear(s);
+	return(1);
+err:
+	return(0);
+	}
+
+void ssl3_free(SSL *s)
+	{
+	if(s == NULL)
+	    return;
+
+#ifdef TLSEXT_TYPE_opaque_prf_input
+	if (s->s3->client_opaque_prf_input != NULL)
+		OPENSSL_free(s->s3->client_opaque_prf_input);
+	if (s->s3->server_opaque_prf_input != NULL)
+		OPENSSL_free(s->s3->server_opaque_prf_input);
+#endif
+
+	ssl3_cleanup_key_block(s);
+	if (s->s3->rbuf.buf != NULL)
+		ssl3_release_read_buffer(s);
+	if (s->s3->wbuf.buf != NULL)
+		ssl3_release_write_buffer(s);
+	if (s->s3->rrec.comp != NULL)
+		OPENSSL_free(s->s3->rrec.comp);
+#ifndef OPENSSL_NO_DH
+	if (s->s3->tmp.dh != NULL)
+		DH_free(s->s3->tmp.dh);
+#endif
+#ifndef OPENSSL_NO_ECDH
+	if (s->s3->tmp.ecdh != NULL)
+		EC_KEY_free(s->s3->tmp.ecdh);
+#endif
+
+	if (s->s3->tmp.ca_names != NULL)
+		sk_X509_NAME_pop_free(s->s3->tmp.ca_names,X509_NAME_free);
+	if (s->s3->handshake_buffer) {
+		BIO_free(s->s3->handshake_buffer);
+	}
+	if (s->s3->handshake_dgst) ssl3_free_digest_list(s);
+	OPENSSL_cleanse(s->s3,sizeof *s->s3);
+	OPENSSL_free(s->s3);
+	s->s3=NULL;
+	}
+
+void ssl3_clear(SSL *s)
+	{
+	unsigned char *rp,*wp;
+	size_t rlen, wlen;
+
+#ifdef TLSEXT_TYPE_opaque_prf_input
+	if (s->s3->client_opaque_prf_input != NULL)
+		OPENSSL_free(s->s3->client_opaque_prf_input);
+	s->s3->client_opaque_prf_input = NULL;
+	if (s->s3->server_opaque_prf_input != NULL)
+		OPENSSL_free(s->s3->server_opaque_prf_input);
+	s->s3->server_opaque_prf_input = NULL;
+#endif
+
+	ssl3_cleanup_key_block(s);
+	if (s->s3->tmp.ca_names != NULL)
+		sk_X509_NAME_pop_free(s->s3->tmp.ca_names,X509_NAME_free);
+
+	if (s->s3->rrec.comp != NULL)
+		{
+		OPENSSL_free(s->s3->rrec.comp);
+		s->s3->rrec.comp=NULL;
+		}
+#ifndef OPENSSL_NO_DH
+	if (s->s3->tmp.dh != NULL)
+		DH_free(s->s3->tmp.dh);
+#endif
+#ifndef OPENSSL_NO_ECDH
+	if (s->s3->tmp.ecdh != NULL)
+		EC_KEY_free(s->s3->tmp.ecdh);
+#endif
+
+	rp = s->s3->rbuf.buf;
+	wp = s->s3->wbuf.buf;
+	rlen = s->s3->rbuf.len;
+ 	wlen = s->s3->wbuf.len;
+	if (s->s3->handshake_buffer) {
+		BIO_free(s->s3->handshake_buffer);
+		s->s3->handshake_buffer = NULL;
+	}
+	if (s->s3->handshake_dgst) {
+		ssl3_free_digest_list(s);
+	}	
+	memset(s->s3,0,sizeof *s->s3);
+	s->s3->rbuf.buf = rp;
+	s->s3->wbuf.buf = wp;
+	s->s3->rbuf.len = rlen;
+ 	s->s3->wbuf.len = wlen;
+
+	ssl_free_wbio_buffer(s);
+
+	s->packet_length=0;
+	s->s3->renegotiate=0;
+	s->s3->total_renegotiations=0;
+	s->s3->num_renegotiations=0;
+	s->s3->in_read_app_data=0;
+	s->version=SSL3_VERSION;
+	}
+
+long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
+	{
+	int ret=0;
+
+#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_RSA)
+	if (
+#ifndef OPENSSL_NO_RSA
+	    cmd == SSL_CTRL_SET_TMP_RSA ||
+	    cmd == SSL_CTRL_SET_TMP_RSA_CB ||
+#endif
+#ifndef OPENSSL_NO_DSA
+	    cmd == SSL_CTRL_SET_TMP_DH ||
+	    cmd == SSL_CTRL_SET_TMP_DH_CB ||
+#endif
+		0)
+		{
+		if (!ssl_cert_inst(&s->cert))
+		    	{
+			SSLerr(SSL_F_SSL3_CTRL, ERR_R_MALLOC_FAILURE);
+			return(0);
+			}
+		}
+#endif
+
+	switch (cmd)
+		{
+	case SSL_CTRL_GET_SESSION_REUSED:
+		ret=s->hit;
+		break;
+	case SSL_CTRL_GET_CLIENT_CERT_REQUEST:
+		break;
+	case SSL_CTRL_GET_NUM_RENEGOTIATIONS:
+		ret=s->s3->num_renegotiations;
+		break;
+	case SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS:
+		ret=s->s3->num_renegotiations;
+		s->s3->num_renegotiations=0;
+		break;
+	case SSL_CTRL_GET_TOTAL_RENEGOTIATIONS:
+		ret=s->s3->total_renegotiations;
+		break;
+	case SSL_CTRL_GET_FLAGS:
+		ret=(int)(s->s3->flags);
+		break;
+#ifndef OPENSSL_NO_RSA
+	case SSL_CTRL_NEED_TMP_RSA:
+		if ((s->cert != NULL) && (s->cert->rsa_tmp == NULL) &&
+		    ((s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL) ||
+		     (EVP_PKEY_size(s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey) > (512/8))))
+			ret = 1;
+		break;
+	case SSL_CTRL_SET_TMP_RSA:
+		{
+			RSA *rsa = (RSA *)parg;
+			if (rsa == NULL)
+				{
+				SSLerr(SSL_F_SSL3_CTRL, ERR_R_PASSED_NULL_PARAMETER);
+				return(ret);
+				}
+			if ((rsa = RSAPrivateKey_dup(rsa)) == NULL)
+				{
+				SSLerr(SSL_F_SSL3_CTRL, ERR_R_RSA_LIB);
+				return(ret);
+				}
+			if (s->cert->rsa_tmp != NULL)
+				RSA_free(s->cert->rsa_tmp);
+			s->cert->rsa_tmp = rsa;
+			ret = 1;
+		}
+		break;
+	case SSL_CTRL_SET_TMP_RSA_CB:
+		{
+		SSLerr(SSL_F_SSL3_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return(ret);
+		}
+		break;
+#endif
+#ifndef OPENSSL_NO_DH
+	case SSL_CTRL_SET_TMP_DH:
+		{
+			DH *dh = (DH *)parg;
+			if (dh == NULL)
+				{
+				SSLerr(SSL_F_SSL3_CTRL, ERR_R_PASSED_NULL_PARAMETER);
+				return(ret);
+				}
+			if ((dh = DHparams_dup(dh)) == NULL)
+				{
+				SSLerr(SSL_F_SSL3_CTRL, ERR_R_DH_LIB);
+				return(ret);
+				}
+			if (!(s->options & SSL_OP_SINGLE_DH_USE))
+				{
+				if (!DH_generate_key(dh))
+					{
+					DH_free(dh);
+					SSLerr(SSL_F_SSL3_CTRL, ERR_R_DH_LIB);
+					return(ret);
+					}
+				}
+			if (s->cert->dh_tmp != NULL)
+				DH_free(s->cert->dh_tmp);
+			s->cert->dh_tmp = dh;
+			ret = 1;
+		}
+		break;
+	case SSL_CTRL_SET_TMP_DH_CB:
+		{
+		SSLerr(SSL_F_SSL3_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return(ret);
+		}
+		break;
+#endif
+#ifndef OPENSSL_NO_ECDH
+	case SSL_CTRL_SET_TMP_ECDH:
+		{
+		EC_KEY *ecdh = NULL;
+ 			
+		if (parg == NULL)
+			{
+			SSLerr(SSL_F_SSL3_CTRL, ERR_R_PASSED_NULL_PARAMETER);
+			return(ret);
+			}
+		if (!EC_KEY_up_ref((EC_KEY *)parg))
+			{
+			SSLerr(SSL_F_SSL3_CTRL,ERR_R_ECDH_LIB);
+			return(ret);
+			}
+		ecdh = (EC_KEY *)parg;
+		if (!(s->options & SSL_OP_SINGLE_ECDH_USE))
+			{
+			if (!EC_KEY_generate_key(ecdh))
+				{
+				EC_KEY_free(ecdh);
+				SSLerr(SSL_F_SSL3_CTRL,ERR_R_ECDH_LIB);
+				return(ret);
+				}
+			}
+		if (s->cert->ecdh_tmp != NULL)
+			EC_KEY_free(s->cert->ecdh_tmp);
+		s->cert->ecdh_tmp = ecdh;
+		ret = 1;
+		}
+		break;
+	case SSL_CTRL_SET_TMP_ECDH_CB:
+		{
+		SSLerr(SSL_F_SSL3_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return(ret);
+		}
+		break;
+#endif /* !OPENSSL_NO_ECDH */
+#ifndef OPENSSL_NO_TLSEXT
+	case SSL_CTRL_SET_TLSEXT_HOSTNAME:
+ 		if (larg == TLSEXT_NAMETYPE_host_name)
+			{
+			if (s->tlsext_hostname != NULL) 
+				OPENSSL_free(s->tlsext_hostname);
+			s->tlsext_hostname = NULL;
+
+			ret = 1;
+			if (parg == NULL) 
+				break;
+			if (strlen((char *)parg) > TLSEXT_MAXLEN_host_name)
+				{
+				SSLerr(SSL_F_SSL3_CTRL, SSL_R_SSL3_EXT_INVALID_SERVERNAME);
+				return 0;
+				}
+			if ((s->tlsext_hostname = BUF_strdup((char *)parg)) == NULL)
+				{
+				SSLerr(SSL_F_SSL3_CTRL, ERR_R_INTERNAL_ERROR);
+				return 0;
+				}
+			}
+		else
+			{
+			SSLerr(SSL_F_SSL3_CTRL, SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE);
+			return 0;
+			}
+ 		break;
+	case SSL_CTRL_SET_TLSEXT_DEBUG_ARG:
+		s->tlsext_debug_arg=parg;
+		ret = 1;
+		break;
+
+#ifdef TLSEXT_TYPE_opaque_prf_input
+	case SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT:
+		if (larg > 12288) /* actual internal limit is 2^16 for the complete hello message
+		                   * (including the cert chain and everything) */
+			{
+			SSLerr(SSL_F_SSL3_CTRL, SSL_R_OPAQUE_PRF_INPUT_TOO_LONG);
+			break;
+			}
+		if (s->tlsext_opaque_prf_input != NULL)
+			OPENSSL_free(s->tlsext_opaque_prf_input);
+		if ((size_t)larg == 0)
+			s->tlsext_opaque_prf_input = OPENSSL_malloc(1); /* dummy byte just to get non-NULL */
+		else
+			s->tlsext_opaque_prf_input = BUF_memdup(parg, (size_t)larg);
+		if (s->tlsext_opaque_prf_input != NULL)
+			{
+			s->tlsext_opaque_prf_input_len = (size_t)larg;
+			ret = 1;
+			}
+		else
+			s->tlsext_opaque_prf_input_len = 0;
+		break;
+#endif
+
+	case SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE:
+		s->tlsext_status_type=larg;
+		ret = 1;
+		break;
+
+	case SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS:
+		*(STACK_OF(X509_EXTENSION) **)parg = s->tlsext_ocsp_exts;
+		ret = 1;
+		break;
+
+	case SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS:
+		s->tlsext_ocsp_exts = parg;
+		ret = 1;
+		break;
+
+	case SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS:
+		*(STACK_OF(OCSP_RESPID) **)parg = s->tlsext_ocsp_ids;
+		ret = 1;
+		break;
+
+	case SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS:
+		s->tlsext_ocsp_ids = parg;
+		ret = 1;
+		break;
+
+	case SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP:
+		*(unsigned char **)parg = s->tlsext_ocsp_resp;
+		return s->tlsext_ocsp_resplen;
+		
+	case SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP:
+		if (s->tlsext_ocsp_resp)
+			OPENSSL_free(s->tlsext_ocsp_resp);
+		s->tlsext_ocsp_resp = parg;
+		s->tlsext_ocsp_resplen = larg;
+		ret = 1;
+		break;
+
+#endif /* !OPENSSL_NO_TLSEXT */
+	default:
+		break;
+		}
+	return(ret);
+	}
+
+long ssl3_callback_ctrl(SSL *s, int cmd, void (*fp)(void))
+	{
+	int ret=0;
+
+#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_RSA)
+	if (
+#ifndef OPENSSL_NO_RSA
+	    cmd == SSL_CTRL_SET_TMP_RSA_CB ||
+#endif
+#ifndef OPENSSL_NO_DSA
+	    cmd == SSL_CTRL_SET_TMP_DH_CB ||
+#endif
+		0)
+		{
+		if (!ssl_cert_inst(&s->cert))
+			{
+			SSLerr(SSL_F_SSL3_CALLBACK_CTRL, ERR_R_MALLOC_FAILURE);
+			return(0);
+			}
+		}
+#endif
+
+	switch (cmd)
+		{
+#ifndef OPENSSL_NO_RSA
+	case SSL_CTRL_SET_TMP_RSA_CB:
+		{
+		s->cert->rsa_tmp_cb = (RSA *(*)(SSL *, int, int))fp;
+		}
+		break;
+#endif
+#ifndef OPENSSL_NO_DH
+	case SSL_CTRL_SET_TMP_DH_CB:
+		{
+		s->cert->dh_tmp_cb = (DH *(*)(SSL *, int, int))fp;
+		}
+		break;
+#endif
+#ifndef OPENSSL_NO_ECDH
+	case SSL_CTRL_SET_TMP_ECDH_CB:
+		{
+		s->cert->ecdh_tmp_cb = (EC_KEY *(*)(SSL *, int, int))fp;
+		}
+		break;
+#endif
+#ifndef OPENSSL_NO_TLSEXT
+	case SSL_CTRL_SET_TLSEXT_DEBUG_CB:
+		s->tlsext_debug_cb=(void (*)(SSL *,int ,int,
+					unsigned char *, int, void *))fp;
+		break;
+#endif
+	default:
+		break;
+		}
+	return(ret);
+	}
+
+long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
+	{
+	CERT *cert;
+
+	cert=ctx->cert;
+
+	switch (cmd)
+		{
+#ifndef OPENSSL_NO_RSA
+	case SSL_CTRL_NEED_TMP_RSA:
+		if (	(cert->rsa_tmp == NULL) &&
+			((cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL) ||
+			 (EVP_PKEY_size(cert->pkeys[SSL_PKEY_RSA_ENC].privatekey) > (512/8)))
+			)
+			return(1);
+		else
+			return(0);
+		/* break; */
+	case SSL_CTRL_SET_TMP_RSA:
+		{
+		RSA *rsa;
+		int i;
+
+		rsa=(RSA *)parg;
+		i=1;
+		if (rsa == NULL)
+			i=0;
+		else
+			{
+			if ((rsa=RSAPrivateKey_dup(rsa)) == NULL)
+				i=0;
+			}
+		if (!i)
+			{
+			SSLerr(SSL_F_SSL3_CTX_CTRL,ERR_R_RSA_LIB);
+			return(0);
+			}
+		else
+			{
+			if (cert->rsa_tmp != NULL)
+				RSA_free(cert->rsa_tmp);
+			cert->rsa_tmp=rsa;
+			return(1);
+			}
+		}
+		/* break; */
+	case SSL_CTRL_SET_TMP_RSA_CB:
+		{
+		SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return(0);
+		}
+		break;
+#endif
+#ifndef OPENSSL_NO_DH
+	case SSL_CTRL_SET_TMP_DH:
+		{
+		DH *new=NULL,*dh;
+
+		dh=(DH *)parg;
+		if ((new=DHparams_dup(dh)) == NULL)
+			{
+			SSLerr(SSL_F_SSL3_CTX_CTRL,ERR_R_DH_LIB);
+			return 0;
+			}
+		if (!(ctx->options & SSL_OP_SINGLE_DH_USE))
+			{
+			if (!DH_generate_key(new))
+				{
+				SSLerr(SSL_F_SSL3_CTX_CTRL,ERR_R_DH_LIB);
+				DH_free(new);
+				return 0;
+				}
+			}
+		if (cert->dh_tmp != NULL)
+			DH_free(cert->dh_tmp);
+		cert->dh_tmp=new;
+		return 1;
+		}
+		/*break; */
+	case SSL_CTRL_SET_TMP_DH_CB:
+		{
+		SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return(0);
+		}
+		break;
+#endif
+#ifndef OPENSSL_NO_ECDH
+	case SSL_CTRL_SET_TMP_ECDH:
+		{
+		EC_KEY *ecdh = NULL;
+ 			
+		if (parg == NULL)
+			{
+			SSLerr(SSL_F_SSL3_CTX_CTRL,ERR_R_ECDH_LIB);
+			return 0;
+			}
+		ecdh = EC_KEY_dup((EC_KEY *)parg);
+		if (ecdh == NULL)
+			{
+			SSLerr(SSL_F_SSL3_CTX_CTRL,ERR_R_EC_LIB);
+			return 0;
+			}
+		if (!(ctx->options & SSL_OP_SINGLE_ECDH_USE))
+			{
+			if (!EC_KEY_generate_key(ecdh))
+				{
+				EC_KEY_free(ecdh);
+				SSLerr(SSL_F_SSL3_CTX_CTRL,ERR_R_ECDH_LIB);
+				return 0;
+				}
+			}
+
+		if (cert->ecdh_tmp != NULL)
+			{
+			EC_KEY_free(cert->ecdh_tmp);
+			}
+		cert->ecdh_tmp = ecdh;
+		return 1;
+		}
+		/* break; */
+	case SSL_CTRL_SET_TMP_ECDH_CB:
+		{
+		SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return(0);
+		}
+		break;
+#endif /* !OPENSSL_NO_ECDH */
+#ifndef OPENSSL_NO_TLSEXT
+	case SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG:
+		ctx->tlsext_servername_arg=parg;
+		break;
+	case SSL_CTRL_SET_TLSEXT_TICKET_KEYS:
+	case SSL_CTRL_GET_TLSEXT_TICKET_KEYS:
+		{
+		unsigned char *keys = parg;
+		if (!keys)
+			return 48;
+		if (larg != 48)
+			{
+			SSLerr(SSL_F_SSL3_CTX_CTRL, SSL_R_INVALID_TICKET_KEYS_LENGTH);
+			return 0;
+			}
+		if (cmd == SSL_CTRL_SET_TLSEXT_TICKET_KEYS)
+			{
+			memcpy(ctx->tlsext_tick_key_name, keys, 16);
+			memcpy(ctx->tlsext_tick_hmac_key, keys + 16, 16);
+			memcpy(ctx->tlsext_tick_aes_key, keys + 32, 16);
+			}
+		else
+			{
+			memcpy(keys, ctx->tlsext_tick_key_name, 16);
+			memcpy(keys + 16, ctx->tlsext_tick_hmac_key, 16);
+			memcpy(keys + 32, ctx->tlsext_tick_aes_key, 16);
+			}
+		return 1;
+		}
+
+#ifdef TLSEXT_TYPE_opaque_prf_input
+	case SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB_ARG:
+		ctx->tlsext_opaque_prf_input_callback_arg = parg;
+		return 1;
+#endif
+
+	case SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG:
+		ctx->tlsext_status_arg=parg;
+		return 1;
+		break;
+
+#endif /* !OPENSSL_NO_TLSEXT */
+
+	/* A Thawte special :-) */
+	case SSL_CTRL_EXTRA_CHAIN_CERT:
+		if (ctx->extra_certs == NULL)
+			{
+			if ((ctx->extra_certs=sk_X509_new_null()) == NULL)
+				return(0);
+			}
+		sk_X509_push(ctx->extra_certs,(X509 *)parg);
+		break;
+
+	default:
+		return(0);
+		}
+	return(1);
+	}
+
+long ssl3_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp)(void))
+	{
+	CERT *cert;
+
+	cert=ctx->cert;
+
+	switch (cmd)
+		{
+#ifndef OPENSSL_NO_RSA
+	case SSL_CTRL_SET_TMP_RSA_CB:
+		{
+		cert->rsa_tmp_cb = (RSA *(*)(SSL *, int, int))fp;
+		}
+		break;
+#endif
+#ifndef OPENSSL_NO_DH
+	case SSL_CTRL_SET_TMP_DH_CB:
+		{
+		cert->dh_tmp_cb = (DH *(*)(SSL *, int, int))fp;
+		}
+		break;
+#endif
+#ifndef OPENSSL_NO_ECDH
+	case SSL_CTRL_SET_TMP_ECDH_CB:
+		{
+		cert->ecdh_tmp_cb = (EC_KEY *(*)(SSL *, int, int))fp;
+		}
+		break;
+#endif
+#ifndef OPENSSL_NO_TLSEXT
+	case SSL_CTRL_SET_TLSEXT_SERVERNAME_CB:
+		ctx->tlsext_servername_callback=(int (*)(SSL *,int *,void *))fp;
+		break;
+
+#ifdef TLSEXT_TYPE_opaque_prf_input
+	case SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB:
+		ctx->tlsext_opaque_prf_input_callback = (int (*)(SSL *,void *, size_t, void *))fp;
+		break;
+#endif
+
+	case SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB:
+		ctx->tlsext_status_cb=(int (*)(SSL *,void *))fp;
+		break;
+
+	case SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB:
+		ctx->tlsext_ticket_key_cb=(int (*)(SSL *,unsigned char  *,
+						unsigned char *,
+						EVP_CIPHER_CTX *,
+						HMAC_CTX *, int))fp;
+		break;
+
+#endif
+	default:
+		return(0);
+		}
+	return(1);
+	}
+
+/* This function needs to check if the ciphers required are actually
+ * available */
+const SSL_CIPHER *ssl3_get_cipher_by_char(const unsigned char *p)
+	{
+	SSL_CIPHER c;
+	const SSL_CIPHER *cp;
+	unsigned long id;
+
+	id=0x03000000L|((unsigned long)p[0]<<8L)|(unsigned long)p[1];
+	c.id=id;
+	cp = OBJ_bsearch_ssl_cipher_id(&c, ssl3_ciphers, SSL3_NUM_CIPHERS);
+	if (cp == NULL || cp->valid == 0)
+		return NULL;
+	else
+		return cp;
+	}
+
+int ssl3_put_cipher_by_char(const SSL_CIPHER *c, unsigned char *p)
+	{
+	long l;
+
+	if (p != NULL)
+		{
+		l=c->id;
+		if ((l & 0xff000000) != 0x03000000) return(0);
+		p[0]=((unsigned char)(l>> 8L))&0xFF;
+		p[1]=((unsigned char)(l     ))&0xFF;
+		}
+	return(2);
+	}
+
+SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
+	     STACK_OF(SSL_CIPHER) *srvr)
+	{
+	SSL_CIPHER *c,*ret=NULL;
+	STACK_OF(SSL_CIPHER) *prio, *allow;
+	int i,ii,ok;
+#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_EC)
+	unsigned int j;
+	int ec_ok, ec_nid;
+	unsigned char ec_search1 = 0, ec_search2 = 0;
+#endif
+	CERT *cert;
+	unsigned long alg_k,alg_a,mask_k,mask_a,emask_k,emask_a;
+
+	/* Let's see which ciphers we can support */
+	cert=s->cert;
+
+#if 0
+	/* Do not set the compare functions, because this may lead to a
+	 * reordering by "id". We want to keep the original ordering.
+	 * We may pay a price in performance during sk_SSL_CIPHER_find(),
+	 * but would have to pay with the price of sk_SSL_CIPHER_dup().
+	 */
+	sk_SSL_CIPHER_set_cmp_func(srvr, ssl_cipher_ptr_id_cmp);
+	sk_SSL_CIPHER_set_cmp_func(clnt, ssl_cipher_ptr_id_cmp);
+#endif
+
+#ifdef CIPHER_DEBUG
+	printf("Server has %d from %p:\n", sk_SSL_CIPHER_num(srvr), (void *)srvr);
+	for(i=0 ; i < sk_SSL_CIPHER_num(srvr) ; ++i)
+		{
+		c=sk_SSL_CIPHER_value(srvr,i);
+		printf("%p:%s\n",(void *)c,c->name);
+		}
+	printf("Client sent %d from %p:\n", sk_SSL_CIPHER_num(clnt), (void *)clnt);
+	for(i=0 ; i < sk_SSL_CIPHER_num(clnt) ; ++i)
+	    {
+	    c=sk_SSL_CIPHER_value(clnt,i);
+	    printf("%p:%s\n",(void *)c,c->name);
+	    }
+#endif
+
+	if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE)
+		{
+		prio = srvr;
+		allow = clnt;
+		}
+	else
+		{
+		prio = clnt;
+		allow = srvr;
+		}
+
+	for (i=0; i<sk_SSL_CIPHER_num(prio); i++)
+		{
+		c=sk_SSL_CIPHER_value(prio,i);
+
+		ssl_set_cert_masks(cert,c);
+		mask_k = cert->mask_k;
+		mask_a = cert->mask_a;
+		emask_k = cert->export_mask_k;
+		emask_a = cert->export_mask_a;
+			
+#ifdef KSSL_DEBUG
+/*		printf("ssl3_choose_cipher %d alg= %lx\n", i,c->algorithms);*/
+#endif    /* KSSL_DEBUG */
+
+		alg_k=c->algorithm_mkey;
+		alg_a=c->algorithm_auth;
+
+#ifndef OPENSSL_NO_KRB5
+		if (alg_k & SSL_kKRB5)
+			{
+			if ( !kssl_keytab_is_available(s->kssl_ctx) )
+			    continue;
+			}
+#endif /* OPENSSL_NO_KRB5 */
+#ifndef OPENSSL_NO_PSK
+		/* with PSK there must be server callback set */
+		if ((alg_k & SSL_kPSK) && s->psk_server_callback == NULL)
+			continue;
+#endif /* OPENSSL_NO_PSK */
+
+		if (SSL_C_IS_EXPORT(c))
+			{
+			ok = (alg_k & emask_k) && (alg_a & emask_a);
+#ifdef CIPHER_DEBUG
+			printf("%d:[%08lX:%08lX:%08lX:%08lX]%p:%s (export)\n",ok,alg_k,alg_a,emask_k,emask_a,
+			       (void *)c,c->name);
+#endif
+			}
+		else
+			{
+			ok = (alg_k & mask_k) && (alg_a & mask_a);
+#ifdef CIPHER_DEBUG
+			printf("%d:[%08lX:%08lX:%08lX:%08lX]%p:%s\n",ok,alg_k,alg_a,mask_k,mask_a,(void *)c,
+			       c->name);
+#endif
+			}
+
+#ifndef OPENSSL_NO_TLSEXT
+#ifndef OPENSSL_NO_EC
+		if (
+			/* if we are considering an ECC cipher suite that uses our certificate */
+			(alg_a & SSL_aECDSA || alg_a & SSL_aECDH)
+			/* and we have an ECC certificate */
+			&& (s->cert->pkeys[SSL_PKEY_ECC].x509 != NULL)
+			/* and the client specified a Supported Point Formats extension */
+			&& ((s->session->tlsext_ecpointformatlist_length > 0) && (s->session->tlsext_ecpointformatlist != NULL))
+			/* and our certificate's point is compressed */
+			&& (
+				(s->cert->pkeys[SSL_PKEY_ECC].x509->cert_info != NULL)
+				&& (s->cert->pkeys[SSL_PKEY_ECC].x509->cert_info->key != NULL)
+				&& (s->cert->pkeys[SSL_PKEY_ECC].x509->cert_info->key->public_key != NULL)
+				&& (s->cert->pkeys[SSL_PKEY_ECC].x509->cert_info->key->public_key->data != NULL)
+				&& (
+					(*(s->cert->pkeys[SSL_PKEY_ECC].x509->cert_info->key->public_key->data) == POINT_CONVERSION_COMPRESSED)
+					|| (*(s->cert->pkeys[SSL_PKEY_ECC].x509->cert_info->key->public_key->data) == POINT_CONVERSION_COMPRESSED + 1)
+					)
+				)
+		)
+			{
+			ec_ok = 0;
+			/* if our certificate's curve is over a field type that the client does not support
+			 * then do not allow this cipher suite to be negotiated */
+			if (
+				(s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec != NULL)
+				&& (s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec->group != NULL)
+				&& (s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec->group->meth != NULL)
+				&& (EC_METHOD_get_field_type(s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec->group->meth) == NID_X9_62_prime_field)
+			)
+				{
+				for (j = 0; j < s->session->tlsext_ecpointformatlist_length; j++)
+					{
+					if (s->session->tlsext_ecpointformatlist[j] == TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime)
+						{
+						ec_ok = 1;
+						break;
+						}
+					}
+				}
+			else if (EC_METHOD_get_field_type(s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec->group->meth) == NID_X9_62_characteristic_two_field)
+				{
+				for (j = 0; j < s->session->tlsext_ecpointformatlist_length; j++)
+					{
+					if (s->session->tlsext_ecpointformatlist[j] == TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2)
+						{
+						ec_ok = 1;
+						break;
+						}
+					}
+				}
+			ok = ok && ec_ok;
+			}
+		if (
+			/* if we are considering an ECC cipher suite that uses our certificate */
+			(alg_a & SSL_aECDSA || alg_a & SSL_aECDH)
+			/* and we have an ECC certificate */
+			&& (s->cert->pkeys[SSL_PKEY_ECC].x509 != NULL)
+			/* and the client specified an EllipticCurves extension */
+			&& ((s->session->tlsext_ellipticcurvelist_length > 0) && (s->session->tlsext_ellipticcurvelist != NULL))
+		)
+			{
+			ec_ok = 0;
+			if (
+				(s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec != NULL)
+				&& (s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec->group != NULL)
+			)
+				{
+				ec_nid = EC_GROUP_get_curve_name(s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec->group);
+				if ((ec_nid == 0)
+					&& (s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec->group->meth != NULL)
+				)
+					{
+					if (EC_METHOD_get_field_type(s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec->group->meth) == NID_X9_62_prime_field)
+						{
+						ec_search1 = 0xFF;
+						ec_search2 = 0x01;
+						}
+					else if (EC_METHOD_get_field_type(s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec->group->meth) == NID_X9_62_characteristic_two_field)
+						{
+						ec_search1 = 0xFF;
+						ec_search2 = 0x02;
+						}
+					}
+				else
+					{
+					ec_search1 = 0x00;
+					ec_search2 = tls1_ec_nid2curve_id(ec_nid);
+					}
+				if ((ec_search1 != 0) || (ec_search2 != 0))
+					{
+					for (j = 0; j < s->session->tlsext_ellipticcurvelist_length / 2; j++)
+						{
+						if ((s->session->tlsext_ellipticcurvelist[2*j] == ec_search1) && (s->session->tlsext_ellipticcurvelist[2*j+1] == ec_search2))
+							{
+							ec_ok = 1;
+							break;
+							}
+						}
+					}
+				}
+			ok = ok && ec_ok;
+			}
+		if (
+			/* if we are considering an ECC cipher suite that uses an ephemeral EC key */
+			(alg_k & SSL_kEECDH)
+			/* and we have an ephemeral EC key */
+			&& (s->cert->ecdh_tmp != NULL)
+			/* and the client specified an EllipticCurves extension */
+			&& ((s->session->tlsext_ellipticcurvelist_length > 0) && (s->session->tlsext_ellipticcurvelist != NULL))
+		)
+			{
+			ec_ok = 0;
+			if (s->cert->ecdh_tmp->group != NULL)
+				{
+				ec_nid = EC_GROUP_get_curve_name(s->cert->ecdh_tmp->group);
+				if ((ec_nid == 0)
+					&& (s->cert->ecdh_tmp->group->meth != NULL)
+				)
+					{
+					if (EC_METHOD_get_field_type(s->cert->ecdh_tmp->group->meth) == NID_X9_62_prime_field)
+						{
+						ec_search1 = 0xFF;
+						ec_search2 = 0x01;
+						}
+					else if (EC_METHOD_get_field_type(s->cert->ecdh_tmp->group->meth) == NID_X9_62_characteristic_two_field)
+						{
+						ec_search1 = 0xFF;
+						ec_search2 = 0x02;
+						}
+					}
+				else
+					{
+					ec_search1 = 0x00;
+					ec_search2 = tls1_ec_nid2curve_id(ec_nid);
+					}
+				if ((ec_search1 != 0) || (ec_search2 != 0))
+					{
+					for (j = 0; j < s->session->tlsext_ellipticcurvelist_length / 2; j++)
+						{
+						if ((s->session->tlsext_ellipticcurvelist[2*j] == ec_search1) && (s->session->tlsext_ellipticcurvelist[2*j+1] == ec_search2))
+							{
+							ec_ok = 1;
+							break;
+							}
+						}
+					}
+				}
+			ok = ok && ec_ok;
+			}
+#endif /* OPENSSL_NO_EC */
+#endif /* OPENSSL_NO_TLSEXT */
+
+		if (!ok) continue;
+		ii=sk_SSL_CIPHER_find(allow,c);
+		if (ii >= 0)
+			{
+			ret=sk_SSL_CIPHER_value(allow,ii);
+			break;
+			}
+		}
+	return(ret);
+	}
+
+int ssl3_get_req_cert_type(SSL *s, unsigned char *p)
+	{
+	int ret=0;
+	unsigned long alg_k;
+
+	alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+
+#ifndef OPENSSL_NO_GOST
+	if (s->version >= TLS1_VERSION)
+		{
+		if (alg_k & SSL_kGOST)
+			{
+			p[ret++]=TLS_CT_GOST94_SIGN;
+			p[ret++]=TLS_CT_GOST01_SIGN;
+			return(ret);
+			}
+		}
+#endif
+
+#ifndef OPENSSL_NO_DH
+	if (alg_k & (SSL_kDHr|SSL_kEDH))
+		{
+#  ifndef OPENSSL_NO_RSA
+		p[ret++]=SSL3_CT_RSA_FIXED_DH;
+#  endif
+#  ifndef OPENSSL_NO_DSA
+		p[ret++]=SSL3_CT_DSS_FIXED_DH;
+#  endif
+		}
+	if ((s->version == SSL3_VERSION) &&
+		(alg_k & (SSL_kEDH|SSL_kDHd|SSL_kDHr)))
+		{
+#  ifndef OPENSSL_NO_RSA
+		p[ret++]=SSL3_CT_RSA_EPHEMERAL_DH;
+#  endif
+#  ifndef OPENSSL_NO_DSA
+		p[ret++]=SSL3_CT_DSS_EPHEMERAL_DH;
+#  endif
+		}
+#endif /* !OPENSSL_NO_DH */
+#ifndef OPENSSL_NO_RSA
+	p[ret++]=SSL3_CT_RSA_SIGN;
+#endif
+#ifndef OPENSSL_NO_DSA
+	p[ret++]=SSL3_CT_DSS_SIGN;
+#endif
+#ifndef OPENSSL_NO_ECDH
+	if ((alg_k & (SSL_kECDHr|SSL_kECDHe)) && (s->version >= TLS1_VERSION))
+		{
+		p[ret++]=TLS_CT_RSA_FIXED_ECDH;
+		p[ret++]=TLS_CT_ECDSA_FIXED_ECDH;
+		}
+#endif
+
+#ifndef OPENSSL_NO_ECDSA
+	/* ECDSA certs can be used with RSA cipher suites as well 
+	 * so we don't need to check for SSL_kECDH or SSL_kEECDH
+	 */
+	if (s->version >= TLS1_VERSION)
+		{
+		p[ret++]=TLS_CT_ECDSA_SIGN;
+		}
+#endif	
+	return(ret);
+	}
+
+int ssl3_shutdown(SSL *s)
+	{
+	int ret;
+
+	/* Don't do anything much if we have not done the handshake or
+	 * we don't want to send messages :-) */
+	if ((s->quiet_shutdown) || (s->state == SSL_ST_BEFORE))
+		{
+		s->shutdown=(SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
+		return(1);
+		}
+
+	if (!(s->shutdown & SSL_SENT_SHUTDOWN))
+		{
+		s->shutdown|=SSL_SENT_SHUTDOWN;
+#if 1
+		ssl3_send_alert(s,SSL3_AL_WARNING,SSL_AD_CLOSE_NOTIFY);
+#endif
+		/* our shutdown alert has been sent now, and if it still needs
+	 	 * to be written, s->s3->alert_dispatch will be true */
+	 	if (s->s3->alert_dispatch)
+	 		return(-1);	/* return WANT_WRITE */
+		}
+	else if (s->s3->alert_dispatch)
+		{
+		/* resend it if not sent */
+#if 1
+		ret=s->method->ssl_dispatch_alert(s);
+		if(ret == -1)
+			{
+			/* we only get to return -1 here the 2nd/Nth
+			 * invocation, we must  have already signalled
+			 * return 0 upon a previous invoation,
+			 * return WANT_WRITE */
+			return(ret);
+			}
+#endif
+		}
+	else if (!(s->shutdown & SSL_RECEIVED_SHUTDOWN))
+		{
+		/* If we are waiting for a close from our peer, we are closed */
+		s->method->ssl_read_bytes(s,0,NULL,0,0);
+		if(!(s->shutdown & SSL_RECEIVED_SHUTDOWN))
+			{
+			return(-1);	/* return WANT_READ */
+			}
+		}
+
+	if ((s->shutdown == (SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN)) &&
+		!s->s3->alert_dispatch)
+		return(1);
+	else
+		return(0);
+	}
+
+int ssl3_write(SSL *s, const void *buf, int len)
+	{
+	int ret,n;
+
+#if 0
+	if (s->shutdown & SSL_SEND_SHUTDOWN)
+		{
+		s->rwstate=SSL_NOTHING;
+		return(0);
+		}
+#endif
+	clear_sys_error();
+	if (s->s3->renegotiate) ssl3_renegotiate_check(s);
+
+	/* This is an experimental flag that sends the
+	 * last handshake message in the same packet as the first
+	 * use data - used to see if it helps the TCP protocol during
+	 * session-id reuse */
+	/* The second test is because the buffer may have been removed */
+	if ((s->s3->flags & SSL3_FLAGS_POP_BUFFER) && (s->wbio == s->bbio))
+		{
+		/* First time through, we write into the buffer */
+		if (s->s3->delay_buf_pop_ret == 0)
+			{
+			ret=ssl3_write_bytes(s,SSL3_RT_APPLICATION_DATA,
+					     buf,len);
+			if (ret <= 0) return(ret);
+
+			s->s3->delay_buf_pop_ret=ret;
+			}
+
+		s->rwstate=SSL_WRITING;
+		n=BIO_flush(s->wbio);
+		if (n <= 0) return(n);
+		s->rwstate=SSL_NOTHING;
+
+		/* We have flushed the buffer, so remove it */
+		ssl_free_wbio_buffer(s);
+		s->s3->flags&= ~SSL3_FLAGS_POP_BUFFER;
+
+		ret=s->s3->delay_buf_pop_ret;
+		s->s3->delay_buf_pop_ret=0;
+		}
+	else
+		{
+		ret=s->method->ssl_write_bytes(s,SSL3_RT_APPLICATION_DATA,
+			buf,len);
+		if (ret <= 0) return(ret);
+		}
+
+	return(ret);
+	}
+
+static int ssl3_read_internal(SSL *s, void *buf, int len, int peek)
+	{
+	int n,ret;
+	
+	clear_sys_error();
+	if ((s->s3->flags & SSL3_FLAGS_POP_BUFFER) && (s->wbio == s->bbio))
+		{
+		/* Deal with an application that calls SSL_read() when handshake data
+		 * is yet to be written.
+		 */
+		if (BIO_wpending(s->wbio) > 0)
+			{
+			s->rwstate=SSL_WRITING;
+			n=BIO_flush(s->wbio);
+			if (n <= 0) return(n);
+			s->rwstate=SSL_NOTHING;
+			}
+		}
+	if (s->s3->renegotiate) ssl3_renegotiate_check(s);
+	s->s3->in_read_app_data=1;
+	ret=s->method->ssl_read_bytes(s,SSL3_RT_APPLICATION_DATA,buf,len,peek);
+	if ((ret == -1) && (s->s3->in_read_app_data == 2))
+		{
+		/* ssl3_read_bytes decided to call s->handshake_func, which
+		 * called ssl3_read_bytes to read handshake data.
+		 * However, ssl3_read_bytes actually found application data
+		 * and thinks that application data makes sense here; so disable
+		 * handshake processing and try to read application data again. */
+		s->in_handshake++;
+		ret=s->method->ssl_read_bytes(s,SSL3_RT_APPLICATION_DATA,buf,len,peek);
+		s->in_handshake--;
+		}
+	else
+		s->s3->in_read_app_data=0;
+
+	return(ret);
+	}
+
+int ssl3_read(SSL *s, void *buf, int len)
+	{
+	return ssl3_read_internal(s, buf, len, 0);
+	}
+
+int ssl3_peek(SSL *s, void *buf, int len)
+	{
+	return ssl3_read_internal(s, buf, len, 1);
+	}
+
+int ssl3_renegotiate(SSL *s)
+	{
+	if (s->handshake_func == NULL)
+		return(1);
+
+	if (s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)
+		return(0);
+
+	s->s3->renegotiate=1;
+	return(1);
+	}
+
+int ssl3_renegotiate_check(SSL *s)
+	{
+	int ret=0;
+
+	if (s->s3->renegotiate)
+		{
+		if (	(s->s3->rbuf.left == 0) &&
+			(s->s3->wbuf.left == 0) &&
+			!SSL_in_init(s))
+			{
+/*
+if we are the server, and we have sent a 'RENEGOTIATE' message, we
+need to go to SSL_ST_ACCEPT.
+*/
+			/* SSL_ST_ACCEPT */
+			s->state=SSL_ST_RENEGOTIATE;
+			s->s3->renegotiate=0;
+			s->s3->num_renegotiations++;
+			s->s3->total_renegotiations++;
+			ret=1;
+			}
+		}
+	return(ret);
+	}
+
diff --git a/lib/openssl/ssl/s3_meth.c b/lib/openssl/ssl/s3_meth.c
new file mode 100644
index 0000000..cdddb17
--- /dev/null
+++ b/lib/openssl/ssl/s3_meth.c
@@ -0,0 +1,77 @@
+/* ssl/s3_meth.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include <openssl/objects.h>
+#include "ssl_locl.h"
+
+static const SSL_METHOD *ssl3_get_method(int ver);
+static const SSL_METHOD *ssl3_get_method(int ver)
+	{
+	if (ver == SSL3_VERSION)
+		return(SSLv3_method());
+	else 
+		return(NULL);
+	}
+
+IMPLEMENT_ssl3_meth_func(SSLv3_method,
+			 ssl3_accept,
+			 ssl3_connect,
+			 ssl3_get_method)
+
+
diff --git a/lib/openssl/ssl/s3_pkt.c b/lib/openssl/ssl/s3_pkt.c
new file mode 100644
index 0000000..c9ef2cd
--- /dev/null
+++ b/lib/openssl/ssl/s3_pkt.c
@@ -0,0 +1,1496 @@
+/* ssl/s3_pkt.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#define USE_SOCKETS
+#include "ssl_locl.h"
+#include <openssl/evp.h>
+#include <openssl/buffer.h>
+
+static int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
+			 unsigned int len, int create_empty_fragment);
+static int ssl3_get_record(SSL *s);
+
+int ssl3_read_n(SSL *s, int n, int max, int extend)
+	{
+	/* If extend == 0, obtain new n-byte packet; if extend == 1, increase
+	 * packet by another n bytes.
+	 * The packet will be in the sub-array of s->s3->rbuf.buf specified
+	 * by s->packet and s->packet_length.
+	 * (If s->read_ahead is set, 'max' bytes may be stored in rbuf
+	 * [plus s->packet_length bytes if extend == 1].)
+	 */
+	int i,len,left;
+	long align=0;
+	unsigned char *pkt;
+	SSL3_BUFFER *rb;
+
+	if (n <= 0) return n;
+
+	rb    = &(s->s3->rbuf);
+	if (rb->buf == NULL)
+		if (!ssl3_setup_read_buffer(s))
+			return -1;
+
+	left  = rb->left;
+#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
+	align = (long)rb->buf + SSL3_RT_HEADER_LENGTH;
+	align = (-align)&(SSL3_ALIGN_PAYLOAD-1);
+#endif
+
+	if (!extend)
+		{
+		/* start with empty packet ... */
+		if (left == 0)
+			rb->offset = align;
+		else if (align != 0 && left >= SSL3_RT_HEADER_LENGTH)
+			{
+			/* check if next packet length is large
+			 * enough to justify payload alignment... */
+			pkt = rb->buf + rb->offset;
+			if (pkt[0] == SSL3_RT_APPLICATION_DATA
+			    && (pkt[3]<<8|pkt[4]) >= 128)
+				{
+				/* Note that even if packet is corrupted
+				 * and its length field is insane, we can
+				 * only be led to wrong decision about
+				 * whether memmove will occur or not.
+				 * Header values has no effect on memmove
+				 * arguments and therefore no buffer
+				 * overrun can be triggered. */
+				memmove (rb->buf+align,pkt,left);
+				rb->offset = align;
+				}
+			}
+		s->packet = rb->buf + rb->offset;
+		s->packet_length = 0;
+		/* ... now we can act as if 'extend' was set */
+		}
+
+	/* For DTLS/UDP reads should not span multiple packets
+	 * because the read operation returns the whole packet
+	 * at once (as long as it fits into the buffer). */
+	if (SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER)
+		{
+		if (left > 0 && n > left)
+			n = left;
+		}
+
+	/* if there is enough in the buffer from a previous read, take some */
+	if (left >= n)
+		{
+		s->packet_length+=n;
+		rb->left=left-n;
+		rb->offset+=n;
+		return(n);
+		}
+
+	/* else we need to read more data */
+
+	len = s->packet_length;
+	pkt = rb->buf+align;
+	/* Move any available bytes to front of buffer:
+	 * 'len' bytes already pointed to by 'packet',
+	 * 'left' extra ones at the end */
+	if (s->packet != pkt) /* len > 0 */
+		{
+		memmove(pkt, s->packet, len+left);
+		s->packet = pkt;
+		rb->offset = len + align;
+		}
+
+	if (n > (int)(rb->len - rb->offset)) /* does not happen */
+		{
+		SSLerr(SSL_F_SSL3_READ_N,ERR_R_INTERNAL_ERROR);
+		return -1;
+		}
+
+	if (!s->read_ahead)
+		/* ignore max parameter */
+		max = n;
+	else
+		{
+		if (max < n)
+			max = n;
+		if (max > (int)(rb->len - rb->offset))
+			max = rb->len - rb->offset;
+		}
+
+	while (left < n)
+		{
+		/* Now we have len+left bytes at the front of s->s3->rbuf.buf
+		 * and need to read in more until we have len+n (up to
+		 * len+max if possible) */
+
+		clear_sys_error();
+		if (s->rbio != NULL)
+			{
+			s->rwstate=SSL_READING;
+			i=BIO_read(s->rbio,pkt+len+left, max-left);
+			}
+		else
+			{
+			SSLerr(SSL_F_SSL3_READ_N,SSL_R_READ_BIO_NOT_SET);
+			i = -1;
+			}
+
+		if (i <= 0)
+			{
+			rb->left = left;
+			if (s->mode & SSL_MODE_RELEASE_BUFFERS)
+				if (len+left == 0)
+					ssl3_release_read_buffer(s);
+			return(i);
+			}
+		left+=i;
+		/* reads should *never* span multiple packets for DTLS because
+		 * the underlying transport protocol is message oriented as opposed
+		 * to byte oriented as in the TLS case. */
+		if (SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER)
+			{
+			if (n > left)
+				n = left; /* makes the while condition false */
+			}
+		}
+
+	/* done reading, now the book-keeping */
+	rb->offset += n;
+	rb->left = left - n;
+	s->packet_length += n;
+	s->rwstate=SSL_NOTHING;
+	return(n);
+	}
+
+/* Call this to get a new input record.
+ * It will return <= 0 if more data is needed, normally due to an error
+ * or non-blocking IO.
+ * When it finishes, one packet has been decoded and can be found in
+ * ssl->s3->rrec.type    - is the type of record
+ * ssl->s3->rrec.data, 	 - data
+ * ssl->s3->rrec.length, - number of bytes
+ */
+/* used only by ssl3_read_bytes */
+static int ssl3_get_record(SSL *s)
+	{
+	int ssl_major,ssl_minor,al;
+	int enc_err,n,i,ret= -1;
+	SSL3_RECORD *rr;
+	SSL_SESSION *sess;
+	unsigned char *p;
+	unsigned char md[EVP_MAX_MD_SIZE];
+	short version;
+	int mac_size;
+	int clear=0;
+	size_t extra;
+	int decryption_failed_or_bad_record_mac = 0;
+	unsigned char *mac = NULL;
+#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
+	long align=SSL3_ALIGN_PAYLOAD;
+#else
+	long align=0;
+#endif
+
+	rr= &(s->s3->rrec);
+	sess=s->session;
+
+	if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER)
+		extra=SSL3_RT_MAX_EXTRA;
+	else
+		extra=0;
+	if (!(SSL_get_mode(s) & SSL_MODE_SMALL_BUFFERS) &&
+		extra && !s->s3->init_extra)
+		{
+		/* An application error: SLS_OP_MICROSOFT_BIG_SSLV3_BUFFER
+		 * set after ssl3_setup_buffers() was done */
+		SSLerr(SSL_F_SSL3_GET_RECORD, ERR_R_INTERNAL_ERROR);
+		return -1;
+		}
+
+again:
+	/* check if we have the header */
+	if (	(s->rstate != SSL_ST_READ_BODY) ||
+		(s->packet_length < SSL3_RT_HEADER_LENGTH)) 
+		{
+		n=ssl3_read_n(s, SSL3_RT_HEADER_LENGTH, s->s3->rbuf.len, 0);
+		if (n <= 0) return(n); /* error or non-blocking */
+		s->rstate=SSL_ST_READ_BODY;
+
+		p=s->packet;
+
+		/* Pull apart the header into the SSL3_RECORD */
+		rr->type= *(p++);
+		ssl_major= *(p++);
+		ssl_minor= *(p++);
+		version=(ssl_major<<8)|ssl_minor;
+		n2s(p,rr->length);
+#if 0
+fprintf(stderr, "Record type=%d, Length=%d\n", rr->type, rr->length);
+#endif
+
+		/* Lets check version */
+		if (!s->first_packet)
+			{
+			if (version != s->version)
+				{
+				SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER);
+                                if ((s->version & 0xFF00) == (version & 0xFF00))
+                                	/* Send back error using their minor version number :-) */
+					s->version = (unsigned short)version;
+				al=SSL_AD_PROTOCOL_VERSION;
+				goto f_err;
+				}
+			}
+
+		if ((version>>8) != SSL3_VERSION_MAJOR)
+			{
+			SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER);
+			goto err;
+			}
+
+		/* If we receive a valid record larger than the current buffer size,
+		 * allocate some memory for it.
+		 */
+		if (rr->length > s->s3->rbuf.len - SSL3_RT_HEADER_LENGTH - align)
+			{
+			if ((p=OPENSSL_realloc(s->s3->rbuf.buf, rr->length + SSL3_RT_HEADER_LENGTH + align))==NULL)
+				{
+				SSLerr(SSL_F_SSL3_GET_RECORD,ERR_R_MALLOC_FAILURE);
+				goto err;
+				}
+			s->s3->rbuf.buf=p;
+			s->s3->rbuf.len=rr->length + SSL3_RT_HEADER_LENGTH + align;
+			s->packet= &(s->s3->rbuf.buf[0]);
+			}
+
+		if (rr->length > s->s3->rbuf.len - SSL3_RT_HEADER_LENGTH)
+			{
+			al=SSL_AD_RECORD_OVERFLOW;
+			SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_PACKET_LENGTH_TOO_LONG);
+			goto f_err;
+			}
+
+		/* now s->rstate == SSL_ST_READ_BODY */
+		}
+
+	/* s->rstate == SSL_ST_READ_BODY, get and decode the data */
+
+	if (rr->length > s->packet_length-SSL3_RT_HEADER_LENGTH)
+		{
+		/* now s->packet_length == SSL3_RT_HEADER_LENGTH */
+		i=rr->length;
+		n=ssl3_read_n(s,i,i,1);
+		if (n <= 0) return(n); /* error or non-blocking io */
+		/* now n == rr->length,
+		 * and s->packet_length == SSL3_RT_HEADER_LENGTH + rr->length */
+		}
+
+	s->rstate=SSL_ST_READ_HEADER; /* set state for later operations */
+
+	/* At this point, s->packet_length == SSL3_RT_HEADER_LNGTH + rr->length,
+	 * and we have that many bytes in s->packet
+	 */
+	rr->input= &(s->packet[SSL3_RT_HEADER_LENGTH]);
+
+	/* ok, we can now read from 's->packet' data into 'rr'
+	 * rr->input points at rr->length bytes, which
+	 * need to be copied into rr->data by either
+	 * the decryption or by the decompression
+	 * When the data is 'copied' into the rr->data buffer,
+	 * rr->input will be pointed at the new buffer */ 
+
+	/* We now have - encrypted [ MAC [ compressed [ plain ] ] ]
+	 * rr->length bytes of encrypted compressed stuff. */
+
+	/* check is not needed I believe */
+	if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH+extra)
+		{
+		al=SSL_AD_RECORD_OVERFLOW;
+		SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
+		goto f_err;
+		}
+
+	/* decrypt in place in 'rr->input' */
+	rr->data=rr->input;
+
+	enc_err = s->method->ssl3_enc->enc(s,0);
+	if (enc_err <= 0)
+		{
+		if (enc_err == 0)
+			/* SSLerr() and ssl3_send_alert() have been called */
+			goto err;
+
+		/* Otherwise enc_err == -1, which indicates bad padding
+		 * (rec->length has not been changed in this case).
+		 * To minimize information leaked via timing, we will perform
+		 * the MAC computation anyway. */
+		decryption_failed_or_bad_record_mac = 1;
+		}
+
+#ifdef TLS_DEBUG
+printf("dec %d\n",rr->length);
+{ unsigned int z; for (z=0; z<rr->length; z++) printf("%02X%c",rr->data[z],((z+1)%16)?' ':'\n'); }
+printf("\n");
+#endif
+
+	/* r->length is now the compressed data plus mac */
+	if (	(sess == NULL) ||
+		(s->enc_read_ctx == NULL) ||
+		(EVP_MD_CTX_md(s->read_hash) == NULL))
+		clear=1;
+
+	if (!clear)
+		{
+		/* !clear => s->read_hash != NULL => mac_size != -1 */
+		mac_size=EVP_MD_CTX_size(s->read_hash);
+		OPENSSL_assert(mac_size >= 0);
+
+		if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra+mac_size)
+			{
+#if 0 /* OK only for stream ciphers (then rr->length is visible from ciphertext anyway) */
+			al=SSL_AD_RECORD_OVERFLOW;
+			SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_PRE_MAC_LENGTH_TOO_LONG);
+			goto f_err;
+#else
+			decryption_failed_or_bad_record_mac = 1;
+#endif			
+			}
+		/* check the MAC for rr->input (it's in mac_size bytes at the tail) */
+		if (rr->length >= (unsigned int)mac_size)
+			{
+			rr->length -= mac_size;
+			mac = &rr->data[rr->length];
+			}
+		else
+			{
+			/* record (minus padding) is too short to contain a MAC */
+#if 0 /* OK only for stream ciphers */
+			al=SSL_AD_DECODE_ERROR;
+			SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_LENGTH_TOO_SHORT);
+			goto f_err;
+#else
+			decryption_failed_or_bad_record_mac = 1;
+			rr->length = 0;
+#endif
+			}
+		i=s->method->ssl3_enc->mac(s,md,0);
+		if (i < 0 || mac == NULL || memcmp(md, mac, (size_t)mac_size) != 0)
+			{
+			decryption_failed_or_bad_record_mac = 1;
+			}
+		}
+
+	if (decryption_failed_or_bad_record_mac)
+		{
+		/* A separate 'decryption_failed' alert was introduced with TLS 1.0,
+		 * SSL 3.0 only has 'bad_record_mac'.  But unless a decryption
+		 * failure is directly visible from the ciphertext anyway,
+		 * we should not reveal which kind of error occured -- this
+		 * might become visible to an attacker (e.g. via a logfile) */
+		al=SSL_AD_BAD_RECORD_MAC;
+		SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
+		goto f_err;
+		}
+
+	/* r->length is now just compressed */
+	if (s->expand != NULL)
+		{
+		if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra)
+			{
+			al=SSL_AD_RECORD_OVERFLOW;
+			SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_COMPRESSED_LENGTH_TOO_LONG);
+			goto f_err;
+			}
+		if (!ssl3_do_uncompress(s))
+			{
+			al=SSL_AD_DECOMPRESSION_FAILURE;
+			SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_BAD_DECOMPRESSION);
+			goto f_err;
+			}
+		}
+
+	if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH+extra)
+		{
+		al=SSL_AD_RECORD_OVERFLOW;
+		SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_DATA_LENGTH_TOO_LONG);
+		goto f_err;
+		}
+
+	rr->off=0;
+	/* So at this point the following is true
+	 * ssl->s3->rrec.type 	is the type of record
+	 * ssl->s3->rrec.length	== number of bytes in record
+	 * ssl->s3->rrec.off	== offset to first valid byte
+	 * ssl->s3->rrec.data	== where to take bytes from, increment
+	 *			   after use :-).
+	 */
+
+	/* we have pulled in a full packet so zero things */
+	s->packet_length=0;
+
+	/* just read a 0 length packet */
+	if (rr->length == 0) goto again;
+
+#if 0
+fprintf(stderr, "Ultimate Record type=%d, Length=%d\n", rr->type, rr->length);
+#endif
+
+	return(1);
+
+f_err:
+	ssl3_send_alert(s,SSL3_AL_FATAL,al);
+err:
+	return(ret);
+	}
+
+int ssl3_do_uncompress(SSL *ssl)
+	{
+#ifndef OPENSSL_NO_COMP
+	int i;
+	SSL3_RECORD *rr;
+
+	rr= &(ssl->s3->rrec);
+	i=COMP_expand_block(ssl->expand,rr->comp,
+		SSL3_RT_MAX_PLAIN_LENGTH,rr->data,(int)rr->length);
+	if (i < 0)
+		return(0);
+	else
+		rr->length=i;
+	rr->data=rr->comp;
+#endif
+	return(1);
+	}
+
+int ssl3_do_compress(SSL *ssl)
+	{
+#ifndef OPENSSL_NO_COMP
+	int i;
+	SSL3_RECORD *wr;
+
+	wr= &(ssl->s3->wrec);
+	i=COMP_compress_block(ssl->compress,wr->data,
+		SSL3_RT_MAX_COMPRESSED_LENGTH,
+		wr->input,(int)wr->length);
+	if (i < 0)
+		return(0);
+	else
+		wr->length=i;
+
+	wr->input=wr->data;
+#endif
+	return(1);
+	}
+
+/* Call this to write data in records of type 'type'
+ * It will return <= 0 if not all data has been sent or non-blocking IO.
+ */
+int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len)
+	{
+	const unsigned char *buf=buf_;
+	unsigned int tot,n,nw;
+	int i;
+	unsigned int max_plain_length;
+
+	s->rwstate=SSL_NOTHING;
+	tot=s->s3->wnum;
+	s->s3->wnum=0;
+
+	if (SSL_in_init(s) && !s->in_handshake)
+		{
+		i=s->handshake_func(s);
+		if (i < 0) return(i);
+		if (i == 0)
+			{
+			SSLerr(SSL_F_SSL3_WRITE_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
+			return -1;
+			}
+		}
+
+	n=(len-tot);
+	for (;;)
+		{
+		if (type == SSL3_RT_APPLICATION_DATA && (SSL_get_mode(s) & SSL_MODE_SMALL_BUFFERS))
+			max_plain_length = SSL3_RT_DEFAULT_PLAIN_LENGTH;
+		else
+			max_plain_length = s->max_send_fragment;
+
+		if (n > max_plain_length)
+			nw = max_plain_length;
+		else
+			nw=n;
+
+		i=do_ssl3_write(s, type, &(buf[tot]), nw, 0);
+		if (i <= 0)
+			{
+			s->s3->wnum=tot;
+			return i;
+			}
+
+		if ((i == (int)n) ||
+			(type == SSL3_RT_APPLICATION_DATA &&
+			 (s->mode & SSL_MODE_ENABLE_PARTIAL_WRITE)))
+			{
+			/* next chunk of data should get another prepended empty fragment
+			 * in ciphersuites with known-IV weakness: */
+			s->s3->empty_fragment_done = 0;
+			
+			return tot+i;
+			}
+
+		n-=i;
+		tot+=i;
+		}
+	}
+
+static int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
+			 unsigned int len, int create_empty_fragment)
+	{
+	unsigned char *p,*plen;
+	int i,mac_size,clear=0;
+	int prefix_len=0;
+	long align=0;
+	SSL3_RECORD *wr;
+	SSL3_BUFFER *wb=&(s->s3->wbuf);
+	SSL_SESSION *sess;
+
+ 	if (wb->buf == NULL)
+		if (!ssl3_setup_write_buffer(s))
+			return -1;
+
+	/* first check if there is a SSL3_BUFFER still being written
+	 * out.  This will happen with non blocking IO */
+	if (wb->left != 0)
+		return(ssl3_write_pending(s,type,buf,len));
+
+	/* If we have an alert to send, lets send it */
+	if (s->s3->alert_dispatch)
+		{
+		i=s->method->ssl_dispatch_alert(s);
+		if (i <= 0)
+			return(i);
+		/* if it went, fall through and send more stuff */
+		}
+
+	if (len == 0 && !create_empty_fragment)
+		return 0;
+
+	wr= &(s->s3->wrec);
+	sess=s->session;
+
+	if (	(sess == NULL) ||
+		(s->enc_write_ctx == NULL) ||
+		(EVP_MD_CTX_md(s->write_hash) == NULL))
+		clear=1;
+
+	if (clear)
+		mac_size=0;
+	else
+		{
+		mac_size=EVP_MD_CTX_size(s->write_hash);
+		if (mac_size < 0)
+			goto err;
+		}
+
+	/* 'create_empty_fragment' is true only when this function calls itself */
+	if (!clear && !create_empty_fragment && !s->s3->empty_fragment_done)
+		{
+		/* countermeasure against known-IV weakness in CBC ciphersuites
+		 * (see http://www.openssl.org/~bodo/tls-cbc.txt) */
+
+		if (s->s3->need_empty_fragments && type == SSL3_RT_APPLICATION_DATA)
+			{
+			/* recursive function call with 'create_empty_fragment' set;
+			 * this prepares and buffers the data for an empty fragment
+			 * (these 'prefix_len' bytes are sent out later
+			 * together with the actual payload) */
+			prefix_len = do_ssl3_write(s, type, buf, 0, 1);
+			if (prefix_len <= 0)
+				goto err;
+
+			if (prefix_len >
+		(SSL3_RT_HEADER_LENGTH + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD))
+				{
+				/* insufficient space */
+				SSLerr(SSL_F_DO_SSL3_WRITE, ERR_R_INTERNAL_ERROR);
+				goto err;
+				}
+			}
+		
+		s->s3->empty_fragment_done = 1;
+		}
+
+	/* resize if necessary to hold the data. */
+	if (len + SSL3_RT_DEFAULT_WRITE_OVERHEAD > wb->len)
+		{
+		if ((p=OPENSSL_realloc(wb->buf, len + SSL3_RT_DEFAULT_WRITE_OVERHEAD))==NULL)
+			{
+			SSLerr(SSL_F_DO_SSL3_WRITE,ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+		wb->buf = p;
+		wb->len = len + SSL3_RT_DEFAULT_WRITE_OVERHEAD;
+		}
+
+	if (create_empty_fragment)
+		{
+#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
+		/* extra fragment would be couple of cipher blocks,
+		 * which would be multiple of SSL3_ALIGN_PAYLOAD, so
+		 * if we want to align the real payload, then we can
+		 * just pretent we simply have two headers. */
+		align = (long)wb->buf + 2*SSL3_RT_HEADER_LENGTH;
+		align = (-align)&(SSL3_ALIGN_PAYLOAD-1);
+#endif
+		p = wb->buf + align;
+		wb->offset  = align;
+		}
+	else if (prefix_len)
+		{
+		p = wb->buf + wb->offset + prefix_len;
+		}
+	else
+		{
+#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
+		align = (long)wb->buf + SSL3_RT_HEADER_LENGTH;
+		align = (-align)&(SSL3_ALIGN_PAYLOAD-1);
+#endif
+		p = wb->buf + align;
+		wb->offset  = align;
+		}
+
+	/* write the header */
+
+	*(p++)=type&0xff;
+	wr->type=type;
+
+	*(p++)=(s->version>>8);
+	*(p++)=s->version&0xff;
+
+	/* field where we are to write out packet length */
+	plen=p; 
+	p+=2;
+
+	/* lets setup the record stuff. */
+	wr->data=p;
+	wr->length=(int)len;
+	wr->input=(unsigned char *)buf;
+
+	/* we now 'read' from wr->input, wr->length bytes into
+	 * wr->data */
+
+	/* first we compress */
+	if (s->compress != NULL)
+		{
+		if (!ssl3_do_compress(s))
+			{
+			SSLerr(SSL_F_DO_SSL3_WRITE,SSL_R_COMPRESSION_FAILURE);
+			goto err;
+			}
+		}
+	else
+		{
+		memcpy(wr->data,wr->input,wr->length);
+		wr->input=wr->data;
+		}
+
+	/* we should still have the output to wr->data and the input
+	 * from wr->input.  Length should be wr->length.
+	 * wr->data still points in the wb->buf */
+
+	if (mac_size != 0)
+		{
+		if (s->method->ssl3_enc->mac(s,&(p[wr->length]),1) < 0)
+			goto err;
+		wr->length+=mac_size;
+		wr->input=p;
+		wr->data=p;
+		}
+
+	/* ssl3_enc can only have an error on read */
+	s->method->ssl3_enc->enc(s,1);
+
+	/* record length after mac and block padding */
+	s2n(wr->length,plen);
+
+	/* we should now have
+	 * wr->data pointing to the encrypted data, which is
+	 * wr->length long */
+	wr->type=type; /* not needed but helps for debugging */
+	wr->length+=SSL3_RT_HEADER_LENGTH;
+
+	if (create_empty_fragment)
+		{
+		/* we are in a recursive call;
+		 * just return the length, don't write out anything here
+		 */
+		return wr->length;
+		}
+
+	/* now let's set up wb */
+	wb->left = prefix_len + wr->length;
+
+	/* memorize arguments so that ssl3_write_pending can detect bad write retries later */
+	s->s3->wpend_tot=len;
+	s->s3->wpend_buf=buf;
+	s->s3->wpend_type=type;
+	s->s3->wpend_ret=len;
+
+	/* we now just need to write the buffer */
+	return ssl3_write_pending(s,type,buf,len);
+err:
+	return -1;
+	}
+
+/* if s->s3->wbuf.left != 0, we need to call this */
+int ssl3_write_pending(SSL *s, int type, const unsigned char *buf,
+	unsigned int len)
+	{
+	int i;
+	SSL3_BUFFER *wb=&(s->s3->wbuf);
+
+/* XXXX */
+	if ((s->s3->wpend_tot > (int)len)
+		|| ((s->s3->wpend_buf != buf) &&
+			!(s->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER))
+		|| (s->s3->wpend_type != type))
+		{
+		SSLerr(SSL_F_SSL3_WRITE_PENDING,SSL_R_BAD_WRITE_RETRY);
+		return(-1);
+		}
+
+	for (;;)
+		{
+		clear_sys_error();
+		if (s->wbio != NULL)
+			{
+			s->rwstate=SSL_WRITING;
+			i=BIO_write(s->wbio,
+				(char *)&(wb->buf[wb->offset]),
+				(unsigned int)wb->left);
+			}
+		else
+			{
+			SSLerr(SSL_F_SSL3_WRITE_PENDING,SSL_R_BIO_NOT_SET);
+			i= -1;
+			}
+		if (i == wb->left)
+			{
+			wb->left=0;
+			wb->offset+=i;
+			if (s->mode & SSL_MODE_RELEASE_BUFFERS)
+				ssl3_release_write_buffer(s);
+			s->rwstate=SSL_NOTHING;
+			return(s->s3->wpend_ret);
+			}
+		else if (i <= 0) {
+			if (s->version == DTLS1_VERSION ||
+			    s->version == DTLS1_BAD_VER) {
+				/* For DTLS, just drop it. That's kind of the whole
+				   point in using a datagram service */
+				wb->left = 0;
+			}
+			return(i);
+		}
+		wb->offset+=i;
+		wb->left-=i;
+		}
+	}
+
+/* Return up to 'len' payload bytes received in 'type' records.
+ * 'type' is one of the following:
+ *
+ *   -  SSL3_RT_HANDSHAKE (when ssl3_get_message calls us)
+ *   -  SSL3_RT_APPLICATION_DATA (when ssl3_read calls us)
+ *   -  0 (during a shutdown, no data has to be returned)
+ *
+ * If we don't have stored data to work from, read a SSL/TLS record first
+ * (possibly multiple records if we still don't have anything to return).
+ *
+ * This function must handle any surprises the peer may have for us, such as
+ * Alert records (e.g. close_notify), ChangeCipherSpec records (not really
+ * a surprise, but handled as if it were), or renegotiation requests.
+ * Also if record payloads contain fragments too small to process, we store
+ * them until there is enough for the respective protocol (the record protocol
+ * may use arbitrary fragmentation and even interleaving):
+ *     Change cipher spec protocol
+ *             just 1 byte needed, no need for keeping anything stored
+ *     Alert protocol
+ *             2 bytes needed (AlertLevel, AlertDescription)
+ *     Handshake protocol
+ *             4 bytes needed (HandshakeType, uint24 length) -- we just have
+ *             to detect unexpected Client Hello and Hello Request messages
+ *             here, anything else is handled by higher layers
+ *     Application data protocol
+ *             none of our business
+ */
+int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
+	{
+	int al,i,j,ret;
+	unsigned int n;
+	SSL3_RECORD *rr;
+	void (*cb)(const SSL *ssl,int type2,int val)=NULL;
+
+	if (s->s3->rbuf.buf == NULL) /* Not initialized yet */
+		if (!ssl3_setup_read_buffer(s))
+			return(-1);
+
+	if ((type && (type != SSL3_RT_APPLICATION_DATA) && (type != SSL3_RT_HANDSHAKE) && type) ||
+	    (peek && (type != SSL3_RT_APPLICATION_DATA)))
+		{
+		SSLerr(SSL_F_SSL3_READ_BYTES, ERR_R_INTERNAL_ERROR);
+		return -1;
+		}
+
+	if ((type == SSL3_RT_HANDSHAKE) && (s->s3->handshake_fragment_len > 0))
+		/* (partially) satisfy request from storage */
+		{
+		unsigned char *src = s->s3->handshake_fragment;
+		unsigned char *dst = buf;
+		unsigned int k;
+
+		/* peek == 0 */
+		n = 0;
+		while ((len > 0) && (s->s3->handshake_fragment_len > 0))
+			{
+			*dst++ = *src++;
+			len--; s->s3->handshake_fragment_len--;
+			n++;
+			}
+		/* move any remaining fragment bytes: */
+		for (k = 0; k < s->s3->handshake_fragment_len; k++)
+			s->s3->handshake_fragment[k] = *src++;
+		return n;
+	}
+
+	/* Now s->s3->handshake_fragment_len == 0 if type == SSL3_RT_HANDSHAKE. */
+
+	if (!s->in_handshake && SSL_in_init(s))
+		{
+		/* type == SSL3_RT_APPLICATION_DATA */
+		i=s->handshake_func(s);
+		if (i < 0) return(i);
+		if (i == 0)
+			{
+			SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
+			return(-1);
+			}
+		}
+start:
+	s->rwstate=SSL_NOTHING;
+
+	/* s->s3->rrec.type	    - is the type of record
+	 * s->s3->rrec.data,    - data
+	 * s->s3->rrec.off,     - offset into 'data' for next read
+	 * s->s3->rrec.length,  - number of bytes. */
+	rr = &(s->s3->rrec);
+
+	/* get new packet if necessary */
+	if ((rr->length == 0) || (s->rstate == SSL_ST_READ_BODY))
+		{
+		ret=ssl3_get_record(s);
+		if (ret <= 0) return(ret);
+		}
+
+	/* we now have a packet which can be read and processed */
+
+	if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec,
+	                               * reset by ssl3_get_finished */
+		&& (rr->type != SSL3_RT_HANDSHAKE))
+		{
+		al=SSL_AD_UNEXPECTED_MESSAGE;
+		SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_DATA_BETWEEN_CCS_AND_FINISHED);
+		goto f_err;
+		}
+
+	/* If the other end has shut down, throw anything we read away
+	 * (even in 'peek' mode) */
+	if (s->shutdown & SSL_RECEIVED_SHUTDOWN)
+		{
+		rr->length=0;
+		s->rwstate=SSL_NOTHING;
+		return(0);
+		}
+
+
+	if (type == rr->type) /* SSL3_RT_APPLICATION_DATA or SSL3_RT_HANDSHAKE */
+		{
+		/* make sure that we are not getting application data when we
+		 * are doing a handshake for the first time */
+		if (SSL_in_init(s) && (type == SSL3_RT_APPLICATION_DATA) &&
+			(s->enc_read_ctx == NULL))
+			{
+			al=SSL_AD_UNEXPECTED_MESSAGE;
+			SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_APP_DATA_IN_HANDSHAKE);
+			goto f_err;
+			}
+
+		if (len <= 0) return(len);
+
+		if ((unsigned int)len > rr->length)
+			n = rr->length;
+		else
+			n = (unsigned int)len;
+
+		memcpy(buf,&(rr->data[rr->off]),n);
+		if (!peek)
+			{
+			rr->length-=n;
+			rr->off+=n;
+			if (rr->length == 0)
+				{
+				s->rstate=SSL_ST_READ_HEADER;
+				rr->off=0;
+				if (s->mode & SSL_MODE_RELEASE_BUFFERS)
+					ssl3_release_read_buffer(s);
+				}
+			}
+		return(n);
+		}
+
+
+	/* If we get here, then type != rr->type; if we have a handshake
+	 * message, then it was unexpected (Hello Request or Client Hello). */
+
+	/* In case of record types for which we have 'fragment' storage,
+	 * fill that so that we can process the data at a fixed place.
+	 */
+		{
+		unsigned int dest_maxlen = 0;
+		unsigned char *dest = NULL;
+		unsigned int *dest_len = NULL;
+
+		if (rr->type == SSL3_RT_HANDSHAKE)
+			{
+			dest_maxlen = sizeof s->s3->handshake_fragment;
+			dest = s->s3->handshake_fragment;
+			dest_len = &s->s3->handshake_fragment_len;
+			}
+		else if (rr->type == SSL3_RT_ALERT)
+			{
+			dest_maxlen = sizeof s->s3->alert_fragment;
+			dest = s->s3->alert_fragment;
+			dest_len = &s->s3->alert_fragment_len;
+			}
+
+		if (dest_maxlen > 0)
+			{
+			n = dest_maxlen - *dest_len; /* available space in 'dest' */
+			if (rr->length < n)
+				n = rr->length; /* available bytes */
+
+			/* now move 'n' bytes: */
+			while (n-- > 0)
+				{
+				dest[(*dest_len)++] = rr->data[rr->off++];
+				rr->length--;
+				}
+
+			if (*dest_len < dest_maxlen)
+				goto start; /* fragment was too small */
+			}
+		}
+
+	/* s->s3->handshake_fragment_len == 4  iff  rr->type == SSL3_RT_HANDSHAKE;
+	 * s->s3->alert_fragment_len == 2      iff  rr->type == SSL3_RT_ALERT.
+	 * (Possibly rr is 'empty' now, i.e. rr->length may be 0.) */
+
+	/* If we are a client, check for an incoming 'Hello Request': */
+	if ((!s->server) &&
+		(s->s3->handshake_fragment_len >= 4) &&
+		(s->s3->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) &&
+		(s->session != NULL) && (s->session->cipher != NULL))
+		{
+		s->s3->handshake_fragment_len = 0;
+
+		if ((s->s3->handshake_fragment[1] != 0) ||
+			(s->s3->handshake_fragment[2] != 0) ||
+			(s->s3->handshake_fragment[3] != 0))
+			{
+			al=SSL_AD_DECODE_ERROR;
+			SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_HELLO_REQUEST);
+			goto f_err;
+			}
+
+		if (s->msg_callback)
+			s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->s3->handshake_fragment, 4, s, s->msg_callback_arg);
+
+		if (SSL_is_init_finished(s) &&
+			!(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) &&
+			!s->s3->renegotiate)
+			{
+			ssl3_renegotiate(s);
+			if (ssl3_renegotiate_check(s))
+				{
+				i=s->handshake_func(s);
+				if (i < 0) return(i);
+				if (i == 0)
+					{
+					SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
+					return(-1);
+					}
+
+				if (!(s->mode & SSL_MODE_AUTO_RETRY))
+					{
+					if (s->s3->rbuf.left == 0) /* no read-ahead left? */
+						{
+						BIO *bio;
+						/* In the case where we try to read application data,
+						 * but we trigger an SSL handshake, we return -1 with
+						 * the retry option set.  Otherwise renegotiation may
+						 * cause nasty problems in the blocking world */
+						s->rwstate=SSL_READING;
+						bio=SSL_get_rbio(s);
+						BIO_clear_retry_flags(bio);
+						BIO_set_retry_read(bio);
+						return(-1);
+						}
+					}
+				}
+			}
+		/* we either finished a handshake or ignored the request,
+		 * now try again to obtain the (application) data we were asked for */
+		goto start;
+		}
+	/* If we are a server and get a client hello when renegotiation isn't
+	 * allowed send back a no renegotiation alert and carry on.
+	 * WARNING: experimental code, needs reviewing (steve)
+	 */
+	if (s->server &&
+		SSL_is_init_finished(s) &&
+    		!s->s3->send_connection_binding &&
+		(s->version > SSL3_VERSION) &&
+		(s->s3->handshake_fragment_len >= 4) &&
+		(s->s3->handshake_fragment[0] == SSL3_MT_CLIENT_HELLO) &&
+		(s->session != NULL) && (s->session->cipher != NULL) &&
+		!(s->ctx->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
+		
+		{
+		/*s->s3->handshake_fragment_len = 0;*/
+		rr->length = 0;
+		ssl3_send_alert(s,SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION);
+		goto start;
+		}
+	if (s->s3->alert_fragment_len >= 2)
+		{
+		int alert_level = s->s3->alert_fragment[0];
+		int alert_descr = s->s3->alert_fragment[1];
+
+		s->s3->alert_fragment_len = 0;
+
+		if (s->msg_callback)
+			s->msg_callback(0, s->version, SSL3_RT_ALERT, s->s3->alert_fragment, 2, s, s->msg_callback_arg);
+
+		if (s->info_callback != NULL)
+			cb=s->info_callback;
+		else if (s->ctx->info_callback != NULL)
+			cb=s->ctx->info_callback;
+
+		if (cb != NULL)
+			{
+			j = (alert_level << 8) | alert_descr;
+			cb(s, SSL_CB_READ_ALERT, j);
+			}
+
+		if (alert_level == 1) /* warning */
+			{
+			s->s3->warn_alert = alert_descr;
+			if (alert_descr == SSL_AD_CLOSE_NOTIFY)
+				{
+				s->shutdown |= SSL_RECEIVED_SHUTDOWN;
+				return(0);
+				}
+			/* This is a warning but we receive it if we requested
+			 * renegotiation and the peer denied it. Terminate with
+			 * a fatal alert because if application tried to
+			 * renegotiatie it presumably had a good reason and
+			 * expects it to succeed.
+			 *
+			 * In future we might have a renegotiation where we
+			 * don't care if the peer refused it where we carry on.
+			 */
+			else if (alert_descr == SSL_AD_NO_RENEGOTIATION)
+				{
+				al = SSL_AD_HANDSHAKE_FAILURE;
+				SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_NO_RENEGOTIATION);
+				goto f_err;
+				}
+			}
+		else if (alert_level == 2) /* fatal */
+			{
+			char tmp[16];
+
+			s->rwstate=SSL_NOTHING;
+			s->s3->fatal_alert = alert_descr;
+			SSLerr(SSL_F_SSL3_READ_BYTES, SSL_AD_REASON_OFFSET + alert_descr);
+			BIO_snprintf(tmp,sizeof tmp,"%d",alert_descr);
+			ERR_add_error_data(2,"SSL alert number ",tmp);
+			s->shutdown|=SSL_RECEIVED_SHUTDOWN;
+			SSL_CTX_remove_session(s->ctx,s->session);
+			return(0);
+			}
+		else
+			{
+			al=SSL_AD_ILLEGAL_PARAMETER;
+			SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNKNOWN_ALERT_TYPE);
+			goto f_err;
+			}
+
+		goto start;
+		}
+
+	if (s->shutdown & SSL_SENT_SHUTDOWN) /* but we have not received a shutdown */
+		{
+		s->rwstate=SSL_NOTHING;
+		rr->length=0;
+		return(0);
+		}
+
+	if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC)
+		{
+		/* 'Change Cipher Spec' is just a single byte, so we know
+		 * exactly what the record payload has to look like */
+		if (	(rr->length != 1) || (rr->off != 0) ||
+			(rr->data[0] != SSL3_MT_CCS))
+			{
+			al=SSL_AD_ILLEGAL_PARAMETER;
+			SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC);
+			goto f_err;
+			}
+
+		/* Check we have a cipher to change to */
+		if (s->s3->tmp.new_cipher == NULL)
+			{
+			al=SSL_AD_UNEXPECTED_MESSAGE;
+			SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_CCS_RECEIVED_EARLY);
+			goto f_err;
+			}
+
+		rr->length=0;
+
+		if (s->msg_callback)
+			s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, rr->data, 1, s, s->msg_callback_arg);
+
+		s->s3->change_cipher_spec=1;
+		if (!ssl3_do_change_cipher_spec(s))
+			goto err;
+		else
+			goto start;
+		}
+
+	/* Unexpected handshake message (Client Hello, or protocol violation) */
+	if ((s->s3->handshake_fragment_len >= 4) &&	!s->in_handshake)
+		{
+		if (((s->state&SSL_ST_MASK) == SSL_ST_OK) &&
+			!(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS))
+			{
+#if 0 /* worked only because C operator preferences are not as expected (and
+       * because this is not really needed for clients except for detecting
+       * protocol violations): */
+			s->state=SSL_ST_BEFORE|(s->server)
+				?SSL_ST_ACCEPT
+				:SSL_ST_CONNECT;
+#else
+			s->state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT;
+#endif
+			s->new_session=1;
+			}
+		i=s->handshake_func(s);
+		if (i < 0) return(i);
+		if (i == 0)
+			{
+			SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
+			return(-1);
+			}
+
+		if (!(s->mode & SSL_MODE_AUTO_RETRY))
+			{
+			if (s->s3->rbuf.left == 0) /* no read-ahead left? */
+				{
+				BIO *bio;
+				/* In the case where we try to read application data,
+				 * but we trigger an SSL handshake, we return -1 with
+				 * the retry option set.  Otherwise renegotiation may
+				 * cause nasty problems in the blocking world */
+				s->rwstate=SSL_READING;
+				bio=SSL_get_rbio(s);
+				BIO_clear_retry_flags(bio);
+				BIO_set_retry_read(bio);
+				return(-1);
+				}
+			}
+		goto start;
+		}
+
+	switch (rr->type)
+		{
+	default:
+#ifndef OPENSSL_NO_TLS
+		/* TLS just ignores unknown message types */
+		if (s->version == TLS1_VERSION)
+			{
+			rr->length = 0;
+			goto start;
+			}
+#endif
+		al=SSL_AD_UNEXPECTED_MESSAGE;
+		SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
+		goto f_err;
+	case SSL3_RT_CHANGE_CIPHER_SPEC:
+	case SSL3_RT_ALERT:
+	case SSL3_RT_HANDSHAKE:
+		/* we already handled all of these, with the possible exception
+		 * of SSL3_RT_HANDSHAKE when s->in_handshake is set, but that
+		 * should not happen when type != rr->type */
+		al=SSL_AD_UNEXPECTED_MESSAGE;
+		SSLerr(SSL_F_SSL3_READ_BYTES,ERR_R_INTERNAL_ERROR);
+		goto f_err;
+	case SSL3_RT_APPLICATION_DATA:
+		/* At this point, we were expecting handshake data,
+		 * but have application data.  If the library was
+		 * running inside ssl3_read() (i.e. in_read_app_data
+		 * is set) and it makes sense to read application data
+		 * at this point (session renegotiation not yet started),
+		 * we will indulge it.
+		 */
+		if (s->s3->in_read_app_data &&
+			(s->s3->total_renegotiations != 0) &&
+			((
+				(s->state & SSL_ST_CONNECT) &&
+				(s->state >= SSL3_ST_CW_CLNT_HELLO_A) &&
+				(s->state <= SSL3_ST_CR_SRVR_HELLO_A)
+				) || (
+					(s->state & SSL_ST_ACCEPT) &&
+					(s->state <= SSL3_ST_SW_HELLO_REQ_A) &&
+					(s->state >= SSL3_ST_SR_CLNT_HELLO_A)
+					)
+				))
+			{
+			s->s3->in_read_app_data=2;
+			return(-1);
+			}
+		else
+			{
+			al=SSL_AD_UNEXPECTED_MESSAGE;
+			SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
+			goto f_err;
+			}
+		}
+	/* not reached */
+
+f_err:
+	ssl3_send_alert(s,SSL3_AL_FATAL,al);
+err:
+	return(-1);
+	}
+
+int ssl3_do_change_cipher_spec(SSL *s)
+	{
+	int i;
+	const char *sender;
+	int slen;
+
+	if (s->state & SSL_ST_ACCEPT)
+		i=SSL3_CHANGE_CIPHER_SERVER_READ;
+	else
+		i=SSL3_CHANGE_CIPHER_CLIENT_READ;
+
+	if (s->s3->tmp.key_block == NULL)
+		{
+		if (s->session == NULL) 
+			{
+			/* might happen if dtls1_read_bytes() calls this */
+			SSLerr(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC,SSL_R_CCS_RECEIVED_EARLY);
+			return (0);
+			}
+
+		s->session->cipher=s->s3->tmp.new_cipher;
+		if (!s->method->ssl3_enc->setup_key_block(s)) return(0);
+		}
+
+	if (!s->method->ssl3_enc->change_cipher_state(s,i))
+		return(0);
+
+	/* we have to record the message digest at
+	 * this point so we can get it before we read
+	 * the finished message */
+	if (s->state & SSL_ST_CONNECT)
+		{
+		sender=s->method->ssl3_enc->server_finished_label;
+		slen=s->method->ssl3_enc->server_finished_label_len;
+		}
+	else
+		{
+		sender=s->method->ssl3_enc->client_finished_label;
+		slen=s->method->ssl3_enc->client_finished_label_len;
+		}
+
+	s->s3->tmp.peer_finish_md_len = s->method->ssl3_enc->final_finish_mac(s,
+		sender,slen,s->s3->tmp.peer_finish_md);
+
+	return(1);
+	}
+
+int ssl3_send_alert(SSL *s, int level, int desc)
+	{
+	/* Map tls/ssl alert value to correct one */
+	desc=s->method->ssl3_enc->alert_value(desc);
+	if (s->version == SSL3_VERSION && desc == SSL_AD_PROTOCOL_VERSION)
+		desc = SSL_AD_HANDSHAKE_FAILURE; /* SSL 3.0 does not have protocol_version alerts */
+	if (desc < 0) return -1;
+	/* If a fatal one, remove from cache */
+	if ((level == 2) && (s->session != NULL))
+		SSL_CTX_remove_session(s->ctx,s->session);
+
+	s->s3->alert_dispatch=1;
+	s->s3->send_alert[0]=level;
+	s->s3->send_alert[1]=desc;
+	if (s->s3->wbuf.left == 0) /* data still being written out? */
+		return s->method->ssl_dispatch_alert(s);
+	/* else data is still being written out, we will get written
+	 * some time in the future */
+	return -1;
+	}
+
+int ssl3_dispatch_alert(SSL *s)
+	{
+	int i,j;
+	void (*cb)(const SSL *ssl,int type,int val)=NULL;
+
+	s->s3->alert_dispatch=0;
+	i = do_ssl3_write(s, SSL3_RT_ALERT, &s->s3->send_alert[0], 2, 0);
+	if (i <= 0)
+		{
+		s->s3->alert_dispatch=1;
+		}
+	else
+		{
+		/* Alert sent to BIO.  If it is important, flush it now.
+		 * If the message does not get sent due to non-blocking IO,
+		 * we will not worry too much. */
+		if (s->s3->send_alert[0] == SSL3_AL_FATAL)
+			(void)BIO_flush(s->wbio);
+
+		if (s->msg_callback)
+			s->msg_callback(1, s->version, SSL3_RT_ALERT, s->s3->send_alert, 2, s, s->msg_callback_arg);
+
+		if (s->info_callback != NULL)
+			cb=s->info_callback;
+		else if (s->ctx->info_callback != NULL)
+			cb=s->ctx->info_callback;
+
+		if (cb != NULL)
+			{
+			j=(s->s3->send_alert[0]<<8)|s->s3->send_alert[1];
+			cb(s,SSL_CB_WRITE_ALERT,j);
+			}
+		}
+	return(i);
+	}
diff --git a/lib/openssl/ssl/s3_srvr.c b/lib/openssl/ssl/s3_srvr.c
new file mode 100644
index 0000000..0d3b536
--- /dev/null
+++ b/lib/openssl/ssl/s3_srvr.c
@@ -0,0 +1,3192 @@
+/* ssl/s3_srvr.c -*- mode:C; c-file-style: "eay" -*- */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * Portions of the attached software ("Contribution") are developed by 
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the OpenSSL open source
+ * license provided above.
+ *
+ * ECC cipher suite support in OpenSSL originally written by
+ * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
+ *
+ */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#define REUSE_CIPHER_BUG
+#define NETSCAPE_HANG_BUG
+
+#include <stdio.h>
+#include "ssl_locl.h"
+#include "kssl_lcl.h"
+#include <openssl/buffer.h>
+#include <openssl/rand.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/x509.h>
+#ifndef OPENSSL_NO_DH
+#include <openssl/dh.h>
+#endif
+#include <openssl/bn.h>
+#ifndef OPENSSL_NO_KRB5
+#include <openssl/krb5_asn.h>
+#endif
+#include <openssl/md5.h>
+
+static const SSL_METHOD *ssl3_get_server_method(int ver);
+
+static const SSL_METHOD *ssl3_get_server_method(int ver)
+	{
+	if (ver == SSL3_VERSION)
+		return(SSLv3_server_method());
+	else
+		return(NULL);
+	}
+
+IMPLEMENT_ssl3_meth_func(SSLv3_server_method,
+			ssl3_accept,
+			ssl_undefined_function,
+			ssl3_get_server_method)
+
+int ssl3_accept(SSL *s)
+	{
+	BUF_MEM *buf;
+	unsigned long alg_k,Time=(unsigned long)time(NULL);
+	void (*cb)(const SSL *ssl,int type,int val)=NULL;
+	int ret= -1;
+	int new_state,state,skip=0;
+
+	RAND_add(&Time,sizeof(Time),0);
+	ERR_clear_error();
+	clear_sys_error();
+
+	if (s->info_callback != NULL)
+		cb=s->info_callback;
+	else if (s->ctx->info_callback != NULL)
+		cb=s->ctx->info_callback;
+
+	/* init things to blank */
+	s->in_handshake++;
+	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);
+
+	if (s->cert == NULL)
+		{
+		SSLerr(SSL_F_SSL3_ACCEPT,SSL_R_NO_CERTIFICATE_SET);
+		return(-1);
+		}
+
+	for (;;)
+		{
+		state=s->state;
+
+		switch (s->state)
+			{
+		case SSL_ST_RENEGOTIATE:
+			s->new_session=1;
+			/* s->state=SSL_ST_ACCEPT; */
+
+		case SSL_ST_BEFORE:
+		case SSL_ST_ACCEPT:
+		case SSL_ST_BEFORE|SSL_ST_ACCEPT:
+		case SSL_ST_OK|SSL_ST_ACCEPT:
+
+			s->server=1;
+			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
+
+			if ((s->version>>8) != 3)
+				{
+				SSLerr(SSL_F_SSL3_ACCEPT, ERR_R_INTERNAL_ERROR);
+				return -1;
+				}
+			s->type=SSL_ST_ACCEPT;
+
+			if (s->init_buf == NULL)
+				{
+				if ((buf=BUF_MEM_new()) == NULL)
+					{
+					ret= -1;
+					goto end;
+					}
+				if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH))
+					{
+					ret= -1;
+					goto end;
+					}
+				s->init_buf=buf;
+				}
+
+			if (!ssl3_setup_buffers(s))
+				{
+				ret= -1;
+				goto end;
+				}
+
+			s->init_num=0;
+
+			if (s->state != SSL_ST_RENEGOTIATE)
+				{
+				/* Ok, we now need to push on a buffering BIO so that
+				 * the output is sent in a way that TCP likes :-)
+				 */
+				if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; }
+				
+				ssl3_init_finished_mac(s);
+				s->state=SSL3_ST_SR_CLNT_HELLO_A;
+				s->ctx->stats.sess_accept++;
+				}
+			else if (!s->s3->send_connection_binding &&
+				!(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
+				{
+				/* Server attempting to renegotiate with
+				 * client that doesn't support secure
+				 * renegotiation.
+				 */
+				SSLerr(SSL_F_SSL3_ACCEPT, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
+				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
+				ret = -1;
+				goto end;
+				}
+			else
+				{
+				/* s->state == SSL_ST_RENEGOTIATE,
+				 * we will just send a HelloRequest */
+				s->ctx->stats.sess_accept_renegotiate++;
+				s->state=SSL3_ST_SW_HELLO_REQ_A;
+				}
+			break;
+
+		case SSL3_ST_SW_HELLO_REQ_A:
+		case SSL3_ST_SW_HELLO_REQ_B:
+
+			s->shutdown=0;
+			ret=ssl3_send_hello_request(s);
+			if (ret <= 0) goto end;
+			s->s3->tmp.next_state=SSL3_ST_SW_HELLO_REQ_C;
+			s->state=SSL3_ST_SW_FLUSH;
+			s->init_num=0;
+
+			ssl3_init_finished_mac(s);
+			break;
+
+		case SSL3_ST_SW_HELLO_REQ_C:
+			s->state=SSL_ST_OK;
+			break;
+
+		case SSL3_ST_SR_CLNT_HELLO_A:
+		case SSL3_ST_SR_CLNT_HELLO_B:
+		case SSL3_ST_SR_CLNT_HELLO_C:
+
+			s->shutdown=0;
+			ret=ssl3_get_client_hello(s);
+			if (ret <= 0) goto end;
+			
+			s->new_session = 2;
+			s->state=SSL3_ST_SW_SRVR_HELLO_A;
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_SW_SRVR_HELLO_A:
+		case SSL3_ST_SW_SRVR_HELLO_B:
+			ret=ssl3_send_server_hello(s);
+			if (ret <= 0) goto end;
+#ifndef OPENSSL_NO_TLSEXT
+			if (s->hit)
+				{
+				if (s->tlsext_ticket_expected)
+					s->state=SSL3_ST_SW_SESSION_TICKET_A;
+				else
+					s->state=SSL3_ST_SW_CHANGE_A;
+				}
+#else
+			if (s->hit)
+					s->state=SSL3_ST_SW_CHANGE_A;
+#endif
+			else
+				s->state=SSL3_ST_SW_CERT_A;
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_SW_CERT_A:
+		case SSL3_ST_SW_CERT_B:
+			/* Check if it is anon DH or anon ECDH, */
+			/* normal PSK or KRB5 */
+			if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)
+				&& !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)
+				&& !(s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5))
+				{
+				ret=ssl3_send_server_certificate(s);
+				if (ret <= 0) goto end;
+#ifndef OPENSSL_NO_TLSEXT
+				if (s->tlsext_status_expected)
+					s->state=SSL3_ST_SW_CERT_STATUS_A;
+				else
+					s->state=SSL3_ST_SW_KEY_EXCH_A;
+				}
+			else
+				{
+				skip = 1;
+				s->state=SSL3_ST_SW_KEY_EXCH_A;
+				}
+#else
+				}
+			else
+				skip=1;
+
+			s->state=SSL3_ST_SW_KEY_EXCH_A;
+#endif
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_SW_KEY_EXCH_A:
+		case SSL3_ST_SW_KEY_EXCH_B:
+			alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+
+			/* clear this, it may get reset by
+			 * send_server_key_exchange */
+			if ((s->options & SSL_OP_EPHEMERAL_RSA)
+#ifndef OPENSSL_NO_KRB5
+				&& !(alg_k & SSL_kKRB5)
+#endif /* OPENSSL_NO_KRB5 */
+				)
+				/* option SSL_OP_EPHEMERAL_RSA sends temporary RSA key
+				 * even when forbidden by protocol specs
+				 * (handshake may fail as clients are not required to
+				 * be able to handle this) */
+				s->s3->tmp.use_rsa_tmp=1;
+			else
+				s->s3->tmp.use_rsa_tmp=0;
+
+
+			/* only send if a DH key exchange, fortezza or
+			 * RSA but we have a sign only certificate
+			 *
+			 * PSK: may send PSK identity hints
+			 *
+			 * For ECC ciphersuites, we send a serverKeyExchange
+			 * message only if the cipher suite is either
+			 * ECDH-anon or ECDHE. In other cases, the
+			 * server certificate contains the server's
+			 * public key for key exchange.
+			 */
+			if (s->s3->tmp.use_rsa_tmp
+			/* PSK: send ServerKeyExchange if PSK identity
+			 * hint if provided */
+#ifndef OPENSSL_NO_PSK
+			    || ((alg_k & SSL_kPSK) && s->ctx->psk_identity_hint)
+#endif
+			    || (alg_k & (SSL_kDHr|SSL_kDHd|SSL_kEDH))
+			    || (alg_k & SSL_kEECDH)
+			    || ((alg_k & SSL_kRSA)
+				&& (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL
+				    || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher)
+					&& EVP_PKEY_size(s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)
+					)
+				    )
+				)
+			    )
+				{
+				ret=ssl3_send_server_key_exchange(s);
+				if (ret <= 0) goto end;
+				}
+			else
+				skip=1;
+
+			s->state=SSL3_ST_SW_CERT_REQ_A;
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_SW_CERT_REQ_A:
+		case SSL3_ST_SW_CERT_REQ_B:
+			if (/* don't request cert unless asked for it: */
+				!(s->verify_mode & SSL_VERIFY_PEER) ||
+				/* if SSL_VERIFY_CLIENT_ONCE is set,
+				 * don't request cert during re-negotiation: */
+				((s->session->peer != NULL) &&
+				 (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) ||
+				/* never request cert in anonymous ciphersuites
+				 * (see section "Certificate request" in SSL 3 drafts
+				 * and in RFC 2246): */
+				((s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) &&
+				 /* ... except when the application insists on verification
+				  * (against the specs, but s3_clnt.c accepts this for SSL 3) */
+				 !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) ||
+				 /* never request cert in Kerberos ciphersuites */
+				(s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5)
+				/* With normal PSK Certificates and
+				 * Certificate Requests are omitted */
+				|| (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
+				{
+				/* no cert request */
+				skip=1;
+				s->s3->tmp.cert_request=0;
+				s->state=SSL3_ST_SW_SRVR_DONE_A;
+				}
+			else
+				{
+				s->s3->tmp.cert_request=1;
+				ret=ssl3_send_certificate_request(s);
+				if (ret <= 0) goto end;
+#ifndef NETSCAPE_HANG_BUG
+				s->state=SSL3_ST_SW_SRVR_DONE_A;
+#else
+				s->state=SSL3_ST_SW_FLUSH;
+				s->s3->tmp.next_state=SSL3_ST_SR_CERT_A;
+#endif
+				s->init_num=0;
+				}
+			break;
+
+		case SSL3_ST_SW_SRVR_DONE_A:
+		case SSL3_ST_SW_SRVR_DONE_B:
+			ret=ssl3_send_server_done(s);
+			if (ret <= 0) goto end;
+			s->s3->tmp.next_state=SSL3_ST_SR_CERT_A;
+			s->state=SSL3_ST_SW_FLUSH;
+			s->init_num=0;
+			break;
+		
+		case SSL3_ST_SW_FLUSH:
+
+			/* This code originally checked to see if
+			 * any data was pending using BIO_CTRL_INFO
+			 * and then flushed. This caused problems
+			 * as documented in PR#1939. The proposed
+			 * fix doesn't completely resolve this issue
+			 * as buggy implementations of BIO_CTRL_PENDING
+			 * still exist. So instead we just flush
+			 * unconditionally.
+			 */
+
+			s->rwstate=SSL_WRITING;
+			if (BIO_flush(s->wbio) <= 0)
+				{
+				ret= -1;
+				goto end;
+				}
+			s->rwstate=SSL_NOTHING;
+
+			s->state=s->s3->tmp.next_state;
+			break;
+
+		case SSL3_ST_SR_CERT_A:
+		case SSL3_ST_SR_CERT_B:
+			/* Check for second client hello (MS SGC) */
+			ret = ssl3_check_client_hello(s);
+			if (ret <= 0)
+				goto end;
+			if (ret == 2)
+				s->state = SSL3_ST_SR_CLNT_HELLO_C;
+			else {
+				if (s->s3->tmp.cert_request)
+					{
+					ret=ssl3_get_client_certificate(s);
+					if (ret <= 0) goto end;
+					}
+				s->init_num=0;
+				s->state=SSL3_ST_SR_KEY_EXCH_A;
+			}
+			break;
+
+		case SSL3_ST_SR_KEY_EXCH_A:
+		case SSL3_ST_SR_KEY_EXCH_B:
+			ret=ssl3_get_client_key_exchange(s);
+			if (ret <= 0)
+				goto end;
+			if (ret == 2)
+				{
+				/* For the ECDH ciphersuites when
+				 * the client sends its ECDH pub key in
+				 * a certificate, the CertificateVerify
+				 * message is not sent.
+				 * Also for GOST ciphersuites when
+				 * the client uses its key from the certificate
+				 * for key exchange.
+				 */
+				s->state=SSL3_ST_SR_FINISHED_A;
+				s->init_num = 0;
+				}
+			else
+				{
+				int offset=0;
+				int dgst_num;
+
+				s->state=SSL3_ST_SR_CERT_VRFY_A;
+				s->init_num=0;
+
+				/* We need to get hashes here so if there is
+				 * a client cert, it can be verified
+				 * FIXME - digest processing for CertificateVerify
+				 * should be generalized. But it is next step
+				 */
+				if (s->s3->handshake_buffer)
+					if (!ssl3_digest_cached_records(s))
+						return -1;
+				for (dgst_num=0; dgst_num<SSL_MAX_DIGEST;dgst_num++)	
+					if (s->s3->handshake_dgst[dgst_num]) 
+						{
+						int dgst_size;
+
+						s->method->ssl3_enc->cert_verify_mac(s,EVP_MD_CTX_type(s->s3->handshake_dgst[dgst_num]),&(s->s3->tmp.cert_verify_md[offset]));
+						dgst_size=EVP_MD_CTX_size(s->s3->handshake_dgst[dgst_num]);
+						if (dgst_size < 0)
+							{
+							ret = -1;
+							goto end;
+							}
+						offset+=dgst_size;
+						}		
+				}
+			break;
+
+		case SSL3_ST_SR_CERT_VRFY_A:
+		case SSL3_ST_SR_CERT_VRFY_B:
+
+			/* we should decide if we expected this one */
+			ret=ssl3_get_cert_verify(s);
+			if (ret <= 0) goto end;
+
+			s->state=SSL3_ST_SR_FINISHED_A;
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_SR_FINISHED_A:
+		case SSL3_ST_SR_FINISHED_B:
+			ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A,
+				SSL3_ST_SR_FINISHED_B);
+			if (ret <= 0) goto end;
+#ifndef OPENSSL_NO_TLSEXT
+			if (s->tlsext_ticket_expected)
+				s->state=SSL3_ST_SW_SESSION_TICKET_A;
+			else if (s->hit)
+				s->state=SSL_ST_OK;
+#else
+			if (s->hit)
+				s->state=SSL_ST_OK;
+#endif
+			else
+				s->state=SSL3_ST_SW_CHANGE_A;
+			s->init_num=0;
+			break;
+
+#ifndef OPENSSL_NO_TLSEXT
+		case SSL3_ST_SW_SESSION_TICKET_A:
+		case SSL3_ST_SW_SESSION_TICKET_B:
+			ret=ssl3_send_newsession_ticket(s);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_SW_CHANGE_A;
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_SW_CERT_STATUS_A:
+		case SSL3_ST_SW_CERT_STATUS_B:
+			ret=ssl3_send_cert_status(s);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_SW_KEY_EXCH_A;
+			s->init_num=0;
+			break;
+
+#endif
+
+		case SSL3_ST_SW_CHANGE_A:
+		case SSL3_ST_SW_CHANGE_B:
+
+			s->session->cipher=s->s3->tmp.new_cipher;
+			if (!s->method->ssl3_enc->setup_key_block(s))
+				{ ret= -1; goto end; }
+
+			ret=ssl3_send_change_cipher_spec(s,
+				SSL3_ST_SW_CHANGE_A,SSL3_ST_SW_CHANGE_B);
+
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_SW_FINISHED_A;
+			s->init_num=0;
+
+			if (!s->method->ssl3_enc->change_cipher_state(s,
+				SSL3_CHANGE_CIPHER_SERVER_WRITE))
+				{
+				ret= -1;
+				goto end;
+				}
+
+			break;
+
+		case SSL3_ST_SW_FINISHED_A:
+		case SSL3_ST_SW_FINISHED_B:
+			ret=ssl3_send_finished(s,
+				SSL3_ST_SW_FINISHED_A,SSL3_ST_SW_FINISHED_B,
+				s->method->ssl3_enc->server_finished_label,
+				s->method->ssl3_enc->server_finished_label_len);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_SW_FLUSH;
+			if (s->hit)
+				s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A;
+			else
+				s->s3->tmp.next_state=SSL_ST_OK;
+			s->init_num=0;
+			break;
+
+		case SSL_ST_OK:
+			/* clean a few things up */
+			ssl3_cleanup_key_block(s);
+
+			BUF_MEM_free(s->init_buf);
+			s->init_buf=NULL;
+
+			/* remove buffering on output */
+			ssl_free_wbio_buffer(s);
+
+			s->init_num=0;
+
+			if (s->new_session == 2) /* skipped if we just sent a HelloRequest */
+				{
+				/* actually not necessarily a 'new' session unless
+				 * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */
+				
+				s->new_session=0;
+				
+				ssl_update_cache(s,SSL_SESS_CACHE_SERVER);
+				
+				s->ctx->stats.sess_accept_good++;
+				/* s->server=1; */
+				s->handshake_func=ssl3_accept;
+
+				if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1);
+				}
+			
+			ret = 1;
+			goto end;
+			/* break; */
+
+		default:
+			SSLerr(SSL_F_SSL3_ACCEPT,SSL_R_UNKNOWN_STATE);
+			ret= -1;
+			goto end;
+			/* break; */
+			}
+		
+		if (!s->s3->tmp.reuse_message && !skip)
+			{
+			if (s->debug)
+				{
+				if ((ret=BIO_flush(s->wbio)) <= 0)
+					goto end;
+				}
+
+
+			if ((cb != NULL) && (s->state != state))
+				{
+				new_state=s->state;
+				s->state=state;
+				cb(s,SSL_CB_ACCEPT_LOOP,1);
+				s->state=new_state;
+				}
+			}
+		skip=0;
+		}
+end:
+	/* BIO_flush(s->wbio); */
+
+	s->in_handshake--;
+	if (cb != NULL)
+		cb(s,SSL_CB_ACCEPT_EXIT,ret);
+	return(ret);
+	}
+
+int ssl3_send_hello_request(SSL *s)
+	{
+	unsigned char *p;
+
+	if (s->state == SSL3_ST_SW_HELLO_REQ_A)
+		{
+		p=(unsigned char *)s->init_buf->data;
+		*(p++)=SSL3_MT_HELLO_REQUEST;
+		*(p++)=0;
+		*(p++)=0;
+		*(p++)=0;
+
+		s->state=SSL3_ST_SW_HELLO_REQ_B;
+		/* number of bytes to write */
+		s->init_num=4;
+		s->init_off=0;
+		}
+
+	/* SSL3_ST_SW_HELLO_REQ_B */
+	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+	}
+
+int ssl3_check_client_hello(SSL *s)
+	{
+	int ok;
+	long n;
+
+	/* this function is called when we really expect a Certificate message,
+	 * so permit appropriate message length */
+	n=s->method->ssl_get_message(s,
+		SSL3_ST_SR_CERT_A,
+		SSL3_ST_SR_CERT_B,
+		-1,
+		s->max_cert_list,
+		&ok);
+	if (!ok) return((int)n);
+	s->s3->tmp.reuse_message = 1;
+	if (s->s3->tmp.message_type == SSL3_MT_CLIENT_HELLO)
+		{
+		/* Throw away what we have done so far in the current handshake,
+		 * which will now be aborted. (A full SSL_clear would be too much.)
+		 * I hope that tmp.dh is the only thing that may need to be cleared
+		 * when a handshake is not completed ... */
+#ifndef OPENSSL_NO_DH
+		if (s->s3->tmp.dh != NULL)
+			{
+			DH_free(s->s3->tmp.dh);
+			s->s3->tmp.dh = NULL;
+			}
+#endif
+		return 2;
+		}
+	return 1;
+}
+
+int ssl3_get_client_hello(SSL *s)
+	{
+	int i,j,ok,al,ret= -1;
+	unsigned int cookie_len;
+	long n;
+	unsigned long id;
+	unsigned char *p,*d,*q;
+	SSL_CIPHER *c;
+#ifndef OPENSSL_NO_COMP
+	SSL_COMP *comp=NULL;
+#endif
+	STACK_OF(SSL_CIPHER) *ciphers=NULL;
+
+	/* We do this so that we will respond with our native type.
+	 * If we are TLSv1 and we get SSLv3, we will respond with TLSv1,
+	 * This down switching should be handled by a different method.
+	 * If we are SSLv3, we will respond with SSLv3, even if prompted with
+	 * TLSv1.
+	 */
+	if (s->state == SSL3_ST_SR_CLNT_HELLO_A)
+		{
+		s->state=SSL3_ST_SR_CLNT_HELLO_B;
+		}
+	s->first_packet=1;
+	n=s->method->ssl_get_message(s,
+		SSL3_ST_SR_CLNT_HELLO_B,
+		SSL3_ST_SR_CLNT_HELLO_C,
+		SSL3_MT_CLIENT_HELLO,
+		SSL3_RT_MAX_PLAIN_LENGTH,
+		&ok);
+
+	if (!ok) return((int)n);
+	s->first_packet=0;
+	d=p=(unsigned char *)s->init_msg;
+
+	/* use version from inside client hello, not from record header
+	 * (may differ: see RFC 2246, Appendix E, second paragraph) */
+	s->client_version=(((int)p[0])<<8)|(int)p[1];
+	p+=2;
+
+	if ((s->version == DTLS1_VERSION && s->client_version > s->version) ||
+	    (s->version != DTLS1_VERSION && s->client_version < s->version))
+		{
+		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_WRONG_VERSION_NUMBER);
+		if ((s->client_version>>8) == SSL3_VERSION_MAJOR)
+			{
+			/* similar to ssl3_get_record, send alert using remote version number */
+			s->version = s->client_version;
+			}
+		al = SSL_AD_PROTOCOL_VERSION;
+		goto f_err;
+		}
+
+	/* If we require cookies and this ClientHello doesn't
+	 * contain one, just return since we do not want to
+	 * allocate any memory yet. So check cookie length...
+	 */
+	if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)
+		{
+		unsigned int session_length, cookie_length;
+		
+		session_length = *(p + SSL3_RANDOM_SIZE);
+		cookie_length = *(p + SSL3_RANDOM_SIZE + session_length + 1);
+
+		if (cookie_length == 0)
+			return 1;
+		}
+
+	/* load the client random */
+	memcpy(s->s3->client_random,p,SSL3_RANDOM_SIZE);
+	p+=SSL3_RANDOM_SIZE;
+
+	/* get the session-id */
+	j= *(p++);
+
+	s->hit=0;
+	/* Versions before 0.9.7 always allow session reuse during renegotiation
+	 * (i.e. when s->new_session is true), option
+	 * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is new with 0.9.7.
+	 * Maybe this optional behaviour should always have been the default,
+	 * but we cannot safely change the default behaviour (or new applications
+	 * might be written that become totally unsecure when compiled with
+	 * an earlier library version)
+	 */
+	if ((s->new_session && (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)))
+		{
+	        if (!s->session_creation_enabled)
+			{
+			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
+			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_SESSION_MAY_NOT_BE_CREATED);
+			goto err;
+		}
+		if (!ssl_get_new_session(s,1))
+			goto err;
+		}
+	else
+		{
+		i=ssl_get_prev_session(s, p, j, d + n);
+		if (i == 1)
+			{ /* previous session */
+			s->hit=1;
+			}
+		else if (i == -1)
+			goto err;
+		else /* i == 0 */
+			{
+		        if (!s->session_creation_enabled)
+				{
+				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
+				SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_SESSION_MAY_NOT_BE_CREATED);
+				goto err;
+				}
+			if (!ssl_get_new_session(s,1))
+				goto err;
+			}
+		}
+
+	p+=j;
+
+	if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER)
+		{
+		/* cookie stuff */
+		cookie_len = *(p++);
+
+		/* 
+		 * The ClientHello may contain a cookie even if the
+		 * HelloVerify message has not been sent--make sure that it
+		 * does not cause an overflow.
+		 */
+		if ( cookie_len > sizeof(s->d1->rcvd_cookie))
+			{
+			/* too much data */
+			al = SSL_AD_DECODE_ERROR;
+			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_COOKIE_MISMATCH);
+			goto f_err;
+			}
+
+		/* verify the cookie if appropriate option is set. */
+		if ((SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) &&
+			cookie_len > 0)
+			{
+			memcpy(s->d1->rcvd_cookie, p, cookie_len);
+
+			if ( s->ctx->app_verify_cookie_cb != NULL)
+				{
+				if ( s->ctx->app_verify_cookie_cb(s, s->d1->rcvd_cookie,
+					cookie_len) == 0)
+					{
+					al=SSL_AD_HANDSHAKE_FAILURE;
+					SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, 
+						SSL_R_COOKIE_MISMATCH);
+					goto f_err;
+					}
+				/* else cookie verification succeeded */
+				}
+			else if ( memcmp(s->d1->rcvd_cookie, s->d1->cookie, 
+						  s->d1->cookie_len) != 0) /* default verification */
+				{
+					al=SSL_AD_HANDSHAKE_FAILURE;
+					SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, 
+						SSL_R_COOKIE_MISMATCH);
+					goto f_err;
+				}
+
+			ret = 2;
+			}
+
+		p += cookie_len;
+		}
+
+	n2s(p,i);
+	if ((i == 0) && (j != 0))
+		{
+		/* we need a cipher if we are not resuming a session */
+		al=SSL_AD_ILLEGAL_PARAMETER;
+		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_CIPHERS_SPECIFIED);
+		goto f_err;
+		}
+	if ((p+i) >= (d+n))
+		{
+		/* not enough data */
+		al=SSL_AD_DECODE_ERROR;
+		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_LENGTH_MISMATCH);
+		goto f_err;
+		}
+	if ((i > 0) && (ssl_bytes_to_cipher_list(s,p,i,&(ciphers))
+		== NULL))
+		{
+		goto err;
+		}
+	p+=i;
+
+	/* If it is a hit, check that the cipher is in the list */
+	if ((s->hit) && (i > 0))
+		{
+		j=0;
+		id=s->session->cipher->id;
+
+#ifdef CIPHER_DEBUG
+		printf("client sent %d ciphers\n",sk_num(ciphers));
+#endif
+		for (i=0; i<sk_SSL_CIPHER_num(ciphers); i++)
+			{
+			c=sk_SSL_CIPHER_value(ciphers,i);
+#ifdef CIPHER_DEBUG
+			printf("client [%2d of %2d]:%s\n",
+				i,sk_num(ciphers),SSL_CIPHER_get_name(c));
+#endif
+			if (c->id == id)
+				{
+				j=1;
+				break;
+				}
+			}
+		if (j == 0 && (s->options & SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) && (sk_SSL_CIPHER_num(ciphers) == 1))
+			{
+			/* Special case as client bug workaround: the previously used cipher may
+			 * not be in the current list, the client instead might be trying to
+			 * continue using a cipher that before wasn't chosen due to server
+			 * preferences.  We'll have to reject the connection if the cipher is not
+			 * enabled, though. */
+			c = sk_SSL_CIPHER_value(ciphers, 0);
+			if (sk_SSL_CIPHER_find(SSL_get_ciphers(s), c) >= 0)
+				{
+				s->session->cipher = c;
+				j = 1;
+				}
+			}
+		if (j == 0)
+			{
+			/* we need to have the cipher in the cipher
+			 * list if we are asked to reuse it */
+			al=SSL_AD_ILLEGAL_PARAMETER;
+			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_REQUIRED_CIPHER_MISSING);
+			goto f_err;
+			}
+		}
+
+	/* compression */
+	i= *(p++);
+	if ((p+i) > (d+n))
+		{
+		/* not enough data */
+		al=SSL_AD_DECODE_ERROR;
+		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_LENGTH_MISMATCH);
+		goto f_err;
+		}
+	q=p;
+	for (j=0; j<i; j++)
+		{
+		if (p[j] == 0) break;
+		}
+
+	p+=i;
+	if (j >= i)
+		{
+		/* no compress */
+		al=SSL_AD_DECODE_ERROR;
+		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_COMPRESSION_SPECIFIED);
+		goto f_err;
+		}
+
+#ifndef OPENSSL_NO_TLSEXT
+	/* TLS extensions*/
+	if (s->version >= SSL3_VERSION)
+		{
+		if (!ssl_parse_clienthello_tlsext(s,&p,d,n, &al))
+			{
+			/* 'al' set by ssl_parse_clienthello_tlsext */
+			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PARSE_TLSEXT);
+			goto f_err;
+			}
+		}
+		if (ssl_check_clienthello_tlsext(s) <= 0) {
+			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
+			goto err;
+		}
+
+	/* Check if we want to use external pre-shared secret for this
+	 * handshake for not reused session only. We need to generate
+	 * server_random before calling tls_session_secret_cb in order to allow
+	 * SessionTicket processing to use it in key derivation. */
+	{
+		unsigned long Time;
+		unsigned char *pos;
+		Time=(unsigned long)time(NULL);			/* Time */
+		pos=s->s3->server_random;
+		l2n(Time,pos);
+		if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0)
+			{
+			al=SSL_AD_INTERNAL_ERROR;
+			goto f_err;
+			}
+	}
+
+	if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb)
+		{
+		SSL_CIPHER *pref_cipher=NULL;
+
+		s->session->master_key_length=sizeof(s->session->master_key);
+		if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
+			ciphers, &pref_cipher, s->tls_session_secret_cb_arg))
+			{
+			s->hit=1;
+			s->session->ciphers=ciphers;
+			s->session->verify_result=X509_V_OK;
+
+			ciphers=NULL;
+
+			/* check if some cipher was preferred by call back */
+			pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
+			if (pref_cipher == NULL)
+				{
+				al=SSL_AD_HANDSHAKE_FAILURE;
+				SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
+				goto f_err;
+				}
+
+			s->session->cipher=pref_cipher;
+
+			if (s->cipher_list)
+				sk_SSL_CIPHER_free(s->cipher_list);
+
+			if (s->cipher_list_by_id)
+				sk_SSL_CIPHER_free(s->cipher_list_by_id);
+
+			s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
+			s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
+			}
+		}
+#endif
+
+	/* Worst case, we will use the NULL compression, but if we have other
+	 * options, we will now look for them.  We have i-1 compression
+	 * algorithms from the client, starting at q. */
+	s->s3->tmp.new_compression=NULL;
+#ifndef OPENSSL_NO_COMP
+	/* This only happens if we have a cache hit */
+	if (s->session->compress_meth != 0)
+		{
+		int m, comp_id = s->session->compress_meth;
+		/* Perform sanity checks on resumed compression algorithm */
+		/* Can't disable compression */
+		if (s->options & SSL_OP_NO_COMPRESSION)
+			{
+			al=SSL_AD_INTERNAL_ERROR;
+			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_INCONSISTENT_COMPRESSION);
+			goto f_err;
+			}
+		/* Look for resumed compression method */
+		for (m = 0; m < sk_SSL_COMP_num(s->ctx->comp_methods); m++)
+			{
+			comp=sk_SSL_COMP_value(s->ctx->comp_methods,m);
+			if (comp_id == comp->id)
+				{
+				s->s3->tmp.new_compression=comp;
+				break;
+				}
+			}
+		if (s->s3->tmp.new_compression == NULL)
+			{
+			al=SSL_AD_INTERNAL_ERROR;
+			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_INVALID_COMPRESSION_ALGORITHM);
+			goto f_err;
+			}
+		/* Look for resumed method in compression list */
+		for (m = 0; m < i; m++)
+			{
+			if (q[m] == comp_id)
+				break;
+			}
+		if (m >= i)
+			{
+			al=SSL_AD_ILLEGAL_PARAMETER;
+			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_REQUIRED_COMPRESSSION_ALGORITHM_MISSING);
+			goto f_err;
+			}
+		}
+	else if (s->hit)
+		comp = NULL;
+	else if (!(s->options & SSL_OP_NO_COMPRESSION) && s->ctx->comp_methods)
+		{ /* See if we have a match */
+		int m,nn,o,v,done=0;
+
+		nn=sk_SSL_COMP_num(s->ctx->comp_methods);
+		for (m=0; m<nn; m++)
+			{
+			comp=sk_SSL_COMP_value(s->ctx->comp_methods,m);
+			v=comp->id;
+			for (o=0; o<i; o++)
+				{
+				if (v == q[o])
+					{
+					done=1;
+					break;
+					}
+				}
+			if (done) break;
+			}
+		if (done)
+			s->s3->tmp.new_compression=comp;
+		else
+			comp=NULL;
+		}
+#else
+	/* If compression is disabled we'd better not try to resume a session
+	 * using compression.
+	 */
+	if (s->session->compress_meth != 0)
+		{
+		al=SSL_AD_INTERNAL_ERROR;
+		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_INCONSISTENT_COMPRESSION);
+		goto f_err;
+		}
+#endif
+
+	/* Given s->session->ciphers and SSL_get_ciphers, we must
+	 * pick a cipher */
+
+	if (!s->hit)
+		{
+#ifdef OPENSSL_NO_COMP
+		s->session->compress_meth=0;
+#else
+		s->session->compress_meth=(comp == NULL)?0:comp->id;
+#endif
+		if (s->session->ciphers != NULL)
+			sk_SSL_CIPHER_free(s->session->ciphers);
+		s->session->ciphers=ciphers;
+		if (ciphers == NULL)
+			{
+			al=SSL_AD_ILLEGAL_PARAMETER;
+			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_CIPHERS_PASSED);
+			goto f_err;
+			}
+		ciphers=NULL;
+		c=ssl3_choose_cipher(s,s->session->ciphers,
+				     SSL_get_ciphers(s));
+
+		if (c == NULL)
+			{
+			al=SSL_AD_HANDSHAKE_FAILURE;
+			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
+			goto f_err;
+			}
+		s->s3->tmp.new_cipher=c;
+		}
+	else
+		{
+		/* Session-id reuse */
+#ifdef REUSE_CIPHER_BUG
+		STACK_OF(SSL_CIPHER) *sk;
+		SSL_CIPHER *nc=NULL;
+		SSL_CIPHER *ec=NULL;
+
+		if (s->options & SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG)
+			{
+			sk=s->session->ciphers;
+			for (i=0; i<sk_SSL_CIPHER_num(sk); i++)
+				{
+				c=sk_SSL_CIPHER_value(sk,i);
+				if (c->algorithm_enc & SSL_eNULL)
+					nc=c;
+				if (SSL_C_IS_EXPORT(c))
+					ec=c;
+				}
+			if (nc != NULL)
+				s->s3->tmp.new_cipher=nc;
+			else if (ec != NULL)
+				s->s3->tmp.new_cipher=ec;
+			else
+				s->s3->tmp.new_cipher=s->session->cipher;
+			}
+		else
+#endif
+		s->s3->tmp.new_cipher=s->session->cipher;
+		}
+
+	if (!ssl3_digest_cached_records(s))
+		goto f_err;
+	
+	/* we now have the following setup. 
+	 * client_random
+	 * cipher_list 		- our prefered list of ciphers
+	 * ciphers 		- the clients prefered list of ciphers
+	 * compression		- basically ignored right now
+	 * ssl version is set	- sslv3
+	 * s->session		- The ssl session has been setup.
+	 * s->hit		- session reuse flag
+	 * s->tmp.new_cipher	- the new cipher to use.
+	 */
+
+	if (ret < 0) ret=1;
+	if (0)
+		{
+f_err:
+		ssl3_send_alert(s,SSL3_AL_FATAL,al);
+		}
+err:
+	if (ciphers != NULL) sk_SSL_CIPHER_free(ciphers);
+	return(ret);
+	}
+
+int ssl3_send_server_hello(SSL *s)
+	{
+	unsigned char *buf;
+	unsigned char *p,*d;
+	int i,sl;
+	unsigned long l;
+#ifdef OPENSSL_NO_TLSEXT
+	unsigned long Time;
+#endif
+
+	if (s->state == SSL3_ST_SW_SRVR_HELLO_A)
+		{
+		buf=(unsigned char *)s->init_buf->data;
+#ifdef OPENSSL_NO_TLSEXT
+		p=s->s3->server_random;
+		/* Generate server_random if it was not needed previously */
+		Time=(unsigned long)time(NULL);			/* Time */
+		l2n(Time,p);
+		if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
+			return -1;
+#endif
+		/* Do the message type and length last */
+		d=p= &(buf[4]);
+
+		*(p++)=s->version>>8;
+		*(p++)=s->version&0xff;
+
+		/* Random stuff */
+		memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE);
+		p+=SSL3_RANDOM_SIZE;
+
+		/* now in theory we have 3 options to sending back the
+		 * session id.  If it is a re-use, we send back the
+		 * old session-id, if it is a new session, we send
+		 * back the new session-id or we send back a 0 length
+		 * session-id if we want it to be single use.
+		 * Currently I will not implement the '0' length session-id
+		 * 12-Jan-98 - I'll now support the '0' length stuff.
+		 *
+		 * We also have an additional case where stateless session
+		 * resumption is successful: we always send back the old
+		 * session id. In this case s->hit is non zero: this can
+		 * only happen if stateless session resumption is succesful
+		 * if session caching is disabled so existing functionality
+		 * is unaffected.
+		 */
+		if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER)
+			&& !s->hit)
+			s->session->session_id_length=0;
+
+		sl=s->session->session_id_length;
+		if (sl > (int)sizeof(s->session->session_id))
+			{
+			SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
+			return -1;
+			}
+		*(p++)=sl;
+		memcpy(p,s->session->session_id,sl);
+		p+=sl;
+
+		/* put the cipher */
+		i=ssl3_put_cipher_by_char(s->s3->tmp.new_cipher,p);
+		p+=i;
+
+		/* put the compression method */
+#ifdef OPENSSL_NO_COMP
+			*(p++)=0;
+#else
+		if (s->s3->tmp.new_compression == NULL)
+			*(p++)=0;
+		else
+			*(p++)=s->s3->tmp.new_compression->id;
+#endif
+#ifndef OPENSSL_NO_TLSEXT
+		if (ssl_prepare_serverhello_tlsext(s) <= 0)
+			{
+			SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO,SSL_R_SERVERHELLO_TLSEXT);
+			return -1;
+			}
+		if ((p = ssl_add_serverhello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
+			{
+			SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO,ERR_R_INTERNAL_ERROR);
+			return -1;
+			}
+#endif
+		/* do the header */
+		l=(p-d);
+		d=buf;
+		*(d++)=SSL3_MT_SERVER_HELLO;
+		l2n3(l,d);
+
+		s->state=SSL3_ST_SW_SRVR_HELLO_B;
+		/* number of bytes to write */
+		s->init_num=p-buf;
+		s->init_off=0;
+		}
+
+	/* SSL3_ST_SW_SRVR_HELLO_B */
+	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+	}
+
+int ssl3_send_server_done(SSL *s)
+	{
+	unsigned char *p;
+
+	if (s->state == SSL3_ST_SW_SRVR_DONE_A)
+		{
+		p=(unsigned char *)s->init_buf->data;
+
+		/* do the header */
+		*(p++)=SSL3_MT_SERVER_DONE;
+		*(p++)=0;
+		*(p++)=0;
+		*(p++)=0;
+
+		s->state=SSL3_ST_SW_SRVR_DONE_B;
+		/* number of bytes to write */
+		s->init_num=4;
+		s->init_off=0;
+		}
+
+	/* SSL3_ST_SW_SRVR_DONE_B */
+	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+	}
+
+int ssl3_send_server_key_exchange(SSL *s)
+	{
+#ifndef OPENSSL_NO_RSA
+	unsigned char *q;
+	int j,num;
+	RSA *rsa;
+	unsigned char md_buf[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH];
+	unsigned int u;
+#endif
+#ifndef OPENSSL_NO_DH
+	DH *dh=NULL,*dhp;
+#endif
+#ifndef OPENSSL_NO_ECDH
+	EC_KEY *ecdh=NULL, *ecdhp;
+	unsigned char *encodedPoint = NULL;
+	int encodedlen = 0;
+	int curve_id = 0;
+	BN_CTX *bn_ctx = NULL; 
+#endif
+	EVP_PKEY *pkey;
+	unsigned char *p,*d;
+	int al,i;
+	unsigned long type;
+	int n;
+	CERT *cert;
+	BIGNUM *r[4];
+	int nr[4],kn;
+	BUF_MEM *buf;
+	EVP_MD_CTX md_ctx;
+
+	EVP_MD_CTX_init(&md_ctx);
+	if (s->state == SSL3_ST_SW_KEY_EXCH_A)
+		{
+		type=s->s3->tmp.new_cipher->algorithm_mkey;
+		cert=s->cert;
+
+		buf=s->init_buf;
+
+		r[0]=r[1]=r[2]=r[3]=NULL;
+		n=0;
+#ifndef OPENSSL_NO_RSA
+		if (type & SSL_kRSA)
+			{
+			rsa=cert->rsa_tmp;
+			if ((rsa == NULL) && (s->cert->rsa_tmp_cb != NULL))
+				{
+				rsa=s->cert->rsa_tmp_cb(s,
+				      SSL_C_IS_EXPORT(s->s3->tmp.new_cipher),
+				      SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher));
+				if(rsa == NULL)
+				{
+					al=SSL_AD_HANDSHAKE_FAILURE;
+					SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_ERROR_GENERATING_TMP_RSA_KEY);
+					goto f_err;
+				}
+				RSA_up_ref(rsa);
+				cert->rsa_tmp=rsa;
+				}
+			if (rsa == NULL)
+				{
+				al=SSL_AD_HANDSHAKE_FAILURE;
+				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_RSA_KEY);
+				goto f_err;
+				}
+			r[0]=rsa->n;
+			r[1]=rsa->e;
+			s->s3->tmp.use_rsa_tmp=1;
+			}
+		else
+#endif
+#ifndef OPENSSL_NO_DH
+			if (type & SSL_kEDH)
+			{
+			dhp=cert->dh_tmp;
+			if ((dhp == NULL) && (s->cert->dh_tmp_cb != NULL))
+				dhp=s->cert->dh_tmp_cb(s,
+				      SSL_C_IS_EXPORT(s->s3->tmp.new_cipher),
+				      SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher));
+			if (dhp == NULL)
+				{
+				al=SSL_AD_HANDSHAKE_FAILURE;
+				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_DH_KEY);
+				goto f_err;
+				}
+
+			if (s->s3->tmp.dh != NULL)
+				{
+				DH_free(dh);
+				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+				goto err;
+				}
+
+			if ((dh=DHparams_dup(dhp)) == NULL)
+				{
+				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_DH_LIB);
+				goto err;
+				}
+
+			s->s3->tmp.dh=dh;
+			if ((dhp->pub_key == NULL ||
+			     dhp->priv_key == NULL ||
+			     (s->options & SSL_OP_SINGLE_DH_USE)))
+				{
+				if(!DH_generate_key(dh))
+				    {
+				    SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,
+					   ERR_R_DH_LIB);
+				    goto err;
+				    }
+				}
+			else
+				{
+				dh->pub_key=BN_dup(dhp->pub_key);
+				dh->priv_key=BN_dup(dhp->priv_key);
+				if ((dh->pub_key == NULL) ||
+					(dh->priv_key == NULL))
+					{
+					SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_DH_LIB);
+					goto err;
+					}
+				}
+			r[0]=dh->p;
+			r[1]=dh->g;
+			r[2]=dh->pub_key;
+			}
+		else 
+#endif
+#ifndef OPENSSL_NO_ECDH
+			if (type & SSL_kEECDH)
+			{
+			const EC_GROUP *group;
+
+			ecdhp=cert->ecdh_tmp;
+			if ((ecdhp == NULL) && (s->cert->ecdh_tmp_cb != NULL))
+				{
+				ecdhp=s->cert->ecdh_tmp_cb(s,
+				      SSL_C_IS_EXPORT(s->s3->tmp.new_cipher),
+				      SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher));
+				}
+			if (ecdhp == NULL)
+				{
+				al=SSL_AD_HANDSHAKE_FAILURE;
+				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_ECDH_KEY);
+				goto f_err;
+				}
+
+			if (s->s3->tmp.ecdh != NULL)
+				{
+				EC_KEY_free(s->s3->tmp.ecdh); 
+				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+				goto err;
+				}
+
+			/* Duplicate the ECDH structure. */
+			if (ecdhp == NULL)
+				{
+				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
+				goto err;
+				}
+			if (!EC_KEY_up_ref(ecdhp))
+				{
+				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
+				goto err;
+				}
+			ecdh = ecdhp;
+
+			s->s3->tmp.ecdh=ecdh;
+			if ((EC_KEY_get0_public_key(ecdh) == NULL) ||
+			    (EC_KEY_get0_private_key(ecdh) == NULL) ||
+			    (s->options & SSL_OP_SINGLE_ECDH_USE))
+				{
+				if(!EC_KEY_generate_key(ecdh))
+				    {
+				    SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
+				    goto err;
+				    }
+				}
+
+			if (((group = EC_KEY_get0_group(ecdh)) == NULL) ||
+			    (EC_KEY_get0_public_key(ecdh)  == NULL) ||
+			    (EC_KEY_get0_private_key(ecdh) == NULL))
+				{
+				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
+				goto err;
+				}
+
+			if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) &&
+			    (EC_GROUP_get_degree(group) > 163)) 
+				{
+				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER);
+				goto err;
+				}
+
+			/* XXX: For now, we only support ephemeral ECDH
+			 * keys over named (not generic) curves. For 
+			 * supported named curves, curve_id is non-zero.
+			 */
+			if ((curve_id = 
+			    tls1_ec_nid2curve_id(EC_GROUP_get_curve_name(group)))
+			    == 0)
+				{
+				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNSUPPORTED_ELLIPTIC_CURVE);
+				goto err;
+				}
+
+			/* Encode the public key.
+			 * First check the size of encoding and
+			 * allocate memory accordingly.
+			 */
+			encodedlen = EC_POINT_point2oct(group, 
+			    EC_KEY_get0_public_key(ecdh),
+			    POINT_CONVERSION_UNCOMPRESSED, 
+			    NULL, 0, NULL);
+
+			encodedPoint = (unsigned char *) 
+			    OPENSSL_malloc(encodedlen*sizeof(unsigned char)); 
+			bn_ctx = BN_CTX_new();
+			if ((encodedPoint == NULL) || (bn_ctx == NULL))
+				{
+				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
+				goto err;
+				}
+
+
+			encodedlen = EC_POINT_point2oct(group, 
+			    EC_KEY_get0_public_key(ecdh), 
+			    POINT_CONVERSION_UNCOMPRESSED, 
+			    encodedPoint, encodedlen, bn_ctx);
+
+			if (encodedlen == 0) 
+				{
+				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
+				goto err;
+				}
+
+			BN_CTX_free(bn_ctx);  bn_ctx=NULL;
+
+			/* XXX: For now, we only support named (not 
+			 * generic) curves in ECDH ephemeral key exchanges.
+			 * In this situation, we need four additional bytes
+			 * to encode the entire ServerECDHParams
+			 * structure. 
+			 */
+			n = 4 + encodedlen;
+
+			/* We'll generate the serverKeyExchange message
+			 * explicitly so we can set these to NULLs
+			 */
+			r[0]=NULL;
+			r[1]=NULL;
+			r[2]=NULL;
+			r[3]=NULL;
+			}
+		else 
+#endif /* !OPENSSL_NO_ECDH */
+#ifndef OPENSSL_NO_PSK
+			if (type & SSL_kPSK)
+				{
+				/* reserve size for record length and PSK identity hint*/
+				n+=2+strlen(s->ctx->psk_identity_hint);
+				}
+			else
+#endif /* !OPENSSL_NO_PSK */
+			{
+			al=SSL_AD_HANDSHAKE_FAILURE;
+			SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
+			goto f_err;
+			}
+		for (i=0; r[i] != NULL; i++)
+			{
+			nr[i]=BN_num_bytes(r[i]);
+			n+=2+nr[i];
+			}
+
+		if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)
+			&& !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
+			{
+			if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher))
+				== NULL)
+				{
+				al=SSL_AD_DECODE_ERROR;
+				goto f_err;
+				}
+			kn=EVP_PKEY_size(pkey);
+			}
+		else
+			{
+			pkey=NULL;
+			kn=0;
+			}
+
+		if (!BUF_MEM_grow_clean(buf,n+4+kn))
+			{
+			SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_BUF);
+			goto err;
+			}
+		d=(unsigned char *)s->init_buf->data;
+		p= &(d[4]);
+
+		for (i=0; r[i] != NULL; i++)
+			{
+			s2n(nr[i],p);
+			BN_bn2bin(r[i],p);
+			p+=nr[i];
+			}
+
+#ifndef OPENSSL_NO_ECDH
+		if (type & SSL_kEECDH) 
+			{
+			/* XXX: For now, we only support named (not generic) curves.
+			 * In this situation, the serverKeyExchange message has:
+			 * [1 byte CurveType], [2 byte CurveName]
+			 * [1 byte length of encoded point], followed by
+			 * the actual encoded point itself
+			 */
+			*p = NAMED_CURVE_TYPE;
+			p += 1;
+			*p = 0;
+			p += 1;
+			*p = curve_id;
+			p += 1;
+			*p = encodedlen;
+			p += 1;
+			memcpy((unsigned char*)p, 
+			    (unsigned char *)encodedPoint, 
+			    encodedlen);
+			OPENSSL_free(encodedPoint);
+			p += encodedlen;
+			}
+#endif
+
+#ifndef OPENSSL_NO_PSK
+		if (type & SSL_kPSK)
+			{
+			/* copy PSK identity hint */
+			s2n(strlen(s->ctx->psk_identity_hint), p); 
+			strncpy((char *)p, s->ctx->psk_identity_hint, strlen(s->ctx->psk_identity_hint));
+			p+=strlen(s->ctx->psk_identity_hint);
+			}
+#endif
+
+		/* not anonymous */
+		if (pkey != NULL)
+			{
+			/* n is the length of the params, they start at &(d[4])
+			 * and p points to the space at the end. */
+#ifndef OPENSSL_NO_RSA
+			if (pkey->type == EVP_PKEY_RSA)
+				{
+				q=md_buf;
+				j=0;
+				for (num=2; num > 0; num--)
+					{
+					EVP_DigestInit_ex(&md_ctx,(num == 2)
+						?s->ctx->md5:s->ctx->sha1, NULL);
+					EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
+					EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
+					EVP_DigestUpdate(&md_ctx,&(d[4]),n);
+					EVP_DigestFinal_ex(&md_ctx,q,
+						(unsigned int *)&i);
+					q+=i;
+					j+=i;
+					}
+				if (RSA_sign(NID_md5_sha1, md_buf, j,
+					&(p[2]), &u, pkey->pkey.rsa) <= 0)
+					{
+					SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_RSA);
+					goto err;
+					}
+				s2n(u,p);
+				n+=u+2;
+				}
+			else
+#endif
+#if !defined(OPENSSL_NO_DSA)
+				if (pkey->type == EVP_PKEY_DSA)
+				{
+				/* lets do DSS */
+				EVP_SignInit_ex(&md_ctx,EVP_dss1(), NULL);
+				EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
+				EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
+				EVP_SignUpdate(&md_ctx,&(d[4]),n);
+				if (!EVP_SignFinal(&md_ctx,&(p[2]),
+					(unsigned int *)&i,pkey))
+					{
+					SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_DSA);
+					goto err;
+					}
+				s2n(i,p);
+				n+=i+2;
+				}
+			else
+#endif
+#if !defined(OPENSSL_NO_ECDSA)
+				if (pkey->type == EVP_PKEY_EC)
+				{
+				/* let's do ECDSA */
+				EVP_SignInit_ex(&md_ctx,EVP_ecdsa(), NULL);
+				EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
+				EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
+				EVP_SignUpdate(&md_ctx,&(d[4]),n);
+				if (!EVP_SignFinal(&md_ctx,&(p[2]),
+					(unsigned int *)&i,pkey))
+					{
+					SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_ECDSA);
+					goto err;
+					}
+				s2n(i,p);
+				n+=i+2;
+				}
+			else
+#endif
+				{
+				/* Is this error check actually needed? */
+				al=SSL_AD_HANDSHAKE_FAILURE;
+				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_PKEY_TYPE);
+				goto f_err;
+				}
+			}
+
+		*(d++)=SSL3_MT_SERVER_KEY_EXCHANGE;
+		l2n3(n,d);
+
+		/* we should now have things packed up, so lets send
+		 * it off */
+		s->init_num=n+4;
+		s->init_off=0;
+		}
+
+	s->state = SSL3_ST_SW_KEY_EXCH_B;
+	EVP_MD_CTX_cleanup(&md_ctx);
+	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+f_err:
+	ssl3_send_alert(s,SSL3_AL_FATAL,al);
+err:
+#ifndef OPENSSL_NO_ECDH
+	if (encodedPoint != NULL) OPENSSL_free(encodedPoint);
+	BN_CTX_free(bn_ctx);
+#endif
+	EVP_MD_CTX_cleanup(&md_ctx);
+	return(-1);
+	}
+
+int ssl3_send_certificate_request(SSL *s)
+	{
+	unsigned char *p,*d;
+	int i,j,nl,off,n;
+	STACK_OF(X509_NAME) *sk=NULL;
+	X509_NAME *name;
+	BUF_MEM *buf;
+
+	if (s->state == SSL3_ST_SW_CERT_REQ_A)
+		{
+		buf=s->init_buf;
+
+		d=p=(unsigned char *)&(buf->data[4]);
+
+		/* get the list of acceptable cert types */
+		p++;
+		n=ssl3_get_req_cert_type(s,p);
+		d[0]=n;
+		p+=n;
+		n++;
+
+		off=n;
+		p+=2;
+		n+=2;
+
+		sk=SSL_get_client_CA_list(s);
+		nl=0;
+		if (sk != NULL)
+			{
+			for (i=0; i<sk_X509_NAME_num(sk); i++)
+				{
+				name=sk_X509_NAME_value(sk,i);
+				j=i2d_X509_NAME(name,NULL);
+				if (!BUF_MEM_grow_clean(buf,4+n+j+2))
+					{
+					SSLerr(SSL_F_SSL3_SEND_CERTIFICATE_REQUEST,ERR_R_BUF_LIB);
+					goto err;
+					}
+				p=(unsigned char *)&(buf->data[4+n]);
+				if (!(s->options & SSL_OP_NETSCAPE_CA_DN_BUG))
+					{
+					s2n(j,p);
+					i2d_X509_NAME(name,&p);
+					n+=2+j;
+					nl+=2+j;
+					}
+				else
+					{
+					d=p;
+					i2d_X509_NAME(name,&p);
+					j-=2; s2n(j,d); j+=2;
+					n+=j;
+					nl+=j;
+					}
+				}
+			}
+		/* else no CA names */
+		p=(unsigned char *)&(buf->data[4+off]);
+		s2n(nl,p);
+
+		d=(unsigned char *)buf->data;
+		*(d++)=SSL3_MT_CERTIFICATE_REQUEST;
+		l2n3(n,d);
+
+		/* we should now have things packed up, so lets send
+		 * it off */
+
+		s->init_num=n+4;
+		s->init_off=0;
+#ifdef NETSCAPE_HANG_BUG
+		p=(unsigned char *)s->init_buf->data + s->init_num;
+
+		/* do the header */
+		*(p++)=SSL3_MT_SERVER_DONE;
+		*(p++)=0;
+		*(p++)=0;
+		*(p++)=0;
+		s->init_num += 4;
+#endif
+
+		s->state = SSL3_ST_SW_CERT_REQ_B;
+		}
+
+	/* SSL3_ST_SW_CERT_REQ_B */
+	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+err:
+	return(-1);
+	}
+
+int ssl3_get_client_key_exchange(SSL *s)
+	{
+	int i,al,ok;
+	long n;
+	unsigned long alg_k;
+	unsigned char *p;
+#ifndef OPENSSL_NO_RSA
+	RSA *rsa=NULL;
+	EVP_PKEY *pkey=NULL;
+#endif
+#ifndef OPENSSL_NO_DH
+	BIGNUM *pub=NULL;
+	DH *dh_srvr;
+#endif
+#ifndef OPENSSL_NO_KRB5
+	KSSL_ERR kssl_err;
+#endif /* OPENSSL_NO_KRB5 */
+
+#ifndef OPENSSL_NO_ECDH
+	EC_KEY *srvr_ecdh = NULL;
+	EVP_PKEY *clnt_pub_pkey = NULL;
+	EC_POINT *clnt_ecpoint = NULL;
+	BN_CTX *bn_ctx = NULL; 
+#endif
+
+	n=s->method->ssl_get_message(s,
+		SSL3_ST_SR_KEY_EXCH_A,
+		SSL3_ST_SR_KEY_EXCH_B,
+		SSL3_MT_CLIENT_KEY_EXCHANGE,
+		2048, /* ??? */
+		&ok);
+
+	if (!ok) return((int)n);
+	p=(unsigned char *)s->init_msg;
+
+	alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
+
+#ifndef OPENSSL_NO_RSA
+	if (alg_k & SSL_kRSA)
+		{
+		/* FIX THIS UP EAY EAY EAY EAY */
+		if (s->s3->tmp.use_rsa_tmp)
+			{
+			if ((s->cert != NULL) && (s->cert->rsa_tmp != NULL))
+				rsa=s->cert->rsa_tmp;
+			/* Don't do a callback because rsa_tmp should
+			 * be sent already */
+			if (rsa == NULL)
+				{
+				al=SSL_AD_HANDSHAKE_FAILURE;
+				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_TMP_RSA_PKEY);
+				goto f_err;
+
+				}
+			}
+		else
+			{
+			pkey=s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey;
+			if (	(pkey == NULL) ||
+				(pkey->type != EVP_PKEY_RSA) ||
+				(pkey->pkey.rsa == NULL))
+				{
+				al=SSL_AD_HANDSHAKE_FAILURE;
+				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_RSA_CERTIFICATE);
+				goto f_err;
+				}
+			rsa=pkey->pkey.rsa;
+			}
+
+		/* TLS and [incidentally] DTLS{0xFEFF} */
+		if (s->version > SSL3_VERSION && s->version != DTLS1_BAD_VER)
+			{
+			n2s(p,i);
+			if (n != i+2)
+				{
+				if (!(s->options & SSL_OP_TLS_D5_BUG))
+					{
+					SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG);
+					goto err;
+					}
+				else
+					p-=2;
+				}
+			else
+				n=i;
+			}
+
+		i=RSA_private_decrypt((int)n,p,p,rsa,RSA_PKCS1_PADDING);
+
+		al = -1;
+		
+		if (i != SSL_MAX_MASTER_KEY_LENGTH)
+			{
+			al=SSL_AD_DECODE_ERROR;
+			/* SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_DECRYPT); */
+			}
+
+		if ((al == -1) && !((p[0] == (s->client_version>>8)) && (p[1] == (s->client_version & 0xff))))
+			{
+			/* The premaster secret must contain the same version number as the
+			 * ClientHello to detect version rollback attacks (strangely, the
+			 * protocol does not offer such protection for DH ciphersuites).
+			 * However, buggy clients exist that send the negotiated protocol
+			 * version instead if the server does not support the requested
+			 * protocol version.
+			 * If SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such clients. */
+			if (!((s->options & SSL_OP_TLS_ROLLBACK_BUG) &&
+				(p[0] == (s->version>>8)) && (p[1] == (s->version & 0xff))))
+				{
+				al=SSL_AD_DECODE_ERROR;
+				/* SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_PROTOCOL_VERSION_NUMBER); */
+
+				/* The Klima-Pokorny-Rosa extension of Bleichenbacher's attack
+				 * (http://eprint.iacr.org/2003/052/) exploits the version
+				 * number check as a "bad version oracle" -- an alert would
+				 * reveal that the plaintext corresponding to some ciphertext
+				 * made up by the adversary is properly formatted except
+				 * that the version number is wrong.  To avoid such attacks,
+				 * we should treat this just like any other decryption error. */
+				}
+			}
+
+		if (al != -1)
+			{
+			/* Some decryption failure -- use random value instead as countermeasure
+			 * against Bleichenbacher's attack on PKCS #1 v1.5 RSA padding
+			 * (see RFC 2246, section 7.4.7.1). */
+			ERR_clear_error();
+			i = SSL_MAX_MASTER_KEY_LENGTH;
+			p[0] = s->client_version >> 8;
+			p[1] = s->client_version & 0xff;
+			if (RAND_pseudo_bytes(p+2, i-2) <= 0) /* should be RAND_bytes, but we cannot work around a failure */
+				goto err;
+			}
+	
+		s->session->master_key_length=
+			s->method->ssl3_enc->generate_master_secret(s,
+				s->session->master_key,
+				p,i);
+		OPENSSL_cleanse(p,i);
+		}
+	else
+#endif
+#ifndef OPENSSL_NO_DH
+		if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
+		{
+		n2s(p,i);
+		if (n != i+2)
+			{
+			if (!(s->options & SSL_OP_SSLEAY_080_CLIENT_DH_BUG))
+				{
+				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG);
+				goto err;
+				}
+			else
+				{
+				p-=2;
+				i=(int)n;
+				}
+			}
+
+		if (n == 0L) /* the parameters are in the cert */
+			{
+			al=SSL_AD_HANDSHAKE_FAILURE;
+			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_UNABLE_TO_DECODE_DH_CERTS);
+			goto f_err;
+			}
+		else
+			{
+			if (s->s3->tmp.dh == NULL)
+				{
+				al=SSL_AD_HANDSHAKE_FAILURE;
+				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_TMP_DH_KEY);
+				goto f_err;
+				}
+			else
+				dh_srvr=s->s3->tmp.dh;
+			}
+
+		pub=BN_bin2bn(p,i,NULL);
+		if (pub == NULL)
+			{
+			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BN_LIB);
+			goto err;
+			}
+
+		i=DH_compute_key(p,pub,dh_srvr);
+
+		if (i <= 0)
+			{
+			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
+			goto err;
+			}
+
+		DH_free(s->s3->tmp.dh);
+		s->s3->tmp.dh=NULL;
+
+		BN_clear_free(pub);
+		pub=NULL;
+		s->session->master_key_length=
+			s->method->ssl3_enc->generate_master_secret(s,
+				s->session->master_key,p,i);
+		OPENSSL_cleanse(p,i);
+		}
+	else
+#endif
+#ifndef OPENSSL_NO_KRB5
+	if (alg_k & SSL_kKRB5)
+		{
+		krb5_error_code		krb5rc;
+		krb5_data		enc_ticket;
+		krb5_data		authenticator;
+		krb5_data		enc_pms;
+		KSSL_CTX		*kssl_ctx = s->kssl_ctx;
+		EVP_CIPHER_CTX		ciph_ctx;
+		const EVP_CIPHER	*enc = NULL;
+		unsigned char		iv[EVP_MAX_IV_LENGTH];
+		unsigned char		pms[SSL_MAX_MASTER_KEY_LENGTH
+					       + EVP_MAX_BLOCK_LENGTH];
+		int		     padl, outl;
+		krb5_timestamp		authtime = 0;
+		krb5_ticket_times	ttimes;
+
+		EVP_CIPHER_CTX_init(&ciph_ctx);
+
+		if (!kssl_ctx)  kssl_ctx = kssl_ctx_new();
+
+		n2s(p,i);
+		enc_ticket.length = i;
+
+		if (n < (long)(enc_ticket.length + 6))
+			{
+			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+				SSL_R_DATA_LENGTH_TOO_LONG);
+			goto err;
+			}
+
+		enc_ticket.data = (char *)p;
+		p+=enc_ticket.length;
+
+		n2s(p,i);
+		authenticator.length = i;
+
+		if (n < (long)(enc_ticket.length + authenticator.length + 6))
+			{
+			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+				SSL_R_DATA_LENGTH_TOO_LONG);
+			goto err;
+			}
+
+		authenticator.data = (char *)p;
+		p+=authenticator.length;
+
+		n2s(p,i);
+		enc_pms.length = i;
+		enc_pms.data = (char *)p;
+		p+=enc_pms.length;
+
+		/* Note that the length is checked again below,
+		** after decryption
+		*/
+		if(enc_pms.length > sizeof pms)
+			{
+			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+			       SSL_R_DATA_LENGTH_TOO_LONG);
+			goto err;
+			}
+
+		if (n != (long)(enc_ticket.length + authenticator.length +
+						enc_pms.length + 6))
+			{
+			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+				SSL_R_DATA_LENGTH_TOO_LONG);
+			goto err;
+			}
+
+		if ((krb5rc = kssl_sget_tkt(kssl_ctx, &enc_ticket, &ttimes,
+					&kssl_err)) != 0)
+			{
+#ifdef KSSL_DEBUG
+			printf("kssl_sget_tkt rtn %d [%d]\n",
+				krb5rc, kssl_err.reason);
+			if (kssl_err.text)
+				printf("kssl_err text= %s\n", kssl_err.text);
+#endif	/* KSSL_DEBUG */
+			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+				kssl_err.reason);
+			goto err;
+			}
+
+		/*  Note: no authenticator is not considered an error,
+		**  but will return authtime == 0.
+		*/
+		if ((krb5rc = kssl_check_authent(kssl_ctx, &authenticator,
+					&authtime, &kssl_err)) != 0)
+			{
+#ifdef KSSL_DEBUG
+			printf("kssl_check_authent rtn %d [%d]\n",
+				krb5rc, kssl_err.reason);
+			if (kssl_err.text)
+				printf("kssl_err text= %s\n", kssl_err.text);
+#endif	/* KSSL_DEBUG */
+			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+				kssl_err.reason);
+			goto err;
+			}
+
+		if ((krb5rc = kssl_validate_times(authtime, &ttimes)) != 0)
+			{
+			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, krb5rc);
+			goto err;
+			}
+
+#ifdef KSSL_DEBUG
+		kssl_ctx_show(kssl_ctx);
+#endif	/* KSSL_DEBUG */
+
+		enc = kssl_map_enc(kssl_ctx->enctype);
+		if (enc == NULL)
+		    goto err;
+
+		memset(iv, 0, sizeof iv);	/* per RFC 1510 */
+
+		if (!EVP_DecryptInit_ex(&ciph_ctx,enc,NULL,kssl_ctx->key,iv))
+			{
+			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+				SSL_R_DECRYPTION_FAILED);
+			goto err;
+			}
+		if (!EVP_DecryptUpdate(&ciph_ctx, pms,&outl,
+					(unsigned char *)enc_pms.data, enc_pms.length))
+			{
+			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+				SSL_R_DECRYPTION_FAILED);
+			goto err;
+			}
+		if (outl > SSL_MAX_MASTER_KEY_LENGTH)
+			{
+			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+				SSL_R_DATA_LENGTH_TOO_LONG);
+			goto err;
+			}
+		if (!EVP_DecryptFinal_ex(&ciph_ctx,&(pms[outl]),&padl))
+			{
+			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+				SSL_R_DECRYPTION_FAILED);
+			goto err;
+			}
+		outl += padl;
+		if (outl > SSL_MAX_MASTER_KEY_LENGTH)
+			{
+			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+				SSL_R_DATA_LENGTH_TOO_LONG);
+			goto err;
+			}
+		if (!((pms[0] == (s->client_version>>8)) && (pms[1] == (s->client_version & 0xff))))
+		    {
+		    /* The premaster secret must contain the same version number as the
+		     * ClientHello to detect version rollback attacks (strangely, the
+		     * protocol does not offer such protection for DH ciphersuites).
+		     * However, buggy clients exist that send random bytes instead of
+		     * the protocol version.
+		     * If SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such clients. 
+		     * (Perhaps we should have a separate BUG value for the Kerberos cipher)
+		     */
+		    if (!(s->options & SSL_OP_TLS_ROLLBACK_BUG))
+			{
+			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+			       SSL_AD_DECODE_ERROR);
+			goto err;
+			}
+		    }
+
+		EVP_CIPHER_CTX_cleanup(&ciph_ctx);
+
+		s->session->master_key_length=
+			s->method->ssl3_enc->generate_master_secret(s,
+				s->session->master_key, pms, outl);
+
+		if (kssl_ctx->client_princ)
+			{
+			size_t len = strlen(kssl_ctx->client_princ);
+			if ( len < SSL_MAX_KRB5_PRINCIPAL_LENGTH ) 
+				{
+				s->session->krb5_client_princ_len = len;
+				memcpy(s->session->krb5_client_princ,kssl_ctx->client_princ,len);
+				}
+			}
+
+
+		/*  Was doing kssl_ctx_free() here,
+		**  but it caused problems for apache.
+		**  kssl_ctx = kssl_ctx_free(kssl_ctx);
+		**  if (s->kssl_ctx)  s->kssl_ctx = NULL;
+		*/
+		}
+	else
+#endif	/* OPENSSL_NO_KRB5 */
+
+#ifndef OPENSSL_NO_ECDH
+		if (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe))
+		{
+		int ret = 1;
+		int field_size = 0;
+		const EC_KEY   *tkey;
+		const EC_GROUP *group;
+		const BIGNUM *priv_key;
+
+		/* initialize structures for server's ECDH key pair */
+		if ((srvr_ecdh = EC_KEY_new()) == NULL) 
+			{
+			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+			    ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+
+		/* Let's get server private key and group information */
+		if (alg_k & (SSL_kECDHr|SSL_kECDHe))
+			{ 
+			/* use the certificate */
+			tkey = s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec;
+			}
+		else
+			{
+			/* use the ephermeral values we saved when
+			 * generating the ServerKeyExchange msg.
+			 */
+			tkey = s->s3->tmp.ecdh;
+			}
+
+		group    = EC_KEY_get0_group(tkey);
+		priv_key = EC_KEY_get0_private_key(tkey);
+
+		if (!EC_KEY_set_group(srvr_ecdh, group) ||
+		    !EC_KEY_set_private_key(srvr_ecdh, priv_key))
+			{
+			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+			       ERR_R_EC_LIB);
+			goto err;
+			}
+
+		/* Let's get client's public key */
+		if ((clnt_ecpoint = EC_POINT_new(group)) == NULL)
+			{
+			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+			    ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+
+		if (n == 0L) 
+			{
+			/* Client Publickey was in Client Certificate */
+
+			 if (alg_k & SSL_kEECDH)
+				 {
+				 al=SSL_AD_HANDSHAKE_FAILURE;
+				 SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_TMP_ECDH_KEY);
+				 goto f_err;
+				 }
+			if (((clnt_pub_pkey=X509_get_pubkey(s->session->peer))
+			    == NULL) || 
+			    (clnt_pub_pkey->type != EVP_PKEY_EC))
+				{
+				/* XXX: For now, we do not support client
+				 * authentication using ECDH certificates
+				 * so this branch (n == 0L) of the code is
+				 * never executed. When that support is
+				 * added, we ought to ensure the key 
+				 * received in the certificate is 
+				 * authorized for key agreement.
+				 * ECDH_compute_key implicitly checks that
+				 * the two ECDH shares are for the same
+				 * group.
+				 */
+			   	al=SSL_AD_HANDSHAKE_FAILURE;
+			   	SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+				    SSL_R_UNABLE_TO_DECODE_ECDH_CERTS);
+			   	goto f_err;
+			   	}
+
+			if (EC_POINT_copy(clnt_ecpoint,
+			    EC_KEY_get0_public_key(clnt_pub_pkey->pkey.ec)) == 0)
+				{
+				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+					ERR_R_EC_LIB);
+				goto err;
+				}
+			ret = 2; /* Skip certificate verify processing */
+			}
+		else
+			{
+			/* Get client's public key from encoded point
+			 * in the ClientKeyExchange message.
+			 */
+			if ((bn_ctx = BN_CTX_new()) == NULL)
+				{
+				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+				    ERR_R_MALLOC_FAILURE);
+				goto err;
+				}
+
+			/* Get encoded point length */
+			i = *p; 
+			p += 1;
+			if (EC_POINT_oct2point(group, 
+			    clnt_ecpoint, p, i, bn_ctx) == 0)
+				{
+				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+				    ERR_R_EC_LIB);
+				goto err;
+				}
+			/* p is pointing to somewhere in the buffer
+			 * currently, so set it to the start 
+			 */ 
+			p=(unsigned char *)s->init_buf->data;
+			}
+
+		/* Compute the shared pre-master secret */
+		field_size = EC_GROUP_get_degree(group);
+		if (field_size <= 0)
+			{
+			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, 
+			       ERR_R_ECDH_LIB);
+			goto err;
+			}
+		i = ECDH_compute_key(p, (field_size+7)/8, clnt_ecpoint, srvr_ecdh, NULL);
+		if (i <= 0)
+			{
+			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+			    ERR_R_ECDH_LIB);
+			goto err;
+			}
+
+		EVP_PKEY_free(clnt_pub_pkey);
+		EC_POINT_free(clnt_ecpoint);
+		EC_KEY_free(srvr_ecdh);
+		BN_CTX_free(bn_ctx);
+		EC_KEY_free(s->s3->tmp.ecdh);
+		s->s3->tmp.ecdh = NULL; 
+
+		/* Compute the master secret */
+		s->session->master_key_length = s->method->ssl3_enc-> \
+		    generate_master_secret(s, s->session->master_key, p, i);
+		
+		OPENSSL_cleanse(p, i);
+		return (ret);
+		}
+	else
+#endif
+#ifndef OPENSSL_NO_PSK
+		if (alg_k & SSL_kPSK)
+			{
+			unsigned char *t = NULL;
+			unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN*2+4];
+			unsigned int pre_ms_len = 0, psk_len = 0;
+			int psk_err = 1;
+			char tmp_id[PSK_MAX_IDENTITY_LEN+1];
+
+			al=SSL_AD_HANDSHAKE_FAILURE;
+
+			n2s(p,i);
+			if (n != i+2)
+				{
+				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+					SSL_R_LENGTH_MISMATCH);
+				goto psk_err;
+				}
+			if (i > PSK_MAX_IDENTITY_LEN)
+				{
+				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+					SSL_R_DATA_LENGTH_TOO_LONG);
+				goto psk_err;
+				}
+			if (s->psk_server_callback == NULL)
+				{
+				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+				       SSL_R_PSK_NO_SERVER_CB);
+				goto psk_err;
+				}
+
+			/* Create guaranteed NULL-terminated identity
+			 * string for the callback */
+			memcpy(tmp_id, p, i);
+			memset(tmp_id+i, 0, PSK_MAX_IDENTITY_LEN+1-i);
+			psk_len = s->psk_server_callback(s, tmp_id,
+				psk_or_pre_ms, sizeof(psk_or_pre_ms));
+			OPENSSL_cleanse(tmp_id, PSK_MAX_IDENTITY_LEN+1);
+
+			if (psk_len > PSK_MAX_PSK_LEN)
+				{
+				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+					ERR_R_INTERNAL_ERROR);
+				goto psk_err;
+				}
+			else if (psk_len == 0)
+				{
+				/* PSK related to the given identity not found */
+				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+				       SSL_R_PSK_IDENTITY_NOT_FOUND);
+				al=SSL_AD_UNKNOWN_PSK_IDENTITY;
+				goto psk_err;
+				}
+
+			/* create PSK pre_master_secret */
+			pre_ms_len=2+psk_len+2+psk_len;
+			t = psk_or_pre_ms;
+			memmove(psk_or_pre_ms+psk_len+4, psk_or_pre_ms, psk_len);
+			s2n(psk_len, t);
+			memset(t, 0, psk_len);
+			t+=psk_len;
+			s2n(psk_len, t);
+
+			if (s->session->psk_identity != NULL)
+				OPENSSL_free(s->session->psk_identity);
+			s->session->psk_identity = BUF_strdup((char *)p);
+			if (s->session->psk_identity == NULL)
+				{
+				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+					ERR_R_MALLOC_FAILURE);
+				goto psk_err;
+				}
+
+			if (s->session->psk_identity_hint != NULL)
+				OPENSSL_free(s->session->psk_identity_hint);
+			s->session->psk_identity_hint = BUF_strdup(s->ctx->psk_identity_hint);
+			if (s->ctx->psk_identity_hint != NULL &&
+				s->session->psk_identity_hint == NULL)
+				{
+				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+					ERR_R_MALLOC_FAILURE);
+				goto psk_err;
+				}
+
+			s->session->master_key_length=
+				s->method->ssl3_enc->generate_master_secret(s,
+					s->session->master_key, psk_or_pre_ms, pre_ms_len);
+			psk_err = 0;
+		psk_err:
+			OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms));
+			if (psk_err != 0)
+				goto f_err;
+			}
+		else
+#endif
+		if (alg_k & SSL_kGOST) 
+			{
+			int ret = 0;
+			EVP_PKEY_CTX *pkey_ctx;
+			EVP_PKEY *client_pub_pkey = NULL;
+			unsigned char premaster_secret[32], *start;
+			size_t outlen=32, inlen;			
+
+			/* Get our certificate private key*/
+			pkey_ctx = EVP_PKEY_CTX_new(s->cert->key->privatekey,NULL);	
+			EVP_PKEY_decrypt_init(pkey_ctx);
+			/* If client certificate is present and is of the same type, maybe
+			 * use it for key exchange.  Don't mind errors from
+			 * EVP_PKEY_derive_set_peer, because it is completely valid to use
+			 * a client certificate for authorization only. */
+			client_pub_pkey = X509_get_pubkey(s->session->peer);
+			if (client_pub_pkey)
+				{
+				if (EVP_PKEY_derive_set_peer(pkey_ctx, client_pub_pkey) <= 0)
+					ERR_clear_error();
+				}
+			/* Decrypt session key */
+			if ((*p!=( V_ASN1_SEQUENCE| V_ASN1_CONSTRUCTED))) 
+				{
+				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED);
+				goto gerr;
+				}
+			if (p[1] == 0x81)
+				{
+				start = p+3;
+				inlen = p[2];
+				}
+			else if (p[1] < 0x80)
+				{
+				start = p+2;
+				inlen = p[1];
+				}
+			else
+				{
+				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED);
+				goto gerr;
+				}
+			if (EVP_PKEY_decrypt(pkey_ctx,premaster_secret,&outlen,start,inlen) <=0) 
+
+				{
+				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED);
+				goto gerr;
+				}
+			/* Generate master secret */
+			s->session->master_key_length=
+				s->method->ssl3_enc->generate_master_secret(s,
+					s->session->master_key,premaster_secret,32);
+			/* Check if pubkey from client certificate was used */
+			if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, NULL) > 0)
+				ret = 2;
+			else
+				ret = 1;
+		gerr:
+			EVP_PKEY_free(client_pub_pkey);
+			EVP_PKEY_CTX_free(pkey_ctx);
+			if (ret)
+				return ret;
+			else
+				goto err;
+			}
+		else
+		{
+		al=SSL_AD_HANDSHAKE_FAILURE;
+		SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+				SSL_R_UNKNOWN_CIPHER_TYPE);
+		goto f_err;
+		}
+
+	return(1);
+f_err:
+	ssl3_send_alert(s,SSL3_AL_FATAL,al);
+#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_ECDH)
+err:
+#endif
+#ifndef OPENSSL_NO_ECDH
+	EVP_PKEY_free(clnt_pub_pkey);
+	EC_POINT_free(clnt_ecpoint);
+	if (srvr_ecdh != NULL) 
+		EC_KEY_free(srvr_ecdh);
+	BN_CTX_free(bn_ctx);
+#endif
+	return(-1);
+	}
+
+int ssl3_get_cert_verify(SSL *s)
+	{
+	EVP_PKEY *pkey=NULL;
+	unsigned char *p;
+	int al,ok,ret=0;
+	long n;
+	int type=0,i,j;
+	X509 *peer;
+
+	n=s->method->ssl_get_message(s,
+		SSL3_ST_SR_CERT_VRFY_A,
+		SSL3_ST_SR_CERT_VRFY_B,
+		-1,
+		514, /* 514? */
+		&ok);
+
+	if (!ok) return((int)n);
+
+	if (s->session->peer != NULL)
+		{
+		peer=s->session->peer;
+		pkey=X509_get_pubkey(peer);
+		type=X509_certificate_type(peer,pkey);
+		}
+	else
+		{
+		peer=NULL;
+		pkey=NULL;
+		}
+
+	if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE_VERIFY)
+		{
+		s->s3->tmp.reuse_message=1;
+		if ((peer != NULL) && (type | EVP_PKT_SIGN))
+			{
+			al=SSL_AD_UNEXPECTED_MESSAGE;
+			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_MISSING_VERIFY_MESSAGE);
+			goto f_err;
+			}
+		ret=1;
+		goto end;
+		}
+
+	if (peer == NULL)
+		{
+		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_NO_CLIENT_CERT_RECEIVED);
+		al=SSL_AD_UNEXPECTED_MESSAGE;
+		goto f_err;
+		}
+
+	if (!(type & EVP_PKT_SIGN))
+		{
+		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE);
+		al=SSL_AD_ILLEGAL_PARAMETER;
+		goto f_err;
+		}
+
+	if (s->s3->change_cipher_spec)
+		{
+		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_CCS_RECEIVED_EARLY);
+		al=SSL_AD_UNEXPECTED_MESSAGE;
+		goto f_err;
+		}
+
+	/* we now have a signature that we need to verify */
+	p=(unsigned char *)s->init_msg;
+	/* Check for broken implementations of GOST ciphersuites */
+	/* If key is GOST and n is exactly 64, it is bare
+	 * signature without length field */
+	if (n==64 && (pkey->type==NID_id_GostR3410_94 ||
+		pkey->type == NID_id_GostR3410_2001) )
+		{
+		i=64;
+		} 
+	else 
+		{	
+		n2s(p,i);
+		n-=2;
+		if (i > n)
+			{
+			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_LENGTH_MISMATCH);
+			al=SSL_AD_DECODE_ERROR;
+			goto f_err;
+			}
+    	}
+	j=EVP_PKEY_size(pkey);
+	if ((i > j) || (n > j) || (n <= 0))
+		{
+		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_WRONG_SIGNATURE_SIZE);
+		al=SSL_AD_DECODE_ERROR;
+		goto f_err;
+		}
+
+#ifndef OPENSSL_NO_RSA 
+	if (pkey->type == EVP_PKEY_RSA)
+		{
+		i=RSA_verify(NID_md5_sha1, s->s3->tmp.cert_verify_md,
+			MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH, p, i, 
+							pkey->pkey.rsa);
+		if (i < 0)
+			{
+			al=SSL_AD_DECRYPT_ERROR;
+			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_RSA_DECRYPT);
+			goto f_err;
+			}
+		if (i == 0)
+			{
+			al=SSL_AD_DECRYPT_ERROR;
+			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_RSA_SIGNATURE);
+			goto f_err;
+			}
+		}
+	else
+#endif
+#ifndef OPENSSL_NO_DSA
+		if (pkey->type == EVP_PKEY_DSA)
+		{
+		j=DSA_verify(pkey->save_type,
+			&(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]),
+			SHA_DIGEST_LENGTH,p,i,pkey->pkey.dsa);
+		if (j <= 0)
+			{
+			/* bad signature */
+			al=SSL_AD_DECRYPT_ERROR;
+			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_DSA_SIGNATURE);
+			goto f_err;
+			}
+		}
+	else
+#endif
+#ifndef OPENSSL_NO_ECDSA
+		if (pkey->type == EVP_PKEY_EC)
+		{
+		j=ECDSA_verify(pkey->save_type,
+			&(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]),
+			SHA_DIGEST_LENGTH,p,i,pkey->pkey.ec);
+		if (j <= 0)
+			{
+			/* bad signature */
+			al=SSL_AD_DECRYPT_ERROR;
+			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,
+			    SSL_R_BAD_ECDSA_SIGNATURE);
+			goto f_err;
+			}
+		}
+	else
+#endif
+	if (pkey->type == NID_id_GostR3410_94 || pkey->type == NID_id_GostR3410_2001)
+		{   unsigned char signature[64];
+			int idx;
+			EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(pkey,NULL);
+			EVP_PKEY_verify_init(pctx);
+			if (i!=64) {
+				fprintf(stderr,"GOST signature length is %d",i);
+			}	
+			for (idx=0;idx<64;idx++) {
+				signature[63-idx]=p[idx];
+			}	
+			j=EVP_PKEY_verify(pctx,signature,64,s->s3->tmp.cert_verify_md,32);
+			EVP_PKEY_CTX_free(pctx);
+			if (j<=0) 
+				{
+				al=SSL_AD_DECRYPT_ERROR;
+				SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,
+					SSL_R_BAD_ECDSA_SIGNATURE);
+				goto f_err;
+				}	
+		}
+	else	
+		{
+		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,ERR_R_INTERNAL_ERROR);
+		al=SSL_AD_UNSUPPORTED_CERTIFICATE;
+		goto f_err;
+		}
+
+
+	ret=1;
+	if (0)
+		{
+f_err:
+		ssl3_send_alert(s,SSL3_AL_FATAL,al);
+		}
+end:
+	EVP_PKEY_free(pkey);
+	return(ret);
+	}
+
+int ssl3_get_client_certificate(SSL *s)
+	{
+	int i,ok,al,ret= -1;
+	X509 *x=NULL;
+	unsigned long l,nc,llen,n;
+	const unsigned char *p,*q;
+	unsigned char *d;
+	STACK_OF(X509) *sk=NULL;
+
+	n=s->method->ssl_get_message(s,
+		SSL3_ST_SR_CERT_A,
+		SSL3_ST_SR_CERT_B,
+		-1,
+		s->max_cert_list,
+		&ok);
+
+	if (!ok) return((int)n);
+
+	if	(s->s3->tmp.message_type == SSL3_MT_CLIENT_KEY_EXCHANGE)
+		{
+		if (	(s->verify_mode & SSL_VERIFY_PEER) &&
+			(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT))
+			{
+			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
+			al=SSL_AD_HANDSHAKE_FAILURE;
+			goto f_err;
+			}
+		/* If tls asked for a client cert, the client must return a 0 list */
+		if ((s->version > SSL3_VERSION) && s->s3->tmp.cert_request)
+			{
+			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST);
+			al=SSL_AD_UNEXPECTED_MESSAGE;
+			goto f_err;
+			}
+		s->s3->tmp.reuse_message=1;
+		return(1);
+		}
+
+	if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE)
+		{
+		al=SSL_AD_UNEXPECTED_MESSAGE;
+		SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_WRONG_MESSAGE_TYPE);
+		goto f_err;
+		}
+	p=d=(unsigned char *)s->init_msg;
+
+	if ((sk=sk_X509_new_null()) == NULL)
+		{
+		SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_MALLOC_FAILURE);
+		goto err;
+		}
+
+	n2l3(p,llen);
+	if (llen+3 != n)
+		{
+		al=SSL_AD_DECODE_ERROR;
+		SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_LENGTH_MISMATCH);
+		goto f_err;
+		}
+	for (nc=0; nc<llen; )
+		{
+		n2l3(p,l);
+		if ((l+nc+3) > llen)
+			{
+			al=SSL_AD_DECODE_ERROR;
+			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH);
+			goto f_err;
+			}
+
+		q=p;
+		x=d2i_X509(NULL,&p,l);
+		if (x == NULL)
+			{
+			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_ASN1_LIB);
+			goto err;
+			}
+		if (p != (q+l))
+			{
+			al=SSL_AD_DECODE_ERROR;
+			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH);
+			goto f_err;
+			}
+		if (!sk_X509_push(sk,x))
+			{
+			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+		x=NULL;
+		nc+=l+3;
+		}
+
+	if (sk_X509_num(sk) <= 0)
+		{
+		/* TLS does not mind 0 certs returned */
+		if (s->version == SSL3_VERSION)
+			{
+			al=SSL_AD_HANDSHAKE_FAILURE;
+			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_NO_CERTIFICATES_RETURNED);
+			goto f_err;
+			}
+		/* Fail for TLS only if we required a certificate */
+		else if ((s->verify_mode & SSL_VERIFY_PEER) &&
+			 (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT))
+			{
+			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
+			al=SSL_AD_HANDSHAKE_FAILURE;
+			goto f_err;
+			}
+		}
+	else
+		{
+		i=ssl_verify_cert_chain(s,sk);
+		if (i <= 0)
+			{
+			al=ssl_verify_alarm_type(s->verify_result);
+			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_NO_CERTIFICATE_RETURNED);
+			goto f_err;
+			}
+		}
+
+	if (s->session->peer != NULL) /* This should not be needed */
+		X509_free(s->session->peer);
+	s->session->peer=sk_X509_shift(sk);
+	s->session->verify_result = s->verify_result;
+
+	/* With the current implementation, sess_cert will always be NULL
+	 * when we arrive here. */
+	if (s->session->sess_cert == NULL)
+		{
+		s->session->sess_cert = ssl_sess_cert_new();
+		if (s->session->sess_cert == NULL)
+			{
+			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE, ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+		}
+	if (s->session->sess_cert->cert_chain != NULL)
+		sk_X509_pop_free(s->session->sess_cert->cert_chain, X509_free);
+	s->session->sess_cert->cert_chain=sk;
+	/* Inconsistency alert: cert_chain does *not* include the
+	 * peer's own certificate, while we do include it in s3_clnt.c */
+
+	sk=NULL;
+
+	ret=1;
+	if (0)
+		{
+f_err:
+		ssl3_send_alert(s,SSL3_AL_FATAL,al);
+		}
+err:
+	if (x != NULL) X509_free(x);
+	if (sk != NULL) sk_X509_pop_free(sk,X509_free);
+	return(ret);
+	}
+
+int ssl3_send_server_certificate(SSL *s)
+	{
+	unsigned long l;
+	X509 *x;
+
+	if (s->state == SSL3_ST_SW_CERT_A)
+		{
+		x=ssl_get_server_send_cert(s);
+		if (x == NULL)
+			{
+			/* VRS: allow null cert if auth == KRB5 */
+			if ((s->s3->tmp.new_cipher->algorithm_auth != SSL_aKRB5) ||
+			    (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kKRB5))
+				{
+				SSLerr(SSL_F_SSL3_SEND_SERVER_CERTIFICATE,ERR_R_INTERNAL_ERROR);
+				return(0);
+				}
+			}
+
+		l=ssl3_output_cert_chain(s,x);
+		s->state=SSL3_ST_SW_CERT_B;
+		s->init_num=(int)l;
+		s->init_off=0;
+		}
+
+	/* SSL3_ST_SW_CERT_B */
+	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+	}
+#ifndef OPENSSL_NO_TLSEXT
+int ssl3_send_newsession_ticket(SSL *s)
+	{
+	if (s->state == SSL3_ST_SW_SESSION_TICKET_A)
+		{
+		unsigned char *p, *senc, *macstart;
+		int len, slen;
+		unsigned int hlen;
+		EVP_CIPHER_CTX ctx;
+		HMAC_CTX hctx;
+		SSL_CTX *tctx = s->initial_ctx;
+		unsigned char iv[EVP_MAX_IV_LENGTH];
+		unsigned char key_name[16];
+
+		/* get session encoding length */
+		slen = i2d_SSL_SESSION(s->session, NULL);
+		/* Some length values are 16 bits, so forget it if session is
+ 		 * too long
+ 		 */
+		if (slen > 0xFF00)
+			return -1;
+		/* Grow buffer if need be: the length calculation is as
+ 		 * follows 1 (size of message name) + 3 (message length
+ 		 * bytes) + 4 (ticket lifetime hint) + 2 (ticket length) +
+ 		 * 16 (key name) + max_iv_len (iv length) +
+ 		 * session_length + max_enc_block_size (max encrypted session
+ 		 * length) + max_md_size (HMAC).
+ 		 */
+		if (!BUF_MEM_grow(s->init_buf,
+			26 + EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH +
+			EVP_MAX_MD_SIZE + slen))
+			return -1;
+		senc = OPENSSL_malloc(slen);
+		if (!senc)
+			return -1;
+		p = senc;
+		i2d_SSL_SESSION(s->session, &p);
+
+		p=(unsigned char *)s->init_buf->data;
+		/* do the header */
+		*(p++)=SSL3_MT_NEWSESSION_TICKET;
+		/* Skip message length for now */
+		p += 3;
+		EVP_CIPHER_CTX_init(&ctx);
+		HMAC_CTX_init(&hctx);
+		/* Initialize HMAC and cipher contexts. If callback present
+		 * it does all the work otherwise use generated values
+		 * from parent ctx.
+		 */
+		if (tctx->tlsext_ticket_key_cb)
+			{
+			if (tctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx,
+							 &hctx, 1) < 0)
+				{
+				OPENSSL_free(senc);
+				return -1;
+				}
+			}
+		else
+			{
+			RAND_pseudo_bytes(iv, 16);
+			EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
+					tctx->tlsext_tick_aes_key, iv);
+			HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16,
+					tlsext_tick_md(), NULL);
+			memcpy(key_name, tctx->tlsext_tick_key_name, 16);
+			}
+		l2n(s->session->tlsext_tick_lifetime_hint, p);
+		/* Skip ticket length for now */
+		p += 2;
+		/* Output key name */
+		macstart = p;
+		memcpy(p, key_name, 16);
+		p += 16;
+		/* output IV */
+		memcpy(p, iv, EVP_CIPHER_CTX_iv_length(&ctx));
+		p += EVP_CIPHER_CTX_iv_length(&ctx);
+		/* Encrypt session data */
+		EVP_EncryptUpdate(&ctx, p, &len, senc, slen);
+		p += len;
+		EVP_EncryptFinal(&ctx, p, &len);
+		p += len;
+		EVP_CIPHER_CTX_cleanup(&ctx);
+
+		HMAC_Update(&hctx, macstart, p - macstart);
+		HMAC_Final(&hctx, p, &hlen);
+		HMAC_CTX_cleanup(&hctx);
+
+		p += hlen;
+		/* Now write out lengths: p points to end of data written */
+		/* Total length */
+		len = p - (unsigned char *)s->init_buf->data;
+		p=(unsigned char *)s->init_buf->data + 1;
+		l2n3(len - 4, p); /* Message length */
+		p += 4;
+		s2n(len - 10, p);  /* Ticket length */
+
+		/* number of bytes to write */
+		s->init_num= len;
+		s->state=SSL3_ST_SW_SESSION_TICKET_B;
+		s->init_off=0;
+		OPENSSL_free(senc);
+		}
+
+	/* SSL3_ST_SW_SESSION_TICKET_B */
+	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+	}
+
+int ssl3_send_cert_status(SSL *s)
+	{
+	if (s->state == SSL3_ST_SW_CERT_STATUS_A)
+		{
+		unsigned char *p;
+		/* Grow buffer if need be: the length calculation is as
+ 		 * follows 1 (message type) + 3 (message length) +
+ 		 * 1 (ocsp response type) + 3 (ocsp response length)
+ 		 * + (ocsp response)
+ 		 */
+		if (!BUF_MEM_grow(s->init_buf, 8 + s->tlsext_ocsp_resplen))
+			return -1;
+
+		p=(unsigned char *)s->init_buf->data;
+
+		/* do the header */
+		*(p++)=SSL3_MT_CERTIFICATE_STATUS;
+		/* message length */
+		l2n3(s->tlsext_ocsp_resplen + 4, p);
+		/* status type */
+		*(p++)= s->tlsext_status_type;
+		/* length of OCSP response */
+		l2n3(s->tlsext_ocsp_resplen, p);
+		/* actual response */
+		memcpy(p, s->tlsext_ocsp_resp, s->tlsext_ocsp_resplen);
+		/* number of bytes to write */
+		s->init_num = 8 + s->tlsext_ocsp_resplen;
+		s->state=SSL3_ST_SW_CERT_STATUS_B;
+		s->init_off = 0;
+		}
+
+	/* SSL3_ST_SW_CERT_STATUS_B */
+	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+	}
+#endif
diff --git a/lib/openssl/ssl/ssl-lib.com b/lib/openssl/ssl/ssl-lib.com
new file mode 100644
index 0000000..c5ca9e1
--- /dev/null
+++ b/lib/openssl/ssl/ssl-lib.com
@@ -0,0 +1,1057 @@
+$!
+$!  SSL-LIB.COM
+$!  Written By:  Robert Byer
+$!               Vice-President
+$!               A-Com Computing, Inc.
+$!               byer@mail.all-net.net
+$!
+$!  Changes by Richard Levitte <richard@levitte.org>
+$!
+$!  This command file compiles and creates the "[.xxx.EXE.SSL]LIBSSL.OLB" 
+$!  library for OpenSSL.  The "xxx" denotes the machine architecture of
+$!  ALPHA, IA64 or VAX.
+$!
+$!  It is written to detect what type of machine you are compiling on
+$!  (i.e. ALPHA or VAX) and which "C" compiler you have (i.e. VAXC, DECC 
+$!  or GNU C) or you can specify which compiler to use.
+$!
+$!  Specify the following as P1 to build just that part or ALL to just
+$!  build everything.
+$!
+$!    		LIBRARY    To just compile the [.xxx.EXE.SSL]LIBSSL.OLB Library.
+$!    		SSL_TASK   To just compile the [.xxx.EXE.SSL]SSL_TASK.EXE
+$!
+$!  Specify DEBUG or NODEBUG as P2 to compile with or without debugger
+$!  information.
+$!
+$!  Specify which compiler at P3 to try to compile under.
+$!
+$!	   VAXC	 For VAX C.
+$!	   DECC	 For DEC C.
+$!	   GNUC	 For GNU C.
+$!
+$!  If you don't specify a compiler, it will try to determine which
+$!  "C" compiler to use.
+$!
+$!  P4, if defined, sets a TCP/IP library to use, through one of the following
+$!  keywords:
+$!
+$!	UCX		for UCX
+$!	TCPIP		for TCPIP (post UCX)
+$!	SOCKETSHR	for SOCKETSHR+NETLIB
+$!
+$!  P5, if defined, sets a compiler thread NOT needed on OpenVMS 7.1 (and up)
+$!
+$!
+$! Define A TCP/IP Library That We Will Need To Link To.
+$! (That Is, If We Need To Link To One.)
+$!
+$ TCPIP_LIB = ""
+$!
+$! Check What Architecture We Are Using.
+$!
+$ IF (F$GETSYI("CPU").LT.128)
+$ THEN
+$!
+$!  The Architecture Is VAX.
+$!
+$   ARCH = "VAX"
+$!
+$! Else...
+$!
+$ ELSE
+$!
+$!  The Architecture Is Alpha, IA64 or whatever comes in the future.
+$!
+$   ARCH = F$EDIT( F$GETSYI( "ARCH_NAME"), "UPCASE")
+$   IF (ARCH .EQS. "") THEN ARCH = "UNK"
+$!
+$! End The Architecture Check.
+$!
+$ ENDIF
+$!
+$! Define The OBJ Directory.
+$!
+$ OBJ_DIR := SYS$DISK:[-.'ARCH'.OBJ.SSL]
+$!
+$! Define The EXE Directory.
+$!
+$ EXE_DIR := SYS$DISK:[-.'ARCH'.EXE.SSL]
+$!
+$! Check To Make Sure We Have Valid Command Line Parameters.
+$!
+$ GOSUB CHECK_OPTIONS
+$!
+$! Initialise logical names and such
+$!
+$ GOSUB INITIALISE
+$!
+$! Tell The User What Kind of Machine We Run On.
+$!
+$ WRITE SYS$OUTPUT "Compiling On A ",ARCH," Machine."
+$!
+$! Check To See If The Architecture Specific OBJ Directory Exists.
+$!
+$ IF (F$PARSE(OBJ_DIR).EQS."")
+$ THEN
+$!
+$!  It Dosen't Exist, So Create It.
+$!
+$   CREATE/DIR 'OBJ_DIR'
+$!
+$! End The Architecture Specific OBJ Directory Check.
+$!
+$ ENDIF
+$!
+$! Check To See If The Architecture Specific Directory Exists.
+$!
+$ IF (F$PARSE(EXE_DIR).EQS."")
+$ THEN
+$!
+$!  It Dosen't Exist, So Create It.
+$!
+$   CREATE/DIR 'EXE_DIR'
+$!
+$! End The Architecture Specific Directory Check.
+$!
+$ ENDIF
+$!
+$! Define The Library Name.
+$!
+$ SSL_LIB := 'EXE_DIR'LIBSSL.OLB
+$!
+$! Define The CRYPTO-LIB We Are To Use.
+$!
+$ CRYPTO_LIB := SYS$DISK:[-.'ARCH'.EXE.CRYPTO]LIBCRYPTO.OLB
+$!
+$! Check To See What We Are To Do.
+$!
+$ IF (BUILDALL.EQS."TRUE")
+$ THEN
+$!
+$!  Since Nothing Special Was Specified, Do Everything.
+$!
+$   GOSUB LIBRARY
+$   GOSUB SSL_TASK
+$!
+$! Else...
+$!
+$ ELSE
+$!
+$!  Build Just What The User Wants Us To Build.
+$!
+$   GOSUB 'BUILDALL'
+$!
+$! End The BUILDALL Check.
+$!
+$ ENDIF
+$!
+$! Time To EXIT.
+$!
+$ EXIT:
+$ GOSUB CLEANUP
+$ EXIT   
+$!
+$! Compile The Library.
+$!
+$ LIBRARY:
+$!
+$! Check To See If We Already Have A "[.xxx.EXE.SSL]LIBSSL.OLB" Library...
+$!
+$ IF (F$SEARCH(SSL_LIB).EQS."")
+$ THEN
+$!
+$! Guess Not, Create The Library.
+$!
+$   LIBRARY/CREATE/OBJECT 'SSL_LIB'
+$!
+$! End The Library Exist Check.
+$!
+$ ENDIF
+$!
+$! Define The Different SSL "library" Files.
+$!
+$ LIB_SSL = "s2_meth,s2_srvr,s2_clnt,s2_lib,s2_enc,s2_pkt,"+ -
+	    "s3_meth,s3_srvr,s3_clnt,s3_lib,s3_enc,s3_pkt,s3_both,"+ -
+	    "s23_meth,s23_srvr,s23_clnt,s23_lib,s23_pkt,"+ -
+	    "t1_meth,t1_srvr,t1_clnt,t1_lib,t1_enc,"+ -
+	    "d1_meth,d1_srvr,d1_clnt,d1_lib,d1_pkt,"+ -
+	    "d1_both,d1_enc,"+ -
+	    "ssl_lib,ssl_err2,ssl_cert,ssl_sess,"+ -
+	    "ssl_ciph,ssl_stat,ssl_rsa,"+ -
+	    "ssl_asn1,ssl_txt,ssl_algs,"+ -
+	    "bio_ssl,ssl_err,kssl,t1_reneg"
+$!
+$! Tell The User That We Are Compiling The Library.
+$!
+$ WRITE SYS$OUTPUT "Building The ",SSL_LIB," Library."
+$!
+$! Define A File Counter And Set It To "0"
+$!
+$ FILE_COUNTER = 0
+$!
+$! Top Of The File Loop.
+$!
+$ NEXT_FILE:
+$!
+$! O.K, Extract The File Name From The File List.
+$!
+$ FILE_NAME = F$ELEMENT(FILE_COUNTER,",",LIB_SSL)
+$!
+$! Check To See If We Are At The End Of The File List.
+$!
+$ IF (FILE_NAME.EQS.",") THEN GOTO FILE_DONE
+$!
+$! Increment The Counter.
+$!
+$ FILE_COUNTER = FILE_COUNTER + 1
+$!
+$! Create The Source File Name.
+$!
+$ SOURCE_FILE = "SYS$DISK:[]" + FILE_NAME + ".C"
+$!
+$! Create The Object File Name.
+$!
+$ OBJECT_FILE = OBJ_DIR + FILE_NAME + ".OBJ"
+$ ON WARNING THEN GOTO NEXT_FILE
+$!
+$! Check To See If The File We Want To Compile Is Actually There.
+$!
+$ IF (F$SEARCH(SOURCE_FILE).EQS."")
+$ THEN
+$!
+$!  Tell The User That The File Dosen't Exist.
+$!
+$   WRITE SYS$OUTPUT ""
+$   WRITE SYS$OUTPUT "The File ",SOURCE_FILE," Dosen't Exist."
+$   WRITE SYS$OUTPUT ""
+$!
+$!  Exit The Build.
+$!
+$   EXIT
+$!
+$! End The File Exists Check.
+$!
+$ ENDIF
+$!
+$!  Tell The User What File We Are Compiling.
+$!
+$ WRITE SYS$OUTPUT "	",FILE_NAME,".c"
+$!
+$! Compile The File.
+$!
+$ ON ERROR THEN GOTO NEXT_FILE
+$ CC/OBJECT='OBJECT_FILE' 'SOURCE_FILE'
+$!
+$! Add It To The Library.
+$!
+$ LIBRARY/REPLACE/OBJECT 'SSL_LIB' 'OBJECT_FILE'
+$!
+$! Time To Clean Up The Object File.
+$!
+$ DELETE 'OBJECT_FILE';*
+$!
+$! Go Back And Get The Next File Name.
+$!
+$ GOTO NEXT_FILE
+$!
+$! All Done With This Library.
+$!
+$ FILE_DONE:
+$!
+$! Tell The User That We Are All Done.
+$!
+$ WRITE SYS$OUTPUT "Library ",SSL_LIB," Compiled."
+$!
+$! Time To RETURN.
+$!
+$ RETURN
+$ SSL_TASK:
+$!
+$! Check To See If We Have The Proper Libraries.
+$!
+$ GOSUB LIB_CHECK
+$!
+$! Check To See If We Have A Linker Option File.
+$!
+$ GOSUB CHECK_OPT_FILE
+$!
+$! Check To See If The File We Want To Compile Is Actually There.
+$!
+$ IF (F$SEARCH("SYS$DISK:[]SSL_TASK.C").EQS."")
+$ THEN
+$!
+$!  Tell The User That The File Dosen't Exist.
+$!
+$   WRITE SYS$OUTPUT ""
+$   WRITE SYS$OUTPUT "The File SSL_TASK.C Dosen't Exist."
+$   WRITE SYS$OUTPUT ""
+$!
+$!  Exit The Build.
+$!
+$   EXIT
+$!
+$! End The SSL_TASK.C File Check.
+$!
+$ ENDIF
+$!
+$! Tell The User We Are Creating The SSL_TASK.
+$!
+$ WRITE SYS$OUTPUT "Creating SSL_TASK OSU HTTP SSL Engine."	
+$!
+$! Compile The File.
+$!
+$ ON ERROR THEN GOTO SSL_TASK_END
+$ CC5/OBJECT='OBJ_DIR'SSL_TASK.OBJ SYS$DISK:[]SSL_TASK.C
+$!
+$! Link The Program.
+$! Check To See If We Are To Link With A Specific TCP/IP Library.
+$!
+$ IF (TCPIP_LIB.NES."")
+$ THEN
+$!
+$!  Link With TCP/IP Library.
+$!
+$   LINK/'DEBUGGER'/'TRACEBACK'/EXE='EXE_DIR'SSL_TASK.EXE -
+        'OBJ_DIR'SSL_TASK.OBJ, -
+	'SSL_LIB'/LIBRARY,'CRYPTO_LIB'/LIBRARY, -
+        'TCPIP_LIB','OPT_FILE'/OPTION
+$!
+$! Else...
+$!
+$ ELSE
+$!
+$!  Don't Link With TCP/IP Library.
+$!
+$   LINK/'DEBUGGER'/'TRACEBACK'/EXE='EXE_DIR'SSL_TASK.EXE -
+        'OBJ_DIR'SSL_TASK.OBJ,-
+	'SSL_LIB'/LIBRARY,'CRYPTO_LIB'/LIBRARY, -
+        'OPT_FILE'/OPTION
+$!
+$! End The TCP/IP Library Check.
+$!
+$ ENDIF
+$!
+$! Time To Return.
+$!
+$SSL_TASK_END:
+$ RETURN
+$!
+$! Check For The Link Option FIle.
+$!
+$ CHECK_OPT_FILE:
+$!
+$! Check To See If We Need To Make A VAX C Option File.
+$!
+$ IF (COMPILER.EQS."VAXC")
+$ THEN
+$!
+$!  Check To See If We Already Have A VAX C Linker Option File.
+$!
+$   IF (F$SEARCH(OPT_FILE).EQS."")
+$   THEN
+$!
+$!    We Need A VAX C Linker Option File.
+$!
+$     CREATE 'OPT_FILE'
+$DECK
+!
+! Default System Options File To Link Agianst 
+! The Sharable VAX C Runtime Library.
+!
+SYS$SHARE:VAXCRTL.EXE/SHARE
+$EOD
+$!
+$!  End The Option File Check.
+$!
+$   ENDIF
+$!
+$! End The VAXC Check.
+$!
+$ ENDIF
+$!
+$! Check To See If We Need A GNU C Option File.
+$!
+$ IF (COMPILER.EQS."GNUC")
+$ THEN
+$!
+$!  Check To See If We Already Have A GNU C Linker Option File.
+$!
+$   IF (F$SEARCH(OPT_FILE).EQS."")
+$   THEN
+$!
+$!    We Need A GNU C Linker Option File.
+$!
+$     CREATE 'OPT_FILE'
+$DECK
+!
+! Default System Options File To Link Agianst 
+! The Sharable C Runtime Library.
+!
+GNU_CC:[000000]GCCLIB/LIBRARY
+SYS$SHARE:VAXCRTL/SHARE
+$EOD
+$!
+$!  End The Option File Check.
+$!
+$   ENDIF
+$!
+$! End The GNU C Check.
+$!
+$ ENDIF
+$!
+$! Check To See If We Need A DEC C Option File.
+$!
+$ IF (COMPILER.EQS."DECC")
+$ THEN
+$!
+$!  Check To See If We Already Have A DEC C Linker Option File.
+$!
+$   IF (F$SEARCH(OPT_FILE).EQS."")
+$   THEN
+$!
+$!    Figure Out If We Need A non-VAX Or A VAX Linker Option File.
+$!
+$     IF (ARCH.EQS."VAX")
+$     THEN
+$!
+$!      We Need A DEC C Linker Option File For VAX.
+$!
+$       CREATE 'OPT_FILE'
+$DECK
+!
+! Default System Options File To Link Agianst 
+! The Sharable DEC C Runtime Library.
+!
+SYS$SHARE:DECC$SHR.EXE/SHARE
+$EOD
+$!
+$!    Else...
+$!
+$     ELSE
+$!
+$!      Create The non-VAX Linker Option File.
+$!
+$       CREATE 'OPT_FILE'
+$DECK
+!
+! Default System Options File For non-VAX To Link Agianst 
+! The Sharable C Runtime Library.
+!
+SYS$SHARE:CMA$OPEN_LIB_SHR/SHARE
+SYS$SHARE:CMA$OPEN_RTL/SHARE
+$EOD
+$!
+$!    End The DEC C Option File Check.
+$!
+$     ENDIF
+$!
+$!  End The Option File Search.
+$!
+$   ENDIF
+$!
+$! End The DEC C Check.
+$!
+$ ENDIF
+$!
+$!  Tell The User What Linker Option File We Are Using.
+$!
+$ WRITE SYS$OUTPUT "Using Linker Option File ",OPT_FILE,"."	
+$!
+$! Time To RETURN.
+$!
+$ RETURN
+$ LIB_CHECK:
+$!
+$! Look For The VAX Library LIBSSL.OLB.
+$!
+$ IF (F$SEARCH(SSL_LIB).EQS."")
+$ THEN
+$!
+$!  Tell The User We Can't Find The LIBSSL.OLB Library.
+$!
+$   WRITE SYS$OUTPUT ""
+$   WRITE SYS$OUTPUT "Can't Find The Library ",SSL_LIB,"."
+$   WRITE SYS$OUTPUT "We Can't Link Without It."
+$   WRITE SYS$OUTPUT ""
+$!
+$!  Since We Can't Link Without It, Exit.
+$!
+$   EXIT
+$!
+$! End The LIBSSL.OLB Library Check.
+$!
+$ ENDIF
+$!
+$! Look For The Library LIBCRYPTO.OLB.
+$!
+$ IF (F$SEARCH(CRYPTO_LIB).EQS."")
+$ THEN
+$!
+$!  Tell The User We Can't Find The LIBCRYPTO.OLB Library.
+$!
+$   WRITE SYS$OUTPUT ""
+$   WRITE SYS$OUTPUT "Can't Find The Library ",CRYPTO_LIB,"."
+$   WRITE SYS$OUTPUT "We Can't Link Without It."
+$   WRITE SYS$OUTPUT ""
+$!
+$!  Since We Can't Link Without It, Exit.
+$!
+$   EXIT
+$!
+$! End The LIBCRYPTO.OLB Library Check.
+$!
+$ ENDIF
+$!
+$! Time To Return.
+$!
+$ RETURN
+$!
+$! Check The User's Options.
+$!
+$ CHECK_OPTIONS:
+$!
+$! Check To See If P1 Is Blank.
+$!
+$ IF (P1.EQS."ALL")
+$ THEN
+$!
+$!   P1 Is Blank, So Build Everything.
+$!
+$    BUILDALL = "TRUE"
+$!
+$! Else...
+$!
+$ ELSE
+$!
+$!  Else, Check To See If P1 Has A Valid Argument.
+$!
+$   IF (P1.EQS."LIBRARY").OR.(P1.EQS."SSL_TASK")
+$   THEN
+$!
+$!    A Valid Argument.
+$!
+$     BUILDALL = P1
+$!
+$!  Else...
+$!
+$   ELSE
+$!
+$!    Tell The User We Don't Know What They Want.
+$!
+$     WRITE SYS$OUTPUT ""
+$     WRITE SYS$OUTPUT "The Option ",P1," Is Invalid.  The Valid Options Are:"
+$     WRITE SYS$OUTPUT ""
+$     WRITE SYS$OUTPUT "    ALL      :  Just Build Everything."
+$     WRITE SYS$OUTPUT "    LIBRARY  :  To Compile Just The [.xxx.EXE.SSL]LIBSSL.OLB Library."
+$     WRITE SYS$OUTPUT "    SSL_TASK :  To Compile Just The [.xxx.EXE.SSL]SSL_TASK.EXE Program."
+$     WRITE SYS$OUTPUT ""
+$     WRITE SYS$OUTPUT " Where 'xxx' Stands For:"
+$     WRITE SYS$OUTPUT ""
+$     WRITE SYS$OUTPUT "    ALPHA    :  Alpha Architecture."
+$     WRITE SYS$OUTPUT "    IA64     :  IA64 Architecture."
+$     WRITE SYS$OUTPUT "    VAX      :  VAX Architecture."
+$     WRITE SYS$OUTPUT ""
+$!
+$!    Time To EXIT.
+$!
+$     EXIT
+$!
+$!  End The Valid Argument Check.
+$!
+$   ENDIF
+$!
+$! End The P1 Check.
+$!
+$ ENDIF
+$!
+$! Check To See If P2 Is Blank.
+$!
+$ IF (P2.EQS."NODEBUG")
+$ THEN
+$!
+$!   P2 Is NODEBUG, So Compile Without Debugger Information.
+$!
+$    DEBUGGER  = "NODEBUG"
+$    TRACEBACK = "NOTRACEBACK" 
+$    GCC_OPTIMIZE = "OPTIMIZE"
+$    CC_OPTIMIZE = "OPTIMIZE"
+$    WRITE SYS$OUTPUT "No Debugger Information Will Be Produced During Compile."
+$    WRITE SYS$OUTPUT "Compiling With Compiler Optimization."
+$!
+$! Else...
+$!
+$ ELSE
+$!
+$!  Check To See If We Are To Compile With Debugger Information.
+$!
+$   IF (P2.EQS."DEBUG")
+$   THEN
+$!
+$!    Compile With Debugger Information.
+$!
+$     DEBUGGER  = "DEBUG"
+$     TRACEBACK = "TRACEBACK"
+$     GCC_OPTIMIZE = "NOOPTIMIZE"
+$     CC_OPTIMIZE = "NOOPTIMIZE"
+$     WRITE SYS$OUTPUT "Debugger Information Will Be Produced During Compile."
+$     WRITE SYS$OUTPUT "Compiling Without Compiler Optimization."
+$   ELSE
+$!
+$!    Tell The User Entered An Invalid Option..
+$!
+$     WRITE SYS$OUTPUT ""
+$     WRITE SYS$OUTPUT "The Option ",P2," Is Invalid.  The Valid Options Are:"
+$     WRITE SYS$OUTPUT ""
+$     WRITE SYS$OUTPUT "    DEBUG    :  Compile With The Debugger Information."
+$     WRITE SYS$OUTPUT "    NODEBUG  :  Compile Without The Debugger Information."
+$     WRITE SYS$OUTPUT ""
+$!
+$!    Time To EXIT.
+$!
+$     EXIT
+$!
+$!  End The Valid Argument Check.
+$!
+$   ENDIF
+$!
+$! End The P2 Check.
+$!
+$ ENDIF
+$!
+$! Special Threads For OpenVMS v7.1 Or Later
+$!
+$! Written By:  Richard Levitte
+$!              richard@levitte.org
+$!
+$!
+$! Check To See If We Have A Option For P5.
+$!
+$ IF (P5.EQS."")
+$ THEN
+$!
+$!  Get The Version Of VMS We Are Using.
+$!
+$   ISSEVEN :=
+$   TMP = F$ELEMENT(0,"-",F$EXTRACT(1,4,F$GETSYI("VERSION")))
+$   TMP = F$INTEGER(F$ELEMENT(0,".",TMP)+F$ELEMENT(1,".",TMP))
+$!
+$!  Check To See If The VMS Version Is v7.1 Or Later.
+$!
+$   IF (TMP.GE.71)
+$   THEN
+$!
+$!    We Have OpenVMS v7.1 Or Later, So Use The Special Threads.
+$!
+$     ISSEVEN := ,PTHREAD_USE_D4
+$!
+$!  End The VMS Version Check.
+$!
+$   ENDIF
+$!
+$! End The P5 Check.
+$!
+$ ENDIF
+$!
+$! Check To See If P3 Is Blank.
+$!
+$ IF (P3.EQS."")
+$ THEN
+$!
+$!  O.K., The User Didn't Specify A Compiler, Let's Try To
+$!  Find Out Which One To Use.
+$!
+$!  Check To See If We Have GNU C.
+$!
+$   IF (F$TRNLNM("GNU_CC").NES."")
+$   THEN
+$!
+$!    Looks Like GNUC, Set To Use GNUC.
+$!
+$     P3 = "GNUC"
+$!
+$!  End The GNU C Compiler Check.
+$!
+$   ELSE
+$!
+$!  Check To See If We Have VAXC Or DECC.
+$!
+$     IF (ARCH.NES."VAX").OR.(F$TRNLNM("DECC$CC_DEFAULT").NES."")
+$     THEN 
+$!
+$!      Looks Like DECC, Set To Use DECC.
+$!
+$       P3 = "DECC"
+$!
+$!      Else...
+$!
+$     ELSE
+$!
+$!      Looks Like VAXC, Set To Use VAXC.
+$!
+$       P3 = "VAXC"
+$!
+$!    End The VAXC Compiler Check.
+$!
+$     ENDIF
+$!
+$!  End The DECC & VAXC Compiler Check.
+$!
+$   ENDIF
+$!
+$!  End The Compiler Check.
+$!
+$ ENDIF
+$!
+$! Check To See If We Have A Option For P4.
+$!
+$ IF (P4.EQS."")
+$ THEN
+$!
+$!  Find out what socket library we have available
+$!
+$   IF F$PARSE("SOCKETSHR:") .NES. ""
+$   THEN
+$!
+$!    We have SOCKETSHR, and it is my opinion that it's the best to use.
+$!
+$     P4 = "SOCKETSHR"
+$!
+$!    Tell the user
+$!
+$     WRITE SYS$OUTPUT "Using SOCKETSHR for TCP/IP"
+$!
+$!    Else, let's look for something else
+$!
+$   ELSE
+$!
+$!    Like UCX (the reason to do this before Multinet is that the UCX
+$!    emulation is easier to use...)
+$!
+$     IF F$TRNLNM("UCX$IPC_SHR") .NES. "" -
+	 .OR. F$PARSE("SYS$SHARE:UCX$IPC_SHR.EXE") .NES. "" -
+	 .OR. F$PARSE("SYS$LIBRARY:UCX$IPC.OLB") .NES. ""
+$     THEN
+$!
+$!	Last resort: a UCX or UCX-compatible library
+$!
+$	P4 = "UCX"
+$!
+$!      Tell the user
+$!
+$       WRITE SYS$OUTPUT "Using UCX or an emulation thereof for TCP/IP"
+$!
+$!	That was all...
+$!
+$     ENDIF
+$   ENDIF
+$ ENDIF
+$!
+$! Set Up Initial CC Definitions, Possibly With User Ones
+$!
+$ CCDEFS = "TCPIP_TYPE_''P4'"
+$ IF F$TYPE(USER_CCDEFS) .NES. "" THEN CCDEFS = CCDEFS + "," + USER_CCDEFS
+$ CCEXTRAFLAGS = ""
+$ IF F$TYPE(USER_CCFLAGS) .NES. "" THEN CCEXTRAFLAGS = USER_CCFLAGS
+$ CCDISABLEWARNINGS = "LONGLONGTYPE,LONGLONGSUFX,FOUNDCR"
+$ IF F$TYPE(USER_CCDISABLEWARNINGS) .NES. "" THEN -
+	CCDISABLEWARNINGS = CCDISABLEWARNINGS + "," + USER_CCDISABLEWARNINGS
+$!
+$!  Check To See If The User Entered A Valid Paramter.
+$!
+$ IF (P3.EQS."VAXC").OR.(P3.EQS."DECC").OR.(P3.EQS."GNUC")
+$ THEN
+$!
+$!  Check To See If The User Wanted DECC.
+$!
+$   IF (P3.EQS."DECC")
+$   THEN
+$!
+$!    Looks Like DECC, Set To Use DECC.
+$!
+$     COMPILER = "DECC"
+$!
+$!    Tell The User We Are Using DECC.
+$!
+$     WRITE SYS$OUTPUT "Using DECC 'C' Compiler."
+$!
+$!    Use DECC...
+$!
+$     CC = "CC"
+$     IF ARCH.EQS."VAX" .AND. F$TRNLNM("DECC$CC_DEFAULT").NES."/DECC" -
+	 THEN CC = "CC/DECC"
+$     CC = CC + "/''CC_OPTIMIZE'/''DEBUGGER'/STANDARD=ANSI89" + -
+           "/NOLIST/PREFIX=ALL" + -
+	   "/INCLUDE=(SYS$DISK:[-.CRYPTO],SYS$DISK:[-])" + CCEXTRAFLAGS
+$!
+$!    Define The Linker Options File Name.
+$!
+$     OPT_FILE = "''EXE_DIR'VAX_DECC_OPTIONS.OPT"
+$!
+$!  End DECC Check.
+$!
+$   ENDIF
+$!
+$!  Check To See If We Are To Use VAXC.
+$!
+$   IF (P3.EQS."VAXC")
+$   THEN
+$!
+$!    Looks Like VAXC, Set To Use VAXC.
+$!
+$     COMPILER = "VAXC"
+$!
+$!    Tell The User We Are Using VAX C.
+$!
+$     WRITE SYS$OUTPUT "Using VAXC 'C' Compiler."
+$!
+$!    Compile Using VAXC.
+$!
+$     CC = "CC"
+$     IF ARCH.NES."VAX"
+$     THEN
+$	WRITE SYS$OUTPUT "There is no VAX C on ''ARCH'!"
+$	EXIT
+$     ENDIF
+$     IF F$TRNLNM("DECC$CC_DEFAULT").EQS."/DECC" THEN CC = "CC/VAXC"
+$     CC = CC + "/''CC_OPTIMIZE'/''DEBUGGER'/NOLIST" + -
+	   "/INCLUDE=(SYS$DISK:[-.CRYPTO],SYS$DISK:[-])" + CCEXTRAFLAGS
+$     CCDEFS = CCDEFS + ",""VAXC"""
+$!
+$!    Define <sys> As SYS$COMMON:[SYSLIB]
+$!
+$     DEFINE/NOLOG SYS SYS$COMMON:[SYSLIB]
+$!
+$!    Define The Linker Options File Name.
+$!
+$     OPT_FILE = "''EXE_DIR'VAX_VAXC_OPTIONS.OPT"
+$!
+$!  End VAXC Check
+$!
+$   ENDIF
+$!
+$!  Check To See If We Are To Use GNU C.
+$!
+$   IF (P3.EQS."GNUC")
+$   THEN
+$!
+$!    Looks Like GNUC, Set To Use GNUC.
+$!
+$     COMPILER = "GNUC"
+$!
+$!    Tell The User We Are Using GNUC.
+$!
+$     WRITE SYS$OUTPUT "Using GNU 'C' Compiler."
+$!
+$!    Use GNU C...
+$!
+$     IF F$TYPE(GCC) .EQS. "" THEN GCC := GCC
+$     CC = GCC+"/NOCASE_HACK/''GCC_OPTIMIZE'/''DEBUGGER'/NOLIST" + -
+	   "/INCLUDE=(SYS$DISK:[-.CRYPTO],SYS$DISK:[-])" + CCEXTRAFLAGS
+$!
+$!    Define The Linker Options File Name.
+$!
+$     OPT_FILE = "''EXE_DIR'VAX_GNUC_OPTIONS.OPT"
+$!
+$!  End The GNU C Check.
+$!
+$   ENDIF
+$!
+$!  Set up default defines
+$!
+$   CCDEFS = """FLAT_INC=1""," + CCDEFS
+$!
+$!  Finish up the definition of CC.
+$!
+$   IF COMPILER .EQS. "DECC"
+$   THEN
+$     IF CCDISABLEWARNINGS .EQS. ""
+$     THEN
+$       CC4DISABLEWARNINGS = "DOLLARID"
+$     ELSE
+$       CC4DISABLEWARNINGS = CCDISABLEWARNINGS + ",DOLLARID"
+$       CCDISABLEWARNINGS = "/WARNING=(DISABLE=(" + CCDISABLEWARNINGS + "))"
+$     ENDIF
+$     CC4DISABLEWARNINGS = "/WARNING=(DISABLE=(" + CC4DISABLEWARNINGS + "))"
+$   ELSE
+$     CCDISABLEWARNINGS = ""
+$     CC4DISABLEWARNINGS = ""
+$   ENDIF
+$   CC2 = CC + "/DEFINE=(" + CCDEFS + ",_POSIX_C_SOURCE)" + CCDISABLEWARNINGS
+$   CC3 = CC + "/DEFINE=(" + CCDEFS + ISSEVEN + ")" + CCDISABLEWARNINGS
+$   CC = CC + "/DEFINE=(" + CCDEFS + ")" + CCDISABLEWARNINGS
+$   IF COMPILER .EQS. "DECC"
+$   THEN
+$     CC4 = CC - CCDISABLEWARNINGS + CC4DISABLEWARNINGS
+$     CC5 = CC3 - CCDISABLEWARNINGS + CC4DISABLEWARNINGS
+$   ELSE
+$     CC4 = CC
+$     CC5 = CC3
+$   ENDIF
+$!
+$!  Show user the result
+$!
+$   WRITE/SYMBOL SYS$OUTPUT "Main Compiling Command: ",CC
+$!
+$!  Else The User Entered An Invalid Argument.
+$!
+$ ELSE
+$!
+$!  Tell The User We Don't Know What They Want.
+$!
+$   WRITE SYS$OUTPUT ""
+$   WRITE SYS$OUTPUT "The Option ",P3," Is Invalid.  The Valid Options Are:"
+$   WRITE SYS$OUTPUT ""
+$   WRITE SYS$OUTPUT "    VAXC  :  To Compile With VAX C."
+$   WRITE SYS$OUTPUT "    DECC  :  To Compile With DEC C."
+$   WRITE SYS$OUTPUT "    GNUC  :  To Compile With GNU C."
+$   WRITE SYS$OUTPUT ""
+$!
+$!  Time To EXIT.
+$!
+$   EXIT
+$ ENDIF
+$!
+$! Time to check the contents, and to make sure we get the correct library.
+$!
+$ IF P4.EQS."SOCKETSHR" .OR. P4.EQS."MULTINET" .OR. P4.EQS."UCX" -
+     .OR. P4.EQS."TCPIP" .OR. P4.EQS."NONE"
+$ THEN
+$!
+$!  Check to see if SOCKETSHR was chosen
+$!
+$   IF P4.EQS."SOCKETSHR"
+$   THEN
+$!
+$!    Set the library to use SOCKETSHR
+$!
+$     TCPIP_LIB = "SYS$DISK:[-.VMS]SOCKETSHR_SHR.OPT/OPT"
+$!
+$!    Done with SOCKETSHR
+$!
+$   ENDIF
+$!
+$!  Check to see if MULTINET was chosen
+$!
+$   IF P4.EQS."MULTINET"
+$   THEN
+$!
+$!    Set the library to use UCX emulation.
+$!
+$     P4 = "UCX"
+$!
+$!    Done with MULTINET
+$!
+$   ENDIF
+$!
+$!  Check to see if UCX was chosen
+$!
+$   IF P4.EQS."UCX"
+$   THEN
+$!
+$!    Set the library to use UCX.
+$!
+$     TCPIP_LIB = "SYS$DISK:[-.VMS]UCX_SHR_DECC.OPT/OPT"
+$     IF F$TRNLNM("UCX$IPC_SHR") .NES. ""
+$     THEN
+$       TCPIP_LIB = "SYS$DISK:[-.VMS]UCX_SHR_DECC_LOG.OPT/OPT"
+$     ELSE
+$       IF COMPILER .NES. "DECC" .AND. ARCH .EQS. "VAX" THEN -
+	  TCPIP_LIB = "SYS$DISK:[-.VMS]UCX_SHR_VAXC.OPT/OPT"
+$     ENDIF
+$!
+$!    Done with UCX
+$!
+$   ENDIF
+$!
+$!  Check to see if TCPIP was chosen
+$!
+$   IF P4.EQS."TCPIP"
+$   THEN
+$!
+$!    Set the library to use TCPIP (post UCX).
+$!
+$     TCPIP_LIB = "SYS$DISK:[-.VMS]TCPIP_SHR_DECC.OPT/OPT"
+$!
+$!    Done with TCPIP
+$!
+$   ENDIF
+$!
+$!  Check to see if NONE was chosen
+$!
+$   IF P4.EQS."NONE"
+$   THEN
+$!
+$!    Do not use a TCPIP library.
+$!
+$     TCPIP_LIB = ""
+$!
+$!    Done with NONE
+$!
+$   ENDIF
+$!
+$!  Print info
+$!
+$   WRITE SYS$OUTPUT "TCP/IP library spec: ", TCPIP_LIB
+$!
+$!  Else The User Entered An Invalid Argument.
+$!
+$ ELSE
+$!
+$!  Tell The User We Don't Know What They Want.
+$!
+$   WRITE SYS$OUTPUT ""
+$   WRITE SYS$OUTPUT "The Option ",P4," Is Invalid.  The Valid Options Are:"
+$   WRITE SYS$OUTPUT ""
+$   WRITE SYS$OUTPUT "    SOCKETSHR  :  To link with SOCKETSHR TCP/IP library."
+$   WRITE SYS$OUTPUT "    UCX        :  To link with UCX TCP/IP library."
+$   WRITE SYS$OUTPUT "    TCPIP      :  To link with TCPIP (post UCX) TCP/IP library."
+$   WRITE SYS$OUTPUT ""
+$!
+$!  Time To EXIT.
+$!
+$   EXIT
+$!
+$!  Done with TCP/IP libraries
+$!
+$ ENDIF
+$!
+$!  Time To RETURN...
+$!
+$ RETURN
+$!
+$ INITIALISE:
+$!
+$! Save old value of the logical name OPENSSL
+$!
+$ __SAVE_OPENSSL = F$TRNLNM("OPENSSL","LNM$PROCESS_TABLE")
+$!
+$! Save directory information
+$!
+$ __HERE = F$PARSE(F$PARSE("A.;",F$ENVIRONMENT("PROCEDURE"))-"A.;","[]A.;") - "A.;"
+$ __HERE = F$EDIT(__HERE,"UPCASE")
+$ __TOP = __HERE - "SSL]"
+$ __INCLUDE = __TOP + "INCLUDE.OPENSSL]"
+$!
+$! Set up the logical name OPENSSL to point at the include directory
+$!
+$ DEFINE OPENSSL/NOLOG '__INCLUDE'
+$!
+$! Done
+$!
+$ RETURN
+$!
+$ CLEANUP:
+$!
+$! Restore the logical name OPENSSL if it had a value
+$!
+$ IF __SAVE_OPENSSL .EQS. ""
+$ THEN
+$   DEASSIGN OPENSSL
+$ ELSE
+$   DEFINE/NOLOG OPENSSL '__SAVE_OPENSSL'
+$ ENDIF
+$!
+$! Done
+$!
+$ RETURN
diff --git a/lib/openssl/ssl/ssl.h b/lib/openssl/ssl/ssl.h
new file mode 100644
index 0000000..a620f6f
--- /dev/null
+++ b/lib/openssl/ssl/ssl.h
@@ -0,0 +1,2320 @@
+/* ssl/ssl.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECC cipher suite support in OpenSSL originally developed by 
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#ifndef HEADER_SSL_H 
+#define HEADER_SSL_H 
+
+#include <openssl/e_os2.h>
+
+#ifndef OPENSSL_NO_COMP
+#include <openssl/comp.h>
+#endif
+#ifndef OPENSSL_NO_BIO
+#include <openssl/bio.h>
+#endif
+#ifndef OPENSSL_NO_DEPRECATED
+#ifndef OPENSSL_NO_X509
+#include <openssl/x509.h>
+#endif
+#include <openssl/crypto.h>
+#include <openssl/lhash.h>
+#include <openssl/buffer.h>
+#endif
+#include <openssl/pem.h>
+#include <openssl/hmac.h>
+
+#include <openssl/kssl.h>
+#include <openssl/safestack.h>
+#include <openssl/symhacks.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* SSLeay version number for ASN.1 encoding of the session information */
+/* Version 0 - initial version
+ * Version 1 - added the optional peer certificate
+ */
+#define SSL_SESSION_ASN1_VERSION 0x0001
+
+/* text strings for the ciphers */
+#define SSL_TXT_NULL_WITH_MD5		SSL2_TXT_NULL_WITH_MD5			
+#define SSL_TXT_RC4_128_WITH_MD5	SSL2_TXT_RC4_128_WITH_MD5		
+#define SSL_TXT_RC4_128_EXPORT40_WITH_MD5 SSL2_TXT_RC4_128_EXPORT40_WITH_MD5	
+#define SSL_TXT_RC2_128_CBC_WITH_MD5	SSL2_TXT_RC2_128_CBC_WITH_MD5		
+#define SSL_TXT_RC2_128_CBC_EXPORT40_WITH_MD5 SSL2_TXT_RC2_128_CBC_EXPORT40_WITH_MD5	
+#define SSL_TXT_IDEA_128_CBC_WITH_MD5	SSL2_TXT_IDEA_128_CBC_WITH_MD5		
+#define SSL_TXT_DES_64_CBC_WITH_MD5	SSL2_TXT_DES_64_CBC_WITH_MD5		
+#define SSL_TXT_DES_64_CBC_WITH_SHA	SSL2_TXT_DES_64_CBC_WITH_SHA		
+#define SSL_TXT_DES_192_EDE3_CBC_WITH_MD5 SSL2_TXT_DES_192_EDE3_CBC_WITH_MD5	
+#define SSL_TXT_DES_192_EDE3_CBC_WITH_SHA SSL2_TXT_DES_192_EDE3_CBC_WITH_SHA	
+
+/*    VRS Additional Kerberos5 entries
+ */
+#define SSL_TXT_KRB5_DES_64_CBC_SHA   SSL3_TXT_KRB5_DES_64_CBC_SHA
+#define SSL_TXT_KRB5_DES_192_CBC3_SHA SSL3_TXT_KRB5_DES_192_CBC3_SHA
+#define SSL_TXT_KRB5_RC4_128_SHA      SSL3_TXT_KRB5_RC4_128_SHA
+#define SSL_TXT_KRB5_IDEA_128_CBC_SHA SSL3_TXT_KRB5_IDEA_128_CBC_SHA
+#define SSL_TXT_KRB5_DES_64_CBC_MD5   SSL3_TXT_KRB5_DES_64_CBC_MD5       
+#define SSL_TXT_KRB5_DES_192_CBC3_MD5 SSL3_TXT_KRB5_DES_192_CBC3_MD5       
+#define SSL_TXT_KRB5_RC4_128_MD5      SSL3_TXT_KRB5_RC4_128_MD5
+#define SSL_TXT_KRB5_IDEA_128_CBC_MD5 SSL3_TXT_KRB5_IDEA_128_CBC_MD5 
+
+#define SSL_TXT_KRB5_DES_40_CBC_SHA   SSL3_TXT_KRB5_DES_40_CBC_SHA 
+#define SSL_TXT_KRB5_RC2_40_CBC_SHA   SSL3_TXT_KRB5_RC2_40_CBC_SHA 
+#define SSL_TXT_KRB5_RC4_40_SHA	      SSL3_TXT_KRB5_RC4_40_SHA
+#define SSL_TXT_KRB5_DES_40_CBC_MD5   SSL3_TXT_KRB5_DES_40_CBC_MD5 
+#define SSL_TXT_KRB5_RC2_40_CBC_MD5   SSL3_TXT_KRB5_RC2_40_CBC_MD5 
+#define SSL_TXT_KRB5_RC4_40_MD5	      SSL3_TXT_KRB5_RC4_40_MD5
+
+#define SSL_TXT_KRB5_DES_40_CBC_SHA   SSL3_TXT_KRB5_DES_40_CBC_SHA
+#define SSL_TXT_KRB5_DES_40_CBC_MD5   SSL3_TXT_KRB5_DES_40_CBC_MD5
+#define SSL_TXT_KRB5_DES_64_CBC_SHA   SSL3_TXT_KRB5_DES_64_CBC_SHA
+#define SSL_TXT_KRB5_DES_64_CBC_MD5   SSL3_TXT_KRB5_DES_64_CBC_MD5
+#define SSL_TXT_KRB5_DES_192_CBC3_SHA SSL3_TXT_KRB5_DES_192_CBC3_SHA
+#define SSL_TXT_KRB5_DES_192_CBC3_MD5 SSL3_TXT_KRB5_DES_192_CBC3_MD5
+#define SSL_MAX_KRB5_PRINCIPAL_LENGTH  256
+
+#define SSL_MAX_SSL_SESSION_ID_LENGTH		32
+#define SSL_MAX_SID_CTX_LENGTH			32
+
+#define SSL_MIN_RSA_MODULUS_LENGTH_IN_BYTES	(512/8)
+#define SSL_MAX_KEY_ARG_LENGTH			8
+#define SSL_MAX_MASTER_KEY_LENGTH		48
+
+
+/* These are used to specify which ciphers to use and not to use */
+
+#define SSL_TXT_EXP40		"EXPORT40"
+#define SSL_TXT_EXP56		"EXPORT56"
+#define SSL_TXT_LOW		"LOW"
+#define SSL_TXT_MEDIUM		"MEDIUM"
+#define SSL_TXT_HIGH		"HIGH"
+#define SSL_TXT_FIPS		"FIPS"
+
+#define SSL_TXT_kFZA		"kFZA" /* unused! */
+#define	SSL_TXT_aFZA		"aFZA" /* unused! */
+#define SSL_TXT_eFZA		"eFZA" /* unused! */
+#define SSL_TXT_FZA		"FZA"  /* unused! */
+
+#define	SSL_TXT_aNULL		"aNULL"
+#define	SSL_TXT_eNULL		"eNULL"
+#define	SSL_TXT_NULL		"NULL"
+
+#define SSL_TXT_kRSA		"kRSA"
+#define SSL_TXT_kDHr		"kDHr" /* no such ciphersuites supported! */
+#define SSL_TXT_kDHd		"kDHd" /* no such ciphersuites supported! */
+#define SSL_TXT_kDH 		"kDH"  /* no such ciphersuites supported! */
+#define SSL_TXT_kEDH		"kEDH"
+#define SSL_TXT_kKRB5     	"kKRB5"
+#define SSL_TXT_kECDHr		"kECDHr"
+#define SSL_TXT_kECDHe		"kECDHe"
+#define SSL_TXT_kECDH		"kECDH"
+#define SSL_TXT_kEECDH		"kEECDH"
+#define SSL_TXT_kPSK            "kPSK"
+#define SSL_TXT_kGOST		"kGOST"
+
+#define	SSL_TXT_aRSA		"aRSA"
+#define	SSL_TXT_aDSS		"aDSS"
+#define	SSL_TXT_aDH		"aDH" /* no such ciphersuites supported! */
+#define	SSL_TXT_aECDH		"aECDH"
+#define SSL_TXT_aKRB5     	"aKRB5"
+#define SSL_TXT_aECDSA		"aECDSA"
+#define SSL_TXT_aPSK            "aPSK"
+#define SSL_TXT_aGOST94	"aGOST94"
+#define SSL_TXT_aGOST01 "aGOST01"
+#define SSL_TXT_aGOST  "aGOST"
+
+#define	SSL_TXT_DSS		"DSS"
+#define SSL_TXT_DH		"DH"
+#define SSL_TXT_EDH		"EDH" /* same as "kEDH:-ADH" */
+#define SSL_TXT_ADH		"ADH"
+#define SSL_TXT_RSA		"RSA"
+#define SSL_TXT_ECDH		"ECDH"
+#define SSL_TXT_EECDH		"EECDH" /* same as "kEECDH:-AECDH" */
+#define SSL_TXT_AECDH		"AECDH"
+#define SSL_TXT_ECDSA		"ECDSA"
+#define SSL_TXT_KRB5      	"KRB5"
+#define SSL_TXT_PSK             "PSK"
+
+#define SSL_TXT_DES		"DES"
+#define SSL_TXT_3DES		"3DES"
+#define SSL_TXT_RC4		"RC4"
+#define SSL_TXT_RC2		"RC2"
+#define SSL_TXT_IDEA		"IDEA"
+#define SSL_TXT_SEED		"SEED"
+#define SSL_TXT_AES128		"AES128"
+#define SSL_TXT_AES256		"AES256"
+#define SSL_TXT_AES		"AES"
+#define SSL_TXT_CAMELLIA128	"CAMELLIA128"
+#define SSL_TXT_CAMELLIA256	"CAMELLIA256"
+#define SSL_TXT_CAMELLIA	"CAMELLIA"
+
+#define SSL_TXT_MD5		"MD5"
+#define SSL_TXT_SHA1		"SHA1"
+#define SSL_TXT_SHA		"SHA" /* same as "SHA1" */
+#define SSL_TXT_GOST94		"GOST94" 
+#define SSL_TXT_GOST89MAC		"GOST89MAC" 
+
+#define SSL_TXT_SSLV2		"SSLv2"
+#define SSL_TXT_SSLV3		"SSLv3"
+#define SSL_TXT_TLSV1		"TLSv1"
+
+#define SSL_TXT_EXP		"EXP"
+#define SSL_TXT_EXPORT		"EXPORT"
+
+#define SSL_TXT_ALL		"ALL"
+
+/*
+ * COMPLEMENTOF* definitions. These identifiers are used to (de-select)
+ * ciphers normally not being used.
+ * Example: "RC4" will activate all ciphers using RC4 including ciphers
+ * without authentication, which would normally disabled by DEFAULT (due
+ * the "!ADH" being part of default). Therefore "RC4:!COMPLEMENTOFDEFAULT"
+ * will make sure that it is also disabled in the specific selection.
+ * COMPLEMENTOF* identifiers are portable between version, as adjustments
+ * to the default cipher setup will also be included here.
+ *
+ * COMPLEMENTOFDEFAULT does not experience the same special treatment that
+ * DEFAULT gets, as only selection is being done and no sorting as needed
+ * for DEFAULT.
+ */
+#define SSL_TXT_CMPALL		"COMPLEMENTOFALL"
+#define SSL_TXT_CMPDEF		"COMPLEMENTOFDEFAULT"
+
+/* The following cipher list is used by default.
+ * It also is substituted when an application-defined cipher list string
+ * starts with 'DEFAULT'. */
+#define SSL_DEFAULT_CIPHER_LIST	"ALL:!aNULL:!eNULL:!SSLv2"
+/* As of OpenSSL 1.0.0, ssl_create_cipher_list() in ssl/ssl_ciph.c always
+ * starts with a reasonable order, and all we have to do for DEFAULT is
+ * throwing out anonymous and unencrypted ciphersuites!
+ * (The latter are not actually enabled by ALL, but "ALL:RSA" would enable
+ * some of them.)
+ */
+
+/* Used in SSL_set_shutdown()/SSL_get_shutdown(); */
+#define SSL_SENT_SHUTDOWN	1
+#define SSL_RECEIVED_SHUTDOWN	2
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#if (defined(OPENSSL_NO_RSA) || defined(OPENSSL_NO_MD5)) && !defined(OPENSSL_NO_SSL2)
+#define OPENSSL_NO_SSL2
+#endif
+
+#define SSL_FILETYPE_ASN1	X509_FILETYPE_ASN1
+#define SSL_FILETYPE_PEM	X509_FILETYPE_PEM
+
+/* This is needed to stop compilers complaining about the
+ * 'struct ssl_st *' function parameters used to prototype callbacks
+ * in SSL_CTX. */
+typedef struct ssl_st *ssl_crock_st;
+typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT;
+
+/* used to hold info on the particular ciphers used */
+typedef struct ssl_cipher_st
+	{
+	int valid;
+	const char *name;		/* text name */
+	unsigned long id;		/* id, 4 bytes, first is version */
+
+	/* changed in 0.9.9: these four used to be portions of a single value 'algorithms' */
+	unsigned long algorithm_mkey;	/* key exchange algorithm */
+	unsigned long algorithm_auth;	/* server authentication */
+	unsigned long algorithm_enc;	/* symmetric encryption */
+	unsigned long algorithm_mac;	/* symmetric authentication */
+	unsigned long algorithm_ssl;	/* (major) protocol version */
+
+	unsigned long algo_strength;	/* strength and export flags */
+	unsigned long algorithm2;	/* Extra flags */
+	int strength_bits;		/* Number of bits really used */
+	int alg_bits;			/* Number of bits for algorithm */
+	} SSL_CIPHER;
+
+DECLARE_STACK_OF(SSL_CIPHER)
+
+typedef int (*tls_session_ticket_ext_cb_fn)(SSL *s, const unsigned char *data, int len, void *arg);
+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
+
+/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
+typedef struct ssl_method_st
+	{
+	int version;
+	int (*ssl_new)(SSL *s);
+	void (*ssl_clear)(SSL *s);
+	void (*ssl_free)(SSL *s);
+	int (*ssl_accept)(SSL *s);
+	int (*ssl_connect)(SSL *s);
+	int (*ssl_read)(SSL *s,void *buf,int len);
+	int (*ssl_peek)(SSL *s,void *buf,int len);
+	int (*ssl_write)(SSL *s,const void *buf,int len);
+	int (*ssl_shutdown)(SSL *s);
+	int (*ssl_renegotiate)(SSL *s);
+	int (*ssl_renegotiate_check)(SSL *s);
+	long (*ssl_get_message)(SSL *s, int st1, int stn, int mt, long
+		max, int *ok);
+	int (*ssl_read_bytes)(SSL *s, int type, unsigned char *buf, int len, 
+		int peek);
+	int (*ssl_write_bytes)(SSL *s, int type, const void *buf_, int len);
+	int (*ssl_dispatch_alert)(SSL *s);
+	long (*ssl_ctrl)(SSL *s,int cmd,long larg,void *parg);
+	long (*ssl_ctx_ctrl)(SSL_CTX *ctx,int cmd,long larg,void *parg);
+	const SSL_CIPHER *(*get_cipher_by_char)(const unsigned char *ptr);
+	int (*put_cipher_by_char)(const SSL_CIPHER *cipher,unsigned char *ptr);
+	int (*ssl_pending)(const SSL *s);
+	int (*num_ciphers)(void);
+	const SSL_CIPHER *(*get_cipher)(unsigned ncipher);
+	const struct ssl_method_st *(*get_ssl_method)(int version);
+	long (*get_timeout)(void);
+	struct ssl3_enc_method *ssl3_enc; /* Extra SSLv3/TLS stuff */
+	int (*ssl_version)(void);
+	long (*ssl_callback_ctrl)(SSL *s, int cb_id, void (*fp)(void));
+	long (*ssl_ctx_callback_ctrl)(SSL_CTX *s, int cb_id, void (*fp)(void));
+	} SSL_METHOD;
+
+/* Lets make this into an ASN.1 type structure as follows
+ * SSL_SESSION_ID ::= SEQUENCE {
+ *	version 		INTEGER,	-- structure version number
+ *	SSLversion 		INTEGER,	-- SSL version number
+ *	Cipher 			OCTET STRING,	-- the 3 byte cipher ID
+ *	Session_ID 		OCTET STRING,	-- the Session ID
+ *	Master_key 		OCTET STRING,	-- the master key
+ *	KRB5_principal		OCTET STRING	-- optional Kerberos principal
+ *	Key_Arg [ 0 ] IMPLICIT	OCTET STRING,	-- the optional Key argument
+ *	Time [ 1 ] EXPLICIT	INTEGER,	-- optional Start Time
+ *	Timeout [ 2 ] EXPLICIT	INTEGER,	-- optional Timeout ins seconds
+ *	Peer [ 3 ] EXPLICIT	X509,		-- optional Peer Certificate
+ *	Session_ID_context [ 4 ] EXPLICIT OCTET STRING,   -- the Session ID context
+ *	Verify_result [ 5 ] EXPLICIT INTEGER,   -- X509_V_... code for `Peer'
+ *	HostName [ 6 ] EXPLICIT OCTET STRING,   -- optional HostName from servername TLS extension 
+ *	ECPointFormatList [ 7 ] OCTET STRING,     -- optional EC point format list from TLS extension
+ *	PSK_identity_hint [ 8 ] EXPLICIT OCTET STRING, -- optional PSK identity hint
+ *	PSK_identity [ 9 ] EXPLICIT OCTET STRING -- optional PSK identity
+ *	}
+ * Look in ssl/ssl_asn1.c for more details
+ * I'm using EXPLICIT tags so I can read the damn things using asn1parse :-).
+ */
+typedef struct ssl_session_st
+	{
+	int ssl_version;	/* what ssl version session info is
+				 * being kept in here? */
+
+	/* only really used in SSLv2 */
+	unsigned int key_arg_length;
+	unsigned char key_arg[SSL_MAX_KEY_ARG_LENGTH];
+	int master_key_length;
+	unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH];
+	/* session_id - valid? */
+	unsigned int session_id_length;
+	unsigned char session_id[SSL_MAX_SSL_SESSION_ID_LENGTH];
+	/* this is used to determine whether the session is being reused in
+	 * the appropriate context. It is up to the application to set this,
+	 * via SSL_new */
+	unsigned int sid_ctx_length;
+	unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];
+
+#ifndef OPENSSL_NO_KRB5
+        unsigned int krb5_client_princ_len;
+        unsigned char krb5_client_princ[SSL_MAX_KRB5_PRINCIPAL_LENGTH];
+#endif /* OPENSSL_NO_KRB5 */
+#ifndef OPENSSL_NO_PSK
+	char *psk_identity_hint;
+	char *psk_identity;
+#endif
+	int not_resumable;
+
+	/* The cert is the certificate used to establish this connection */
+	struct sess_cert_st /* SESS_CERT */ *sess_cert;
+
+	/* This is the cert for the other end.
+	 * On clients, it will be the same as sess_cert->peer_key->x509
+	 * (the latter is not enough as sess_cert is not retained
+	 * in the external representation of sessions, see ssl_asn1.c). */
+	X509 *peer;
+	/* when app_verify_callback accepts a session where the peer's certificate
+	 * is not ok, we must remember the error for session reuse: */
+	long verify_result; /* only for servers */
+
+	int references;
+	long timeout;
+	long time;
+
+	unsigned int compress_meth;	/* Need to lookup the method */
+
+	const SSL_CIPHER *cipher;
+	unsigned long cipher_id;	/* when ASN.1 loaded, this
+					 * needs to be used to load
+					 * the 'cipher' structure */
+
+	STACK_OF(SSL_CIPHER) *ciphers; /* shared ciphers? */
+
+	CRYPTO_EX_DATA ex_data; /* application specific data */
+
+	/* These are used to make removal of session-ids more
+	 * efficient and to implement a maximum cache size. */
+	struct ssl_session_st *prev,*next;
+#ifndef OPENSSL_NO_TLSEXT
+	char *tlsext_hostname;
+#ifndef OPENSSL_NO_EC
+	size_t tlsext_ecpointformatlist_length;
+	unsigned char *tlsext_ecpointformatlist; /* peer's list */
+	size_t tlsext_ellipticcurvelist_length;
+	unsigned char *tlsext_ellipticcurvelist; /* peer's list */
+#endif /* OPENSSL_NO_EC */
+	/* RFC4507 info */
+	unsigned char *tlsext_tick;	/* Session ticket */
+	size_t	tlsext_ticklen;		/* Session ticket length */	
+	long tlsext_tick_lifetime_hint;	/* Session lifetime hint in seconds */
+#endif
+	} SSL_SESSION;
+
+
+#define SSL_OP_MICROSOFT_SESS_ID_BUG			0x00000001L
+#define SSL_OP_NETSCAPE_CHALLENGE_BUG			0x00000002L
+/* Allow initial connection to servers that don't support RI */
+#define SSL_OP_LEGACY_SERVER_CONNECT			0x00000004L
+#define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG		0x00000008L
+#define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG		0x00000010L
+#define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER		0x00000020L
+#define SSL_OP_MSIE_SSLV2_RSA_PADDING			0x00000040L /* no effect since 0.9.7h and 0.9.8b */
+#define SSL_OP_SSLEAY_080_CLIENT_DH_BUG			0x00000080L
+#define SSL_OP_TLS_D5_BUG				0x00000100L
+#define SSL_OP_TLS_BLOCK_PADDING_BUG			0x00000200L
+
+/* Disable SSL 3.0/TLS 1.0 CBC vulnerability workaround that was added
+ * in OpenSSL 0.9.6d.  Usually (depending on the application protocol)
+ * the workaround is not needed.  Unfortunately some broken SSL/TLS
+ * implementations cannot handle it at all, which is why we include
+ * it in SSL_OP_ALL. */
+#define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS              0x00000800L /* added in 0.9.6e */
+
+/* SSL_OP_ALL: various bug workarounds that should be rather harmless.
+ *             This used to be 0x000FFFFFL before 0.9.7. */
+#define SSL_OP_ALL					0x80000FFFL
+
+/* DTLS options */
+#define SSL_OP_NO_QUERY_MTU                 0x00001000L
+/* Turn on Cookie Exchange (on relevant for servers) */
+#define SSL_OP_COOKIE_EXCHANGE              0x00002000L
+/* Don't use RFC4507 ticket extension */
+#define SSL_OP_NO_TICKET	            0x00004000L
+/* Use Cisco's "speshul" version of DTLS_BAD_VER (as client)  */
+#define SSL_OP_CISCO_ANYCONNECT		    0x00008000L
+
+/* As server, disallow session resumption on renegotiation */
+#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION	0x00010000L
+/* Don't use compression even if supported */
+#define SSL_OP_NO_COMPRESSION				0x00020000L
+/* Permit unsafe legacy renegotiation */
+#define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION	0x00040000L
+/* If set, always create a new key when using tmp_ecdh parameters */
+#define SSL_OP_SINGLE_ECDH_USE				0x00080000L
+/* If set, always create a new key when using tmp_dh parameters */
+#define SSL_OP_SINGLE_DH_USE				0x00100000L
+/* Set to always use the tmp_rsa key when doing RSA operations,
+ * even when this violates protocol specs */
+#define SSL_OP_EPHEMERAL_RSA				0x00200000L
+/* Set on servers to choose the cipher according to the server's
+ * preferences */
+#define SSL_OP_CIPHER_SERVER_PREFERENCE			0x00400000L
+/* If set, a server will allow a client to issue a SSLv3.0 version number
+ * as latest version supported in the premaster secret, even when TLSv1.0
+ * (version 3.1) was announced in the client hello. Normally this is
+ * forbidden to prevent version rollback attacks. */
+#define SSL_OP_TLS_ROLLBACK_BUG				0x00800000L
+
+#define SSL_OP_NO_SSLv2					0x01000000L
+#define SSL_OP_NO_SSLv3					0x02000000L
+#define SSL_OP_NO_TLSv1					0x04000000L
+
+/* The next flag deliberately changes the ciphertest, this is a check
+ * for the PKCS#1 attack */
+#define SSL_OP_PKCS1_CHECK_1				0x08000000L
+#define SSL_OP_PKCS1_CHECK_2				0x10000000L
+#define SSL_OP_NETSCAPE_CA_DN_BUG			0x20000000L
+#define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG		0x40000000L
+/* Make server add server-hello extension from early version of
+ * cryptopro draft, when GOST ciphersuite is negotiated. 
+ * Required for interoperability with CryptoPro CSP 3.x 
+ */
+#define SSL_OP_CRYPTOPRO_TLSEXT_BUG			0x80000000L
+
+/* Allow SSL_write(..., n) to return r with 0 < r < n (i.e. report success
+ * when just a single record has been written): */
+#define SSL_MODE_ENABLE_PARTIAL_WRITE       0x00000001L
+/* Make it possible to retry SSL_write() with changed buffer location
+ * (buffer contents must stay the same!); this is not the default to avoid
+ * the misconception that non-blocking SSL_write() behaves like
+ * non-blocking write(): */
+#define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 0x00000002L
+/* Never bother the application with retries if the transport
+ * is blocking: */
+#define SSL_MODE_AUTO_RETRY 0x00000004L
+/* Don't attempt to automatically build certificate chain */
+#define SSL_MODE_NO_AUTO_CHAIN 0x00000008L
+/* Save RAM by releasing read and write buffers when they're empty. (SSL3 and
+ * TLS only.)  "Released" buffers are put onto a free-list in the context
+ * or just freed (depending on the context's setting for freelist_max_len). */
+#define SSL_MODE_RELEASE_BUFFERS 0x00000010L
+/* Use small read and write buffers: (a) lazy allocate read buffers for
+ * large incoming records, and (b) limit the size of outgoing records. */
+#define SSL_MODE_SMALL_BUFFERS 0x00000020L
+/* When set, clients may send application data before receipt of CCS
+ * and Finished.  This mode enables full-handshakes to 'complete' in
+ * one RTT. */
+#define SSL_MODE_HANDSHAKE_CUTTHROUGH 0x00000040L
+
+/* Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value,
+ * they cannot be used to clear bits. */
+
+#define SSL_CTX_set_options(ctx,op) \
+	SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,(op),NULL)
+#define SSL_CTX_clear_options(ctx,op) \
+	SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_OPTIONS,(op),NULL)
+#define SSL_CTX_get_options(ctx) \
+	SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,0,NULL)
+#define SSL_set_options(ssl,op) \
+	SSL_ctrl((ssl),SSL_CTRL_OPTIONS,(op),NULL)
+#define SSL_clear_options(ssl,op) \
+	SSL_ctrl((ssl),SSL_CTRL_CLEAR_OPTIONS,(op),NULL)
+#define SSL_get_options(ssl) \
+        SSL_ctrl((ssl),SSL_CTRL_OPTIONS,0,NULL)
+
+#define SSL_CTX_set_mode(ctx,op) \
+	SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL)
+#define SSL_CTX_clear_mode(ctx,op) \
+	SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_MODE,(op),NULL)
+#define SSL_CTX_get_mode(ctx) \
+	SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,0,NULL)
+#define SSL_clear_mode(ssl,op) \
+	SSL_ctrl((ssl),SSL_CTRL_CLEAR_MODE,(op),NULL)
+#define SSL_set_mode(ssl,op) \
+	SSL_ctrl((ssl),SSL_CTRL_MODE,(op),NULL)
+#define SSL_get_mode(ssl) \
+        SSL_ctrl((ssl),SSL_CTRL_MODE,0,NULL)
+#define SSL_set_mtu(ssl, mtu) \
+        SSL_ctrl((ssl),SSL_CTRL_SET_MTU,(mtu),NULL)
+
+#define SSL_get_secure_renegotiation_support(ssl) \
+	SSL_ctrl((ssl), SSL_CTRL_GET_RI_SUPPORT, 0, NULL)
+
+void SSL_CTX_set_msg_callback(SSL_CTX *ctx, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg));
+void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg));
+#define SSL_CTX_set_msg_callback_arg(ctx, arg) SSL_CTX_ctrl((ctx), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))
+#define SSL_set_msg_callback_arg(ssl, arg) SSL_ctrl((ssl), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))
+
+
+
+#if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN32)
+#define SSL_MAX_CERT_LIST_DEFAULT 1024*30 /* 30k max cert list :-) */
+#else
+#define SSL_MAX_CERT_LIST_DEFAULT 1024*100 /* 100k max cert list :-) */
+#endif
+
+#define SSL_SESSION_CACHE_MAX_SIZE_DEFAULT	(1024*20)
+
+/* This callback type is used inside SSL_CTX, SSL, and in the functions that set
+ * them. It is used to override the generation of SSL/TLS session IDs in a
+ * server. Return value should be zero on an error, non-zero to proceed. Also,
+ * callbacks should themselves check if the id they generate is unique otherwise
+ * the SSL handshake will fail with an error - callbacks can do this using the
+ * 'ssl' value they're passed by;
+ *      SSL_has_matching_session_id(ssl, id, *id_len)
+ * The length value passed in is set at the maximum size the session ID can be.
+ * In SSLv2 this is 16 bytes, whereas SSLv3/TLSv1 it is 32 bytes. The callback
+ * can alter this length to be less if desired, but under SSLv2 session IDs are
+ * supposed to be fixed at 16 bytes so the id will be padded after the callback
+ * returns in this case. It is also an error for the callback to set the size to
+ * zero. */
+typedef int (*GEN_SESSION_CB)(const SSL *ssl, unsigned char *id,
+				unsigned int *id_len);
+
+typedef struct ssl_comp_st
+	{
+	int id;
+	const char *name;
+#ifndef OPENSSL_NO_COMP
+	COMP_METHOD *method;
+#else
+	char *method;
+#endif
+	} SSL_COMP;
+
+DECLARE_STACK_OF(SSL_COMP)
+DECLARE_LHASH_OF(SSL_SESSION);
+
+struct ssl_ctx_st
+	{
+	const SSL_METHOD *method;
+
+	STACK_OF(SSL_CIPHER) *cipher_list;
+	/* same as above but sorted for lookup */
+	STACK_OF(SSL_CIPHER) *cipher_list_by_id;
+
+	struct x509_store_st /* X509_STORE */ *cert_store;
+	LHASH_OF(SSL_SESSION) *sessions;
+	/* Most session-ids that will be cached, default is
+	 * SSL_SESSION_CACHE_MAX_SIZE_DEFAULT. 0 is unlimited. */
+	unsigned long session_cache_size;
+	struct ssl_session_st *session_cache_head;
+	struct ssl_session_st *session_cache_tail;
+
+	/* This can have one of 2 values, ored together,
+	 * SSL_SESS_CACHE_CLIENT,
+	 * SSL_SESS_CACHE_SERVER,
+	 * Default is SSL_SESSION_CACHE_SERVER, which means only
+	 * SSL_accept which cache SSL_SESSIONS. */
+	int session_cache_mode;
+
+	/* If timeout is not 0, it is the default timeout value set
+	 * when SSL_new() is called.  This has been put in to make
+	 * life easier to set things up */
+	long session_timeout;
+
+	/* If this callback is not null, it will be called each
+	 * time a session id is added to the cache.  If this function
+	 * returns 1, it means that the callback will do a
+	 * SSL_SESSION_free() when it has finished using it.  Otherwise,
+	 * on 0, it means the callback has finished with it.
+	 * If remove_session_cb is not null, it will be called when
+	 * a session-id is removed from the cache.  After the call,
+	 * OpenSSL will SSL_SESSION_free() it. */
+	int (*new_session_cb)(struct ssl_st *ssl,SSL_SESSION *sess);
+	void (*remove_session_cb)(struct ssl_ctx_st *ctx,SSL_SESSION *sess);
+	SSL_SESSION *(*get_session_cb)(struct ssl_st *ssl,
+		unsigned char *data,int len,int *copy);
+
+	struct
+		{
+		int sess_connect;	/* SSL new conn - started */
+		int sess_connect_renegotiate;/* SSL reneg - requested */
+		int sess_connect_good;	/* SSL new conne/reneg - finished */
+		int sess_accept;	/* SSL new accept - started */
+		int sess_accept_renegotiate;/* SSL reneg - requested */
+		int sess_accept_good;	/* SSL accept/reneg - finished */
+		int sess_miss;		/* session lookup misses  */
+		int sess_timeout;	/* reuse attempt on timeouted session */
+		int sess_cache_full;	/* session removed due to full cache */
+		int sess_hit;		/* session reuse actually done */
+		int sess_cb_hit;	/* session-id that was not
+					 * in the cache was
+					 * passed back via the callback.  This
+					 * indicates that the application is
+					 * supplying session-id's from other
+					 * processes - spooky :-) */
+		} stats;
+
+	int references;
+
+	/* if defined, these override the X509_verify_cert() calls */
+	int (*app_verify_callback)(X509_STORE_CTX *, void *);
+	void *app_verify_arg;
+	/* before OpenSSL 0.9.7, 'app_verify_arg' was ignored
+	 * ('app_verify_callback' was called with just one argument) */
+
+	/* Default password callback. */
+	pem_password_cb *default_passwd_callback;
+
+	/* Default password callback user data. */
+	void *default_passwd_callback_userdata;
+
+	/* get client cert callback */
+	int (*client_cert_cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey);
+
+    /* cookie generate callback */
+    int (*app_gen_cookie_cb)(SSL *ssl, unsigned char *cookie, 
+        unsigned int *cookie_len);
+
+    /* verify cookie callback */
+    int (*app_verify_cookie_cb)(SSL *ssl, unsigned char *cookie, 
+        unsigned int cookie_len);
+
+	CRYPTO_EX_DATA ex_data;
+
+	const EVP_MD *rsa_md5;/* For SSLv2 - name is 'ssl2-md5' */
+	const EVP_MD *md5;	/* For SSLv3/TLSv1 'ssl3-md5' */
+	const EVP_MD *sha1;   /* For SSLv3/TLSv1 'ssl3->sha1' */
+
+	STACK_OF(X509) *extra_certs;
+	STACK_OF(SSL_COMP) *comp_methods; /* stack of SSL_COMP, SSLv3/TLSv1 */
+
+
+	/* Default values used when no per-SSL value is defined follow */
+
+	void (*info_callback)(const SSL *ssl,int type,int val); /* used if SSL's info_callback is NULL */
+
+	/* what we put in client cert requests */
+	STACK_OF(X509_NAME) *client_CA;
+
+
+	/* Default values to use in SSL structures follow (these are copied by SSL_new) */
+
+	unsigned long options;
+	unsigned long mode;
+	long max_cert_list;
+
+	struct cert_st /* CERT */ *cert;
+	int read_ahead;
+
+	/* callback that allows applications to peek at protocol messages */
+	void (*msg_callback)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg);
+	void *msg_callback_arg;
+
+	int verify_mode;
+	unsigned int sid_ctx_length;
+	unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];
+	int (*default_verify_callback)(int ok,X509_STORE_CTX *ctx); /* called 'verify_callback' in the SSL */
+
+	/* Default generate session ID callback. */
+	GEN_SESSION_CB generate_session_id;
+
+	X509_VERIFY_PARAM *param;
+
+#if 0
+	int purpose;		/* Purpose setting */
+	int trust;		/* Trust setting */
+#endif
+
+	int quiet_shutdown;
+
+	/* Maximum amount of data to send in one fragment.
+	 * actual record size can be more than this due to
+	 * padding and MAC overheads.
+	 */
+	unsigned int max_send_fragment;
+
+#ifndef OPENSSL_ENGINE
+	/* Engine to pass requests for client certs to
+	 */
+	ENGINE *client_cert_engine;
+#endif
+
+#ifndef OPENSSL_NO_TLSEXT
+	/* TLS extensions servername callback */
+	int (*tlsext_servername_callback)(SSL*, int *, void *);
+	void *tlsext_servername_arg;
+	/* RFC 4507 session ticket keys */
+	unsigned char tlsext_tick_key_name[16];
+	unsigned char tlsext_tick_hmac_key[16];
+	unsigned char tlsext_tick_aes_key[16];
+	/* Callback to support customisation of ticket key setting */
+	int (*tlsext_ticket_key_cb)(SSL *ssl,
+					unsigned char *name, unsigned char *iv,
+					EVP_CIPHER_CTX *ectx,
+ 					HMAC_CTX *hctx, int enc);
+
+	/* certificate status request info */
+	/* Callback for status request */
+	int (*tlsext_status_cb)(SSL *ssl, void *arg);
+	void *tlsext_status_arg;
+
+	/* draft-rescorla-tls-opaque-prf-input-00.txt information */
+	int (*tlsext_opaque_prf_input_callback)(SSL *, void *peerinput, size_t len, void *arg);
+	void *tlsext_opaque_prf_input_callback_arg;
+#endif
+
+#ifndef OPENSSL_NO_PSK
+	char *psk_identity_hint;
+	unsigned int (*psk_client_callback)(SSL *ssl, const char *hint, char *identity,
+		unsigned int max_identity_len, unsigned char *psk,
+		unsigned int max_psk_len);
+	unsigned int (*psk_server_callback)(SSL *ssl, const char *identity,
+		unsigned char *psk, unsigned int max_psk_len);
+#endif
+
+#ifndef OPENSSL_NO_BUF_FREELISTS
+#define SSL_MAX_BUF_FREELIST_LEN_DEFAULT 32
+	unsigned int freelist_max_len;
+	struct ssl3_buf_freelist_st *wbuf_freelist;
+	struct ssl3_buf_freelist_st *rbuf_freelist;
+#endif
+	};
+
+#define SSL_SESS_CACHE_OFF			0x0000
+#define SSL_SESS_CACHE_CLIENT			0x0001
+#define SSL_SESS_CACHE_SERVER			0x0002
+#define SSL_SESS_CACHE_BOTH	(SSL_SESS_CACHE_CLIENT|SSL_SESS_CACHE_SERVER)
+#define SSL_SESS_CACHE_NO_AUTO_CLEAR		0x0080
+/* enough comments already ... see SSL_CTX_set_session_cache_mode(3) */
+#define SSL_SESS_CACHE_NO_INTERNAL_LOOKUP	0x0100
+#define SSL_SESS_CACHE_NO_INTERNAL_STORE	0x0200
+#define SSL_SESS_CACHE_NO_INTERNAL \
+	(SSL_SESS_CACHE_NO_INTERNAL_LOOKUP|SSL_SESS_CACHE_NO_INTERNAL_STORE)
+
+LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx);
+#define SSL_CTX_sess_number(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_NUMBER,0,NULL)
+#define SSL_CTX_sess_connect(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT,0,NULL)
+#define SSL_CTX_sess_connect_good(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_GOOD,0,NULL)
+#define SSL_CTX_sess_connect_renegotiate(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_RENEGOTIATE,0,NULL)
+#define SSL_CTX_sess_accept(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT,0,NULL)
+#define SSL_CTX_sess_accept_renegotiate(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_RENEGOTIATE,0,NULL)
+#define SSL_CTX_sess_accept_good(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_GOOD,0,NULL)
+#define SSL_CTX_sess_hits(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_HIT,0,NULL)
+#define SSL_CTX_sess_cb_hits(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CB_HIT,0,NULL)
+#define SSL_CTX_sess_misses(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_MISSES,0,NULL)
+#define SSL_CTX_sess_timeouts(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_TIMEOUTS,0,NULL)
+#define SSL_CTX_sess_cache_full(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CACHE_FULL,0,NULL)
+
+void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx, int (*new_session_cb)(struct ssl_st *ssl,SSL_SESSION *sess));
+int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(struct ssl_st *ssl, SSL_SESSION *sess);
+void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx, void (*remove_session_cb)(struct ssl_ctx_st *ctx,SSL_SESSION *sess));
+void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(struct ssl_ctx_st *ctx, SSL_SESSION *sess);
+void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx, SSL_SESSION *(*get_session_cb)(struct ssl_st *ssl, unsigned char *data,int len,int *copy));
+SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(struct ssl_st *ssl, unsigned char *Data, int len, int *copy);
+void SSL_CTX_set_info_callback(SSL_CTX *ctx, void (*cb)(const SSL *ssl,int type,int val));
+void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl,int type,int val);
+void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, int (*client_cert_cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey));
+int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL *ssl, X509 **x509, EVP_PKEY **pkey);
+#ifndef OPENSSL_NO_ENGINE
+int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e);
+#endif
+void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx, int (*app_gen_cookie_cb)(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len));
+void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx, int (*app_verify_cookie_cb)(SSL *ssl, unsigned char *cookie, unsigned int cookie_len));
+
+#ifndef OPENSSL_NO_PSK
+/* the maximum length of the buffer given to callbacks containing the
+ * resulting identity/psk */
+#define PSK_MAX_IDENTITY_LEN 128
+#define PSK_MAX_PSK_LEN 256
+void SSL_CTX_set_psk_client_callback(SSL_CTX *ctx, 
+	unsigned int (*psk_client_callback)(SSL *ssl, const char *hint, 
+		char *identity, unsigned int max_identity_len, unsigned char *psk,
+		unsigned int max_psk_len));
+void SSL_set_psk_client_callback(SSL *ssl, 
+	unsigned int (*psk_client_callback)(SSL *ssl, const char *hint, 
+		char *identity, unsigned int max_identity_len, unsigned char *psk,
+		unsigned int max_psk_len));
+void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx, 
+	unsigned int (*psk_server_callback)(SSL *ssl, const char *identity,
+		unsigned char *psk, unsigned int max_psk_len));
+void SSL_set_psk_server_callback(SSL *ssl,
+	unsigned int (*psk_server_callback)(SSL *ssl, const char *identity,
+		unsigned char *psk, unsigned int max_psk_len));
+int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint);
+int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint);
+const char *SSL_get_psk_identity_hint(const SSL *s);
+const char *SSL_get_psk_identity(const SSL *s);
+#endif
+
+#define SSL_NOTHING	1
+#define SSL_WRITING	2
+#define SSL_READING	3
+#define SSL_X509_LOOKUP	4
+
+/* These will only be used when doing non-blocking IO */
+#define SSL_want_nothing(s)	(SSL_want(s) == SSL_NOTHING)
+#define SSL_want_read(s)	(SSL_want(s) == SSL_READING)
+#define SSL_want_write(s)	(SSL_want(s) == SSL_WRITING)
+#define SSL_want_x509_lookup(s)	(SSL_want(s) == SSL_X509_LOOKUP)
+
+#define SSL_MAC_FLAG_READ_MAC_STREAM 1
+#define SSL_MAC_FLAG_WRITE_MAC_STREAM 2
+
+struct ssl_st
+	{
+	/* protocol version
+	 * (one of SSL2_VERSION, SSL3_VERSION, TLS1_VERSION, DTLS1_VERSION)
+	 */
+	int version;
+	int type; /* SSL_ST_CONNECT or SSL_ST_ACCEPT */
+
+	const SSL_METHOD *method; /* SSLv3 */
+
+	/* There are 2 BIO's even though they are normally both the
+	 * same.  This is so data can be read and written to different
+	 * handlers */
+
+#ifndef OPENSSL_NO_BIO
+	BIO *rbio; /* used by SSL_read */
+	BIO *wbio; /* used by SSL_write */
+	BIO *bbio; /* used during session-id reuse to concatenate
+		    * messages */
+#else
+	char *rbio; /* used by SSL_read */
+	char *wbio; /* used by SSL_write */
+	char *bbio;
+#endif
+	/* This holds a variable that indicates what we were doing
+	 * when a 0 or -1 is returned.  This is needed for
+	 * non-blocking IO so we know what request needs re-doing when
+	 * in SSL_accept or SSL_connect */
+	int rwstate;
+
+	/* true when we are actually in SSL_accept() or SSL_connect() */
+	int in_handshake;
+	int (*handshake_func)(SSL *);
+
+	/* Imagine that here's a boolean member "init" that is
+	 * switched as soon as SSL_set_{accept/connect}_state
+	 * is called for the first time, so that "state" and
+	 * "handshake_func" are properly initialized.  But as
+	 * handshake_func is == 0 until then, we use this
+	 * test instead of an "init" member.
+	 */
+
+	int server;	/* are we the server side? - mostly used by SSL_clear*/
+
+	int new_session;/* 1 if we are to use a new session.
+	                 * 2 if we are a server and are inside a handshake
+	                 *   (i.e. not just sending a HelloRequest)
+	                 * NB: For servers, the 'new' session may actually be a previously
+	                 * cached session or even the previous session unless
+	                 * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */
+	int quiet_shutdown;/* don't send shutdown packets */
+	int shutdown;	/* we have shut things down, 0x01 sent, 0x02
+			 * for received */
+	int state;	/* where we are */
+	int rstate;	/* where we are when reading */
+
+	BUF_MEM *init_buf;	/* buffer used during init */
+	void *init_msg;   	/* pointer to handshake message body, set by ssl3_get_message() */
+	int init_num;		/* amount read/written */
+	int init_off;		/* amount read/written */
+
+	/* used internally to point at a raw packet */
+	unsigned char *packet;
+	unsigned int packet_length;
+
+	struct ssl2_state_st *s2; /* SSLv2 variables */
+	struct ssl3_state_st *s3; /* SSLv3 variables */
+	struct dtls1_state_st *d1; /* DTLSv1 variables */
+
+	int read_ahead;		/* Read as many input bytes as possible
+	               	 	 * (for non-blocking reads) */
+
+	/* callback that allows applications to peek at protocol messages */
+	void (*msg_callback)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg);
+	void *msg_callback_arg;
+
+	int hit;		/* reusing a previous session */
+
+	X509_VERIFY_PARAM *param;
+
+#if 0
+	int purpose;		/* Purpose setting */
+	int trust;		/* Trust setting */
+#endif
+
+	/* crypto */
+	STACK_OF(SSL_CIPHER) *cipher_list;
+	STACK_OF(SSL_CIPHER) *cipher_list_by_id;
+
+	/* These are the ones being used, the ones in SSL_SESSION are
+	 * the ones to be 'copied' into these ones */
+	int mac_flags; 
+	EVP_CIPHER_CTX *enc_read_ctx;		/* cryptographic state */
+	EVP_MD_CTX *read_hash;		/* used for mac generation */
+#ifndef OPENSSL_NO_COMP
+	COMP_CTX *expand;			/* uncompress */
+#else
+	char *expand;
+#endif
+
+	EVP_CIPHER_CTX *enc_write_ctx;		/* cryptographic state */
+	EVP_MD_CTX *write_hash;		/* used for mac generation */
+#ifndef OPENSSL_NO_COMP
+	COMP_CTX *compress;			/* compression */
+#else
+	char *compress;	
+#endif
+
+	/* session info */
+
+	/* client cert? */
+	/* This is used to hold the server certificate used */
+	struct cert_st /* CERT */ *cert;
+
+	/* the session_id_context is used to ensure sessions are only reused
+	 * in the appropriate context */
+	unsigned int sid_ctx_length;
+	unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];
+
+	/* This can also be in the session once a session is established */
+	SSL_SESSION *session;
+
+        /* This can be disabled to prevent the use of uncached sessions */
+	int session_creation_enabled;
+
+	/* Default generate session ID callback. */
+	GEN_SESSION_CB generate_session_id;
+
+	/* Used in SSL2 and SSL3 */
+	int verify_mode;	/* 0 don't care about verify failure.
+				 * 1 fail if verify fails */
+	int (*verify_callback)(int ok,X509_STORE_CTX *ctx); /* fail if callback returns 0 */
+
+	void (*info_callback)(const SSL *ssl,int type,int val); /* optional informational callback */
+
+	int error;		/* error bytes to be written */
+	int error_code;		/* actual code */
+
+#ifndef OPENSSL_NO_KRB5
+	KSSL_CTX *kssl_ctx;     /* Kerberos 5 context */
+#endif	/* OPENSSL_NO_KRB5 */
+
+#ifndef OPENSSL_NO_PSK
+	unsigned int (*psk_client_callback)(SSL *ssl, const char *hint, char *identity,
+		unsigned int max_identity_len, unsigned char *psk,
+		unsigned int max_psk_len);
+	unsigned int (*psk_server_callback)(SSL *ssl, const char *identity,
+		unsigned char *psk, unsigned int max_psk_len);
+#endif
+
+	SSL_CTX *ctx;
+	/* set this flag to 1 and a sleep(1) is put into all SSL_read()
+	 * and SSL_write() calls, good for nbio debuging :-) */
+	int debug;	
+
+	/* extra application data */
+	long verify_result;
+	CRYPTO_EX_DATA ex_data;
+
+	/* for server side, keep the list of CA_dn we can use */
+	STACK_OF(X509_NAME) *client_CA;
+
+	int references;
+	unsigned long options; /* protocol behaviour */
+	unsigned long mode; /* API behaviour */
+	long max_cert_list;
+	int first_packet;
+	int client_version;	/* what was passed, used for
+				 * SSLv3/TLS rollback check */
+	unsigned int max_send_fragment;
+#ifndef OPENSSL_NO_TLSEXT
+	/* TLS extension debug callback */
+	void (*tlsext_debug_cb)(SSL *s, int client_server, int type,
+					unsigned char *data, int len,
+					void *arg);
+	void *tlsext_debug_arg;
+	char *tlsext_hostname;
+	int servername_done;   /* no further mod of servername 
+	                          0 : call the servername extension callback.
+	                          1 : prepare 2, allow last ack just after in server callback.
+	                          2 : don't call servername callback, no ack in server hello
+	                       */
+	/* certificate status request info */
+	/* Status type or -1 if no status type */
+	int tlsext_status_type;
+	/* Expect OCSP CertificateStatus message */
+	int tlsext_status_expected;
+	/* OCSP status request only */
+	STACK_OF(OCSP_RESPID) *tlsext_ocsp_ids;
+	X509_EXTENSIONS *tlsext_ocsp_exts;
+	/* OCSP response received or to be sent */
+	unsigned char *tlsext_ocsp_resp;
+	int tlsext_ocsp_resplen;
+
+	/* RFC4507 session ticket expected to be received or sent */
+	int tlsext_ticket_expected;
+#ifndef OPENSSL_NO_EC
+	size_t tlsext_ecpointformatlist_length;
+	unsigned char *tlsext_ecpointformatlist; /* our list */
+	size_t tlsext_ellipticcurvelist_length;
+	unsigned char *tlsext_ellipticcurvelist; /* our list */
+#endif /* OPENSSL_NO_EC */
+
+	/* draft-rescorla-tls-opaque-prf-input-00.txt information to be used for handshakes */
+	void *tlsext_opaque_prf_input;
+	size_t tlsext_opaque_prf_input_len;
+
+	/* TLS Session Ticket extension override */
+	TLS_SESSION_TICKET_EXT *tlsext_session_ticket;
+
+	/* TLS Session Ticket extension callback */
+	tls_session_ticket_ext_cb_fn tls_session_ticket_ext_cb;
+	void *tls_session_ticket_ext_cb_arg;
+
+	/* TLS pre-shared secret session resumption */
+	tls_session_secret_cb_fn tls_session_secret_cb;
+	void *tls_session_secret_cb_arg;
+
+	SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */
+#define session_ctx initial_ctx
+#else
+#define session_ctx ctx
+#endif /* OPENSSL_NO_TLSEXT */
+	};
+
+#ifdef __cplusplus
+}
+#endif
+
+#include <openssl/ssl2.h>
+#include <openssl/ssl3.h>
+#include <openssl/tls1.h> /* This is mostly sslv3 with a few tweaks */
+#include <openssl/dtls1.h> /* Datagram TLS */
+#include <openssl/ssl23.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* compatibility */
+#define SSL_set_app_data(s,arg)		(SSL_set_ex_data(s,0,(char *)arg))
+#define SSL_get_app_data(s)		(SSL_get_ex_data(s,0))
+#define SSL_SESSION_set_app_data(s,a)	(SSL_SESSION_set_ex_data(s,0,(char *)a))
+#define SSL_SESSION_get_app_data(s)	(SSL_SESSION_get_ex_data(s,0))
+#define SSL_CTX_get_app_data(ctx)	(SSL_CTX_get_ex_data(ctx,0))
+#define SSL_CTX_set_app_data(ctx,arg)	(SSL_CTX_set_ex_data(ctx,0,(char *)arg))
+
+/* The following are the possible values for ssl->state are are
+ * used to indicate where we are up to in the SSL connection establishment.
+ * The macros that follow are about the only things you should need to use
+ * and even then, only when using non-blocking IO.
+ * It can also be useful to work out where you were when the connection
+ * failed */
+
+#define SSL_ST_CONNECT			0x1000
+#define SSL_ST_ACCEPT			0x2000
+#define SSL_ST_MASK			0x0FFF
+#define SSL_ST_INIT			(SSL_ST_CONNECT|SSL_ST_ACCEPT)
+#define SSL_ST_BEFORE			0x4000
+#define SSL_ST_OK			0x03
+#define SSL_ST_RENEGOTIATE		(0x04|SSL_ST_INIT)
+
+#define SSL_CB_LOOP			0x01
+#define SSL_CB_EXIT			0x02
+#define SSL_CB_READ			0x04
+#define SSL_CB_WRITE			0x08
+#define SSL_CB_ALERT			0x4000 /* used in callback */
+#define SSL_CB_READ_ALERT		(SSL_CB_ALERT|SSL_CB_READ)
+#define SSL_CB_WRITE_ALERT		(SSL_CB_ALERT|SSL_CB_WRITE)
+#define SSL_CB_ACCEPT_LOOP		(SSL_ST_ACCEPT|SSL_CB_LOOP)
+#define SSL_CB_ACCEPT_EXIT		(SSL_ST_ACCEPT|SSL_CB_EXIT)
+#define SSL_CB_CONNECT_LOOP		(SSL_ST_CONNECT|SSL_CB_LOOP)
+#define SSL_CB_CONNECT_EXIT		(SSL_ST_CONNECT|SSL_CB_EXIT)
+#define SSL_CB_HANDSHAKE_START		0x10
+#define SSL_CB_HANDSHAKE_DONE		0x20
+
+/* Is the SSL_connection established? */
+#define SSL_get_state(a)		SSL_state(a)
+#define SSL_is_init_finished(a)		(SSL_state(a) == SSL_ST_OK)
+#define SSL_in_init(a)			((SSL_state(a)&SSL_ST_INIT) && \
+                                  !SSL_cutthrough_complete(a))
+#define SSL_in_before(a)		(SSL_state(a)&SSL_ST_BEFORE)
+#define SSL_in_connect_init(a)		(SSL_state(a)&SSL_ST_CONNECT)
+#define SSL_in_accept_init(a)		(SSL_state(a)&SSL_ST_ACCEPT)
+int SSL_cutthrough_complete(const SSL *s);
+
+/* The following 2 states are kept in ssl->rstate when reads fail,
+ * you should not need these */
+#define SSL_ST_READ_HEADER			0xF0
+#define SSL_ST_READ_BODY			0xF1
+#define SSL_ST_READ_DONE			0xF2
+
+/* Obtain latest Finished message
+ *   -- that we sent (SSL_get_finished)
+ *   -- that we expected from peer (SSL_get_peer_finished).
+ * Returns length (0 == no Finished so far), copies up to 'count' bytes. */
+size_t SSL_get_finished(const SSL *s, void *buf, size_t count);
+size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count);
+
+/* use either SSL_VERIFY_NONE or SSL_VERIFY_PEER, the last 2 options
+ * are 'ored' with SSL_VERIFY_PEER if they are desired */
+#define SSL_VERIFY_NONE			0x00
+#define SSL_VERIFY_PEER			0x01
+#define SSL_VERIFY_FAIL_IF_NO_PEER_CERT	0x02
+#define SSL_VERIFY_CLIENT_ONCE		0x04
+
+#define OpenSSL_add_ssl_algorithms()	SSL_library_init()
+#define SSLeay_add_ssl_algorithms()	SSL_library_init()
+
+/* this is for backward compatibility */
+#if 0 /* NEW_SSLEAY */
+#define SSL_CTX_set_default_verify(a,b,c) SSL_CTX_set_verify(a,b,c)
+#define SSL_set_pref_cipher(c,n)	SSL_set_cipher_list(c,n)
+#define SSL_add_session(a,b)            SSL_CTX_add_session((a),(b))
+#define SSL_remove_session(a,b)		SSL_CTX_remove_session((a),(b))
+#define SSL_flush_sessions(a,b)		SSL_CTX_flush_sessions((a),(b))
+#endif
+/* More backward compatibility */
+#define SSL_get_cipher(s) \
+		SSL_CIPHER_get_name(SSL_get_current_cipher(s))
+#define SSL_get_cipher_bits(s,np) \
+		SSL_CIPHER_get_bits(SSL_get_current_cipher(s),np)
+#define SSL_get_cipher_version(s) \
+		SSL_CIPHER_get_version(SSL_get_current_cipher(s))
+#define SSL_get_cipher_name(s) \
+		SSL_CIPHER_get_name(SSL_get_current_cipher(s))
+#define SSL_get_time(a)		SSL_SESSION_get_time(a)
+#define SSL_set_time(a,b)	SSL_SESSION_set_time((a),(b))
+#define SSL_get_timeout(a)	SSL_SESSION_get_timeout(a)
+#define SSL_set_timeout(a,b)	SSL_SESSION_set_timeout((a),(b))
+
+#define d2i_SSL_SESSION_bio(bp,s_id) ASN1_d2i_bio_of(SSL_SESSION,SSL_SESSION_new,d2i_SSL_SESSION,bp,s_id)
+#define i2d_SSL_SESSION_bio(bp,s_id) ASN1_i2d_bio_of(SSL_SESSION,i2d_SSL_SESSION,bp,s_id)
+
+DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
+
+#define SSL_AD_REASON_OFFSET		1000 /* offset to get SSL_R_... value from SSL_AD_... */
+
+/* These alert types are for SSLv3 and TLSv1 */
+#define SSL_AD_CLOSE_NOTIFY		SSL3_AD_CLOSE_NOTIFY
+#define SSL_AD_UNEXPECTED_MESSAGE	SSL3_AD_UNEXPECTED_MESSAGE /* fatal */
+#define SSL_AD_BAD_RECORD_MAC		SSL3_AD_BAD_RECORD_MAC     /* fatal */
+#define SSL_AD_DECRYPTION_FAILED	TLS1_AD_DECRYPTION_FAILED
+#define SSL_AD_RECORD_OVERFLOW		TLS1_AD_RECORD_OVERFLOW
+#define SSL_AD_DECOMPRESSION_FAILURE	SSL3_AD_DECOMPRESSION_FAILURE/* fatal */
+#define SSL_AD_HANDSHAKE_FAILURE	SSL3_AD_HANDSHAKE_FAILURE/* fatal */
+#define SSL_AD_NO_CERTIFICATE		SSL3_AD_NO_CERTIFICATE /* Not for TLS */
+#define SSL_AD_BAD_CERTIFICATE		SSL3_AD_BAD_CERTIFICATE
+#define SSL_AD_UNSUPPORTED_CERTIFICATE	SSL3_AD_UNSUPPORTED_CERTIFICATE
+#define SSL_AD_CERTIFICATE_REVOKED	SSL3_AD_CERTIFICATE_REVOKED
+#define SSL_AD_CERTIFICATE_EXPIRED	SSL3_AD_CERTIFICATE_EXPIRED
+#define SSL_AD_CERTIFICATE_UNKNOWN	SSL3_AD_CERTIFICATE_UNKNOWN
+#define SSL_AD_ILLEGAL_PARAMETER	SSL3_AD_ILLEGAL_PARAMETER   /* fatal */
+#define SSL_AD_UNKNOWN_CA		TLS1_AD_UNKNOWN_CA	/* fatal */
+#define SSL_AD_ACCESS_DENIED		TLS1_AD_ACCESS_DENIED	/* fatal */
+#define SSL_AD_DECODE_ERROR		TLS1_AD_DECODE_ERROR	/* fatal */
+#define SSL_AD_DECRYPT_ERROR		TLS1_AD_DECRYPT_ERROR
+#define SSL_AD_EXPORT_RESTRICTION	TLS1_AD_EXPORT_RESTRICTION/* fatal */
+#define SSL_AD_PROTOCOL_VERSION		TLS1_AD_PROTOCOL_VERSION /* fatal */
+#define SSL_AD_INSUFFICIENT_SECURITY	TLS1_AD_INSUFFICIENT_SECURITY/* fatal */
+#define SSL_AD_INTERNAL_ERROR		TLS1_AD_INTERNAL_ERROR	/* fatal */
+#define SSL_AD_USER_CANCELLED		TLS1_AD_USER_CANCELLED
+#define SSL_AD_NO_RENEGOTIATION		TLS1_AD_NO_RENEGOTIATION
+#define SSL_AD_UNSUPPORTED_EXTENSION	TLS1_AD_UNSUPPORTED_EXTENSION
+#define SSL_AD_CERTIFICATE_UNOBTAINABLE TLS1_AD_CERTIFICATE_UNOBTAINABLE
+#define SSL_AD_UNRECOGNIZED_NAME	TLS1_AD_UNRECOGNIZED_NAME
+#define SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE
+#define SSL_AD_BAD_CERTIFICATE_HASH_VALUE TLS1_AD_BAD_CERTIFICATE_HASH_VALUE
+#define SSL_AD_UNKNOWN_PSK_IDENTITY     TLS1_AD_UNKNOWN_PSK_IDENTITY /* fatal */
+
+#define SSL_ERROR_NONE			0
+#define SSL_ERROR_SSL			1
+#define SSL_ERROR_WANT_READ		2
+#define SSL_ERROR_WANT_WRITE		3
+#define SSL_ERROR_WANT_X509_LOOKUP	4
+#define SSL_ERROR_SYSCALL		5 /* look at error stack/return value/errno */
+#define SSL_ERROR_ZERO_RETURN		6
+#define SSL_ERROR_WANT_CONNECT		7
+#define SSL_ERROR_WANT_ACCEPT		8
+
+#define SSL_CTRL_NEED_TMP_RSA			1
+#define SSL_CTRL_SET_TMP_RSA			2
+#define SSL_CTRL_SET_TMP_DH			3
+#define SSL_CTRL_SET_TMP_ECDH			4
+#define SSL_CTRL_SET_TMP_RSA_CB			5
+#define SSL_CTRL_SET_TMP_DH_CB			6
+#define SSL_CTRL_SET_TMP_ECDH_CB		7
+
+#define SSL_CTRL_GET_SESSION_REUSED		8
+#define SSL_CTRL_GET_CLIENT_CERT_REQUEST	9
+#define SSL_CTRL_GET_NUM_RENEGOTIATIONS		10
+#define SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS	11
+#define SSL_CTRL_GET_TOTAL_RENEGOTIATIONS	12
+#define SSL_CTRL_GET_FLAGS			13
+#define SSL_CTRL_EXTRA_CHAIN_CERT		14
+
+#define SSL_CTRL_SET_MSG_CALLBACK               15
+#define SSL_CTRL_SET_MSG_CALLBACK_ARG           16
+
+/* only applies to datagram connections */
+#define SSL_CTRL_SET_MTU                17
+/* Stats */
+#define SSL_CTRL_SESS_NUMBER			20
+#define SSL_CTRL_SESS_CONNECT			21
+#define SSL_CTRL_SESS_CONNECT_GOOD		22
+#define SSL_CTRL_SESS_CONNECT_RENEGOTIATE	23
+#define SSL_CTRL_SESS_ACCEPT			24
+#define SSL_CTRL_SESS_ACCEPT_GOOD		25
+#define SSL_CTRL_SESS_ACCEPT_RENEGOTIATE	26
+#define SSL_CTRL_SESS_HIT			27
+#define SSL_CTRL_SESS_CB_HIT			28
+#define SSL_CTRL_SESS_MISSES			29
+#define SSL_CTRL_SESS_TIMEOUTS			30
+#define SSL_CTRL_SESS_CACHE_FULL		31
+#define SSL_CTRL_OPTIONS			32
+#define SSL_CTRL_MODE				33
+
+#define SSL_CTRL_GET_READ_AHEAD			40
+#define SSL_CTRL_SET_READ_AHEAD			41
+#define SSL_CTRL_SET_SESS_CACHE_SIZE		42
+#define SSL_CTRL_GET_SESS_CACHE_SIZE		43
+#define SSL_CTRL_SET_SESS_CACHE_MODE		44
+#define SSL_CTRL_GET_SESS_CACHE_MODE		45
+
+#define SSL_CTRL_GET_MAX_CERT_LIST		50
+#define SSL_CTRL_SET_MAX_CERT_LIST		51
+
+#define SSL_CTRL_SET_MAX_SEND_FRAGMENT		52
+
+/* see tls1.h for macros based on these */
+#ifndef OPENSSL_NO_TLSEXT
+#define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB	53
+#define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG	54
+#define SSL_CTRL_SET_TLSEXT_HOSTNAME		55
+#define SSL_CTRL_SET_TLSEXT_DEBUG_CB		56
+#define SSL_CTRL_SET_TLSEXT_DEBUG_ARG		57
+#define SSL_CTRL_GET_TLSEXT_TICKET_KEYS		58
+#define SSL_CTRL_SET_TLSEXT_TICKET_KEYS		59
+#define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT	60
+#define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB	61
+#define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB_ARG 62
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB	63
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG	64
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE	65
+#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS	66
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS	67
+#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS	68
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS	69
+#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP	70
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP	71
+
+#define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB	72
+#endif
+
+#define DTLS_CTRL_GET_TIMEOUT		73
+#define DTLS_CTRL_HANDLE_TIMEOUT	74
+#define DTLS_CTRL_LISTEN			75
+
+#define SSL_CTRL_GET_RI_SUPPORT			76
+#define SSL_CTRL_CLEAR_OPTIONS			77
+#define SSL_CTRL_CLEAR_MODE			78
+
+#define DTLSv1_get_timeout(ssl, arg) \
+	SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg)
+#define DTLSv1_handle_timeout(ssl) \
+	SSL_ctrl(ssl,DTLS_CTRL_HANDLE_TIMEOUT,0, NULL)
+#define DTLSv1_listen(ssl, peer) \
+	SSL_ctrl(ssl,DTLS_CTRL_LISTEN,0, (void *)peer)
+
+#define SSL_session_reused(ssl) \
+	SSL_ctrl((ssl),SSL_CTRL_GET_SESSION_REUSED,0,NULL)
+#define SSL_num_renegotiations(ssl) \
+	SSL_ctrl((ssl),SSL_CTRL_GET_NUM_RENEGOTIATIONS,0,NULL)
+#define SSL_clear_num_renegotiations(ssl) \
+	SSL_ctrl((ssl),SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS,0,NULL)
+#define SSL_total_renegotiations(ssl) \
+	SSL_ctrl((ssl),SSL_CTRL_GET_TOTAL_RENEGOTIATIONS,0,NULL)
+
+#define SSL_CTX_need_tmp_RSA(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_NEED_TMP_RSA,0,NULL)
+#define SSL_CTX_set_tmp_rsa(ctx,rsa) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_RSA,0,(char *)rsa)
+#define SSL_CTX_set_tmp_dh(ctx,dh) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH,0,(char *)dh)
+#define SSL_CTX_set_tmp_ecdh(ctx,ecdh) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_ECDH,0,(char *)ecdh)
+
+#define SSL_need_tmp_RSA(ssl) \
+	SSL_ctrl(ssl,SSL_CTRL_NEED_TMP_RSA,0,NULL)
+#define SSL_set_tmp_rsa(ssl,rsa) \
+	SSL_ctrl(ssl,SSL_CTRL_SET_TMP_RSA,0,(char *)rsa)
+#define SSL_set_tmp_dh(ssl,dh) \
+	SSL_ctrl(ssl,SSL_CTRL_SET_TMP_DH,0,(char *)dh)
+#define SSL_set_tmp_ecdh(ssl,ecdh) \
+	SSL_ctrl(ssl,SSL_CTRL_SET_TMP_ECDH,0,(char *)ecdh)
+
+#define SSL_CTX_add_extra_chain_cert(ctx,x509) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char *)x509)
+
+#ifndef OPENSSL_NO_BIO
+BIO_METHOD *BIO_f_ssl(void);
+BIO *BIO_new_ssl(SSL_CTX *ctx,int client);
+BIO *BIO_new_ssl_connect(SSL_CTX *ctx);
+BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx);
+int BIO_ssl_copy_session_id(BIO *to,BIO *from);
+void BIO_ssl_shutdown(BIO *ssl_bio);
+
+#endif
+
+int	SSL_CTX_set_cipher_list(SSL_CTX *,const char *str);
+SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth);
+void	SSL_CTX_free(SSL_CTX *);
+long SSL_CTX_set_timeout(SSL_CTX *ctx,long t);
+long SSL_CTX_get_timeout(const SSL_CTX *ctx);
+X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *);
+void SSL_CTX_set_cert_store(SSL_CTX *,X509_STORE *);
+int SSL_want(const SSL *s);
+int	SSL_clear(SSL *s);
+
+void	SSL_CTX_flush_sessions(SSL_CTX *ctx,long tm);
+
+const SSL_CIPHER *SSL_get_current_cipher(const SSL *s);
+int	SSL_CIPHER_get_bits(const SSL_CIPHER *c,int *alg_bits);
+char *	SSL_CIPHER_get_version(const SSL_CIPHER *c);
+const char *	SSL_CIPHER_get_name(const SSL_CIPHER *c);
+
+int	SSL_get_fd(const SSL *s);
+int	SSL_get_rfd(const SSL *s);
+int	SSL_get_wfd(const SSL *s);
+const char  * SSL_get_cipher_list(const SSL *s,int n);
+char *	SSL_get_shared_ciphers(const SSL *s, char *buf, int len);
+int	SSL_get_read_ahead(const SSL * s);
+int	SSL_pending(const SSL *s);
+#ifndef OPENSSL_NO_SOCK
+int	SSL_set_fd(SSL *s, int fd);
+int	SSL_set_rfd(SSL *s, int fd);
+int	SSL_set_wfd(SSL *s, int fd);
+#endif
+#ifndef OPENSSL_NO_BIO
+void	SSL_set_bio(SSL *s, BIO *rbio,BIO *wbio);
+BIO *	SSL_get_rbio(const SSL *s);
+BIO *	SSL_get_wbio(const SSL *s);
+#endif
+int	SSL_set_cipher_list(SSL *s, const char *str);
+int	SSL_set_cipher_lists(SSL *s, STACK_OF(SSL_CIPHER) *sk);
+void	SSL_set_read_ahead(SSL *s, int yes);
+int	SSL_get_verify_mode(const SSL *s);
+int	SSL_get_verify_depth(const SSL *s);
+int	(*SSL_get_verify_callback(const SSL *s))(int,X509_STORE_CTX *);
+void	SSL_set_verify(SSL *s, int mode,
+		       int (*callback)(int ok,X509_STORE_CTX *ctx));
+void	SSL_set_verify_depth(SSL *s, int depth);
+#ifndef OPENSSL_NO_RSA
+int	SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa);
+#endif
+int	SSL_use_RSAPrivateKey_ASN1(SSL *ssl, unsigned char *d, long len);
+int	SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey);
+int	SSL_use_PrivateKey_ASN1(int pk,SSL *ssl, const unsigned char *d, long len);
+int	SSL_use_certificate(SSL *ssl, X509 *x);
+int	SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len);
+int	SSL_use_certificate_chain(SSL *ssl, STACK_OF(X509) *cert_chain);
+STACK_OF(X509) * SSL_get_certificate_chain(SSL *ssl, X509 *x);
+
+#ifndef OPENSSL_NO_STDIO
+int	SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type);
+int	SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type);
+int	SSL_use_certificate_file(SSL *ssl, const char *file, int type);
+int	SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type);
+int	SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type);
+int	SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type);
+int	SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file); /* PEM type */
+STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file);
+int	SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
+					    const char *file);
+#ifndef OPENSSL_SYS_VMS
+#ifndef OPENSSL_SYS_MACINTOSH_CLASSIC /* XXXXX: Better scheme needed! [was: #ifndef MAC_OS_pre_X] */
+int	SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
+					   const char *dir);
+#endif
+#endif
+
+#endif
+
+void	SSL_load_error_strings(void );
+const char *SSL_state_string(const SSL *s);
+const char *SSL_rstate_string(const SSL *s);
+const char *SSL_state_string_long(const SSL *s);
+const char *SSL_rstate_string_long(const SSL *s);
+long	SSL_SESSION_get_time(const SSL_SESSION *s);
+long	SSL_SESSION_set_time(SSL_SESSION *s, long t);
+long	SSL_SESSION_get_timeout(const SSL_SESSION *s);
+long	SSL_SESSION_set_timeout(SSL_SESSION *s, long t);
+void	SSL_copy_session_id(SSL *to,const SSL *from);
+
+SSL_SESSION *SSL_SESSION_new(void);
+const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s,
+					unsigned int *len);
+#ifndef OPENSSL_NO_FP_API
+int	SSL_SESSION_print_fp(FILE *fp,const SSL_SESSION *ses);
+#endif
+#ifndef OPENSSL_NO_BIO
+int	SSL_SESSION_print(BIO *fp,const SSL_SESSION *ses);
+#endif
+void	SSL_SESSION_free(SSL_SESSION *ses);
+int	i2d_SSL_SESSION(SSL_SESSION *in,unsigned char **pp);
+int	SSL_set_session(SSL *to, SSL_SESSION *session);
+void	SSL_set_session_creation_enabled(SSL *, int);
+int	SSL_CTX_add_session(SSL_CTX *s, SSL_SESSION *c);
+int	SSL_CTX_remove_session(SSL_CTX *,SSL_SESSION *c);
+int	SSL_CTX_set_generate_session_id(SSL_CTX *, GEN_SESSION_CB);
+int	SSL_set_generate_session_id(SSL *, GEN_SESSION_CB);
+int	SSL_has_matching_session_id(const SSL *ssl, const unsigned char *id,
+					unsigned int id_len);
+SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a,const unsigned char **pp,
+			     long length);
+
+#ifdef HEADER_X509_H
+X509 *	SSL_get_peer_certificate(const SSL *s);
+#endif
+
+STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *s);
+
+int SSL_CTX_get_verify_mode(const SSL_CTX *ctx);
+int SSL_CTX_get_verify_depth(const SSL_CTX *ctx);
+int (*SSL_CTX_get_verify_callback(const SSL_CTX *ctx))(int,X509_STORE_CTX *);
+void SSL_CTX_set_verify(SSL_CTX *ctx,int mode,
+			int (*callback)(int, X509_STORE_CTX *));
+void SSL_CTX_set_verify_depth(SSL_CTX *ctx,int depth);
+void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, int (*cb)(X509_STORE_CTX *,void *), void *arg);
+#ifndef OPENSSL_NO_RSA
+int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa);
+#endif
+int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d, long len);
+int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey);
+int SSL_CTX_use_PrivateKey_ASN1(int pk,SSL_CTX *ctx,
+	const unsigned char *d, long len);
+int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x);
+int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const unsigned char *d);
+
+void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb);
+void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u);
+
+int SSL_CTX_check_private_key(const SSL_CTX *ctx);
+int SSL_check_private_key(const SSL *ctx);
+
+int	SSL_CTX_set_session_id_context(SSL_CTX *ctx,const unsigned char *sid_ctx,
+				       unsigned int sid_ctx_len);
+
+SSL *	SSL_new(SSL_CTX *ctx);
+int	SSL_set_session_id_context(SSL *ssl,const unsigned char *sid_ctx,
+				   unsigned int sid_ctx_len);
+
+int SSL_CTX_set_purpose(SSL_CTX *s, int purpose);
+int SSL_set_purpose(SSL *s, int purpose);
+int SSL_CTX_set_trust(SSL_CTX *s, int trust);
+int SSL_set_trust(SSL *s, int trust);
+
+int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm);
+int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm);
+
+void	SSL_free(SSL *ssl);
+int 	SSL_accept(SSL *ssl);
+int 	SSL_connect(SSL *ssl);
+int 	SSL_read(SSL *ssl,void *buf,int num);
+int 	SSL_peek(SSL *ssl,void *buf,int num);
+int 	SSL_write(SSL *ssl,const void *buf,int num);
+long	SSL_ctrl(SSL *ssl,int cmd, long larg, void *parg);
+long	SSL_callback_ctrl(SSL *, int, void (*)(void));
+long	SSL_CTX_ctrl(SSL_CTX *ctx,int cmd, long larg, void *parg);
+long	SSL_CTX_callback_ctrl(SSL_CTX *, int, void (*)(void));
+
+int	SSL_get_error(const SSL *s,int ret_code);
+const char *SSL_get_version(const SSL *s);
+
+/* This sets the 'default' SSL version that SSL_new() will create */
+int SSL_CTX_set_ssl_version(SSL_CTX *ctx, const SSL_METHOD *meth);
+
+#ifndef OPENSSL_NO_SSL2
+const SSL_METHOD *SSLv2_method(void);		/* SSLv2 */
+const SSL_METHOD *SSLv2_server_method(void);	/* SSLv2 */
+const SSL_METHOD *SSLv2_client_method(void);	/* SSLv2 */
+#endif
+
+const SSL_METHOD *SSLv3_method(void);		/* SSLv3 */
+const SSL_METHOD *SSLv3_server_method(void);	/* SSLv3 */
+const SSL_METHOD *SSLv3_client_method(void);	/* SSLv3 */
+
+const SSL_METHOD *SSLv23_method(void);	/* SSLv3 but can rollback to v2 */
+const SSL_METHOD *SSLv23_server_method(void);	/* SSLv3 but can rollback to v2 */
+const SSL_METHOD *SSLv23_client_method(void);	/* SSLv3 but can rollback to v2 */
+
+const SSL_METHOD *TLSv1_method(void);		/* TLSv1.0 */
+const SSL_METHOD *TLSv1_server_method(void);	/* TLSv1.0 */
+const SSL_METHOD *TLSv1_client_method(void);	/* TLSv1.0 */
+
+const SSL_METHOD *DTLSv1_method(void);		/* DTLSv1.0 */
+const SSL_METHOD *DTLSv1_server_method(void);	/* DTLSv1.0 */
+const SSL_METHOD *DTLSv1_client_method(void);	/* DTLSv1.0 */
+
+STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s);
+
+int SSL_do_handshake(SSL *s);
+int SSL_renegotiate(SSL *s);
+int SSL_renegotiate_pending(SSL *s);
+int SSL_shutdown(SSL *s);
+
+const SSL_METHOD *SSL_get_ssl_method(SSL *s);
+int SSL_set_ssl_method(SSL *s, const SSL_METHOD *method);
+const char *SSL_alert_type_string_long(int value);
+const char *SSL_alert_type_string(int value);
+const char *SSL_alert_desc_string_long(int value);
+const char *SSL_alert_desc_string(int value);
+
+void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list);
+void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list);
+STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s);
+STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *s);
+int SSL_add_client_CA(SSL *ssl,X509 *x);
+int SSL_CTX_add_client_CA(SSL_CTX *ctx,X509 *x);
+
+void SSL_set_connect_state(SSL *s);
+void SSL_set_accept_state(SSL *s);
+
+long SSL_get_default_timeout(const SSL *s);
+
+int SSL_library_init(void );
+
+char *SSL_CIPHER_description(const SSL_CIPHER *,char *buf,int size);
+STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *sk);
+
+SSL *SSL_dup(SSL *ssl);
+
+X509 *SSL_get_certificate(const SSL *ssl);
+/* EVP_PKEY */ struct evp_pkey_st *SSL_get_privatekey(SSL *ssl);
+
+void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx,int mode);
+int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx);
+void SSL_set_quiet_shutdown(SSL *ssl,int mode);
+int SSL_get_quiet_shutdown(const SSL *ssl);
+void SSL_set_shutdown(SSL *ssl,int mode);
+int SSL_get_shutdown(const SSL *ssl);
+int SSL_version(const SSL *ssl);
+int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx);
+int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,
+	const char *CApath);
+#define SSL_get0_session SSL_get_session /* just peek at pointer */
+SSL_SESSION *SSL_get_session(const SSL *ssl);
+SSL_SESSION *SSL_get1_session(SSL *ssl); /* obtain a reference count */
+SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl);
+SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX* ctx);
+void SSL_set_info_callback(SSL *ssl,
+			   void (*cb)(const SSL *ssl,int type,int val));
+void (*SSL_get_info_callback(const SSL *ssl))(const SSL *ssl,int type,int val);
+int SSL_state(const SSL *ssl);
+
+void SSL_set_verify_result(SSL *ssl,long v);
+long SSL_get_verify_result(const SSL *ssl);
+
+int SSL_set_ex_data(SSL *ssl,int idx,void *data);
+void *SSL_get_ex_data(const SSL *ssl,int idx);
+int SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+	CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+
+int SSL_SESSION_set_ex_data(SSL_SESSION *ss,int idx,void *data);
+void *SSL_SESSION_get_ex_data(const SSL_SESSION *ss,int idx);
+int SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+	CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+
+int SSL_CTX_set_ex_data(SSL_CTX *ssl,int idx,void *data);
+void *SSL_CTX_get_ex_data(const SSL_CTX *ssl,int idx);
+int SSL_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+	CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+
+int SSL_get_ex_data_X509_STORE_CTX_idx(void );
+
+#define SSL_CTX_sess_set_cache_size(ctx,t) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_SIZE,t,NULL)
+#define SSL_CTX_sess_get_cache_size(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_SIZE,0,NULL)
+#define SSL_CTX_set_session_cache_mode(ctx,m) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_MODE,m,NULL)
+#define SSL_CTX_get_session_cache_mode(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_MODE,0,NULL)
+
+#define SSL_CTX_get_default_read_ahead(ctx) SSL_CTX_get_read_ahead(ctx)
+#define SSL_CTX_set_default_read_ahead(ctx,m) SSL_CTX_set_read_ahead(ctx,m)
+#define SSL_CTX_get_read_ahead(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_GET_READ_AHEAD,0,NULL)
+#define SSL_CTX_set_read_ahead(ctx,m) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_READ_AHEAD,m,NULL)
+#define SSL_CTX_get_max_cert_list(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL)
+#define SSL_CTX_set_max_cert_list(ctx,m) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL)
+#define SSL_get_max_cert_list(ssl) \
+	SSL_ctrl(ssl,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL)
+#define SSL_set_max_cert_list(ssl,m) \
+	SSL_ctrl(ssl,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL)
+
+#define SSL_CTX_set_max_send_fragment(ctx,m) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_SEND_FRAGMENT,m,NULL)
+#define SSL_set_max_send_fragment(ssl,m) \
+	SSL_ctrl(ssl,SSL_CTRL_SET_MAX_SEND_FRAGMENT,m,NULL)
+
+     /* NB: the keylength is only applicable when is_export is true */
+#ifndef OPENSSL_NO_RSA
+void SSL_CTX_set_tmp_rsa_callback(SSL_CTX *ctx,
+				  RSA *(*cb)(SSL *ssl,int is_export,
+					     int keylength));
+
+void SSL_set_tmp_rsa_callback(SSL *ssl,
+				  RSA *(*cb)(SSL *ssl,int is_export,
+					     int keylength));
+#endif
+#ifndef OPENSSL_NO_DH
+void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,
+				 DH *(*dh)(SSL *ssl,int is_export,
+					   int keylength));
+void SSL_set_tmp_dh_callback(SSL *ssl,
+				 DH *(*dh)(SSL *ssl,int is_export,
+					   int keylength));
+#endif
+#ifndef OPENSSL_NO_ECDH
+void SSL_CTX_set_tmp_ecdh_callback(SSL_CTX *ctx,
+				 EC_KEY *(*ecdh)(SSL *ssl,int is_export,
+					   int keylength));
+void SSL_set_tmp_ecdh_callback(SSL *ssl,
+				 EC_KEY *(*ecdh)(SSL *ssl,int is_export,
+					   int keylength));
+#endif
+
+#ifndef OPENSSL_NO_COMP
+const COMP_METHOD *SSL_get_current_compression(SSL *s);
+const COMP_METHOD *SSL_get_current_expansion(SSL *s);
+const char *SSL_COMP_get_name(const COMP_METHOD *comp);
+STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void);
+int SSL_COMP_add_compression_method(int id,COMP_METHOD *cm);
+#else
+const void *SSL_get_current_compression(SSL *s);
+const void *SSL_get_current_expansion(SSL *s);
+const char *SSL_COMP_get_name(const void *comp);
+void *SSL_COMP_get_compression_methods(void);
+int SSL_COMP_add_compression_method(int id,void *cm);
+#endif
+
+/* TLS extensions functions */
+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len);
+
+int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb,
+				  void *arg);
+
+/* Pre-shared secret session resumption functions */
+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_SSL_strings(void);
+
+/* Error codes for the SSL functions. */
+
+/* Function codes. */
+#define SSL_F_CLIENT_CERTIFICATE			 100
+#define SSL_F_CLIENT_FINISHED				 167
+#define SSL_F_CLIENT_HELLO				 101
+#define SSL_F_CLIENT_MASTER_KEY				 102
+#define SSL_F_D2I_SSL_SESSION				 103
+#define SSL_F_DO_DTLS1_WRITE				 245
+#define SSL_F_DO_SSL3_WRITE				 104
+#define SSL_F_DTLS1_ACCEPT				 246
+#define SSL_F_DTLS1_ADD_CERT_TO_BUF			 295
+#define SSL_F_DTLS1_BUFFER_RECORD			 247
+#define SSL_F_DTLS1_CLIENT_HELLO			 248
+#define SSL_F_DTLS1_CONNECT				 249
+#define SSL_F_DTLS1_ENC					 250
+#define SSL_F_DTLS1_GET_HELLO_VERIFY			 251
+#define SSL_F_DTLS1_GET_MESSAGE				 252
+#define SSL_F_DTLS1_GET_MESSAGE_FRAGMENT		 253
+#define SSL_F_DTLS1_GET_RECORD				 254
+#define SSL_F_DTLS1_HANDLE_TIMEOUT			 297
+#define SSL_F_DTLS1_OUTPUT_CERT_CHAIN			 255
+#define SSL_F_DTLS1_PREPROCESS_FRAGMENT			 288
+#define SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE		 256
+#define SSL_F_DTLS1_PROCESS_RECORD			 257
+#define SSL_F_DTLS1_READ_BYTES				 258
+#define SSL_F_DTLS1_READ_FAILED				 259
+#define SSL_F_DTLS1_SEND_CERTIFICATE_REQUEST		 260
+#define SSL_F_DTLS1_SEND_CLIENT_CERTIFICATE		 261
+#define SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE		 262
+#define SSL_F_DTLS1_SEND_CLIENT_VERIFY			 263
+#define SSL_F_DTLS1_SEND_HELLO_VERIFY_REQUEST		 264
+#define SSL_F_DTLS1_SEND_SERVER_CERTIFICATE		 265
+#define SSL_F_DTLS1_SEND_SERVER_HELLO			 266
+#define SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE		 267
+#define SSL_F_DTLS1_WRITE_APP_DATA_BYTES		 268
+#define SSL_F_GET_CLIENT_FINISHED			 105
+#define SSL_F_GET_CLIENT_HELLO				 106
+#define SSL_F_GET_CLIENT_MASTER_KEY			 107
+#define SSL_F_GET_SERVER_FINISHED			 108
+#define SSL_F_GET_SERVER_HELLO				 109
+#define SSL_F_GET_SERVER_VERIFY				 110
+#define SSL_F_I2D_SSL_SESSION				 111
+#define SSL_F_READ_N					 112
+#define SSL_F_REQUEST_CERTIFICATE			 113
+#define SSL_F_SERVER_FINISH				 239
+#define SSL_F_SERVER_HELLO				 114
+#define SSL_F_SERVER_VERIFY				 240
+#define SSL_F_SSL23_ACCEPT				 115
+#define SSL_F_SSL23_CLIENT_HELLO			 116
+#define SSL_F_SSL23_CONNECT				 117
+#define SSL_F_SSL23_GET_CLIENT_HELLO			 118
+#define SSL_F_SSL23_GET_SERVER_HELLO			 119
+#define SSL_F_SSL23_PEEK				 237
+#define SSL_F_SSL23_READ				 120
+#define SSL_F_SSL23_WRITE				 121
+#define SSL_F_SSL2_ACCEPT				 122
+#define SSL_F_SSL2_CONNECT				 123
+#define SSL_F_SSL2_ENC_INIT				 124
+#define SSL_F_SSL2_GENERATE_KEY_MATERIAL		 241
+#define SSL_F_SSL2_PEEK					 234
+#define SSL_F_SSL2_READ					 125
+#define SSL_F_SSL2_READ_INTERNAL			 236
+#define SSL_F_SSL2_SET_CERTIFICATE			 126
+#define SSL_F_SSL2_WRITE				 127
+#define SSL_F_SSL3_ACCEPT				 128
+#define SSL_F_SSL3_ADD_CERT_TO_BUF			 296
+#define SSL_F_SSL3_CALLBACK_CTRL			 233
+#define SSL_F_SSL3_CHANGE_CIPHER_STATE			 129
+#define SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM		 130
+#define SSL_F_SSL3_CLIENT_HELLO				 131
+#define SSL_F_SSL3_CONNECT				 132
+#define SSL_F_SSL3_CTRL					 213
+#define SSL_F_SSL3_CTX_CTRL				 133
+#define SSL_F_SSL3_DIGEST_CACHED_RECORDS		 293
+#define SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC		 292
+#define SSL_F_SSL3_ENC					 134
+#define SSL_F_SSL3_GENERATE_KEY_BLOCK			 238
+#define SSL_F_SSL3_GET_CERTIFICATE_REQUEST		 135
+#define SSL_F_SSL3_GET_CERT_STATUS			 289
+#define SSL_F_SSL3_GET_CERT_VERIFY			 136
+#define SSL_F_SSL3_GET_CLIENT_CERTIFICATE		 137
+#define SSL_F_SSL3_GET_CLIENT_HELLO			 138
+#define SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE		 139
+#define SSL_F_SSL3_GET_FINISHED				 140
+#define SSL_F_SSL3_GET_KEY_EXCHANGE			 141
+#define SSL_F_SSL3_GET_MESSAGE				 142
+#define SSL_F_SSL3_GET_NEW_SESSION_TICKET		 283
+#define SSL_F_SSL3_GET_RECORD				 143
+#define SSL_F_SSL3_GET_SERVER_CERTIFICATE		 144
+#define SSL_F_SSL3_GET_SERVER_DONE			 145
+#define SSL_F_SSL3_GET_SERVER_HELLO			 146
+#define SSL_F_SSL3_HANDSHAKE_MAC			 285
+#define SSL_F_SSL3_NEW_SESSION_TICKET			 287
+#define SSL_F_SSL3_OUTPUT_CERT_CHAIN			 147
+#define SSL_F_SSL3_PEEK					 235
+#define SSL_F_SSL3_READ_BYTES				 148
+#define SSL_F_SSL3_READ_N				 149
+#define SSL_F_SSL3_SEND_CERTIFICATE_REQUEST		 150
+#define SSL_F_SSL3_SEND_CLIENT_CERTIFICATE		 151
+#define SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE		 152
+#define SSL_F_SSL3_SEND_CLIENT_VERIFY			 153
+#define SSL_F_SSL3_SEND_SERVER_CERTIFICATE		 154
+#define SSL_F_SSL3_SEND_SERVER_HELLO			 242
+#define SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE		 155
+#define SSL_F_SSL3_SETUP_KEY_BLOCK			 157
+#define SSL_F_SSL3_SETUP_READ_BUFFER			 156
+#define SSL_F_SSL3_SETUP_WRITE_BUFFER			 291
+#define SSL_F_SSL3_WRITE_BYTES				 158
+#define SSL_F_SSL3_WRITE_PENDING			 159
+#define SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT	 298
+#define SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT		 277
+#define SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK	 215
+#define SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK	 216
+#define SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT	 299
+#define SSL_F_SSL_ADD_SERVERHELLO_TLSEXT		 278
+#define SSL_F_SSL_BAD_METHOD				 160
+#define SSL_F_SSL_BYTES_TO_CIPHER_LIST			 161
+#define SSL_F_SSL_CERT_DUP				 221
+#define SSL_F_SSL_CERT_INST				 222
+#define SSL_F_SSL_CERT_INSTANTIATE			 214
+#define SSL_F_SSL_CERT_NEW				 162
+#define SSL_F_SSL_CHECK_PRIVATE_KEY			 163
+#define SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT		 280
+#define SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG		 279
+#define SSL_F_SSL_CIPHER_PROCESS_RULESTR		 230
+#define SSL_F_SSL_CIPHER_STRENGTH_SORT			 231
+#define SSL_F_SSL_CLEAR					 164
+#define SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD		 165
+#define SSL_F_SSL_CREATE_CIPHER_LIST			 166
+#define SSL_F_SSL_CTRL					 232
+#define SSL_F_SSL_CTX_CHECK_PRIVATE_KEY			 168
+#define SSL_F_SSL_CTX_NEW				 169
+#define SSL_F_SSL_CTX_SET_CIPHER_LIST			 269
+#define SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE		 290
+#define SSL_F_SSL_CTX_SET_PURPOSE			 226
+#define SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT		 219
+#define SSL_F_SSL_CTX_SET_SSL_VERSION			 170
+#define SSL_F_SSL_CTX_SET_TRUST				 229
+#define SSL_F_SSL_CTX_USE_CERTIFICATE			 171
+#define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1		 172
+#define SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE	 220
+#define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE		 173
+#define SSL_F_SSL_CTX_USE_PRIVATEKEY			 174
+#define SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1		 175
+#define SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE		 176
+#define SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT		 272
+#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY			 177
+#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1		 178
+#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE		 179
+#define SSL_F_SSL_DO_HANDSHAKE				 180
+#define SSL_F_SSL_GET_NEW_SESSION			 181
+#define SSL_F_SSL_GET_PREV_SESSION			 217
+#define SSL_F_SSL_GET_SERVER_SEND_CERT			 182
+#define SSL_F_SSL_GET_SIGN_PKEY				 183
+#define SSL_F_SSL_INIT_WBIO_BUFFER			 184
+#define SSL_F_SSL_LOAD_CLIENT_CA_FILE			 185
+#define SSL_F_SSL_NEW					 186
+#define SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT	 300
+#define SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT		 302
+#define SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT	 301
+#define SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT		 303
+#define SSL_F_SSL_PEEK					 270
+#define SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT		 281
+#define SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT		 282
+#define SSL_F_SSL_READ					 223
+#define SSL_F_SSL_RSA_PRIVATE_DECRYPT			 187
+#define SSL_F_SSL_RSA_PUBLIC_ENCRYPT			 188
+#define SSL_F_SSL_SESSION_NEW				 189
+#define SSL_F_SSL_SESSION_PRINT_FP			 190
+#define SSL_F_SSL_SESS_CERT_NEW				 225
+#define SSL_F_SSL_SET_CERT				 191
+#define SSL_F_SSL_SET_CIPHER_LIST			 271
+#define SSL_F_SSL_SET_FD				 192
+#define SSL_F_SSL_SET_PKEY				 193
+#define SSL_F_SSL_SET_PURPOSE				 227
+#define SSL_F_SSL_SET_RFD				 194
+#define SSL_F_SSL_SET_SESSION				 195
+#define SSL_F_SSL_SET_SESSION_ID_CONTEXT		 218
+#define SSL_F_SSL_SET_SESSION_TICKET_EXT		 294
+#define SSL_F_SSL_SET_TRUST				 228
+#define SSL_F_SSL_SET_WFD				 196
+#define SSL_F_SSL_SHUTDOWN				 224
+#define SSL_F_SSL_UNDEFINED_CONST_FUNCTION		 243
+#define SSL_F_SSL_UNDEFINED_FUNCTION			 197
+#define SSL_F_SSL_UNDEFINED_VOID_FUNCTION		 244
+#define SSL_F_SSL_USE_CERTIFICATE			 198
+#define SSL_F_SSL_USE_CERTIFICATE_ASN1			 199
+#define SSL_F_SSL_USE_CERTIFICATE_CHAIN			 2000
+#define SSL_F_SSL_USE_CERTIFICATE_FILE			 200
+#define SSL_F_SSL_USE_PRIVATEKEY			 201
+#define SSL_F_SSL_USE_PRIVATEKEY_ASN1			 202
+#define SSL_F_SSL_USE_PRIVATEKEY_FILE			 203
+#define SSL_F_SSL_USE_PSK_IDENTITY_HINT			 273
+#define SSL_F_SSL_USE_RSAPRIVATEKEY			 204
+#define SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1		 205
+#define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE		 206
+#define SSL_F_SSL_VERIFY_CERT_CHAIN			 207
+#define SSL_F_SSL_WRITE					 208
+#define SSL_F_TLS1_CERT_VERIFY_MAC			 286
+#define SSL_F_TLS1_CHANGE_CIPHER_STATE			 209
+#define SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT		 274
+#define SSL_F_TLS1_ENC					 210
+#define SSL_F_TLS1_PREPARE_CLIENTHELLO_TLSEXT		 275
+#define SSL_F_TLS1_PREPARE_SERVERHELLO_TLSEXT		 276
+#define SSL_F_TLS1_PRF					 284
+#define SSL_F_TLS1_SETUP_KEY_BLOCK			 211
+#define SSL_F_WRITE_PENDING				 212
+
+/* Reason codes. */
+#define SSL_R_APP_DATA_IN_HANDSHAKE			 100
+#define SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT 272
+#define SSL_R_BAD_ALERT_RECORD				 101
+#define SSL_R_BAD_AUTHENTICATION_TYPE			 102
+#define SSL_R_BAD_CHANGE_CIPHER_SPEC			 103
+#define SSL_R_BAD_CHECKSUM				 104
+#define SSL_R_BAD_DATA_RETURNED_BY_CALLBACK		 106
+#define SSL_R_BAD_DECOMPRESSION				 107
+#define SSL_R_BAD_DH_G_LENGTH				 108
+#define SSL_R_BAD_DH_PUB_KEY_LENGTH			 109
+#define SSL_R_BAD_DH_P_LENGTH				 110
+#define SSL_R_BAD_DIGEST_LENGTH				 111
+#define SSL_R_BAD_DSA_SIGNATURE				 112
+#define SSL_R_BAD_ECC_CERT				 304
+#define SSL_R_BAD_ECDSA_SIGNATURE			 305
+#define SSL_R_BAD_ECPOINT				 306
+#define SSL_R_BAD_HANDSHAKE_LENGTH			 332
+#define SSL_R_BAD_HELLO_REQUEST				 105
+#define SSL_R_BAD_LENGTH				 271
+#define SSL_R_BAD_MAC_DECODE				 113
+#define SSL_R_BAD_MAC_LENGTH				 333
+#define SSL_R_BAD_MESSAGE_TYPE				 114
+#define SSL_R_BAD_PACKET_LENGTH				 115
+#define SSL_R_BAD_PROTOCOL_VERSION_NUMBER		 116
+#define SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH		 316
+#define SSL_R_BAD_RESPONSE_ARGUMENT			 117
+#define SSL_R_BAD_RSA_DECRYPT				 118
+#define SSL_R_BAD_RSA_ENCRYPT				 119
+#define SSL_R_BAD_RSA_E_LENGTH				 120
+#define SSL_R_BAD_RSA_MODULUS_LENGTH			 121
+#define SSL_R_BAD_RSA_SIGNATURE				 122
+#define SSL_R_BAD_SIGNATURE				 123
+#define SSL_R_BAD_SSL_FILETYPE				 124
+#define SSL_R_BAD_SSL_SESSION_ID_LENGTH			 125
+#define SSL_R_BAD_STATE					 126
+#define SSL_R_BAD_WRITE_RETRY				 127
+#define SSL_R_BIO_NOT_SET				 128
+#define SSL_R_BLOCK_CIPHER_PAD_IS_WRONG			 129
+#define SSL_R_BN_LIB					 130
+#define SSL_R_CA_DN_LENGTH_MISMATCH			 131
+#define SSL_R_CA_DN_TOO_LONG				 132
+#define SSL_R_CCS_RECEIVED_EARLY			 133
+#define SSL_R_CERTIFICATE_VERIFY_FAILED			 134
+#define SSL_R_CERT_LENGTH_MISMATCH			 135
+#define SSL_R_CHALLENGE_IS_DIFFERENT			 136
+#define SSL_R_CIPHER_CODE_WRONG_LENGTH			 137
+#define SSL_R_CIPHER_OR_HASH_UNAVAILABLE		 138
+#define SSL_R_CIPHER_TABLE_SRC_ERROR			 139
+#define SSL_R_CLIENTHELLO_TLSEXT			 226
+#define SSL_R_COMPRESSED_LENGTH_TOO_LONG		 140
+#define SSL_R_COMPRESSION_DISABLED			 343
+#define SSL_R_COMPRESSION_FAILURE			 141
+#define SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE	 307
+#define SSL_R_COMPRESSION_LIBRARY_ERROR			 142
+#define SSL_R_CONNECTION_ID_IS_DIFFERENT		 143
+#define SSL_R_CONNECTION_TYPE_NOT_SET			 144
+#define SSL_R_COOKIE_MISMATCH				 308
+#define SSL_R_DATA_BETWEEN_CCS_AND_FINISHED		 145
+#define SSL_R_DATA_LENGTH_TOO_LONG			 146
+#define SSL_R_DECRYPTION_FAILED				 147
+#define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC	 281
+#define SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG		 148
+#define SSL_R_DIGEST_CHECK_FAILED			 149
+#define SSL_R_DTLS_MESSAGE_TOO_BIG			 334
+#define SSL_R_DUPLICATE_COMPRESSION_ID			 309
+#define SSL_R_ECC_CERT_NOT_FOR_KEY_AGREEMENT		 317
+#define SSL_R_ECC_CERT_NOT_FOR_SIGNING			 318
+#define SSL_R_ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE	 322
+#define SSL_R_ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE	 323
+#define SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER		 310
+#define SSL_R_ENCRYPTED_LENGTH_TOO_LONG			 150
+#define SSL_R_ERROR_GENERATING_TMP_RSA_KEY		 282
+#define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST		 151
+#define SSL_R_EXCESSIVE_MESSAGE_SIZE			 152
+#define SSL_R_EXTRA_DATA_IN_MESSAGE			 153
+#define SSL_R_GOT_A_FIN_BEFORE_A_CCS			 154
+#define SSL_R_HTTPS_PROXY_REQUEST			 155
+#define SSL_R_HTTP_REQUEST				 156
+#define SSL_R_ILLEGAL_PADDING				 283
+#define SSL_R_INCONSISTENT_COMPRESSION			 340
+#define SSL_R_INVALID_CHALLENGE_LENGTH			 158
+#define SSL_R_INVALID_COMMAND				 280
+#define SSL_R_INVALID_COMPRESSION_ALGORITHM		 341
+#define SSL_R_INVALID_PURPOSE				 278
+#define SSL_R_INVALID_STATUS_RESPONSE			 328
+#define SSL_R_INVALID_TICKET_KEYS_LENGTH		 325
+#define SSL_R_INVALID_TRUST				 279
+#define SSL_R_KEY_ARG_TOO_LONG				 284
+#define SSL_R_KRB5					 285
+#define SSL_R_KRB5_C_CC_PRINC				 286
+#define SSL_R_KRB5_C_GET_CRED				 287
+#define SSL_R_KRB5_C_INIT				 288
+#define SSL_R_KRB5_C_MK_REQ				 289
+#define SSL_R_KRB5_S_BAD_TICKET				 290
+#define SSL_R_KRB5_S_INIT				 291
+#define SSL_R_KRB5_S_RD_REQ				 292
+#define SSL_R_KRB5_S_TKT_EXPIRED			 293
+#define SSL_R_KRB5_S_TKT_NYV				 294
+#define SSL_R_KRB5_S_TKT_SKEW				 295
+#define SSL_R_LENGTH_MISMATCH				 159
+#define SSL_R_LENGTH_TOO_SHORT				 160
+#define SSL_R_LIBRARY_BUG				 274
+#define SSL_R_LIBRARY_HAS_NO_CIPHERS			 161
+#define SSL_R_MESSAGE_TOO_LONG				 296
+#define SSL_R_MISSING_DH_DSA_CERT			 162
+#define SSL_R_MISSING_DH_KEY				 163
+#define SSL_R_MISSING_DH_RSA_CERT			 164
+#define SSL_R_MISSING_DSA_SIGNING_CERT			 165
+#define SSL_R_MISSING_EXPORT_TMP_DH_KEY			 166
+#define SSL_R_MISSING_EXPORT_TMP_RSA_KEY		 167
+#define SSL_R_MISSING_RSA_CERTIFICATE			 168
+#define SSL_R_MISSING_RSA_ENCRYPTING_CERT		 169
+#define SSL_R_MISSING_RSA_SIGNING_CERT			 170
+#define SSL_R_MISSING_TMP_DH_KEY			 171
+#define SSL_R_MISSING_TMP_ECDH_KEY			 311
+#define SSL_R_MISSING_TMP_RSA_KEY			 172
+#define SSL_R_MISSING_TMP_RSA_PKEY			 173
+#define SSL_R_MISSING_VERIFY_MESSAGE			 174
+#define SSL_R_NON_SSLV2_INITIAL_PACKET			 175
+#define SSL_R_NO_CERTIFICATES_RETURNED			 176
+#define SSL_R_NO_CERTIFICATE_ASSIGNED			 177
+#define SSL_R_NO_CERTIFICATE_RETURNED			 178
+#define SSL_R_NO_CERTIFICATE_SET			 179
+#define SSL_R_NO_CERTIFICATE_SPECIFIED			 180
+#define SSL_R_NO_CIPHERS_AVAILABLE			 181
+#define SSL_R_NO_CIPHERS_PASSED				 182
+#define SSL_R_NO_CIPHERS_SPECIFIED			 183
+#define SSL_R_NO_CIPHER_LIST				 184
+#define SSL_R_NO_CIPHER_MATCH				 185
+#define SSL_R_NO_CLIENT_CERT_METHOD			 331
+#define SSL_R_NO_CLIENT_CERT_RECEIVED			 186
+#define SSL_R_NO_COMPRESSION_SPECIFIED			 187
+#define SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER		 330
+#define SSL_R_NO_METHOD_SPECIFIED			 188
+#define SSL_R_NO_PRIVATEKEY				 189
+#define SSL_R_NO_PRIVATE_KEY_ASSIGNED			 190
+#define SSL_R_NO_PROTOCOLS_AVAILABLE			 191
+#define SSL_R_NO_PUBLICKEY				 192
+#define SSL_R_NO_RENEGOTIATION				 339
+#define SSL_R_NO_REQUIRED_DIGEST			 324
+#define SSL_R_NO_SHARED_CIPHER				 193
+#define SSL_R_NO_VERIFY_CALLBACK			 194
+#define SSL_R_NULL_SSL_CTX				 195
+#define SSL_R_NULL_SSL_METHOD_PASSED			 196
+#define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED		 197
+#define SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED 344
+#define SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE		 297
+#define SSL_R_OPAQUE_PRF_INPUT_TOO_LONG			 327
+#define SSL_R_PACKET_LENGTH_TOO_LONG			 198
+#define SSL_R_PARSE_TLSEXT				 227
+#define SSL_R_PATH_TOO_LONG				 270
+#define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE		 199
+#define SSL_R_PEER_ERROR				 200
+#define SSL_R_PEER_ERROR_CERTIFICATE			 201
+#define SSL_R_PEER_ERROR_NO_CERTIFICATE			 202
+#define SSL_R_PEER_ERROR_NO_CIPHER			 203
+#define SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE	 204
+#define SSL_R_PRE_MAC_LENGTH_TOO_LONG			 205
+#define SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS		 206
+#define SSL_R_PROTOCOL_IS_SHUTDOWN			 207
+#define SSL_R_PSK_IDENTITY_NOT_FOUND			 223
+#define SSL_R_PSK_NO_CLIENT_CB				 224
+#define SSL_R_PSK_NO_SERVER_CB				 225
+#define SSL_R_PUBLIC_KEY_ENCRYPT_ERROR			 208
+#define SSL_R_PUBLIC_KEY_IS_NOT_RSA			 209
+#define SSL_R_PUBLIC_KEY_NOT_RSA			 210
+#define SSL_R_READ_BIO_NOT_SET				 211
+#define SSL_R_READ_TIMEOUT_EXPIRED			 312
+#define SSL_R_READ_WRONG_PACKET_TYPE			 212
+#define SSL_R_RECORD_LENGTH_MISMATCH			 213
+#define SSL_R_RECORD_TOO_LARGE				 214
+#define SSL_R_RECORD_TOO_SMALL				 298
+#define SSL_R_RENEGOTIATE_EXT_TOO_LONG			 335
+#define SSL_R_RENEGOTIATION_ENCODING_ERR		 336
+#define SSL_R_RENEGOTIATION_MISMATCH			 337
+#define SSL_R_REQUIRED_CIPHER_MISSING			 215
+#define SSL_R_REQUIRED_COMPRESSSION_ALGORITHM_MISSING	 342
+#define SSL_R_REUSE_CERT_LENGTH_NOT_ZERO		 216
+#define SSL_R_REUSE_CERT_TYPE_NOT_ZERO			 217
+#define SSL_R_REUSE_CIPHER_LIST_NOT_ZERO		 218
+#define SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING		 345
+#define SSL_R_SERVERHELLO_TLSEXT			 275
+#define SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED		 277
+#define SSL_R_SESSION_MAY_NOT_BE_CREATED		 2000
+#define SSL_R_SHORT_READ				 219
+#define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE	 220
+#define SSL_R_SSL23_DOING_SESSION_ID_REUSE		 221
+#define SSL_R_SSL2_CONNECTION_ID_TOO_LONG		 299
+#define SSL_R_SSL3_EXT_INVALID_ECPOINTFORMAT		 321
+#define SSL_R_SSL3_EXT_INVALID_SERVERNAME		 319
+#define SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE		 320
+#define SSL_R_SSL3_SESSION_ID_TOO_LONG			 300
+#define SSL_R_SSL3_SESSION_ID_TOO_SHORT			 222
+#define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE		 1042
+#define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC		 1020
+#define SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED		 1045
+#define SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED		 1044
+#define SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN		 1046
+#define SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE		 1030
+#define SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE		 1040
+#define SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER		 1047
+#define SSL_R_SSLV3_ALERT_NO_CERTIFICATE		 1041
+#define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE		 1010
+#define SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE	 1043
+#define SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION	 228
+#define SSL_R_SSL_HANDSHAKE_FAILURE			 229
+#define SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS		 230
+#define SSL_R_SSL_SESSION_ID_CALLBACK_FAILED		 301
+#define SSL_R_SSL_SESSION_ID_CONFLICT			 302
+#define SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG		 273
+#define SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH		 303
+#define SSL_R_SSL_SESSION_ID_IS_DIFFERENT		 231
+#define SSL_R_TLSV1_ALERT_ACCESS_DENIED			 1049
+#define SSL_R_TLSV1_ALERT_DECODE_ERROR			 1050
+#define SSL_R_TLSV1_ALERT_DECRYPTION_FAILED		 1021
+#define SSL_R_TLSV1_ALERT_DECRYPT_ERROR			 1051
+#define SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION		 1060
+#define SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY		 1071
+#define SSL_R_TLSV1_ALERT_INTERNAL_ERROR		 1080
+#define SSL_R_TLSV1_ALERT_NO_RENEGOTIATION		 1100
+#define SSL_R_TLSV1_ALERT_PROTOCOL_VERSION		 1070
+#define SSL_R_TLSV1_ALERT_RECORD_OVERFLOW		 1022
+#define SSL_R_TLSV1_ALERT_UNKNOWN_CA			 1048
+#define SSL_R_TLSV1_ALERT_USER_CANCELLED		 1090
+#define SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE		 1114
+#define SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE	 1113
+#define SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE		 1111
+#define SSL_R_TLSV1_UNRECOGNIZED_NAME			 1112
+#define SSL_R_TLSV1_UNSUPPORTED_EXTENSION		 1110
+#define SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER	 232
+#define SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST		 157
+#define SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST 233
+#define SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG	 234
+#define SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER		 235
+#define SSL_R_UNABLE_TO_DECODE_DH_CERTS			 236
+#define SSL_R_UNABLE_TO_DECODE_ECDH_CERTS		 313
+#define SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY		 237
+#define SSL_R_UNABLE_TO_FIND_DH_PARAMETERS		 238
+#define SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS		 314
+#define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS	 239
+#define SSL_R_UNABLE_TO_FIND_SSL_METHOD			 240
+#define SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES		 241
+#define SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES		 242
+#define SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES		 243
+#define SSL_R_UNEXPECTED_MESSAGE			 244
+#define SSL_R_UNEXPECTED_RECORD				 245
+#define SSL_R_UNINITIALIZED				 276
+#define SSL_R_UNKNOWN_ALERT_TYPE			 246
+#define SSL_R_UNKNOWN_CERTIFICATE_TYPE			 247
+#define SSL_R_UNKNOWN_CIPHER_RETURNED			 248
+#define SSL_R_UNKNOWN_CIPHER_TYPE			 249
+#define SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE			 250
+#define SSL_R_UNKNOWN_PKEY_TYPE				 251
+#define SSL_R_UNKNOWN_PROTOCOL				 252
+#define SSL_R_UNKNOWN_REMOTE_ERROR_TYPE			 253
+#define SSL_R_UNKNOWN_SSL_VERSION			 254
+#define SSL_R_UNKNOWN_STATE				 255
+#define SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED	 338
+#define SSL_R_UNSUPPORTED_CIPHER			 256
+#define SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM		 257
+#define SSL_R_UNSUPPORTED_DIGEST_TYPE			 326
+#define SSL_R_UNSUPPORTED_ELLIPTIC_CURVE		 315
+#define SSL_R_UNSUPPORTED_PROTOCOL			 258
+#define SSL_R_UNSUPPORTED_SSL_VERSION			 259
+#define SSL_R_UNSUPPORTED_STATUS_TYPE			 329
+#define SSL_R_WRITE_BIO_NOT_SET				 260
+#define SSL_R_WRONG_CIPHER_RETURNED			 261
+#define SSL_R_WRONG_MESSAGE_TYPE			 262
+#define SSL_R_WRONG_NUMBER_OF_KEY_BITS			 263
+#define SSL_R_WRONG_SIGNATURE_LENGTH			 264
+#define SSL_R_WRONG_SIGNATURE_SIZE			 265
+#define SSL_R_WRONG_SSL_VERSION				 266
+#define SSL_R_WRONG_VERSION_NUMBER			 267
+#define SSL_R_X509_LIB					 268
+#define SSL_R_X509_VERIFICATION_SETUP_PROBLEMS		 269
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/lib/openssl/ssl/ssl2.h b/lib/openssl/ssl/ssl2.h
new file mode 100644
index 0000000..99a52ea
--- /dev/null
+++ b/lib/openssl/ssl/ssl2.h
@@ -0,0 +1,268 @@
+/* ssl/ssl2.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_SSL2_H 
+#define HEADER_SSL2_H 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* Protocol Version Codes */
+#define SSL2_VERSION		0x0002
+#define SSL2_VERSION_MAJOR	0x00
+#define SSL2_VERSION_MINOR	0x02
+/* #define SSL2_CLIENT_VERSION	0x0002 */
+/* #define SSL2_SERVER_VERSION	0x0002 */
+
+/* Protocol Message Codes */
+#define SSL2_MT_ERROR			0
+#define SSL2_MT_CLIENT_HELLO		1
+#define SSL2_MT_CLIENT_MASTER_KEY	2
+#define SSL2_MT_CLIENT_FINISHED		3
+#define SSL2_MT_SERVER_HELLO		4
+#define SSL2_MT_SERVER_VERIFY		5
+#define SSL2_MT_SERVER_FINISHED		6
+#define SSL2_MT_REQUEST_CERTIFICATE	7
+#define SSL2_MT_CLIENT_CERTIFICATE	8
+
+/* Error Message Codes */
+#define SSL2_PE_UNDEFINED_ERROR		0x0000
+#define SSL2_PE_NO_CIPHER		0x0001
+#define SSL2_PE_NO_CERTIFICATE		0x0002
+#define SSL2_PE_BAD_CERTIFICATE		0x0004
+#define SSL2_PE_UNSUPPORTED_CERTIFICATE_TYPE 0x0006
+
+/* Cipher Kind Values */
+#define SSL2_CK_NULL_WITH_MD5			0x02000000 /* v3 */
+#define SSL2_CK_RC4_128_WITH_MD5		0x02010080
+#define SSL2_CK_RC4_128_EXPORT40_WITH_MD5	0x02020080
+#define SSL2_CK_RC2_128_CBC_WITH_MD5		0x02030080
+#define SSL2_CK_RC2_128_CBC_EXPORT40_WITH_MD5	0x02040080
+#define SSL2_CK_IDEA_128_CBC_WITH_MD5		0x02050080
+#define SSL2_CK_DES_64_CBC_WITH_MD5		0x02060040
+#define SSL2_CK_DES_64_CBC_WITH_SHA		0x02060140 /* v3 */
+#define SSL2_CK_DES_192_EDE3_CBC_WITH_MD5	0x020700c0
+#define SSL2_CK_DES_192_EDE3_CBC_WITH_SHA	0x020701c0 /* v3 */
+#define SSL2_CK_RC4_64_WITH_MD5			0x02080080 /* MS hack */
+ 
+#define SSL2_CK_DES_64_CFB64_WITH_MD5_1		0x02ff0800 /* SSLeay */
+#define SSL2_CK_NULL				0x02ff0810 /* SSLeay */
+
+#define SSL2_TXT_DES_64_CFB64_WITH_MD5_1	"DES-CFB-M1"
+#define SSL2_TXT_NULL_WITH_MD5			"NULL-MD5"
+#define SSL2_TXT_RC4_128_WITH_MD5		"RC4-MD5"
+#define SSL2_TXT_RC4_128_EXPORT40_WITH_MD5	"EXP-RC4-MD5"
+#define SSL2_TXT_RC2_128_CBC_WITH_MD5		"RC2-CBC-MD5"
+#define SSL2_TXT_RC2_128_CBC_EXPORT40_WITH_MD5	"EXP-RC2-CBC-MD5"
+#define SSL2_TXT_IDEA_128_CBC_WITH_MD5		"IDEA-CBC-MD5"
+#define SSL2_TXT_DES_64_CBC_WITH_MD5		"DES-CBC-MD5"
+#define SSL2_TXT_DES_64_CBC_WITH_SHA		"DES-CBC-SHA"
+#define SSL2_TXT_DES_192_EDE3_CBC_WITH_MD5	"DES-CBC3-MD5"
+#define SSL2_TXT_DES_192_EDE3_CBC_WITH_SHA	"DES-CBC3-SHA"
+#define SSL2_TXT_RC4_64_WITH_MD5		"RC4-64-MD5"
+
+#define SSL2_TXT_NULL				"NULL"
+
+/* Flags for the SSL_CIPHER.algorithm2 field */
+#define SSL2_CF_5_BYTE_ENC			0x01
+#define SSL2_CF_8_BYTE_ENC			0x02
+
+/* Certificate Type Codes */
+#define SSL2_CT_X509_CERTIFICATE		0x01
+
+/* Authentication Type Code */
+#define SSL2_AT_MD5_WITH_RSA_ENCRYPTION		0x01
+
+#define SSL2_MAX_SSL_SESSION_ID_LENGTH		32
+
+/* Upper/Lower Bounds */
+#define SSL2_MAX_MASTER_KEY_LENGTH_IN_BITS	256
+#ifdef OPENSSL_SYS_MPE
+#define SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER	29998u
+#else
+#define SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER	32767u  /* 2^15-1 */
+#endif
+#define SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER	16383 /* 2^14-1 */
+
+#define SSL2_CHALLENGE_LENGTH	16
+/*#define SSL2_CHALLENGE_LENGTH	32 */
+#define SSL2_MIN_CHALLENGE_LENGTH	16
+#define SSL2_MAX_CHALLENGE_LENGTH	32
+#define SSL2_CONNECTION_ID_LENGTH	16
+#define SSL2_MAX_CONNECTION_ID_LENGTH	16
+#define SSL2_SSL_SESSION_ID_LENGTH	16
+#define SSL2_MAX_CERT_CHALLENGE_LENGTH	32
+#define SSL2_MIN_CERT_CHALLENGE_LENGTH	16
+#define SSL2_MAX_KEY_MATERIAL_LENGTH	24
+
+#ifndef HEADER_SSL_LOCL_H
+#define  CERT		char
+#endif
+
+typedef struct ssl2_state_st
+	{
+	int three_byte_header;
+	int clear_text;		/* clear text */
+	int escape;		/* not used in SSLv2 */
+	int ssl2_rollback;	/* used if SSLv23 rolled back to SSLv2 */
+
+	/* non-blocking io info, used to make sure the same
+	 * args were passwd */
+	unsigned int wnum;	/* number of bytes sent so far */
+	int wpend_tot;
+	const unsigned char *wpend_buf;
+
+	int wpend_off;	/* offset to data to write */
+	int wpend_len; 	/* number of bytes passwd to write */
+	int wpend_ret; 	/* number of bytes to return to caller */
+
+	/* buffer raw data */
+	int rbuf_left;
+	int rbuf_offs;
+	unsigned char *rbuf;
+	unsigned char *wbuf;
+
+	unsigned char *write_ptr;/* used to point to the start due to
+				  * 2/3 byte header. */
+
+	unsigned int padding;
+	unsigned int rlength; /* passed to ssl2_enc */
+	int ract_data_length; /* Set when things are encrypted. */
+	unsigned int wlength; /* passed to ssl2_enc */
+	int wact_data_length; /* Set when things are decrypted. */
+	unsigned char *ract_data;
+	unsigned char *wact_data;
+	unsigned char *mac_data;
+
+	unsigned char *read_key;
+	unsigned char *write_key;
+
+		/* Stuff specifically to do with this SSL session */
+	unsigned int challenge_length;
+	unsigned char challenge[SSL2_MAX_CHALLENGE_LENGTH];
+	unsigned int conn_id_length;
+	unsigned char conn_id[SSL2_MAX_CONNECTION_ID_LENGTH];
+	unsigned int key_material_length;
+	unsigned char key_material[SSL2_MAX_KEY_MATERIAL_LENGTH*2];
+
+	unsigned long read_sequence;
+	unsigned long write_sequence;
+
+	struct	{
+		unsigned int conn_id_length;
+		unsigned int cert_type;	
+		unsigned int cert_length;
+		unsigned int csl; 
+		unsigned int clear;
+		unsigned int enc; 
+		unsigned char ccl[SSL2_MAX_CERT_CHALLENGE_LENGTH];
+		unsigned int cipher_spec_length;
+		unsigned int session_id_length;
+		unsigned int clen;
+		unsigned int rlen;
+		} tmp;
+	} SSL2_STATE;
+
+/* SSLv2 */
+/* client */
+#define SSL2_ST_SEND_CLIENT_HELLO_A		(0x10|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_HELLO_B		(0x11|SSL_ST_CONNECT)
+#define SSL2_ST_GET_SERVER_HELLO_A		(0x20|SSL_ST_CONNECT)
+#define SSL2_ST_GET_SERVER_HELLO_B		(0x21|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_MASTER_KEY_A	(0x30|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_MASTER_KEY_B	(0x31|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_FINISHED_A		(0x40|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_FINISHED_B		(0x41|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_CERTIFICATE_A	(0x50|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_CERTIFICATE_B	(0x51|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_CERTIFICATE_C	(0x52|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_CERTIFICATE_D	(0x53|SSL_ST_CONNECT)
+#define SSL2_ST_GET_SERVER_VERIFY_A		(0x60|SSL_ST_CONNECT)
+#define SSL2_ST_GET_SERVER_VERIFY_B		(0x61|SSL_ST_CONNECT)
+#define SSL2_ST_GET_SERVER_FINISHED_A		(0x70|SSL_ST_CONNECT)
+#define SSL2_ST_GET_SERVER_FINISHED_B		(0x71|SSL_ST_CONNECT)
+#define SSL2_ST_CLIENT_START_ENCRYPTION		(0x80|SSL_ST_CONNECT)
+#define SSL2_ST_X509_GET_CLIENT_CERTIFICATE	(0x90|SSL_ST_CONNECT)
+/* server */
+#define SSL2_ST_GET_CLIENT_HELLO_A		(0x10|SSL_ST_ACCEPT)
+#define SSL2_ST_GET_CLIENT_HELLO_B		(0x11|SSL_ST_ACCEPT)
+#define SSL2_ST_GET_CLIENT_HELLO_C		(0x12|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_HELLO_A		(0x20|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_HELLO_B		(0x21|SSL_ST_ACCEPT)
+#define SSL2_ST_GET_CLIENT_MASTER_KEY_A		(0x30|SSL_ST_ACCEPT)
+#define SSL2_ST_GET_CLIENT_MASTER_KEY_B		(0x31|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_VERIFY_A		(0x40|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_VERIFY_B		(0x41|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_VERIFY_C		(0x42|SSL_ST_ACCEPT)
+#define SSL2_ST_GET_CLIENT_FINISHED_A		(0x50|SSL_ST_ACCEPT)
+#define SSL2_ST_GET_CLIENT_FINISHED_B		(0x51|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_FINISHED_A		(0x60|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_FINISHED_B		(0x61|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_REQUEST_CERTIFICATE_A	(0x70|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_REQUEST_CERTIFICATE_B	(0x71|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_REQUEST_CERTIFICATE_C	(0x72|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_REQUEST_CERTIFICATE_D	(0x73|SSL_ST_ACCEPT)
+#define SSL2_ST_SERVER_START_ENCRYPTION		(0x80|SSL_ST_ACCEPT)
+#define SSL2_ST_X509_GET_SERVER_CERTIFICATE	(0x90|SSL_ST_ACCEPT)
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
+
diff --git a/lib/openssl/ssl/ssl23.h b/lib/openssl/ssl/ssl23.h
new file mode 100644
index 0000000..d322898
--- /dev/null
+++ b/lib/openssl/ssl/ssl23.h
@@ -0,0 +1,83 @@
+/* ssl/ssl23.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_SSL23_H 
+#define HEADER_SSL23_H 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/*client */
+/* write to server */
+#define SSL23_ST_CW_CLNT_HELLO_A	(0x210|SSL_ST_CONNECT)
+#define SSL23_ST_CW_CLNT_HELLO_B	(0x211|SSL_ST_CONNECT)
+/* read from server */
+#define SSL23_ST_CR_SRVR_HELLO_A	(0x220|SSL_ST_CONNECT)
+#define SSL23_ST_CR_SRVR_HELLO_B	(0x221|SSL_ST_CONNECT)
+
+/* server */
+/* read from client */
+#define SSL23_ST_SR_CLNT_HELLO_A	(0x210|SSL_ST_ACCEPT)
+#define SSL23_ST_SR_CLNT_HELLO_B	(0x211|SSL_ST_ACCEPT)
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
+
diff --git a/lib/openssl/ssl/ssl3.h b/lib/openssl/ssl/ssl3.h
new file mode 100644
index 0000000..0633950
--- /dev/null
+++ b/lib/openssl/ssl/ssl3.h
@@ -0,0 +1,647 @@
+/* ssl/ssl3.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECC cipher suite support in OpenSSL originally developed by 
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#ifndef HEADER_SSL3_H 
+#define HEADER_SSL3_H 
+
+#ifndef OPENSSL_NO_COMP
+#include <openssl/comp.h>
+#endif
+#include <openssl/buffer.h>
+#include <openssl/evp.h>
+#include <openssl/ssl.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* Signalling cipher suite value: from draft-ietf-tls-renegotiation-03.txt */
+#define SSL3_CK_SCSV				0x030000FF
+
+#define SSL3_CK_RSA_NULL_MD5			0x03000001
+#define SSL3_CK_RSA_NULL_SHA			0x03000002
+#define SSL3_CK_RSA_RC4_40_MD5 			0x03000003
+#define SSL3_CK_RSA_RC4_128_MD5			0x03000004
+#define SSL3_CK_RSA_RC4_128_SHA			0x03000005
+#define SSL3_CK_RSA_RC2_40_MD5			0x03000006
+#define SSL3_CK_RSA_IDEA_128_SHA		0x03000007
+#define SSL3_CK_RSA_DES_40_CBC_SHA		0x03000008
+#define SSL3_CK_RSA_DES_64_CBC_SHA		0x03000009
+#define SSL3_CK_RSA_DES_192_CBC3_SHA		0x0300000A
+
+#define SSL3_CK_DH_DSS_DES_40_CBC_SHA		0x0300000B
+#define SSL3_CK_DH_DSS_DES_64_CBC_SHA		0x0300000C
+#define SSL3_CK_DH_DSS_DES_192_CBC3_SHA 	0x0300000D
+#define SSL3_CK_DH_RSA_DES_40_CBC_SHA		0x0300000E
+#define SSL3_CK_DH_RSA_DES_64_CBC_SHA		0x0300000F
+#define SSL3_CK_DH_RSA_DES_192_CBC3_SHA 	0x03000010
+
+#define SSL3_CK_EDH_DSS_DES_40_CBC_SHA		0x03000011
+#define SSL3_CK_EDH_DSS_DES_64_CBC_SHA		0x03000012
+#define SSL3_CK_EDH_DSS_DES_192_CBC3_SHA	0x03000013
+#define SSL3_CK_EDH_RSA_DES_40_CBC_SHA		0x03000014
+#define SSL3_CK_EDH_RSA_DES_64_CBC_SHA		0x03000015
+#define SSL3_CK_EDH_RSA_DES_192_CBC3_SHA	0x03000016
+
+#define SSL3_CK_ADH_RC4_40_MD5			0x03000017
+#define SSL3_CK_ADH_RC4_128_MD5			0x03000018
+#define SSL3_CK_ADH_DES_40_CBC_SHA		0x03000019
+#define SSL3_CK_ADH_DES_64_CBC_SHA		0x0300001A
+#define SSL3_CK_ADH_DES_192_CBC_SHA		0x0300001B
+
+#if 0
+	#define SSL3_CK_FZA_DMS_NULL_SHA		0x0300001C
+	#define SSL3_CK_FZA_DMS_FZA_SHA			0x0300001D
+	#if 0 /* Because it clashes with KRB5, is never used any more, and is safe
+		 to remove according to David Hopwood <david.hopwood@zetnet.co.uk>
+		 of the ietf-tls list */
+	#define SSL3_CK_FZA_DMS_RC4_SHA			0x0300001E
+	#endif
+#endif
+
+/*    VRS Additional Kerberos5 entries
+ */
+#define SSL3_CK_KRB5_DES_64_CBC_SHA		0x0300001E
+#define SSL3_CK_KRB5_DES_192_CBC3_SHA		0x0300001F
+#define SSL3_CK_KRB5_RC4_128_SHA		0x03000020
+#define SSL3_CK_KRB5_IDEA_128_CBC_SHA	       	0x03000021
+#define SSL3_CK_KRB5_DES_64_CBC_MD5       	0x03000022
+#define SSL3_CK_KRB5_DES_192_CBC3_MD5       	0x03000023
+#define SSL3_CK_KRB5_RC4_128_MD5	       	0x03000024
+#define SSL3_CK_KRB5_IDEA_128_CBC_MD5 		0x03000025
+
+#define SSL3_CK_KRB5_DES_40_CBC_SHA 		0x03000026
+#define SSL3_CK_KRB5_RC2_40_CBC_SHA 		0x03000027
+#define SSL3_CK_KRB5_RC4_40_SHA	 		0x03000028
+#define SSL3_CK_KRB5_DES_40_CBC_MD5 		0x03000029
+#define SSL3_CK_KRB5_RC2_40_CBC_MD5 		0x0300002A
+#define SSL3_CK_KRB5_RC4_40_MD5	 		0x0300002B
+
+#define SSL3_TXT_RSA_NULL_MD5			"NULL-MD5"
+#define SSL3_TXT_RSA_NULL_SHA			"NULL-SHA"
+#define SSL3_TXT_RSA_RC4_40_MD5 		"EXP-RC4-MD5"
+#define SSL3_TXT_RSA_RC4_128_MD5		"RC4-MD5"
+#define SSL3_TXT_RSA_RC4_128_SHA		"RC4-SHA"
+#define SSL3_TXT_RSA_RC2_40_MD5			"EXP-RC2-CBC-MD5"
+#define SSL3_TXT_RSA_IDEA_128_SHA		"IDEA-CBC-SHA"
+#define SSL3_TXT_RSA_DES_40_CBC_SHA		"EXP-DES-CBC-SHA"
+#define SSL3_TXT_RSA_DES_64_CBC_SHA		"DES-CBC-SHA"
+#define SSL3_TXT_RSA_DES_192_CBC3_SHA		"DES-CBC3-SHA"
+
+#define SSL3_TXT_DH_DSS_DES_40_CBC_SHA		"EXP-DH-DSS-DES-CBC-SHA"
+#define SSL3_TXT_DH_DSS_DES_64_CBC_SHA		"DH-DSS-DES-CBC-SHA"
+#define SSL3_TXT_DH_DSS_DES_192_CBC3_SHA 	"DH-DSS-DES-CBC3-SHA"
+#define SSL3_TXT_DH_RSA_DES_40_CBC_SHA		"EXP-DH-RSA-DES-CBC-SHA"
+#define SSL3_TXT_DH_RSA_DES_64_CBC_SHA		"DH-RSA-DES-CBC-SHA"
+#define SSL3_TXT_DH_RSA_DES_192_CBC3_SHA 	"DH-RSA-DES-CBC3-SHA"
+
+#define SSL3_TXT_EDH_DSS_DES_40_CBC_SHA		"EXP-EDH-DSS-DES-CBC-SHA"
+#define SSL3_TXT_EDH_DSS_DES_64_CBC_SHA		"EDH-DSS-DES-CBC-SHA"
+#define SSL3_TXT_EDH_DSS_DES_192_CBC3_SHA	"EDH-DSS-DES-CBC3-SHA"
+#define SSL3_TXT_EDH_RSA_DES_40_CBC_SHA		"EXP-EDH-RSA-DES-CBC-SHA"
+#define SSL3_TXT_EDH_RSA_DES_64_CBC_SHA		"EDH-RSA-DES-CBC-SHA"
+#define SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA	"EDH-RSA-DES-CBC3-SHA"
+
+#define SSL3_TXT_ADH_RC4_40_MD5			"EXP-ADH-RC4-MD5"
+#define SSL3_TXT_ADH_RC4_128_MD5		"ADH-RC4-MD5"
+#define SSL3_TXT_ADH_DES_40_CBC_SHA		"EXP-ADH-DES-CBC-SHA"
+#define SSL3_TXT_ADH_DES_64_CBC_SHA		"ADH-DES-CBC-SHA"
+#define SSL3_TXT_ADH_DES_192_CBC_SHA		"ADH-DES-CBC3-SHA"
+
+#if 0
+	#define SSL3_TXT_FZA_DMS_NULL_SHA		"FZA-NULL-SHA"
+	#define SSL3_TXT_FZA_DMS_FZA_SHA		"FZA-FZA-CBC-SHA"
+	#define SSL3_TXT_FZA_DMS_RC4_SHA		"FZA-RC4-SHA"
+#endif
+
+#define SSL3_TXT_KRB5_DES_64_CBC_SHA		"KRB5-DES-CBC-SHA"
+#define SSL3_TXT_KRB5_DES_192_CBC3_SHA		"KRB5-DES-CBC3-SHA"
+#define SSL3_TXT_KRB5_RC4_128_SHA		"KRB5-RC4-SHA"
+#define SSL3_TXT_KRB5_IDEA_128_CBC_SHA	       	"KRB5-IDEA-CBC-SHA"
+#define SSL3_TXT_KRB5_DES_64_CBC_MD5       	"KRB5-DES-CBC-MD5"
+#define SSL3_TXT_KRB5_DES_192_CBC3_MD5       	"KRB5-DES-CBC3-MD5"
+#define SSL3_TXT_KRB5_RC4_128_MD5		"KRB5-RC4-MD5"
+#define SSL3_TXT_KRB5_IDEA_128_CBC_MD5 		"KRB5-IDEA-CBC-MD5"
+
+#define SSL3_TXT_KRB5_DES_40_CBC_SHA 		"EXP-KRB5-DES-CBC-SHA"
+#define SSL3_TXT_KRB5_RC2_40_CBC_SHA 		"EXP-KRB5-RC2-CBC-SHA"
+#define SSL3_TXT_KRB5_RC4_40_SHA	 	"EXP-KRB5-RC4-SHA"
+#define SSL3_TXT_KRB5_DES_40_CBC_MD5 		"EXP-KRB5-DES-CBC-MD5"
+#define SSL3_TXT_KRB5_RC2_40_CBC_MD5 		"EXP-KRB5-RC2-CBC-MD5"
+#define SSL3_TXT_KRB5_RC4_40_MD5	 	"EXP-KRB5-RC4-MD5"
+
+#define SSL3_SSL_SESSION_ID_LENGTH		32
+#define SSL3_MAX_SSL_SESSION_ID_LENGTH		32
+
+#define SSL3_MASTER_SECRET_SIZE			48
+#define SSL3_RANDOM_SIZE			32
+#define SSL3_SESSION_ID_SIZE			32
+#define SSL3_RT_HEADER_LENGTH			5
+
+#ifndef SSL3_ALIGN_PAYLOAD
+ /* Some will argue that this increases memory footprint, but it's
+  * not actually true. Point is that malloc has to return at least
+  * 64-bit aligned pointers, meaning that allocating 5 bytes wastes
+  * 3 bytes in either case. Suggested pre-gaping simply moves these
+  * wasted bytes from the end of allocated region to its front,
+  * but makes data payload aligned, which improves performance:-) */
+# define SSL3_ALIGN_PAYLOAD			8
+#else
+# if (SSL3_ALIGN_PAYLOAD&(SSL3_ALIGN_PAYLOAD-1))!=0
+#  error "insane SSL3_ALIGN_PAYLOAD"
+#  undef SSL3_ALIGN_PAYLOAD
+# endif
+#endif
+
+/* This is the maximum MAC (digest) size used by the SSL library.
+ * Currently maximum of 20 is used by SHA1, but we reserve for
+ * future extension for 512-bit hashes.
+ */
+
+#define SSL3_RT_MAX_MD_SIZE			64
+
+/* Maximum block size used in all ciphersuites. Currently 16 for AES.
+ */
+
+#define	SSL_RT_MAX_CIPHER_BLOCK_SIZE		16
+
+#define SSL3_RT_MAX_EXTRA			(16384)
+
+/* Default buffer length used for writen records.  Thus a generated record
+ * will contain plaintext no larger than this value. */
+#define SSL3_RT_DEFAULT_PLAIN_LENGTH	2048
+/* Maximum plaintext length: defined by SSL/TLS standards */
+#define SSL3_RT_MAX_PLAIN_LENGTH		16384
+/* Maximum compression overhead: defined by SSL/TLS standards */
+#define SSL3_RT_MAX_COMPRESSED_OVERHEAD		1024
+
+/* The standards give a maximum encryption overhead of 1024 bytes.
+ * In practice the value is lower than this. The overhead is the maximum
+ * number of padding bytes (256) plus the mac size.
+ */
+#define SSL3_RT_MAX_ENCRYPTED_OVERHEAD	(256 + SSL3_RT_MAX_MD_SIZE)
+
+/* OpenSSL currently only uses a padding length of at most one block so
+ * the send overhead is smaller.
+ */
+
+#define SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD \
+			(SSL_RT_MAX_CIPHER_BLOCK_SIZE + SSL3_RT_MAX_MD_SIZE)
+
+/* If compression isn't used don't include the compression overhead */
+
+#ifdef OPENSSL_NO_COMP
+#define SSL3_RT_MAX_COMPRESSED_LENGTH		SSL3_RT_MAX_PLAIN_LENGTH
+#else
+#define SSL3_RT_MAX_COMPRESSED_LENGTH	\
+		(SSL3_RT_MAX_PLAIN_LENGTH+SSL3_RT_MAX_COMPRESSED_OVERHEAD)
+#endif
+#define SSL3_RT_MAX_ENCRYPTED_LENGTH	\
+		(SSL3_RT_MAX_ENCRYPTED_OVERHEAD+SSL3_RT_MAX_COMPRESSED_LENGTH)
+#define SSL3_RT_MAX_PACKET_SIZE		\
+		(SSL3_RT_MAX_ENCRYPTED_LENGTH+SSL3_RT_HEADER_LENGTH)
+
+/* Extra space for empty fragment, headers, MAC, and padding. */
+#define SSL3_RT_DEFAULT_WRITE_OVERHEAD  256
+#define SSL3_RT_DEFAULT_PACKET_SIZE     4096 - SSL3_RT_DEFAULT_WRITE_OVERHEAD
+#if SSL3_RT_DEFAULT_PLAIN_LENGTH + SSL3_RT_DEFAULT_WRITE_OVERHEAD > SSL3_RT_DEFAULT_PACKET_SIZE
+#error "Insufficient space allocated for write buffers."
+#endif
+
+#define SSL3_MD_CLIENT_FINISHED_CONST	"\x43\x4C\x4E\x54"
+#define SSL3_MD_SERVER_FINISHED_CONST	"\x53\x52\x56\x52"
+
+#define SSL3_VERSION			0x0300
+#define SSL3_VERSION_MAJOR		0x03
+#define SSL3_VERSION_MINOR		0x00
+
+#define SSL3_RT_CHANGE_CIPHER_SPEC	20
+#define SSL3_RT_ALERT			21
+#define SSL3_RT_HANDSHAKE		22
+#define SSL3_RT_APPLICATION_DATA	23
+
+#define SSL3_AL_WARNING			1
+#define SSL3_AL_FATAL			2
+
+#define SSL3_AD_CLOSE_NOTIFY		 0
+#define SSL3_AD_UNEXPECTED_MESSAGE	10	/* fatal */
+#define SSL3_AD_BAD_RECORD_MAC		20	/* fatal */
+#define SSL3_AD_DECOMPRESSION_FAILURE	30	/* fatal */
+#define SSL3_AD_HANDSHAKE_FAILURE	40	/* fatal */
+#define SSL3_AD_NO_CERTIFICATE		41
+#define SSL3_AD_BAD_CERTIFICATE		42
+#define SSL3_AD_UNSUPPORTED_CERTIFICATE	43
+#define SSL3_AD_CERTIFICATE_REVOKED	44
+#define SSL3_AD_CERTIFICATE_EXPIRED	45
+#define SSL3_AD_CERTIFICATE_UNKNOWN	46
+#define SSL3_AD_ILLEGAL_PARAMETER	47	/* fatal */
+
+typedef struct ssl3_record_st
+	{
+/*r */	int type;               /* type of record */
+/*rw*/	unsigned int length;    /* How many bytes available */
+/*r */	unsigned int off;       /* read/write offset into 'buf' */
+/*rw*/	unsigned char *data;    /* pointer to the record data */
+/*rw*/	unsigned char *input;   /* where the decode bytes are */
+/*r */	unsigned char *comp;    /* only used with decompression - malloc()ed */
+/*r */  unsigned long epoch;    /* epoch number, needed by DTLS1 */
+/*r */  unsigned char seq_num[8]; /* sequence number, needed by DTLS1 */
+	} SSL3_RECORD;
+
+typedef struct ssl3_buffer_st
+	{
+	unsigned char *buf;     /* at least SSL3_RT_MAX_PACKET_SIZE bytes,
+	                         * see ssl3_setup_buffers() */
+	size_t len;             /* buffer size */
+	int offset;             /* where to 'copy from' */
+	int left;               /* how many bytes left */
+	} SSL3_BUFFER;
+
+#define SSL3_CT_RSA_SIGN			1
+#define SSL3_CT_DSS_SIGN			2
+#define SSL3_CT_RSA_FIXED_DH			3
+#define SSL3_CT_DSS_FIXED_DH			4
+#define SSL3_CT_RSA_EPHEMERAL_DH		5
+#define SSL3_CT_DSS_EPHEMERAL_DH		6
+#define SSL3_CT_FORTEZZA_DMS			20
+/* SSL3_CT_NUMBER is used to size arrays and it must be large
+ * enough to contain all of the cert types defined either for
+ * SSLv3 and TLSv1.
+ */
+#define SSL3_CT_NUMBER			9
+
+
+#define SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS	0x0001
+#define SSL3_FLAGS_DELAY_CLIENT_FINISHED	0x0002
+#define SSL3_FLAGS_POP_BUFFER			0x0004
+#define TLS1_FLAGS_TLS_PADDING_BUG		0x0008
+#define TLS1_FLAGS_SKIP_CERT_VERIFY		0x0010
+
+typedef struct ssl3_state_st
+	{
+	long flags;
+	int delay_buf_pop_ret;
+
+	unsigned char read_sequence[8];
+	int read_mac_secret_size;
+	unsigned char read_mac_secret[EVP_MAX_MD_SIZE];
+	unsigned char write_sequence[8];
+	int write_mac_secret_size;
+	unsigned char write_mac_secret[EVP_MAX_MD_SIZE];
+
+	unsigned char server_random[SSL3_RANDOM_SIZE];
+	unsigned char client_random[SSL3_RANDOM_SIZE];
+
+	/* flags for countermeasure against known-IV weakness */
+	int need_empty_fragments;
+	int empty_fragment_done;
+
+	/* The value of 'extra' when the buffers were initialized */
+	int init_extra;
+
+	SSL3_BUFFER rbuf;	/* read IO goes into here */
+	SSL3_BUFFER wbuf;	/* write IO goes into here */
+
+	SSL3_RECORD rrec;	/* each decoded record goes in here */
+	SSL3_RECORD wrec;	/* goes out from here */
+
+	/* storage for Alert/Handshake protocol data received but not
+	 * yet processed by ssl3_read_bytes: */
+	unsigned char alert_fragment[2];
+	unsigned int alert_fragment_len;
+	unsigned char handshake_fragment[4];
+	unsigned int handshake_fragment_len;
+
+	/* partial write - check the numbers match */
+	unsigned int wnum;	/* number of bytes sent so far */
+	int wpend_tot;		/* number bytes written */
+	int wpend_type;
+	int wpend_ret;		/* number of bytes submitted */
+	const unsigned char *wpend_buf;
+
+	/* used during startup, digest all incoming/outgoing packets */
+	BIO *handshake_buffer;
+	/* When set of handshake digests is determined, buffer is hashed
+	 * and freed and MD_CTX-es for all required digests are stored in
+	 * this array */
+	EVP_MD_CTX **handshake_dgst;
+	/* this is set whenerver we see a change_cipher_spec message
+	 * come in when we are not looking for one */
+	int change_cipher_spec;
+
+	int warn_alert;
+	int fatal_alert;
+	/* we allow one fatal and one warning alert to be outstanding,
+	 * send close alert via the warning alert */
+	int alert_dispatch;
+	unsigned char send_alert[2];
+
+	/* This flag is set when we should renegotiate ASAP, basically when
+	 * there is no more data in the read or write buffers */
+	int renegotiate;
+	int total_renegotiations;
+	int num_renegotiations;
+
+	int in_read_app_data;
+
+	/* Opaque PRF input as used for the current handshake.
+	 * These fields are used only if TLSEXT_TYPE_opaque_prf_input is defined
+	 * (otherwise, they are merely present to improve binary compatibility) */
+	void *client_opaque_prf_input;
+	size_t client_opaque_prf_input_len;
+	void *server_opaque_prf_input;
+	size_t server_opaque_prf_input_len;
+
+	struct	{
+		/* actually only needs to be 16+20 */
+		unsigned char cert_verify_md[EVP_MAX_MD_SIZE*2];
+
+		/* actually only need to be 16+20 for SSLv3 and 12 for TLS */
+		unsigned char finish_md[EVP_MAX_MD_SIZE*2];
+		int finish_md_len;
+		unsigned char peer_finish_md[EVP_MAX_MD_SIZE*2];
+		int peer_finish_md_len;
+		
+		unsigned long message_size;
+		int message_type;
+
+		/* used to hold the new cipher we are going to use */
+		const SSL_CIPHER *new_cipher;
+#ifndef OPENSSL_NO_DH
+		DH *dh;
+#endif
+
+#ifndef OPENSSL_NO_ECDH
+		EC_KEY *ecdh; /* holds short lived ECDH key */
+#endif
+
+		/* used when SSL_ST_FLUSH_DATA is entered */
+		int next_state;			
+
+		int reuse_message;
+
+		/* used for certificate requests */
+		int cert_req;
+		int ctype_num;
+		char ctype[SSL3_CT_NUMBER];
+		STACK_OF(X509_NAME) *ca_names;
+
+		int use_rsa_tmp;
+
+		int key_block_length;
+		unsigned char *key_block;
+
+		const EVP_CIPHER *new_sym_enc;
+		const EVP_MD *new_hash;
+		int new_mac_pkey_type;
+		int new_mac_secret_size;
+#ifndef OPENSSL_NO_COMP
+		const SSL_COMP *new_compression;
+#else
+		char *new_compression;
+#endif
+		int cert_request;
+		} tmp;
+
+        /* Connection binding to prevent renegotiation attacks */
+        unsigned char previous_client_finished[EVP_MAX_MD_SIZE];
+        unsigned char previous_client_finished_len;
+        unsigned char previous_server_finished[EVP_MAX_MD_SIZE];
+        unsigned char previous_server_finished_len;
+        int send_connection_binding; /* TODOEKR */
+	} SSL3_STATE;
+
+
+/* SSLv3 */
+/*client */
+/* extra state */
+#define SSL3_ST_CW_FLUSH		(0x100|SSL_ST_CONNECT)
+#define SSL3_ST_CUTTHROUGH_COMPLETE	(0x101|SSL_ST_CONNECT)
+/* write to server */
+#define SSL3_ST_CW_CLNT_HELLO_A		(0x110|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CLNT_HELLO_B		(0x111|SSL_ST_CONNECT)
+/* read from server */
+#define SSL3_ST_CR_SRVR_HELLO_A		(0x120|SSL_ST_CONNECT)
+#define SSL3_ST_CR_SRVR_HELLO_B		(0x121|SSL_ST_CONNECT)
+#define DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A (0x126|SSL_ST_CONNECT)
+#define DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B (0x127|SSL_ST_CONNECT)
+#define SSL3_ST_CR_CERT_A		(0x130|SSL_ST_CONNECT)
+#define SSL3_ST_CR_CERT_B		(0x131|SSL_ST_CONNECT)
+#define SSL3_ST_CR_KEY_EXCH_A		(0x140|SSL_ST_CONNECT)
+#define SSL3_ST_CR_KEY_EXCH_B		(0x141|SSL_ST_CONNECT)
+#define SSL3_ST_CR_CERT_REQ_A		(0x150|SSL_ST_CONNECT)
+#define SSL3_ST_CR_CERT_REQ_B		(0x151|SSL_ST_CONNECT)
+#define SSL3_ST_CR_SRVR_DONE_A		(0x160|SSL_ST_CONNECT)
+#define SSL3_ST_CR_SRVR_DONE_B		(0x161|SSL_ST_CONNECT)
+/* write to server */
+#define SSL3_ST_CW_CERT_A		(0x170|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CERT_B		(0x171|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CERT_C		(0x172|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CERT_D		(0x173|SSL_ST_CONNECT)
+#define SSL3_ST_CW_KEY_EXCH_A		(0x180|SSL_ST_CONNECT)
+#define SSL3_ST_CW_KEY_EXCH_B		(0x181|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CERT_VRFY_A		(0x190|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CERT_VRFY_B		(0x191|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CHANGE_A		(0x1A0|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CHANGE_B		(0x1A1|SSL_ST_CONNECT)
+#define SSL3_ST_CW_FINISHED_A		(0x1B0|SSL_ST_CONNECT)
+#define SSL3_ST_CW_FINISHED_B		(0x1B1|SSL_ST_CONNECT)
+/* read from server */
+#define SSL3_ST_CR_CHANGE_A		(0x1C0|SSL_ST_CONNECT)
+#define SSL3_ST_CR_CHANGE_B		(0x1C1|SSL_ST_CONNECT)
+#define SSL3_ST_CR_FINISHED_A		(0x1D0|SSL_ST_CONNECT)
+#define SSL3_ST_CR_FINISHED_B		(0x1D1|SSL_ST_CONNECT)
+#define SSL3_ST_CR_SESSION_TICKET_A	(0x1E0|SSL_ST_CONNECT)
+#define SSL3_ST_CR_SESSION_TICKET_B	(0x1E1|SSL_ST_CONNECT)
+#define SSL3_ST_CR_CERT_STATUS_A	(0x1F0|SSL_ST_CONNECT)
+#define SSL3_ST_CR_CERT_STATUS_B	(0x1F1|SSL_ST_CONNECT)
+
+/* server */
+/* extra state */
+#define SSL3_ST_SW_FLUSH		(0x100|SSL_ST_ACCEPT)
+/* read from client */
+/* Do not change the number values, they do matter */
+#define SSL3_ST_SR_CLNT_HELLO_A		(0x110|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CLNT_HELLO_B		(0x111|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CLNT_HELLO_C		(0x112|SSL_ST_ACCEPT)
+/* write to client */
+#define DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A (0x113|SSL_ST_ACCEPT)
+#define DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B (0x114|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_HELLO_REQ_A		(0x120|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_HELLO_REQ_B		(0x121|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_HELLO_REQ_C		(0x122|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_SRVR_HELLO_A		(0x130|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_SRVR_HELLO_B		(0x131|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_CERT_A		(0x140|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_CERT_B		(0x141|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_KEY_EXCH_A		(0x150|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_KEY_EXCH_B		(0x151|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_CERT_REQ_A		(0x160|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_CERT_REQ_B		(0x161|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_SRVR_DONE_A		(0x170|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_SRVR_DONE_B		(0x171|SSL_ST_ACCEPT)
+/* read from client */
+#define SSL3_ST_SR_CERT_A		(0x180|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CERT_B		(0x181|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_KEY_EXCH_A		(0x190|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_KEY_EXCH_B		(0x191|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CERT_VRFY_A		(0x1A0|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CERT_VRFY_B		(0x1A1|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CHANGE_A		(0x1B0|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CHANGE_B		(0x1B1|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_FINISHED_A		(0x1C0|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_FINISHED_B		(0x1C1|SSL_ST_ACCEPT)
+/* write to client */
+#define SSL3_ST_SW_CHANGE_A		(0x1D0|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_CHANGE_B		(0x1D1|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_FINISHED_A		(0x1E0|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_FINISHED_B		(0x1E1|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_SESSION_TICKET_A	(0x1F0|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_SESSION_TICKET_B	(0x1F1|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_CERT_STATUS_A	(0x200|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_CERT_STATUS_B	(0x201|SSL_ST_ACCEPT)
+
+#define SSL3_MT_HELLO_REQUEST			0
+#define SSL3_MT_CLIENT_HELLO			1
+#define SSL3_MT_SERVER_HELLO			2
+#define	SSL3_MT_NEWSESSION_TICKET		4
+#define SSL3_MT_CERTIFICATE			11
+#define SSL3_MT_SERVER_KEY_EXCHANGE		12
+#define SSL3_MT_CERTIFICATE_REQUEST		13
+#define SSL3_MT_SERVER_DONE			14
+#define SSL3_MT_CERTIFICATE_VERIFY		15
+#define SSL3_MT_CLIENT_KEY_EXCHANGE		16
+#define SSL3_MT_FINISHED			20
+#define SSL3_MT_CERTIFICATE_STATUS		22
+#define DTLS1_MT_HELLO_VERIFY_REQUEST    3
+
+
+#define SSL3_MT_CCS				1
+
+/* These are used when changing over to a new cipher */
+#define SSL3_CC_READ		0x01
+#define SSL3_CC_WRITE		0x02
+#define SSL3_CC_CLIENT		0x10
+#define SSL3_CC_SERVER		0x20
+#define SSL3_CHANGE_CIPHER_CLIENT_WRITE	(SSL3_CC_CLIENT|SSL3_CC_WRITE)	
+#define SSL3_CHANGE_CIPHER_SERVER_READ	(SSL3_CC_SERVER|SSL3_CC_READ)
+#define SSL3_CHANGE_CIPHER_CLIENT_READ	(SSL3_CC_CLIENT|SSL3_CC_READ)
+#define SSL3_CHANGE_CIPHER_SERVER_WRITE	(SSL3_CC_SERVER|SSL3_CC_WRITE)
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/lib/openssl/ssl/ssl_algs.c b/lib/openssl/ssl/ssl_algs.c
new file mode 100644
index 0000000..0967b2d
--- /dev/null
+++ b/lib/openssl/ssl/ssl_algs.c
@@ -0,0 +1,140 @@
+/* ssl/ssl_algs.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include <openssl/objects.h>
+#include <openssl/lhash.h>
+#include "ssl_locl.h"
+
+int SSL_library_init(void)
+	{
+
+#ifndef OPENSSL_NO_DES
+	EVP_add_cipher(EVP_des_cbc());
+	EVP_add_cipher(EVP_des_ede3_cbc());
+#endif
+#ifndef OPENSSL_NO_IDEA
+	EVP_add_cipher(EVP_idea_cbc());
+#endif
+#ifndef OPENSSL_NO_RC4
+	EVP_add_cipher(EVP_rc4());
+#endif  
+#ifndef OPENSSL_NO_RC2
+	EVP_add_cipher(EVP_rc2_cbc());
+	/* Not actually used for SSL/TLS but this makes PKCS#12 work
+	 * if an application only calls SSL_library_init().
+	 */
+	EVP_add_cipher(EVP_rc2_40_cbc());
+#endif
+#ifndef OPENSSL_NO_AES
+	EVP_add_cipher(EVP_aes_128_cbc());
+	EVP_add_cipher(EVP_aes_192_cbc());
+	EVP_add_cipher(EVP_aes_256_cbc());
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+	EVP_add_cipher(EVP_camellia_128_cbc());
+	EVP_add_cipher(EVP_camellia_256_cbc());
+#endif
+
+#ifndef OPENSSL_NO_SEED
+	EVP_add_cipher(EVP_seed_cbc());
+#endif
+  
+#ifndef OPENSSL_NO_MD5
+	EVP_add_digest(EVP_md5());
+	EVP_add_digest_alias(SN_md5,"ssl2-md5");
+	EVP_add_digest_alias(SN_md5,"ssl3-md5");
+#endif
+#ifndef OPENSSL_NO_SHA
+	EVP_add_digest(EVP_sha1()); /* RSA with sha1 */
+	EVP_add_digest_alias(SN_sha1,"ssl3-sha1");
+	EVP_add_digest_alias(SN_sha1WithRSAEncryption,SN_sha1WithRSA);
+#endif
+#ifndef OPENSSL_NO_SHA256
+	EVP_add_digest(EVP_sha224());
+	EVP_add_digest(EVP_sha256());
+#endif
+#ifndef OPENSSL_NO_SHA512
+	EVP_add_digest(EVP_sha384());
+	EVP_add_digest(EVP_sha512());
+#endif
+#if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_DSA)
+	EVP_add_digest(EVP_dss1()); /* DSA with sha1 */
+	EVP_add_digest_alias(SN_dsaWithSHA1,SN_dsaWithSHA1_2);
+	EVP_add_digest_alias(SN_dsaWithSHA1,"DSS1");
+	EVP_add_digest_alias(SN_dsaWithSHA1,"dss1");
+#endif
+#ifndef OPENSSL_NO_ECDSA
+	EVP_add_digest(EVP_ecdsa());
+#endif
+	/* If you want support for phased out ciphers, add the following */
+#if 0
+	EVP_add_digest(EVP_sha());
+	EVP_add_digest(EVP_dss());
+#endif
+#ifndef OPENSSL_NO_COMP
+	/* This will initialise the built-in compression algorithms.
+	   The value returned is a STACK_OF(SSL_COMP), but that can
+	   be discarded safely */
+	(void)SSL_COMP_get_compression_methods();
+#endif
+	/* initialize cipher/digest methods table */
+	ssl_load_ciphers();
+	return(1);
+	}
+
diff --git a/lib/openssl/ssl/ssl_asn1.c b/lib/openssl/ssl/ssl_asn1.c
new file mode 100644
index 0000000..2870997
--- /dev/null
+++ b/lib/openssl/ssl/ssl_asn1.c
@@ -0,0 +1,593 @@
+/* ssl/ssl_asn1.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "ssl_locl.h"
+#include <openssl/asn1_mac.h>
+#include <openssl/objects.h>
+#include <openssl/x509.h>
+
+typedef struct ssl_session_asn1_st
+	{
+	ASN1_INTEGER version;
+	ASN1_INTEGER ssl_version;
+	ASN1_OCTET_STRING cipher;
+	ASN1_OCTET_STRING comp_id;
+	ASN1_OCTET_STRING master_key;
+	ASN1_OCTET_STRING session_id;
+	ASN1_OCTET_STRING session_id_context;
+	ASN1_OCTET_STRING key_arg;
+#ifndef OPENSSL_NO_KRB5
+        ASN1_OCTET_STRING krb5_princ;
+#endif /* OPENSSL_NO_KRB5 */
+	ASN1_INTEGER time;
+	ASN1_INTEGER timeout;
+	ASN1_INTEGER verify_result;
+#ifndef OPENSSL_NO_TLSEXT
+	ASN1_OCTET_STRING tlsext_hostname;
+	ASN1_INTEGER tlsext_tick_lifetime;
+	ASN1_OCTET_STRING tlsext_tick;
+#endif /* OPENSSL_NO_TLSEXT */
+#ifndef OPENSSL_NO_PSK
+	ASN1_OCTET_STRING psk_identity_hint;
+	ASN1_OCTET_STRING psk_identity;
+#endif /* OPENSSL_NO_PSK */
+	} SSL_SESSION_ASN1;
+
+int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
+	{
+#define LSIZE2 (sizeof(long)*2)
+	int v1=0,v2=0,v3=0,v4=0,v5=0,v7=0,v8=0;
+	unsigned char buf[4],ibuf1[LSIZE2],ibuf2[LSIZE2];
+	unsigned char ibuf3[LSIZE2],ibuf4[LSIZE2],ibuf5[LSIZE2];
+#ifndef OPENSSL_NO_TLSEXT
+	int v6=0,v9=0,v10=0;
+	unsigned char ibuf6[LSIZE2];
+#endif
+#ifndef OPENSSL_NO_COMP
+	unsigned char cbuf;
+	int v11=0;
+#endif
+	long l;
+	SSL_SESSION_ASN1 a;
+	M_ASN1_I2D_vars(in);
+
+	if ((in == NULL) || ((in->cipher == NULL) && (in->cipher_id == 0)))
+		return(0);
+
+	/* Note that I cheat in the following 2 assignments.  I know
+	 * that if the ASN1_INTEGER passed to ASN1_INTEGER_set
+	 * is > sizeof(long)+1, the buffer will not be re-OPENSSL_malloc()ed.
+	 * This is a bit evil but makes things simple, no dynamic allocation
+	 * to clean up :-) */
+	a.version.length=LSIZE2;
+	a.version.type=V_ASN1_INTEGER;
+	a.version.data=ibuf1;
+	ASN1_INTEGER_set(&(a.version),SSL_SESSION_ASN1_VERSION);
+
+	a.ssl_version.length=LSIZE2;
+	a.ssl_version.type=V_ASN1_INTEGER;
+	a.ssl_version.data=ibuf2;
+	ASN1_INTEGER_set(&(a.ssl_version),in->ssl_version);
+
+	a.cipher.type=V_ASN1_OCTET_STRING;
+	a.cipher.data=buf;
+
+	if (in->cipher == NULL)
+		l=in->cipher_id;
+	else
+		l=in->cipher->id;
+	if (in->ssl_version == SSL2_VERSION)
+		{
+		a.cipher.length=3;
+		buf[0]=((unsigned char)(l>>16L))&0xff;
+		buf[1]=((unsigned char)(l>> 8L))&0xff;
+		buf[2]=((unsigned char)(l     ))&0xff;
+		}
+	else
+		{
+		a.cipher.length=2;
+		buf[0]=((unsigned char)(l>>8L))&0xff;
+		buf[1]=((unsigned char)(l    ))&0xff;
+		}
+
+#ifndef OPENSSL_NO_COMP
+	if (in->compress_meth)
+		{
+		cbuf = (unsigned char)in->compress_meth;
+		a.comp_id.length = 1;
+		a.comp_id.type = V_ASN1_OCTET_STRING;
+		a.comp_id.data = &cbuf;
+		}
+#endif
+
+	a.master_key.length=in->master_key_length;
+	a.master_key.type=V_ASN1_OCTET_STRING;
+	a.master_key.data=in->master_key;
+
+	a.session_id.length=in->session_id_length;
+	a.session_id.type=V_ASN1_OCTET_STRING;
+	a.session_id.data=in->session_id;
+
+	a.session_id_context.length=in->sid_ctx_length;
+	a.session_id_context.type=V_ASN1_OCTET_STRING;
+	a.session_id_context.data=in->sid_ctx;
+
+	a.key_arg.length=in->key_arg_length;
+	a.key_arg.type=V_ASN1_OCTET_STRING;
+	a.key_arg.data=in->key_arg;
+
+#ifndef OPENSSL_NO_KRB5
+	if (in->krb5_client_princ_len)
+		{
+		a.krb5_princ.length=in->krb5_client_princ_len;
+		a.krb5_princ.type=V_ASN1_OCTET_STRING;
+		a.krb5_princ.data=in->krb5_client_princ;
+		}
+#endif /* OPENSSL_NO_KRB5 */
+
+	if (in->time != 0L)
+		{
+		a.time.length=LSIZE2;
+		a.time.type=V_ASN1_INTEGER;
+		a.time.data=ibuf3;
+		ASN1_INTEGER_set(&(a.time),in->time);
+		}
+
+	if (in->timeout != 0L)
+		{
+		a.timeout.length=LSIZE2;
+		a.timeout.type=V_ASN1_INTEGER;
+		a.timeout.data=ibuf4;
+		ASN1_INTEGER_set(&(a.timeout),in->timeout);
+		}
+
+	if (in->verify_result != X509_V_OK)
+		{
+		a.verify_result.length=LSIZE2;
+		a.verify_result.type=V_ASN1_INTEGER;
+		a.verify_result.data=ibuf5;
+		ASN1_INTEGER_set(&a.verify_result,in->verify_result);
+		}
+
+#ifndef OPENSSL_NO_TLSEXT
+	if (in->tlsext_hostname)
+                {
+                a.tlsext_hostname.length=strlen(in->tlsext_hostname);
+                a.tlsext_hostname.type=V_ASN1_OCTET_STRING;
+                a.tlsext_hostname.data=(unsigned char *)in->tlsext_hostname;
+                }
+	if (in->tlsext_tick)
+                {
+                a.tlsext_tick.length= in->tlsext_ticklen;
+                a.tlsext_tick.type=V_ASN1_OCTET_STRING;
+                a.tlsext_tick.data=(unsigned char *)in->tlsext_tick;
+                }
+	if (in->tlsext_tick_lifetime_hint > 0)
+		{
+		a.tlsext_tick_lifetime.length=LSIZE2;
+		a.tlsext_tick_lifetime.type=V_ASN1_INTEGER;
+		a.tlsext_tick_lifetime.data=ibuf6;
+		ASN1_INTEGER_set(&a.tlsext_tick_lifetime,in->tlsext_tick_lifetime_hint);
+		}
+#endif /* OPENSSL_NO_TLSEXT */
+#ifndef OPENSSL_NO_PSK
+	if (in->psk_identity_hint)
+		{
+		a.psk_identity_hint.length=strlen(in->psk_identity_hint);
+		a.psk_identity_hint.type=V_ASN1_OCTET_STRING;
+		a.psk_identity_hint.data=(unsigned char *)(in->psk_identity_hint);
+		}
+	if (in->psk_identity)
+		{
+		a.psk_identity.length=strlen(in->psk_identity);
+		a.psk_identity.type=V_ASN1_OCTET_STRING;
+		a.psk_identity.data=(unsigned char *)(in->psk_identity);
+		}
+#endif /* OPENSSL_NO_PSK */
+
+	M_ASN1_I2D_len(&(a.version),		i2d_ASN1_INTEGER);
+	M_ASN1_I2D_len(&(a.ssl_version),	i2d_ASN1_INTEGER);
+	M_ASN1_I2D_len(&(a.cipher),		i2d_ASN1_OCTET_STRING);
+	M_ASN1_I2D_len(&(a.session_id),		i2d_ASN1_OCTET_STRING);
+	M_ASN1_I2D_len(&(a.master_key),		i2d_ASN1_OCTET_STRING);
+#ifndef OPENSSL_NO_KRB5
+	if (in->krb5_client_princ_len)
+        	M_ASN1_I2D_len(&(a.krb5_princ),	i2d_ASN1_OCTET_STRING);
+#endif /* OPENSSL_NO_KRB5 */
+	if (in->key_arg_length > 0)
+		M_ASN1_I2D_len_IMP_opt(&(a.key_arg),i2d_ASN1_OCTET_STRING);
+	if (in->time != 0L)
+		M_ASN1_I2D_len_EXP_opt(&(a.time),i2d_ASN1_INTEGER,1,v1);
+	if (in->timeout != 0L)
+		M_ASN1_I2D_len_EXP_opt(&(a.timeout),i2d_ASN1_INTEGER,2,v2);
+	if (in->peer != NULL)
+		M_ASN1_I2D_len_EXP_opt(in->peer,i2d_X509,3,v3);
+	M_ASN1_I2D_len_EXP_opt(&a.session_id_context,i2d_ASN1_OCTET_STRING,4,v4);
+	if (in->verify_result != X509_V_OK)
+		M_ASN1_I2D_len_EXP_opt(&(a.verify_result),i2d_ASN1_INTEGER,5,v5);
+
+#ifndef OPENSSL_NO_TLSEXT
+	if (in->tlsext_tick_lifetime_hint > 0)
+      	 	M_ASN1_I2D_len_EXP_opt(&a.tlsext_tick_lifetime, i2d_ASN1_INTEGER,9,v9);
+	if (in->tlsext_tick)
+        	M_ASN1_I2D_len_EXP_opt(&(a.tlsext_tick), i2d_ASN1_OCTET_STRING,10,v10);
+	if (in->tlsext_hostname)
+        	M_ASN1_I2D_len_EXP_opt(&(a.tlsext_hostname), i2d_ASN1_OCTET_STRING,6,v6);
+#ifndef OPENSSL_NO_COMP
+	if (in->compress_meth)
+        	M_ASN1_I2D_len_EXP_opt(&(a.comp_id), i2d_ASN1_OCTET_STRING,11,v11);
+#endif
+#endif /* OPENSSL_NO_TLSEXT */
+#ifndef OPENSSL_NO_PSK
+	if (in->psk_identity_hint)
+        	M_ASN1_I2D_len_EXP_opt(&(a.psk_identity_hint), i2d_ASN1_OCTET_STRING,7,v7);
+	if (in->psk_identity)
+        	M_ASN1_I2D_len_EXP_opt(&(a.psk_identity), i2d_ASN1_OCTET_STRING,8,v8);
+#endif /* OPENSSL_NO_PSK */
+
+	M_ASN1_I2D_seq_total();
+
+	M_ASN1_I2D_put(&(a.version),		i2d_ASN1_INTEGER);
+	M_ASN1_I2D_put(&(a.ssl_version),	i2d_ASN1_INTEGER);
+	M_ASN1_I2D_put(&(a.cipher),		i2d_ASN1_OCTET_STRING);
+	M_ASN1_I2D_put(&(a.session_id),		i2d_ASN1_OCTET_STRING);
+	M_ASN1_I2D_put(&(a.master_key),		i2d_ASN1_OCTET_STRING);
+#ifndef OPENSSL_NO_KRB5
+	if (in->krb5_client_princ_len)
+        	M_ASN1_I2D_put(&(a.krb5_princ),	i2d_ASN1_OCTET_STRING);
+#endif /* OPENSSL_NO_KRB5 */
+	if (in->key_arg_length > 0)
+		M_ASN1_I2D_put_IMP_opt(&(a.key_arg),i2d_ASN1_OCTET_STRING,0);
+	if (in->time != 0L)
+		M_ASN1_I2D_put_EXP_opt(&(a.time),i2d_ASN1_INTEGER,1,v1);
+	if (in->timeout != 0L)
+		M_ASN1_I2D_put_EXP_opt(&(a.timeout),i2d_ASN1_INTEGER,2,v2);
+	if (in->peer != NULL)
+		M_ASN1_I2D_put_EXP_opt(in->peer,i2d_X509,3,v3);
+	M_ASN1_I2D_put_EXP_opt(&a.session_id_context,i2d_ASN1_OCTET_STRING,4,
+			       v4);
+	if (in->verify_result != X509_V_OK)
+		M_ASN1_I2D_put_EXP_opt(&a.verify_result,i2d_ASN1_INTEGER,5,v5);
+#ifndef OPENSSL_NO_TLSEXT
+	if (in->tlsext_hostname)
+        	M_ASN1_I2D_put_EXP_opt(&(a.tlsext_hostname), i2d_ASN1_OCTET_STRING,6,v6);
+#endif /* OPENSSL_NO_TLSEXT */
+#ifndef OPENSSL_NO_PSK
+	if (in->psk_identity_hint)
+		M_ASN1_I2D_put_EXP_opt(&(a.psk_identity_hint), i2d_ASN1_OCTET_STRING,7,v7);
+	if (in->psk_identity)
+		M_ASN1_I2D_put_EXP_opt(&(a.psk_identity), i2d_ASN1_OCTET_STRING,8,v8);
+#endif /* OPENSSL_NO_PSK */
+#ifndef OPENSSL_NO_TLSEXT
+	if (in->tlsext_tick_lifetime_hint > 0)
+      	 	M_ASN1_I2D_put_EXP_opt(&a.tlsext_tick_lifetime, i2d_ASN1_INTEGER,9,v9);
+	if (in->tlsext_tick)
+        	M_ASN1_I2D_put_EXP_opt(&(a.tlsext_tick), i2d_ASN1_OCTET_STRING,10,v10);
+#endif /* OPENSSL_NO_TLSEXT */
+#ifndef OPENSSL_NO_COMP
+	if (in->compress_meth)
+        	M_ASN1_I2D_put_EXP_opt(&(a.comp_id), i2d_ASN1_OCTET_STRING,11,v11);
+#endif
+	M_ASN1_I2D_finish();
+	}
+
+SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
+			     long length)
+	{
+	int version,ssl_version=0,i;
+	long id;
+	ASN1_INTEGER ai,*aip;
+	ASN1_OCTET_STRING os,*osp;
+	M_ASN1_D2I_vars(a,SSL_SESSION *,SSL_SESSION_new);
+
+	aip= &ai;
+	osp= &os;
+
+	M_ASN1_D2I_Init();
+	M_ASN1_D2I_start_sequence();
+
+	ai.data=NULL; ai.length=0;
+	M_ASN1_D2I_get_x(ASN1_INTEGER,aip,d2i_ASN1_INTEGER);
+	version=(int)ASN1_INTEGER_get(aip);
+	if (ai.data != NULL) { OPENSSL_free(ai.data); ai.data=NULL; ai.length=0; }
+
+	/* we don't care about the version right now :-) */
+	M_ASN1_D2I_get_x(ASN1_INTEGER,aip,d2i_ASN1_INTEGER);
+	ssl_version=(int)ASN1_INTEGER_get(aip);
+	ret->ssl_version=ssl_version;
+	if (ai.data != NULL) { OPENSSL_free(ai.data); ai.data=NULL; ai.length=0; }
+
+	os.data=NULL; os.length=0;
+	M_ASN1_D2I_get_x(ASN1_OCTET_STRING,osp,d2i_ASN1_OCTET_STRING);
+	if (ssl_version == SSL2_VERSION)
+		{
+		if (os.length != 3)
+			{
+			c.error=SSL_R_CIPHER_CODE_WRONG_LENGTH;
+			goto err;
+			}
+		id=0x02000000L|
+			((unsigned long)os.data[0]<<16L)|
+			((unsigned long)os.data[1]<< 8L)|
+			 (unsigned long)os.data[2];
+		}
+	else if ((ssl_version>>8) >= SSL3_VERSION_MAJOR)
+		{
+		if (os.length != 2)
+			{
+			c.error=SSL_R_CIPHER_CODE_WRONG_LENGTH;
+			goto err;
+			}
+		id=0x03000000L|
+			((unsigned long)os.data[0]<<8L)|
+			 (unsigned long)os.data[1];
+		}
+	else
+		{
+		c.error=SSL_R_UNKNOWN_SSL_VERSION;
+		goto err;
+		}
+	
+	ret->cipher=NULL;
+	ret->cipher_id=id;
+
+	M_ASN1_D2I_get_x(ASN1_OCTET_STRING,osp,d2i_ASN1_OCTET_STRING);
+	if ((ssl_version>>8) >= SSL3_VERSION_MAJOR)
+		i=SSL3_MAX_SSL_SESSION_ID_LENGTH;
+	else /* if (ssl_version>>8 == SSL2_VERSION_MAJOR) */
+		i=SSL2_MAX_SSL_SESSION_ID_LENGTH;
+
+	if (os.length > i)
+		os.length = i;
+	if (os.length > (int)sizeof(ret->session_id)) /* can't happen */
+		os.length = sizeof(ret->session_id);
+
+	ret->session_id_length=os.length;
+	OPENSSL_assert(os.length <= (int)sizeof(ret->session_id));
+	memcpy(ret->session_id,os.data,os.length);
+
+	M_ASN1_D2I_get_x(ASN1_OCTET_STRING,osp,d2i_ASN1_OCTET_STRING);
+	if (os.length > SSL_MAX_MASTER_KEY_LENGTH)
+		ret->master_key_length=SSL_MAX_MASTER_KEY_LENGTH;
+	else
+		ret->master_key_length=os.length;
+	memcpy(ret->master_key,os.data,ret->master_key_length);
+
+	os.length=0;
+
+#ifndef OPENSSL_NO_KRB5
+	os.length=0;
+	M_ASN1_D2I_get_opt(osp,d2i_ASN1_OCTET_STRING,V_ASN1_OCTET_STRING);
+	if (os.data)
+		{
+        	if (os.length > SSL_MAX_KRB5_PRINCIPAL_LENGTH)
+            		ret->krb5_client_princ_len=0;
+		else
+			ret->krb5_client_princ_len=os.length;
+		memcpy(ret->krb5_client_princ,os.data,ret->krb5_client_princ_len);
+		OPENSSL_free(os.data);
+		os.data = NULL;
+		os.length = 0;
+		}
+	else
+		ret->krb5_client_princ_len=0;
+#endif /* OPENSSL_NO_KRB5 */
+
+	M_ASN1_D2I_get_IMP_opt(osp,d2i_ASN1_OCTET_STRING,0,V_ASN1_OCTET_STRING);
+	if (os.length > SSL_MAX_KEY_ARG_LENGTH)
+		ret->key_arg_length=SSL_MAX_KEY_ARG_LENGTH;
+	else
+		ret->key_arg_length=os.length;
+	memcpy(ret->key_arg,os.data,ret->key_arg_length);
+	if (os.data != NULL) OPENSSL_free(os.data);
+
+	ai.length=0;
+	M_ASN1_D2I_get_EXP_opt(aip,d2i_ASN1_INTEGER,1);
+	if (ai.data != NULL)
+		{
+		ret->time=ASN1_INTEGER_get(aip);
+		OPENSSL_free(ai.data); ai.data=NULL; ai.length=0;
+		}
+	else
+		ret->time=(unsigned long)time(NULL);
+
+	ai.length=0;
+	M_ASN1_D2I_get_EXP_opt(aip,d2i_ASN1_INTEGER,2);
+	if (ai.data != NULL)
+		{
+		ret->timeout=ASN1_INTEGER_get(aip);
+		OPENSSL_free(ai.data); ai.data=NULL; ai.length=0;
+		}
+	else
+		ret->timeout=3;
+
+	if (ret->peer != NULL)
+		{
+		X509_free(ret->peer);
+		ret->peer=NULL;
+		}
+	M_ASN1_D2I_get_EXP_opt(ret->peer,d2i_X509,3);
+
+	os.length=0;
+	os.data=NULL;
+	M_ASN1_D2I_get_EXP_opt(osp,d2i_ASN1_OCTET_STRING,4);
+
+	if(os.data != NULL)
+	    {
+	    if (os.length > SSL_MAX_SID_CTX_LENGTH)
+		{
+		c.error=SSL_R_BAD_LENGTH;
+		goto err;
+		}
+	    else
+		{
+		ret->sid_ctx_length=os.length;
+		memcpy(ret->sid_ctx,os.data,os.length);
+		}
+	    OPENSSL_free(os.data); os.data=NULL; os.length=0;
+	    }
+	else
+	    ret->sid_ctx_length=0;
+
+	ai.length=0;
+	M_ASN1_D2I_get_EXP_opt(aip,d2i_ASN1_INTEGER,5);
+	if (ai.data != NULL)
+		{
+		ret->verify_result=ASN1_INTEGER_get(aip);
+		OPENSSL_free(ai.data); ai.data=NULL; ai.length=0;
+		}
+	else
+		ret->verify_result=X509_V_OK;
+
+#ifndef OPENSSL_NO_TLSEXT
+	os.length=0;
+	os.data=NULL;
+	M_ASN1_D2I_get_EXP_opt(osp,d2i_ASN1_OCTET_STRING,6);
+	if (os.data)
+		{
+		ret->tlsext_hostname = BUF_strndup((char *)os.data, os.length);
+		OPENSSL_free(os.data);
+		os.data = NULL;
+		os.length = 0;
+		}
+	else
+		ret->tlsext_hostname=NULL;
+#endif /* OPENSSL_NO_TLSEXT */
+
+#ifndef OPENSSL_NO_PSK
+	os.length=0;
+	os.data=NULL;
+	M_ASN1_D2I_get_EXP_opt(osp,d2i_ASN1_OCTET_STRING,7);
+	if (os.data)
+		{
+		ret->psk_identity_hint = BUF_strndup((char *)os.data, os.length);
+		OPENSSL_free(os.data);
+		os.data = NULL;
+		os.length = 0;
+		}
+	else
+		ret->psk_identity_hint=NULL;
+#endif /* OPENSSL_NO_PSK */
+
+#ifndef OPENSSL_NO_TLSEXT
+	ai.length=0;
+	M_ASN1_D2I_get_EXP_opt(aip,d2i_ASN1_INTEGER,9);
+	if (ai.data != NULL)
+		{
+		ret->tlsext_tick_lifetime_hint=ASN1_INTEGER_get(aip);
+		OPENSSL_free(ai.data); ai.data=NULL; ai.length=0;
+		}
+	else if (ret->tlsext_ticklen && ret->session_id_length)
+		ret->tlsext_tick_lifetime_hint = -1;
+	else
+		ret->tlsext_tick_lifetime_hint=0;
+	os.length=0;
+	os.data=NULL;
+	M_ASN1_D2I_get_EXP_opt(osp,d2i_ASN1_OCTET_STRING,10);
+	if (os.data)
+		{
+		ret->tlsext_tick = os.data;
+		ret->tlsext_ticklen = os.length;
+		os.data = NULL;
+		os.length = 0;
+		}
+	else
+		ret->tlsext_tick=NULL;
+#endif /* OPENSSL_NO_TLSEXT */
+#ifndef OPENSSL_NO_COMP
+	os.length=0;
+	os.data=NULL;
+	M_ASN1_D2I_get_EXP_opt(osp,d2i_ASN1_OCTET_STRING,11);
+	if (os.data)
+		{
+		ret->compress_meth = os.data[0];
+		OPENSSL_free(os.data);
+		os.data = NULL;
+		}
+#endif
+
+	M_ASN1_D2I_Finish(a,SSL_SESSION_free,SSL_F_D2I_SSL_SESSION);
+	}
diff --git a/lib/openssl/ssl/ssl_cert.c b/lib/openssl/ssl/ssl_cert.c
new file mode 100644
index 0000000..27256ee
--- /dev/null
+++ b/lib/openssl/ssl/ssl_cert.c
@@ -0,0 +1,834 @@
+/*! \file ssl/ssl_cert.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECC cipher suite support in OpenSSL originally developed by 
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#include <stdio.h>
+
+#include "e_os.h"
+#ifndef NO_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include "o_dir.h"
+#include <openssl/objects.h>
+#include <openssl/bio.h>
+#include <openssl/pem.h>
+#include <openssl/x509v3.h>
+#ifndef OPENSSL_NO_DH
+#include <openssl/dh.h>
+#endif
+#include <openssl/bn.h>
+#include "ssl_locl.h"
+
+int SSL_get_ex_data_X509_STORE_CTX_idx(void)
+	{
+	static volatile int ssl_x509_store_ctx_idx= -1;
+	int got_write_lock = 0;
+
+	CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
+
+	if (ssl_x509_store_ctx_idx < 0)
+		{
+		CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
+		CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
+		got_write_lock = 1;
+		
+		if (ssl_x509_store_ctx_idx < 0)
+			{
+			ssl_x509_store_ctx_idx=X509_STORE_CTX_get_ex_new_index(
+				0,"SSL for verify callback",NULL,NULL,NULL);
+			}
+		}
+
+	if (got_write_lock)
+		CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
+	else
+		CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
+	
+	return ssl_x509_store_ctx_idx;
+	}
+
+CERT *ssl_cert_new(void)
+	{
+	CERT *ret;
+
+	ret=(CERT *)OPENSSL_malloc(sizeof(CERT));
+	if (ret == NULL)
+		{
+		SSLerr(SSL_F_SSL_CERT_NEW,ERR_R_MALLOC_FAILURE);
+		return(NULL);
+		}
+	memset(ret,0,sizeof(CERT));
+
+	ret->key= &(ret->pkeys[SSL_PKEY_RSA_ENC]);
+	ret->references=1;
+
+	return(ret);
+	}
+
+CERT *ssl_cert_dup(CERT *cert)
+	{
+	CERT *ret;
+	int i;
+
+	ret = (CERT *)OPENSSL_malloc(sizeof(CERT));
+	if (ret == NULL)
+		{
+		SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
+		return(NULL);
+		}
+
+	memset(ret, 0, sizeof(CERT));
+
+	ret->key = &ret->pkeys[cert->key - &cert->pkeys[0]];
+	/* or ret->key = ret->pkeys + (cert->key - cert->pkeys),
+	 * if you find that more readable */
+
+	ret->valid = cert->valid;
+	ret->mask_k = cert->mask_k;
+	ret->mask_a = cert->mask_a;
+	ret->export_mask_k = cert->export_mask_k;
+	ret->export_mask_a = cert->export_mask_a;
+
+#ifndef OPENSSL_NO_RSA
+	if (cert->rsa_tmp != NULL)
+		{
+		RSA_up_ref(cert->rsa_tmp);
+		ret->rsa_tmp = cert->rsa_tmp;
+		}
+	ret->rsa_tmp_cb = cert->rsa_tmp_cb;
+#endif
+
+#ifndef OPENSSL_NO_DH
+	if (cert->dh_tmp != NULL)
+		{
+		ret->dh_tmp = DHparams_dup(cert->dh_tmp);
+		if (ret->dh_tmp == NULL)
+			{
+			SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_DH_LIB);
+			goto err;
+			}
+		if (cert->dh_tmp->priv_key)
+			{
+			BIGNUM *b = BN_dup(cert->dh_tmp->priv_key);
+			if (!b)
+				{
+				SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_BN_LIB);
+				goto err;
+				}
+			ret->dh_tmp->priv_key = b;
+			}
+		if (cert->dh_tmp->pub_key)
+			{
+			BIGNUM *b = BN_dup(cert->dh_tmp->pub_key);
+			if (!b)
+				{
+				SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_BN_LIB);
+				goto err;
+				}
+			ret->dh_tmp->pub_key = b;
+			}
+		}
+	ret->dh_tmp_cb = cert->dh_tmp_cb;
+#endif
+
+#ifndef OPENSSL_NO_ECDH
+	if (cert->ecdh_tmp)
+		{
+		ret->ecdh_tmp = EC_KEY_dup(cert->ecdh_tmp);
+		if (ret->ecdh_tmp == NULL)
+			{
+			SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_EC_LIB);
+			goto err;
+			}
+		}
+	ret->ecdh_tmp_cb = cert->ecdh_tmp_cb;
+#endif
+
+	for (i = 0; i < SSL_PKEY_NUM; i++)
+		{
+		if (cert->pkeys[i].x509 != NULL)
+			{
+			ret->pkeys[i].x509 = cert->pkeys[i].x509;
+			CRYPTO_add(&ret->pkeys[i].x509->references, 1,
+				CRYPTO_LOCK_X509);
+			}
+		
+		if (cert->pkeys[i].privatekey != NULL)
+			{
+			ret->pkeys[i].privatekey = cert->pkeys[i].privatekey;
+			CRYPTO_add(&ret->pkeys[i].privatekey->references, 1,
+				CRYPTO_LOCK_EVP_PKEY);
+
+			switch(i) 
+				{
+				/* If there was anything special to do for
+				 * certain types of keys, we'd do it here.
+				 * (Nothing at the moment, I think.) */
+
+			case SSL_PKEY_RSA_ENC:
+			case SSL_PKEY_RSA_SIGN:
+				/* We have an RSA key. */
+				break;
+				
+			case SSL_PKEY_DSA_SIGN:
+				/* We have a DSA key. */
+				break;
+				
+			case SSL_PKEY_DH_RSA:
+			case SSL_PKEY_DH_DSA:
+				/* We have a DH key. */
+				break;
+
+			case SSL_PKEY_ECC:
+				/* We have an ECC key */
+				break;
+
+			default:
+				/* Can't happen. */
+				SSLerr(SSL_F_SSL_CERT_DUP, SSL_R_LIBRARY_BUG);
+				}
+			}
+		}
+	
+	/* ret->extra_certs *should* exist, but currently the own certificate
+	 * chain is held inside SSL_CTX */
+
+	ret->references=1;
+
+	return(ret);
+	
+#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_ECDH)
+err:
+#endif
+#ifndef OPENSSL_NO_RSA
+	if (ret->rsa_tmp != NULL)
+		RSA_free(ret->rsa_tmp);
+#endif
+#ifndef OPENSSL_NO_DH
+	if (ret->dh_tmp != NULL)
+		DH_free(ret->dh_tmp);
+#endif
+#ifndef OPENSSL_NO_ECDH
+	if (ret->ecdh_tmp != NULL)
+		EC_KEY_free(ret->ecdh_tmp);
+#endif
+
+	for (i = 0; i < SSL_PKEY_NUM; i++)
+		{
+		if (ret->pkeys[i].x509 != NULL)
+			X509_free(ret->pkeys[i].x509);
+		if (ret->pkeys[i].privatekey != NULL)
+			EVP_PKEY_free(ret->pkeys[i].privatekey);
+		}
+
+	return NULL;
+	}
+
+
+void ssl_cert_free(CERT *c)
+	{
+	int i;
+
+	if(c == NULL)
+	    return;
+
+	i=CRYPTO_add(&c->references,-1,CRYPTO_LOCK_SSL_CERT);
+#ifdef REF_PRINT
+	REF_PRINT("CERT",c);
+#endif
+	if (i > 0) return;
+#ifdef REF_CHECK
+	if (i < 0)
+		{
+		fprintf(stderr,"ssl_cert_free, bad reference count\n");
+		abort(); /* ok */
+		}
+#endif
+
+#ifndef OPENSSL_NO_RSA
+	if (c->rsa_tmp) RSA_free(c->rsa_tmp);
+#endif
+#ifndef OPENSSL_NO_DH
+	if (c->dh_tmp) DH_free(c->dh_tmp);
+#endif
+#ifndef OPENSSL_NO_ECDH
+	if (c->ecdh_tmp) EC_KEY_free(c->ecdh_tmp);
+#endif
+
+	for (i=0; i<SSL_PKEY_NUM; i++)
+		{
+		if (c->pkeys[i].x509 != NULL)
+			X509_free(c->pkeys[i].x509);
+		if (c->pkeys[i].privatekey != NULL)
+			EVP_PKEY_free(c->pkeys[i].privatekey);
+#if 0
+		if (c->pkeys[i].publickey != NULL)
+			EVP_PKEY_free(c->pkeys[i].publickey);
+#endif
+		}
+	OPENSSL_free(c);
+	}
+
+int ssl_cert_inst(CERT **o)
+	{
+	/* Create a CERT if there isn't already one
+	 * (which cannot really happen, as it is initially created in
+	 * SSL_CTX_new; but the earlier code usually allows for that one
+	 * being non-existant, so we follow that behaviour, as it might
+	 * turn out that there actually is a reason for it -- but I'm
+	 * not sure that *all* of the existing code could cope with
+	 * s->cert being NULL, otherwise we could do without the
+	 * initialization in SSL_CTX_new).
+	 */
+	
+	if (o == NULL) 
+		{
+		SSLerr(SSL_F_SSL_CERT_INST, ERR_R_PASSED_NULL_PARAMETER);
+		return(0);
+		}
+	if (*o == NULL)
+		{
+		if ((*o = ssl_cert_new()) == NULL)
+			{
+			SSLerr(SSL_F_SSL_CERT_INST, ERR_R_MALLOC_FAILURE);
+			return(0);
+			}
+		}
+	return(1);
+	}
+
+
+SESS_CERT *ssl_sess_cert_new(void)
+	{
+	SESS_CERT *ret;
+
+	ret = OPENSSL_malloc(sizeof *ret);
+	if (ret == NULL)
+		{
+		SSLerr(SSL_F_SSL_SESS_CERT_NEW, ERR_R_MALLOC_FAILURE);
+		return NULL;
+		}
+
+	memset(ret, 0 ,sizeof *ret);
+	ret->peer_key = &(ret->peer_pkeys[SSL_PKEY_RSA_ENC]);
+	ret->references = 1;
+
+	return ret;
+	}
+
+void ssl_sess_cert_free(SESS_CERT *sc)
+	{
+	int i;
+
+	if (sc == NULL)
+		return;
+
+	i = CRYPTO_add(&sc->references, -1, CRYPTO_LOCK_SSL_SESS_CERT);
+#ifdef REF_PRINT
+	REF_PRINT("SESS_CERT", sc);
+#endif
+	if (i > 0)
+		return;
+#ifdef REF_CHECK
+	if (i < 0)
+		{
+		fprintf(stderr,"ssl_sess_cert_free, bad reference count\n");
+		abort(); /* ok */
+		}
+#endif
+
+	/* i == 0 */
+	if (sc->cert_chain != NULL)
+		sk_X509_pop_free(sc->cert_chain, X509_free);
+	for (i = 0; i < SSL_PKEY_NUM; i++)
+		{
+		if (sc->peer_pkeys[i].x509 != NULL)
+			X509_free(sc->peer_pkeys[i].x509);
+#if 0 /* We don't have the peer's private key.  These lines are just
+	   * here as a reminder that we're still using a not-quite-appropriate
+	   * data structure. */
+		if (sc->peer_pkeys[i].privatekey != NULL)
+			EVP_PKEY_free(sc->peer_pkeys[i].privatekey);
+#endif
+		}
+
+#ifndef OPENSSL_NO_RSA
+	if (sc->peer_rsa_tmp != NULL)
+		RSA_free(sc->peer_rsa_tmp);
+#endif
+#ifndef OPENSSL_NO_DH
+	if (sc->peer_dh_tmp != NULL)
+		DH_free(sc->peer_dh_tmp);
+#endif
+#ifndef OPENSSL_NO_ECDH
+	if (sc->peer_ecdh_tmp != NULL)
+		EC_KEY_free(sc->peer_ecdh_tmp);
+#endif
+
+	OPENSSL_free(sc);
+	}
+
+int ssl_set_peer_cert_type(SESS_CERT *sc,int type)
+	{
+	sc->peer_cert_type = type;
+	return(1);
+	}
+
+int ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk)
+	{
+	X509 *x;
+	int i;
+	X509_STORE_CTX ctx;
+
+	if ((sk == NULL) || (sk_X509_num(sk) == 0))
+		return(0);
+
+	x=sk_X509_value(sk,0);
+	if(!X509_STORE_CTX_init(&ctx,s->ctx->cert_store,x,sk))
+		{
+		SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN,ERR_R_X509_LIB);
+		return(0);
+		}
+#if 0
+	if (SSL_get_verify_depth(s) >= 0)
+		X509_STORE_CTX_set_depth(&ctx, SSL_get_verify_depth(s));
+#endif
+	X509_STORE_CTX_set_ex_data(&ctx,SSL_get_ex_data_X509_STORE_CTX_idx(),s);
+
+	/* We need to inherit the verify parameters. These can be determined by
+	 * the context: if its a server it will verify SSL client certificates
+	 * or vice versa.
+	 */
+
+	X509_STORE_CTX_set_default(&ctx,
+				s->server ? "ssl_client" : "ssl_server");
+	/* Anything non-default in "param" should overwrite anything in the
+	 * ctx.
+	 */
+	X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(&ctx), s->param);
+
+	if (s->verify_callback)
+		X509_STORE_CTX_set_verify_cb(&ctx, s->verify_callback);
+
+	if (s->ctx->app_verify_callback != NULL)
+#if 1 /* new with OpenSSL 0.9.7 */
+		i=s->ctx->app_verify_callback(&ctx, s->ctx->app_verify_arg); 
+#else
+		i=s->ctx->app_verify_callback(&ctx); /* should pass app_verify_arg */
+#endif
+	else
+		{
+#ifndef OPENSSL_NO_X509_VERIFY
+		i=X509_verify_cert(&ctx);
+#else
+		i=0;
+		ctx.error=X509_V_ERR_APPLICATION_VERIFICATION;
+		SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN,SSL_R_NO_VERIFY_CALLBACK);
+#endif
+		}
+
+	s->verify_result=ctx.error;
+	X509_STORE_CTX_cleanup(&ctx);
+
+	return(i);
+	}
+
+static void set_client_CA_list(STACK_OF(X509_NAME) **ca_list,STACK_OF(X509_NAME) *name_list)
+	{
+	if (*ca_list != NULL)
+		sk_X509_NAME_pop_free(*ca_list,X509_NAME_free);
+
+	*ca_list=name_list;
+	}
+
+STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *sk)
+	{
+	int i;
+	STACK_OF(X509_NAME) *ret;
+	X509_NAME *name;
+
+	ret=sk_X509_NAME_new_null();
+	for (i=0; i<sk_X509_NAME_num(sk); i++)
+		{
+		name=X509_NAME_dup(sk_X509_NAME_value(sk,i));
+		if ((name == NULL) || !sk_X509_NAME_push(ret,name))
+			{
+			sk_X509_NAME_pop_free(ret,X509_NAME_free);
+			return(NULL);
+			}
+		}
+	return(ret);
+	}
+
+void SSL_set_client_CA_list(SSL *s,STACK_OF(X509_NAME) *name_list)
+	{
+	set_client_CA_list(&(s->client_CA),name_list);
+	}
+
+void SSL_CTX_set_client_CA_list(SSL_CTX *ctx,STACK_OF(X509_NAME) *name_list)
+	{
+	set_client_CA_list(&(ctx->client_CA),name_list);
+	}
+
+STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *ctx)
+	{
+	return(ctx->client_CA);
+	}
+
+STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s)
+	{
+	if (s->type == SSL_ST_CONNECT)
+		{ /* we are in the client */
+		if (((s->version>>8) == SSL3_VERSION_MAJOR) &&
+			(s->s3 != NULL))
+			return(s->s3->tmp.ca_names);
+		else
+			return(NULL);
+		}
+	else
+		{
+		if (s->client_CA != NULL)
+			return(s->client_CA);
+		else
+			return(s->ctx->client_CA);
+		}
+	}
+
+static int add_client_CA(STACK_OF(X509_NAME) **sk,X509 *x)
+	{
+	X509_NAME *name;
+
+	if (x == NULL) return(0);
+	if ((*sk == NULL) && ((*sk=sk_X509_NAME_new_null()) == NULL))
+		return(0);
+		
+	if ((name=X509_NAME_dup(X509_get_subject_name(x))) == NULL)
+		return(0);
+
+	if (!sk_X509_NAME_push(*sk,name))
+		{
+		X509_NAME_free(name);
+		return(0);
+		}
+	return(1);
+	}
+
+int SSL_add_client_CA(SSL *ssl,X509 *x)
+	{
+	return(add_client_CA(&(ssl->client_CA),x));
+	}
+
+int SSL_CTX_add_client_CA(SSL_CTX *ctx,X509 *x)
+	{
+	return(add_client_CA(&(ctx->client_CA),x));
+	}
+
+static int xname_cmp(const X509_NAME * const *a, const X509_NAME * const *b)
+	{
+	return(X509_NAME_cmp(*a,*b));
+	}
+
+#ifndef OPENSSL_NO_STDIO
+/*!
+ * Load CA certs from a file into a ::STACK. Note that it is somewhat misnamed;
+ * it doesn't really have anything to do with clients (except that a common use
+ * for a stack of CAs is to send it to the client). Actually, it doesn't have
+ * much to do with CAs, either, since it will load any old cert.
+ * \param file the file containing one or more certs.
+ * \return a ::STACK containing the certs.
+ */
+STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file)
+	{
+	BIO *in;
+	X509 *x=NULL;
+	X509_NAME *xn=NULL;
+	STACK_OF(X509_NAME) *ret = NULL,*sk;
+
+	sk=sk_X509_NAME_new(xname_cmp);
+
+	in=BIO_new(BIO_s_file_internal());
+
+	if ((sk == NULL) || (in == NULL))
+		{
+		SSLerr(SSL_F_SSL_LOAD_CLIENT_CA_FILE,ERR_R_MALLOC_FAILURE);
+		goto err;
+		}
+	
+	if (!BIO_read_filename(in,file))
+		goto err;
+
+	for (;;)
+		{
+		if (PEM_read_bio_X509(in,&x,NULL,NULL) == NULL)
+			break;
+		if (ret == NULL)
+			{
+			ret = sk_X509_NAME_new_null();
+			if (ret == NULL)
+				{
+				SSLerr(SSL_F_SSL_LOAD_CLIENT_CA_FILE,ERR_R_MALLOC_FAILURE);
+				goto err;
+				}
+			}
+		if ((xn=X509_get_subject_name(x)) == NULL) goto err;
+		/* check for duplicates */
+		xn=X509_NAME_dup(xn);
+		if (xn == NULL) goto err;
+		if (sk_X509_NAME_find(sk,xn) >= 0)
+			X509_NAME_free(xn);
+		else
+			{
+			sk_X509_NAME_push(sk,xn);
+			sk_X509_NAME_push(ret,xn);
+			}
+		}
+
+	if (0)
+		{
+err:
+		if (ret != NULL) sk_X509_NAME_pop_free(ret,X509_NAME_free);
+		ret=NULL;
+		}
+	if (sk != NULL) sk_X509_NAME_free(sk);
+	if (in != NULL) BIO_free(in);
+	if (x != NULL) X509_free(x);
+	if (ret != NULL)
+		ERR_clear_error();
+	return(ret);
+	}
+#endif
+
+/*!
+ * Add a file of certs to a stack.
+ * \param stack the stack to add to.
+ * \param file the file to add from. All certs in this file that are not
+ * already in the stack will be added.
+ * \return 1 for success, 0 for failure. Note that in the case of failure some
+ * certs may have been added to \c stack.
+ */
+
+int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
+					const char *file)
+	{
+	BIO *in;
+	X509 *x=NULL;
+	X509_NAME *xn=NULL;
+	int ret=1;
+	int (*oldcmp)(const X509_NAME * const *a, const X509_NAME * const *b);
+	
+	oldcmp=sk_X509_NAME_set_cmp_func(stack,xname_cmp);
+	
+	in=BIO_new(BIO_s_file_internal());
+	
+	if (in == NULL)
+		{
+		SSLerr(SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK,ERR_R_MALLOC_FAILURE);
+		goto err;
+		}
+	
+	if (!BIO_read_filename(in,file))
+		goto err;
+	
+	for (;;)
+		{
+		if (PEM_read_bio_X509(in,&x,NULL,NULL) == NULL)
+			break;
+		if ((xn=X509_get_subject_name(x)) == NULL) goto err;
+		xn=X509_NAME_dup(xn);
+		if (xn == NULL) goto err;
+		if (sk_X509_NAME_find(stack,xn) >= 0)
+			X509_NAME_free(xn);
+		else
+			sk_X509_NAME_push(stack,xn);
+		}
+
+	ERR_clear_error();
+
+	if (0)
+		{
+err:
+		ret=0;
+		}
+	if(in != NULL)
+		BIO_free(in);
+	if(x != NULL)
+		X509_free(x);
+	
+	(void)sk_X509_NAME_set_cmp_func(stack,oldcmp);
+
+	return ret;
+	}
+
+/*!
+ * Add a directory of certs to a stack.
+ * \param stack the stack to append to.
+ * \param dir the directory to append from. All files in this directory will be
+ * examined as potential certs. Any that are acceptable to
+ * SSL_add_dir_cert_subjects_to_stack() that are not already in the stack will be
+ * included.
+ * \return 1 for success, 0 for failure. Note that in the case of failure some
+ * certs may have been added to \c stack.
+ */
+
+int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
+				       const char *dir)
+	{
+	OPENSSL_DIR_CTX *d = NULL;
+	const char *filename;
+	int ret = 0;
+
+	CRYPTO_w_lock(CRYPTO_LOCK_READDIR);
+
+	/* Note that a side effect is that the CAs will be sorted by name */
+
+	while((filename = OPENSSL_DIR_read(&d, dir)))
+		{
+		char buf[1024];
+		int r;
+
+		if(strlen(dir)+strlen(filename)+2 > sizeof buf)
+			{
+			SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK,SSL_R_PATH_TOO_LONG);
+			goto err;
+			}
+
+#ifdef OPENSSL_SYS_VMS
+		r = BIO_snprintf(buf,sizeof buf,"%s%s",dir,filename);
+#else
+		r = BIO_snprintf(buf,sizeof buf,"%s/%s",dir,filename);
+#endif
+		if (r <= 0 || r >= (int)sizeof(buf))
+			goto err;
+		if(!SSL_add_file_cert_subjects_to_stack(stack,buf))
+			goto err;
+		}
+
+	if (errno)
+		{
+		SYSerr(SYS_F_OPENDIR, get_last_sys_error());
+		ERR_add_error_data(3, "OPENSSL_DIR_read(&ctx, '", dir, "')");
+		SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK, ERR_R_SYS_LIB);
+		goto err;
+		}
+
+	ret = 1;
+
+err:
+	if (d) OPENSSL_DIR_end(&d);
+	CRYPTO_w_unlock(CRYPTO_LOCK_READDIR);
+	return ret;
+	}
+
diff --git a/lib/openssl/ssl/ssl_ciph.c b/lib/openssl/ssl/ssl_ciph.c
new file mode 100644
index 0000000..bee3507
--- /dev/null
+++ b/lib/openssl/ssl/ssl_ciph.c
@@ -0,0 +1,1748 @@
+/* ssl/ssl_ciph.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECC cipher suite support in OpenSSL originally developed by 
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#include <stdio.h>
+#include <openssl/objects.h>
+#ifndef OPENSSL_NO_COMP
+#include <openssl/comp.h>
+#endif
+#ifndef OPENSSL_NO_ENGINE
+#include <openssl/engine.h>
+#endif
+#include "ssl_locl.h"
+
+#define SSL_ENC_DES_IDX		0
+#define SSL_ENC_3DES_IDX	1
+#define SSL_ENC_RC4_IDX		2
+#define SSL_ENC_RC2_IDX		3
+#define SSL_ENC_IDEA_IDX	4
+#define SSL_ENC_NULL_IDX	5
+#define SSL_ENC_AES128_IDX	6
+#define SSL_ENC_AES256_IDX	7
+#define SSL_ENC_CAMELLIA128_IDX	8
+#define SSL_ENC_CAMELLIA256_IDX	9
+#define SSL_ENC_GOST89_IDX	10
+#define SSL_ENC_SEED_IDX    	11
+#define SSL_ENC_NUM_IDX		12
+
+
+static const EVP_CIPHER *ssl_cipher_methods[SSL_ENC_NUM_IDX]={
+	NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+	};
+
+#define SSL_COMP_NULL_IDX	0
+#define SSL_COMP_ZLIB_IDX	1
+#define SSL_COMP_NUM_IDX	2
+
+static STACK_OF(SSL_COMP) *ssl_comp_methods=NULL;
+
+#define SSL_MD_MD5_IDX	0
+#define SSL_MD_SHA1_IDX	1
+#define SSL_MD_GOST94_IDX 2
+#define SSL_MD_GOST89MAC_IDX 3
+/*Constant SSL_MAX_DIGEST equal to size of digests array should be 
+ * defined in the
+ * ssl_locl.h */
+#define SSL_MD_NUM_IDX	SSL_MAX_DIGEST 
+static const EVP_MD *ssl_digest_methods[SSL_MD_NUM_IDX]={
+	NULL,NULL,NULL,NULL
+	};
+/* PKEY_TYPE for GOST89MAC is known in advance, but, because
+ * implementation is engine-provided, we'll fill it only if
+ * corresponding EVP_PKEY_METHOD is found 
+ */
+static int  ssl_mac_pkey_id[SSL_MD_NUM_IDX]={
+	EVP_PKEY_HMAC,EVP_PKEY_HMAC,EVP_PKEY_HMAC,NID_undef
+	};
+
+static int ssl_mac_secret_size[SSL_MD_NUM_IDX]={
+	0,0,0,0
+	};
+
+static int ssl_handshake_digest_flag[SSL_MD_NUM_IDX]={
+	SSL_HANDSHAKE_MAC_MD5,SSL_HANDSHAKE_MAC_SHA,
+	SSL_HANDSHAKE_MAC_GOST94,0
+	};
+
+#define CIPHER_ADD	1
+#define CIPHER_KILL	2
+#define CIPHER_DEL	3
+#define CIPHER_ORD	4
+#define CIPHER_SPECIAL	5
+
+typedef struct cipher_order_st
+	{
+	const SSL_CIPHER *cipher;
+	int active;
+	int dead;
+	struct cipher_order_st *next,*prev;
+	} CIPHER_ORDER;
+
+static const SSL_CIPHER cipher_aliases[]={
+	/* "ALL" doesn't include eNULL (must be specifically enabled) */
+	{0,SSL_TXT_ALL,0,     0,0,~SSL_eNULL,0,0,0,0,0,0},
+	/* "COMPLEMENTOFALL" */
+	{0,SSL_TXT_CMPALL,0,  0,0,SSL_eNULL,0,0,0,0,0,0},
+
+	/* "COMPLEMENTOFDEFAULT" (does *not* include ciphersuites not found in ALL!) */
+	{0,SSL_TXT_CMPDEF,0,  SSL_kEDH|SSL_kEECDH,SSL_aNULL,~SSL_eNULL,0,0,0,0,0,0},
+
+	/* key exchange aliases
+	 * (some of those using only a single bit here combine
+	 * multiple key exchange algs according to the RFCs,
+	 * e.g. kEDH combines DHE_DSS and DHE_RSA) */
+	{0,SSL_TXT_kRSA,0,    SSL_kRSA,  0,0,0,0,0,0,0,0},
+
+	{0,SSL_TXT_kDHr,0,    SSL_kDHr,  0,0,0,0,0,0,0,0}, /* no such ciphersuites supported! */
+	{0,SSL_TXT_kDHd,0,    SSL_kDHd,  0,0,0,0,0,0,0,0}, /* no such ciphersuites supported! */
+	{0,SSL_TXT_kDH,0,     SSL_kDHr|SSL_kDHd,0,0,0,0,0,0,0,0}, /* no such ciphersuites supported! */
+	{0,SSL_TXT_kEDH,0,    SSL_kEDH,  0,0,0,0,0,0,0,0},
+	{0,SSL_TXT_DH,0,      SSL_kDHr|SSL_kDHd|SSL_kEDH,0,0,0,0,0,0,0,0},
+
+	{0,SSL_TXT_kKRB5,0,   SSL_kKRB5, 0,0,0,0,0,0,0,0},
+
+	{0,SSL_TXT_kECDHr,0,  SSL_kECDHr,0,0,0,0,0,0,0,0},
+	{0,SSL_TXT_kECDHe,0,  SSL_kECDHe,0,0,0,0,0,0,0,0},
+	{0,SSL_TXT_kECDH,0,   SSL_kECDHr|SSL_kECDHe,0,0,0,0,0,0,0,0},
+	{0,SSL_TXT_kEECDH,0,  SSL_kEECDH,0,0,0,0,0,0,0,0},
+	{0,SSL_TXT_ECDH,0,    SSL_kECDHr|SSL_kECDHe|SSL_kEECDH,0,0,0,0,0,0,0,0},
+
+        {0,SSL_TXT_kPSK,0,    SSL_kPSK,  0,0,0,0,0,0,0,0},
+	{0,SSL_TXT_kGOST,0, SSL_kGOST,0,0,0,0,0,0,0,0},
+
+	/* server authentication aliases */
+	{0,SSL_TXT_aRSA,0,    0,SSL_aRSA,  0,0,0,0,0,0,0},
+	{0,SSL_TXT_aDSS,0,    0,SSL_aDSS,  0,0,0,0,0,0,0},
+	{0,SSL_TXT_DSS,0,     0,SSL_aDSS,   0,0,0,0,0,0,0},
+	{0,SSL_TXT_aKRB5,0,   0,SSL_aKRB5, 0,0,0,0,0,0,0},
+	{0,SSL_TXT_aNULL,0,   0,SSL_aNULL, 0,0,0,0,0,0,0},
+	{0,SSL_TXT_aDH,0,     0,SSL_aDH,   0,0,0,0,0,0,0}, /* no such ciphersuites supported! */
+	{0,SSL_TXT_aECDH,0,   0,SSL_aECDH, 0,0,0,0,0,0,0},
+	{0,SSL_TXT_aECDSA,0,  0,SSL_aECDSA,0,0,0,0,0,0,0},
+	{0,SSL_TXT_ECDSA,0,   0,SSL_aECDSA, 0,0,0,0,0,0,0},
+        {0,SSL_TXT_aPSK,0,    0,SSL_aPSK,  0,0,0,0,0,0,0},
+	{0,SSL_TXT_aGOST94,0,0,SSL_aGOST94,0,0,0,0,0,0,0},
+	{0,SSL_TXT_aGOST01,0,0,SSL_aGOST01,0,0,0,0,0,0,0},
+	{0,SSL_TXT_aGOST,0,0,SSL_aGOST94|SSL_aGOST01,0,0,0,0,0,0,0},
+
+	/* aliases combining key exchange and server authentication */
+	{0,SSL_TXT_EDH,0,     SSL_kEDH,~SSL_aNULL,0,0,0,0,0,0,0},
+	{0,SSL_TXT_EECDH,0,   SSL_kEECDH,~SSL_aNULL,0,0,0,0,0,0,0},
+	{0,SSL_TXT_NULL,0,    0,0,SSL_eNULL, 0,0,0,0,0,0},
+	{0,SSL_TXT_KRB5,0,    SSL_kKRB5,SSL_aKRB5,0,0,0,0,0,0,0},
+	{0,SSL_TXT_RSA,0,     SSL_kRSA,SSL_aRSA,0,0,0,0,0,0,0},
+	{0,SSL_TXT_ADH,0,     SSL_kEDH,SSL_aNULL,0,0,0,0,0,0,0},
+	{0,SSL_TXT_AECDH,0,   SSL_kEECDH,SSL_aNULL,0,0,0,0,0,0,0},
+        {0,SSL_TXT_PSK,0,     SSL_kPSK,SSL_aPSK,0,0,0,0,0,0,0},
+
+
+	/* symmetric encryption aliases */
+	{0,SSL_TXT_DES,0,     0,0,SSL_DES,   0,0,0,0,0,0},
+	{0,SSL_TXT_3DES,0,    0,0,SSL_3DES,  0,0,0,0,0,0},
+	{0,SSL_TXT_RC4,0,     0,0,SSL_RC4,   0,0,0,0,0,0},
+	{0,SSL_TXT_RC2,0,     0,0,SSL_RC2,   0,0,0,0,0,0},
+	{0,SSL_TXT_IDEA,0,    0,0,SSL_IDEA,  0,0,0,0,0,0},
+	{0,SSL_TXT_SEED,0,    0,0,SSL_SEED,  0,0,0,0,0,0},
+	{0,SSL_TXT_eNULL,0,   0,0,SSL_eNULL, 0,0,0,0,0,0},
+	{0,SSL_TXT_AES128,0,  0,0,SSL_AES128,0,0,0,0,0,0},
+	{0,SSL_TXT_AES256,0,  0,0,SSL_AES256,0,0,0,0,0,0},
+	{0,SSL_TXT_AES,0,     0,0,SSL_AES128|SSL_AES256,0,0,0,0,0,0},
+	{0,SSL_TXT_CAMELLIA128,0,0,0,SSL_CAMELLIA128,0,0,0,0,0,0},
+	{0,SSL_TXT_CAMELLIA256,0,0,0,SSL_CAMELLIA256,0,0,0,0,0,0},
+	{0,SSL_TXT_CAMELLIA   ,0,0,0,SSL_CAMELLIA128|SSL_CAMELLIA256,0,0,0,0,0,0},
+
+	/* MAC aliases */	
+	{0,SSL_TXT_MD5,0,     0,0,0,SSL_MD5,   0,0,0,0,0},
+	{0,SSL_TXT_SHA1,0,    0,0,0,SSL_SHA1,  0,0,0,0,0},
+	{0,SSL_TXT_SHA,0,     0,0,0,SSL_SHA1,  0,0,0,0,0},
+	{0,SSL_TXT_GOST94,0,     0,0,0,SSL_GOST94,  0,0,0,0,0},
+	{0,SSL_TXT_GOST89MAC,0,     0,0,0,SSL_GOST89MAC,  0,0,0,0,0},
+
+	/* protocol version aliases */
+	{0,SSL_TXT_SSLV2,0,   0,0,0,0,SSL_SSLV2, 0,0,0,0},
+	{0,SSL_TXT_SSLV3,0,   0,0,0,0,SSL_SSLV3, 0,0,0,0},
+	{0,SSL_TXT_TLSV1,0,   0,0,0,0,SSL_TLSV1, 0,0,0,0},
+
+	/* export flag */
+	{0,SSL_TXT_EXP,0,     0,0,0,0,0,SSL_EXPORT,0,0,0},
+	{0,SSL_TXT_EXPORT,0,  0,0,0,0,0,SSL_EXPORT,0,0,0},
+
+	/* strength classes */
+	{0,SSL_TXT_EXP40,0,   0,0,0,0,0,SSL_EXP40, 0,0,0},
+	{0,SSL_TXT_EXP56,0,   0,0,0,0,0,SSL_EXP56, 0,0,0},
+	{0,SSL_TXT_LOW,0,     0,0,0,0,0,SSL_LOW,   0,0,0},
+	{0,SSL_TXT_MEDIUM,0,  0,0,0,0,0,SSL_MEDIUM,0,0,0},
+	{0,SSL_TXT_HIGH,0,    0,0,0,0,0,SSL_HIGH,  0,0,0},
+	/* FIPS 140-2 approved ciphersuite */
+	{0,SSL_TXT_FIPS,0,    0,0,~SSL_eNULL,0,0,SSL_FIPS,  0,0,0},
+	};
+/* Search for public key algorithm with given name and 
+ * return its pkey_id if it is available. Otherwise return 0
+ */
+#ifdef OPENSSL_NO_ENGINE
+
+static int get_optional_pkey_id(const char *pkey_name)
+	{
+	const EVP_PKEY_ASN1_METHOD *ameth;
+	int pkey_id=0;
+	ameth = EVP_PKEY_asn1_find_str(NULL,pkey_name,-1);
+	if (ameth) 
+		{
+		EVP_PKEY_asn1_get0_info(&pkey_id, NULL,NULL,NULL,NULL,ameth);
+		}		
+	return pkey_id;
+	}
+
+#else
+
+static int get_optional_pkey_id(const char *pkey_name)
+	{
+	const EVP_PKEY_ASN1_METHOD *ameth;
+	ENGINE *tmpeng = NULL;
+	int pkey_id=0;
+	ameth = EVP_PKEY_asn1_find_str(&tmpeng,pkey_name,-1);
+	if (ameth)
+		{
+		EVP_PKEY_asn1_get0_info(&pkey_id, NULL,NULL,NULL,NULL,ameth);
+		}
+	if (tmpeng) ENGINE_finish(tmpeng);
+	return pkey_id;
+	}
+
+#endif
+
+void ssl_load_ciphers(void)
+	{
+	ssl_cipher_methods[SSL_ENC_DES_IDX]= 
+		EVP_get_cipherbyname(SN_des_cbc);
+	ssl_cipher_methods[SSL_ENC_3DES_IDX]=
+		EVP_get_cipherbyname(SN_des_ede3_cbc);
+	ssl_cipher_methods[SSL_ENC_RC4_IDX]=
+		EVP_get_cipherbyname(SN_rc4);
+	ssl_cipher_methods[SSL_ENC_RC2_IDX]= 
+		EVP_get_cipherbyname(SN_rc2_cbc);
+#ifndef OPENSSL_NO_IDEA
+	ssl_cipher_methods[SSL_ENC_IDEA_IDX]= 
+		EVP_get_cipherbyname(SN_idea_cbc);
+#else
+	ssl_cipher_methods[SSL_ENC_IDEA_IDX]= NULL;
+#endif
+	ssl_cipher_methods[SSL_ENC_AES128_IDX]=
+	  EVP_get_cipherbyname(SN_aes_128_cbc);
+	ssl_cipher_methods[SSL_ENC_AES256_IDX]=
+	  EVP_get_cipherbyname(SN_aes_256_cbc);
+	ssl_cipher_methods[SSL_ENC_CAMELLIA128_IDX]=
+	  EVP_get_cipherbyname(SN_camellia_128_cbc);
+	ssl_cipher_methods[SSL_ENC_CAMELLIA256_IDX]=
+	  EVP_get_cipherbyname(SN_camellia_256_cbc);
+	ssl_cipher_methods[SSL_ENC_GOST89_IDX]=
+	  EVP_get_cipherbyname(SN_gost89_cnt);
+	ssl_cipher_methods[SSL_ENC_SEED_IDX]=
+	  EVP_get_cipherbyname(SN_seed_cbc);
+
+	ssl_digest_methods[SSL_MD_MD5_IDX]=
+		EVP_get_digestbyname(SN_md5);
+	ssl_mac_secret_size[SSL_MD_MD5_IDX]=
+		EVP_MD_size(ssl_digest_methods[SSL_MD_MD5_IDX]);
+	OPENSSL_assert(ssl_mac_secret_size[SSL_MD_MD5_IDX] >= 0);
+	ssl_digest_methods[SSL_MD_SHA1_IDX]=
+		EVP_get_digestbyname(SN_sha1);
+	ssl_mac_secret_size[SSL_MD_SHA1_IDX]=
+		EVP_MD_size(ssl_digest_methods[SSL_MD_SHA1_IDX]);
+	OPENSSL_assert(ssl_mac_secret_size[SSL_MD_SHA1_IDX] >= 0);
+	ssl_digest_methods[SSL_MD_GOST94_IDX]=
+		EVP_get_digestbyname(SN_id_GostR3411_94);
+	if (ssl_digest_methods[SSL_MD_GOST94_IDX])
+		{	
+		ssl_mac_secret_size[SSL_MD_GOST94_IDX]=
+			EVP_MD_size(ssl_digest_methods[SSL_MD_GOST94_IDX]);
+		OPENSSL_assert(ssl_mac_secret_size[SSL_MD_GOST94_IDX] >= 0);
+		}
+	ssl_digest_methods[SSL_MD_GOST89MAC_IDX]=
+		EVP_get_digestbyname(SN_id_Gost28147_89_MAC);
+		ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX] = get_optional_pkey_id("gost-mac");
+		if (ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX]) {
+			ssl_mac_secret_size[SSL_MD_GOST89MAC_IDX]=32;
+		}		
+
+	}
+#ifndef OPENSSL_NO_COMP
+
+static int sk_comp_cmp(const SSL_COMP * const *a,
+			const SSL_COMP * const *b)
+	{
+	return((*a)->id-(*b)->id);
+	}
+
+static void load_builtin_compressions(void)
+	{
+	int got_write_lock = 0;
+
+	CRYPTO_r_lock(CRYPTO_LOCK_SSL);
+	if (ssl_comp_methods == NULL)
+		{
+		CRYPTO_r_unlock(CRYPTO_LOCK_SSL);
+		CRYPTO_w_lock(CRYPTO_LOCK_SSL);
+		got_write_lock = 1;
+		
+		if (ssl_comp_methods == NULL)
+			{
+			SSL_COMP *comp = NULL;
+
+			MemCheck_off();
+			ssl_comp_methods=sk_SSL_COMP_new(sk_comp_cmp);
+			if (ssl_comp_methods != NULL)
+				{
+				comp=(SSL_COMP *)OPENSSL_malloc(sizeof(SSL_COMP));
+				if (comp != NULL)
+					{
+					comp->method=COMP_zlib();
+					if (comp->method
+						&& comp->method->type == NID_undef)
+						OPENSSL_free(comp);
+					else
+						{
+						comp->id=SSL_COMP_ZLIB_IDX;
+						comp->name=comp->method->name;
+						sk_SSL_COMP_push(ssl_comp_methods,comp);
+						}
+					}
+				}
+			MemCheck_on();
+			}
+		}
+	
+	if (got_write_lock)
+		CRYPTO_w_unlock(CRYPTO_LOCK_SSL);
+	else
+		CRYPTO_r_unlock(CRYPTO_LOCK_SSL);
+	}
+#endif
+
+int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
+	     const EVP_MD **md, int *mac_pkey_type, int *mac_secret_size,SSL_COMP **comp)
+	{
+	int i;
+	const SSL_CIPHER *c;
+
+	c=s->cipher;
+	if (c == NULL) return(0);
+	if (comp != NULL)
+		{
+		SSL_COMP ctmp;
+#ifndef OPENSSL_NO_COMP
+		load_builtin_compressions();
+#endif
+
+		*comp=NULL;
+		ctmp.id=s->compress_meth;
+		if (ssl_comp_methods != NULL)
+			{
+			i=sk_SSL_COMP_find(ssl_comp_methods,&ctmp);
+			if (i >= 0)
+				*comp=sk_SSL_COMP_value(ssl_comp_methods,i);
+			else
+				*comp=NULL;
+			}
+		}
+
+	if ((enc == NULL) || (md == NULL)) return(0);
+
+	switch (c->algorithm_enc)
+		{
+	case SSL_DES:
+		i=SSL_ENC_DES_IDX;
+		break;
+	case SSL_3DES:
+		i=SSL_ENC_3DES_IDX;
+		break;
+	case SSL_RC4:
+		i=SSL_ENC_RC4_IDX;
+		break;
+	case SSL_RC2:
+		i=SSL_ENC_RC2_IDX;
+		break;
+	case SSL_IDEA:
+		i=SSL_ENC_IDEA_IDX;
+		break;
+	case SSL_eNULL:
+		i=SSL_ENC_NULL_IDX;
+		break;
+	case SSL_AES128:
+		i=SSL_ENC_AES128_IDX;
+		break;
+	case SSL_AES256:
+		i=SSL_ENC_AES256_IDX;
+		break;
+	case SSL_CAMELLIA128:
+		i=SSL_ENC_CAMELLIA128_IDX;
+		break;
+	case SSL_CAMELLIA256:
+		i=SSL_ENC_CAMELLIA256_IDX;
+		break;
+	case SSL_eGOST2814789CNT:
+		i=SSL_ENC_GOST89_IDX;
+		break;
+	case SSL_SEED:
+		i=SSL_ENC_SEED_IDX;
+		break;
+	default:
+		i= -1;
+		break;
+		}
+
+	if ((i < 0) || (i > SSL_ENC_NUM_IDX))
+		*enc=NULL;
+	else
+		{
+		if (i == SSL_ENC_NULL_IDX)
+			*enc=EVP_enc_null();
+		else
+			*enc=ssl_cipher_methods[i];
+		}
+
+	switch (c->algorithm_mac)
+		{
+	case SSL_MD5:
+		i=SSL_MD_MD5_IDX;
+		break;
+	case SSL_SHA1:
+		i=SSL_MD_SHA1_IDX;
+		break;
+	case SSL_GOST94:
+		i = SSL_MD_GOST94_IDX;
+		break;
+	case SSL_GOST89MAC:
+		i = SSL_MD_GOST89MAC_IDX;
+		break;
+	default:
+		i= -1;
+		break;
+		}
+	if ((i < 0) || (i > SSL_MD_NUM_IDX))
+	{
+		*md=NULL; 
+		if (mac_pkey_type!=NULL) *mac_pkey_type = NID_undef;
+		if (mac_secret_size!=NULL) *mac_secret_size = 0;
+
+	}
+	else
+	{
+		*md=ssl_digest_methods[i];
+		if (mac_pkey_type!=NULL) *mac_pkey_type = ssl_mac_pkey_id[i];
+		if (mac_secret_size!=NULL) *mac_secret_size = ssl_mac_secret_size[i];
+	}	
+
+	if ((*enc != NULL) && (*md != NULL) && (!mac_pkey_type||*mac_pkey_type != NID_undef))
+		return(1);
+	else
+		return(0);
+	}
+
+int ssl_get_handshake_digest(int idx, long *mask, const EVP_MD **md) 
+{
+	if (idx <0||idx>=SSL_MD_NUM_IDX) 
+		{
+		return 0;
+		}
+	if (ssl_handshake_digest_flag[idx]==0) return 0;
+	*mask = ssl_handshake_digest_flag[idx];
+	*md = ssl_digest_methods[idx];
+	return 1;
+}
+
+#define ITEM_SEP(a) \
+	(((a) == ':') || ((a) == ' ') || ((a) == ';') || ((a) == ','))
+
+static void ll_append_tail(CIPHER_ORDER **head, CIPHER_ORDER *curr,
+	     CIPHER_ORDER **tail)
+	{
+	if (curr == *tail) return;
+	if (curr == *head)
+		*head=curr->next;
+	if (curr->prev != NULL)
+		curr->prev->next=curr->next;
+	if (curr->next != NULL)
+		curr->next->prev=curr->prev;
+	(*tail)->next=curr;
+	curr->prev= *tail;
+	curr->next=NULL;
+	*tail=curr;
+	}
+
+static void ll_append_head(CIPHER_ORDER **head, CIPHER_ORDER *curr,
+	     CIPHER_ORDER **tail)
+	{
+	if (curr == *head) return;
+	if (curr == *tail)
+		*tail=curr->prev;
+	if (curr->next != NULL)
+		curr->next->prev=curr->prev;
+	if (curr->prev != NULL)
+		curr->prev->next=curr->next;
+	(*head)->prev=curr;
+	curr->next= *head;
+	curr->prev=NULL;
+	*head=curr;
+	}
+
+static void ssl_cipher_get_disabled(unsigned long *mkey, unsigned long *auth, unsigned long *enc, unsigned long *mac, unsigned long *ssl)
+	{
+	*mkey = 0;
+	*auth = 0;
+	*enc = 0;
+	*mac = 0;
+	*ssl = 0;
+
+#ifdef OPENSSL_NO_RSA
+	*mkey |= SSL_kRSA;
+	*auth |= SSL_aRSA;
+#endif
+#ifdef OPENSSL_NO_DSA
+	*auth |= SSL_aDSS;
+#endif
+	*mkey |= SSL_kDHr|SSL_kDHd; /* no such ciphersuites supported! */
+	*auth |= SSL_aDH;
+#ifdef OPENSSL_NO_DH
+	*mkey |= SSL_kDHr|SSL_kDHd|SSL_kEDH;
+	*auth |= SSL_aDH;
+#endif
+#ifdef OPENSSL_NO_KRB5
+	*mkey |= SSL_kKRB5;
+	*auth |= SSL_aKRB5;
+#endif
+#ifdef OPENSSL_NO_ECDSA
+	*auth |= SSL_aECDSA;
+#endif
+#ifdef OPENSSL_NO_ECDH
+	*mkey |= SSL_kECDHe|SSL_kECDHr;
+	*auth |= SSL_aECDH;
+#endif
+#ifdef OPENSSL_NO_PSK
+	*mkey |= SSL_kPSK;
+	*auth |= SSL_aPSK;
+#endif
+	/* Check for presence of GOST 34.10 algorithms, and if they
+	 * do not present, disable  appropriate auth and key exchange */
+	if (!get_optional_pkey_id("gost94")) {
+		*auth |= SSL_aGOST94;
+	}
+	if (!get_optional_pkey_id("gost2001")) {
+		*auth |= SSL_aGOST01;
+	}
+	/* Disable GOST key exchange if no GOST signature algs are available * */
+	if ((*auth & (SSL_aGOST94|SSL_aGOST01)) == (SSL_aGOST94|SSL_aGOST01)) {
+		*mkey |= SSL_kGOST;
+	}	
+#ifdef SSL_FORBID_ENULL
+	*enc |= SSL_eNULL;
+#endif
+		
+
+
+	*enc |= (ssl_cipher_methods[SSL_ENC_DES_IDX ] == NULL) ? SSL_DES :0;
+	*enc |= (ssl_cipher_methods[SSL_ENC_3DES_IDX] == NULL) ? SSL_3DES:0;
+	*enc |= (ssl_cipher_methods[SSL_ENC_RC4_IDX ] == NULL) ? SSL_RC4 :0;
+	*enc |= (ssl_cipher_methods[SSL_ENC_RC2_IDX ] == NULL) ? SSL_RC2 :0;
+	*enc |= (ssl_cipher_methods[SSL_ENC_IDEA_IDX] == NULL) ? SSL_IDEA:0;
+	*enc |= (ssl_cipher_methods[SSL_ENC_AES128_IDX] == NULL) ? SSL_AES128:0;
+	*enc |= (ssl_cipher_methods[SSL_ENC_AES256_IDX] == NULL) ? SSL_AES256:0;
+	*enc |= (ssl_cipher_methods[SSL_ENC_CAMELLIA128_IDX] == NULL) ? SSL_CAMELLIA128:0;
+	*enc |= (ssl_cipher_methods[SSL_ENC_CAMELLIA256_IDX] == NULL) ? SSL_CAMELLIA256:0;
+	*enc |= (ssl_cipher_methods[SSL_ENC_GOST89_IDX] == NULL) ? SSL_eGOST2814789CNT:0;
+	*enc |= (ssl_cipher_methods[SSL_ENC_SEED_IDX] == NULL) ? SSL_SEED:0;
+
+	*mac |= (ssl_digest_methods[SSL_MD_MD5_IDX ] == NULL) ? SSL_MD5 :0;
+	*mac |= (ssl_digest_methods[SSL_MD_SHA1_IDX] == NULL) ? SSL_SHA1:0;
+	*mac |= (ssl_digest_methods[SSL_MD_GOST94_IDX] == NULL) ? SSL_GOST94:0;
+	*mac |= (ssl_digest_methods[SSL_MD_GOST89MAC_IDX] == NULL || ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX]==NID_undef)? SSL_GOST89MAC:0;
+
+	}
+
+static void ssl_cipher_collect_ciphers(const SSL_METHOD *ssl_method,
+                int num_of_ciphers,
+                unsigned long disabled_mkey, unsigned long disabled_auth,
+                unsigned long disabled_enc, unsigned long disabled_mac,
+                unsigned long disabled_ssl,
+                CIPHER_ORDER *co_list,
+                CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p)
+	{
+	int i, co_list_num;
+	const SSL_CIPHER *c;
+
+	/*
+	 * We have num_of_ciphers descriptions compiled in, depending on the
+	 * method selected (SSLv2 and/or SSLv3, TLSv1 etc).
+	 * These will later be sorted in a linked list with at most num
+	 * entries.
+	 */
+
+	/* Get the initial list of ciphers */
+	co_list_num = 0;	/* actual count of ciphers */
+	for (i = 0; i < num_of_ciphers; i++)
+		{
+		c = ssl_method->get_cipher(i);
+		/* drop those that use any of that is not available */
+		if ((c != NULL) && c->valid &&
+		    !(c->algorithm_mkey & disabled_mkey) &&
+		    !(c->algorithm_auth & disabled_auth) &&
+		    !(c->algorithm_enc & disabled_enc) &&
+		    !(c->algorithm_mac & disabled_mac) &&
+		    !(c->algorithm_ssl & disabled_ssl))
+			{
+			co_list[co_list_num].cipher = c;
+			co_list[co_list_num].next = NULL;
+			co_list[co_list_num].prev = NULL;
+			co_list[co_list_num].active = 0;
+			co_list_num++;
+#ifdef KSSL_DEBUG
+			printf("\t%d: %s %lx %lx %lx\n",i,c->name,c->id,c->algorithm_mkey,c->algorithm_auth);
+#endif	/* KSSL_DEBUG */
+			/*
+			if (!sk_push(ca_list,(char *)c)) goto err;
+			*/
+			}
+		}
+
+	/*
+	 * Prepare linked list from list entries
+	 */	
+	if (co_list_num > 0)
+		{
+		co_list[0].prev = NULL;
+
+		if (co_list_num > 1)
+			{
+			co_list[0].next = &co_list[1];
+			
+			for (i = 1; i < co_list_num - 1; i++)
+				{
+				co_list[i].prev = &co_list[i - 1];
+				co_list[i].next = &co_list[i + 1];
+				}
+
+			co_list[co_list_num - 1].prev = &co_list[co_list_num - 2];
+			}
+		
+		co_list[co_list_num - 1].next = NULL;
+
+		*head_p = &co_list[0];
+		*tail_p = &co_list[co_list_num - 1];
+		}
+	}
+
+static void ssl_cipher_collect_aliases(const SSL_CIPHER **ca_list,
+                        int num_of_group_aliases,
+                        unsigned long disabled_mkey, unsigned long disabled_auth,
+                        unsigned long disabled_enc, unsigned long disabled_mac,
+                        unsigned long disabled_ssl,
+			CIPHER_ORDER *head)
+	{
+	CIPHER_ORDER *ciph_curr;
+	const SSL_CIPHER **ca_curr;
+	int i;
+	unsigned long mask_mkey = ~disabled_mkey;
+	unsigned long mask_auth = ~disabled_auth;
+	unsigned long mask_enc = ~disabled_enc;
+	unsigned long mask_mac = ~disabled_mac;
+	unsigned long mask_ssl = ~disabled_ssl;
+
+	/*
+	 * First, add the real ciphers as already collected
+	 */
+	ciph_curr = head;
+	ca_curr = ca_list;
+	while (ciph_curr != NULL)
+		{
+		*ca_curr = ciph_curr->cipher;
+		ca_curr++;
+		ciph_curr = ciph_curr->next;
+		}
+
+	/*
+	 * Now we add the available ones from the cipher_aliases[] table.
+	 * They represent either one or more algorithms, some of which
+	 * in any affected category must be supported (set in enabled_mask),
+	 * or represent a cipher strength value (will be added in any case because algorithms=0).
+	 */
+	for (i = 0; i < num_of_group_aliases; i++)
+		{
+		unsigned long algorithm_mkey = cipher_aliases[i].algorithm_mkey;
+		unsigned long algorithm_auth = cipher_aliases[i].algorithm_auth;
+		unsigned long algorithm_enc = cipher_aliases[i].algorithm_enc;
+		unsigned long algorithm_mac = cipher_aliases[i].algorithm_mac;
+		unsigned long algorithm_ssl = cipher_aliases[i].algorithm_ssl;
+
+		if (algorithm_mkey)
+			if ((algorithm_mkey & mask_mkey) == 0)
+				continue;
+	
+		if (algorithm_auth)
+			if ((algorithm_auth & mask_auth) == 0)
+				continue;
+		
+		if (algorithm_enc)
+			if ((algorithm_enc & mask_enc) == 0)
+				continue;
+		
+		if (algorithm_mac)
+			if ((algorithm_mac & mask_mac) == 0)
+				continue;
+		
+		if (algorithm_ssl)
+			if ((algorithm_ssl & mask_ssl) == 0)
+				continue;
+		
+		*ca_curr = (SSL_CIPHER *)(cipher_aliases + i);
+		ca_curr++;
+		}
+
+	*ca_curr = NULL;	/* end of list */
+	}
+
+static void ssl_cipher_apply_rule(unsigned long cipher_id,
+                unsigned long alg_mkey, unsigned long alg_auth,
+                unsigned long alg_enc, unsigned long alg_mac,
+                unsigned long alg_ssl,
+		unsigned long algo_strength,
+		int rule, int strength_bits,
+		CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p)
+	{
+	CIPHER_ORDER *head, *tail, *curr, *curr2, *last;
+	const SSL_CIPHER *cp;
+	int reverse = 0;
+
+#ifdef CIPHER_DEBUG
+	printf("Applying rule %d with %08lx/%08lx/%08lx/%08lx/%08lx %08lx (%d)\n",
+		rule, alg_mkey, alg_auth, alg_enc, alg_mac, alg_ssl, algo_strength, strength_bits);
+#endif
+
+	if (rule == CIPHER_DEL)
+		reverse = 1; /* needed to maintain sorting between currently deleted ciphers */
+
+	head = *head_p;
+	tail = *tail_p;
+
+	if (reverse)
+		{
+		curr = tail;
+		last = head;
+		}
+	else
+		{
+		curr = head;
+		last = tail;
+		}
+
+	curr2 = curr;
+	for (;;)
+		{
+		if ((curr == NULL) || (curr == last)) break;
+		curr = curr2;
+		curr2 = reverse ? curr->prev : curr->next;
+
+		cp = curr->cipher;
+
+		/*
+		 * Selection criteria is either the value of strength_bits
+		 * or the algorithms used.
+		 */
+		if (strength_bits >= 0)
+			{
+			if (strength_bits != cp->strength_bits)
+				continue;
+			}
+		else
+			{
+#ifdef CIPHER_DEBUG
+			printf("\nName: %s:\nAlgo = %08lx/%08lx/%08lx/%08lx/%08lx Algo_strength = %08lx\n", cp->name, cp->algorithm_mkey, cp->algorithm_auth, cp->algorithm_enc, cp->algorithm_mac, cp->algorithm_ssl, cp->algo_strength);
+#endif
+
+			if (alg_mkey && !(alg_mkey & cp->algorithm_mkey))
+				continue;
+			if (alg_auth && !(alg_auth & cp->algorithm_auth))
+				continue;
+			if (alg_enc && !(alg_enc & cp->algorithm_enc))
+				continue;
+			if (alg_mac && !(alg_mac & cp->algorithm_mac))
+				continue;
+			if (alg_ssl && !(alg_ssl & cp->algorithm_ssl))
+				continue;
+			if ((algo_strength & SSL_EXP_MASK) && !(algo_strength & SSL_EXP_MASK & cp->algo_strength))
+				continue;
+			if ((algo_strength & SSL_STRONG_MASK) && !(algo_strength & SSL_STRONG_MASK & cp->algo_strength))
+				continue;
+			}
+
+#ifdef CIPHER_DEBUG
+		printf("Action = %d\n", rule);
+#endif
+
+		/* add the cipher if it has not been added yet. */
+		if (rule == CIPHER_ADD)
+			{
+			/* reverse == 0 */
+			if (!curr->active)
+				{
+				ll_append_tail(&head, curr, &tail);
+				curr->active = 1;
+				}
+			}
+		/* Move the added cipher to this location */
+		else if (rule == CIPHER_ORD)
+			{
+			/* reverse == 0 */
+			if (curr->active)
+				{
+				ll_append_tail(&head, curr, &tail);
+				}
+			}
+		else if	(rule == CIPHER_DEL)
+			{
+			/* reverse == 1 */
+			if (curr->active)
+				{
+				/* most recently deleted ciphersuites get best positions
+				 * for any future CIPHER_ADD (note that the CIPHER_DEL loop
+				 * works in reverse to maintain the order) */
+				ll_append_head(&head, curr, &tail);
+				curr->active = 0;
+				}
+			}
+		else if (rule == CIPHER_KILL)
+			{
+			/* reverse == 0 */
+			if (head == curr)
+				head = curr->next;
+			else
+				curr->prev->next = curr->next;
+			if (tail == curr)
+				tail = curr->prev;
+			curr->active = 0;
+			if (curr->next != NULL)
+				curr->next->prev = curr->prev;
+			if (curr->prev != NULL)
+				curr->prev->next = curr->next;
+			curr->next = NULL;
+			curr->prev = NULL;
+			}
+		}
+
+	*head_p = head;
+	*tail_p = tail;
+	}
+
+static int ssl_cipher_strength_sort(CIPHER_ORDER **head_p,
+				    CIPHER_ORDER **tail_p)
+	{
+	int max_strength_bits, i, *number_uses;
+	CIPHER_ORDER *curr;
+
+	/*
+	 * This routine sorts the ciphers with descending strength. The sorting
+	 * must keep the pre-sorted sequence, so we apply the normal sorting
+	 * routine as '+' movement to the end of the list.
+	 */
+	max_strength_bits = 0;
+	curr = *head_p;
+	while (curr != NULL)
+		{
+		if (curr->active &&
+		    (curr->cipher->strength_bits > max_strength_bits))
+		    max_strength_bits = curr->cipher->strength_bits;
+		curr = curr->next;
+		}
+
+	number_uses = OPENSSL_malloc((max_strength_bits + 1) * sizeof(int));
+	if (!number_uses)
+		{
+		SSLerr(SSL_F_SSL_CIPHER_STRENGTH_SORT,ERR_R_MALLOC_FAILURE);
+		return(0);
+		}
+	memset(number_uses, 0, (max_strength_bits + 1) * sizeof(int));
+
+	/*
+	 * Now find the strength_bits values actually used
+	 */
+	curr = *head_p;
+	while (curr != NULL)
+		{
+		if (curr->active)
+			number_uses[curr->cipher->strength_bits]++;
+		curr = curr->next;
+		}
+	/*
+	 * Go through the list of used strength_bits values in descending
+	 * order.
+	 */
+	for (i = max_strength_bits; i >= 0; i--)
+		if (number_uses[i] > 0)
+			ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ORD, i, head_p, tail_p);
+
+	OPENSSL_free(number_uses);
+	return(1);
+	}
+
+static int ssl_cipher_process_rulestr(const char *rule_str,
+                CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p,
+                const SSL_CIPHER **ca_list)
+	{
+	unsigned long alg_mkey, alg_auth, alg_enc, alg_mac, alg_ssl, algo_strength;
+	const char *l, *start, *buf;
+	int j, multi, found, rule, retval, ok, buflen;
+	unsigned long cipher_id = 0;
+	char ch;
+
+	retval = 1;
+	l = rule_str;
+	for (;;)
+		{
+		ch = *l;
+
+		if (ch == '\0')
+			break;		/* done */
+		if (ch == '-')
+			{ rule = CIPHER_DEL; l++; }
+		else if (ch == '+')
+			{ rule = CIPHER_ORD; l++; }
+		else if (ch == '!')
+			{ rule = CIPHER_KILL; l++; }
+		else if (ch == '@')
+			{ rule = CIPHER_SPECIAL; l++; }
+		else
+			{ rule = CIPHER_ADD; }
+
+		if (ITEM_SEP(ch))
+			{
+			l++;
+			continue;
+			}
+
+		alg_mkey = 0;
+		alg_auth = 0;
+		alg_enc = 0;
+		alg_mac = 0;
+		alg_ssl = 0;
+		algo_strength = 0;
+
+		start=l;
+		for (;;)
+			{
+			ch = *l;
+			buf = l;
+			buflen = 0;
+#ifndef CHARSET_EBCDIC
+			while (	((ch >= 'A') && (ch <= 'Z')) ||
+				((ch >= '0') && (ch <= '9')) ||
+				((ch >= 'a') && (ch <= 'z')) ||
+				 (ch == '-'))
+#else
+			while (	isalnum(ch) || (ch == '-'))
+#endif
+				 {
+				 ch = *(++l);
+				 buflen++;
+				 }
+
+			if (buflen == 0)
+				{
+				/*
+				 * We hit something we cannot deal with,
+				 * it is no command or separator nor
+				 * alphanumeric, so we call this an error.
+				 */
+				SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR,
+				       SSL_R_INVALID_COMMAND);
+				retval = found = 0;
+				l++;
+				break;
+				}
+
+			if (rule == CIPHER_SPECIAL)
+				{
+				found = 0; /* unused -- avoid compiler warning */
+				break;	/* special treatment */
+				}
+
+			/* check for multi-part specification */
+			if (ch == '+')
+				{
+				multi=1;
+				l++;
+				}
+			else
+				multi=0;
+
+			/*
+			 * Now search for the cipher alias in the ca_list. Be careful
+			 * with the strncmp, because the "buflen" limitation
+			 * will make the rule "ADH:SOME" and the cipher
+			 * "ADH-MY-CIPHER" look like a match for buflen=3.
+			 * So additionally check whether the cipher name found
+			 * has the correct length. We can save a strlen() call:
+			 * just checking for the '\0' at the right place is
+			 * sufficient, we have to strncmp() anyway. (We cannot
+			 * use strcmp(), because buf is not '\0' terminated.)
+			 */
+			j = found = 0;
+			cipher_id = 0;
+			while (ca_list[j])
+				{
+				if (!strncmp(buf, ca_list[j]->name, buflen) &&
+				    (ca_list[j]->name[buflen] == '\0'))
+					{
+					found = 1;
+					break;
+					}
+				else
+					j++;
+				}
+
+			if (!found)
+				break;	/* ignore this entry */
+
+			if (ca_list[j]->algorithm_mkey)
+				{
+				if (alg_mkey)
+					{
+					alg_mkey &= ca_list[j]->algorithm_mkey;
+					if (!alg_mkey) { found = 0; break; }
+					}
+				else
+					alg_mkey = ca_list[j]->algorithm_mkey;
+				}
+
+			if (ca_list[j]->algorithm_auth)
+				{
+				if (alg_auth)
+					{
+					alg_auth &= ca_list[j]->algorithm_auth;
+					if (!alg_auth) { found = 0; break; }
+					}
+				else
+					alg_auth = ca_list[j]->algorithm_auth;
+				}
+			
+			if (ca_list[j]->algorithm_enc)
+				{
+				if (alg_enc)
+					{
+					alg_enc &= ca_list[j]->algorithm_enc;
+					if (!alg_enc) { found = 0; break; }
+					}
+				else
+					alg_enc = ca_list[j]->algorithm_enc;
+				}
+						
+			if (ca_list[j]->algorithm_mac)
+				{
+				if (alg_mac)
+					{
+					alg_mac &= ca_list[j]->algorithm_mac;
+					if (!alg_mac) { found = 0; break; }
+					}
+				else
+					alg_mac = ca_list[j]->algorithm_mac;
+				}
+			
+			if (ca_list[j]->algo_strength & SSL_EXP_MASK)
+				{
+				if (algo_strength & SSL_EXP_MASK)
+					{
+					algo_strength &= (ca_list[j]->algo_strength & SSL_EXP_MASK) | ~SSL_EXP_MASK;
+					if (!(algo_strength & SSL_EXP_MASK)) { found = 0; break; }
+					}
+				else
+					algo_strength |= ca_list[j]->algo_strength & SSL_EXP_MASK;
+				}
+
+			if (ca_list[j]->algo_strength & SSL_STRONG_MASK)
+				{
+				if (algo_strength & SSL_STRONG_MASK)
+					{
+					algo_strength &= (ca_list[j]->algo_strength & SSL_STRONG_MASK) | ~SSL_STRONG_MASK;
+					if (!(algo_strength & SSL_STRONG_MASK)) { found = 0; break; }
+					}
+				else
+					algo_strength |= ca_list[j]->algo_strength & SSL_STRONG_MASK;
+				}
+			
+			if (ca_list[j]->valid)
+				{
+				/* explicit ciphersuite found; its protocol version
+				 * does not become part of the search pattern!*/
+
+				cipher_id = ca_list[j]->id;
+				}
+			else
+				{
+				/* not an explicit ciphersuite; only in this case, the
+				 * protocol version is considered part of the search pattern */
+
+				if (ca_list[j]->algorithm_ssl)
+					{
+					if (alg_ssl)
+						{
+						alg_ssl &= ca_list[j]->algorithm_ssl;
+						if (!alg_ssl) { found = 0; break; }
+						}
+					else
+						alg_ssl = ca_list[j]->algorithm_ssl;
+					}
+				}
+			
+			if (!multi) break;
+			}
+
+		/*
+		 * Ok, we have the rule, now apply it
+		 */
+		if (rule == CIPHER_SPECIAL)
+			{	/* special command */
+			ok = 0;
+			if ((buflen == 8) &&
+				!strncmp(buf, "STRENGTH", 8))
+				ok = ssl_cipher_strength_sort(head_p, tail_p);
+			else
+				SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR,
+					SSL_R_INVALID_COMMAND);
+			if (ok == 0)
+				retval = 0;
+			/*
+			 * We do not support any "multi" options
+			 * together with "@", so throw away the
+			 * rest of the command, if any left, until
+			 * end or ':' is found.
+			 */
+			while ((*l != '\0') && !ITEM_SEP(*l))
+				l++;
+			}
+		else if (found)
+			{
+			ssl_cipher_apply_rule(cipher_id,
+				alg_mkey, alg_auth, alg_enc, alg_mac, alg_ssl, algo_strength,
+				rule, -1, head_p, tail_p);
+			}
+		else
+			{
+			while ((*l != '\0') && !ITEM_SEP(*l))
+				l++;
+			}
+		if (*l == '\0') break; /* done */
+		}
+
+	return(retval);
+	}
+
+STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
+		STACK_OF(SSL_CIPHER) **cipher_list,
+		STACK_OF(SSL_CIPHER) **cipher_list_by_id,
+		const char *rule_str)
+	{
+	int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases;
+	unsigned long disabled_mkey, disabled_auth, disabled_enc, disabled_mac, disabled_ssl;
+	STACK_OF(SSL_CIPHER) *cipherstack, *tmp_cipher_list;
+	const char *rule_p;
+	CIPHER_ORDER *co_list = NULL, *head = NULL, *tail = NULL, *curr;
+	const SSL_CIPHER **ca_list = NULL;
+
+	/*
+	 * Return with error if nothing to do.
+	 */
+	if (rule_str == NULL || cipher_list == NULL || cipher_list_by_id == NULL)
+		return NULL;
+
+	/*
+	 * To reduce the work to do we only want to process the compiled
+	 * in algorithms, so we first get the mask of disabled ciphers.
+	 */
+	ssl_cipher_get_disabled(&disabled_mkey, &disabled_auth, &disabled_enc, &disabled_mac, &disabled_ssl);
+
+	/*
+	 * Now we have to collect the available ciphers from the compiled
+	 * in ciphers. We cannot get more than the number compiled in, so
+	 * it is used for allocation.
+	 */
+	num_of_ciphers = ssl_method->num_ciphers();
+#ifdef KSSL_DEBUG
+	printf("ssl_create_cipher_list() for %d ciphers\n", num_of_ciphers);
+#endif    /* KSSL_DEBUG */
+	co_list = (CIPHER_ORDER *)OPENSSL_malloc(sizeof(CIPHER_ORDER) * num_of_ciphers);
+	if (co_list == NULL)
+		{
+		SSLerr(SSL_F_SSL_CREATE_CIPHER_LIST,ERR_R_MALLOC_FAILURE);
+		return(NULL);	/* Failure */
+		}
+
+	ssl_cipher_collect_ciphers(ssl_method, num_of_ciphers,
+	                           disabled_mkey, disabled_auth, disabled_enc, disabled_mac, disabled_ssl,
+	                           co_list, &head, &tail);
+
+
+	/* Now arrange all ciphers by preference: */
+
+	/* Everything else being equal, prefer ephemeral ECDH over other key exchange mechanisms */
+	ssl_cipher_apply_rule(0, SSL_kEECDH, 0, 0, 0, 0, 0, CIPHER_ADD, -1, &head, &tail);
+	ssl_cipher_apply_rule(0, SSL_kEECDH, 0, 0, 0, 0, 0, CIPHER_DEL, -1, &head, &tail);
+
+	/* AES is our preferred symmetric cipher */
+	ssl_cipher_apply_rule(0, 0, 0, SSL_AES, 0, 0, 0, CIPHER_ADD, -1, &head, &tail);
+
+	/* Temporarily enable everything else for sorting */
+	ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ADD, -1, &head, &tail);
+
+	/* Low priority for MD5 */
+	ssl_cipher_apply_rule(0, 0, 0, 0, SSL_MD5, 0, 0, CIPHER_ORD, -1, &head, &tail);
+
+	/* Move anonymous ciphers to the end.  Usually, these will remain disabled.
+	 * (For applications that allow them, they aren't too bad, but we prefer
+	 * authenticated ciphers.) */
+	ssl_cipher_apply_rule(0, 0, SSL_aNULL, 0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail);
+
+	/* Move ciphers without forward secrecy to the end */
+	ssl_cipher_apply_rule(0, 0, SSL_aECDH, 0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail);
+	/* ssl_cipher_apply_rule(0, 0, SSL_aDH, 0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail); */
+	ssl_cipher_apply_rule(0, SSL_kRSA, 0, 0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail);
+	ssl_cipher_apply_rule(0, SSL_kPSK, 0,0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail);
+	ssl_cipher_apply_rule(0, SSL_kKRB5, 0,0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail);
+
+	/* RC4 is sort-of broken -- move the the end */
+	ssl_cipher_apply_rule(0, 0, 0, SSL_RC4, 0, 0, 0, CIPHER_ORD, -1, &head, &tail);
+
+	/* Now sort by symmetric encryption strength.  The above ordering remains
+	 * in force within each class */
+	if (!ssl_cipher_strength_sort(&head, &tail))
+		{
+		OPENSSL_free(co_list);
+		return NULL;
+		}
+
+	/* Now disable everything (maintaining the ordering!) */
+	ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_DEL, -1, &head, &tail);
+
+
+	/*
+	 * We also need cipher aliases for selecting based on the rule_str.
+	 * There might be two types of entries in the rule_str: 1) names
+	 * of ciphers themselves 2) aliases for groups of ciphers.
+	 * For 1) we need the available ciphers and for 2) the cipher
+	 * groups of cipher_aliases added together in one list (otherwise
+	 * we would be happy with just the cipher_aliases table).
+	 */
+	num_of_group_aliases = sizeof(cipher_aliases) / sizeof(SSL_CIPHER);
+	num_of_alias_max = num_of_ciphers + num_of_group_aliases + 1;
+	ca_list = OPENSSL_malloc(sizeof(SSL_CIPHER *) * num_of_alias_max);
+	if (ca_list == NULL)
+		{
+		OPENSSL_free(co_list);
+		SSLerr(SSL_F_SSL_CREATE_CIPHER_LIST,ERR_R_MALLOC_FAILURE);
+		return(NULL);	/* Failure */
+		}
+	ssl_cipher_collect_aliases(ca_list, num_of_group_aliases,
+	                           disabled_mkey, disabled_auth, disabled_enc,
+				   disabled_mac, disabled_ssl, head);
+
+	/*
+	 * If the rule_string begins with DEFAULT, apply the default rule
+	 * before using the (possibly available) additional rules.
+	 */
+	ok = 1;
+	rule_p = rule_str;
+	if (strncmp(rule_str,"DEFAULT",7) == 0)
+		{
+		ok = ssl_cipher_process_rulestr(SSL_DEFAULT_CIPHER_LIST,
+			&head, &tail, ca_list);
+		rule_p += 7;
+		if (*rule_p == ':')
+			rule_p++;
+		}
+
+	if (ok && (strlen(rule_p) > 0))
+		ok = ssl_cipher_process_rulestr(rule_p, &head, &tail, ca_list);
+
+	OPENSSL_free((void *)ca_list);	/* Not needed anymore */
+
+	if (!ok)
+		{	/* Rule processing failure */
+		OPENSSL_free(co_list);
+		return(NULL);
+		}
+	
+	/*
+	 * Allocate new "cipherstack" for the result, return with error
+	 * if we cannot get one.
+	 */
+	if ((cipherstack = sk_SSL_CIPHER_new_null()) == NULL)
+		{
+		OPENSSL_free(co_list);
+		return(NULL);
+		}
+
+	/*
+	 * The cipher selection for the list is done. The ciphers are added
+	 * to the resulting precedence to the STACK_OF(SSL_CIPHER).
+	 */
+	for (curr = head; curr != NULL; curr = curr->next)
+		{
+		if (curr->active)
+			{
+			sk_SSL_CIPHER_push(cipherstack, curr->cipher);
+#ifdef CIPHER_DEBUG
+			printf("<%s>\n",curr->cipher->name);
+#endif
+			}
+		}
+	OPENSSL_free(co_list);	/* Not needed any longer */
+
+	tmp_cipher_list = sk_SSL_CIPHER_dup(cipherstack);
+	if (tmp_cipher_list == NULL)
+		{
+		sk_SSL_CIPHER_free(cipherstack);
+		return NULL;
+		}
+	if (*cipher_list != NULL)
+		sk_SSL_CIPHER_free(*cipher_list);
+	*cipher_list = cipherstack;
+	if (*cipher_list_by_id != NULL)
+		sk_SSL_CIPHER_free(*cipher_list_by_id);
+	*cipher_list_by_id = tmp_cipher_list;
+	(void)sk_SSL_CIPHER_set_cmp_func(*cipher_list_by_id,ssl_cipher_ptr_id_cmp);
+
+	sk_SSL_CIPHER_sort(*cipher_list_by_id);
+	return(cipherstack);
+	}
+
+char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len)
+	{
+	int is_export,pkl,kl;
+	const char *ver,*exp_str;
+	const char *kx,*au,*enc,*mac;
+	unsigned long alg_mkey,alg_auth,alg_enc,alg_mac,alg_ssl,alg2,alg_s;
+#ifdef KSSL_DEBUG
+	static const char *format="%-23s %s Kx=%-8s Au=%-4s Enc=%-9s Mac=%-4s%s AL=%lx/%lx/%lx/%lx/%lx\n";
+#else
+	static const char *format="%-23s %s Kx=%-8s Au=%-4s Enc=%-9s Mac=%-4s%s\n";
+#endif /* KSSL_DEBUG */
+
+	alg_mkey = cipher->algorithm_mkey;
+	alg_auth = cipher->algorithm_auth;
+	alg_enc = cipher->algorithm_enc;
+	alg_mac = cipher->algorithm_mac;
+	alg_ssl = cipher->algorithm_ssl;
+
+	alg_s=cipher->algo_strength;
+	alg2=cipher->algorithm2;
+
+	is_export=SSL_C_IS_EXPORT(cipher);
+	pkl=SSL_C_EXPORT_PKEYLENGTH(cipher);
+	kl=SSL_C_EXPORT_KEYLENGTH(cipher);
+	exp_str=is_export?" export":"";
+	
+	if (alg_ssl & SSL_SSLV2)
+		ver="SSLv2";
+	else if (alg_ssl & SSL_SSLV3)
+		ver="SSLv3";
+	else
+		ver="unknown";
+
+	switch (alg_mkey)
+		{
+	case SSL_kRSA:
+		kx=is_export?(pkl == 512 ? "RSA(512)" : "RSA(1024)"):"RSA";
+		break;
+	case SSL_kDHr:
+		kx="DH/RSA";
+		break;
+	case SSL_kDHd:
+		kx="DH/DSS";
+		break;
+        case SSL_kKRB5:
+		kx="KRB5";
+		break;
+	case SSL_kEDH:
+		kx=is_export?(pkl == 512 ? "DH(512)" : "DH(1024)"):"DH";
+		break;
+	case SSL_kECDHr:
+		kx="ECDH/RSA";
+		break;
+	case SSL_kECDHe:
+		kx="ECDH/ECDSA";
+		break;
+	case SSL_kEECDH:
+		kx="ECDH";
+		break;
+	case SSL_kPSK:
+		kx="PSK";
+		break;
+	default:
+		kx="unknown";
+		}
+
+	switch (alg_auth)
+		{
+	case SSL_aRSA:
+		au="RSA";
+		break;
+	case SSL_aDSS:
+		au="DSS";
+		break;
+	case SSL_aDH:
+		au="DH";
+		break;
+        case SSL_aKRB5:
+		au="KRB5";
+		break;
+        case SSL_aECDH:
+		au="ECDH";
+		break;
+	case SSL_aNULL:
+		au="None";
+		break;
+	case SSL_aECDSA:
+		au="ECDSA";
+		break;
+	case SSL_aPSK:
+		au="PSK";
+		break;
+	default:
+		au="unknown";
+		break;
+		}
+
+	switch (alg_enc)
+		{
+	case SSL_DES:
+		enc=(is_export && kl == 5)?"DES(40)":"DES(56)";
+		break;
+	case SSL_3DES:
+		enc="3DES(168)";
+		break;
+	case SSL_RC4:
+		enc=is_export?(kl == 5 ? "RC4(40)" : "RC4(56)")
+		  :((alg2&SSL2_CF_8_BYTE_ENC)?"RC4(64)":"RC4(128)");
+		break;
+	case SSL_RC2:
+		enc=is_export?(kl == 5 ? "RC2(40)" : "RC2(56)"):"RC2(128)";
+		break;
+	case SSL_IDEA:
+		enc="IDEA(128)";
+		break;
+	case SSL_eNULL:
+		enc="None";
+		break;
+	case SSL_AES128:
+		enc="AES(128)";
+		break;
+	case SSL_AES256:
+		enc="AES(256)";
+		break;
+	case SSL_CAMELLIA128:
+		enc="Camellia(128)";
+		break;
+	case SSL_CAMELLIA256:
+		enc="Camellia(256)";
+		break;
+	case SSL_SEED:
+		enc="SEED(128)";
+		break;
+	default:
+		enc="unknown";
+		break;
+		}
+
+	switch (alg_mac)
+		{
+	case SSL_MD5:
+		mac="MD5";
+		break;
+	case SSL_SHA1:
+		mac="SHA1";
+		break;
+	default:
+		mac="unknown";
+		break;
+		}
+
+	if (buf == NULL)
+		{
+		len=128;
+		buf=OPENSSL_malloc(len);
+		if (buf == NULL) return("OPENSSL_malloc Error");
+		}
+	else if (len < 128)
+		return("Buffer too small");
+
+#ifdef KSSL_DEBUG
+	BIO_snprintf(buf,len,format,cipher->name,ver,kx,au,enc,mac,exp_str,alg_mkey,alg_auth,alg_enc,alg_mac,alg_ssl);
+#else
+	BIO_snprintf(buf,len,format,cipher->name,ver,kx,au,enc,mac,exp_str);
+#endif /* KSSL_DEBUG */
+	return(buf);
+	}
+
+char *SSL_CIPHER_get_version(const SSL_CIPHER *c)
+	{
+	int i;
+
+	if (c == NULL) return("(NONE)");
+	i=(int)(c->id>>24L);
+	if (i == 3)
+		return("TLSv1/SSLv3");
+	else if (i == 2)
+		return("SSLv2");
+	else
+		return("unknown");
+	}
+
+/* return the actual cipher being used */
+const char *SSL_CIPHER_get_name(const SSL_CIPHER *c)
+	{
+	if (c != NULL)
+		return(c->name);
+	return("(NONE)");
+	}
+
+/* number of bits for symmetric cipher */
+int SSL_CIPHER_get_bits(const SSL_CIPHER *c, int *alg_bits)
+	{
+	int ret=0;
+
+	if (c != NULL)
+		{
+		if (alg_bits != NULL) *alg_bits = c->alg_bits;
+		ret = c->strength_bits;
+		}
+	return(ret);
+	}
+
+SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n)
+	{
+	SSL_COMP *ctmp;
+	int i,nn;
+
+	if ((n == 0) || (sk == NULL)) return(NULL);
+	nn=sk_SSL_COMP_num(sk);
+	for (i=0; i<nn; i++)
+		{
+		ctmp=sk_SSL_COMP_value(sk,i);
+		if (ctmp->id == n)
+			return(ctmp);
+		}
+	return(NULL);
+	}
+
+#ifdef OPENSSL_NO_COMP
+void *SSL_COMP_get_compression_methods(void)
+	{
+	return NULL;
+	}
+int SSL_COMP_add_compression_method(int id, void *cm)
+	{
+	return 1;
+	}
+
+const char *SSL_COMP_get_name(const void *comp)
+	{
+	return NULL;
+	}
+#else
+STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void)
+	{
+	load_builtin_compressions();
+	return(ssl_comp_methods);
+	}
+
+int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm)
+	{
+	SSL_COMP *comp;
+
+        if (cm == NULL || cm->type == NID_undef)
+                return 1;
+
+	/* According to draft-ietf-tls-compression-04.txt, the
+	   compression number ranges should be the following:
+
+	   0 to 63:    methods defined by the IETF
+	   64 to 192:  external party methods assigned by IANA
+	   193 to 255: reserved for private use */
+	if (id < 193 || id > 255)
+		{
+		SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD,SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE);
+		return 0;
+		}
+
+	MemCheck_off();
+	comp=(SSL_COMP *)OPENSSL_malloc(sizeof(SSL_COMP));
+	comp->id=id;
+	comp->method=cm;
+	load_builtin_compressions();
+	if (ssl_comp_methods
+		&& sk_SSL_COMP_find(ssl_comp_methods,comp) >= 0)
+		{
+		OPENSSL_free(comp);
+		MemCheck_on();
+		SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD,SSL_R_DUPLICATE_COMPRESSION_ID);
+		return(1);
+		}
+	else if ((ssl_comp_methods == NULL)
+		|| !sk_SSL_COMP_push(ssl_comp_methods,comp))
+		{
+		OPENSSL_free(comp);
+		MemCheck_on();
+		SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD,ERR_R_MALLOC_FAILURE);
+		return(1);
+		}
+	else
+		{
+		MemCheck_on();
+		return(0);
+		}
+	}
+
+const char *SSL_COMP_get_name(const COMP_METHOD *comp)
+	{
+	if (comp)
+		return comp->name;
+	return NULL;
+	}
+
+#endif
diff --git a/lib/openssl/ssl/ssl_err.c b/lib/openssl/ssl/ssl_err.c
new file mode 100644
index 0000000..34f7db7
--- /dev/null
+++ b/lib/openssl/ssl/ssl_err.c
@@ -0,0 +1,572 @@
+/* ssl/ssl_err.c */
+/* ====================================================================
+ * Copyright (c) 1999-2009 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/* NOTE: this file was auto generated by the mkerr.pl script: any changes
+ * made to it will be overwritten when the script next updates this file,
+ * only reason strings will be preserved.
+ */
+
+#include <stdio.h>
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+
+/* BEGIN ERROR CODES */
+#ifndef OPENSSL_NO_ERR
+
+#define ERR_FUNC(func) ERR_PACK(ERR_LIB_SSL,func,0)
+#define ERR_REASON(reason) ERR_PACK(ERR_LIB_SSL,0,reason)
+
+static ERR_STRING_DATA SSL_str_functs[]=
+	{
+{ERR_FUNC(SSL_F_CLIENT_CERTIFICATE),	"CLIENT_CERTIFICATE"},
+{ERR_FUNC(SSL_F_CLIENT_FINISHED),	"CLIENT_FINISHED"},
+{ERR_FUNC(SSL_F_CLIENT_HELLO),	"CLIENT_HELLO"},
+{ERR_FUNC(SSL_F_CLIENT_MASTER_KEY),	"CLIENT_MASTER_KEY"},
+{ERR_FUNC(SSL_F_D2I_SSL_SESSION),	"d2i_SSL_SESSION"},
+{ERR_FUNC(SSL_F_DO_DTLS1_WRITE),	"DO_DTLS1_WRITE"},
+{ERR_FUNC(SSL_F_DO_SSL3_WRITE),	"DO_SSL3_WRITE"},
+{ERR_FUNC(SSL_F_DTLS1_ACCEPT),	"DTLS1_ACCEPT"},
+{ERR_FUNC(SSL_F_DTLS1_ADD_CERT_TO_BUF),	"DTLS1_ADD_CERT_TO_BUF"},
+{ERR_FUNC(SSL_F_DTLS1_BUFFER_RECORD),	"DTLS1_BUFFER_RECORD"},
+{ERR_FUNC(SSL_F_DTLS1_CLIENT_HELLO),	"DTLS1_CLIENT_HELLO"},
+{ERR_FUNC(SSL_F_DTLS1_CONNECT),	"DTLS1_CONNECT"},
+{ERR_FUNC(SSL_F_DTLS1_ENC),	"DTLS1_ENC"},
+{ERR_FUNC(SSL_F_DTLS1_GET_HELLO_VERIFY),	"DTLS1_GET_HELLO_VERIFY"},
+{ERR_FUNC(SSL_F_DTLS1_GET_MESSAGE),	"DTLS1_GET_MESSAGE"},
+{ERR_FUNC(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT),	"DTLS1_GET_MESSAGE_FRAGMENT"},
+{ERR_FUNC(SSL_F_DTLS1_GET_RECORD),	"DTLS1_GET_RECORD"},
+{ERR_FUNC(SSL_F_DTLS1_HANDLE_TIMEOUT),	"DTLS1_HANDLE_TIMEOUT"},
+{ERR_FUNC(SSL_F_DTLS1_OUTPUT_CERT_CHAIN),	"DTLS1_OUTPUT_CERT_CHAIN"},
+{ERR_FUNC(SSL_F_DTLS1_PREPROCESS_FRAGMENT),	"DTLS1_PREPROCESS_FRAGMENT"},
+{ERR_FUNC(SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE),	"DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE"},
+{ERR_FUNC(SSL_F_DTLS1_PROCESS_RECORD),	"DTLS1_PROCESS_RECORD"},
+{ERR_FUNC(SSL_F_DTLS1_READ_BYTES),	"DTLS1_READ_BYTES"},
+{ERR_FUNC(SSL_F_DTLS1_READ_FAILED),	"DTLS1_READ_FAILED"},
+{ERR_FUNC(SSL_F_DTLS1_SEND_CERTIFICATE_REQUEST),	"DTLS1_SEND_CERTIFICATE_REQUEST"},
+{ERR_FUNC(SSL_F_DTLS1_SEND_CLIENT_CERTIFICATE),	"DTLS1_SEND_CLIENT_CERTIFICATE"},
+{ERR_FUNC(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE),	"DTLS1_SEND_CLIENT_KEY_EXCHANGE"},
+{ERR_FUNC(SSL_F_DTLS1_SEND_CLIENT_VERIFY),	"DTLS1_SEND_CLIENT_VERIFY"},
+{ERR_FUNC(SSL_F_DTLS1_SEND_HELLO_VERIFY_REQUEST),	"DTLS1_SEND_HELLO_VERIFY_REQUEST"},
+{ERR_FUNC(SSL_F_DTLS1_SEND_SERVER_CERTIFICATE),	"DTLS1_SEND_SERVER_CERTIFICATE"},
+{ERR_FUNC(SSL_F_DTLS1_SEND_SERVER_HELLO),	"DTLS1_SEND_SERVER_HELLO"},
+{ERR_FUNC(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE),	"DTLS1_SEND_SERVER_KEY_EXCHANGE"},
+{ERR_FUNC(SSL_F_DTLS1_WRITE_APP_DATA_BYTES),	"DTLS1_WRITE_APP_DATA_BYTES"},
+{ERR_FUNC(SSL_F_GET_CLIENT_FINISHED),	"GET_CLIENT_FINISHED"},
+{ERR_FUNC(SSL_F_GET_CLIENT_HELLO),	"GET_CLIENT_HELLO"},
+{ERR_FUNC(SSL_F_GET_CLIENT_MASTER_KEY),	"GET_CLIENT_MASTER_KEY"},
+{ERR_FUNC(SSL_F_GET_SERVER_FINISHED),	"GET_SERVER_FINISHED"},
+{ERR_FUNC(SSL_F_GET_SERVER_HELLO),	"GET_SERVER_HELLO"},
+{ERR_FUNC(SSL_F_GET_SERVER_VERIFY),	"GET_SERVER_VERIFY"},
+{ERR_FUNC(SSL_F_I2D_SSL_SESSION),	"i2d_SSL_SESSION"},
+{ERR_FUNC(SSL_F_READ_N),	"READ_N"},
+{ERR_FUNC(SSL_F_REQUEST_CERTIFICATE),	"REQUEST_CERTIFICATE"},
+{ERR_FUNC(SSL_F_SERVER_FINISH),	"SERVER_FINISH"},
+{ERR_FUNC(SSL_F_SERVER_HELLO),	"SERVER_HELLO"},
+{ERR_FUNC(SSL_F_SERVER_VERIFY),	"SERVER_VERIFY"},
+{ERR_FUNC(SSL_F_SSL23_ACCEPT),	"SSL23_ACCEPT"},
+{ERR_FUNC(SSL_F_SSL23_CLIENT_HELLO),	"SSL23_CLIENT_HELLO"},
+{ERR_FUNC(SSL_F_SSL23_CONNECT),	"SSL23_CONNECT"},
+{ERR_FUNC(SSL_F_SSL23_GET_CLIENT_HELLO),	"SSL23_GET_CLIENT_HELLO"},
+{ERR_FUNC(SSL_F_SSL23_GET_SERVER_HELLO),	"SSL23_GET_SERVER_HELLO"},
+{ERR_FUNC(SSL_F_SSL23_PEEK),	"SSL23_PEEK"},
+{ERR_FUNC(SSL_F_SSL23_READ),	"SSL23_READ"},
+{ERR_FUNC(SSL_F_SSL23_WRITE),	"SSL23_WRITE"},
+{ERR_FUNC(SSL_F_SSL2_ACCEPT),	"SSL2_ACCEPT"},
+{ERR_FUNC(SSL_F_SSL2_CONNECT),	"SSL2_CONNECT"},
+{ERR_FUNC(SSL_F_SSL2_ENC_INIT),	"SSL2_ENC_INIT"},
+{ERR_FUNC(SSL_F_SSL2_GENERATE_KEY_MATERIAL),	"SSL2_GENERATE_KEY_MATERIAL"},
+{ERR_FUNC(SSL_F_SSL2_PEEK),	"SSL2_PEEK"},
+{ERR_FUNC(SSL_F_SSL2_READ),	"SSL2_READ"},
+{ERR_FUNC(SSL_F_SSL2_READ_INTERNAL),	"SSL2_READ_INTERNAL"},
+{ERR_FUNC(SSL_F_SSL2_SET_CERTIFICATE),	"SSL2_SET_CERTIFICATE"},
+{ERR_FUNC(SSL_F_SSL2_WRITE),	"SSL2_WRITE"},
+{ERR_FUNC(SSL_F_SSL3_ACCEPT),	"SSL3_ACCEPT"},
+{ERR_FUNC(SSL_F_SSL3_ADD_CERT_TO_BUF),	"SSL3_ADD_CERT_TO_BUF"},
+{ERR_FUNC(SSL_F_SSL3_CALLBACK_CTRL),	"SSL3_CALLBACK_CTRL"},
+{ERR_FUNC(SSL_F_SSL3_CHANGE_CIPHER_STATE),	"SSL3_CHANGE_CIPHER_STATE"},
+{ERR_FUNC(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM),	"SSL3_CHECK_CERT_AND_ALGORITHM"},
+{ERR_FUNC(SSL_F_SSL3_CLIENT_HELLO),	"SSL3_CLIENT_HELLO"},
+{ERR_FUNC(SSL_F_SSL3_CONNECT),	"SSL3_CONNECT"},
+{ERR_FUNC(SSL_F_SSL3_CTRL),	"SSL3_CTRL"},
+{ERR_FUNC(SSL_F_SSL3_CTX_CTRL),	"SSL3_CTX_CTRL"},
+{ERR_FUNC(SSL_F_SSL3_DIGEST_CACHED_RECORDS),	"SSL3_DIGEST_CACHED_RECORDS"},
+{ERR_FUNC(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC),	"SSL3_DO_CHANGE_CIPHER_SPEC"},
+{ERR_FUNC(SSL_F_SSL3_ENC),	"SSL3_ENC"},
+{ERR_FUNC(SSL_F_SSL3_GENERATE_KEY_BLOCK),	"SSL3_GENERATE_KEY_BLOCK"},
+{ERR_FUNC(SSL_F_SSL3_GET_CERTIFICATE_REQUEST),	"SSL3_GET_CERTIFICATE_REQUEST"},
+{ERR_FUNC(SSL_F_SSL3_GET_CERT_STATUS),	"SSL3_GET_CERT_STATUS"},
+{ERR_FUNC(SSL_F_SSL3_GET_CERT_VERIFY),	"SSL3_GET_CERT_VERIFY"},
+{ERR_FUNC(SSL_F_SSL3_GET_CLIENT_CERTIFICATE),	"SSL3_GET_CLIENT_CERTIFICATE"},
+{ERR_FUNC(SSL_F_SSL3_GET_CLIENT_HELLO),	"SSL3_GET_CLIENT_HELLO"},
+{ERR_FUNC(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE),	"SSL3_GET_CLIENT_KEY_EXCHANGE"},
+{ERR_FUNC(SSL_F_SSL3_GET_FINISHED),	"SSL3_GET_FINISHED"},
+{ERR_FUNC(SSL_F_SSL3_GET_KEY_EXCHANGE),	"SSL3_GET_KEY_EXCHANGE"},
+{ERR_FUNC(SSL_F_SSL3_GET_MESSAGE),	"SSL3_GET_MESSAGE"},
+{ERR_FUNC(SSL_F_SSL3_GET_NEW_SESSION_TICKET),	"SSL3_GET_NEW_SESSION_TICKET"},
+{ERR_FUNC(SSL_F_SSL3_GET_RECORD),	"SSL3_GET_RECORD"},
+{ERR_FUNC(SSL_F_SSL3_GET_SERVER_CERTIFICATE),	"SSL3_GET_SERVER_CERTIFICATE"},
+{ERR_FUNC(SSL_F_SSL3_GET_SERVER_DONE),	"SSL3_GET_SERVER_DONE"},
+{ERR_FUNC(SSL_F_SSL3_GET_SERVER_HELLO),	"SSL3_GET_SERVER_HELLO"},
+{ERR_FUNC(SSL_F_SSL3_HANDSHAKE_MAC),	"ssl3_handshake_mac"},
+{ERR_FUNC(SSL_F_SSL3_NEW_SESSION_TICKET),	"SSL3_NEW_SESSION_TICKET"},
+{ERR_FUNC(SSL_F_SSL3_OUTPUT_CERT_CHAIN),	"SSL3_OUTPUT_CERT_CHAIN"},
+{ERR_FUNC(SSL_F_SSL3_PEEK),	"SSL3_PEEK"},
+{ERR_FUNC(SSL_F_SSL3_READ_BYTES),	"SSL3_READ_BYTES"},
+{ERR_FUNC(SSL_F_SSL3_READ_N),	"SSL3_READ_N"},
+{ERR_FUNC(SSL_F_SSL3_SEND_CERTIFICATE_REQUEST),	"SSL3_SEND_CERTIFICATE_REQUEST"},
+{ERR_FUNC(SSL_F_SSL3_SEND_CLIENT_CERTIFICATE),	"SSL3_SEND_CLIENT_CERTIFICATE"},
+{ERR_FUNC(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE),	"SSL3_SEND_CLIENT_KEY_EXCHANGE"},
+{ERR_FUNC(SSL_F_SSL3_SEND_CLIENT_VERIFY),	"SSL3_SEND_CLIENT_VERIFY"},
+{ERR_FUNC(SSL_F_SSL3_SEND_SERVER_CERTIFICATE),	"SSL3_SEND_SERVER_CERTIFICATE"},
+{ERR_FUNC(SSL_F_SSL3_SEND_SERVER_HELLO),	"SSL3_SEND_SERVER_HELLO"},
+{ERR_FUNC(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE),	"SSL3_SEND_SERVER_KEY_EXCHANGE"},
+{ERR_FUNC(SSL_F_SSL3_SETUP_KEY_BLOCK),	"SSL3_SETUP_KEY_BLOCK"},
+{ERR_FUNC(SSL_F_SSL3_SETUP_READ_BUFFER),	"SSL3_SETUP_READ_BUFFER"},
+{ERR_FUNC(SSL_F_SSL3_SETUP_WRITE_BUFFER),	"SSL3_SETUP_WRITE_BUFFER"},
+{ERR_FUNC(SSL_F_SSL3_WRITE_BYTES),	"SSL3_WRITE_BYTES"},
+{ERR_FUNC(SSL_F_SSL3_WRITE_PENDING),	"SSL3_WRITE_PENDING"},
+{ERR_FUNC(SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT),	"SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT"},
+{ERR_FUNC(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT),	"SSL_ADD_CLIENTHELLO_TLSEXT"},
+{ERR_FUNC(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK),	"SSL_add_dir_cert_subjects_to_stack"},
+{ERR_FUNC(SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK),	"SSL_add_file_cert_subjects_to_stack"},
+{ERR_FUNC(SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT),	"SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT"},
+{ERR_FUNC(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT),	"SSL_ADD_SERVERHELLO_TLSEXT"},
+{ERR_FUNC(SSL_F_SSL_BAD_METHOD),	"SSL_BAD_METHOD"},
+{ERR_FUNC(SSL_F_SSL_BYTES_TO_CIPHER_LIST),	"SSL_BYTES_TO_CIPHER_LIST"},
+{ERR_FUNC(SSL_F_SSL_CERT_DUP),	"SSL_CERT_DUP"},
+{ERR_FUNC(SSL_F_SSL_CERT_INST),	"SSL_CERT_INST"},
+{ERR_FUNC(SSL_F_SSL_CERT_INSTANTIATE),	"SSL_CERT_INSTANTIATE"},
+{ERR_FUNC(SSL_F_SSL_CERT_NEW),	"SSL_CERT_NEW"},
+{ERR_FUNC(SSL_F_SSL_CHECK_PRIVATE_KEY),	"SSL_check_private_key"},
+{ERR_FUNC(SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT),	"SSL_CHECK_SERVERHELLO_TLSEXT"},
+{ERR_FUNC(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG),	"SSL_CHECK_SRVR_ECC_CERT_AND_ALG"},
+{ERR_FUNC(SSL_F_SSL_CIPHER_PROCESS_RULESTR),	"SSL_CIPHER_PROCESS_RULESTR"},
+{ERR_FUNC(SSL_F_SSL_CIPHER_STRENGTH_SORT),	"SSL_CIPHER_STRENGTH_SORT"},
+{ERR_FUNC(SSL_F_SSL_CLEAR),	"SSL_clear"},
+{ERR_FUNC(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD),	"SSL_COMP_add_compression_method"},
+{ERR_FUNC(SSL_F_SSL_CREATE_CIPHER_LIST),	"SSL_CREATE_CIPHER_LIST"},
+{ERR_FUNC(SSL_F_SSL_CTRL),	"SSL_ctrl"},
+{ERR_FUNC(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY),	"SSL_CTX_check_private_key"},
+{ERR_FUNC(SSL_F_SSL_CTX_NEW),	"SSL_CTX_new"},
+{ERR_FUNC(SSL_F_SSL_CTX_SET_CIPHER_LIST),	"SSL_CTX_set_cipher_list"},
+{ERR_FUNC(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE),	"SSL_CTX_set_client_cert_engine"},
+{ERR_FUNC(SSL_F_SSL_CTX_SET_PURPOSE),	"SSL_CTX_set_purpose"},
+{ERR_FUNC(SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT),	"SSL_CTX_set_session_id_context"},
+{ERR_FUNC(SSL_F_SSL_CTX_SET_SSL_VERSION),	"SSL_CTX_set_ssl_version"},
+{ERR_FUNC(SSL_F_SSL_CTX_SET_TRUST),	"SSL_CTX_set_trust"},
+{ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE),	"SSL_CTX_use_certificate"},
+{ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1),	"SSL_CTX_use_certificate_ASN1"},
+{ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE),	"SSL_CTX_use_certificate_chain_file"},
+{ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE),	"SSL_CTX_use_certificate_file"},
+{ERR_FUNC(SSL_F_SSL_CTX_USE_PRIVATEKEY),	"SSL_CTX_use_PrivateKey"},
+{ERR_FUNC(SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1),	"SSL_CTX_use_PrivateKey_ASN1"},
+{ERR_FUNC(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE),	"SSL_CTX_use_PrivateKey_file"},
+{ERR_FUNC(SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT),	"SSL_CTX_use_psk_identity_hint"},
+{ERR_FUNC(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY),	"SSL_CTX_use_RSAPrivateKey"},
+{ERR_FUNC(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1),	"SSL_CTX_use_RSAPrivateKey_ASN1"},
+{ERR_FUNC(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE),	"SSL_CTX_use_RSAPrivateKey_file"},
+{ERR_FUNC(SSL_F_SSL_DO_HANDSHAKE),	"SSL_do_handshake"},
+{ERR_FUNC(SSL_F_SSL_GET_NEW_SESSION),	"SSL_GET_NEW_SESSION"},
+{ERR_FUNC(SSL_F_SSL_GET_PREV_SESSION),	"SSL_GET_PREV_SESSION"},
+{ERR_FUNC(SSL_F_SSL_GET_SERVER_SEND_CERT),	"SSL_GET_SERVER_SEND_CERT"},
+{ERR_FUNC(SSL_F_SSL_GET_SIGN_PKEY),	"SSL_GET_SIGN_PKEY"},
+{ERR_FUNC(SSL_F_SSL_INIT_WBIO_BUFFER),	"SSL_INIT_WBIO_BUFFER"},
+{ERR_FUNC(SSL_F_SSL_LOAD_CLIENT_CA_FILE),	"SSL_load_client_CA_file"},
+{ERR_FUNC(SSL_F_SSL_NEW),	"SSL_new"},
+{ERR_FUNC(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT),	"SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT"},
+{ERR_FUNC(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT),	"SSL_PARSE_CLIENTHELLO_TLSEXT"},
+{ERR_FUNC(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT),	"SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT"},
+{ERR_FUNC(SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT),	"SSL_PARSE_SERVERHELLO_TLSEXT"},
+{ERR_FUNC(SSL_F_SSL_PEEK),	"SSL_peek"},
+{ERR_FUNC(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT),	"SSL_PREPARE_CLIENTHELLO_TLSEXT"},
+{ERR_FUNC(SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT),	"SSL_PREPARE_SERVERHELLO_TLSEXT"},
+{ERR_FUNC(SSL_F_SSL_READ),	"SSL_read"},
+{ERR_FUNC(SSL_F_SSL_RSA_PRIVATE_DECRYPT),	"SSL_RSA_PRIVATE_DECRYPT"},
+{ERR_FUNC(SSL_F_SSL_RSA_PUBLIC_ENCRYPT),	"SSL_RSA_PUBLIC_ENCRYPT"},
+{ERR_FUNC(SSL_F_SSL_SESSION_NEW),	"SSL_SESSION_new"},
+{ERR_FUNC(SSL_F_SSL_SESSION_PRINT_FP),	"SSL_SESSION_print_fp"},
+{ERR_FUNC(SSL_F_SSL_SESS_CERT_NEW),	"SSL_SESS_CERT_NEW"},
+{ERR_FUNC(SSL_F_SSL_SET_CERT),	"SSL_SET_CERT"},
+{ERR_FUNC(SSL_F_SSL_SET_CIPHER_LIST),	"SSL_set_cipher_list"},
+{ERR_FUNC(SSL_F_SSL_SET_FD),	"SSL_set_fd"},
+{ERR_FUNC(SSL_F_SSL_SET_PKEY),	"SSL_SET_PKEY"},
+{ERR_FUNC(SSL_F_SSL_SET_PURPOSE),	"SSL_set_purpose"},
+{ERR_FUNC(SSL_F_SSL_SET_RFD),	"SSL_set_rfd"},
+{ERR_FUNC(SSL_F_SSL_SET_SESSION),	"SSL_set_session"},
+{ERR_FUNC(SSL_F_SSL_SET_SESSION_ID_CONTEXT),	"SSL_set_session_id_context"},
+{ERR_FUNC(SSL_F_SSL_SET_SESSION_TICKET_EXT),	"SSL_set_session_ticket_ext"},
+{ERR_FUNC(SSL_F_SSL_SET_TRUST),	"SSL_set_trust"},
+{ERR_FUNC(SSL_F_SSL_SET_WFD),	"SSL_set_wfd"},
+{ERR_FUNC(SSL_F_SSL_SHUTDOWN),	"SSL_shutdown"},
+{ERR_FUNC(SSL_F_SSL_UNDEFINED_CONST_FUNCTION),	"SSL_UNDEFINED_CONST_FUNCTION"},
+{ERR_FUNC(SSL_F_SSL_UNDEFINED_FUNCTION),	"SSL_UNDEFINED_FUNCTION"},
+{ERR_FUNC(SSL_F_SSL_UNDEFINED_VOID_FUNCTION),	"SSL_UNDEFINED_VOID_FUNCTION"},
+{ERR_FUNC(SSL_F_SSL_USE_CERTIFICATE),	"SSL_use_certificate"},
+{ERR_FUNC(SSL_F_SSL_USE_CERTIFICATE_ASN1),	"SSL_use_certificate_ASN1"},
+{ERR_FUNC(SSL_F_SSL_USE_CERTIFICATE_FILE),	"SSL_use_certificate_file"},
+{ERR_FUNC(SSL_F_SSL_USE_PRIVATEKEY),	"SSL_use_PrivateKey"},
+{ERR_FUNC(SSL_F_SSL_USE_PRIVATEKEY_ASN1),	"SSL_use_PrivateKey_ASN1"},
+{ERR_FUNC(SSL_F_SSL_USE_PRIVATEKEY_FILE),	"SSL_use_PrivateKey_file"},
+{ERR_FUNC(SSL_F_SSL_USE_PSK_IDENTITY_HINT),	"SSL_use_psk_identity_hint"},
+{ERR_FUNC(SSL_F_SSL_USE_RSAPRIVATEKEY),	"SSL_use_RSAPrivateKey"},
+{ERR_FUNC(SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1),	"SSL_use_RSAPrivateKey_ASN1"},
+{ERR_FUNC(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE),	"SSL_use_RSAPrivateKey_file"},
+{ERR_FUNC(SSL_F_SSL_VERIFY_CERT_CHAIN),	"SSL_VERIFY_CERT_CHAIN"},
+{ERR_FUNC(SSL_F_SSL_WRITE),	"SSL_write"},
+{ERR_FUNC(SSL_F_TLS1_CERT_VERIFY_MAC),	"tls1_cert_verify_mac"},
+{ERR_FUNC(SSL_F_TLS1_CHANGE_CIPHER_STATE),	"TLS1_CHANGE_CIPHER_STATE"},
+{ERR_FUNC(SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT),	"TLS1_CHECK_SERVERHELLO_TLSEXT"},
+{ERR_FUNC(SSL_F_TLS1_ENC),	"TLS1_ENC"},
+{ERR_FUNC(SSL_F_TLS1_PREPARE_CLIENTHELLO_TLSEXT),	"TLS1_PREPARE_CLIENTHELLO_TLSEXT"},
+{ERR_FUNC(SSL_F_TLS1_PREPARE_SERVERHELLO_TLSEXT),	"TLS1_PREPARE_SERVERHELLO_TLSEXT"},
+{ERR_FUNC(SSL_F_TLS1_PRF),	"tls1_prf"},
+{ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK),	"TLS1_SETUP_KEY_BLOCK"},
+{ERR_FUNC(SSL_F_WRITE_PENDING),	"WRITE_PENDING"},
+{0,NULL}
+	};
+
+static ERR_STRING_DATA SSL_str_reasons[]=
+	{
+{ERR_REASON(SSL_R_APP_DATA_IN_HANDSHAKE) ,"app data in handshake"},
+{ERR_REASON(SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT),"attempt to reuse session in different context"},
+{ERR_REASON(SSL_R_BAD_ALERT_RECORD)      ,"bad alert record"},
+{ERR_REASON(SSL_R_BAD_AUTHENTICATION_TYPE),"bad authentication type"},
+{ERR_REASON(SSL_R_BAD_CHANGE_CIPHER_SPEC),"bad change cipher spec"},
+{ERR_REASON(SSL_R_BAD_CHECKSUM)          ,"bad checksum"},
+{ERR_REASON(SSL_R_BAD_DATA_RETURNED_BY_CALLBACK),"bad data returned by callback"},
+{ERR_REASON(SSL_R_BAD_DECOMPRESSION)     ,"bad decompression"},
+{ERR_REASON(SSL_R_BAD_DH_G_LENGTH)       ,"bad dh g length"},
+{ERR_REASON(SSL_R_BAD_DH_PUB_KEY_LENGTH) ,"bad dh pub key length"},
+{ERR_REASON(SSL_R_BAD_DH_P_LENGTH)       ,"bad dh p length"},
+{ERR_REASON(SSL_R_BAD_DIGEST_LENGTH)     ,"bad digest length"},
+{ERR_REASON(SSL_R_BAD_DSA_SIGNATURE)     ,"bad dsa signature"},
+{ERR_REASON(SSL_R_BAD_ECC_CERT)          ,"bad ecc cert"},
+{ERR_REASON(SSL_R_BAD_ECDSA_SIGNATURE)   ,"bad ecdsa signature"},
+{ERR_REASON(SSL_R_BAD_ECPOINT)           ,"bad ecpoint"},
+{ERR_REASON(SSL_R_BAD_HANDSHAKE_LENGTH)  ,"bad handshake length"},
+{ERR_REASON(SSL_R_BAD_HELLO_REQUEST)     ,"bad hello request"},
+{ERR_REASON(SSL_R_BAD_LENGTH)            ,"bad length"},
+{ERR_REASON(SSL_R_BAD_MAC_DECODE)        ,"bad mac decode"},
+{ERR_REASON(SSL_R_BAD_MAC_LENGTH)        ,"bad mac length"},
+{ERR_REASON(SSL_R_BAD_MESSAGE_TYPE)      ,"bad message type"},
+{ERR_REASON(SSL_R_BAD_PACKET_LENGTH)     ,"bad packet length"},
+{ERR_REASON(SSL_R_BAD_PROTOCOL_VERSION_NUMBER),"bad protocol version number"},
+{ERR_REASON(SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH),"bad psk identity hint length"},
+{ERR_REASON(SSL_R_BAD_RESPONSE_ARGUMENT) ,"bad response argument"},
+{ERR_REASON(SSL_R_BAD_RSA_DECRYPT)       ,"bad rsa decrypt"},
+{ERR_REASON(SSL_R_BAD_RSA_ENCRYPT)       ,"bad rsa encrypt"},
+{ERR_REASON(SSL_R_BAD_RSA_E_LENGTH)      ,"bad rsa e length"},
+{ERR_REASON(SSL_R_BAD_RSA_MODULUS_LENGTH),"bad rsa modulus length"},
+{ERR_REASON(SSL_R_BAD_RSA_SIGNATURE)     ,"bad rsa signature"},
+{ERR_REASON(SSL_R_BAD_SIGNATURE)         ,"bad signature"},
+{ERR_REASON(SSL_R_BAD_SSL_FILETYPE)      ,"bad ssl filetype"},
+{ERR_REASON(SSL_R_BAD_SSL_SESSION_ID_LENGTH),"bad ssl session id length"},
+{ERR_REASON(SSL_R_BAD_STATE)             ,"bad state"},
+{ERR_REASON(SSL_R_BAD_WRITE_RETRY)       ,"bad write retry"},
+{ERR_REASON(SSL_R_BIO_NOT_SET)           ,"bio not set"},
+{ERR_REASON(SSL_R_BLOCK_CIPHER_PAD_IS_WRONG),"block cipher pad is wrong"},
+{ERR_REASON(SSL_R_BN_LIB)                ,"bn lib"},
+{ERR_REASON(SSL_R_CA_DN_LENGTH_MISMATCH) ,"ca dn length mismatch"},
+{ERR_REASON(SSL_R_CA_DN_TOO_LONG)        ,"ca dn too long"},
+{ERR_REASON(SSL_R_CCS_RECEIVED_EARLY)    ,"ccs received early"},
+{ERR_REASON(SSL_R_CERTIFICATE_VERIFY_FAILED),"certificate verify failed"},
+{ERR_REASON(SSL_R_CERT_LENGTH_MISMATCH)  ,"cert length mismatch"},
+{ERR_REASON(SSL_R_CHALLENGE_IS_DIFFERENT),"challenge is different"},
+{ERR_REASON(SSL_R_CIPHER_CODE_WRONG_LENGTH),"cipher code wrong length"},
+{ERR_REASON(SSL_R_CIPHER_OR_HASH_UNAVAILABLE),"cipher or hash unavailable"},
+{ERR_REASON(SSL_R_CIPHER_TABLE_SRC_ERROR),"cipher table src error"},
+{ERR_REASON(SSL_R_CLIENTHELLO_TLSEXT)    ,"clienthello tlsext"},
+{ERR_REASON(SSL_R_COMPRESSED_LENGTH_TOO_LONG),"compressed length too long"},
+{ERR_REASON(SSL_R_COMPRESSION_DISABLED)  ,"compression disabled"},
+{ERR_REASON(SSL_R_COMPRESSION_FAILURE)   ,"compression failure"},
+{ERR_REASON(SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE),"compression id not within private range"},
+{ERR_REASON(SSL_R_COMPRESSION_LIBRARY_ERROR),"compression library error"},
+{ERR_REASON(SSL_R_CONNECTION_ID_IS_DIFFERENT),"connection id is different"},
+{ERR_REASON(SSL_R_CONNECTION_TYPE_NOT_SET),"connection type not set"},
+{ERR_REASON(SSL_R_COOKIE_MISMATCH)       ,"cookie mismatch"},
+{ERR_REASON(SSL_R_DATA_BETWEEN_CCS_AND_FINISHED),"data between ccs and finished"},
+{ERR_REASON(SSL_R_DATA_LENGTH_TOO_LONG)  ,"data length too long"},
+{ERR_REASON(SSL_R_DECRYPTION_FAILED)     ,"decryption failed"},
+{ERR_REASON(SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC),"decryption failed or bad record mac"},
+{ERR_REASON(SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG),"dh public value length is wrong"},
+{ERR_REASON(SSL_R_DIGEST_CHECK_FAILED)   ,"digest check failed"},
+{ERR_REASON(SSL_R_DTLS_MESSAGE_TOO_BIG)  ,"dtls message too big"},
+{ERR_REASON(SSL_R_DUPLICATE_COMPRESSION_ID),"duplicate compression id"},
+{ERR_REASON(SSL_R_ECC_CERT_NOT_FOR_KEY_AGREEMENT),"ecc cert not for key agreement"},
+{ERR_REASON(SSL_R_ECC_CERT_NOT_FOR_SIGNING),"ecc cert not for signing"},
+{ERR_REASON(SSL_R_ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE),"ecc cert should have rsa signature"},
+{ERR_REASON(SSL_R_ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE),"ecc cert should have sha1 signature"},
+{ERR_REASON(SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER),"ecgroup too large for cipher"},
+{ERR_REASON(SSL_R_ENCRYPTED_LENGTH_TOO_LONG),"encrypted length too long"},
+{ERR_REASON(SSL_R_ERROR_GENERATING_TMP_RSA_KEY),"error generating tmp rsa key"},
+{ERR_REASON(SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST),"error in received cipher list"},
+{ERR_REASON(SSL_R_EXCESSIVE_MESSAGE_SIZE),"excessive message size"},
+{ERR_REASON(SSL_R_EXTRA_DATA_IN_MESSAGE) ,"extra data in message"},
+{ERR_REASON(SSL_R_GOT_A_FIN_BEFORE_A_CCS),"got a fin before a ccs"},
+{ERR_REASON(SSL_R_HTTPS_PROXY_REQUEST)   ,"https proxy request"},
+{ERR_REASON(SSL_R_HTTP_REQUEST)          ,"http request"},
+{ERR_REASON(SSL_R_ILLEGAL_PADDING)       ,"illegal padding"},
+{ERR_REASON(SSL_R_INCONSISTENT_COMPRESSION),"inconsistent compression"},
+{ERR_REASON(SSL_R_INVALID_CHALLENGE_LENGTH),"invalid challenge length"},
+{ERR_REASON(SSL_R_INVALID_COMMAND)       ,"invalid command"},
+{ERR_REASON(SSL_R_INVALID_COMPRESSION_ALGORITHM),"invalid compression algorithm"},
+{ERR_REASON(SSL_R_INVALID_PURPOSE)       ,"invalid purpose"},
+{ERR_REASON(SSL_R_INVALID_STATUS_RESPONSE),"invalid status response"},
+{ERR_REASON(SSL_R_INVALID_TICKET_KEYS_LENGTH),"invalid ticket keys length"},
+{ERR_REASON(SSL_R_INVALID_TRUST)         ,"invalid trust"},
+{ERR_REASON(SSL_R_KEY_ARG_TOO_LONG)      ,"key arg too long"},
+{ERR_REASON(SSL_R_KRB5)                  ,"krb5"},
+{ERR_REASON(SSL_R_KRB5_C_CC_PRINC)       ,"krb5 client cc principal (no tkt?)"},
+{ERR_REASON(SSL_R_KRB5_C_GET_CRED)       ,"krb5 client get cred"},
+{ERR_REASON(SSL_R_KRB5_C_INIT)           ,"krb5 client init"},
+{ERR_REASON(SSL_R_KRB5_C_MK_REQ)         ,"krb5 client mk_req (expired tkt?)"},
+{ERR_REASON(SSL_R_KRB5_S_BAD_TICKET)     ,"krb5 server bad ticket"},
+{ERR_REASON(SSL_R_KRB5_S_INIT)           ,"krb5 server init"},
+{ERR_REASON(SSL_R_KRB5_S_RD_REQ)         ,"krb5 server rd_req (keytab perms?)"},
+{ERR_REASON(SSL_R_KRB5_S_TKT_EXPIRED)    ,"krb5 server tkt expired"},
+{ERR_REASON(SSL_R_KRB5_S_TKT_NYV)        ,"krb5 server tkt not yet valid"},
+{ERR_REASON(SSL_R_KRB5_S_TKT_SKEW)       ,"krb5 server tkt skew"},
+{ERR_REASON(SSL_R_LENGTH_MISMATCH)       ,"length mismatch"},
+{ERR_REASON(SSL_R_LENGTH_TOO_SHORT)      ,"length too short"},
+{ERR_REASON(SSL_R_LIBRARY_BUG)           ,"library bug"},
+{ERR_REASON(SSL_R_LIBRARY_HAS_NO_CIPHERS),"library has no ciphers"},
+{ERR_REASON(SSL_R_MESSAGE_TOO_LONG)      ,"message too long"},
+{ERR_REASON(SSL_R_MISSING_DH_DSA_CERT)   ,"missing dh dsa cert"},
+{ERR_REASON(SSL_R_MISSING_DH_KEY)        ,"missing dh key"},
+{ERR_REASON(SSL_R_MISSING_DH_RSA_CERT)   ,"missing dh rsa cert"},
+{ERR_REASON(SSL_R_MISSING_DSA_SIGNING_CERT),"missing dsa signing cert"},
+{ERR_REASON(SSL_R_MISSING_EXPORT_TMP_DH_KEY),"missing export tmp dh key"},
+{ERR_REASON(SSL_R_MISSING_EXPORT_TMP_RSA_KEY),"missing export tmp rsa key"},
+{ERR_REASON(SSL_R_MISSING_RSA_CERTIFICATE),"missing rsa certificate"},
+{ERR_REASON(SSL_R_MISSING_RSA_ENCRYPTING_CERT),"missing rsa encrypting cert"},
+{ERR_REASON(SSL_R_MISSING_RSA_SIGNING_CERT),"missing rsa signing cert"},
+{ERR_REASON(SSL_R_MISSING_TMP_DH_KEY)    ,"missing tmp dh key"},
+{ERR_REASON(SSL_R_MISSING_TMP_ECDH_KEY)  ,"missing tmp ecdh key"},
+{ERR_REASON(SSL_R_MISSING_TMP_RSA_KEY)   ,"missing tmp rsa key"},
+{ERR_REASON(SSL_R_MISSING_TMP_RSA_PKEY)  ,"missing tmp rsa pkey"},
+{ERR_REASON(SSL_R_MISSING_VERIFY_MESSAGE),"missing verify message"},
+{ERR_REASON(SSL_R_NON_SSLV2_INITIAL_PACKET),"non sslv2 initial packet"},
+{ERR_REASON(SSL_R_NO_CERTIFICATES_RETURNED),"no certificates returned"},
+{ERR_REASON(SSL_R_NO_CERTIFICATE_ASSIGNED),"no certificate assigned"},
+{ERR_REASON(SSL_R_NO_CERTIFICATE_RETURNED),"no certificate returned"},
+{ERR_REASON(SSL_R_NO_CERTIFICATE_SET)    ,"no certificate set"},
+{ERR_REASON(SSL_R_NO_CERTIFICATE_SPECIFIED),"no certificate specified"},
+{ERR_REASON(SSL_R_NO_CIPHERS_AVAILABLE)  ,"no ciphers available"},
+{ERR_REASON(SSL_R_NO_CIPHERS_PASSED)     ,"no ciphers passed"},
+{ERR_REASON(SSL_R_NO_CIPHERS_SPECIFIED)  ,"no ciphers specified"},
+{ERR_REASON(SSL_R_NO_CIPHER_LIST)        ,"no cipher list"},
+{ERR_REASON(SSL_R_NO_CIPHER_MATCH)       ,"no cipher match"},
+{ERR_REASON(SSL_R_NO_CLIENT_CERT_METHOD) ,"no client cert method"},
+{ERR_REASON(SSL_R_NO_CLIENT_CERT_RECEIVED),"no client cert received"},
+{ERR_REASON(SSL_R_NO_COMPRESSION_SPECIFIED),"no compression specified"},
+{ERR_REASON(SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER),"Peer haven't sent GOST certificate, required for selected ciphersuite"},
+{ERR_REASON(SSL_R_NO_METHOD_SPECIFIED)   ,"no method specified"},
+{ERR_REASON(SSL_R_NO_PRIVATEKEY)         ,"no privatekey"},
+{ERR_REASON(SSL_R_NO_PRIVATE_KEY_ASSIGNED),"no private key assigned"},
+{ERR_REASON(SSL_R_NO_PROTOCOLS_AVAILABLE),"no protocols available"},
+{ERR_REASON(SSL_R_NO_PUBLICKEY)          ,"no publickey"},
+{ERR_REASON(SSL_R_NO_RENEGOTIATION)      ,"no renegotiation"},
+{ERR_REASON(SSL_R_NO_REQUIRED_DIGEST)    ,"digest requred for handshake isn't computed"},
+{ERR_REASON(SSL_R_NO_SHARED_CIPHER)      ,"no shared cipher"},
+{ERR_REASON(SSL_R_NO_VERIFY_CALLBACK)    ,"no verify callback"},
+{ERR_REASON(SSL_R_NULL_SSL_CTX)          ,"null ssl ctx"},
+{ERR_REASON(SSL_R_NULL_SSL_METHOD_PASSED),"null ssl method passed"},
+{ERR_REASON(SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED),"old session cipher not returned"},
+{ERR_REASON(SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED),"old session compression algorithm not returned"},
+{ERR_REASON(SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE),"only tls allowed in fips mode"},
+{ERR_REASON(SSL_R_OPAQUE_PRF_INPUT_TOO_LONG),"opaque PRF input too long"},
+{ERR_REASON(SSL_R_PACKET_LENGTH_TOO_LONG),"packet length too long"},
+{ERR_REASON(SSL_R_PARSE_TLSEXT)          ,"parse tlsext"},
+{ERR_REASON(SSL_R_PATH_TOO_LONG)         ,"path too long"},
+{ERR_REASON(SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE),"peer did not return a certificate"},
+{ERR_REASON(SSL_R_PEER_ERROR)            ,"peer error"},
+{ERR_REASON(SSL_R_PEER_ERROR_CERTIFICATE),"peer error certificate"},
+{ERR_REASON(SSL_R_PEER_ERROR_NO_CERTIFICATE),"peer error no certificate"},
+{ERR_REASON(SSL_R_PEER_ERROR_NO_CIPHER)  ,"peer error no cipher"},
+{ERR_REASON(SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE),"peer error unsupported certificate type"},
+{ERR_REASON(SSL_R_PRE_MAC_LENGTH_TOO_LONG),"pre mac length too long"},
+{ERR_REASON(SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS),"problems mapping cipher functions"},
+{ERR_REASON(SSL_R_PROTOCOL_IS_SHUTDOWN)  ,"protocol is shutdown"},
+{ERR_REASON(SSL_R_PSK_IDENTITY_NOT_FOUND),"psk identity not found"},
+{ERR_REASON(SSL_R_PSK_NO_CLIENT_CB)      ,"psk no client cb"},
+{ERR_REASON(SSL_R_PSK_NO_SERVER_CB)      ,"psk no server cb"},
+{ERR_REASON(SSL_R_PUBLIC_KEY_ENCRYPT_ERROR),"public key encrypt error"},
+{ERR_REASON(SSL_R_PUBLIC_KEY_IS_NOT_RSA) ,"public key is not rsa"},
+{ERR_REASON(SSL_R_PUBLIC_KEY_NOT_RSA)    ,"public key not rsa"},
+{ERR_REASON(SSL_R_READ_BIO_NOT_SET)      ,"read bio not set"},
+{ERR_REASON(SSL_R_READ_TIMEOUT_EXPIRED)  ,"read timeout expired"},
+{ERR_REASON(SSL_R_READ_WRONG_PACKET_TYPE),"read wrong packet type"},
+{ERR_REASON(SSL_R_RECORD_LENGTH_MISMATCH),"record length mismatch"},
+{ERR_REASON(SSL_R_RECORD_TOO_LARGE)      ,"record too large"},
+{ERR_REASON(SSL_R_RECORD_TOO_SMALL)      ,"record too small"},
+{ERR_REASON(SSL_R_RENEGOTIATE_EXT_TOO_LONG),"renegotiate ext too long"},
+{ERR_REASON(SSL_R_RENEGOTIATION_ENCODING_ERR),"renegotiation encoding err"},
+{ERR_REASON(SSL_R_RENEGOTIATION_MISMATCH),"renegotiation mismatch"},
+{ERR_REASON(SSL_R_REQUIRED_CIPHER_MISSING),"required cipher missing"},
+{ERR_REASON(SSL_R_REQUIRED_COMPRESSSION_ALGORITHM_MISSING),"required compresssion algorithm missing"},
+{ERR_REASON(SSL_R_REUSE_CERT_LENGTH_NOT_ZERO),"reuse cert length not zero"},
+{ERR_REASON(SSL_R_REUSE_CERT_TYPE_NOT_ZERO),"reuse cert type not zero"},
+{ERR_REASON(SSL_R_REUSE_CIPHER_LIST_NOT_ZERO),"reuse cipher list not zero"},
+{ERR_REASON(SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING),"scsv received when renegotiating"},
+{ERR_REASON(SSL_R_SERVERHELLO_TLSEXT)    ,"serverhello tlsext"},
+{ERR_REASON(SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED),"session id context uninitialized"},
+{ERR_REASON(SSL_R_SESSION_MAY_NOT_BE_CREATED),"session may not be created"},
+{ERR_REASON(SSL_R_SHORT_READ)            ,"short read"},
+{ERR_REASON(SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE),"signature for non signing certificate"},
+{ERR_REASON(SSL_R_SSL23_DOING_SESSION_ID_REUSE),"ssl23 doing session id reuse"},
+{ERR_REASON(SSL_R_SSL2_CONNECTION_ID_TOO_LONG),"ssl2 connection id too long"},
+{ERR_REASON(SSL_R_SSL3_EXT_INVALID_ECPOINTFORMAT),"ssl3 ext invalid ecpointformat"},
+{ERR_REASON(SSL_R_SSL3_EXT_INVALID_SERVERNAME),"ssl3 ext invalid servername"},
+{ERR_REASON(SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE),"ssl3 ext invalid servername type"},
+{ERR_REASON(SSL_R_SSL3_SESSION_ID_TOO_LONG),"ssl3 session id too long"},
+{ERR_REASON(SSL_R_SSL3_SESSION_ID_TOO_SHORT),"ssl3 session id too short"},
+{ERR_REASON(SSL_R_SSLV3_ALERT_BAD_CERTIFICATE),"sslv3 alert bad certificate"},
+{ERR_REASON(SSL_R_SSLV3_ALERT_BAD_RECORD_MAC),"sslv3 alert bad record mac"},
+{ERR_REASON(SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED),"sslv3 alert certificate expired"},
+{ERR_REASON(SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED),"sslv3 alert certificate revoked"},
+{ERR_REASON(SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN),"sslv3 alert certificate unknown"},
+{ERR_REASON(SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE),"sslv3 alert decompression failure"},
+{ERR_REASON(SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE),"sslv3 alert handshake failure"},
+{ERR_REASON(SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER),"sslv3 alert illegal parameter"},
+{ERR_REASON(SSL_R_SSLV3_ALERT_NO_CERTIFICATE),"sslv3 alert no certificate"},
+{ERR_REASON(SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE),"sslv3 alert unexpected message"},
+{ERR_REASON(SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE),"sslv3 alert unsupported certificate"},
+{ERR_REASON(SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION),"ssl ctx has no default ssl version"},
+{ERR_REASON(SSL_R_SSL_HANDSHAKE_FAILURE) ,"ssl handshake failure"},
+{ERR_REASON(SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS),"ssl library has no ciphers"},
+{ERR_REASON(SSL_R_SSL_SESSION_ID_CALLBACK_FAILED),"ssl session id callback failed"},
+{ERR_REASON(SSL_R_SSL_SESSION_ID_CONFLICT),"ssl session id conflict"},
+{ERR_REASON(SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG),"ssl session id context too long"},
+{ERR_REASON(SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH),"ssl session id has bad length"},
+{ERR_REASON(SSL_R_SSL_SESSION_ID_IS_DIFFERENT),"ssl session id is different"},
+{ERR_REASON(SSL_R_TLSV1_ALERT_ACCESS_DENIED),"tlsv1 alert access denied"},
+{ERR_REASON(SSL_R_TLSV1_ALERT_DECODE_ERROR),"tlsv1 alert decode error"},
+{ERR_REASON(SSL_R_TLSV1_ALERT_DECRYPTION_FAILED),"tlsv1 alert decryption failed"},
+{ERR_REASON(SSL_R_TLSV1_ALERT_DECRYPT_ERROR),"tlsv1 alert decrypt error"},
+{ERR_REASON(SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION),"tlsv1 alert export restriction"},
+{ERR_REASON(SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY),"tlsv1 alert insufficient security"},
+{ERR_REASON(SSL_R_TLSV1_ALERT_INTERNAL_ERROR),"tlsv1 alert internal error"},
+{ERR_REASON(SSL_R_TLSV1_ALERT_NO_RENEGOTIATION),"tlsv1 alert no renegotiation"},
+{ERR_REASON(SSL_R_TLSV1_ALERT_PROTOCOL_VERSION),"tlsv1 alert protocol version"},
+{ERR_REASON(SSL_R_TLSV1_ALERT_RECORD_OVERFLOW),"tlsv1 alert record overflow"},
+{ERR_REASON(SSL_R_TLSV1_ALERT_UNKNOWN_CA),"tlsv1 alert unknown ca"},
+{ERR_REASON(SSL_R_TLSV1_ALERT_USER_CANCELLED),"tlsv1 alert user cancelled"},
+{ERR_REASON(SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE),"tlsv1 bad certificate hash value"},
+{ERR_REASON(SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE),"tlsv1 bad certificate status response"},
+{ERR_REASON(SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE),"tlsv1 certificate unobtainable"},
+{ERR_REASON(SSL_R_TLSV1_UNRECOGNIZED_NAME),"tlsv1 unrecognized name"},
+{ERR_REASON(SSL_R_TLSV1_UNSUPPORTED_EXTENSION),"tlsv1 unsupported extension"},
+{ERR_REASON(SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER),"tls client cert req with anon cipher"},
+{ERR_REASON(SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST),"tls invalid ecpointformat list"},
+{ERR_REASON(SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST),"tls peer did not respond with certificate list"},
+{ERR_REASON(SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG),"tls rsa encrypted value length is wrong"},
+{ERR_REASON(SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER),"tried to use unsupported cipher"},
+{ERR_REASON(SSL_R_UNABLE_TO_DECODE_DH_CERTS),"unable to decode dh certs"},
+{ERR_REASON(SSL_R_UNABLE_TO_DECODE_ECDH_CERTS),"unable to decode ecdh certs"},
+{ERR_REASON(SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY),"unable to extract public key"},
+{ERR_REASON(SSL_R_UNABLE_TO_FIND_DH_PARAMETERS),"unable to find dh parameters"},
+{ERR_REASON(SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS),"unable to find ecdh parameters"},
+{ERR_REASON(SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS),"unable to find public key parameters"},
+{ERR_REASON(SSL_R_UNABLE_TO_FIND_SSL_METHOD),"unable to find ssl method"},
+{ERR_REASON(SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES),"unable to load ssl2 md5 routines"},
+{ERR_REASON(SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES),"unable to load ssl3 md5 routines"},
+{ERR_REASON(SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES),"unable to load ssl3 sha1 routines"},
+{ERR_REASON(SSL_R_UNEXPECTED_MESSAGE)    ,"unexpected message"},
+{ERR_REASON(SSL_R_UNEXPECTED_RECORD)     ,"unexpected record"},
+{ERR_REASON(SSL_R_UNINITIALIZED)         ,"uninitialized"},
+{ERR_REASON(SSL_R_UNKNOWN_ALERT_TYPE)    ,"unknown alert type"},
+{ERR_REASON(SSL_R_UNKNOWN_CERTIFICATE_TYPE),"unknown certificate type"},
+{ERR_REASON(SSL_R_UNKNOWN_CIPHER_RETURNED),"unknown cipher returned"},
+{ERR_REASON(SSL_R_UNKNOWN_CIPHER_TYPE)   ,"unknown cipher type"},
+{ERR_REASON(SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE),"unknown key exchange type"},
+{ERR_REASON(SSL_R_UNKNOWN_PKEY_TYPE)     ,"unknown pkey type"},
+{ERR_REASON(SSL_R_UNKNOWN_PROTOCOL)      ,"unknown protocol"},
+{ERR_REASON(SSL_R_UNKNOWN_REMOTE_ERROR_TYPE),"unknown remote error type"},
+{ERR_REASON(SSL_R_UNKNOWN_SSL_VERSION)   ,"unknown ssl version"},
+{ERR_REASON(SSL_R_UNKNOWN_STATE)         ,"unknown state"},
+{ERR_REASON(SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED),"unsafe legacy renegotiation disabled"},
+{ERR_REASON(SSL_R_UNSUPPORTED_CIPHER)    ,"unsupported cipher"},
+{ERR_REASON(SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM),"unsupported compression algorithm"},
+{ERR_REASON(SSL_R_UNSUPPORTED_DIGEST_TYPE),"unsupported digest type"},
+{ERR_REASON(SSL_R_UNSUPPORTED_ELLIPTIC_CURVE),"unsupported elliptic curve"},
+{ERR_REASON(SSL_R_UNSUPPORTED_PROTOCOL)  ,"unsupported protocol"},
+{ERR_REASON(SSL_R_UNSUPPORTED_SSL_VERSION),"unsupported ssl version"},
+{ERR_REASON(SSL_R_UNSUPPORTED_STATUS_TYPE),"unsupported status type"},
+{ERR_REASON(SSL_R_WRITE_BIO_NOT_SET)     ,"write bio not set"},
+{ERR_REASON(SSL_R_WRONG_CIPHER_RETURNED) ,"wrong cipher returned"},
+{ERR_REASON(SSL_R_WRONG_MESSAGE_TYPE)    ,"wrong message type"},
+{ERR_REASON(SSL_R_WRONG_NUMBER_OF_KEY_BITS),"wrong number of key bits"},
+{ERR_REASON(SSL_R_WRONG_SIGNATURE_LENGTH),"wrong signature length"},
+{ERR_REASON(SSL_R_WRONG_SIGNATURE_SIZE)  ,"wrong signature size"},
+{ERR_REASON(SSL_R_WRONG_SSL_VERSION)     ,"wrong ssl version"},
+{ERR_REASON(SSL_R_WRONG_VERSION_NUMBER)  ,"wrong version number"},
+{ERR_REASON(SSL_R_X509_LIB)              ,"x509 lib"},
+{ERR_REASON(SSL_R_X509_VERIFICATION_SETUP_PROBLEMS),"x509 verification setup problems"},
+{0,NULL}
+	};
+
+#endif
+
+void ERR_load_SSL_strings(void)
+	{
+#ifndef OPENSSL_NO_ERR
+
+	if (ERR_func_error_string(SSL_str_functs[0].error) == NULL)
+		{
+		ERR_load_strings(0,SSL_str_functs);
+		ERR_load_strings(0,SSL_str_reasons);
+		}
+#endif
+	}
diff --git a/lib/openssl/ssl/ssl_err2.c b/lib/openssl/ssl/ssl_err2.c
new file mode 100644
index 0000000..ea95a5f
--- /dev/null
+++ b/lib/openssl/ssl/ssl_err2.c
@@ -0,0 +1,70 @@
+/* ssl/ssl_err2.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+
+void SSL_load_error_strings(void)
+	{
+#ifndef OPENSSL_NO_ERR
+	ERR_load_crypto_strings();
+	ERR_load_SSL_strings();
+#endif
+	}
+
diff --git a/lib/openssl/ssl/ssl_lib.c b/lib/openssl/ssl/ssl_lib.c
new file mode 100644
index 0000000..e120dad
--- /dev/null
+++ b/lib/openssl/ssl/ssl_lib.c
@@ -0,0 +1,3102 @@
+/*! \file ssl/ssl_lib.c
+ *  \brief Version independent SSL functions.
+ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECC cipher suite support in OpenSSL originally developed by 
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#ifdef REF_CHECK
+#  include <assert.h>
+#endif
+#include <stdio.h>
+#include "ssl_locl.h"
+#include "kssl_lcl.h"
+#include <openssl/objects.h>
+#include <openssl/lhash.h>
+#include <openssl/x509v3.h>
+#include <openssl/rand.h>
+#include <openssl/ocsp.h>
+#ifndef OPENSSL_NO_DH
+#include <openssl/dh.h>
+#endif
+#ifndef OPENSSL_NO_ENGINE
+#include <openssl/engine.h>
+#endif
+
+const char *SSL_version_str=OPENSSL_VERSION_TEXT;
+
+SSL3_ENC_METHOD ssl3_undef_enc_method={
+	/* evil casts, but these functions are only called if there's a library bug */
+	(int (*)(SSL *,int))ssl_undefined_function,
+	(int (*)(SSL *, unsigned char *, int))ssl_undefined_function,
+	ssl_undefined_function,
+	(int (*)(SSL *, unsigned char *, unsigned char *, int))ssl_undefined_function,
+	(int (*)(SSL*, int))ssl_undefined_function,
+	(int (*)(SSL *,  const char*, int, unsigned char *))ssl_undefined_function,
+	0,	/* finish_mac_length */
+	(int (*)(SSL *, int, unsigned char *))ssl_undefined_function,
+	NULL,	/* client_finished_label */
+	0,	/* client_finished_label_len */
+	NULL,	/* server_finished_label */
+	0,	/* server_finished_label_len */
+	(int (*)(int))ssl_undefined_function
+	};
+
+int SSL_clear(SSL *s)
+	{
+
+	if (s->method == NULL)
+		{
+		SSLerr(SSL_F_SSL_CLEAR,SSL_R_NO_METHOD_SPECIFIED);
+		return(0);
+		}
+
+	if (ssl_clear_bad_session(s))
+		{
+		SSL_SESSION_free(s->session);
+		s->session=NULL;
+		}
+
+	s->error=0;
+	s->hit=0;
+	s->shutdown=0;
+
+#if 0 /* Disabled since version 1.10 of this file (early return not
+       * needed because SSL_clear is not called when doing renegotiation) */
+	/* This is set if we are doing dynamic renegotiation so keep
+	 * the old cipher.  It is sort of a SSL_clear_lite :-) */
+	if (s->new_session) return(1);
+#else
+	if (s->new_session)
+		{
+		SSLerr(SSL_F_SSL_CLEAR,ERR_R_INTERNAL_ERROR);
+		return 0;
+		}
+#endif
+
+	s->type=0;
+
+	s->state=SSL_ST_BEFORE|((s->server)?SSL_ST_ACCEPT:SSL_ST_CONNECT);
+
+	s->version=s->method->version;
+	s->client_version=s->version;
+	s->rwstate=SSL_NOTHING;
+	s->rstate=SSL_ST_READ_HEADER;
+#if 0
+	s->read_ahead=s->ctx->read_ahead;
+#endif
+
+	if (s->init_buf != NULL)
+		{
+		BUF_MEM_free(s->init_buf);
+		s->init_buf=NULL;
+		}
+
+	ssl_clear_cipher_ctx(s);
+	ssl_clear_hash_ctx(&s->read_hash);
+	ssl_clear_hash_ctx(&s->write_hash);
+
+	s->first_packet=0;
+
+#if 1
+	/* Check to see if we were changed into a different method, if
+	 * so, revert back if we are not doing session-id reuse. */
+	if (!s->in_handshake && (s->session == NULL) && (s->method != s->ctx->method))
+		{
+		s->method->ssl_free(s);
+		s->method=s->ctx->method;
+		if (!s->method->ssl_new(s))
+			return(0);
+		}
+	else
+#endif
+		s->method->ssl_clear(s);
+	return(1);
+	}
+
+/** Used to change an SSL_CTXs default SSL method type */
+int SSL_CTX_set_ssl_version(SSL_CTX *ctx,const SSL_METHOD *meth)
+	{
+	STACK_OF(SSL_CIPHER) *sk;
+
+	ctx->method=meth;
+
+	sk=ssl_create_cipher_list(ctx->method,&(ctx->cipher_list),
+		&(ctx->cipher_list_by_id),
+		meth->version == SSL2_VERSION ? "SSLv2" : SSL_DEFAULT_CIPHER_LIST);
+	if ((sk == NULL) || (sk_SSL_CIPHER_num(sk) <= 0))
+		{
+		SSLerr(SSL_F_SSL_CTX_SET_SSL_VERSION,SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS);
+		return(0);
+		}
+	return(1);
+	}
+
+SSL *SSL_new(SSL_CTX *ctx)
+	{
+	SSL *s;
+
+	if (ctx == NULL)
+		{
+		SSLerr(SSL_F_SSL_NEW,SSL_R_NULL_SSL_CTX);
+		return(NULL);
+		}
+	if (ctx->method == NULL)
+		{
+		SSLerr(SSL_F_SSL_NEW,SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION);
+		return(NULL);
+		}
+
+	s=(SSL *)OPENSSL_malloc(sizeof(SSL));
+	if (s == NULL) goto err;
+	memset(s,0,sizeof(SSL));
+
+#ifndef	OPENSSL_NO_KRB5
+	s->kssl_ctx = kssl_ctx_new();
+#endif	/* OPENSSL_NO_KRB5 */
+
+	s->options=ctx->options;
+	s->mode=ctx->mode;
+	s->max_cert_list=ctx->max_cert_list;
+
+	if (ctx->cert != NULL)
+		{
+		/* Earlier library versions used to copy the pointer to
+		 * the CERT, not its contents; only when setting new
+		 * parameters for the per-SSL copy, ssl_cert_new would be
+		 * called (and the direct reference to the per-SSL_CTX
+		 * settings would be lost, but those still were indirectly
+		 * accessed for various purposes, and for that reason they
+		 * used to be known as s->ctx->default_cert).
+		 * Now we don't look at the SSL_CTX's CERT after having
+		 * duplicated it once. */
+
+		s->cert = ssl_cert_dup(ctx->cert);
+		if (s->cert == NULL)
+			goto err;
+		}
+	else
+		s->cert=NULL; /* Cannot really happen (see SSL_CTX_new) */
+
+	s->read_ahead=ctx->read_ahead;
+	s->msg_callback=ctx->msg_callback;
+	s->msg_callback_arg=ctx->msg_callback_arg;
+	s->verify_mode=ctx->verify_mode;
+#if 0
+	s->verify_depth=ctx->verify_depth;
+#endif
+	s->sid_ctx_length=ctx->sid_ctx_length;
+	OPENSSL_assert(s->sid_ctx_length <= sizeof s->sid_ctx);
+	memcpy(&s->sid_ctx,&ctx->sid_ctx,sizeof(s->sid_ctx));
+	s->verify_callback=ctx->default_verify_callback;
+	s->session_creation_enabled=1;
+	s->generate_session_id=ctx->generate_session_id;
+
+	s->param = X509_VERIFY_PARAM_new();
+	if (!s->param)
+		goto err;
+	X509_VERIFY_PARAM_inherit(s->param, ctx->param);
+#if 0
+	s->purpose = ctx->purpose;
+	s->trust = ctx->trust;
+#endif
+	s->quiet_shutdown=ctx->quiet_shutdown;
+	s->max_send_fragment = ctx->max_send_fragment;
+
+	CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX);
+	s->ctx=ctx;
+#ifndef OPENSSL_NO_TLSEXT
+	s->tlsext_debug_cb = 0;
+	s->tlsext_debug_arg = NULL;
+	s->tlsext_ticket_expected = 0;
+	s->tlsext_status_type = -1;
+	s->tlsext_status_expected = 0;
+	s->tlsext_ocsp_ids = NULL;
+	s->tlsext_ocsp_exts = NULL;
+	s->tlsext_ocsp_resp = NULL;
+	s->tlsext_ocsp_resplen = -1;
+	CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX);
+	s->initial_ctx=ctx;
+#endif
+
+	s->verify_result=X509_V_OK;
+
+	s->method=ctx->method;
+
+	if (!s->method->ssl_new(s))
+		goto err;
+
+	s->references=1;
+	s->server=(ctx->method->ssl_accept == ssl_undefined_function)?0:1;
+
+	SSL_clear(s);
+
+	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data);
+
+#ifndef OPENSSL_NO_PSK
+	s->psk_client_callback=ctx->psk_client_callback;
+	s->psk_server_callback=ctx->psk_server_callback;
+#endif
+
+	return(s);
+err:
+	if (s != NULL)
+		{
+		if (s->cert != NULL)
+			ssl_cert_free(s->cert);
+		if (s->ctx != NULL)
+			SSL_CTX_free(s->ctx); /* decrement reference count */
+		OPENSSL_free(s);
+		}
+	SSLerr(SSL_F_SSL_NEW,ERR_R_MALLOC_FAILURE);
+	return(NULL);
+	}
+
+int SSL_CTX_set_session_id_context(SSL_CTX *ctx,const unsigned char *sid_ctx,
+				   unsigned int sid_ctx_len)
+    {
+    if(sid_ctx_len > sizeof ctx->sid_ctx)
+	{
+	SSLerr(SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT,SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
+	return 0;
+	}
+    ctx->sid_ctx_length=sid_ctx_len;
+    memcpy(ctx->sid_ctx,sid_ctx,sid_ctx_len);
+
+    return 1;
+    }
+
+int SSL_set_session_id_context(SSL *ssl,const unsigned char *sid_ctx,
+			       unsigned int sid_ctx_len)
+    {
+    if(sid_ctx_len > SSL_MAX_SID_CTX_LENGTH)
+	{
+	SSLerr(SSL_F_SSL_SET_SESSION_ID_CONTEXT,SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
+	return 0;
+	}
+    ssl->sid_ctx_length=sid_ctx_len;
+    memcpy(ssl->sid_ctx,sid_ctx,sid_ctx_len);
+
+    return 1;
+    }
+
+int SSL_CTX_set_generate_session_id(SSL_CTX *ctx, GEN_SESSION_CB cb)
+	{
+	CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
+	ctx->generate_session_id = cb;
+	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
+	return 1;
+	}
+
+int SSL_set_generate_session_id(SSL *ssl, GEN_SESSION_CB cb)
+	{
+	CRYPTO_w_lock(CRYPTO_LOCK_SSL);
+	ssl->generate_session_id = cb;
+	CRYPTO_w_unlock(CRYPTO_LOCK_SSL);
+	return 1;
+	}
+
+int SSL_has_matching_session_id(const SSL *ssl, const unsigned char *id,
+				unsigned int id_len)
+	{
+	/* A quick examination of SSL_SESSION_hash and SSL_SESSION_cmp shows how
+	 * we can "construct" a session to give us the desired check - ie. to
+	 * find if there's a session in the hash table that would conflict with
+	 * any new session built out of this id/id_len and the ssl_version in
+	 * use by this SSL. */
+	SSL_SESSION r, *p;
+
+	if(id_len > sizeof r.session_id)
+		return 0;
+
+	r.ssl_version = ssl->version;
+	r.session_id_length = id_len;
+	memcpy(r.session_id, id, id_len);
+	/* NB: SSLv2 always uses a fixed 16-byte session ID, so even if a
+	 * callback is calling us to check the uniqueness of a shorter ID, it
+	 * must be compared as a padded-out ID because that is what it will be
+	 * converted to when the callback has finished choosing it. */
+	if((r.ssl_version == SSL2_VERSION) &&
+			(id_len < SSL2_SSL_SESSION_ID_LENGTH))
+		{
+		memset(r.session_id + id_len, 0,
+			SSL2_SSL_SESSION_ID_LENGTH - id_len);
+		r.session_id_length = SSL2_SSL_SESSION_ID_LENGTH;
+		}
+
+	CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
+	p = lh_SSL_SESSION_retrieve(ssl->ctx->sessions, &r);
+	CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
+	return (p != NULL);
+	}
+
+int SSL_CTX_set_purpose(SSL_CTX *s, int purpose)
+	{
+	return X509_VERIFY_PARAM_set_purpose(s->param, purpose);
+	}
+
+int SSL_set_purpose(SSL *s, int purpose)
+	{
+	return X509_VERIFY_PARAM_set_purpose(s->param, purpose);
+	}
+
+int SSL_CTX_set_trust(SSL_CTX *s, int trust)
+	{
+	return X509_VERIFY_PARAM_set_trust(s->param, trust);
+	}
+
+int SSL_set_trust(SSL *s, int trust)
+	{
+	return X509_VERIFY_PARAM_set_trust(s->param, trust);
+	}
+
+int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm)
+	{
+	return X509_VERIFY_PARAM_set1(ctx->param, vpm);
+	}
+
+int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm)
+	{
+	return X509_VERIFY_PARAM_set1(ssl->param, vpm);
+	}
+
+void SSL_free(SSL *s)
+	{
+	int i;
+
+	if(s == NULL)
+	    return;
+
+	i=CRYPTO_add(&s->references,-1,CRYPTO_LOCK_SSL);
+#ifdef REF_PRINT
+	REF_PRINT("SSL",s);
+#endif
+	if (i > 0) return;
+#ifdef REF_CHECK
+	if (i < 0)
+		{
+		fprintf(stderr,"SSL_free, bad reference count\n");
+		abort(); /* ok */
+		}
+#endif
+
+	if (s->param)
+		X509_VERIFY_PARAM_free(s->param);
+
+	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data);
+
+	if (s->bbio != NULL)
+		{
+		/* If the buffering BIO is in place, pop it off */
+		if (s->bbio == s->wbio)
+			{
+			s->wbio=BIO_pop(s->wbio);
+			}
+		BIO_free(s->bbio);
+		s->bbio=NULL;
+		}
+	if (s->rbio != NULL)
+		BIO_free_all(s->rbio);
+	if ((s->wbio != NULL) && (s->wbio != s->rbio))
+		BIO_free_all(s->wbio);
+
+	if (s->init_buf != NULL) BUF_MEM_free(s->init_buf);
+
+	/* add extra stuff */
+	if (s->cipher_list != NULL) sk_SSL_CIPHER_free(s->cipher_list);
+	if (s->cipher_list_by_id != NULL) sk_SSL_CIPHER_free(s->cipher_list_by_id);
+
+	/* Make the next call work :-) */
+	if (s->session != NULL)
+		{
+		ssl_clear_bad_session(s);
+		SSL_SESSION_free(s->session);
+		}
+
+	ssl_clear_cipher_ctx(s);
+	ssl_clear_hash_ctx(&s->read_hash);
+	ssl_clear_hash_ctx(&s->write_hash);
+
+	if (s->cert != NULL) ssl_cert_free(s->cert);
+	/* Free up if allocated */
+
+#ifndef OPENSSL_NO_TLSEXT
+	if (s->tlsext_hostname)
+		OPENSSL_free(s->tlsext_hostname);
+	if (s->initial_ctx) SSL_CTX_free(s->initial_ctx);
+#ifndef OPENSSL_NO_EC
+	if (s->tlsext_ecpointformatlist) OPENSSL_free(s->tlsext_ecpointformatlist);
+	if (s->tlsext_ellipticcurvelist) OPENSSL_free(s->tlsext_ellipticcurvelist);
+#endif /* OPENSSL_NO_EC */
+	if (s->tlsext_opaque_prf_input) OPENSSL_free(s->tlsext_opaque_prf_input);
+	if (s->tlsext_ocsp_exts)
+		sk_X509_EXTENSION_pop_free(s->tlsext_ocsp_exts,
+						X509_EXTENSION_free);
+	if (s->tlsext_ocsp_ids)
+		sk_OCSP_RESPID_pop_free(s->tlsext_ocsp_ids, OCSP_RESPID_free);
+	if (s->tlsext_ocsp_resp)
+		OPENSSL_free(s->tlsext_ocsp_resp);
+#endif
+
+	if (s->client_CA != NULL)
+		sk_X509_NAME_pop_free(s->client_CA,X509_NAME_free);
+
+	if (s->method != NULL) s->method->ssl_free(s);
+
+	if (s->ctx) SSL_CTX_free(s->ctx);
+
+#ifndef	OPENSSL_NO_KRB5
+	if (s->kssl_ctx != NULL)
+		kssl_ctx_free(s->kssl_ctx);
+#endif	/* OPENSSL_NO_KRB5 */
+
+	OPENSSL_free(s);
+	}
+
+void SSL_set_bio(SSL *s,BIO *rbio,BIO *wbio)
+	{
+	/* If the output buffering BIO is still in place, remove it
+	 */
+	if (s->bbio != NULL)
+		{
+		if (s->wbio == s->bbio)
+			{
+			s->wbio=s->wbio->next_bio;
+			s->bbio->next_bio=NULL;
+			}
+		}
+	if ((s->rbio != NULL) && (s->rbio != rbio))
+		BIO_free_all(s->rbio);
+	if ((s->wbio != NULL) && (s->wbio != wbio) && (s->rbio != s->wbio))
+		BIO_free_all(s->wbio);
+	s->rbio=rbio;
+	s->wbio=wbio;
+	}
+
+BIO *SSL_get_rbio(const SSL *s)
+	{ return(s->rbio); }
+
+BIO *SSL_get_wbio(const SSL *s)
+	{ return(s->wbio); }
+
+int SSL_get_fd(const SSL *s)
+	{
+	return(SSL_get_rfd(s));
+	}
+
+int SSL_get_rfd(const SSL *s)
+	{
+	int ret= -1;
+	BIO *b,*r;
+
+	b=SSL_get_rbio(s);
+	r=BIO_find_type(b,BIO_TYPE_DESCRIPTOR);
+	if (r != NULL)
+		BIO_get_fd(r,&ret);
+	return(ret);
+	}
+
+int SSL_get_wfd(const SSL *s)
+	{
+	int ret= -1;
+	BIO *b,*r;
+
+	b=SSL_get_wbio(s);
+	r=BIO_find_type(b,BIO_TYPE_DESCRIPTOR);
+	if (r != NULL)
+		BIO_get_fd(r,&ret);
+	return(ret);
+	}
+
+#ifndef OPENSSL_NO_SOCK
+int SSL_set_fd(SSL *s,int fd)
+	{
+	int ret=0;
+	BIO *bio=NULL;
+
+	bio=BIO_new(BIO_s_socket());
+
+	if (bio == NULL)
+		{
+		SSLerr(SSL_F_SSL_SET_FD,ERR_R_BUF_LIB);
+		goto err;
+		}
+	BIO_set_fd(bio,fd,BIO_NOCLOSE);
+	SSL_set_bio(s,bio,bio);
+	ret=1;
+err:
+	return(ret);
+	}
+
+int SSL_set_wfd(SSL *s,int fd)
+	{
+	int ret=0;
+	BIO *bio=NULL;
+
+	if ((s->rbio == NULL) || (BIO_method_type(s->rbio) != BIO_TYPE_SOCKET)
+		|| ((int)BIO_get_fd(s->rbio,NULL) != fd))
+		{
+		bio=BIO_new(BIO_s_socket());
+
+		if (bio == NULL)
+			{ SSLerr(SSL_F_SSL_SET_WFD,ERR_R_BUF_LIB); goto err; }
+		BIO_set_fd(bio,fd,BIO_NOCLOSE);
+		SSL_set_bio(s,SSL_get_rbio(s),bio);
+		}
+	else
+		SSL_set_bio(s,SSL_get_rbio(s),SSL_get_rbio(s));
+	ret=1;
+err:
+	return(ret);
+	}
+
+int SSL_set_rfd(SSL *s,int fd)
+	{
+	int ret=0;
+	BIO *bio=NULL;
+
+	if ((s->wbio == NULL) || (BIO_method_type(s->wbio) != BIO_TYPE_SOCKET)
+		|| ((int)BIO_get_fd(s->wbio,NULL) != fd))
+		{
+		bio=BIO_new(BIO_s_socket());
+
+		if (bio == NULL)
+			{
+			SSLerr(SSL_F_SSL_SET_RFD,ERR_R_BUF_LIB);
+			goto err;
+			}
+		BIO_set_fd(bio,fd,BIO_NOCLOSE);
+		SSL_set_bio(s,bio,SSL_get_wbio(s));
+		}
+	else
+		SSL_set_bio(s,SSL_get_wbio(s),SSL_get_wbio(s));
+	ret=1;
+err:
+	return(ret);
+	}
+#endif
+
+
+/* return length of latest Finished message we sent, copy to 'buf' */
+size_t SSL_get_finished(const SSL *s, void *buf, size_t count)
+	{
+	size_t ret = 0;
+	
+	if (s->s3 != NULL)
+		{
+		ret = s->s3->tmp.finish_md_len;
+		if (count > ret)
+			count = ret;
+		memcpy(buf, s->s3->tmp.finish_md, count);
+		}
+	return ret;
+	}
+
+/* return length of latest Finished message we expected, copy to 'buf' */
+size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count)
+	{
+	size_t ret = 0;
+	
+	if (s->s3 != NULL)
+		{
+		ret = s->s3->tmp.peer_finish_md_len;
+		if (count > ret)
+			count = ret;
+		memcpy(buf, s->s3->tmp.peer_finish_md, count);
+		}
+	return ret;
+	}
+
+
+int SSL_get_verify_mode(const SSL *s)
+	{
+	return(s->verify_mode);
+	}
+
+int SSL_get_verify_depth(const SSL *s)
+	{
+	return X509_VERIFY_PARAM_get_depth(s->param);
+	}
+
+int (*SSL_get_verify_callback(const SSL *s))(int,X509_STORE_CTX *)
+	{
+	return(s->verify_callback);
+	}
+
+int SSL_CTX_get_verify_mode(const SSL_CTX *ctx)
+	{
+	return(ctx->verify_mode);
+	}
+
+int SSL_CTX_get_verify_depth(const SSL_CTX *ctx)
+	{
+	return X509_VERIFY_PARAM_get_depth(ctx->param);
+	}
+
+int (*SSL_CTX_get_verify_callback(const SSL_CTX *ctx))(int,X509_STORE_CTX *)
+	{
+	return(ctx->default_verify_callback);
+	}
+
+void SSL_set_verify(SSL *s,int mode,
+		    int (*callback)(int ok,X509_STORE_CTX *ctx))
+	{
+	s->verify_mode=mode;
+	if (callback != NULL)
+		s->verify_callback=callback;
+	}
+
+void SSL_set_verify_depth(SSL *s,int depth)
+	{
+	X509_VERIFY_PARAM_set_depth(s->param, depth);
+	}
+
+void SSL_set_read_ahead(SSL *s,int yes)
+	{
+	s->read_ahead=yes;
+	}
+
+int SSL_get_read_ahead(const SSL *s)
+	{
+	return(s->read_ahead);
+	}
+
+int SSL_pending(const SSL *s)
+	{
+	/* SSL_pending cannot work properly if read-ahead is enabled
+	 * (SSL_[CTX_]ctrl(..., SSL_CTRL_SET_READ_AHEAD, 1, NULL)),
+	 * and it is impossible to fix since SSL_pending cannot report
+	 * errors that may be observed while scanning the new data.
+	 * (Note that SSL_pending() is often used as a boolean value,
+	 * so we'd better not return -1.)
+	 */
+	return(s->method->ssl_pending(s));
+	}
+
+X509 *SSL_get_peer_certificate(const SSL *s)
+	{
+	X509 *r;
+	
+	if ((s == NULL) || (s->session == NULL))
+		r=NULL;
+	else
+		r=s->session->peer;
+
+	if (r == NULL) return(r);
+
+	CRYPTO_add(&r->references,1,CRYPTO_LOCK_X509);
+
+	return(r);
+	}
+
+STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *s)
+	{
+	STACK_OF(X509) *r;
+	
+	if ((s == NULL) || (s->session == NULL) || (s->session->sess_cert == NULL))
+		r=NULL;
+	else
+		r=s->session->sess_cert->cert_chain;
+
+	/* If we are a client, cert_chain includes the peer's own
+	 * certificate; if we are a server, it does not. */
+	
+	return(r);
+	}
+
+/* Now in theory, since the calling process own 't' it should be safe to
+ * modify.  We need to be able to read f without being hassled */
+void SSL_copy_session_id(SSL *t,const SSL *f)
+	{
+	CERT *tmp;
+
+	/* Do we need to to SSL locking? */
+	SSL_set_session(t,SSL_get_session(f));
+
+	/* what if we are setup as SSLv2 but want to talk SSLv3 or
+	 * vice-versa */
+	if (t->method != f->method)
+		{
+		t->method->ssl_free(t);	/* cleanup current */
+		t->method=f->method;	/* change method */
+		t->method->ssl_new(t);	/* setup new */
+		}
+
+	tmp=t->cert;
+	if (f->cert != NULL)
+		{
+		CRYPTO_add(&f->cert->references,1,CRYPTO_LOCK_SSL_CERT);
+		t->cert=f->cert;
+		}
+	else
+		t->cert=NULL;
+	if (tmp != NULL) ssl_cert_free(tmp);
+	SSL_set_session_id_context(t,f->sid_ctx,f->sid_ctx_length);
+	}
+
+/* Fix this so it checks all the valid key/cert options */
+int SSL_CTX_check_private_key(const SSL_CTX *ctx)
+	{
+	if (	(ctx == NULL) ||
+		(ctx->cert == NULL) ||
+		(ctx->cert->key->x509 == NULL))
+		{
+		SSLerr(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY,SSL_R_NO_CERTIFICATE_ASSIGNED);
+		return(0);
+		}
+	if 	(ctx->cert->key->privatekey == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY,SSL_R_NO_PRIVATE_KEY_ASSIGNED);
+		return(0);
+		}
+	return(X509_check_private_key(ctx->cert->key->x509, ctx->cert->key->privatekey));
+	}
+
+/* Fix this function so that it takes an optional type parameter */
+int SSL_check_private_key(const SSL *ssl)
+	{
+	if (ssl == NULL)
+		{
+		SSLerr(SSL_F_SSL_CHECK_PRIVATE_KEY,ERR_R_PASSED_NULL_PARAMETER);
+		return(0);
+		}
+	if (ssl->cert == NULL)
+		{
+		SSLerr(SSL_F_SSL_CHECK_PRIVATE_KEY,SSL_R_NO_CERTIFICATE_ASSIGNED);
+		return 0;
+		}
+	if (ssl->cert->key->x509 == NULL)
+		{
+		SSLerr(SSL_F_SSL_CHECK_PRIVATE_KEY,SSL_R_NO_CERTIFICATE_ASSIGNED);
+		return(0);
+		}
+	if (ssl->cert->key->privatekey == NULL)
+		{
+		SSLerr(SSL_F_SSL_CHECK_PRIVATE_KEY,SSL_R_NO_PRIVATE_KEY_ASSIGNED);
+		return(0);
+		}
+	return(X509_check_private_key(ssl->cert->key->x509,
+		ssl->cert->key->privatekey));
+	}
+
+int SSL_accept(SSL *s)
+	{
+	if (s->handshake_func == 0)
+		/* Not properly initialized yet */
+		SSL_set_accept_state(s);
+
+	return(s->method->ssl_accept(s));
+	}
+
+int SSL_connect(SSL *s)
+	{
+	if (s->handshake_func == 0)
+		/* Not properly initialized yet */
+		SSL_set_connect_state(s);
+
+	return(s->method->ssl_connect(s));
+	}
+
+long SSL_get_default_timeout(const SSL *s)
+	{
+	return(s->method->get_timeout());
+	}
+
+int SSL_read(SSL *s,void *buf,int num)
+	{
+	if (s->handshake_func == 0)
+		{
+		SSLerr(SSL_F_SSL_READ, SSL_R_UNINITIALIZED);
+		return -1;
+		}
+
+	if (s->shutdown & SSL_RECEIVED_SHUTDOWN)
+		{
+		s->rwstate=SSL_NOTHING;
+		return(0);
+		}
+	return(s->method->ssl_read(s,buf,num));
+	}
+
+int SSL_peek(SSL *s,void *buf,int num)
+	{
+	if (s->handshake_func == 0)
+		{
+		SSLerr(SSL_F_SSL_PEEK, SSL_R_UNINITIALIZED);
+		return -1;
+		}
+
+	if (s->shutdown & SSL_RECEIVED_SHUTDOWN)
+		{
+		return(0);
+		}
+	return(s->method->ssl_peek(s,buf,num));
+	}
+
+int SSL_write(SSL *s,const void *buf,int num)
+	{
+	if (s->handshake_func == 0)
+		{
+		SSLerr(SSL_F_SSL_WRITE, SSL_R_UNINITIALIZED);
+		return -1;
+		}
+
+	if (s->shutdown & SSL_SENT_SHUTDOWN)
+		{
+		s->rwstate=SSL_NOTHING;
+		SSLerr(SSL_F_SSL_WRITE,SSL_R_PROTOCOL_IS_SHUTDOWN);
+		return(-1);
+		}
+	return(s->method->ssl_write(s,buf,num));
+	}
+
+int SSL_shutdown(SSL *s)
+	{
+	/* Note that this function behaves differently from what one might
+	 * expect.  Return values are 0 for no success (yet),
+	 * 1 for success; but calling it once is usually not enough,
+	 * even if blocking I/O is used (see ssl3_shutdown).
+	 */
+
+	if (s->handshake_func == 0)
+		{
+		SSLerr(SSL_F_SSL_SHUTDOWN, SSL_R_UNINITIALIZED);
+		return -1;
+		}
+
+	if ((s != NULL) && !SSL_in_init(s))
+		return(s->method->ssl_shutdown(s));
+	else
+		return(1);
+	}
+
+int SSL_renegotiate(SSL *s)
+	{
+	if (s->new_session == 0)
+		{
+		s->new_session=1;
+		}
+	return(s->method->ssl_renegotiate(s));
+	}
+
+int SSL_renegotiate_pending(SSL *s)
+	{
+	/* becomes true when negotiation is requested;
+	 * false again once a handshake has finished */
+	return (s->new_session != 0);
+	}
+
+long SSL_ctrl(SSL *s,int cmd,long larg,void *parg)
+	{
+	long l;
+
+	switch (cmd)
+		{
+	case SSL_CTRL_GET_READ_AHEAD:
+		return(s->read_ahead);
+	case SSL_CTRL_SET_READ_AHEAD:
+		l=s->read_ahead;
+		s->read_ahead=larg;
+		return(l);
+
+	case SSL_CTRL_SET_MSG_CALLBACK_ARG:
+		s->msg_callback_arg = parg;
+		return 1;
+
+	case SSL_CTRL_OPTIONS:
+		return(s->options|=larg);
+	case SSL_CTRL_CLEAR_OPTIONS:
+		return(s->options&=~larg);
+	case SSL_CTRL_MODE:
+		return(s->mode|=larg);
+	case SSL_CTRL_CLEAR_MODE:
+		return(s->mode &=~larg);
+	case SSL_CTRL_GET_MAX_CERT_LIST:
+		return(s->max_cert_list);
+	case SSL_CTRL_SET_MAX_CERT_LIST:
+		l=s->max_cert_list;
+		s->max_cert_list=larg;
+		return(l);
+	case SSL_CTRL_SET_MTU:
+		if (SSL_version(s) == DTLS1_VERSION ||
+		    SSL_version(s) == DTLS1_BAD_VER)
+			{
+			s->d1->mtu = larg;
+			return larg;
+			}
+		return 0;
+	case SSL_CTRL_SET_MAX_SEND_FRAGMENT:
+		if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH)
+			return 0;
+		s->max_send_fragment = larg;
+		return 1;
+	case SSL_CTRL_GET_RI_SUPPORT:
+		if (s->s3)
+			return s->s3->send_connection_binding;
+		else return 0;
+	default:
+		return(s->method->ssl_ctrl(s,cmd,larg,parg));
+		}
+	}
+
+long SSL_callback_ctrl(SSL *s, int cmd, void (*fp)(void))
+	{
+	switch(cmd)
+		{
+	case SSL_CTRL_SET_MSG_CALLBACK:
+		s->msg_callback = (void (*)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg))(fp);
+		return 1;
+		
+	default:
+		return(s->method->ssl_callback_ctrl(s,cmd,fp));
+		}
+	}
+
+LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx)
+	{
+	return ctx->sessions;
+	}
+
+long SSL_CTX_ctrl(SSL_CTX *ctx,int cmd,long larg,void *parg)
+	{
+	long l;
+
+	switch (cmd)
+		{
+	case SSL_CTRL_GET_READ_AHEAD:
+		return(ctx->read_ahead);
+	case SSL_CTRL_SET_READ_AHEAD:
+		l=ctx->read_ahead;
+		ctx->read_ahead=larg;
+		return(l);
+		
+	case SSL_CTRL_SET_MSG_CALLBACK_ARG:
+		ctx->msg_callback_arg = parg;
+		return 1;
+
+	case SSL_CTRL_GET_MAX_CERT_LIST:
+		return(ctx->max_cert_list);
+	case SSL_CTRL_SET_MAX_CERT_LIST:
+		l=ctx->max_cert_list;
+		ctx->max_cert_list=larg;
+		return(l);
+
+	case SSL_CTRL_SET_SESS_CACHE_SIZE:
+		l=ctx->session_cache_size;
+		ctx->session_cache_size=larg;
+		return(l);
+	case SSL_CTRL_GET_SESS_CACHE_SIZE:
+		return(ctx->session_cache_size);
+	case SSL_CTRL_SET_SESS_CACHE_MODE:
+		l=ctx->session_cache_mode;
+		ctx->session_cache_mode=larg;
+		return(l);
+	case SSL_CTRL_GET_SESS_CACHE_MODE:
+		return(ctx->session_cache_mode);
+
+	case SSL_CTRL_SESS_NUMBER:
+		return(lh_SSL_SESSION_num_items(ctx->sessions));
+	case SSL_CTRL_SESS_CONNECT:
+		return(ctx->stats.sess_connect);
+	case SSL_CTRL_SESS_CONNECT_GOOD:
+		return(ctx->stats.sess_connect_good);
+	case SSL_CTRL_SESS_CONNECT_RENEGOTIATE:
+		return(ctx->stats.sess_connect_renegotiate);
+	case SSL_CTRL_SESS_ACCEPT:
+		return(ctx->stats.sess_accept);
+	case SSL_CTRL_SESS_ACCEPT_GOOD:
+		return(ctx->stats.sess_accept_good);
+	case SSL_CTRL_SESS_ACCEPT_RENEGOTIATE:
+		return(ctx->stats.sess_accept_renegotiate);
+	case SSL_CTRL_SESS_HIT:
+		return(ctx->stats.sess_hit);
+	case SSL_CTRL_SESS_CB_HIT:
+		return(ctx->stats.sess_cb_hit);
+	case SSL_CTRL_SESS_MISSES:
+		return(ctx->stats.sess_miss);
+	case SSL_CTRL_SESS_TIMEOUTS:
+		return(ctx->stats.sess_timeout);
+	case SSL_CTRL_SESS_CACHE_FULL:
+		return(ctx->stats.sess_cache_full);
+	case SSL_CTRL_OPTIONS:
+		return(ctx->options|=larg);
+	case SSL_CTRL_CLEAR_OPTIONS:
+		return(ctx->options&=~larg);
+	case SSL_CTRL_MODE:
+		return(ctx->mode|=larg);
+	case SSL_CTRL_CLEAR_MODE:
+		return(ctx->mode&=~larg);
+	case SSL_CTRL_SET_MAX_SEND_FRAGMENT:
+		if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH)
+			return 0;
+		ctx->max_send_fragment = larg;
+		return 1;
+	default:
+		return(ctx->method->ssl_ctx_ctrl(ctx,cmd,larg,parg));
+		}
+	}
+
+long SSL_CTX_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp)(void))
+	{
+	switch(cmd)
+		{
+	case SSL_CTRL_SET_MSG_CALLBACK:
+		ctx->msg_callback = (void (*)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg))(fp);
+		return 1;
+
+	default:
+		return(ctx->method->ssl_ctx_callback_ctrl(ctx,cmd,fp));
+		}
+	}
+
+int ssl_cipher_id_cmp(const SSL_CIPHER *a, const SSL_CIPHER *b)
+	{
+	long l;
+
+	l=a->id-b->id;
+	if (l == 0L)
+		return(0);
+	else
+		return((l > 0)?1:-1);
+	}
+
+int ssl_cipher_ptr_id_cmp(const SSL_CIPHER * const *ap,
+			const SSL_CIPHER * const *bp)
+	{
+	long l;
+
+	l=(*ap)->id-(*bp)->id;
+	if (l == 0L)
+		return(0);
+	else
+		return((l > 0)?1:-1);
+	}
+
+/** return a STACK of the ciphers available for the SSL and in order of
+ * preference */
+STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s)
+	{
+	if (s != NULL)
+		{
+		if (s->cipher_list != NULL)
+			{
+			return(s->cipher_list);
+			}
+		else if ((s->ctx != NULL) &&
+			(s->ctx->cipher_list != NULL))
+			{
+			return(s->ctx->cipher_list);
+			}
+		}
+	return(NULL);
+	}
+
+/** return a STACK of the ciphers available for the SSL and in order of
+ * algorithm id */
+STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s)
+	{
+	if (s != NULL)
+		{
+		if (s->cipher_list_by_id != NULL)
+			{
+			return(s->cipher_list_by_id);
+			}
+		else if ((s->ctx != NULL) &&
+			(s->ctx->cipher_list_by_id != NULL))
+			{
+			return(s->ctx->cipher_list_by_id);
+			}
+		}
+	return(NULL);
+	}
+
+/** The old interface to get the same thing as SSL_get_ciphers() */
+const char *SSL_get_cipher_list(const SSL *s,int n)
+	{
+	SSL_CIPHER *c;
+	STACK_OF(SSL_CIPHER) *sk;
+
+	if (s == NULL) return(NULL);
+	sk=SSL_get_ciphers(s);
+	if ((sk == NULL) || (sk_SSL_CIPHER_num(sk) <= n))
+		return(NULL);
+	c=sk_SSL_CIPHER_value(sk,n);
+	if (c == NULL) return(NULL);
+	return(c->name);
+	}
+
+/** specify the ciphers to be used by default by the SSL_CTX */
+int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str)
+	{
+	STACK_OF(SSL_CIPHER) *sk;
+	
+	sk=ssl_create_cipher_list(ctx->method,&ctx->cipher_list,
+		&ctx->cipher_list_by_id,str);
+	/* ssl_create_cipher_list may return an empty stack if it
+	 * was unable to find a cipher matching the given rule string
+	 * (for example if the rule string specifies a cipher which
+	 * has been disabled). This is not an error as far as
+	 * ssl_create_cipher_list is concerned, and hence
+	 * ctx->cipher_list and ctx->cipher_list_by_id has been
+	 * updated. */
+	if (sk == NULL)
+		return 0;
+	else if (sk_SSL_CIPHER_num(sk) == 0)
+		{
+		SSLerr(SSL_F_SSL_CTX_SET_CIPHER_LIST, SSL_R_NO_CIPHER_MATCH);
+		return 0;
+		}
+	return 1;
+	}
+
+/** specify the ciphers to be used by the SSL */
+int SSL_set_cipher_list(SSL *s,const char *str)
+	{
+	STACK_OF(SSL_CIPHER) *sk;
+	
+	sk=ssl_create_cipher_list(s->ctx->method,&s->cipher_list,
+		&s->cipher_list_by_id,str);
+	/* see comment in SSL_CTX_set_cipher_list */
+	if (sk == NULL)
+		return 0;
+	else if (sk_SSL_CIPHER_num(sk) == 0)
+		{
+		SSLerr(SSL_F_SSL_SET_CIPHER_LIST, SSL_R_NO_CIPHER_MATCH);
+		return 0;
+		}
+	return 1;
+	}
+
+/** specify the ciphers to be used by the SSL */
+int SSL_set_cipher_lists(SSL *s,STACK_OF(SSL_CIPHER) *sk)
+	{
+	STACK_OF(SSL_CIPHER) *tmp_cipher_list;
+
+	if (sk == NULL)
+		return 0;
+
+        /* Based on end of ssl_create_cipher_list */
+	tmp_cipher_list = sk_SSL_CIPHER_dup(sk);
+	if (tmp_cipher_list == NULL)
+		{
+		return 0;
+		}
+	if (s->cipher_list != NULL)
+		sk_SSL_CIPHER_free(s->cipher_list);
+	s->cipher_list = sk;
+	if (s->cipher_list_by_id != NULL)
+		sk_SSL_CIPHER_free(s->cipher_list_by_id);
+	s->cipher_list_by_id = tmp_cipher_list;
+	(void)sk_SSL_CIPHER_set_cmp_func(s->cipher_list_by_id,ssl_cipher_ptr_id_cmp);
+
+	sk_SSL_CIPHER_sort(s->cipher_list_by_id);
+	return 1;
+	}
+
+/* works well for SSLv2, not so good for SSLv3 */
+char *SSL_get_shared_ciphers(const SSL *s,char *buf,int len)
+	{
+	char *p;
+	STACK_OF(SSL_CIPHER) *sk;
+	SSL_CIPHER *c;
+	int i;
+
+	if ((s->session == NULL) || (s->session->ciphers == NULL) ||
+		(len < 2))
+		return(NULL);
+
+	p=buf;
+	sk=s->session->ciphers;
+	for (i=0; i<sk_SSL_CIPHER_num(sk); i++)
+		{
+		int n;
+
+		c=sk_SSL_CIPHER_value(sk,i);
+		n=strlen(c->name);
+		if (n+1 > len)
+			{
+			if (p != buf)
+				--p;
+			*p='\0';
+			return buf;
+			}
+		strcpy(p,c->name);
+		p+=n;
+		*(p++)=':';
+		len-=n+1;
+		}
+	p[-1]='\0';
+	return(buf);
+	}
+
+int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p,
+			     int (*put_cb)(const SSL_CIPHER *, unsigned char *))
+	{
+	int i,j=0;
+	SSL_CIPHER *c;
+	unsigned char *q;
+#ifndef OPENSSL_NO_KRB5
+	int nokrb5 = !kssl_tgt_is_available(s->kssl_ctx);
+#endif /* OPENSSL_NO_KRB5 */
+
+	if (sk == NULL) return(0);
+	q=p;
+
+	for (i=0; i<sk_SSL_CIPHER_num(sk); i++)
+		{
+		c=sk_SSL_CIPHER_value(sk,i);
+#ifndef OPENSSL_NO_KRB5
+		if (((c->algorithm_mkey & SSL_kKRB5) || (c->algorithm_auth & SSL_aKRB5)) &&
+		    nokrb5)
+		    continue;
+#endif /* OPENSSL_NO_KRB5 */
+#ifndef OPENSSL_NO_PSK
+		/* with PSK there must be client callback set */
+		if (((c->algorithm_mkey & SSL_kPSK) || (c->algorithm_auth & SSL_aPSK)) &&
+		    s->psk_client_callback == NULL)
+			continue;
+#endif /* OPENSSL_NO_PSK */
+		j = put_cb ? put_cb(c,p) : ssl_put_cipher_by_char(s,c,p);
+		p+=j;
+		}
+	/* If p == q, no ciphers and caller indicates an error. Otherwise
+	 * add SCSV if not renegotiating.
+	 */
+	if (p != q && !s->new_session)
+		{
+		static SSL_CIPHER scsv =
+			{
+			0, NULL, SSL3_CK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0
+			};
+		j = put_cb ? put_cb(&scsv,p) : ssl_put_cipher_by_char(s,&scsv,p);
+		p+=j;
+#ifdef OPENSSL_RI_DEBUG
+		fprintf(stderr, "SCSV sent by client\n");
+#endif
+		}
+
+	return(p-q);
+	}
+
+STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num,
+					       STACK_OF(SSL_CIPHER) **skp)
+	{
+	const SSL_CIPHER *c;
+	STACK_OF(SSL_CIPHER) *sk;
+	int i,n;
+	if (s->s3)
+		s->s3->send_connection_binding = 0;
+
+	n=ssl_put_cipher_by_char(s,NULL,NULL);
+	if ((num%n) != 0)
+		{
+		SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);
+		return(NULL);
+		}
+	if ((skp == NULL) || (*skp == NULL))
+		sk=sk_SSL_CIPHER_new_null(); /* change perhaps later */
+	else
+		{
+		sk= *skp;
+		sk_SSL_CIPHER_zero(sk);
+		}
+
+	for (i=0; i<num; i+=n)
+		{
+		/* Check for SCSV */
+		if (s->s3 && (n != 3 || !p[0]) &&
+			(p[n-2] == ((SSL3_CK_SCSV >> 8) & 0xff)) &&
+			(p[n-1] == (SSL3_CK_SCSV & 0xff)))
+			{
+			/* SCSV fatal if renegotiating */
+			if (s->new_session)
+				{
+				SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING);
+				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE); 
+				goto err;
+				}
+			s->s3->send_connection_binding = 1;
+			p += n;
+#ifdef OPENSSL_RI_DEBUG
+			fprintf(stderr, "SCSV received by server\n");
+#endif
+			continue;
+			}
+
+		c=ssl_get_cipher_by_char(s,p);
+		p+=n;
+		if (c != NULL)
+			{
+			if (!sk_SSL_CIPHER_push(sk,c))
+				{
+				SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,ERR_R_MALLOC_FAILURE);
+				goto err;
+				}
+			}
+		}
+
+	if (skp != NULL)
+		*skp=sk;
+	return(sk);
+err:
+	if ((skp == NULL) || (*skp == NULL))
+		sk_SSL_CIPHER_free(sk);
+	return(NULL);
+	}
+
+
+#ifndef OPENSSL_NO_TLSEXT
+/** return a servername extension value if provided in Client Hello, or NULL.
+ * So far, only host_name types are defined (RFC 3546).
+ */
+
+const char *SSL_get_servername(const SSL *s, const int type)
+	{
+	if (type != TLSEXT_NAMETYPE_host_name)
+		return NULL;
+
+	return s->session && !s->tlsext_hostname ?
+		s->session->tlsext_hostname :
+		s->tlsext_hostname;
+	}
+
+int SSL_get_servername_type(const SSL *s)
+	{
+	if (s->session && (!s->tlsext_hostname ? s->session->tlsext_hostname : s->tlsext_hostname))
+		return TLSEXT_NAMETYPE_host_name;
+	return -1;
+	}
+#endif
+
+static unsigned long ssl_session_hash(const SSL_SESSION *a)
+	{
+	unsigned long l;
+
+	l=(unsigned long)
+		((unsigned int) a->session_id[0]     )|
+		((unsigned int) a->session_id[1]<< 8L)|
+		((unsigned long)a->session_id[2]<<16L)|
+		((unsigned long)a->session_id[3]<<24L);
+	return(l);
+	}
+
+/* NB: If this function (or indeed the hash function which uses a sort of
+ * coarser function than this one) is changed, ensure
+ * SSL_CTX_has_matching_session_id() is checked accordingly. It relies on being
+ * able to construct an SSL_SESSION that will collide with any existing session
+ * with a matching session ID. */
+static int ssl_session_cmp(const SSL_SESSION *a,const SSL_SESSION *b)
+	{
+	if (a->ssl_version != b->ssl_version)
+		return(1);
+	if (a->session_id_length != b->session_id_length)
+		return(1);
+	return(memcmp(a->session_id,b->session_id,a->session_id_length));
+	}
+
+/* These wrapper functions should remain rather than redeclaring
+ * SSL_SESSION_hash and SSL_SESSION_cmp for void* types and casting each
+ * variable. The reason is that the functions aren't static, they're exposed via
+ * ssl.h. */
+static IMPLEMENT_LHASH_HASH_FN(ssl_session, SSL_SESSION)
+static IMPLEMENT_LHASH_COMP_FN(ssl_session, SSL_SESSION)
+
+SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
+	{
+	SSL_CTX *ret=NULL;
+
+	if (meth == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_NULL_SSL_METHOD_PASSED);
+		return(NULL);
+		}
+
+	if (SSL_get_ex_data_X509_STORE_CTX_idx() < 0)
+		{
+		SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_X509_VERIFICATION_SETUP_PROBLEMS);
+		goto err;
+		}
+	ret=(SSL_CTX *)OPENSSL_malloc(sizeof(SSL_CTX));
+	if (ret == NULL)
+		goto err;
+
+	memset(ret,0,sizeof(SSL_CTX));
+
+	ret->method=meth;
+
+	ret->cert_store=NULL;
+	ret->session_cache_mode=SSL_SESS_CACHE_SERVER;
+	ret->session_cache_size=SSL_SESSION_CACHE_MAX_SIZE_DEFAULT;
+	ret->session_cache_head=NULL;
+	ret->session_cache_tail=NULL;
+
+	/* We take the system default */
+	ret->session_timeout=meth->get_timeout();
+
+	ret->new_session_cb=0;
+	ret->remove_session_cb=0;
+	ret->get_session_cb=0;
+	ret->generate_session_id=0;
+
+	memset((char *)&ret->stats,0,sizeof(ret->stats));
+
+	ret->references=1;
+	ret->quiet_shutdown=0;
+
+/*	ret->cipher=NULL;*/
+/*	ret->s2->challenge=NULL;
+	ret->master_key=NULL;
+	ret->key_arg=NULL;
+	ret->s2->conn_id=NULL; */
+
+	ret->info_callback=NULL;
+
+	ret->app_verify_callback=0;
+	ret->app_verify_arg=NULL;
+
+	ret->max_cert_list=SSL_MAX_CERT_LIST_DEFAULT;
+	ret->read_ahead=0;
+	ret->msg_callback=0;
+	ret->msg_callback_arg=NULL;
+	ret->verify_mode=SSL_VERIFY_NONE;
+#if 0
+	ret->verify_depth=-1; /* Don't impose a limit (but x509_lu.c does) */
+#endif
+	ret->sid_ctx_length=0;
+	ret->default_verify_callback=NULL;
+	if ((ret->cert=ssl_cert_new()) == NULL)
+		goto err;
+
+	ret->default_passwd_callback=0;
+	ret->default_passwd_callback_userdata=NULL;
+	ret->client_cert_cb=0;
+	ret->app_gen_cookie_cb=0;
+	ret->app_verify_cookie_cb=0;
+
+	ret->sessions=lh_SSL_SESSION_new();
+	if (ret->sessions == NULL) goto err;
+	ret->cert_store=X509_STORE_new();
+	if (ret->cert_store == NULL) goto err;
+
+	ssl_create_cipher_list(ret->method,
+		&ret->cipher_list,&ret->cipher_list_by_id,
+		meth->version == SSL2_VERSION ? "SSLv2" : SSL_DEFAULT_CIPHER_LIST);
+	if (ret->cipher_list == NULL
+	    || sk_SSL_CIPHER_num(ret->cipher_list) <= 0)
+		{
+		SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_LIBRARY_HAS_NO_CIPHERS);
+		goto err2;
+		}
+
+	ret->param = X509_VERIFY_PARAM_new();
+	if (!ret->param)
+		goto err;
+
+	if ((ret->rsa_md5=EVP_get_digestbyname("ssl2-md5")) == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES);
+		goto err2;
+		}
+	if ((ret->md5=EVP_get_digestbyname("ssl3-md5")) == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES);
+		goto err2;
+		}
+	if ((ret->sha1=EVP_get_digestbyname("ssl3-sha1")) == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES);
+		goto err2;
+		}
+
+	if ((ret->client_CA=sk_X509_NAME_new_null()) == NULL)
+		goto err;
+
+	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_CTX, ret, &ret->ex_data);
+
+	ret->extra_certs=NULL;
+	ret->comp_methods=SSL_COMP_get_compression_methods();
+
+	ret->max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH;
+
+#ifndef OPENSSL_NO_TLSEXT
+	ret->tlsext_servername_callback = 0;
+	ret->tlsext_servername_arg = NULL;
+	/* Setup RFC4507 ticket keys */
+	if ((RAND_pseudo_bytes(ret->tlsext_tick_key_name, 16) <= 0)
+		|| (RAND_bytes(ret->tlsext_tick_hmac_key, 16) <= 0)
+		|| (RAND_bytes(ret->tlsext_tick_aes_key, 16) <= 0))
+		ret->options |= SSL_OP_NO_TICKET;
+
+	ret->tlsext_status_cb = 0;
+	ret->tlsext_status_arg = NULL;
+
+#endif
+#ifndef OPENSSL_NO_PSK
+	ret->psk_identity_hint=NULL;
+	ret->psk_client_callback=NULL;
+	ret->psk_server_callback=NULL;
+#endif
+#ifndef OPENSSL_NO_BUF_FREELISTS
+	ret->freelist_max_len = SSL_MAX_BUF_FREELIST_LEN_DEFAULT;
+	ret->rbuf_freelist = OPENSSL_malloc(sizeof(SSL3_BUF_FREELIST));
+	if (!ret->rbuf_freelist)
+		goto err;
+	ret->rbuf_freelist->chunklen = 0;
+	ret->rbuf_freelist->len = 0;
+	ret->rbuf_freelist->head = NULL;
+	ret->wbuf_freelist = OPENSSL_malloc(sizeof(SSL3_BUF_FREELIST));
+	if (!ret->wbuf_freelist)
+		{
+		OPENSSL_free(ret->rbuf_freelist);
+		goto err;
+		}
+	ret->wbuf_freelist->chunklen = 0;
+	ret->wbuf_freelist->len = 0;
+	ret->wbuf_freelist->head = NULL;
+#endif
+#ifndef OPENSSL_NO_ENGINE
+	ret->client_cert_engine = NULL;
+#ifdef OPENSSL_SSL_CLIENT_ENGINE_AUTO
+#define eng_strx(x)	#x
+#define eng_str(x)	eng_strx(x)
+	/* Use specific client engine automatically... ignore errors */
+	{
+	ENGINE *eng;
+	eng = ENGINE_by_id(eng_str(OPENSSL_SSL_CLIENT_ENGINE_AUTO));
+	if (!eng)
+		{
+		ERR_clear_error();
+		ENGINE_load_builtin_engines();
+		eng = ENGINE_by_id(eng_str(OPENSSL_SSL_CLIENT_ENGINE_AUTO));
+		}
+	if (!eng || !SSL_CTX_set_client_cert_engine(ret, eng))
+		ERR_clear_error();
+	}
+#endif
+#endif
+	/* Default is to connect to non-RI servers. When RI is more widely
+	 * deployed might change this.
+	 */
+	ret->options |= SSL_OP_LEGACY_SERVER_CONNECT;
+
+	return(ret);
+err:
+	SSLerr(SSL_F_SSL_CTX_NEW,ERR_R_MALLOC_FAILURE);
+err2:
+	if (ret != NULL) SSL_CTX_free(ret);
+	return(NULL);
+	}
+
+#if 0
+static void SSL_COMP_free(SSL_COMP *comp)
+    { OPENSSL_free(comp); }
+#endif
+
+#ifndef OPENSSL_NO_BUF_FREELISTS
+static void
+ssl_buf_freelist_free(SSL3_BUF_FREELIST *list)
+	{
+	SSL3_BUF_FREELIST_ENTRY *ent, *next;
+	for (ent = list->head; ent; ent = next)
+		{
+		next = ent->next;
+		OPENSSL_free(ent);
+		}
+	OPENSSL_free(list);
+	}
+#endif
+
+void SSL_CTX_free(SSL_CTX *a)
+	{
+	int i;
+
+	if (a == NULL) return;
+
+	i=CRYPTO_add(&a->references,-1,CRYPTO_LOCK_SSL_CTX);
+#ifdef REF_PRINT
+	REF_PRINT("SSL_CTX",a);
+#endif
+	if (i > 0) return;
+#ifdef REF_CHECK
+	if (i < 0)
+		{
+		fprintf(stderr,"SSL_CTX_free, bad reference count\n");
+		abort(); /* ok */
+		}
+#endif
+
+	if (a->param)
+		X509_VERIFY_PARAM_free(a->param);
+
+	/*
+	 * Free internal session cache. However: the remove_cb() may reference
+	 * the ex_data of SSL_CTX, thus the ex_data store can only be removed
+	 * after the sessions were flushed.
+	 * As the ex_data handling routines might also touch the session cache,
+	 * the most secure solution seems to be: empty (flush) the cache, then
+	 * free ex_data, then finally free the cache.
+	 * (See ticket [openssl.org #212].)
+	 */
+	if (a->sessions != NULL)
+		SSL_CTX_flush_sessions(a,0);
+
+	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_CTX, a, &a->ex_data);
+
+	if (a->sessions != NULL)
+		lh_SSL_SESSION_free(a->sessions);
+
+	if (a->cert_store != NULL)
+		X509_STORE_free(a->cert_store);
+	if (a->cipher_list != NULL)
+		sk_SSL_CIPHER_free(a->cipher_list);
+	if (a->cipher_list_by_id != NULL)
+		sk_SSL_CIPHER_free(a->cipher_list_by_id);
+	if (a->cert != NULL)
+		ssl_cert_free(a->cert);
+	if (a->client_CA != NULL)
+		sk_X509_NAME_pop_free(a->client_CA,X509_NAME_free);
+	if (a->extra_certs != NULL)
+		sk_X509_pop_free(a->extra_certs,X509_free);
+#if 0 /* This should never be done, since it removes a global database */
+	if (a->comp_methods != NULL)
+		sk_SSL_COMP_pop_free(a->comp_methods,SSL_COMP_free);
+#else
+	a->comp_methods = NULL;
+#endif
+
+#ifndef OPENSSL_NO_PSK
+	if (a->psk_identity_hint)
+		OPENSSL_free(a->psk_identity_hint);
+#endif
+#ifndef OPENSSL_NO_ENGINE
+	if (a->client_cert_engine)
+		ENGINE_finish(a->client_cert_engine);
+#endif
+
+#ifndef OPENSSL_NO_BUF_FREELISTS
+	if (a->wbuf_freelist)
+		ssl_buf_freelist_free(a->wbuf_freelist);
+	if (a->rbuf_freelist)
+		ssl_buf_freelist_free(a->rbuf_freelist);
+#endif
+
+	OPENSSL_free(a);
+	}
+
+void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb)
+	{
+	ctx->default_passwd_callback=cb;
+	}
+
+void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx,void *u)
+	{
+	ctx->default_passwd_callback_userdata=u;
+	}
+
+void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, int (*cb)(X509_STORE_CTX *,void *), void *arg)
+	{
+	ctx->app_verify_callback=cb;
+	ctx->app_verify_arg=arg;
+	}
+
+void SSL_CTX_set_verify(SSL_CTX *ctx,int mode,int (*cb)(int, X509_STORE_CTX *))
+	{
+	ctx->verify_mode=mode;
+	ctx->default_verify_callback=cb;
+	}
+
+void SSL_CTX_set_verify_depth(SSL_CTX *ctx,int depth)
+	{
+	X509_VERIFY_PARAM_set_depth(ctx->param, depth);
+	}
+
+void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher)
+	{
+	CERT_PKEY *cpk;
+	int rsa_enc,rsa_tmp,rsa_sign,dh_tmp,dh_rsa,dh_dsa,dsa_sign;
+	int rsa_enc_export,dh_rsa_export,dh_dsa_export;
+	int rsa_tmp_export,dh_tmp_export,kl;
+	unsigned long mask_k,mask_a,emask_k,emask_a;
+	int have_ecc_cert, ecdh_ok, ecdsa_ok, ecc_pkey_size;
+#ifndef OPENSSL_NO_ECDH
+	int have_ecdh_tmp;
+#endif
+	X509 *x = NULL;
+	EVP_PKEY *ecc_pkey = NULL;
+	int signature_nid = 0;
+
+	if (c == NULL) return;
+
+	kl=SSL_C_EXPORT_PKEYLENGTH(cipher);
+
+#ifndef OPENSSL_NO_RSA
+	rsa_tmp=(c->rsa_tmp != NULL || c->rsa_tmp_cb != NULL);
+	rsa_tmp_export=(c->rsa_tmp_cb != NULL ||
+		(rsa_tmp && RSA_size(c->rsa_tmp)*8 <= kl));
+#else
+	rsa_tmp=rsa_tmp_export=0;
+#endif
+#ifndef OPENSSL_NO_DH
+	dh_tmp=(c->dh_tmp != NULL || c->dh_tmp_cb != NULL);
+	dh_tmp_export=(c->dh_tmp_cb != NULL ||
+		(dh_tmp && DH_size(c->dh_tmp)*8 <= kl));
+#else
+	dh_tmp=dh_tmp_export=0;
+#endif
+
+#ifndef OPENSSL_NO_ECDH
+	have_ecdh_tmp=(c->ecdh_tmp != NULL || c->ecdh_tmp_cb != NULL);
+#endif
+	cpk= &(c->pkeys[SSL_PKEY_RSA_ENC]);
+	rsa_enc= (cpk->x509 != NULL && cpk->privatekey != NULL);
+	rsa_enc_export=(rsa_enc && EVP_PKEY_size(cpk->privatekey)*8 <= kl);
+	cpk= &(c->pkeys[SSL_PKEY_RSA_SIGN]);
+	rsa_sign=(cpk->x509 != NULL && cpk->privatekey != NULL);
+	cpk= &(c->pkeys[SSL_PKEY_DSA_SIGN]);
+	dsa_sign=(cpk->x509 != NULL && cpk->privatekey != NULL);
+	cpk= &(c->pkeys[SSL_PKEY_DH_RSA]);
+	dh_rsa=  (cpk->x509 != NULL && cpk->privatekey != NULL);
+	dh_rsa_export=(dh_rsa && EVP_PKEY_size(cpk->privatekey)*8 <= kl);
+	cpk= &(c->pkeys[SSL_PKEY_DH_DSA]);
+/* FIX THIS EAY EAY EAY */
+	dh_dsa=  (cpk->x509 != NULL && cpk->privatekey != NULL);
+	dh_dsa_export=(dh_dsa && EVP_PKEY_size(cpk->privatekey)*8 <= kl);
+	cpk= &(c->pkeys[SSL_PKEY_ECC]);
+	have_ecc_cert= (cpk->x509 != NULL && cpk->privatekey != NULL);
+	mask_k=0;
+	mask_a=0;
+	emask_k=0;
+	emask_a=0;
+
+	
+
+#ifdef CIPHER_DEBUG
+	printf("rt=%d rte=%d dht=%d ecdht=%d re=%d ree=%d rs=%d ds=%d dhr=%d dhd=%d\n",
+	        rsa_tmp,rsa_tmp_export,dh_tmp,have_ecdh_tmp,
+		rsa_enc,rsa_enc_export,rsa_sign,dsa_sign,dh_rsa,dh_dsa);
+#endif
+	
+	cpk = &(c->pkeys[SSL_PKEY_GOST01]);
+	if (cpk->x509 != NULL && cpk->privatekey !=NULL) {
+		mask_k |= SSL_kGOST;
+		mask_a |= SSL_aGOST01;
+	}
+	cpk = &(c->pkeys[SSL_PKEY_GOST94]);
+	if (cpk->x509 != NULL && cpk->privatekey !=NULL) {
+		mask_k |= SSL_kGOST;
+		mask_a |= SSL_aGOST94;
+	}
+
+	if (rsa_enc || (rsa_tmp && rsa_sign))
+		mask_k|=SSL_kRSA;
+	if (rsa_enc_export || (rsa_tmp_export && (rsa_sign || rsa_enc)))
+		emask_k|=SSL_kRSA;
+
+#if 0
+	/* The match needs to be both kEDH and aRSA or aDSA, so don't worry */
+	if (	(dh_tmp || dh_rsa || dh_dsa) &&
+		(rsa_enc || rsa_sign || dsa_sign))
+		mask_k|=SSL_kEDH;
+	if ((dh_tmp_export || dh_rsa_export || dh_dsa_export) &&
+		(rsa_enc || rsa_sign || dsa_sign))
+		emask_k|=SSL_kEDH;
+#endif
+
+	if (dh_tmp_export)
+		emask_k|=SSL_kEDH;
+
+	if (dh_tmp)
+		mask_k|=SSL_kEDH;
+
+	if (dh_rsa) mask_k|=SSL_kDHr;
+	if (dh_rsa_export) emask_k|=SSL_kDHr;
+
+	if (dh_dsa) mask_k|=SSL_kDHd;
+	if (dh_dsa_export) emask_k|=SSL_kDHd;
+
+	if (rsa_enc || rsa_sign)
+		{
+		mask_a|=SSL_aRSA;
+		emask_a|=SSL_aRSA;
+		}
+
+	if (dsa_sign)
+		{
+		mask_a|=SSL_aDSS;
+		emask_a|=SSL_aDSS;
+		}
+
+	mask_a|=SSL_aNULL;
+	emask_a|=SSL_aNULL;
+
+#ifndef OPENSSL_NO_KRB5
+	mask_k|=SSL_kKRB5;
+	mask_a|=SSL_aKRB5;
+	emask_k|=SSL_kKRB5;
+	emask_a|=SSL_aKRB5;
+#endif
+
+	/* An ECC certificate may be usable for ECDH and/or
+	 * ECDSA cipher suites depending on the key usage extension.
+	 */
+	if (have_ecc_cert)
+		{
+		/* This call populates extension flags (ex_flags) */
+		x = (c->pkeys[SSL_PKEY_ECC]).x509;
+		X509_check_purpose(x, -1, 0);
+		ecdh_ok = (x->ex_flags & EXFLAG_KUSAGE) ?
+		    (x->ex_kusage & X509v3_KU_KEY_AGREEMENT) : 1;
+		ecdsa_ok = (x->ex_flags & EXFLAG_KUSAGE) ?
+		    (x->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE) : 1;
+		ecc_pkey = X509_get_pubkey(x);
+		ecc_pkey_size = (ecc_pkey != NULL) ?
+		    EVP_PKEY_bits(ecc_pkey) : 0;
+		EVP_PKEY_free(ecc_pkey);
+		if ((x->sig_alg) && (x->sig_alg->algorithm))
+			signature_nid = OBJ_obj2nid(x->sig_alg->algorithm);
+#ifndef OPENSSL_NO_ECDH
+		if (ecdh_ok)
+			{
+			const char *sig = OBJ_nid2ln(signature_nid);
+			if (sig == NULL)
+				{
+				ERR_clear_error();
+				sig = "unknown";
+				}
+				
+			if (strstr(sig, "WithRSA"))
+				{
+				mask_k|=SSL_kECDHr;
+				mask_a|=SSL_aECDH;
+				if (ecc_pkey_size <= 163)
+					{
+					emask_k|=SSL_kECDHr;
+					emask_a|=SSL_aECDH;
+					}
+				}
+
+			if (signature_nid == NID_ecdsa_with_SHA1)
+				{
+				mask_k|=SSL_kECDHe;
+				mask_a|=SSL_aECDH;
+				if (ecc_pkey_size <= 163)
+					{
+					emask_k|=SSL_kECDHe;
+					emask_a|=SSL_aECDH;
+					}
+				}
+			}
+#endif
+#ifndef OPENSSL_NO_ECDSA
+		if (ecdsa_ok)
+			{
+			mask_a|=SSL_aECDSA;
+			emask_a|=SSL_aECDSA;
+			}
+#endif
+		}
+
+#ifndef OPENSSL_NO_ECDH
+	if (have_ecdh_tmp)
+		{
+		mask_k|=SSL_kEECDH;
+		emask_k|=SSL_kEECDH;
+		}
+#endif
+
+#ifndef OPENSSL_NO_PSK
+	mask_k |= SSL_kPSK;
+	mask_a |= SSL_aPSK;
+	emask_k |= SSL_kPSK;
+	emask_a |= SSL_aPSK;
+#endif
+
+	c->mask_k=mask_k;
+	c->mask_a=mask_a;
+	c->export_mask_k=emask_k;
+	c->export_mask_a=emask_a;
+	c->valid=1;
+	}
+
+/* This handy macro borrowed from crypto/x509v3/v3_purp.c */
+#define ku_reject(x, usage) \
+	(((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage)))
+
+#ifndef OPENSSL_NO_EC
+
+int ssl_check_srvr_ecc_cert_and_alg(X509 *x, const SSL_CIPHER *cs)
+	{
+	unsigned long alg_k, alg_a;
+	EVP_PKEY *pkey = NULL;
+	int keysize = 0;
+	int signature_nid = 0;
+
+	alg_k = cs->algorithm_mkey;
+	alg_a = cs->algorithm_auth;
+
+	if (SSL_C_IS_EXPORT(cs))
+		{
+		/* ECDH key length in export ciphers must be <= 163 bits */
+		pkey = X509_get_pubkey(x);
+		if (pkey == NULL) return 0;
+		keysize = EVP_PKEY_bits(pkey);
+		EVP_PKEY_free(pkey);
+		if (keysize > 163) return 0;
+		}
+
+	/* This call populates the ex_flags field correctly */
+	X509_check_purpose(x, -1, 0);
+	if ((x->sig_alg) && (x->sig_alg->algorithm))
+		signature_nid = OBJ_obj2nid(x->sig_alg->algorithm);
+	if (alg_k & SSL_kECDHe || alg_k & SSL_kECDHr)
+		{
+		/* key usage, if present, must allow key agreement */
+		if (ku_reject(x, X509v3_KU_KEY_AGREEMENT))
+			{
+			SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG, SSL_R_ECC_CERT_NOT_FOR_KEY_AGREEMENT);
+			return 0;
+			}
+		if (alg_k & SSL_kECDHe)
+			{
+			/* signature alg must be ECDSA */
+			if (signature_nid != NID_ecdsa_with_SHA1)
+				{
+				SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG, SSL_R_ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE);
+				return 0;
+				}
+			}
+		if (alg_k & SSL_kECDHr)
+			{
+			/* signature alg must be RSA */
+
+			const char *sig = OBJ_nid2ln(signature_nid);
+			if (sig == NULL)
+				{
+				ERR_clear_error();
+				sig = "unknown";
+				}
+			if (strstr(sig, "WithRSA") == NULL)
+				{
+				SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG, SSL_R_ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE);
+				return 0;
+				}
+			}
+		}
+	if (alg_a & SSL_aECDSA)
+		{
+		/* key usage, if present, must allow signing */
+		if (ku_reject(x, X509v3_KU_DIGITAL_SIGNATURE))
+			{
+			SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG, SSL_R_ECC_CERT_NOT_FOR_SIGNING);
+			return 0;
+			}
+		}
+
+	return 1;  /* all checks are ok */
+	}
+
+#endif
+
+/* THIS NEEDS CLEANING UP */
+X509 *ssl_get_server_send_cert(SSL *s)
+	{
+	unsigned long alg_k,alg_a,mask_k,mask_a;
+	CERT *c;
+	int i,is_export;
+
+	c=s->cert;
+	ssl_set_cert_masks(c, s->s3->tmp.new_cipher);
+	is_export=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher);
+	if (is_export)
+		{
+		mask_k = c->export_mask_k;
+		mask_a = c->export_mask_a;
+		}
+	else
+		{
+		mask_k = c->mask_k;
+		mask_a = c->mask_a;
+		}
+	
+	alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+	alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+
+	if (alg_k & (SSL_kECDHr|SSL_kECDHe))
+		{
+		/* we don't need to look at SSL_kEECDH
+		 * since no certificate is needed for
+		 * anon ECDH and for authenticated
+		 * EECDH, the check for the auth
+		 * algorithm will set i correctly
+		 * NOTE: For ECDH-RSA, we need an ECC
+		 * not an RSA cert but for EECDH-RSA
+		 * we need an RSA cert. Placing the
+		 * checks for SSL_kECDH before RSA
+		 * checks ensures the correct cert is chosen.
+		 */
+		i=SSL_PKEY_ECC;
+		}
+	else if (alg_a & SSL_aECDSA)
+		{
+		i=SSL_PKEY_ECC;
+		}
+	else if (alg_k & SSL_kDHr)
+		i=SSL_PKEY_DH_RSA;
+	else if (alg_k & SSL_kDHd)
+		i=SSL_PKEY_DH_DSA;
+	else if (alg_a & SSL_aDSS)
+		i=SSL_PKEY_DSA_SIGN;
+	else if (alg_a & SSL_aRSA)
+		{
+		if (c->pkeys[SSL_PKEY_RSA_ENC].x509 == NULL)
+			i=SSL_PKEY_RSA_SIGN;
+		else
+			i=SSL_PKEY_RSA_ENC;
+		}
+	else if (alg_a & SSL_aKRB5)
+		{
+		/* VRS something else here? */
+		return(NULL);
+		}
+	else if (alg_a & SSL_aGOST94) 
+		i=SSL_PKEY_GOST94;
+	else if (alg_a & SSL_aGOST01)
+		i=SSL_PKEY_GOST01;
+	else /* if (alg_a & SSL_aNULL) */
+		{
+		SSLerr(SSL_F_SSL_GET_SERVER_SEND_CERT,ERR_R_INTERNAL_ERROR);
+		return(NULL);
+		}
+	if (c->pkeys[i].x509 == NULL) return(NULL);
+
+	return(c->pkeys[i].x509);
+	}
+
+EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *cipher)
+	{
+	unsigned long alg_a;
+	CERT *c;
+
+	alg_a = cipher->algorithm_auth;
+	c=s->cert;
+
+	if ((alg_a & SSL_aDSS) &&
+		(c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL))
+		return(c->pkeys[SSL_PKEY_DSA_SIGN].privatekey);
+	else if (alg_a & SSL_aRSA)
+		{
+		if (c->pkeys[SSL_PKEY_RSA_SIGN].privatekey != NULL)
+			return(c->pkeys[SSL_PKEY_RSA_SIGN].privatekey);
+		else if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey != NULL)
+			return(c->pkeys[SSL_PKEY_RSA_ENC].privatekey);
+		else
+			return(NULL);
+		}
+	else if ((alg_a & SSL_aECDSA) &&
+	         (c->pkeys[SSL_PKEY_ECC].privatekey != NULL))
+		return(c->pkeys[SSL_PKEY_ECC].privatekey);
+	else /* if (alg_a & SSL_aNULL) */
+		{
+		SSLerr(SSL_F_SSL_GET_SIGN_PKEY,ERR_R_INTERNAL_ERROR);
+		return(NULL);
+		}
+	}
+
+void ssl_update_cache(SSL *s,int mode)
+	{
+	int i;
+
+	/* If the session_id_length is 0, we are not supposed to cache it,
+	 * and it would be rather hard to do anyway :-) */
+	if (s->session->session_id_length == 0) return;
+
+	i=s->session_ctx->session_cache_mode;
+	if ((i & mode) && (!s->hit)
+		&& ((i & SSL_SESS_CACHE_NO_INTERNAL_STORE)
+		    || SSL_CTX_add_session(s->session_ctx,s->session))
+		&& (s->session_ctx->new_session_cb != NULL))
+		{
+		CRYPTO_add(&s->session->references,1,CRYPTO_LOCK_SSL_SESSION);
+		if (!s->session_ctx->new_session_cb(s,s->session))
+			SSL_SESSION_free(s->session);
+		}
+
+	/* auto flush every 255 connections */
+	if ((!(i & SSL_SESS_CACHE_NO_AUTO_CLEAR)) &&
+		((i & mode) == mode))
+		{
+		if (  (((mode & SSL_SESS_CACHE_CLIENT)
+			?s->session_ctx->stats.sess_connect_good
+			:s->session_ctx->stats.sess_accept_good) & 0xff) == 0xff)
+			{
+			SSL_CTX_flush_sessions(s->session_ctx,(unsigned long)time(NULL));
+			}
+		}
+	}
+
+const SSL_METHOD *SSL_get_ssl_method(SSL *s)
+	{
+	return(s->method);
+	}
+
+int SSL_set_ssl_method(SSL *s, const SSL_METHOD *meth)
+	{
+	int conn= -1;
+	int ret=1;
+
+	if (s->method != meth)
+		{
+		if (s->handshake_func != NULL)
+			conn=(s->handshake_func == s->method->ssl_connect);
+
+		if (s->method->version == meth->version)
+			s->method=meth;
+		else
+			{
+			s->method->ssl_free(s);
+			s->method=meth;
+			ret=s->method->ssl_new(s);
+			}
+
+		if (conn == 1)
+			s->handshake_func=meth->ssl_connect;
+		else if (conn == 0)
+			s->handshake_func=meth->ssl_accept;
+		}
+	return(ret);
+	}
+
+int SSL_get_error(const SSL *s,int i)
+	{
+	int reason;
+	unsigned long l;
+	BIO *bio;
+
+	if (i > 0) return(SSL_ERROR_NONE);
+
+	/* Make things return SSL_ERROR_SYSCALL when doing SSL_do_handshake
+	 * etc, where we do encode the error */
+	if ((l=ERR_peek_error()) != 0)
+		{
+		if (ERR_GET_LIB(l) == ERR_LIB_SYS)
+			return(SSL_ERROR_SYSCALL);
+		else
+			return(SSL_ERROR_SSL);
+		}
+
+	if ((i < 0) && SSL_want_read(s))
+		{
+		bio=SSL_get_rbio(s);
+		if (BIO_should_read(bio))
+			return(SSL_ERROR_WANT_READ);
+		else if (BIO_should_write(bio))
+			/* This one doesn't make too much sense ... We never try
+			 * to write to the rbio, and an application program where
+			 * rbio and wbio are separate couldn't even know what it
+			 * should wait for.
+			 * However if we ever set s->rwstate incorrectly
+			 * (so that we have SSL_want_read(s) instead of
+			 * SSL_want_write(s)) and rbio and wbio *are* the same,
+			 * this test works around that bug; so it might be safer
+			 * to keep it. */
+			return(SSL_ERROR_WANT_WRITE);
+		else if (BIO_should_io_special(bio))
+			{
+			reason=BIO_get_retry_reason(bio);
+			if (reason == BIO_RR_CONNECT)
+				return(SSL_ERROR_WANT_CONNECT);
+			else if (reason == BIO_RR_ACCEPT)
+				return(SSL_ERROR_WANT_ACCEPT);
+			else
+				return(SSL_ERROR_SYSCALL); /* unknown */
+			}
+		}
+
+	if ((i < 0) && SSL_want_write(s))
+		{
+		bio=SSL_get_wbio(s);
+		if (BIO_should_write(bio))
+			return(SSL_ERROR_WANT_WRITE);
+		else if (BIO_should_read(bio))
+			/* See above (SSL_want_read(s) with BIO_should_write(bio)) */
+			return(SSL_ERROR_WANT_READ);
+		else if (BIO_should_io_special(bio))
+			{
+			reason=BIO_get_retry_reason(bio);
+			if (reason == BIO_RR_CONNECT)
+				return(SSL_ERROR_WANT_CONNECT);
+			else if (reason == BIO_RR_ACCEPT)
+				return(SSL_ERROR_WANT_ACCEPT);
+			else
+				return(SSL_ERROR_SYSCALL);
+			}
+		}
+	if ((i < 0) && SSL_want_x509_lookup(s))
+		{
+		return(SSL_ERROR_WANT_X509_LOOKUP);
+		}
+
+	if (i == 0)
+		{
+		if (s->version == SSL2_VERSION)
+			{
+			/* assume it is the socket being closed */
+			return(SSL_ERROR_ZERO_RETURN);
+			}
+		else
+			{
+			if ((s->shutdown & SSL_RECEIVED_SHUTDOWN) &&
+				(s->s3->warn_alert == SSL_AD_CLOSE_NOTIFY))
+				return(SSL_ERROR_ZERO_RETURN);
+			}
+		}
+	return(SSL_ERROR_SYSCALL);
+	}
+
+int SSL_do_handshake(SSL *s)
+	{
+	int ret=1;
+
+	if (s->handshake_func == NULL)
+		{
+		SSLerr(SSL_F_SSL_DO_HANDSHAKE,SSL_R_CONNECTION_TYPE_NOT_SET);
+		return(-1);
+		}
+
+	s->method->ssl_renegotiate_check(s);
+
+	if (SSL_in_init(s) || SSL_in_before(s))
+		{
+		ret=s->handshake_func(s);
+		}
+	return(ret);
+	}
+
+/* For the next 2 functions, SSL_clear() sets shutdown and so
+ * one of these calls will reset it */
+void SSL_set_accept_state(SSL *s)
+	{
+	s->server=1;
+	s->shutdown=0;
+	s->state=SSL_ST_ACCEPT|SSL_ST_BEFORE;
+	s->handshake_func=s->method->ssl_accept;
+	/* clear the current cipher */
+	ssl_clear_cipher_ctx(s);
+	ssl_clear_hash_ctx(&s->read_hash);
+	ssl_clear_hash_ctx(&s->write_hash);
+	}
+
+void SSL_set_connect_state(SSL *s)
+	{
+	s->server=0;
+	s->shutdown=0;
+	s->state=SSL_ST_CONNECT|SSL_ST_BEFORE;
+	s->handshake_func=s->method->ssl_connect;
+	/* clear the current cipher */
+	ssl_clear_cipher_ctx(s);
+	ssl_clear_hash_ctx(&s->read_hash);
+	ssl_clear_hash_ctx(&s->write_hash);
+	}
+
+int ssl_undefined_function(SSL *s)
+	{
+	SSLerr(SSL_F_SSL_UNDEFINED_FUNCTION,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+	return(0);
+	}
+
+int ssl_undefined_void_function(void)
+	{
+	SSLerr(SSL_F_SSL_UNDEFINED_VOID_FUNCTION,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+	return(0);
+	}
+
+int ssl_undefined_const_function(const SSL *s)
+	{
+	SSLerr(SSL_F_SSL_UNDEFINED_CONST_FUNCTION,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+	return(0);
+	}
+
+SSL_METHOD *ssl_bad_method(int ver)
+	{
+	SSLerr(SSL_F_SSL_BAD_METHOD,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+	return(NULL);
+	}
+
+const char *SSL_get_version(const SSL *s)
+	{
+	if (s->version == TLS1_VERSION)
+		return("TLSv1");
+	else if (s->version == SSL3_VERSION)
+		return("SSLv3");
+	else if (s->version == SSL2_VERSION)
+		return("SSLv2");
+	else
+		return("unknown");
+	}
+
+SSL *SSL_dup(SSL *s)
+	{
+	STACK_OF(X509_NAME) *sk;
+	X509_NAME *xn;
+	SSL *ret;
+	int i;
+	
+	if ((ret=SSL_new(SSL_get_SSL_CTX(s))) == NULL)
+	    return(NULL);
+
+	ret->version = s->version;
+	ret->type = s->type;
+	ret->method = s->method;
+
+	if (s->session != NULL)
+		{
+		/* This copies session-id, SSL_METHOD, sid_ctx, and 'cert' */
+		SSL_copy_session_id(ret,s);
+		}
+	else
+		{
+		/* No session has been established yet, so we have to expect
+		 * that s->cert or ret->cert will be changed later --
+		 * they should not both point to the same object,
+		 * and thus we can't use SSL_copy_session_id. */
+
+		ret->method->ssl_free(ret);
+		ret->method = s->method;
+		ret->method->ssl_new(ret);
+
+		if (s->cert != NULL)
+			{
+			if (ret->cert != NULL)
+				{
+				ssl_cert_free(ret->cert);
+				}
+			ret->cert = ssl_cert_dup(s->cert);
+			if (ret->cert == NULL)
+				goto err;
+			}
+				
+		SSL_set_session_id_context(ret,
+			s->sid_ctx, s->sid_ctx_length);
+		}
+
+	ret->options=s->options;
+	ret->mode=s->mode;
+	SSL_set_max_cert_list(ret,SSL_get_max_cert_list(s));
+	SSL_set_read_ahead(ret,SSL_get_read_ahead(s));
+	ret->msg_callback = s->msg_callback;
+	ret->msg_callback_arg = s->msg_callback_arg;
+	SSL_set_verify(ret,SSL_get_verify_mode(s),
+		SSL_get_verify_callback(s));
+	SSL_set_verify_depth(ret,SSL_get_verify_depth(s));
+	ret->generate_session_id = s->generate_session_id;
+
+	SSL_set_info_callback(ret,SSL_get_info_callback(s));
+	
+	ret->debug=s->debug;
+
+	/* copy app data, a little dangerous perhaps */
+	if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL, &ret->ex_data, &s->ex_data))
+		goto err;
+
+	/* setup rbio, and wbio */
+	if (s->rbio != NULL)
+		{
+		if (!BIO_dup_state(s->rbio,(char *)&ret->rbio))
+			goto err;
+		}
+	if (s->wbio != NULL)
+		{
+		if (s->wbio != s->rbio)
+			{
+			if (!BIO_dup_state(s->wbio,(char *)&ret->wbio))
+				goto err;
+			}
+		else
+			ret->wbio=ret->rbio;
+		}
+	ret->rwstate = s->rwstate;
+	ret->in_handshake = s->in_handshake;
+	ret->handshake_func = s->handshake_func;
+	ret->server = s->server;
+	ret->new_session = s->new_session;
+	ret->quiet_shutdown = s->quiet_shutdown;
+	ret->shutdown=s->shutdown;
+	ret->state=s->state; /* SSL_dup does not really work at any state, though */
+	ret->rstate=s->rstate;
+	ret->init_num = 0; /* would have to copy ret->init_buf, ret->init_msg, ret->init_num, ret->init_off */
+	ret->hit=s->hit;
+
+	X509_VERIFY_PARAM_inherit(ret->param, s->param);
+
+	/* dup the cipher_list and cipher_list_by_id stacks */
+	if (s->cipher_list != NULL)
+		{
+		if ((ret->cipher_list=sk_SSL_CIPHER_dup(s->cipher_list)) == NULL)
+			goto err;
+		}
+	if (s->cipher_list_by_id != NULL)
+		if ((ret->cipher_list_by_id=sk_SSL_CIPHER_dup(s->cipher_list_by_id))
+			== NULL)
+			goto err;
+
+	/* Dup the client_CA list */
+	if (s->client_CA != NULL)
+		{
+		if ((sk=sk_X509_NAME_dup(s->client_CA)) == NULL) goto err;
+		ret->client_CA=sk;
+		for (i=0; i<sk_X509_NAME_num(sk); i++)
+			{
+			xn=sk_X509_NAME_value(sk,i);
+			if (sk_X509_NAME_set(sk,i,X509_NAME_dup(xn)) == NULL)
+				{
+				X509_NAME_free(xn);
+				goto err;
+				}
+			}
+		}
+
+	if (0)
+		{
+err:
+		if (ret != NULL) SSL_free(ret);
+		ret=NULL;
+		}
+	return(ret);
+	}
+
+void ssl_clear_cipher_ctx(SSL *s)
+	{
+	if (s->enc_read_ctx != NULL)
+		{
+		EVP_CIPHER_CTX_cleanup(s->enc_read_ctx);
+		OPENSSL_free(s->enc_read_ctx);
+		s->enc_read_ctx=NULL;
+		}
+	if (s->enc_write_ctx != NULL)
+		{
+		EVP_CIPHER_CTX_cleanup(s->enc_write_ctx);
+		OPENSSL_free(s->enc_write_ctx);
+		s->enc_write_ctx=NULL;
+		}
+#ifndef OPENSSL_NO_COMP
+	if (s->expand != NULL)
+		{
+		COMP_CTX_free(s->expand);
+		s->expand=NULL;
+		}
+	if (s->compress != NULL)
+		{
+		COMP_CTX_free(s->compress);
+		s->compress=NULL;
+		}
+#endif
+	}
+
+/* Fix this function so that it takes an optional type parameter */
+X509 *SSL_get_certificate(const SSL *s)
+	{
+	if (s->cert != NULL)
+		return(s->cert->key->x509);
+	else
+		return(NULL);
+	}
+
+/* Fix this function so that it takes an optional type parameter */
+EVP_PKEY *SSL_get_privatekey(SSL *s)
+	{
+	if (s->cert != NULL)
+		return(s->cert->key->privatekey);
+	else
+		return(NULL);
+	}
+
+const SSL_CIPHER *SSL_get_current_cipher(const SSL *s)
+	{
+	if ((s->session != NULL) && (s->session->cipher != NULL))
+		return(s->session->cipher);
+	return(NULL);
+	}
+#ifdef OPENSSL_NO_COMP
+const void *SSL_get_current_compression(SSL *s)
+	{
+	return NULL;
+	}
+const void *SSL_get_current_expansion(SSL *s)
+	{
+	return NULL;
+	}
+#else
+
+const COMP_METHOD *SSL_get_current_compression(SSL *s)
+	{
+	if (s->compress != NULL)
+		return(s->compress->meth);
+	return(NULL);
+	}
+
+const COMP_METHOD *SSL_get_current_expansion(SSL *s)
+	{
+	if (s->expand != NULL)
+		return(s->expand->meth);
+	return(NULL);
+	}
+#endif
+
+int ssl_init_wbio_buffer(SSL *s,int push)
+	{
+	BIO *bbio;
+
+	if (s->bbio == NULL)
+		{
+		bbio=BIO_new(BIO_f_buffer());
+		if (bbio == NULL) return(0);
+		s->bbio=bbio;
+		}
+	else
+		{
+		bbio=s->bbio;
+		if (s->bbio == s->wbio)
+			s->wbio=BIO_pop(s->wbio);
+		}
+	(void)BIO_reset(bbio);
+/*	if (!BIO_set_write_buffer_size(bbio,16*1024)) */
+	if (!BIO_set_read_buffer_size(bbio,1))
+		{
+		SSLerr(SSL_F_SSL_INIT_WBIO_BUFFER,ERR_R_BUF_LIB);
+		return(0);
+		}
+	if (push)
+		{
+		if (s->wbio != bbio)
+			s->wbio=BIO_push(bbio,s->wbio);
+		}
+	else
+		{
+		if (s->wbio == bbio)
+			s->wbio=BIO_pop(bbio);
+		}
+	return(1);
+	}
+
+void ssl_free_wbio_buffer(SSL *s)
+	{
+	if (s->bbio == NULL) return;
+
+	if (s->bbio == s->wbio)
+		{
+		/* remove buffering */
+		s->wbio=BIO_pop(s->wbio);
+#ifdef REF_CHECK /* not the usual REF_CHECK, but this avoids adding one more preprocessor symbol */
+		assert(s->wbio != NULL);
+#endif
+	}
+	BIO_free(s->bbio);
+	s->bbio=NULL;
+	}
+	
+void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx,int mode)
+	{
+	ctx->quiet_shutdown=mode;
+	}
+
+int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx)
+	{
+	return(ctx->quiet_shutdown);
+	}
+
+void SSL_set_quiet_shutdown(SSL *s,int mode)
+	{
+	s->quiet_shutdown=mode;
+	}
+
+int SSL_get_quiet_shutdown(const SSL *s)
+	{
+	return(s->quiet_shutdown);
+	}
+
+void SSL_set_shutdown(SSL *s,int mode)
+	{
+	s->shutdown=mode;
+	}
+
+int SSL_get_shutdown(const SSL *s)
+	{
+	return(s->shutdown);
+	}
+
+int SSL_version(const SSL *s)
+	{
+	return(s->version);
+	}
+
+SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl)
+	{
+	return(ssl->ctx);
+	}
+
+SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX* ctx)
+	{
+	if (ssl->ctx == ctx)
+		return ssl->ctx;
+#ifndef OPENSSL_NO_TLSEXT
+	if (ctx == NULL)
+		ctx = ssl->initial_ctx;
+#endif
+	if (ssl->cert != NULL)
+		ssl_cert_free(ssl->cert);
+	ssl->cert = ssl_cert_dup(ctx->cert);
+	CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX);
+	if (ssl->ctx != NULL)
+		SSL_CTX_free(ssl->ctx); /* decrement reference count */
+	ssl->ctx = ctx;
+	return(ssl->ctx);
+	}
+
+#ifndef OPENSSL_NO_STDIO
+int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx)
+	{
+	return(X509_STORE_set_default_paths(ctx->cert_store));
+	}
+
+int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,
+		const char *CApath)
+	{
+	return(X509_STORE_load_locations(ctx->cert_store,CAfile,CApath));
+	}
+#endif
+
+void SSL_set_info_callback(SSL *ssl,
+	void (*cb)(const SSL *ssl,int type,int val))
+	{
+	ssl->info_callback=cb;
+	}
+
+/* One compiler (Diab DCC) doesn't like argument names in returned
+   function pointer.  */
+void (*SSL_get_info_callback(const SSL *ssl))(const SSL * /*ssl*/,int /*type*/,int /*val*/)
+	{
+	return ssl->info_callback;
+	}
+
+int SSL_state(const SSL *ssl)
+	{
+	return(ssl->state);
+	}
+
+void SSL_set_verify_result(SSL *ssl,long arg)
+	{
+	ssl->verify_result=arg;
+	}
+
+long SSL_get_verify_result(const SSL *ssl)
+	{
+	return(ssl->verify_result);
+	}
+
+int SSL_get_ex_new_index(long argl,void *argp,CRYPTO_EX_new *new_func,
+			 CRYPTO_EX_dup *dup_func,CRYPTO_EX_free *free_func)
+	{
+	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, argl, argp,
+				new_func, dup_func, free_func);
+	}
+
+int SSL_set_ex_data(SSL *s,int idx,void *arg)
+	{
+	return(CRYPTO_set_ex_data(&s->ex_data,idx,arg));
+	}
+
+void *SSL_get_ex_data(const SSL *s,int idx)
+	{
+	return(CRYPTO_get_ex_data(&s->ex_data,idx));
+	}
+
+int SSL_CTX_get_ex_new_index(long argl,void *argp,CRYPTO_EX_new *new_func,
+			     CRYPTO_EX_dup *dup_func,CRYPTO_EX_free *free_func)
+	{
+	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_CTX, argl, argp,
+				new_func, dup_func, free_func);
+	}
+
+int SSL_CTX_set_ex_data(SSL_CTX *s,int idx,void *arg)
+	{
+	return(CRYPTO_set_ex_data(&s->ex_data,idx,arg));
+	}
+
+void *SSL_CTX_get_ex_data(const SSL_CTX *s,int idx)
+	{
+	return(CRYPTO_get_ex_data(&s->ex_data,idx));
+	}
+
+int ssl_ok(SSL *s)
+	{
+	return(1);
+	}
+
+X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *ctx)
+	{
+	return(ctx->cert_store);
+	}
+
+void SSL_CTX_set_cert_store(SSL_CTX *ctx,X509_STORE *store)
+	{
+	if (ctx->cert_store != NULL)
+		X509_STORE_free(ctx->cert_store);
+	ctx->cert_store=store;
+	}
+
+int SSL_want(const SSL *s)
+	{
+	return(s->rwstate);
+	}
+
+/*!
+ * \brief Set the callback for generating temporary RSA keys.
+ * \param ctx the SSL context.
+ * \param cb the callback
+ */
+
+#ifndef OPENSSL_NO_RSA
+void SSL_CTX_set_tmp_rsa_callback(SSL_CTX *ctx,RSA *(*cb)(SSL *ssl,
+							  int is_export,
+							  int keylength))
+    {
+    SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TMP_RSA_CB,(void (*)(void))cb);
+    }
+
+void SSL_set_tmp_rsa_callback(SSL *ssl,RSA *(*cb)(SSL *ssl,
+						  int is_export,
+						  int keylength))
+    {
+    SSL_callback_ctrl(ssl,SSL_CTRL_SET_TMP_RSA_CB,(void (*)(void))cb);
+    }
+#endif
+
+#ifdef DOXYGEN
+/*!
+ * \brief The RSA temporary key callback function.
+ * \param ssl the SSL session.
+ * \param is_export \c TRUE if the temp RSA key is for an export ciphersuite.
+ * \param keylength if \c is_export is \c TRUE, then \c keylength is the size
+ * of the required key in bits.
+ * \return the temporary RSA key.
+ * \sa SSL_CTX_set_tmp_rsa_callback, SSL_set_tmp_rsa_callback
+ */
+
+RSA *cb(SSL *ssl,int is_export,int keylength)
+    {}
+#endif
+
+/*!
+ * \brief Set the callback for generating temporary DH keys.
+ * \param ctx the SSL context.
+ * \param dh the callback
+ */
+
+#ifndef OPENSSL_NO_DH
+void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,DH *(*dh)(SSL *ssl,int is_export,
+                                                        int keylength))
+	{
+	SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TMP_DH_CB,(void (*)(void))dh);
+	}
+
+void SSL_set_tmp_dh_callback(SSL *ssl,DH *(*dh)(SSL *ssl,int is_export,
+                                                int keylength))
+	{
+	SSL_callback_ctrl(ssl,SSL_CTRL_SET_TMP_DH_CB,(void (*)(void))dh);
+	}
+#endif
+
+#ifndef OPENSSL_NO_ECDH
+void SSL_CTX_set_tmp_ecdh_callback(SSL_CTX *ctx,EC_KEY *(*ecdh)(SSL *ssl,int is_export,
+                                                                int keylength))
+	{
+	SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TMP_ECDH_CB,(void (*)(void))ecdh);
+	}
+
+void SSL_set_tmp_ecdh_callback(SSL *ssl,EC_KEY *(*ecdh)(SSL *ssl,int is_export,
+                                                        int keylength))
+	{
+	SSL_callback_ctrl(ssl,SSL_CTRL_SET_TMP_ECDH_CB,(void (*)(void))ecdh);
+	}
+#endif
+
+#ifndef OPENSSL_NO_PSK
+int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint)
+	{
+	if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT, SSL_R_DATA_LENGTH_TOO_LONG);
+		return 0;
+		}
+	if (ctx->psk_identity_hint != NULL)
+		OPENSSL_free(ctx->psk_identity_hint);
+	if (identity_hint != NULL)
+		{
+		ctx->psk_identity_hint = BUF_strdup(identity_hint);
+		if (ctx->psk_identity_hint == NULL)
+			return 0;
+		}
+	else
+		ctx->psk_identity_hint = NULL;
+	return 1;
+	}
+
+int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint)
+	{
+	if (s == NULL)
+		return 0;
+
+	if (s->session == NULL)
+		return 1; /* session not created yet, ignored */
+
+	if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN)
+		{
+		SSLerr(SSL_F_SSL_USE_PSK_IDENTITY_HINT, SSL_R_DATA_LENGTH_TOO_LONG);
+		return 0;
+		}
+	if (s->session->psk_identity_hint != NULL)
+		OPENSSL_free(s->session->psk_identity_hint);
+	if (identity_hint != NULL)
+		{
+		s->session->psk_identity_hint = BUF_strdup(identity_hint);
+		if (s->session->psk_identity_hint == NULL)
+			return 0;
+		}
+	else
+		s->session->psk_identity_hint = NULL;
+	return 1;
+	}
+
+const char *SSL_get_psk_identity_hint(const SSL *s)
+	{
+	if (s == NULL || s->session == NULL)
+		return NULL;
+	return(s->session->psk_identity_hint);
+	}
+
+const char *SSL_get_psk_identity(const SSL *s)
+	{
+	if (s == NULL || s->session == NULL)
+		return NULL;
+	return(s->session->psk_identity);
+	}
+
+void SSL_set_psk_client_callback(SSL *s,
+    unsigned int (*cb)(SSL *ssl, const char *hint,
+                       char *identity, unsigned int max_identity_len, unsigned char *psk,
+                       unsigned int max_psk_len))
+	{
+	s->psk_client_callback = cb;
+	}
+
+void SSL_CTX_set_psk_client_callback(SSL_CTX *ctx,
+    unsigned int (*cb)(SSL *ssl, const char *hint,
+                       char *identity, unsigned int max_identity_len, unsigned char *psk,
+                       unsigned int max_psk_len))
+	{
+	ctx->psk_client_callback = cb;
+	}
+
+void SSL_set_psk_server_callback(SSL *s,
+    unsigned int (*cb)(SSL *ssl, const char *identity,
+                       unsigned char *psk, unsigned int max_psk_len))
+	{
+	s->psk_server_callback = cb;
+	}
+
+void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx,
+    unsigned int (*cb)(SSL *ssl, const char *identity,
+                       unsigned char *psk, unsigned int max_psk_len))
+	{
+	ctx->psk_server_callback = cb;
+	}
+#endif
+
+void SSL_CTX_set_msg_callback(SSL_CTX *ctx, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg))
+	{
+	SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb);
+	}
+void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg))
+	{
+	SSL_callback_ctrl(ssl, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb);
+	}
+
+int SSL_cutthrough_complete(const SSL *s)
+	{
+	return (!s->server &&                 /* cutthrough only applies to clients */
+		!s->hit &&                        /* full-handshake */
+		s->version >= SSL3_VERSION &&
+		s->s3->in_read_app_data == 0 &&   /* cutthrough only applies to write() */
+		(SSL_get_mode((SSL*)s) & SSL_MODE_HANDSHAKE_CUTTHROUGH) &&  /* cutthrough enabled */
+		SSL_get_cipher_bits(s, NULL) >= 128 &&                      /* strong cipher choosen */
+		s->s3->previous_server_finished_len == 0 &&                 /* not a renegotiation handshake */
+		(s->state == SSL3_ST_CR_SESSION_TICKET_A ||                 /* ready to write app-data*/
+			s->state == SSL3_ST_CR_FINISHED_A));
+	}
+
+/* Allocates new EVP_MD_CTX and sets pointer to it into given pointer
+ * vairable, freeing  EVP_MD_CTX previously stored in that variable, if
+ * any. If EVP_MD pointer is passed, initializes ctx with this md
+ * Returns newly allocated ctx;
+ */
+
+EVP_MD_CTX *ssl_replace_hash(EVP_MD_CTX **hash,const EVP_MD *md) 
+{
+	ssl_clear_hash_ctx(hash);
+	*hash = EVP_MD_CTX_create();
+	if (md) EVP_DigestInit_ex(*hash,md,NULL);
+	return *hash;
+}
+void ssl_clear_hash_ctx(EVP_MD_CTX **hash) 
+{
+
+	if (*hash) EVP_MD_CTX_destroy(*hash);
+	*hash=NULL;
+}
+
+#if defined(_WINDLL) && defined(OPENSSL_SYS_WIN16)
+#include "../crypto/bio/bss_file.c"
+#endif
+
+IMPLEMENT_STACK_OF(SSL_CIPHER)
+IMPLEMENT_STACK_OF(SSL_COMP)
+IMPLEMENT_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER,
+				    ssl_cipher_id);
+
diff --git a/lib/openssl/ssl/ssl_locl.h b/lib/openssl/ssl/ssl_locl.h
new file mode 100644
index 0000000..73d2290
--- /dev/null
+++ b/lib/openssl/ssl/ssl_locl.h
@@ -0,0 +1,1079 @@
+/* ssl/ssl_locl.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECC cipher suite support in OpenSSL originally developed by 
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#ifndef HEADER_SSL_LOCL_H
+#define HEADER_SSL_LOCL_H
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <errno.h>
+
+#include "e_os.h"
+
+#include <openssl/buffer.h>
+#ifndef OPENSSL_NO_COMP
+#include <openssl/comp.h>
+#endif
+#include <openssl/bio.h>
+#include <openssl/stack.h>
+#ifndef OPENSSL_NO_RSA
+#include <openssl/rsa.h>
+#endif
+#ifndef OPENSSL_NO_DSA
+#include <openssl/dsa.h>
+#endif
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+#include <openssl/symhacks.h>
+
+#ifdef OPENSSL_BUILD_SHLIBSSL
+# undef OPENSSL_EXTERN
+# define OPENSSL_EXTERN OPENSSL_EXPORT
+#endif
+
+#define PKCS1_CHECK
+
+#define c2l(c,l)	(l = ((unsigned long)(*((c)++)))     , \
+			 l|=(((unsigned long)(*((c)++)))<< 8), \
+			 l|=(((unsigned long)(*((c)++)))<<16), \
+			 l|=(((unsigned long)(*((c)++)))<<24))
+
+/* NOTE - c is not incremented as per c2l */
+#define c2ln(c,l1,l2,n)	{ \
+			c+=n; \
+			l1=l2=0; \
+			switch (n) { \
+			case 8: l2 =((unsigned long)(*(--(c))))<<24; \
+			case 7: l2|=((unsigned long)(*(--(c))))<<16; \
+			case 6: l2|=((unsigned long)(*(--(c))))<< 8; \
+			case 5: l2|=((unsigned long)(*(--(c))));     \
+			case 4: l1 =((unsigned long)(*(--(c))))<<24; \
+			case 3: l1|=((unsigned long)(*(--(c))))<<16; \
+			case 2: l1|=((unsigned long)(*(--(c))))<< 8; \
+			case 1: l1|=((unsigned long)(*(--(c))));     \
+				} \
+			}
+
+#define l2c(l,c)	(*((c)++)=(unsigned char)(((l)    )&0xff), \
+			 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
+			 *((c)++)=(unsigned char)(((l)>>16)&0xff), \
+			 *((c)++)=(unsigned char)(((l)>>24)&0xff))
+
+#define n2l(c,l)	(l =((unsigned long)(*((c)++)))<<24, \
+			 l|=((unsigned long)(*((c)++)))<<16, \
+			 l|=((unsigned long)(*((c)++)))<< 8, \
+			 l|=((unsigned long)(*((c)++))))
+
+#define l2n(l,c)	(*((c)++)=(unsigned char)(((l)>>24)&0xff), \
+			 *((c)++)=(unsigned char)(((l)>>16)&0xff), \
+			 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
+			 *((c)++)=(unsigned char)(((l)    )&0xff))
+
+#define l2n6(l,c)	(*((c)++)=(unsigned char)(((l)>>40)&0xff), \
+			 *((c)++)=(unsigned char)(((l)>>32)&0xff), \
+			 *((c)++)=(unsigned char)(((l)>>24)&0xff), \
+			 *((c)++)=(unsigned char)(((l)>>16)&0xff), \
+			 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
+			 *((c)++)=(unsigned char)(((l)    )&0xff))
+
+#define n2l6(c,l)	(l =((BN_ULLONG)(*((c)++)))<<40, \
+			 l|=((BN_ULLONG)(*((c)++)))<<32, \
+			 l|=((BN_ULLONG)(*((c)++)))<<24, \
+			 l|=((BN_ULLONG)(*((c)++)))<<16, \
+			 l|=((BN_ULLONG)(*((c)++)))<< 8, \
+			 l|=((BN_ULLONG)(*((c)++))))
+
+/* NOTE - c is not incremented as per l2c */
+#define l2cn(l1,l2,c,n)	{ \
+			c+=n; \
+			switch (n) { \
+			case 8: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \
+			case 7: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \
+			case 6: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \
+			case 5: *(--(c))=(unsigned char)(((l2)    )&0xff); \
+			case 4: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \
+			case 3: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \
+			case 2: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \
+			case 1: *(--(c))=(unsigned char)(((l1)    )&0xff); \
+				} \
+			}
+
+#define n2s(c,s)	((s=(((unsigned int)(c[0]))<< 8)| \
+			    (((unsigned int)(c[1]))    )),c+=2)
+#define s2n(s,c)	((c[0]=(unsigned char)(((s)>> 8)&0xff), \
+			  c[1]=(unsigned char)(((s)    )&0xff)),c+=2)
+
+#define n2l3(c,l)	((l =(((unsigned long)(c[0]))<<16)| \
+			     (((unsigned long)(c[1]))<< 8)| \
+			     (((unsigned long)(c[2]))    )),c+=3)
+
+#define l2n3(l,c)	((c[0]=(unsigned char)(((l)>>16)&0xff), \
+			  c[1]=(unsigned char)(((l)>> 8)&0xff), \
+			  c[2]=(unsigned char)(((l)    )&0xff)),c+=3)
+
+/* LOCAL STUFF */
+
+#define SSL_DECRYPT	0
+#define SSL_ENCRYPT	1
+
+#define TWO_BYTE_BIT	0x80
+#define SEC_ESC_BIT	0x40
+#define TWO_BYTE_MASK	0x7fff
+#define THREE_BYTE_MASK	0x3fff
+
+#define INC32(a)	((a)=((a)+1)&0xffffffffL)
+#define DEC32(a)	((a)=((a)-1)&0xffffffffL)
+#define MAX_MAC_SIZE	20 /* up from 16 for SSLv3 */
+
+/*
+ * Define the Bitmasks for SSL_CIPHER.algorithms.
+ * This bits are used packed as dense as possible. If new methods/ciphers
+ * etc will be added, the bits a likely to change, so this information
+ * is for internal library use only, even though SSL_CIPHER.algorithms
+ * can be publicly accessed.
+ * Use the according functions for cipher management instead.
+ *
+ * The bit mask handling in the selection and sorting scheme in
+ * ssl_create_cipher_list() has only limited capabilities, reflecting
+ * that the different entities within are mutually exclusive:
+ * ONLY ONE BIT PER MASK CAN BE SET AT A TIME.
+ */
+
+/* Bits for algorithm_mkey (key exchange algorithm) */
+#define SSL_kRSA		0x00000001L /* RSA key exchange */
+#define SSL_kDHr		0x00000002L /* DH cert, RSA CA cert */ /* no such ciphersuites supported! */
+#define SSL_kDHd		0x00000004L /* DH cert, DSA CA cert */ /* no such ciphersuite supported! */
+#define SSL_kEDH		0x00000008L /* tmp DH key no DH cert */
+#define SSL_kKRB5		0x00000010L /* Kerberos5 key exchange */
+#define SSL_kECDHr		0x00000020L /* ECDH cert, RSA CA cert */
+#define SSL_kECDHe		0x00000040L /* ECDH cert, ECDSA CA cert */
+#define SSL_kEECDH		0x00000080L /* ephemeral ECDH */
+#define SSL_kPSK		0x00000100L /* PSK */
+#define SSL_kGOST       0x00000200L /* GOST key exchange */
+
+/* Bits for algorithm_auth (server authentication) */
+#define SSL_aRSA		0x00000001L /* RSA auth */
+#define SSL_aDSS 		0x00000002L /* DSS auth */
+#define SSL_aNULL 		0x00000004L /* no auth (i.e. use ADH or AECDH) */
+#define SSL_aDH 		0x00000008L /* Fixed DH auth (kDHd or kDHr) */ /* no such ciphersuites supported! */
+#define SSL_aECDH 		0x00000010L /* Fixed ECDH auth (kECDHe or kECDHr) */
+#define SSL_aKRB5               0x00000020L /* KRB5 auth */
+#define SSL_aECDSA              0x00000040L /* ECDSA auth*/
+#define SSL_aPSK                0x00000080L /* PSK auth */
+#define SSL_aGOST94				0x00000100L /* GOST R 34.10-94 signature auth */
+#define SSL_aGOST01 			0x00000200L /* GOST R 34.10-2001 signature auth */
+
+
+/* Bits for algorithm_enc (symmetric encryption) */
+#define SSL_DES			0x00000001L
+#define SSL_3DES		0x00000002L
+#define SSL_RC4			0x00000004L
+#define SSL_RC2			0x00000008L
+#define SSL_IDEA		0x00000010L
+#define SSL_eNULL		0x00000020L
+#define SSL_AES128		0x00000040L
+#define SSL_AES256		0x00000080L
+#define SSL_CAMELLIA128		0x00000100L
+#define SSL_CAMELLIA256		0x00000200L
+#define SSL_eGOST2814789CNT	0x00000400L
+#define SSL_SEED		0x00000800L
+
+#define SSL_AES        		(SSL_AES128|SSL_AES256)
+#define SSL_CAMELLIA		(SSL_CAMELLIA128|SSL_CAMELLIA256)
+
+
+/* Bits for algorithm_mac (symmetric authentication) */
+#define SSL_MD5			0x00000001L
+#define SSL_SHA1		0x00000002L
+#define SSL_GOST94      0x00000004L
+#define SSL_GOST89MAC   0x00000008L
+
+/* Bits for algorithm_ssl (protocol version) */
+#define SSL_SSLV2		0x00000001L
+#define SSL_SSLV3		0x00000002L
+#define SSL_TLSV1		SSL_SSLV3	/* for now */
+
+
+/* Bits for algorithm2 (handshake digests and other extra flags) */
+
+#define SSL_HANDSHAKE_MAC_MD5 0x10
+#define SSL_HANDSHAKE_MAC_SHA 0x20
+#define SSL_HANDSHAKE_MAC_GOST94 0x40
+#define SSL_HANDSHAKE_MAC_DEFAULT (SSL_HANDSHAKE_MAC_MD5 | SSL_HANDSHAKE_MAC_SHA)
+
+/* When adding new digest in the ssl_ciph.c and increment SSM_MD_NUM_IDX
+ * make sure to update this constant too */
+#define SSL_MAX_DIGEST 4
+
+#define TLS1_PRF_DGST_SHIFT 8
+#define TLS1_PRF_MD5 (SSL_HANDSHAKE_MAC_MD5 << TLS1_PRF_DGST_SHIFT)
+#define TLS1_PRF_SHA1 (SSL_HANDSHAKE_MAC_SHA << TLS1_PRF_DGST_SHIFT)
+#define TLS1_PRF_GOST94 (SSL_HANDSHAKE_MAC_GOST94 << TLS1_PRF_DGST_SHIFT)
+#define TLS1_PRF (TLS1_PRF_MD5 | TLS1_PRF_SHA1)
+
+/* Stream MAC for GOST ciphersuites from cryptopro draft
+ * (currently this also goes into algorithm2) */
+#define TLS1_STREAM_MAC 0x04
+
+
+
+/*
+ * Export and cipher strength information. For each cipher we have to decide
+ * whether it is exportable or not. This information is likely to change
+ * over time, since the export control rules are no static technical issue.
+ *
+ * Independent of the export flag the cipher strength is sorted into classes.
+ * SSL_EXP40 was denoting the 40bit US export limit of past times, which now
+ * is at 56bit (SSL_EXP56). If the exportable cipher class is going to change
+ * again (eg. to 64bit) the use of "SSL_EXP*" becomes blurred even more,
+ * since SSL_EXP64 could be similar to SSL_LOW.
+ * For this reason SSL_MICRO and SSL_MINI macros are included to widen the
+ * namespace of SSL_LOW-SSL_HIGH to lower values. As development of speed
+ * and ciphers goes, another extension to SSL_SUPER and/or SSL_ULTRA would
+ * be possible.
+ */
+#define SSL_EXP_MASK		0x00000003L
+#define SSL_STRONG_MASK		0x000001fcL
+
+#define SSL_NOT_EXP		0x00000001L
+#define SSL_EXPORT		0x00000002L
+
+#define SSL_STRONG_NONE		0x00000004L
+#define SSL_EXP40		0x00000008L
+#define SSL_MICRO		(SSL_EXP40)
+#define SSL_EXP56		0x00000010L
+#define SSL_MINI		(SSL_EXP56)
+#define SSL_LOW			0x00000020L
+#define SSL_MEDIUM		0x00000040L
+#define SSL_HIGH		0x00000080L
+#define SSL_FIPS		0x00000100L
+
+/* we have used 000001ff - 23 bits left to go */
+
+/*
+ * Macros to check the export status and cipher strength for export ciphers.
+ * Even though the macros for EXPORT and EXPORT40/56 have similar names,
+ * their meaning is different:
+ * *_EXPORT macros check the 'exportable' status.
+ * *_EXPORT40/56 macros are used to check whether a certain cipher strength
+ *          is given.
+ * Since the SSL_IS_EXPORT* and SSL_EXPORT* macros depend on the correct
+ * algorithm structure element to be passed (algorithms, algo_strength) and no
+ * typechecking can be done as they are all of type unsigned long, their
+ * direct usage is discouraged.
+ * Use the SSL_C_* macros instead.
+ */
+#define SSL_IS_EXPORT(a)	((a)&SSL_EXPORT)
+#define SSL_IS_EXPORT56(a)	((a)&SSL_EXP56)
+#define SSL_IS_EXPORT40(a)	((a)&SSL_EXP40)
+#define SSL_C_IS_EXPORT(c)	SSL_IS_EXPORT((c)->algo_strength)
+#define SSL_C_IS_EXPORT56(c)	SSL_IS_EXPORT56((c)->algo_strength)
+#define SSL_C_IS_EXPORT40(c)	SSL_IS_EXPORT40((c)->algo_strength)
+
+#define SSL_EXPORT_KEYLENGTH(a,s)	(SSL_IS_EXPORT40(s) ? 5 : \
+				 (a) == SSL_DES ? 8 : 7)
+#define SSL_EXPORT_PKEYLENGTH(a) (SSL_IS_EXPORT40(a) ? 512 : 1024)
+#define SSL_C_EXPORT_KEYLENGTH(c)	SSL_EXPORT_KEYLENGTH((c)->algorithm_enc, \
+				(c)->algo_strength)
+#define SSL_C_EXPORT_PKEYLENGTH(c)	SSL_EXPORT_PKEYLENGTH((c)->algo_strength)
+
+
+
+
+/* Mostly for SSLv3 */
+#define SSL_PKEY_RSA_ENC	0
+#define SSL_PKEY_RSA_SIGN	1
+#define SSL_PKEY_DSA_SIGN	2
+#define SSL_PKEY_DH_RSA		3
+#define SSL_PKEY_DH_DSA		4
+#define SSL_PKEY_ECC            5
+#define SSL_PKEY_GOST94		6
+#define SSL_PKEY_GOST01		7
+#define SSL_PKEY_NUM		8
+
+/* SSL_kRSA <- RSA_ENC | (RSA_TMP & RSA_SIGN) |
+ * 	    <- (EXPORT & (RSA_ENC | RSA_TMP) & RSA_SIGN)
+ * SSL_kDH  <- DH_ENC & (RSA_ENC | RSA_SIGN | DSA_SIGN)
+ * SSL_kEDH <- RSA_ENC | RSA_SIGN | DSA_SIGN
+ * SSL_aRSA <- RSA_ENC | RSA_SIGN
+ * SSL_aDSS <- DSA_SIGN
+ */
+
+/*
+#define CERT_INVALID		0
+#define CERT_PUBLIC_KEY		1
+#define CERT_PRIVATE_KEY	2
+*/
+
+#ifndef OPENSSL_NO_EC
+/* From ECC-TLS draft, used in encoding the curve type in 
+ * ECParameters
+ */
+#define EXPLICIT_PRIME_CURVE_TYPE  1   
+#define EXPLICIT_CHAR2_CURVE_TYPE  2
+#define NAMED_CURVE_TYPE           3
+#endif  /* OPENSSL_NO_EC */
+
+typedef struct cert_pkey_st
+	{
+	X509 *x509;
+	STACK_OF(X509) *cert_chain;
+	EVP_PKEY *privatekey;
+	} CERT_PKEY;
+
+typedef struct cert_st
+	{
+	/* Current active set */
+	CERT_PKEY *key; /* ALWAYS points to an element of the pkeys array
+			 * Probably it would make more sense to store
+			 * an index, not a pointer. */
+ 
+	/* The following masks are for the key and auth
+	 * algorithms that are supported by the certs below */
+	int valid;
+	unsigned long mask_k;
+	unsigned long mask_a;
+	unsigned long export_mask_k;
+	unsigned long export_mask_a;
+#ifndef OPENSSL_NO_RSA
+	RSA *rsa_tmp;
+	RSA *(*rsa_tmp_cb)(SSL *ssl,int is_export,int keysize);
+#endif
+#ifndef OPENSSL_NO_DH
+	DH *dh_tmp;
+	DH *(*dh_tmp_cb)(SSL *ssl,int is_export,int keysize);
+#endif
+#ifndef OPENSSL_NO_ECDH
+	EC_KEY *ecdh_tmp;
+	/* Callback for generating ephemeral ECDH keys */
+	EC_KEY *(*ecdh_tmp_cb)(SSL *ssl,int is_export,int keysize);
+#endif
+
+	CERT_PKEY pkeys[SSL_PKEY_NUM];
+
+	int references; /* >1 only if SSL_copy_session_id is used */
+	} CERT;
+
+
+typedef struct sess_cert_st
+	{
+	STACK_OF(X509) *cert_chain; /* as received from peer (not for SSL2) */
+
+	/* The 'peer_...' members are used only by clients. */
+	int peer_cert_type;
+
+	CERT_PKEY *peer_key; /* points to an element of peer_pkeys (never NULL!) */
+	CERT_PKEY peer_pkeys[SSL_PKEY_NUM];
+	/* Obviously we don't have the private keys of these,
+	 * so maybe we shouldn't even use the CERT_PKEY type here. */
+
+#ifndef OPENSSL_NO_RSA
+	RSA *peer_rsa_tmp; /* not used for SSL 2 */
+#endif
+#ifndef OPENSSL_NO_DH
+	DH *peer_dh_tmp; /* not used for SSL 2 */
+#endif
+#ifndef OPENSSL_NO_ECDH
+	EC_KEY *peer_ecdh_tmp;
+#endif
+
+	int references; /* actually always 1 at the moment */
+	} SESS_CERT;
+
+
+/*#define MAC_DEBUG	*/
+
+/*#define ERR_DEBUG	*/
+/*#define ABORT_DEBUG	*/
+/*#define PKT_DEBUG 1   */
+/*#define DES_DEBUG	*/
+/*#define DES_OFB_DEBUG	*/
+/*#define SSL_DEBUG	*/
+/*#define RSA_DEBUG	*/ 
+/*#define IDEA_DEBUG	*/ 
+
+#define FP_ICC  (int (*)(const void *,const void *))
+#define ssl_put_cipher_by_char(ssl,ciph,ptr) \
+		((ssl)->method->put_cipher_by_char((ciph),(ptr)))
+#define ssl_get_cipher_by_char(ssl,ptr) \
+		((ssl)->method->get_cipher_by_char(ptr))
+
+/* This is for the SSLv3/TLSv1.0 differences in crypto/hash stuff
+ * It is a bit of a mess of functions, but hell, think of it as
+ * an opaque structure :-) */
+typedef struct ssl3_enc_method
+	{
+	int (*enc)(SSL *, int);
+	int (*mac)(SSL *, unsigned char *, int);
+	int (*setup_key_block)(SSL *);
+	int (*generate_master_secret)(SSL *, unsigned char *, unsigned char *, int);
+	int (*change_cipher_state)(SSL *, int);
+	int (*final_finish_mac)(SSL *,  const char *, int, unsigned char *);
+	int finish_mac_length;
+	int (*cert_verify_mac)(SSL *, int, unsigned char *);
+	const char *client_finished_label;
+	int client_finished_label_len;
+	const char *server_finished_label;
+	int server_finished_label_len;
+	int (*alert_value)(int);
+	} SSL3_ENC_METHOD;
+
+#ifndef OPENSSL_NO_COMP
+/* Used for holding the relevant compression methods loaded into SSL_CTX */
+typedef struct ssl3_comp_st
+	{
+	int comp_id;	/* The identifier byte for this compression type */
+	char *name;	/* Text name used for the compression type */
+	COMP_METHOD *method; /* The method :-) */
+	} SSL3_COMP;
+#endif
+
+#ifndef OPENSSL_NO_BUF_FREELISTS
+typedef struct ssl3_buf_freelist_st
+	{
+	size_t chunklen;
+	unsigned int len;
+	struct ssl3_buf_freelist_entry_st *head;
+	} SSL3_BUF_FREELIST;
+
+typedef struct ssl3_buf_freelist_entry_st
+	{
+	struct ssl3_buf_freelist_entry_st *next;
+	} SSL3_BUF_FREELIST_ENTRY;
+#endif
+
+extern SSL3_ENC_METHOD ssl3_undef_enc_method;
+OPENSSL_EXTERN const SSL_CIPHER ssl2_ciphers[];
+OPENSSL_EXTERN SSL_CIPHER ssl3_ciphers[];
+
+
+SSL_METHOD *ssl_bad_method(int ver);
+
+extern SSL3_ENC_METHOD TLSv1_enc_data;
+extern SSL3_ENC_METHOD SSLv3_enc_data;
+extern SSL3_ENC_METHOD DTLSv1_enc_data;
+
+#define IMPLEMENT_tls1_meth_func(func_name, s_accept, s_connect, s_get_meth) \
+const SSL_METHOD *func_name(void)  \
+	{ \
+	static const SSL_METHOD func_name##_data= { \
+		TLS1_VERSION, \
+		tls1_new, \
+		tls1_clear, \
+		tls1_free, \
+		s_accept, \
+		s_connect, \
+		ssl3_read, \
+		ssl3_peek, \
+		ssl3_write, \
+		ssl3_shutdown, \
+		ssl3_renegotiate, \
+		ssl3_renegotiate_check, \
+		ssl3_get_message, \
+		ssl3_read_bytes, \
+		ssl3_write_bytes, \
+		ssl3_dispatch_alert, \
+		ssl3_ctrl, \
+		ssl3_ctx_ctrl, \
+		ssl3_get_cipher_by_char, \
+		ssl3_put_cipher_by_char, \
+		ssl3_pending, \
+		ssl3_num_ciphers, \
+		ssl3_get_cipher, \
+		s_get_meth, \
+		tls1_default_timeout, \
+		&TLSv1_enc_data, \
+		ssl_undefined_void_function, \
+		ssl3_callback_ctrl, \
+		ssl3_ctx_callback_ctrl, \
+	}; \
+	return &func_name##_data; \
+	}
+
+#define IMPLEMENT_ssl3_meth_func(func_name, s_accept, s_connect, s_get_meth) \
+const SSL_METHOD *func_name(void)  \
+	{ \
+	static const SSL_METHOD func_name##_data= { \
+		SSL3_VERSION, \
+		ssl3_new, \
+		ssl3_clear, \
+		ssl3_free, \
+		s_accept, \
+		s_connect, \
+		ssl3_read, \
+		ssl3_peek, \
+		ssl3_write, \
+		ssl3_shutdown, \
+		ssl3_renegotiate, \
+		ssl3_renegotiate_check, \
+		ssl3_get_message, \
+		ssl3_read_bytes, \
+		ssl3_write_bytes, \
+		ssl3_dispatch_alert, \
+		ssl3_ctrl, \
+		ssl3_ctx_ctrl, \
+		ssl3_get_cipher_by_char, \
+		ssl3_put_cipher_by_char, \
+		ssl3_pending, \
+		ssl3_num_ciphers, \
+		ssl3_get_cipher, \
+		s_get_meth, \
+		ssl3_default_timeout, \
+		&SSLv3_enc_data, \
+		ssl_undefined_void_function, \
+		ssl3_callback_ctrl, \
+		ssl3_ctx_callback_ctrl, \
+	}; \
+	return &func_name##_data; \
+	}
+
+#define IMPLEMENT_ssl23_meth_func(func_name, s_accept, s_connect, s_get_meth) \
+const SSL_METHOD *func_name(void)  \
+	{ \
+	static const SSL_METHOD func_name##_data= { \
+	TLS1_VERSION, \
+	tls1_new, \
+	tls1_clear, \
+	tls1_free, \
+	s_accept, \
+	s_connect, \
+	ssl23_read, \
+	ssl23_peek, \
+	ssl23_write, \
+	ssl_undefined_function, \
+	ssl_undefined_function, \
+	ssl_ok, \
+	ssl3_get_message, \
+	ssl3_read_bytes, \
+	ssl3_write_bytes, \
+	ssl3_dispatch_alert, \
+	ssl3_ctrl, \
+	ssl3_ctx_ctrl, \
+	ssl23_get_cipher_by_char, \
+	ssl23_put_cipher_by_char, \
+	ssl_undefined_const_function, \
+	ssl23_num_ciphers, \
+	ssl23_get_cipher, \
+	s_get_meth, \
+	ssl23_default_timeout, \
+	&ssl3_undef_enc_method, \
+	ssl_undefined_void_function, \
+	ssl3_callback_ctrl, \
+	ssl3_ctx_callback_ctrl, \
+	}; \
+	return &func_name##_data; \
+	}
+
+#define IMPLEMENT_ssl2_meth_func(func_name, s_accept, s_connect, s_get_meth) \
+const SSL_METHOD *func_name(void)  \
+	{ \
+	static const SSL_METHOD func_name##_data= { \
+		SSL2_VERSION, \
+		ssl2_new,	/* local */ \
+		ssl2_clear,	/* local */ \
+		ssl2_free,	/* local */ \
+		s_accept, \
+		s_connect, \
+		ssl2_read, \
+		ssl2_peek, \
+		ssl2_write, \
+		ssl2_shutdown, \
+		ssl_ok,	/* NULL - renegotiate */ \
+		ssl_ok,	/* NULL - check renegotiate */ \
+		NULL, /* NULL - ssl_get_message */ \
+		NULL, /* NULL - ssl_get_record */ \
+		NULL, /* NULL - ssl_write_bytes */ \
+		NULL, /* NULL - dispatch_alert */ \
+		ssl2_ctrl,	/* local */ \
+		ssl2_ctx_ctrl,	/* local */ \
+		ssl2_get_cipher_by_char, \
+		ssl2_put_cipher_by_char, \
+		ssl2_pending, \
+		ssl2_num_ciphers, \
+		ssl2_get_cipher, \
+		s_get_meth, \
+		ssl2_default_timeout, \
+		&ssl3_undef_enc_method, \
+		ssl_undefined_void_function, \
+		ssl2_callback_ctrl,	/* local */ \
+		ssl2_ctx_callback_ctrl,	/* local */ \
+	}; \
+	return &func_name##_data; \
+	}
+
+#define IMPLEMENT_dtls1_meth_func(func_name, s_accept, s_connect, s_get_meth) \
+const SSL_METHOD *func_name(void)  \
+	{ \
+	static const SSL_METHOD func_name##_data= { \
+		DTLS1_VERSION, \
+		dtls1_new, \
+		dtls1_clear, \
+		dtls1_free, \
+		s_accept, \
+		s_connect, \
+		ssl3_read, \
+		ssl3_peek, \
+		ssl3_write, \
+		ssl3_shutdown, \
+		ssl3_renegotiate, \
+		ssl3_renegotiate_check, \
+		dtls1_get_message, \
+		dtls1_read_bytes, \
+		dtls1_write_app_data_bytes, \
+		dtls1_dispatch_alert, \
+		dtls1_ctrl, \
+		ssl3_ctx_ctrl, \
+		ssl3_get_cipher_by_char, \
+		ssl3_put_cipher_by_char, \
+		ssl3_pending, \
+		ssl3_num_ciphers, \
+		dtls1_get_cipher, \
+		s_get_meth, \
+		dtls1_default_timeout, \
+		&DTLSv1_enc_data, \
+		ssl_undefined_void_function, \
+		ssl3_callback_ctrl, \
+		ssl3_ctx_callback_ctrl, \
+	}; \
+	return &func_name##_data; \
+	}
+
+void ssl_clear_cipher_ctx(SSL *s);
+int ssl_clear_bad_session(SSL *s);
+CERT *ssl_cert_new(void);
+CERT *ssl_cert_dup(CERT *cert);
+int ssl_cert_inst(CERT **o);
+void ssl_cert_free(CERT *c);
+SESS_CERT *ssl_sess_cert_new(void);
+void ssl_sess_cert_free(SESS_CERT *sc);
+int ssl_set_peer_cert_type(SESS_CERT *c, int type);
+int ssl_get_new_session(SSL *s, int session);
+int ssl_get_prev_session(SSL *s, unsigned char *session,int len, const unsigned char *limit);
+int ssl_cipher_id_cmp(const SSL_CIPHER *a,const SSL_CIPHER *b);
+DECLARE_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER,
+				  ssl_cipher_id);
+int ssl_cipher_ptr_id_cmp(const SSL_CIPHER * const *ap,
+			const SSL_CIPHER * const *bp);
+STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num,
+					       STACK_OF(SSL_CIPHER) **skp);
+int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p,
+                             int (*put_cb)(const SSL_CIPHER *, unsigned char *));
+STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *meth,
+					     STACK_OF(SSL_CIPHER) **pref,
+					     STACK_OF(SSL_CIPHER) **sorted,
+					     const char *rule_str);
+void ssl_update_cache(SSL *s, int mode);
+int ssl_cipher_get_evp(const SSL_SESSION *s,const EVP_CIPHER **enc,
+		       const EVP_MD **md,int *mac_pkey_type,int *mac_secret_size, SSL_COMP **comp);
+int ssl_get_handshake_digest(int i,long *mask,const EVP_MD **md);			   
+int ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk);
+int ssl_undefined_function(SSL *s);
+int ssl_undefined_void_function(void);
+int ssl_undefined_const_function(const SSL *s);
+X509 *ssl_get_server_send_cert(SSL *);
+EVP_PKEY *ssl_get_sign_pkey(SSL *,const SSL_CIPHER *);
+int ssl_cert_type(X509 *x,EVP_PKEY *pkey);
+void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher);
+STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s);
+int ssl_verify_alarm_type(long type);
+void ssl_load_ciphers(void);
+
+int ssl2_enc_init(SSL *s, int client);
+int ssl2_generate_key_material(SSL *s);
+void ssl2_enc(SSL *s,int send_data);
+void ssl2_mac(SSL *s,unsigned char *mac,int send_data);
+const SSL_CIPHER *ssl2_get_cipher_by_char(const unsigned char *p);
+int ssl2_put_cipher_by_char(const SSL_CIPHER *c,unsigned char *p);
+int ssl2_part_read(SSL *s, unsigned long f, int i);
+int ssl2_do_write(SSL *s);
+int ssl2_set_certificate(SSL *s, int type, int len, const unsigned char *data);
+void ssl2_return_error(SSL *s,int reason);
+void ssl2_write_error(SSL *s);
+int ssl2_num_ciphers(void);
+const SSL_CIPHER *ssl2_get_cipher(unsigned int u);
+int	ssl2_new(SSL *s);
+void	ssl2_free(SSL *s);
+int	ssl2_accept(SSL *s);
+int	ssl2_connect(SSL *s);
+int	ssl2_read(SSL *s, void *buf, int len);
+int	ssl2_peek(SSL *s, void *buf, int len);
+int	ssl2_write(SSL *s, const void *buf, int len);
+int	ssl2_shutdown(SSL *s);
+void	ssl2_clear(SSL *s);
+long	ssl2_ctrl(SSL *s,int cmd, long larg, void *parg);
+long	ssl2_ctx_ctrl(SSL_CTX *s,int cmd, long larg, void *parg);
+long	ssl2_callback_ctrl(SSL *s,int cmd, void (*fp)(void));
+long	ssl2_ctx_callback_ctrl(SSL_CTX *s,int cmd, void (*fp)(void));
+int	ssl2_pending(const SSL *s);
+long	ssl2_default_timeout(void );
+
+const SSL_CIPHER *ssl3_get_cipher_by_char(const unsigned char *p);
+int ssl3_put_cipher_by_char(const SSL_CIPHER *c,unsigned char *p);
+void ssl3_init_finished_mac(SSL *s);
+int ssl3_send_server_certificate(SSL *s);
+int ssl3_send_newsession_ticket(SSL *s);
+int ssl3_send_cert_status(SSL *s);
+int ssl3_get_finished(SSL *s,int state_a,int state_b);
+int ssl3_setup_key_block(SSL *s);
+int ssl3_send_change_cipher_spec(SSL *s,int state_a,int state_b);
+int ssl3_change_cipher_state(SSL *s,int which);
+void ssl3_cleanup_key_block(SSL *s);
+int ssl3_do_write(SSL *s,int type);
+int ssl3_send_alert(SSL *s,int level, int desc);
+int ssl3_generate_master_secret(SSL *s, unsigned char *out,
+	unsigned char *p, int len);
+int ssl3_get_req_cert_type(SSL *s,unsigned char *p);
+long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok);
+int ssl3_send_finished(SSL *s, int a, int b, const char *sender,int slen);
+int ssl3_num_ciphers(void);
+const SSL_CIPHER *ssl3_get_cipher(unsigned int u);
+int ssl3_renegotiate(SSL *ssl); 
+int ssl3_renegotiate_check(SSL *ssl); 
+int ssl3_dispatch_alert(SSL *s);
+int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek);
+int ssl3_write_bytes(SSL *s, int type, const void *buf, int len);
+int ssl3_final_finish_mac(SSL *s, const char *sender, int slen,unsigned char *p);
+int ssl3_cert_verify_mac(SSL *s, int md_nid, unsigned char *p);
+void ssl3_finish_mac(SSL *s, const unsigned char *buf, int len);
+int ssl3_enc(SSL *s, int send_data);
+int n_ssl3_mac(SSL *ssl, unsigned char *md, int send_data);
+void ssl3_free_digest_list(SSL *s);
+unsigned long ssl3_output_cert_chain(SSL *s, X509 *x);
+SSL_CIPHER *ssl3_choose_cipher(SSL *ssl,STACK_OF(SSL_CIPHER) *clnt,
+			       STACK_OF(SSL_CIPHER) *srvr);
+int	ssl3_setup_buffers(SSL *s);
+int	ssl3_setup_read_buffer(SSL *s);
+int	ssl3_setup_write_buffer(SSL *s);
+int	ssl3_release_read_buffer(SSL *s);
+int	ssl3_release_write_buffer(SSL *s);
+int	ssl3_digest_cached_records(SSL *s);
+int	ssl3_new(SSL *s);
+void	ssl3_free(SSL *s);
+int	ssl3_accept(SSL *s);
+int	ssl3_connect(SSL *s);
+int	ssl3_read(SSL *s, void *buf, int len);
+int	ssl3_peek(SSL *s, void *buf, int len);
+int	ssl3_write(SSL *s, const void *buf, int len);
+int	ssl3_shutdown(SSL *s);
+void	ssl3_clear(SSL *s);
+long	ssl3_ctrl(SSL *s,int cmd, long larg, void *parg);
+long	ssl3_ctx_ctrl(SSL_CTX *s,int cmd, long larg, void *parg);
+long	ssl3_callback_ctrl(SSL *s,int cmd, void (*fp)(void));
+long	ssl3_ctx_callback_ctrl(SSL_CTX *s,int cmd, void (*fp)(void));
+int	ssl3_pending(const SSL *s);
+
+void ssl3_record_sequence_update(unsigned char *seq);
+int ssl3_do_change_cipher_spec(SSL *ssl);
+long ssl3_default_timeout(void );
+
+int ssl23_num_ciphers(void );
+const SSL_CIPHER *ssl23_get_cipher(unsigned int u);
+int ssl23_read(SSL *s, void *buf, int len);
+int ssl23_peek(SSL *s, void *buf, int len);
+int ssl23_write(SSL *s, const void *buf, int len);
+int ssl23_put_cipher_by_char(const SSL_CIPHER *c, unsigned char *p);
+const SSL_CIPHER *ssl23_get_cipher_by_char(const unsigned char *p);
+long ssl23_default_timeout(void );
+
+long tls1_default_timeout(void);
+int dtls1_do_write(SSL *s,int type);
+int ssl3_read_n(SSL *s, int n, int max, int extend);
+int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek);
+int ssl3_do_compress(SSL *ssl);
+int ssl3_do_uncompress(SSL *ssl);
+int ssl3_write_pending(SSL *s, int type, const unsigned char *buf,
+	unsigned int len);
+unsigned char *dtls1_set_message_header(SSL *s, 
+	unsigned char *p, unsigned char mt,	unsigned long len, 
+	unsigned long frag_off, unsigned long frag_len);
+
+int dtls1_write_app_data_bytes(SSL *s, int type, const void *buf, int len);
+int dtls1_write_bytes(SSL *s, int type, const void *buf, int len);
+
+int dtls1_send_change_cipher_spec(SSL *s, int a, int b);
+int dtls1_send_finished(SSL *s, int a, int b, const char *sender, int slen);
+unsigned long dtls1_output_cert_chain(SSL *s, X509 *x);
+int dtls1_read_failed(SSL *s, int code);
+int dtls1_buffer_message(SSL *s, int ccs);
+int dtls1_retransmit_message(SSL *s, unsigned short seq, 
+	unsigned long frag_off, int *found);
+int dtls1_get_queue_priority(unsigned short seq, int is_ccs);
+int dtls1_retransmit_buffered_messages(SSL *s);
+void dtls1_clear_record_buffer(SSL *s);
+void dtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr);
+void dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr);
+void dtls1_reset_seq_numbers(SSL *s, int rw);
+long dtls1_default_timeout(void);
+struct timeval* dtls1_get_timeout(SSL *s, struct timeval* timeleft);
+int dtls1_handle_timeout(SSL *s);
+const SSL_CIPHER *dtls1_get_cipher(unsigned int u);
+void dtls1_start_timer(SSL *s);
+void dtls1_stop_timer(SSL *s);
+int dtls1_is_timer_expired(SSL *s);
+void dtls1_double_timeout(SSL *s);
+int dtls1_send_newsession_ticket(SSL *s);
+
+/* some client-only functions */
+int ssl3_client_hello(SSL *s);
+int ssl3_get_server_hello(SSL *s);
+int ssl3_get_certificate_request(SSL *s);
+int ssl3_get_new_session_ticket(SSL *s);
+int ssl3_get_cert_status(SSL *s);
+int ssl3_get_server_done(SSL *s);
+int ssl3_send_client_verify(SSL *s);
+int ssl3_send_client_certificate(SSL *s);
+int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey);
+int ssl3_send_client_key_exchange(SSL *s);
+int ssl3_get_key_exchange(SSL *s);
+int ssl3_get_server_certificate(SSL *s);
+int ssl3_check_cert_and_algorithm(SSL *s);
+#ifndef OPENSSL_NO_TLSEXT
+int ssl3_check_finished(SSL *s);
+#endif
+
+int dtls1_client_hello(SSL *s);
+int dtls1_send_client_certificate(SSL *s);
+int dtls1_send_client_key_exchange(SSL *s);
+int dtls1_send_client_verify(SSL *s);
+
+/* some server-only functions */
+int ssl3_get_client_hello(SSL *s);
+int ssl3_send_server_hello(SSL *s);
+int ssl3_send_hello_request(SSL *s);
+int ssl3_send_server_key_exchange(SSL *s);
+int ssl3_send_certificate_request(SSL *s);
+int ssl3_send_server_done(SSL *s);
+int ssl3_check_client_hello(SSL *s);
+int ssl3_get_client_certificate(SSL *s);
+int ssl3_get_client_key_exchange(SSL *s);
+int ssl3_get_cert_verify(SSL *s);
+
+int dtls1_send_hello_request(SSL *s);
+int dtls1_send_server_hello(SSL *s);
+int dtls1_send_server_certificate(SSL *s);
+int dtls1_send_server_key_exchange(SSL *s);
+int dtls1_send_certificate_request(SSL *s);
+int dtls1_send_server_done(SSL *s);
+
+
+
+int ssl23_accept(SSL *s);
+int ssl23_connect(SSL *s);
+int ssl23_read_bytes(SSL *s, int n);
+int ssl23_write_bytes(SSL *s);
+
+int tls1_new(SSL *s);
+void tls1_free(SSL *s);
+void tls1_clear(SSL *s);
+long tls1_ctrl(SSL *s,int cmd, long larg, void *parg);
+long tls1_callback_ctrl(SSL *s,int cmd, void (*fp)(void));
+
+int dtls1_new(SSL *s);
+int	dtls1_accept(SSL *s);
+int	dtls1_connect(SSL *s);
+void dtls1_free(SSL *s);
+void dtls1_clear(SSL *s);
+long dtls1_ctrl(SSL *s,int cmd, long larg, void *parg);
+
+long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok);
+int dtls1_get_record(SSL *s);
+int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
+	unsigned int len, int create_empty_fragement);
+int dtls1_dispatch_alert(SSL *s);
+int dtls1_enc(SSL *s, int snd);
+
+int ssl_init_wbio_buffer(SSL *s, int push);
+void ssl_free_wbio_buffer(SSL *s);
+
+int tls1_change_cipher_state(SSL *s, int which);
+int tls1_setup_key_block(SSL *s);
+int tls1_enc(SSL *s, int snd);
+int tls1_final_finish_mac(SSL *s,
+	const char *str, int slen, unsigned char *p);
+int tls1_cert_verify_mac(SSL *s, int md_nid, unsigned char *p);
+int tls1_mac(SSL *ssl, unsigned char *md, int snd);
+int tls1_generate_master_secret(SSL *s, unsigned char *out,
+	unsigned char *p, int len);
+int tls1_alert_code(int code);
+int ssl3_alert_code(int code);
+int ssl_ok(SSL *s);
+
+#ifndef OPENSSL_NO_ECDH
+int ssl_check_srvr_ecc_cert_and_alg(X509 *x, const SSL_CIPHER *cs);
+#endif
+
+SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n);
+
+#ifndef OPENSSL_NO_EC
+int tls1_ec_curve_id2nid(int curve_id);
+int tls1_ec_nid2curve_id(int nid);
+#endif /* OPENSSL_NO_EC */
+
+#ifndef OPENSSL_NO_TLSEXT
+unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit); 
+unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit); 
+int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **data, unsigned char *d, int n, int *al);
+int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **data, unsigned char *d, int n, int *al);
+int ssl_prepare_clienthello_tlsext(SSL *s);
+int ssl_prepare_serverhello_tlsext(SSL *s);
+int ssl_check_clienthello_tlsext(SSL *s);
+int ssl_check_serverhello_tlsext(SSL *s);
+
+#ifdef OPENSSL_NO_SHA256
+#define tlsext_tick_md	EVP_sha1
+#else
+#define tlsext_tick_md	EVP_sha256
+#endif
+int tls1_process_ticket(SSL *s, unsigned char *session_id, int len,
+				const unsigned char *limit, SSL_SESSION **ret);
+#endif
+EVP_MD_CTX* ssl_replace_hash(EVP_MD_CTX **hash,const EVP_MD *md) ;
+void ssl_clear_hash_ctx(EVP_MD_CTX **hash);
+int ssl_add_serverhello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
+					int maxlen);
+int ssl_parse_serverhello_renegotiate_ext(SSL *s, unsigned char *d, int len,
+					  int *al);
+int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
+					int maxlen);
+int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len,
+					  int *al);
+#endif
diff --git a/lib/openssl/ssl/ssl_rsa.c b/lib/openssl/ssl/ssl_rsa.c
new file mode 100644
index 0000000..c43f3e2
--- /dev/null
+++ b/lib/openssl/ssl/ssl_rsa.c
@@ -0,0 +1,815 @@
+/* ssl/ssl_rsa.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include "ssl_locl.h"
+#include <openssl/bio.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+#include <openssl/pem.h>
+
+static int ssl_set_cert(CERT *c, X509 *x509);
+static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey);
+int SSL_use_certificate(SSL *ssl, X509 *x)
+	{
+	if (x == NULL)
+		{
+		SSLerr(SSL_F_SSL_USE_CERTIFICATE,ERR_R_PASSED_NULL_PARAMETER);
+		return(0);
+		}
+	if (!ssl_cert_inst(&ssl->cert))
+		{
+		SSLerr(SSL_F_SSL_USE_CERTIFICATE,ERR_R_MALLOC_FAILURE);
+		return(0);
+		}
+	return(ssl_set_cert(ssl->cert,x));
+	}
+
+#ifndef OPENSSL_NO_STDIO
+int SSL_use_certificate_file(SSL *ssl, const char *file, int type)
+	{
+	int j;
+	BIO *in;
+	int ret=0;
+	X509 *x=NULL;
+
+	in=BIO_new(BIO_s_file_internal());
+	if (in == NULL)
+		{
+		SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE,ERR_R_BUF_LIB);
+		goto end;
+		}
+
+	if (BIO_read_filename(in,file) <= 0)
+		{
+		SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE,ERR_R_SYS_LIB);
+		goto end;
+		}
+	if (type == SSL_FILETYPE_ASN1)
+		{
+		j=ERR_R_ASN1_LIB;
+		x=d2i_X509_bio(in,NULL);
+		}
+	else if (type == SSL_FILETYPE_PEM)
+		{
+		j=ERR_R_PEM_LIB;
+		x=PEM_read_bio_X509(in,NULL,ssl->ctx->default_passwd_callback,ssl->ctx->default_passwd_callback_userdata);
+		}
+	else
+		{
+		SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE,SSL_R_BAD_SSL_FILETYPE);
+		goto end;
+		}
+
+	if (x == NULL)
+		{
+		SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE,j);
+		goto end;
+		}
+
+	ret=SSL_use_certificate(ssl,x);
+end:
+	if (x != NULL) X509_free(x);
+	if (in != NULL) BIO_free(in);
+	return(ret);
+	}
+#endif
+
+int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len)
+	{
+	X509 *x;
+	int ret;
+
+	x=d2i_X509(NULL,&d,(long)len);
+	if (x == NULL)
+		{
+		SSLerr(SSL_F_SSL_USE_CERTIFICATE_ASN1,ERR_R_ASN1_LIB);
+		return(0);
+		}
+
+	ret=SSL_use_certificate(ssl,x);
+	X509_free(x);
+	return(ret);
+	}
+
+#ifndef OPENSSL_NO_RSA
+int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa)
+	{
+	EVP_PKEY *pkey;
+	int ret;
+
+	if (rsa == NULL)
+		{
+		SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER);
+		return(0);
+		}
+	if (!ssl_cert_inst(&ssl->cert))
+		{
+		SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY,ERR_R_MALLOC_FAILURE);
+		return(0);
+		}
+	if ((pkey=EVP_PKEY_new()) == NULL)
+		{
+		SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY,ERR_R_EVP_LIB);
+		return(0);
+		}
+
+	RSA_up_ref(rsa);
+	EVP_PKEY_assign_RSA(pkey,rsa);
+
+	ret=ssl_set_pkey(ssl->cert,pkey);
+	EVP_PKEY_free(pkey);
+	return(ret);
+	}
+#endif
+
+static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey)
+	{
+	int i;
+
+	i=ssl_cert_type(NULL,pkey);
+	if (i < 0)
+		{
+		SSLerr(SSL_F_SSL_SET_PKEY,SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+		return(0);
+		}
+
+	if (c->pkeys[i].x509 != NULL)
+		{
+		EVP_PKEY *pktmp;
+		pktmp =	X509_get_pubkey(c->pkeys[i].x509);
+		EVP_PKEY_copy_parameters(pktmp,pkey);
+		EVP_PKEY_free(pktmp);
+		ERR_clear_error();
+
+#ifndef OPENSSL_NO_RSA
+		/* Don't check the public/private key, this is mostly
+		 * for smart cards. */
+		if ((pkey->type == EVP_PKEY_RSA) &&
+			(RSA_flags(pkey->pkey.rsa) & RSA_METHOD_FLAG_NO_CHECK))
+			;
+		else
+#endif
+		if (!X509_check_private_key(c->pkeys[i].x509,pkey))
+			{
+			X509_free(c->pkeys[i].x509);
+			c->pkeys[i].x509 = NULL;
+			return 0;
+			}
+		}
+
+	if (c->pkeys[i].privatekey != NULL)
+		EVP_PKEY_free(c->pkeys[i].privatekey);
+	CRYPTO_add(&pkey->references,1,CRYPTO_LOCK_EVP_PKEY);
+	c->pkeys[i].privatekey=pkey;
+	c->key= &(c->pkeys[i]);
+
+	c->valid=0;
+	return(1);
+	}
+
+#ifndef OPENSSL_NO_RSA
+#ifndef OPENSSL_NO_STDIO
+int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type)
+	{
+	int j,ret=0;
+	BIO *in;
+	RSA *rsa=NULL;
+
+	in=BIO_new(BIO_s_file_internal());
+	if (in == NULL)
+		{
+		SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE,ERR_R_BUF_LIB);
+		goto end;
+		}
+
+	if (BIO_read_filename(in,file) <= 0)
+		{
+		SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE,ERR_R_SYS_LIB);
+		goto end;
+		}
+	if	(type == SSL_FILETYPE_ASN1)
+		{
+		j=ERR_R_ASN1_LIB;
+		rsa=d2i_RSAPrivateKey_bio(in,NULL);
+		}
+	else if (type == SSL_FILETYPE_PEM)
+		{
+		j=ERR_R_PEM_LIB;
+		rsa=PEM_read_bio_RSAPrivateKey(in,NULL,
+			ssl->ctx->default_passwd_callback,ssl->ctx->default_passwd_callback_userdata);
+		}
+	else
+		{
+		SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE,SSL_R_BAD_SSL_FILETYPE);
+		goto end;
+		}
+	if (rsa == NULL)
+		{
+		SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE,j);
+		goto end;
+		}
+	ret=SSL_use_RSAPrivateKey(ssl,rsa);
+	RSA_free(rsa);
+end:
+	if (in != NULL) BIO_free(in);
+	return(ret);
+	}
+#endif
+
+int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, unsigned char *d, long len)
+	{
+	int ret;
+	const unsigned char *p;
+	RSA *rsa;
+
+	p=d;
+	if ((rsa=d2i_RSAPrivateKey(NULL,&p,(long)len)) == NULL)
+		{
+		SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1,ERR_R_ASN1_LIB);
+		return(0);
+		}
+
+	ret=SSL_use_RSAPrivateKey(ssl,rsa);
+	RSA_free(rsa);
+	return(ret);
+	}
+#endif /* !OPENSSL_NO_RSA */
+
+int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey)
+	{
+	int ret;
+
+	if (pkey == NULL)
+		{
+		SSLerr(SSL_F_SSL_USE_PRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER);
+		return(0);
+		}
+	if (!ssl_cert_inst(&ssl->cert))
+		{
+		SSLerr(SSL_F_SSL_USE_PRIVATEKEY,ERR_R_MALLOC_FAILURE);
+		return(0);
+		}
+	ret=ssl_set_pkey(ssl->cert,pkey);
+	return(ret);
+	}
+
+#ifndef OPENSSL_NO_STDIO
+int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type)
+	{
+	int j,ret=0;
+	BIO *in;
+	EVP_PKEY *pkey=NULL;
+
+	in=BIO_new(BIO_s_file_internal());
+	if (in == NULL)
+		{
+		SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE,ERR_R_BUF_LIB);
+		goto end;
+		}
+
+	if (BIO_read_filename(in,file) <= 0)
+		{
+		SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE,ERR_R_SYS_LIB);
+		goto end;
+		}
+	if (type == SSL_FILETYPE_PEM)
+		{
+		j=ERR_R_PEM_LIB;
+		pkey=PEM_read_bio_PrivateKey(in,NULL,
+			ssl->ctx->default_passwd_callback,ssl->ctx->default_passwd_callback_userdata);
+		}
+	else if (type == SSL_FILETYPE_ASN1)
+		{
+		j = ERR_R_ASN1_LIB;
+		pkey = d2i_PrivateKey_bio(in,NULL);
+		}
+	else
+		{
+		SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE,SSL_R_BAD_SSL_FILETYPE);
+		goto end;
+		}
+	if (pkey == NULL)
+		{
+		SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE,j);
+		goto end;
+		}
+	ret=SSL_use_PrivateKey(ssl,pkey);
+	EVP_PKEY_free(pkey);
+end:
+	if (in != NULL) BIO_free(in);
+	return(ret);
+	}
+#endif
+
+int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const unsigned char *d, long len)
+	{
+	int ret;
+	const unsigned char *p;
+	EVP_PKEY *pkey;
+
+	p=d;
+	if ((pkey=d2i_PrivateKey(type,NULL,&p,(long)len)) == NULL)
+		{
+		SSLerr(SSL_F_SSL_USE_PRIVATEKEY_ASN1,ERR_R_ASN1_LIB);
+		return(0);
+		}
+
+	ret=SSL_use_PrivateKey(ssl,pkey);
+	EVP_PKEY_free(pkey);
+	return(ret);
+	}
+
+int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x)
+	{
+	if (x == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE,ERR_R_PASSED_NULL_PARAMETER);
+		return(0);
+		}
+	if (!ssl_cert_inst(&ctx->cert))
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE,ERR_R_MALLOC_FAILURE);
+		return(0);
+		}
+	return(ssl_set_cert(ctx->cert, x));
+	}
+
+static int ssl_set_cert(CERT *c, X509 *x)
+	{
+	EVP_PKEY *pkey;
+	int i;
+
+	pkey=X509_get_pubkey(x);
+	if (pkey == NULL)
+		{
+		SSLerr(SSL_F_SSL_SET_CERT,SSL_R_X509_LIB);
+		return(0);
+		}
+
+	i=ssl_cert_type(x,pkey);
+	if (i < 0)
+		{
+		SSLerr(SSL_F_SSL_SET_CERT,SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+		EVP_PKEY_free(pkey);
+		return(0);
+		}
+
+	if (c->pkeys[i].privatekey != NULL)
+		{
+		EVP_PKEY_copy_parameters(pkey,c->pkeys[i].privatekey);
+		ERR_clear_error();
+
+#ifndef OPENSSL_NO_RSA
+		/* Don't check the public/private key, this is mostly
+		 * for smart cards. */
+		if ((c->pkeys[i].privatekey->type == EVP_PKEY_RSA) &&
+			(RSA_flags(c->pkeys[i].privatekey->pkey.rsa) &
+			 RSA_METHOD_FLAG_NO_CHECK))
+			 ;
+		else
+#endif /* OPENSSL_NO_RSA */
+		if (!X509_check_private_key(x,c->pkeys[i].privatekey))
+			{
+			/* don't fail for a cert/key mismatch, just free
+			 * current private key (when switching to a different
+			 * cert & key, first this function should be used,
+			 * then ssl_set_pkey */
+			EVP_PKEY_free(c->pkeys[i].privatekey);
+			c->pkeys[i].privatekey=NULL;
+			/* clear error queue */
+			ERR_clear_error();
+			}
+		}
+
+	EVP_PKEY_free(pkey);
+
+	if (c->pkeys[i].x509 != NULL)
+		X509_free(c->pkeys[i].x509);
+	CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509);
+	c->pkeys[i].x509=x;
+	c->key= &(c->pkeys[i]);
+
+	c->valid=0;
+	return(1);
+	}
+
+#ifndef OPENSSL_NO_STDIO
+int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type)
+	{
+	int j;
+	BIO *in;
+	int ret=0;
+	X509 *x=NULL;
+
+	in=BIO_new(BIO_s_file_internal());
+	if (in == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,ERR_R_BUF_LIB);
+		goto end;
+		}
+
+	if (BIO_read_filename(in,file) <= 0)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,ERR_R_SYS_LIB);
+		goto end;
+		}
+	if (type == SSL_FILETYPE_ASN1)
+		{
+		j=ERR_R_ASN1_LIB;
+		x=d2i_X509_bio(in,NULL);
+		}
+	else if (type == SSL_FILETYPE_PEM)
+		{
+		j=ERR_R_PEM_LIB;
+		x=PEM_read_bio_X509(in,NULL,ctx->default_passwd_callback,ctx->default_passwd_callback_userdata);
+		}
+	else
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,SSL_R_BAD_SSL_FILETYPE);
+		goto end;
+		}
+
+	if (x == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,j);
+		goto end;
+		}
+
+	ret=SSL_CTX_use_certificate(ctx,x);
+end:
+	if (x != NULL) X509_free(x);
+	if (in != NULL) BIO_free(in);
+	return(ret);
+	}
+#endif
+
+int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const unsigned char *d)
+	{
+	X509 *x;
+	int ret;
+
+	x=d2i_X509(NULL,&d,(long)len);
+	if (x == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1,ERR_R_ASN1_LIB);
+		return(0);
+		}
+
+	ret=SSL_CTX_use_certificate(ctx,x);
+	X509_free(x);
+	return(ret);
+	}
+
+#ifndef OPENSSL_NO_RSA
+int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa)
+	{
+	int ret;
+	EVP_PKEY *pkey;
+
+	if (rsa == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER);
+		return(0);
+		}
+	if (!ssl_cert_inst(&ctx->cert))
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY,ERR_R_MALLOC_FAILURE);
+		return(0);
+		}
+	if ((pkey=EVP_PKEY_new()) == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY,ERR_R_EVP_LIB);
+		return(0);
+		}
+
+	RSA_up_ref(rsa);
+	EVP_PKEY_assign_RSA(pkey,rsa);
+
+	ret=ssl_set_pkey(ctx->cert, pkey);
+	EVP_PKEY_free(pkey);
+	return(ret);
+	}
+
+#ifndef OPENSSL_NO_STDIO
+int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type)
+	{
+	int j,ret=0;
+	BIO *in;
+	RSA *rsa=NULL;
+
+	in=BIO_new(BIO_s_file_internal());
+	if (in == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE,ERR_R_BUF_LIB);
+		goto end;
+		}
+
+	if (BIO_read_filename(in,file) <= 0)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE,ERR_R_SYS_LIB);
+		goto end;
+		}
+	if	(type == SSL_FILETYPE_ASN1)
+		{
+		j=ERR_R_ASN1_LIB;
+		rsa=d2i_RSAPrivateKey_bio(in,NULL);
+		}
+	else if (type == SSL_FILETYPE_PEM)
+		{
+		j=ERR_R_PEM_LIB;
+		rsa=PEM_read_bio_RSAPrivateKey(in,NULL,
+			ctx->default_passwd_callback,ctx->default_passwd_callback_userdata);
+		}
+	else
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE,SSL_R_BAD_SSL_FILETYPE);
+		goto end;
+		}
+	if (rsa == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE,j);
+		goto end;
+		}
+	ret=SSL_CTX_use_RSAPrivateKey(ctx,rsa);
+	RSA_free(rsa);
+end:
+	if (in != NULL) BIO_free(in);
+	return(ret);
+	}
+#endif
+
+int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d, long len)
+	{
+	int ret;
+	const unsigned char *p;
+	RSA *rsa;
+
+	p=d;
+	if ((rsa=d2i_RSAPrivateKey(NULL,&p,(long)len)) == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1,ERR_R_ASN1_LIB);
+		return(0);
+		}
+
+	ret=SSL_CTX_use_RSAPrivateKey(ctx,rsa);
+	RSA_free(rsa);
+	return(ret);
+	}
+#endif /* !OPENSSL_NO_RSA */
+
+int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey)
+	{
+	if (pkey == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER);
+		return(0);
+		}
+	if (!ssl_cert_inst(&ctx->cert))
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY,ERR_R_MALLOC_FAILURE);
+		return(0);
+		}
+	return(ssl_set_pkey(ctx->cert,pkey));
+	}
+
+#ifndef OPENSSL_NO_STDIO
+int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type)
+	{
+	int j,ret=0;
+	BIO *in;
+	EVP_PKEY *pkey=NULL;
+
+	in=BIO_new(BIO_s_file_internal());
+	if (in == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE,ERR_R_BUF_LIB);
+		goto end;
+		}
+
+	if (BIO_read_filename(in,file) <= 0)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE,ERR_R_SYS_LIB);
+		goto end;
+		}
+	if (type == SSL_FILETYPE_PEM)
+		{
+		j=ERR_R_PEM_LIB;
+		pkey=PEM_read_bio_PrivateKey(in,NULL,
+			ctx->default_passwd_callback,ctx->default_passwd_callback_userdata);
+		}
+	else if (type == SSL_FILETYPE_ASN1)
+		{
+		j = ERR_R_ASN1_LIB;
+		pkey = d2i_PrivateKey_bio(in,NULL);
+		}
+	else
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE,SSL_R_BAD_SSL_FILETYPE);
+		goto end;
+		}
+	if (pkey == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE,j);
+		goto end;
+		}
+	ret=SSL_CTX_use_PrivateKey(ctx,pkey);
+	EVP_PKEY_free(pkey);
+end:
+	if (in != NULL) BIO_free(in);
+	return(ret);
+	}
+#endif
+
+int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, const unsigned char *d,
+	     long len)
+	{
+	int ret;
+	const unsigned char *p;
+	EVP_PKEY *pkey;
+
+	p=d;
+	if ((pkey=d2i_PrivateKey(type,NULL,&p,(long)len)) == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1,ERR_R_ASN1_LIB);
+		return(0);
+		}
+
+	ret=SSL_CTX_use_PrivateKey(ctx,pkey);
+	EVP_PKEY_free(pkey);
+	return(ret);
+	}
+
+
+int SSL_use_certificate_chain(SSL *ssl, STACK_OF(X509) *cert_chain)
+	{
+	if (ssl == NULL)
+		{
+		SSLerr(SSL_F_SSL_USE_CERTIFICATE_CHAIN,ERR_R_PASSED_NULL_PARAMETER);
+		return(0);
+		}
+	if (ssl->cert == NULL)
+		{
+		SSLerr(SSL_F_SSL_USE_CERTIFICATE_CHAIN,SSL_R_NO_CERTIFICATE_ASSIGNED);
+		return(0);
+		}
+	if (ssl->cert->key == NULL)
+		{
+		SSLerr(SSL_F_SSL_USE_CERTIFICATE_CHAIN,SSL_R_NO_CERTIFICATE_ASSIGNED);
+		return(0);
+		}
+	ssl->cert->key->cert_chain = cert_chain;
+	return(1);
+	}
+
+STACK_OF(X509) *SSL_get_certificate_chain(SSL *ssl, X509 *x)
+	{
+	int i;
+	if (x == NULL)
+		return NULL;
+	if (ssl == NULL)
+		return NULL;
+	if (ssl->cert == NULL)
+		return NULL;
+	for (i = 0; i < SSL_PKEY_NUM; i++)
+		if (ssl->cert->pkeys[i].x509 == x)
+			return ssl->cert->pkeys[i].cert_chain;
+	return NULL;
+	}
+
+#ifndef OPENSSL_NO_STDIO
+/* Read a file that contains our certificate in "PEM" format,
+ * possibly followed by a sequence of CA certificates that should be
+ * sent to the peer in the Certificate message.
+ */
+int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file)
+	{
+	BIO *in;
+	int ret=0;
+	X509 *x=NULL;
+
+	ERR_clear_error(); /* clear error stack for SSL_CTX_use_certificate() */
+
+	in=BIO_new(BIO_s_file_internal());
+	if (in == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE,ERR_R_BUF_LIB);
+		goto end;
+		}
+
+	if (BIO_read_filename(in,file) <= 0)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE,ERR_R_SYS_LIB);
+		goto end;
+		}
+
+	x=PEM_read_bio_X509_AUX(in,NULL,ctx->default_passwd_callback,ctx->default_passwd_callback_userdata);
+	if (x == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE,ERR_R_PEM_LIB);
+		goto end;
+		}
+
+	ret=SSL_CTX_use_certificate(ctx,x);
+	if (ERR_peek_error() != 0)
+		ret = 0;  /* Key/certificate mismatch doesn't imply ret==0 ... */
+	if (ret)
+		{
+		/* If we could set up our certificate, now proceed to
+		 * the CA certificates.
+		 */
+		X509 *ca;
+		int r;
+		unsigned long err;
+		
+		if (ctx->extra_certs != NULL) 
+			{
+			sk_X509_pop_free(ctx->extra_certs, X509_free);
+			ctx->extra_certs = NULL;
+			}
+
+		while ((ca = PEM_read_bio_X509(in,NULL,ctx->default_passwd_callback,ctx->default_passwd_callback_userdata))
+			!= NULL)
+			{
+			r = SSL_CTX_add_extra_chain_cert(ctx, ca);
+			if (!r) 
+				{
+				X509_free(ca);
+				ret = 0;
+				goto end;
+				}
+			/* Note that we must not free r if it was successfully
+			 * added to the chain (while we must free the main
+			 * certificate, since its reference count is increased
+			 * by SSL_CTX_use_certificate). */
+			}
+		/* When the while loop ends, it's usually just EOF. */
+		err = ERR_peek_last_error();
+		if (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)
+			ERR_clear_error();
+		else 
+			ret = 0; /* some real error */
+		}
+
+end:
+	if (x != NULL) X509_free(x);
+	if (in != NULL) BIO_free(in);
+	return(ret);
+	}
+#endif
diff --git a/lib/openssl/ssl/ssl_sess.c b/lib/openssl/ssl/ssl_sess.c
new file mode 100644
index 0000000..93954e4
--- /dev/null
+++ b/lib/openssl/ssl/ssl_sess.c
@@ -0,0 +1,1102 @@
+/* ssl/ssl_sess.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#include <stdio.h>
+#include <openssl/lhash.h>
+#include <openssl/rand.h>
+#ifndef OPENSSL_NO_ENGINE
+#include <openssl/engine.h>
+#endif
+#include "ssl_locl.h"
+
+static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s);
+static void SSL_SESSION_list_add(SSL_CTX *ctx,SSL_SESSION *s);
+static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck);
+
+SSL_SESSION *SSL_get_session(const SSL *ssl)
+/* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */
+	{
+	return(ssl->session);
+	}
+
+SSL_SESSION *SSL_get1_session(SSL *ssl)
+/* variant of SSL_get_session: caller really gets something */
+	{
+	SSL_SESSION *sess;
+	/* Need to lock this all up rather than just use CRYPTO_add so that
+	 * somebody doesn't free ssl->session between when we check it's
+	 * non-null and when we up the reference count. */
+	CRYPTO_w_lock(CRYPTO_LOCK_SSL_SESSION);
+	sess = ssl->session;
+	if(sess)
+		sess->references++;
+	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_SESSION);
+	return(sess);
+	}
+
+int SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
+	{
+	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION, argl, argp,
+			new_func, dup_func, free_func);
+	}
+
+int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg)
+	{
+	return(CRYPTO_set_ex_data(&s->ex_data,idx,arg));
+	}
+
+void *SSL_SESSION_get_ex_data(const SSL_SESSION *s, int idx)
+	{
+	return(CRYPTO_get_ex_data(&s->ex_data,idx));
+	}
+
+SSL_SESSION *SSL_SESSION_new(void)
+	{
+	SSL_SESSION *ss;
+
+	ss=(SSL_SESSION *)OPENSSL_malloc(sizeof(SSL_SESSION));
+	if (ss == NULL)
+		{
+		SSLerr(SSL_F_SSL_SESSION_NEW,ERR_R_MALLOC_FAILURE);
+		return(0);
+		}
+	memset(ss,0,sizeof(SSL_SESSION));
+
+	ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */
+	ss->references=1;
+	ss->timeout=60*5+4; /* 5 minute timeout by default */
+	ss->time=(unsigned long)time(NULL);
+	ss->prev=NULL;
+	ss->next=NULL;
+	ss->compress_meth=0;
+#ifndef OPENSSL_NO_TLSEXT
+	ss->tlsext_hostname = NULL; 
+#ifndef OPENSSL_NO_EC
+	ss->tlsext_ecpointformatlist_length = 0;
+	ss->tlsext_ecpointformatlist = NULL;
+	ss->tlsext_ellipticcurvelist_length = 0;
+	ss->tlsext_ellipticcurvelist = NULL;
+#endif
+#endif
+	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
+#ifndef OPENSSL_NO_PSK
+	ss->psk_identity_hint=NULL;
+	ss->psk_identity=NULL;
+#endif
+	return(ss);
+	}
+
+const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len)
+	{
+	if(len)
+		*len = s->session_id_length;
+	return s->session_id;
+	}
+
+/* Even with SSLv2, we have 16 bytes (128 bits) of session ID space. SSLv3/TLSv1
+ * has 32 bytes (256 bits). As such, filling the ID with random gunk repeatedly
+ * until we have no conflict is going to complete in one iteration pretty much
+ * "most" of the time (btw: understatement). So, if it takes us 10 iterations
+ * and we still can't avoid a conflict - well that's a reasonable point to call
+ * it quits. Either the RAND code is broken or someone is trying to open roughly
+ * very close to 2^128 (or 2^256) SSL sessions to our server. How you might
+ * store that many sessions is perhaps a more interesting question ... */
+
+#define MAX_SESS_ID_ATTEMPTS 10
+static int def_generate_session_id(const SSL *ssl, unsigned char *id,
+				unsigned int *id_len)
+{
+	unsigned int retry = 0;
+	do
+		if (RAND_pseudo_bytes(id, *id_len) <= 0)
+			return 0;
+	while(SSL_has_matching_session_id(ssl, id, *id_len) &&
+		(++retry < MAX_SESS_ID_ATTEMPTS));
+	if(retry < MAX_SESS_ID_ATTEMPTS)
+		return 1;
+	/* else - woops a session_id match */
+	/* XXX We should also check the external cache --
+	 * but the probability of a collision is negligible, and
+	 * we could not prevent the concurrent creation of sessions
+	 * with identical IDs since we currently don't have means
+	 * to atomically check whether a session ID already exists
+	 * and make a reservation for it if it does not
+	 * (this problem applies to the internal cache as well).
+	 */
+	return 0;
+}
+
+void SSL_set_session_creation_enabled (SSL *s, int creation_enabled)
+	{
+	s->session_creation_enabled = creation_enabled;
+	}
+
+int ssl_get_new_session(SSL *s, int session)
+	{
+	/* This gets used by clients and servers. */
+
+	unsigned int tmp;
+	SSL_SESSION *ss=NULL;
+	GEN_SESSION_CB cb = def_generate_session_id;
+
+	/* caller should check this if they can do better error handling */
+        if (!s->session_creation_enabled) return(0);
+	if ((ss=SSL_SESSION_new()) == NULL) return(0);
+
+	/* If the context has a default timeout, use it */
+	if (s->session_ctx->session_timeout == 0)
+		ss->timeout=SSL_get_default_timeout(s);
+	else
+		ss->timeout=s->session_ctx->session_timeout;
+
+	if (s->session != NULL)
+		{
+		SSL_SESSION_free(s->session);
+		s->session=NULL;
+		}
+
+	if (session)
+		{
+		if (s->version == SSL2_VERSION)
+			{
+			ss->ssl_version=SSL2_VERSION;
+			ss->session_id_length=SSL2_SSL_SESSION_ID_LENGTH;
+			}
+		else if (s->version == SSL3_VERSION)
+			{
+			ss->ssl_version=SSL3_VERSION;
+			ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
+			}
+		else if (s->version == TLS1_VERSION)
+			{
+			ss->ssl_version=TLS1_VERSION;
+			ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
+			}
+		else if (s->version == DTLS1_BAD_VER)
+			{
+			ss->ssl_version=DTLS1_BAD_VER;
+			ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
+			}
+		else if (s->version == DTLS1_VERSION)
+			{
+			ss->ssl_version=DTLS1_VERSION;
+			ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
+			}
+		else
+			{
+			SSLerr(SSL_F_SSL_GET_NEW_SESSION,SSL_R_UNSUPPORTED_SSL_VERSION);
+			SSL_SESSION_free(ss);
+			return(0);
+			}
+#ifndef OPENSSL_NO_TLSEXT
+		/* If RFC4507 ticket use empty session ID */
+		if (s->tlsext_ticket_expected)
+			{
+			ss->session_id_length = 0;
+			goto sess_id_done;
+			}
+#endif
+		/* Choose which callback will set the session ID */
+		CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
+		if(s->generate_session_id)
+			cb = s->generate_session_id;
+		else if(s->session_ctx->generate_session_id)
+			cb = s->session_ctx->generate_session_id;
+		CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
+		/* Choose a session ID */
+		tmp = ss->session_id_length;
+		if(!cb(s, ss->session_id, &tmp))
+			{
+			/* The callback failed */
+			SSLerr(SSL_F_SSL_GET_NEW_SESSION,
+				SSL_R_SSL_SESSION_ID_CALLBACK_FAILED);
+			SSL_SESSION_free(ss);
+			return(0);
+			}
+		/* Don't allow the callback to set the session length to zero.
+		 * nor set it higher than it was. */
+		if(!tmp || (tmp > ss->session_id_length))
+			{
+			/* The callback set an illegal length */
+			SSLerr(SSL_F_SSL_GET_NEW_SESSION,
+				SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH);
+			SSL_SESSION_free(ss);
+			return(0);
+			}
+		/* If the session length was shrunk and we're SSLv2, pad it */
+		if((tmp < ss->session_id_length) && (s->version == SSL2_VERSION))
+			memset(ss->session_id + tmp, 0, ss->session_id_length - tmp);
+		else
+			ss->session_id_length = tmp;
+		/* Finally, check for a conflict */
+		if(SSL_has_matching_session_id(s, ss->session_id,
+						ss->session_id_length))
+			{
+			SSLerr(SSL_F_SSL_GET_NEW_SESSION,
+				SSL_R_SSL_SESSION_ID_CONFLICT);
+			SSL_SESSION_free(ss);
+			return(0);
+			}
+#ifndef OPENSSL_NO_TLSEXT
+		sess_id_done:
+		if (s->tlsext_hostname) {
+			ss->tlsext_hostname = BUF_strdup(s->tlsext_hostname);
+			if (ss->tlsext_hostname == NULL) {
+				SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_INTERNAL_ERROR);
+				SSL_SESSION_free(ss);
+				return 0;
+				}
+			}
+#ifndef OPENSSL_NO_EC
+		if (s->tlsext_ecpointformatlist)
+			{
+			if (ss->tlsext_ecpointformatlist != NULL) OPENSSL_free(ss->tlsext_ecpointformatlist);
+			if ((ss->tlsext_ecpointformatlist = OPENSSL_malloc(s->tlsext_ecpointformatlist_length)) == NULL)
+				{
+				SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_MALLOC_FAILURE);
+				SSL_SESSION_free(ss);
+				return 0;
+				}
+			ss->tlsext_ecpointformatlist_length = s->tlsext_ecpointformatlist_length;
+			memcpy(ss->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist_length);
+			}
+		if (s->tlsext_ellipticcurvelist)
+			{
+			if (ss->tlsext_ellipticcurvelist != NULL) OPENSSL_free(ss->tlsext_ellipticcurvelist);
+			if ((ss->tlsext_ellipticcurvelist = OPENSSL_malloc(s->tlsext_ellipticcurvelist_length)) == NULL)
+				{
+				SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_MALLOC_FAILURE);
+				SSL_SESSION_free(ss);
+				return 0;
+				}
+			ss->tlsext_ellipticcurvelist_length = s->tlsext_ellipticcurvelist_length;
+			memcpy(ss->tlsext_ellipticcurvelist, s->tlsext_ellipticcurvelist, s->tlsext_ellipticcurvelist_length);
+			}
+#endif
+#endif
+		}
+	else
+		{
+		ss->session_id_length=0;
+		}
+
+	if (s->sid_ctx_length > sizeof ss->sid_ctx)
+		{
+		SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_INTERNAL_ERROR);
+		SSL_SESSION_free(ss);
+		return 0;
+		}
+	memcpy(ss->sid_ctx,s->sid_ctx,s->sid_ctx_length);
+	ss->sid_ctx_length=s->sid_ctx_length;
+	s->session=ss;
+	ss->ssl_version=s->version;
+	ss->verify_result = X509_V_OK;
+
+	return(1);
+	}
+
+int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
+			const unsigned char *limit)
+	{
+	/* This is used only by servers. */
+
+	SSL_SESSION *ret=NULL;
+	int fatal = 0;
+#ifndef OPENSSL_NO_TLSEXT
+	int r;
+#endif
+
+	if (len > SSL_MAX_SSL_SESSION_ID_LENGTH)
+		goto err;
+#ifndef OPENSSL_NO_TLSEXT
+	r = tls1_process_ticket(s, session_id, len, limit, &ret);
+	if (r == -1)
+		{
+		fatal = 1;
+		goto err;
+		}
+	else if (r == 0 || (!ret && !len))
+		goto err;
+	else if (!ret && !(s->session_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP))
+#else
+	if (len == 0)
+		goto err;
+	if (!(s->session_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP))
+#endif
+		{
+		SSL_SESSION data;
+		data.ssl_version=s->version;
+		data.session_id_length=len;
+		if (len == 0)
+			return 0;
+		memcpy(data.session_id,session_id,len);
+		CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
+		ret=lh_SSL_SESSION_retrieve(s->session_ctx->sessions,&data);
+		if (ret != NULL)
+		    /* don't allow other threads to steal it: */
+		    CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION);
+		CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
+		}
+
+	if (ret == NULL)
+		{
+		int copy=1;
+	
+		s->session_ctx->stats.sess_miss++;
+		ret=NULL;
+		if (s->session_ctx->get_session_cb != NULL
+		    && (ret=s->session_ctx->get_session_cb(s,session_id,len,&copy))
+		       != NULL)
+			{
+			s->session_ctx->stats.sess_cb_hit++;
+
+			/* Increment reference count now if the session callback
+			 * asks us to do so (note that if the session structures
+			 * returned by the callback are shared between threads,
+			 * it must handle the reference count itself [i.e. copy == 0],
+			 * or things won't be thread-safe). */
+			if (copy)
+				CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION);
+
+			/* Add the externally cached session to the internal
+			 * cache as well if and only if we are supposed to. */
+			if(!(s->session_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_STORE))
+				/* The following should not return 1, otherwise,
+				 * things are very strange */
+				SSL_CTX_add_session(s->session_ctx,ret);
+			}
+		if (ret == NULL)
+			goto err;
+		}
+
+	/* Now ret is non-NULL, and we own one of its reference counts. */
+
+	if (ret->sid_ctx_length != s->sid_ctx_length
+	    || memcmp(ret->sid_ctx,s->sid_ctx,ret->sid_ctx_length))
+		{
+		/* We've found the session named by the client, but we don't
+		 * want to use it in this context. */
+
+#if 0 /* The client cannot always know when a session is not appropriate,
+       * so we shouldn't generate an error message. */
+
+		SSLerr(SSL_F_SSL_GET_PREV_SESSION,SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
+#endif
+		goto err; /* treat like cache miss */
+		}
+	
+	if((s->verify_mode & SSL_VERIFY_PEER) && s->sid_ctx_length == 0)
+		{
+		/* We can't be sure if this session is being used out of
+		 * context, which is especially important for SSL_VERIFY_PEER.
+		 * The application should have used SSL[_CTX]_set_session_id_context.
+		 *
+		 * For this error case, we generate an error instead of treating
+		 * the event like a cache miss (otherwise it would be easy for
+		 * applications to effectively disable the session cache by
+		 * accident without anyone noticing).
+		 */
+		
+		SSLerr(SSL_F_SSL_GET_PREV_SESSION,SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED);
+		fatal = 1;
+		goto err;
+		}
+
+	if (ret->cipher == NULL)
+		{
+		unsigned char buf[5],*p;
+		unsigned long l;
+
+		p=buf;
+		l=ret->cipher_id;
+		l2n(l,p);
+		if ((ret->ssl_version>>8) >= SSL3_VERSION_MAJOR)
+			ret->cipher=ssl_get_cipher_by_char(s,&(buf[2]));
+		else 
+			ret->cipher=ssl_get_cipher_by_char(s,&(buf[1]));
+		if (ret->cipher == NULL)
+			goto err;
+		}
+
+
+#if 0 /* This is way too late. */
+
+	/* If a thread got the session, then 'swaped', and another got
+	 * it and then due to a time-out decided to 'OPENSSL_free' it we could
+	 * be in trouble.  So I'll increment it now, then double decrement
+	 * later - am I speaking rubbish?. */
+	CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION);
+#endif
+
+	if (ret->timeout < (long)(time(NULL) - ret->time)) /* timeout */
+		{
+		s->session_ctx->stats.sess_timeout++;
+		/* remove it from the cache */
+		SSL_CTX_remove_session(s->session_ctx,ret);
+		goto err;
+		}
+
+	s->session_ctx->stats.sess_hit++;
+
+	/* ret->time=time(NULL); */ /* rezero timeout? */
+	/* again, just leave the session 
+	 * if it is the same session, we have just incremented and
+	 * then decremented the reference count :-) */
+	if (s->session != NULL)
+		SSL_SESSION_free(s->session);
+	s->session=ret;
+	s->verify_result = s->session->verify_result;
+	return(1);
+
+ err:
+	if (ret != NULL)
+		SSL_SESSION_free(ret);
+	if (fatal)
+		return -1;
+	else
+		return 0;
+	}
+
+int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c)
+	{
+	int ret=0;
+	SSL_SESSION *s;
+
+	/* add just 1 reference count for the SSL_CTX's session cache
+	 * even though it has two ways of access: each session is in a
+	 * doubly linked list and an lhash */
+	CRYPTO_add(&c->references,1,CRYPTO_LOCK_SSL_SESSION);
+	/* if session c is in already in cache, we take back the increment later */
+
+	CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
+	s=lh_SSL_SESSION_insert(ctx->sessions,c);
+	
+	/* s != NULL iff we already had a session with the given PID.
+	 * In this case, s == c should hold (then we did not really modify
+	 * ctx->sessions), or we're in trouble. */
+	if (s != NULL && s != c)
+		{
+		/* We *are* in trouble ... */
+		SSL_SESSION_list_remove(ctx,s);
+		SSL_SESSION_free(s);
+		/* ... so pretend the other session did not exist in cache
+		 * (we cannot handle two SSL_SESSION structures with identical
+		 * session ID in the same cache, which could happen e.g. when
+		 * two threads concurrently obtain the same session from an external
+		 * cache) */
+		s = NULL;
+		}
+
+ 	/* Put at the head of the queue unless it is already in the cache */
+	if (s == NULL)
+		SSL_SESSION_list_add(ctx,c);
+
+	if (s != NULL)
+		{
+		/* existing cache entry -- decrement previously incremented reference
+		 * count because it already takes into account the cache */
+
+		SSL_SESSION_free(s); /* s == c */
+		ret=0;
+		}
+	else
+		{
+		/* new cache entry -- remove old ones if cache has become too large */
+		
+		ret=1;
+
+		if (SSL_CTX_sess_get_cache_size(ctx) > 0)
+			{
+			while (SSL_CTX_sess_number(ctx) >
+				SSL_CTX_sess_get_cache_size(ctx))
+				{
+				if (!remove_session_lock(ctx,
+					ctx->session_cache_tail, 0))
+					break;
+				else
+					ctx->stats.sess_cache_full++;
+				}
+			}
+		}
+	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
+	return(ret);
+	}
+
+int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c)
+{
+	return remove_session_lock(ctx, c, 1);
+}
+
+static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck)
+	{
+	SSL_SESSION *r;
+	int ret=0;
+
+	if ((c != NULL) && (c->session_id_length != 0))
+		{
+		if(lck) CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
+		if ((r = lh_SSL_SESSION_retrieve(ctx->sessions,c)) == c)
+			{
+			ret=1;
+			r=lh_SSL_SESSION_delete(ctx->sessions,c);
+			SSL_SESSION_list_remove(ctx,c);
+			}
+
+		if(lck) CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
+
+		if (ret)
+			{
+			r->not_resumable=1;
+			if (ctx->remove_session_cb != NULL)
+				ctx->remove_session_cb(ctx,r);
+			SSL_SESSION_free(r);
+			}
+		}
+	else
+		ret=0;
+	return(ret);
+	}
+
+void SSL_SESSION_free(SSL_SESSION *ss)
+	{
+	int i;
+
+	if(ss == NULL)
+	    return;
+
+	i=CRYPTO_add(&ss->references,-1,CRYPTO_LOCK_SSL_SESSION);
+#ifdef REF_PRINT
+	REF_PRINT("SSL_SESSION",ss);
+#endif
+	if (i > 0) return;
+#ifdef REF_CHECK
+	if (i < 0)
+		{
+		fprintf(stderr,"SSL_SESSION_free, bad reference count\n");
+		abort(); /* ok */
+		}
+#endif
+
+	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
+
+	OPENSSL_cleanse(ss->key_arg,sizeof ss->key_arg);
+	OPENSSL_cleanse(ss->master_key,sizeof ss->master_key);
+	OPENSSL_cleanse(ss->session_id,sizeof ss->session_id);
+	if (ss->sess_cert != NULL) ssl_sess_cert_free(ss->sess_cert);
+	if (ss->peer != NULL) X509_free(ss->peer);
+	if (ss->ciphers != NULL) sk_SSL_CIPHER_free(ss->ciphers);
+#ifndef OPENSSL_NO_TLSEXT
+	if (ss->tlsext_hostname != NULL) OPENSSL_free(ss->tlsext_hostname);
+	if (ss->tlsext_tick != NULL) OPENSSL_free(ss->tlsext_tick);
+#ifndef OPENSSL_NO_EC
+	ss->tlsext_ecpointformatlist_length = 0;
+	if (ss->tlsext_ecpointformatlist != NULL) OPENSSL_free(ss->tlsext_ecpointformatlist);
+	ss->tlsext_ellipticcurvelist_length = 0;
+	if (ss->tlsext_ellipticcurvelist != NULL) OPENSSL_free(ss->tlsext_ellipticcurvelist);
+#endif /* OPENSSL_NO_EC */
+#endif
+#ifndef OPENSSL_NO_PSK
+	if (ss->psk_identity_hint != NULL)
+		OPENSSL_free(ss->psk_identity_hint);
+	if (ss->psk_identity != NULL)
+		OPENSSL_free(ss->psk_identity);
+#endif
+	OPENSSL_cleanse(ss,sizeof(*ss));
+	OPENSSL_free(ss);
+	}
+
+int SSL_set_session(SSL *s, SSL_SESSION *session)
+	{
+	int ret=0;
+	const SSL_METHOD *meth;
+
+	if (session != NULL)
+		{
+		meth=s->ctx->method->get_ssl_method(session->ssl_version);
+		if (meth == NULL)
+			meth=s->method->get_ssl_method(session->ssl_version);
+		if (meth == NULL)
+			{
+			SSLerr(SSL_F_SSL_SET_SESSION,SSL_R_UNABLE_TO_FIND_SSL_METHOD);
+			return(0);
+			}
+
+		if (meth != s->method)
+			{
+			if (!SSL_set_ssl_method(s,meth))
+				return(0);
+			if (s->ctx->session_timeout == 0)
+				session->timeout=SSL_get_default_timeout(s);
+			else
+				session->timeout=s->ctx->session_timeout;
+			}
+
+#ifndef OPENSSL_NO_KRB5
+                if (s->kssl_ctx && !s->kssl_ctx->client_princ &&
+                    session->krb5_client_princ_len > 0)
+                {
+                    s->kssl_ctx->client_princ = (char *)OPENSSL_malloc(session->krb5_client_princ_len + 1);
+                    memcpy(s->kssl_ctx->client_princ,session->krb5_client_princ,
+                            session->krb5_client_princ_len);
+                    s->kssl_ctx->client_princ[session->krb5_client_princ_len] = '\0';
+                }
+#endif /* OPENSSL_NO_KRB5 */
+
+		/* CRYPTO_w_lock(CRYPTO_LOCK_SSL);*/
+		CRYPTO_add(&session->references,1,CRYPTO_LOCK_SSL_SESSION);
+		if (s->session != NULL)
+			SSL_SESSION_free(s->session);
+		s->session=session;
+		s->verify_result = s->session->verify_result;
+		/* CRYPTO_w_unlock(CRYPTO_LOCK_SSL);*/
+		ret=1;
+		}
+	else
+		{
+		if (s->session != NULL)
+			{
+			SSL_SESSION_free(s->session);
+			s->session=NULL;
+			}
+
+		meth=s->ctx->method;
+		if (meth != s->method)
+			{
+			if (!SSL_set_ssl_method(s,meth))
+				return(0);
+			}
+		ret=1;
+		}
+	return(ret);
+	}
+
+long SSL_SESSION_set_timeout(SSL_SESSION *s, long t)
+	{
+	if (s == NULL) return(0);
+	s->timeout=t;
+	return(1);
+	}
+
+long SSL_SESSION_get_timeout(const SSL_SESSION *s)
+	{
+	if (s == NULL) return(0);
+	return(s->timeout);
+	}
+
+long SSL_SESSION_get_time(const SSL_SESSION *s)
+	{
+	if (s == NULL) return(0);
+	return(s->time);
+	}
+
+long SSL_SESSION_set_time(SSL_SESSION *s, long t)
+	{
+	if (s == NULL) return(0);
+	s->time=t;
+	return(t);
+	}
+
+long SSL_CTX_set_timeout(SSL_CTX *s, long t)
+	{
+	long l;
+	if (s == NULL) return(0);
+	l=s->session_timeout;
+	s->session_timeout=t;
+	return(l);
+	}
+
+long SSL_CTX_get_timeout(const SSL_CTX *s)
+	{
+	if (s == NULL) return(0);
+	return(s->session_timeout);
+	}
+
+#ifndef OPENSSL_NO_TLSEXT
+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len,
+	STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg)
+	{
+	if (s == NULL) return(0);
+	s->tls_session_secret_cb = tls_session_secret_cb;
+	s->tls_session_secret_cb_arg = arg;
+	return(1);
+	}
+
+int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb,
+				  void *arg)
+	{
+	if (s == NULL) return(0);
+	s->tls_session_ticket_ext_cb = cb;
+	s->tls_session_ticket_ext_cb_arg = arg;
+	return(1);
+	}
+
+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len)
+	{
+	if (s->version >= TLS1_VERSION)
+		{
+		if (s->tlsext_session_ticket)
+			{
+			OPENSSL_free(s->tlsext_session_ticket);
+			s->tlsext_session_ticket = NULL;
+			}
+
+		s->tlsext_session_ticket = OPENSSL_malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len);
+		if (!s->tlsext_session_ticket)
+			{
+			SSLerr(SSL_F_SSL_SET_SESSION_TICKET_EXT, ERR_R_MALLOC_FAILURE);
+			return 0;
+			}
+
+		if (ext_data)
+			{
+			s->tlsext_session_ticket->length = ext_len;
+			s->tlsext_session_ticket->data = s->tlsext_session_ticket + 1;
+			memcpy(s->tlsext_session_ticket->data, ext_data, ext_len);
+			}
+		else
+			{
+			s->tlsext_session_ticket->length = 0;
+			s->tlsext_session_ticket->data = NULL;
+			}
+
+		return 1;
+		}
+
+	return 0;
+	}
+#endif /* OPENSSL_NO_TLSEXT */
+
+typedef struct timeout_param_st
+	{
+	SSL_CTX *ctx;
+	long time;
+	LHASH_OF(SSL_SESSION) *cache;
+	} TIMEOUT_PARAM;
+
+static void timeout_doall_arg(SSL_SESSION *s, TIMEOUT_PARAM *p)
+	{
+	if ((p->time == 0) || (p->time > (s->time+s->timeout))) /* timeout */
+		{
+		/* The reason we don't call SSL_CTX_remove_session() is to
+		 * save on locking overhead */
+		(void)lh_SSL_SESSION_delete(p->cache,s);
+		SSL_SESSION_list_remove(p->ctx,s);
+		s->not_resumable=1;
+		if (p->ctx->remove_session_cb != NULL)
+			p->ctx->remove_session_cb(p->ctx,s);
+		SSL_SESSION_free(s);
+		}
+	}
+
+static IMPLEMENT_LHASH_DOALL_ARG_FN(timeout, SSL_SESSION, TIMEOUT_PARAM)
+
+void SSL_CTX_flush_sessions(SSL_CTX *s, long t)
+	{
+	unsigned long i;
+	TIMEOUT_PARAM tp;
+
+	tp.ctx=s;
+	tp.cache=s->sessions;
+	if (tp.cache == NULL) return;
+	tp.time=t;
+	CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
+	i=CHECKED_LHASH_OF(SSL_SESSION, tp.cache)->down_load;
+	CHECKED_LHASH_OF(SSL_SESSION, tp.cache)->down_load=0;
+	lh_SSL_SESSION_doall_arg(tp.cache, LHASH_DOALL_ARG_FN(timeout),
+				 TIMEOUT_PARAM, &tp);
+	CHECKED_LHASH_OF(SSL_SESSION, tp.cache)->down_load=i;
+	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
+	}
+
+int ssl_clear_bad_session(SSL *s)
+	{
+	if (	(s->session != NULL) &&
+		!(s->shutdown & SSL_SENT_SHUTDOWN) &&
+		!(SSL_in_init(s) || SSL_in_before(s)))
+		{
+		SSL_CTX_remove_session(s->ctx,s->session);
+		return(1);
+		}
+	else
+		return(0);
+	}
+
+/* locked by SSL_CTX in the calling function */
+static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s)
+	{
+	if ((s->next == NULL) || (s->prev == NULL)) return;
+
+	if (s->next == (SSL_SESSION *)&(ctx->session_cache_tail))
+		{ /* last element in list */
+		if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head))
+			{ /* only one element in list */
+			ctx->session_cache_head=NULL;
+			ctx->session_cache_tail=NULL;
+			}
+		else
+			{
+			ctx->session_cache_tail=s->prev;
+			s->prev->next=(SSL_SESSION *)&(ctx->session_cache_tail);
+			}
+		}
+	else
+		{
+		if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head))
+			{ /* first element in list */
+			ctx->session_cache_head=s->next;
+			s->next->prev=(SSL_SESSION *)&(ctx->session_cache_head);
+			}
+		else
+			{ /* middle of list */
+			s->next->prev=s->prev;
+			s->prev->next=s->next;
+			}
+		}
+	s->prev=s->next=NULL;
+	}
+
+static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s)
+	{
+	if ((s->next != NULL) && (s->prev != NULL))
+		SSL_SESSION_list_remove(ctx,s);
+
+	if (ctx->session_cache_head == NULL)
+		{
+		ctx->session_cache_head=s;
+		ctx->session_cache_tail=s;
+		s->prev=(SSL_SESSION *)&(ctx->session_cache_head);
+		s->next=(SSL_SESSION *)&(ctx->session_cache_tail);
+		}
+	else
+		{
+		s->next=ctx->session_cache_head;
+		s->next->prev=s;
+		s->prev=(SSL_SESSION *)&(ctx->session_cache_head);
+		ctx->session_cache_head=s;
+		}
+	}
+
+void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx,
+	int (*cb)(struct ssl_st *ssl,SSL_SESSION *sess))
+	{
+	ctx->new_session_cb=cb;
+	}
+
+int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(SSL *ssl, SSL_SESSION *sess)
+	{
+	return ctx->new_session_cb;
+	}
+
+void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx,
+	void (*cb)(SSL_CTX *ctx,SSL_SESSION *sess))
+	{
+	ctx->remove_session_cb=cb;
+	}
+
+void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(SSL_CTX * ctx,SSL_SESSION *sess)
+	{
+	return ctx->remove_session_cb;
+	}
+
+void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx,
+	SSL_SESSION *(*cb)(struct ssl_st *ssl,
+	         unsigned char *data,int len,int *copy))
+	{
+	ctx->get_session_cb=cb;
+	}
+
+SSL_SESSION * (*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(SSL *ssl,
+	         unsigned char *data,int len,int *copy)
+	{
+	return ctx->get_session_cb;
+	}
+
+void SSL_CTX_set_info_callback(SSL_CTX *ctx, 
+	void (*cb)(const SSL *ssl,int type,int val))
+	{
+	ctx->info_callback=cb;
+	}
+
+void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl,int type,int val)
+	{
+	return ctx->info_callback;
+	}
+
+void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx,
+	int (*cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey))
+	{
+	ctx->client_cert_cb=cb;
+	}
+
+int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL * ssl, X509 ** x509 , EVP_PKEY **pkey)
+	{
+	return ctx->client_cert_cb;
+	}
+
+#ifndef OPENSSL_NO_ENGINE
+int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e)
+	{
+	if (!ENGINE_init(e))
+		{
+		SSLerr(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE, ERR_R_ENGINE_LIB);
+		return 0;
+		}
+	if(!ENGINE_get_ssl_client_cert_function(e))
+		{
+		SSLerr(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE, SSL_R_NO_CLIENT_CERT_METHOD);
+		ENGINE_finish(e);
+		return 0;
+		}
+	ctx->client_cert_engine = e;
+	return 1;
+	}
+#endif
+
+void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx,
+	int (*cb)(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len))
+	{
+	ctx->app_gen_cookie_cb=cb;
+	}
+
+void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx,
+	int (*cb)(SSL *ssl, unsigned char *cookie, unsigned int cookie_len))
+	{
+	ctx->app_verify_cookie_cb=cb;
+	}
+
+IMPLEMENT_PEM_rw(SSL_SESSION, SSL_SESSION, PEM_STRING_SSL_SESSION, SSL_SESSION)
diff --git a/lib/openssl/ssl/ssl_stat.c b/lib/openssl/ssl/ssl_stat.c
new file mode 100644
index 0000000..144b81e
--- /dev/null
+++ b/lib/openssl/ssl/ssl_stat.c
@@ -0,0 +1,567 @@
+/* ssl/ssl_stat.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#include <stdio.h>
+#include "ssl_locl.h"
+
+const char *SSL_state_string_long(const SSL *s)
+	{
+	const char *str;
+
+	switch (s->state)
+		{
+case SSL_ST_BEFORE: str="before SSL initialization"; break;
+case SSL_ST_ACCEPT: str="before accept initialization"; break;
+case SSL_ST_CONNECT: str="before connect initialization"; break;
+case SSL_ST_OK: str="SSL negotiation finished successfully"; break;
+case SSL_ST_RENEGOTIATE:	str="SSL renegotiate ciphers"; break;
+case SSL_ST_BEFORE|SSL_ST_CONNECT: str="before/connect initialization"; break;
+case SSL_ST_OK|SSL_ST_CONNECT: str="ok/connect SSL initialization"; break;
+case SSL_ST_BEFORE|SSL_ST_ACCEPT: str="before/accept initialization"; break;
+case SSL_ST_OK|SSL_ST_ACCEPT: str="ok/accept SSL initialization"; break;
+#ifndef OPENSSL_NO_SSL2
+case SSL2_ST_CLIENT_START_ENCRYPTION: str="SSLv2 client start encryption"; break;
+case SSL2_ST_SERVER_START_ENCRYPTION: str="SSLv2 server start encryption"; break;
+case SSL2_ST_SEND_CLIENT_HELLO_A: str="SSLv2 write client hello A"; break;
+case SSL2_ST_SEND_CLIENT_HELLO_B: str="SSLv2 write client hello B"; break;
+case SSL2_ST_GET_SERVER_HELLO_A: str="SSLv2 read server hello A"; break;
+case SSL2_ST_GET_SERVER_HELLO_B: str="SSLv2 read server hello B"; break;
+case SSL2_ST_SEND_CLIENT_MASTER_KEY_A: str="SSLv2 write client master key A"; break;
+case SSL2_ST_SEND_CLIENT_MASTER_KEY_B: str="SSLv2 write client master key B"; break;
+case SSL2_ST_SEND_CLIENT_FINISHED_A: str="SSLv2 write client finished A"; break;
+case SSL2_ST_SEND_CLIENT_FINISHED_B: str="SSLv2 write client finished B"; break;
+case SSL2_ST_SEND_CLIENT_CERTIFICATE_A: str="SSLv2 write client certificate A"; break;
+case SSL2_ST_SEND_CLIENT_CERTIFICATE_B: str="SSLv2 write client certificate B"; break;
+case SSL2_ST_SEND_CLIENT_CERTIFICATE_C: str="SSLv2 write client certificate C"; break;
+case SSL2_ST_SEND_CLIENT_CERTIFICATE_D: str="SSLv2 write client certificate D"; break;
+case SSL2_ST_GET_SERVER_VERIFY_A: str="SSLv2 read server verify A"; break;
+case SSL2_ST_GET_SERVER_VERIFY_B: str="SSLv2 read server verify B"; break;
+case SSL2_ST_GET_SERVER_FINISHED_A: str="SSLv2 read server finished A"; break;
+case SSL2_ST_GET_SERVER_FINISHED_B: str="SSLv2 read server finished B"; break;
+case SSL2_ST_GET_CLIENT_HELLO_A: str="SSLv2 read client hello A"; break;
+case SSL2_ST_GET_CLIENT_HELLO_B: str="SSLv2 read client hello B"; break;
+case SSL2_ST_GET_CLIENT_HELLO_C: str="SSLv2 read client hello C"; break;
+case SSL2_ST_SEND_SERVER_HELLO_A: str="SSLv2 write server hello A"; break;
+case SSL2_ST_SEND_SERVER_HELLO_B: str="SSLv2 write server hello B"; break;
+case SSL2_ST_GET_CLIENT_MASTER_KEY_A: str="SSLv2 read client master key A"; break;
+case SSL2_ST_GET_CLIENT_MASTER_KEY_B: str="SSLv2 read client master key B"; break;
+case SSL2_ST_SEND_SERVER_VERIFY_A: str="SSLv2 write server verify A"; break;
+case SSL2_ST_SEND_SERVER_VERIFY_B: str="SSLv2 write server verify B"; break;
+case SSL2_ST_SEND_SERVER_VERIFY_C: str="SSLv2 write server verify C"; break;
+case SSL2_ST_GET_CLIENT_FINISHED_A: str="SSLv2 read client finished A"; break;
+case SSL2_ST_GET_CLIENT_FINISHED_B: str="SSLv2 read client finished B"; break;
+case SSL2_ST_SEND_SERVER_FINISHED_A: str="SSLv2 write server finished A"; break;
+case SSL2_ST_SEND_SERVER_FINISHED_B: str="SSLv2 write server finished B"; break;
+case SSL2_ST_SEND_REQUEST_CERTIFICATE_A: str="SSLv2 write request certificate A"; break;
+case SSL2_ST_SEND_REQUEST_CERTIFICATE_B: str="SSLv2 write request certificate B"; break;
+case SSL2_ST_SEND_REQUEST_CERTIFICATE_C: str="SSLv2 write request certificate C"; break;
+case SSL2_ST_SEND_REQUEST_CERTIFICATE_D: str="SSLv2 write request certificate D"; break;
+case SSL2_ST_X509_GET_SERVER_CERTIFICATE: str="SSLv2 X509 read server certificate"; break;
+case SSL2_ST_X509_GET_CLIENT_CERTIFICATE: str="SSLv2 X509 read client certificate"; break;
+#endif
+
+#ifndef OPENSSL_NO_SSL3
+/* SSLv3 additions */
+case SSL3_ST_CW_CLNT_HELLO_A:	str="SSLv3 write client hello A"; break;
+case SSL3_ST_CW_CLNT_HELLO_B:	str="SSLv3 write client hello B"; break;
+case SSL3_ST_CR_SRVR_HELLO_A:	str="SSLv3 read server hello A"; break;
+case SSL3_ST_CR_SRVR_HELLO_B:	str="SSLv3 read server hello B"; break;
+case SSL3_ST_CR_CERT_A:		str="SSLv3 read server certificate A"; break;
+case SSL3_ST_CR_CERT_B:		str="SSLv3 read server certificate B"; break;
+case SSL3_ST_CR_KEY_EXCH_A:	str="SSLv3 read server key exchange A"; break;
+case SSL3_ST_CR_KEY_EXCH_B:	str="SSLv3 read server key exchange B"; break;
+case SSL3_ST_CR_CERT_REQ_A:	str="SSLv3 read server certificate request A"; break;
+case SSL3_ST_CR_CERT_REQ_B:	str="SSLv3 read server certificate request B"; break;
+case SSL3_ST_CR_SESSION_TICKET_A: str="SSLv3 read server session ticket A";break;
+case SSL3_ST_CR_SESSION_TICKET_B: str="SSLv3 read server session ticket B";break;
+case SSL3_ST_CR_SRVR_DONE_A:	str="SSLv3 read server done A"; break;
+case SSL3_ST_CR_SRVR_DONE_B:	str="SSLv3 read server done B"; break;
+case SSL3_ST_CW_CERT_A:		str="SSLv3 write client certificate A"; break;
+case SSL3_ST_CW_CERT_B:		str="SSLv3 write client certificate B"; break;
+case SSL3_ST_CW_CERT_C:		str="SSLv3 write client certificate C"; break;
+case SSL3_ST_CW_CERT_D:		str="SSLv3 write client certificate D"; break;
+case SSL3_ST_CW_KEY_EXCH_A:	str="SSLv3 write client key exchange A"; break;
+case SSL3_ST_CW_KEY_EXCH_B:	str="SSLv3 write client key exchange B"; break;
+case SSL3_ST_CW_CERT_VRFY_A:	str="SSLv3 write certificate verify A"; break;
+case SSL3_ST_CW_CERT_VRFY_B:	str="SSLv3 write certificate verify B"; break;
+
+case SSL3_ST_CW_CHANGE_A:
+case SSL3_ST_SW_CHANGE_A:	str="SSLv3 write change cipher spec A"; break;
+case SSL3_ST_CW_CHANGE_B:	
+case SSL3_ST_SW_CHANGE_B:	str="SSLv3 write change cipher spec B"; break;
+case SSL3_ST_CW_FINISHED_A:	
+case SSL3_ST_SW_FINISHED_A:	str="SSLv3 write finished A"; break;
+case SSL3_ST_CW_FINISHED_B:	
+case SSL3_ST_SW_FINISHED_B:	str="SSLv3 write finished B"; break;
+case SSL3_ST_CR_CHANGE_A:	
+case SSL3_ST_SR_CHANGE_A:	str="SSLv3 read change cipher spec A"; break;
+case SSL3_ST_CR_CHANGE_B:	
+case SSL3_ST_SR_CHANGE_B:	str="SSLv3 read change cipher spec B"; break;
+case SSL3_ST_CR_FINISHED_A:	
+case SSL3_ST_SR_FINISHED_A:	str="SSLv3 read finished A"; break;
+case SSL3_ST_CR_FINISHED_B:	
+case SSL3_ST_SR_FINISHED_B:	str="SSLv3 read finished B"; break;
+
+case SSL3_ST_CW_FLUSH:
+case SSL3_ST_SW_FLUSH:		str="SSLv3 flush data"; break;
+
+case SSL3_ST_SR_CLNT_HELLO_A:	str="SSLv3 read client hello A"; break;
+case SSL3_ST_SR_CLNT_HELLO_B:	str="SSLv3 read client hello B"; break;
+case SSL3_ST_SR_CLNT_HELLO_C:	str="SSLv3 read client hello C"; break;
+case SSL3_ST_SW_HELLO_REQ_A:	str="SSLv3 write hello request A"; break;
+case SSL3_ST_SW_HELLO_REQ_B:	str="SSLv3 write hello request B"; break;
+case SSL3_ST_SW_HELLO_REQ_C:	str="SSLv3 write hello request C"; break;
+case SSL3_ST_SW_SRVR_HELLO_A:	str="SSLv3 write server hello A"; break;
+case SSL3_ST_SW_SRVR_HELLO_B:	str="SSLv3 write server hello B"; break;
+case SSL3_ST_SW_CERT_A:		str="SSLv3 write certificate A"; break;
+case SSL3_ST_SW_CERT_B:		str="SSLv3 write certificate B"; break;
+case SSL3_ST_SW_KEY_EXCH_A:	str="SSLv3 write key exchange A"; break;
+case SSL3_ST_SW_KEY_EXCH_B:	str="SSLv3 write key exchange B"; break;
+case SSL3_ST_SW_CERT_REQ_A:	str="SSLv3 write certificate request A"; break;
+case SSL3_ST_SW_CERT_REQ_B:	str="SSLv3 write certificate request B"; break;
+case SSL3_ST_SW_SESSION_TICKET_A: str="SSLv3 write session ticket A"; break;
+case SSL3_ST_SW_SESSION_TICKET_B: str="SSLv3 write session ticket B"; break;
+case SSL3_ST_SW_SRVR_DONE_A:	str="SSLv3 write server done A"; break;
+case SSL3_ST_SW_SRVR_DONE_B:	str="SSLv3 write server done B"; break;
+case SSL3_ST_SR_CERT_A:		str="SSLv3 read client certificate A"; break;
+case SSL3_ST_SR_CERT_B:		str="SSLv3 read client certificate B"; break;
+case SSL3_ST_SR_KEY_EXCH_A:	str="SSLv3 read client key exchange A"; break;
+case SSL3_ST_SR_KEY_EXCH_B:	str="SSLv3 read client key exchange B"; break;
+case SSL3_ST_SR_CERT_VRFY_A:	str="SSLv3 read certificate verify A"; break;
+case SSL3_ST_SR_CERT_VRFY_B:	str="SSLv3 read certificate verify B"; break;
+#endif
+
+#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
+/* SSLv2/v3 compatibility states */
+/* client */
+case SSL23_ST_CW_CLNT_HELLO_A:	str="SSLv2/v3 write client hello A"; break;
+case SSL23_ST_CW_CLNT_HELLO_B:	str="SSLv2/v3 write client hello B"; break;
+case SSL23_ST_CR_SRVR_HELLO_A:	str="SSLv2/v3 read server hello A"; break;
+case SSL23_ST_CR_SRVR_HELLO_B:	str="SSLv2/v3 read server hello B"; break;
+/* server */
+case SSL23_ST_SR_CLNT_HELLO_A:	str="SSLv2/v3 read client hello A"; break;
+case SSL23_ST_SR_CLNT_HELLO_B:	str="SSLv2/v3 read client hello B"; break;
+#endif
+
+/* DTLS */
+case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A: str="DTLS1 read hello verify request A"; break;
+case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B: str="DTLS1 read hello verify request B"; break;
+case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A: str="DTLS1 write hello verify request A"; break;
+case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B: str="DTLS1 write hello verify request B"; break;
+
+default:	str="unknown state"; break;
+		}
+	return(str);
+	}
+
+const char *SSL_rstate_string_long(const SSL *s)
+	{
+	const char *str;
+
+	switch (s->rstate)
+		{
+	case SSL_ST_READ_HEADER: str="read header"; break;
+	case SSL_ST_READ_BODY: str="read body"; break;
+	case SSL_ST_READ_DONE: str="read done"; break;
+	default: str="unknown"; break;
+		}
+	return(str);
+	}
+
+const char *SSL_state_string(const SSL *s)
+	{
+	const char *str;
+
+	switch (s->state)
+		{
+case SSL_ST_BEFORE:				str="PINIT "; break;
+case SSL_ST_ACCEPT:				str="AINIT "; break;
+case SSL_ST_CONNECT:				str="CINIT "; break;
+case SSL_ST_OK:			 		str="SSLOK "; break;
+#ifndef OPENSSL_NO_SSL2
+case SSL2_ST_CLIENT_START_ENCRYPTION:		str="2CSENC"; break;
+case SSL2_ST_SERVER_START_ENCRYPTION:		str="2SSENC"; break;
+case SSL2_ST_SEND_CLIENT_HELLO_A:		str="2SCH_A"; break;
+case SSL2_ST_SEND_CLIENT_HELLO_B:		str="2SCH_B"; break;
+case SSL2_ST_GET_SERVER_HELLO_A:		str="2GSH_A"; break;
+case SSL2_ST_GET_SERVER_HELLO_B:		str="2GSH_B"; break;
+case SSL2_ST_SEND_CLIENT_MASTER_KEY_A:		str="2SCMKA"; break;
+case SSL2_ST_SEND_CLIENT_MASTER_KEY_B:		str="2SCMKB"; break;
+case SSL2_ST_SEND_CLIENT_FINISHED_A:		str="2SCF_A"; break;
+case SSL2_ST_SEND_CLIENT_FINISHED_B:		str="2SCF_B"; break;
+case SSL2_ST_SEND_CLIENT_CERTIFICATE_A:		str="2SCC_A"; break;
+case SSL2_ST_SEND_CLIENT_CERTIFICATE_B:		str="2SCC_B"; break;
+case SSL2_ST_SEND_CLIENT_CERTIFICATE_C:		str="2SCC_C"; break;
+case SSL2_ST_SEND_CLIENT_CERTIFICATE_D:		str="2SCC_D"; break;
+case SSL2_ST_GET_SERVER_VERIFY_A:		str="2GSV_A"; break;
+case SSL2_ST_GET_SERVER_VERIFY_B:		str="2GSV_B"; break;
+case SSL2_ST_GET_SERVER_FINISHED_A:		str="2GSF_A"; break;
+case SSL2_ST_GET_SERVER_FINISHED_B:		str="2GSF_B"; break;
+case SSL2_ST_GET_CLIENT_HELLO_A:		str="2GCH_A"; break;
+case SSL2_ST_GET_CLIENT_HELLO_B:		str="2GCH_B"; break;
+case SSL2_ST_GET_CLIENT_HELLO_C:		str="2GCH_C"; break;
+case SSL2_ST_SEND_SERVER_HELLO_A:		str="2SSH_A"; break;
+case SSL2_ST_SEND_SERVER_HELLO_B:		str="2SSH_B"; break;
+case SSL2_ST_GET_CLIENT_MASTER_KEY_A:		str="2GCMKA"; break;
+case SSL2_ST_GET_CLIENT_MASTER_KEY_B:		str="2GCMKA"; break;
+case SSL2_ST_SEND_SERVER_VERIFY_A:		str="2SSV_A"; break;
+case SSL2_ST_SEND_SERVER_VERIFY_B:		str="2SSV_B"; break;
+case SSL2_ST_SEND_SERVER_VERIFY_C:		str="2SSV_C"; break;
+case SSL2_ST_GET_CLIENT_FINISHED_A:		str="2GCF_A"; break;
+case SSL2_ST_GET_CLIENT_FINISHED_B:		str="2GCF_B"; break;
+case SSL2_ST_SEND_SERVER_FINISHED_A:		str="2SSF_A"; break;
+case SSL2_ST_SEND_SERVER_FINISHED_B:		str="2SSF_B"; break;
+case SSL2_ST_SEND_REQUEST_CERTIFICATE_A:	str="2SRC_A"; break;
+case SSL2_ST_SEND_REQUEST_CERTIFICATE_B:	str="2SRC_B"; break;
+case SSL2_ST_SEND_REQUEST_CERTIFICATE_C:	str="2SRC_C"; break;
+case SSL2_ST_SEND_REQUEST_CERTIFICATE_D:	str="2SRC_D"; break;
+case SSL2_ST_X509_GET_SERVER_CERTIFICATE:	str="2X9GSC"; break;
+case SSL2_ST_X509_GET_CLIENT_CERTIFICATE:	str="2X9GCC"; break;
+#endif
+
+#ifndef OPENSSL_NO_SSL3
+/* SSLv3 additions */
+case SSL3_ST_SW_FLUSH:
+case SSL3_ST_CW_FLUSH:				str="3FLUSH"; break;
+case SSL3_ST_CW_CLNT_HELLO_A:			str="3WCH_A"; break;
+case SSL3_ST_CW_CLNT_HELLO_B:			str="3WCH_B"; break;
+case SSL3_ST_CR_SRVR_HELLO_A:			str="3RSH_A"; break;
+case SSL3_ST_CR_SRVR_HELLO_B:			str="3RSH_B"; break;
+case SSL3_ST_CR_CERT_A:				str="3RSC_A"; break;
+case SSL3_ST_CR_CERT_B:				str="3RSC_B"; break;
+case SSL3_ST_CR_KEY_EXCH_A:			str="3RSKEA"; break;
+case SSL3_ST_CR_KEY_EXCH_B:			str="3RSKEB"; break;
+case SSL3_ST_CR_CERT_REQ_A:			str="3RCR_A"; break;
+case SSL3_ST_CR_CERT_REQ_B:			str="3RCR_B"; break;
+case SSL3_ST_CR_SRVR_DONE_A:			str="3RSD_A"; break;
+case SSL3_ST_CR_SRVR_DONE_B:			str="3RSD_B"; break;
+case SSL3_ST_CW_CERT_A:				str="3WCC_A"; break;
+case SSL3_ST_CW_CERT_B:				str="3WCC_B"; break;
+case SSL3_ST_CW_CERT_C:				str="3WCC_C"; break;
+case SSL3_ST_CW_CERT_D:				str="3WCC_D"; break;
+case SSL3_ST_CW_KEY_EXCH_A:			str="3WCKEA"; break;
+case SSL3_ST_CW_KEY_EXCH_B:			str="3WCKEB"; break;
+case SSL3_ST_CW_CERT_VRFY_A:			str="3WCV_A"; break;
+case SSL3_ST_CW_CERT_VRFY_B:			str="3WCV_B"; break;
+
+case SSL3_ST_SW_CHANGE_A:
+case SSL3_ST_CW_CHANGE_A:			str="3WCCSA"; break;
+case SSL3_ST_SW_CHANGE_B:
+case SSL3_ST_CW_CHANGE_B:			str="3WCCSB"; break;
+case SSL3_ST_SW_FINISHED_A:
+case SSL3_ST_CW_FINISHED_A:			str="3WFINA"; break;
+case SSL3_ST_SW_FINISHED_B:
+case SSL3_ST_CW_FINISHED_B:			str="3WFINB"; break;
+case SSL3_ST_SR_CHANGE_A:
+case SSL3_ST_CR_CHANGE_A:			str="3RCCSA"; break;
+case SSL3_ST_SR_CHANGE_B:
+case SSL3_ST_CR_CHANGE_B:			str="3RCCSB"; break;
+case SSL3_ST_SR_FINISHED_A:
+case SSL3_ST_CR_FINISHED_A:			str="3RFINA"; break;
+case SSL3_ST_SR_FINISHED_B:
+case SSL3_ST_CR_FINISHED_B:			str="3RFINB"; break;
+
+case SSL3_ST_SW_HELLO_REQ_A:			str="3WHR_A"; break;
+case SSL3_ST_SW_HELLO_REQ_B:			str="3WHR_B"; break;
+case SSL3_ST_SW_HELLO_REQ_C:			str="3WHR_C"; break;
+case SSL3_ST_SR_CLNT_HELLO_A:			str="3RCH_A"; break;
+case SSL3_ST_SR_CLNT_HELLO_B:			str="3RCH_B"; break;
+case SSL3_ST_SR_CLNT_HELLO_C:			str="3RCH_C"; break;
+case SSL3_ST_SW_SRVR_HELLO_A:			str="3WSH_A"; break;
+case SSL3_ST_SW_SRVR_HELLO_B:			str="3WSH_B"; break;
+case SSL3_ST_SW_CERT_A:				str="3WSC_A"; break;
+case SSL3_ST_SW_CERT_B:				str="3WSC_B"; break;
+case SSL3_ST_SW_KEY_EXCH_A:			str="3WSKEA"; break;
+case SSL3_ST_SW_KEY_EXCH_B:			str="3WSKEB"; break;
+case SSL3_ST_SW_CERT_REQ_A:			str="3WCR_A"; break;
+case SSL3_ST_SW_CERT_REQ_B:			str="3WCR_B"; break;
+case SSL3_ST_SW_SRVR_DONE_A:			str="3WSD_A"; break;
+case SSL3_ST_SW_SRVR_DONE_B:			str="3WSD_B"; break;
+case SSL3_ST_SR_CERT_A:				str="3RCC_A"; break;
+case SSL3_ST_SR_CERT_B:				str="3RCC_B"; break;
+case SSL3_ST_SR_KEY_EXCH_A:			str="3RCKEA"; break;
+case SSL3_ST_SR_KEY_EXCH_B:			str="3RCKEB"; break;
+case SSL3_ST_SR_CERT_VRFY_A:			str="3RCV_A"; break;
+case SSL3_ST_SR_CERT_VRFY_B:			str="3RCV_B"; break;
+#endif
+
+#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
+/* SSLv2/v3 compatibility states */
+/* client */
+case SSL23_ST_CW_CLNT_HELLO_A:			str="23WCHA"; break;
+case SSL23_ST_CW_CLNT_HELLO_B:			str="23WCHB"; break;
+case SSL23_ST_CR_SRVR_HELLO_A:			str="23RSHA"; break;
+case SSL23_ST_CR_SRVR_HELLO_B:			str="23RSHA"; break;
+/* server */
+case SSL23_ST_SR_CLNT_HELLO_A:			str="23RCHA"; break;
+case SSL23_ST_SR_CLNT_HELLO_B:			str="23RCHB"; break;
+#endif
+/* DTLS */
+case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A: str="DRCHVA"; break;
+case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B: str="DRCHVB"; break;
+case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A: str="DWCHVA"; break;
+case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B: str="DWCHVB"; break;
+
+default:					str="UNKWN "; break;
+		}
+	return(str);
+	}
+
+const char *SSL_alert_type_string_long(int value)
+	{
+	value>>=8;
+	if (value == SSL3_AL_WARNING)
+		return("warning");
+	else if (value == SSL3_AL_FATAL)
+		return("fatal");
+	else
+		return("unknown");
+	}
+
+const char *SSL_alert_type_string(int value)
+	{
+	value>>=8;
+	if (value == SSL3_AL_WARNING)
+		return("W");
+	else if (value == SSL3_AL_FATAL)
+		return("F");
+	else
+		return("U");
+	}
+
+const char *SSL_alert_desc_string(int value)
+	{
+	const char *str;
+
+	switch (value & 0xff)
+		{
+	case SSL3_AD_CLOSE_NOTIFY:		str="CN"; break;
+	case SSL3_AD_UNEXPECTED_MESSAGE:	str="UM"; break;
+	case SSL3_AD_BAD_RECORD_MAC:		str="BM"; break;
+	case SSL3_AD_DECOMPRESSION_FAILURE:	str="DF"; break;
+	case SSL3_AD_HANDSHAKE_FAILURE:		str="HF"; break;
+	case SSL3_AD_NO_CERTIFICATE:		str="NC"; break;
+	case SSL3_AD_BAD_CERTIFICATE:		str="BC"; break;
+	case SSL3_AD_UNSUPPORTED_CERTIFICATE:	str="UC"; break;
+	case SSL3_AD_CERTIFICATE_REVOKED:	str="CR"; break;
+	case SSL3_AD_CERTIFICATE_EXPIRED:	str="CE"; break;
+	case SSL3_AD_CERTIFICATE_UNKNOWN:	str="CU"; break;
+	case SSL3_AD_ILLEGAL_PARAMETER:		str="IP"; break;
+	case TLS1_AD_DECRYPTION_FAILED:		str="DC"; break;
+	case TLS1_AD_RECORD_OVERFLOW:		str="RO"; break;
+	case TLS1_AD_UNKNOWN_CA:		str="CA"; break;
+	case TLS1_AD_ACCESS_DENIED:		str="AD"; break;
+	case TLS1_AD_DECODE_ERROR:		str="DE"; break;
+	case TLS1_AD_DECRYPT_ERROR:		str="CY"; break;
+	case TLS1_AD_EXPORT_RESTRICTION:	str="ER"; break;
+	case TLS1_AD_PROTOCOL_VERSION:		str="PV"; break;
+	case TLS1_AD_INSUFFICIENT_SECURITY:	str="IS"; break;
+	case TLS1_AD_INTERNAL_ERROR:		str="IE"; break;
+	case TLS1_AD_USER_CANCELLED:		str="US"; break;
+	case TLS1_AD_NO_RENEGOTIATION:		str="NR"; break;
+	case TLS1_AD_UNSUPPORTED_EXTENSION:	str="UE"; break;
+	case TLS1_AD_CERTIFICATE_UNOBTAINABLE:	str="CO"; break;
+	case TLS1_AD_UNRECOGNIZED_NAME:		str="UN"; break;
+	case TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE: str="BR"; break;
+	case TLS1_AD_BAD_CERTIFICATE_HASH_VALUE: str="BH"; break;
+	case TLS1_AD_UNKNOWN_PSK_IDENTITY:	str="UP"; break;
+	default:				str="UK"; break;
+		}
+	return(str);
+	}
+
+const char *SSL_alert_desc_string_long(int value)
+	{
+	const char *str;
+
+	switch (value & 0xff)
+		{
+	case SSL3_AD_CLOSE_NOTIFY:
+		str="close notify";
+		break;
+	case SSL3_AD_UNEXPECTED_MESSAGE:
+		str="unexpected_message";
+		break;
+	case SSL3_AD_BAD_RECORD_MAC:
+		str="bad record mac";
+		break;
+	case SSL3_AD_DECOMPRESSION_FAILURE:
+		str="decompression failure";
+		break;
+	case SSL3_AD_HANDSHAKE_FAILURE:
+		str="handshake failure";
+		break;
+	case SSL3_AD_NO_CERTIFICATE:
+		str="no certificate";
+		break;
+	case SSL3_AD_BAD_CERTIFICATE:
+		str="bad certificate";
+		break;
+	case SSL3_AD_UNSUPPORTED_CERTIFICATE:
+		str="unsupported certificate";
+		break;
+	case SSL3_AD_CERTIFICATE_REVOKED:
+		str="certificate revoked";
+		break;
+	case SSL3_AD_CERTIFICATE_EXPIRED:
+		str="certificate expired";
+		break;
+	case SSL3_AD_CERTIFICATE_UNKNOWN:
+		str="certificate unknown";
+		break;
+	case SSL3_AD_ILLEGAL_PARAMETER:
+		str="illegal parameter";
+		break;
+	case TLS1_AD_DECRYPTION_FAILED:
+		str="decryption failed";
+		break;
+	case TLS1_AD_RECORD_OVERFLOW:
+		str="record overflow";
+		break;
+	case TLS1_AD_UNKNOWN_CA:
+		str="unknown CA";
+		break;
+	case TLS1_AD_ACCESS_DENIED:
+		str="access denied";
+		break;
+	case TLS1_AD_DECODE_ERROR:
+		str="decode error";
+		break;
+	case TLS1_AD_DECRYPT_ERROR:
+		str="decrypt error";
+		break;
+	case TLS1_AD_EXPORT_RESTRICTION:
+		str="export restriction";
+		break;
+	case TLS1_AD_PROTOCOL_VERSION:
+		str="protocol version";
+		break;
+	case TLS1_AD_INSUFFICIENT_SECURITY:
+		str="insufficient security";
+		break;
+	case TLS1_AD_INTERNAL_ERROR:
+		str="internal error";
+		break;
+	case TLS1_AD_USER_CANCELLED:
+		str="user canceled";
+		break;
+	case TLS1_AD_NO_RENEGOTIATION:
+		str="no renegotiation";
+		break;
+	case TLS1_AD_UNSUPPORTED_EXTENSION:
+		str="unsupported extension";
+		break;
+	case TLS1_AD_CERTIFICATE_UNOBTAINABLE:
+		str="certificate unobtainable";
+		break;
+	case TLS1_AD_UNRECOGNIZED_NAME:
+		str="unrecognized name";
+		break;
+	case TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE:
+		str="bad certificate status response";
+		break;
+	case TLS1_AD_BAD_CERTIFICATE_HASH_VALUE:
+		str="bad certificate hash value";
+		break;
+	case TLS1_AD_UNKNOWN_PSK_IDENTITY:
+		str="unknown PSK identity";
+		break;
+	default: str="unknown"; break;
+		}
+	return(str);
+	}
+
+const char *SSL_rstate_string(const SSL *s)
+	{
+	const char *str;
+
+	switch (s->rstate)
+		{
+	case SSL_ST_READ_HEADER:str="RH"; break;
+	case SSL_ST_READ_BODY:	str="RB"; break;
+	case SSL_ST_READ_DONE:	str="RD"; break;
+	default: str="unknown"; break;
+		}
+	return(str);
+	}
diff --git a/lib/openssl/ssl/ssl_task.c b/lib/openssl/ssl/ssl_task.c
new file mode 100644
index 0000000..b5ce44b
--- /dev/null
+++ b/lib/openssl/ssl/ssl_task.c
@@ -0,0 +1,369 @@
+/* ssl/ssl_task.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/* VMS */
+/*
+ * DECnet object for servicing SSL.  We accept the inbound and speak a
+ * simple protocol for multiplexing the 2 data streams (application and
+ * ssl data) over this logical link.
+ *
+ * Logical names:
+ *    SSL_CIPHER	Defines a list of cipher specifications the server
+ *			will support in order of preference.
+ *    SSL_SERVER_CERTIFICATE
+ *			Points to PEM (privacy enhanced mail) file that
+ *			contains the server certificate and private password.
+ *    SYS$NET		Logical created by netserver.exe as hook for completing
+ *			DECnet logical link.
+ *
+ * Each NSP message sent over the DECnet link has the following structure:
+ *    struct rpc_msg { 
+ *      char channel;
+ *      char function;
+ *      short length;
+ *      char data[MAX_DATA];
+ *    } msg;
+ *
+ * The channel field designates the virtual data stream this message applies
+ * to and is one of:
+ *   A - Application data (payload).
+ *   R - Remote client connection that initiated the SSL connection.  Encrypted
+ *       data is sent over this connection.
+ *   G - General data, reserved for future use.
+ *
+ * The data streams are half-duplex read/write and have following functions:
+ *   G - Get, requests that up to msg.length bytes of data be returned.  The
+ *       data is returned in the next 'C' function response that matches the
+ *       requesting channel.
+ *   P - Put, requests that the first msg.length bytes of msg.data be appended
+ *       to the designated stream.
+ *   C - Confirms a get or put.  Every get and put will get a confirm response,
+ *       you cannot initiate another function on a channel until the previous
+ *       operation has been confirmed.
+ *
+ *  The 2 channels may interleave their operations, for example:
+ *        Server msg           Client msg
+ *         A, Get, 4092          ---->
+ *                               <----  R, get, 4092
+ *         R, Confirm, {hello}   ---->
+ *                               <----  R, put, {srv hello}
+ *         R, Confirm, 0         ---->
+ *                               .		(SSL handshake completed)
+ *                               .              (read first app data).
+ *                               <----  A, confirm, {http data}
+ *         A, Put, {http data}   ---->
+ *                               <----  A, confirm, 0
+ *
+ *  The length field is not permitted to be larger that 4092 bytes.
+ *
+ * Author: Dave Jones
+ * Date:   22-JUL-1996
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <iodef.h>		/* VMS IO$_ definitions */
+#include <descrip.h>		/* VMS string descriptors */
+extern int SYS$QIOW(), SYS$ASSIGN();
+int LIB$INIT_TIMER(), LIB$SHOW_TIMER();
+
+#include <string.h>		/* from ssltest.c */
+#include <errno.h>
+
+#include "e_os.h"
+
+#include <openssl/buffer.h>
+#include <openssl/x509.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+int MS_CALLBACK verify_callback(int ok, X509 *xs, X509 *xi, int depth,
+	int error);
+BIO *bio_err=NULL;
+BIO *bio_stdout=NULL;
+BIO_METHOD *BIO_s_rtcp();
+
+static char *cipher=NULL;
+int verbose=1;
+#ifdef FIONBIO
+static int s_nbio=0;
+#endif
+#define TEST_SERVER_CERT "SSL_SERVER_CERTIFICATE"
+/*************************************************************************/
+struct rpc_msg {		/* Should have member alignment inhibited */
+   char channel;		/* 'A'-app data. 'R'-remote client 'G'-global */
+   char function;		/* 'G'-get, 'P'-put, 'C'-confirm, 'X'-close */
+   unsigned short int length;	/* Amount of data returned or max to return */
+   char data[4092];		/* variable data */
+};
+#define RPC_HDR_SIZE (sizeof(struct rpc_msg) - 4092)
+
+static $DESCRIPTOR(sysnet, "SYS$NET");
+typedef unsigned short io_channel;
+
+struct io_status {
+    unsigned short status;
+    unsigned short count;
+    unsigned long stsval;
+};
+int doit(io_channel chan, SSL_CTX *s_ctx );
+/*****************************************************************************/
+/* Decnet I/O routines.
+ */
+static int get ( io_channel chan, char *buffer, int maxlen, int *length )
+{
+    int status;
+    struct io_status iosb;
+    status = SYS$QIOW ( 0, chan, IO$_READVBLK, &iosb, 0, 0,
+	buffer, maxlen, 0, 0, 0, 0 );
+    if ( (status&1) == 1 ) status = iosb.status;
+    if ( (status&1) == 1 ) *length = iosb.count;
+    return status;
+}
+
+static int put ( io_channel chan, char *buffer, int length )
+{
+    int status;
+    struct io_status iosb;
+    status = SYS$QIOW ( 0, chan, IO$_WRITEVBLK, &iosb, 0, 0,
+	buffer, length, 0, 0, 0, 0 );
+    if ( (status&1) == 1 ) status = iosb.status;
+    return status;
+}
+/***************************************************************************/
+/* Handle operations on the 'G' channel.
+ */
+static int general_request ( io_channel chan, struct rpc_msg *msg, int length )
+{
+    return 48;
+}
+/***************************************************************************/
+int main ( int argc, char **argv )
+{
+    int status, length;
+    io_channel chan;
+    struct rpc_msg msg;
+
+	char *CApath=NULL,*CAfile=NULL;
+	int badop=0;
+	int ret=1;
+	int client_auth=0;
+	int server_auth=0;
+	SSL_CTX *s_ctx=NULL;
+    /*
+     * Confirm logical link with initiating client.
+     */
+    LIB$INIT_TIMER();
+    status = SYS$ASSIGN ( &sysnet, &chan, 0, 0, 0 );
+    printf("status of assign to SYS$NET: %d\n", status );
+    /*
+     * Initialize standard out and error files.
+     */
+	if (bio_err == NULL)
+		if ((bio_err=BIO_new(BIO_s_file())) != NULL)
+			BIO_set_fp(bio_err,stderr,BIO_NOCLOSE);
+	if (bio_stdout == NULL)
+		if ((bio_stdout=BIO_new(BIO_s_file())) != NULL)
+			BIO_set_fp(bio_stdout,stdout,BIO_NOCLOSE);
+    /*
+     * get the preferred cipher list and other initialization
+     */
+	if (cipher == NULL) cipher=getenv("SSL_CIPHER");
+	printf("cipher list: %s\n", cipher ? cipher : "{undefined}" );
+
+	SSL_load_error_strings();
+	OpenSSL_add_all_algorithms();
+
+/* DRM, this was the original, but there is no such thing as SSLv2()
+	s_ctx=SSL_CTX_new(SSLv2());
+*/
+	s_ctx=SSL_CTX_new(SSLv2_server_method());
+
+	if (s_ctx == NULL) goto end;
+
+	SSL_CTX_use_certificate_file(s_ctx,TEST_SERVER_CERT,SSL_FILETYPE_PEM);
+	SSL_CTX_use_RSAPrivateKey_file(s_ctx,TEST_SERVER_CERT,SSL_FILETYPE_PEM);
+	printf("Loaded server certificate: '%s'\n", TEST_SERVER_CERT );
+
+    /*
+     * Take commands from client until bad status.
+     */
+    LIB$SHOW_TIMER();
+    status = doit ( chan, s_ctx );
+    LIB$SHOW_TIMER();
+    /*
+     * do final cleanup and exit.
+     */
+end:
+	if (s_ctx != NULL) SSL_CTX_free(s_ctx);
+    LIB$SHOW_TIMER();
+    return 1;
+}
+
+int doit(io_channel chan, SSL_CTX *s_ctx )
+{
+    int status, length, link_state;
+     struct rpc_msg msg;
+
+	SSL *s_ssl=NULL;
+	BIO *c_to_s=NULL;
+	BIO *s_to_c=NULL;
+	BIO *c_bio=NULL;
+	BIO *s_bio=NULL;
+	int i;
+	int done=0;
+
+	s_ssl=SSL_new(s_ctx);
+	if (s_ssl == NULL) goto err;
+
+	c_to_s=BIO_new(BIO_s_rtcp());
+	s_to_c=BIO_new(BIO_s_rtcp());
+	if ((s_to_c == NULL) || (c_to_s == NULL)) goto err;
+/* original, DRM 24-SEP-1997
+	BIO_set_fd ( c_to_s, "", chan );
+	BIO_set_fd ( s_to_c, "", chan );
+*/
+	BIO_set_fd ( c_to_s, 0, chan );
+	BIO_set_fd ( s_to_c, 0, chan );
+
+	c_bio=BIO_new(BIO_f_ssl());
+	s_bio=BIO_new(BIO_f_ssl());
+	if ((c_bio == NULL) || (s_bio == NULL)) goto err;
+
+	SSL_set_accept_state(s_ssl);
+	SSL_set_bio(s_ssl,c_to_s,s_to_c);
+	BIO_set_ssl(s_bio,s_ssl,BIO_CLOSE);
+
+	/* We can always do writes */
+	printf("Begin doit main loop\n");
+	/*
+	 * Link states: 0-idle, 1-read pending, 2-write pending, 3-closed.
+	 */
+	for (link_state = 0; link_state < 3; ) {
+	    /*
+	     * Wait for remote end to request data action on A channel.
+	     */
+	    while ( link_state == 0 ) {
+		status = get ( chan, (char *) &msg, sizeof(msg), &length );
+		if ( (status&1) == 0 ) {
+		    printf("Error in main loop get: %d\n", status );
+		    link_state = 3;
+		    break;
+		}
+	   	if ( length < RPC_HDR_SIZE ) {
+		    printf("Error in main loop get size: %d\n", length );
+		    break;
+		    link_state = 3;
+		}
+	   	if ( msg.channel != 'A' ) {
+		    printf("Error in main loop, unexpected channel: %c\n", 
+			msg.channel );
+		    break;
+		    link_state = 3;
+		}
+		if ( msg.function == 'G' ) {
+		    link_state = 1;
+		} else if ( msg.function == 'P' ) {
+		    link_state = 2;	/* write pending */
+		} else if ( msg.function == 'X' ) {
+		    link_state = 3;
+		} else {
+		    link_state = 3;
+		}
+	    }
+	    if ( link_state == 1 ) {
+		i = BIO_read ( s_bio, msg.data, msg.length );
+		if ( i < 0 ) link_state = 3;
+		else {
+		    msg.channel = 'A';
+		    msg.function = 'C';		/* confirm */
+		    msg.length = i;
+		    status = put ( chan, (char *) &msg, i+RPC_HDR_SIZE );
+		    if ( (status&1) == 0 ) break;
+		    link_state = 0;
+		}
+	    } else if ( link_state == 2 ) {
+		i = BIO_write ( s_bio, msg.data, msg.length );
+		if ( i < 0 ) link_state = 3;
+		else {
+		    msg.channel = 'A';
+		    msg.function = 'C';		/* confirm */
+		    msg.length = 0;
+		    status = put ( chan, (char *) &msg, RPC_HDR_SIZE );
+		    if ( (status&1) == 0 ) break;
+		    link_state = 0;
+		}
+	    }
+	}
+	fprintf(stdout,"DONE\n");
+err:
+	/* We have to set the BIO's to NULL otherwise they will be
+	 * free()ed twice.  Once when th s_ssl is SSL_free()ed and
+	 * again when c_ssl is SSL_free()ed.
+	 * This is a hack required because s_ssl and c_ssl are sharing the same
+	 * BIO structure and SSL_set_bio() and SSL_free() automatically
+	 * BIO_free non NULL entries.
+	 * You should not normally do this or be required to do this */
+	s_ssl->rbio=NULL;
+	s_ssl->wbio=NULL;
+
+	if (c_to_s != NULL) BIO_free(c_to_s);
+	if (s_to_c != NULL) BIO_free(s_to_c);
+	if (c_bio != NULL) BIO_free(c_bio);
+	if (s_bio != NULL) BIO_free(s_bio);
+	return(0);
+}
diff --git a/lib/openssl/ssl/ssl_txt.c b/lib/openssl/ssl/ssl_txt.c
new file mode 100644
index 0000000..3122440
--- /dev/null
+++ b/lib/openssl/ssl/ssl_txt.c
@@ -0,0 +1,240 @@
+/* ssl/ssl_txt.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#include <stdio.h>
+#include <openssl/buffer.h>
+#include "ssl_locl.h"
+
+#ifndef OPENSSL_NO_FP_API
+int SSL_SESSION_print_fp(FILE *fp, const SSL_SESSION *x)
+	{
+	BIO *b;
+	int ret;
+
+	if ((b=BIO_new(BIO_s_file_internal())) == NULL)
+		{
+		SSLerr(SSL_F_SSL_SESSION_PRINT_FP,ERR_R_BUF_LIB);
+		return(0);
+		}
+	BIO_set_fp(b,fp,BIO_NOCLOSE);
+	ret=SSL_SESSION_print(b,x);
+	BIO_free(b);
+	return(ret);
+	}
+#endif
+
+int SSL_SESSION_print(BIO *bp, const SSL_SESSION *x)
+	{
+	unsigned int i;
+	const char *s;
+
+	if (x == NULL) goto err;
+	if (BIO_puts(bp,"SSL-Session:\n") <= 0) goto err;
+	if (x->ssl_version == SSL2_VERSION)
+		s="SSLv2";
+	else if (x->ssl_version == SSL3_VERSION)
+		s="SSLv3";
+	else if (x->ssl_version == TLS1_VERSION)
+		s="TLSv1";
+	else if (x->ssl_version == DTLS1_VERSION)
+		s="DTLSv1";
+	else if (x->ssl_version == DTLS1_BAD_VER)
+		s="DTLSv1-bad";
+	else
+		s="unknown";
+	if (BIO_printf(bp,"    Protocol  : %s\n",s) <= 0) goto err;
+
+	if (x->cipher == NULL)
+		{
+		if (((x->cipher_id) & 0xff000000) == 0x02000000)
+			{
+			if (BIO_printf(bp,"    Cipher    : %06lX\n",x->cipher_id&0xffffff) <= 0)
+				goto err;
+			}
+		else
+			{
+			if (BIO_printf(bp,"    Cipher    : %04lX\n",x->cipher_id&0xffff) <= 0)
+				goto err;
+			}
+		}
+	else
+		{
+		if (BIO_printf(bp,"    Cipher    : %s\n",((x->cipher == NULL)?"unknown":x->cipher->name)) <= 0)
+			goto err;
+		}
+	if (BIO_puts(bp,"    Session-ID: ") <= 0) goto err;
+	for (i=0; i<x->session_id_length; i++)
+		{
+		if (BIO_printf(bp,"%02X",x->session_id[i]) <= 0) goto err;
+		}
+	if (BIO_puts(bp,"\n    Session-ID-ctx: ") <= 0) goto err;
+	for (i=0; i<x->sid_ctx_length; i++)
+		{
+		if (BIO_printf(bp,"%02X",x->sid_ctx[i]) <= 0)
+			goto err;
+		}
+	if (BIO_puts(bp,"\n    Master-Key: ") <= 0) goto err;
+	for (i=0; i<(unsigned int)x->master_key_length; i++)
+		{
+		if (BIO_printf(bp,"%02X",x->master_key[i]) <= 0) goto err;
+		}
+	if (BIO_puts(bp,"\n    Key-Arg   : ") <= 0) goto err;
+	if (x->key_arg_length == 0)
+		{
+		if (BIO_puts(bp,"None") <= 0) goto err;
+		}
+	else
+		for (i=0; i<x->key_arg_length; i++)
+			{
+			if (BIO_printf(bp,"%02X",x->key_arg[i]) <= 0) goto err;
+			}
+#ifndef OPENSSL_NO_KRB5
+       if (BIO_puts(bp,"\n    Krb5 Principal: ") <= 0) goto err;
+            if (x->krb5_client_princ_len == 0)
+            {
+		if (BIO_puts(bp,"None") <= 0) goto err;
+		}
+	else
+		for (i=0; i<x->krb5_client_princ_len; i++)
+			{
+			if (BIO_printf(bp,"%02X",x->krb5_client_princ[i]) <= 0) goto err;
+			}
+#endif /* OPENSSL_NO_KRB5 */
+#ifndef OPENSSL_NO_PSK
+	if (BIO_puts(bp,"\n    PSK identity: ") <= 0) goto err;
+	if (BIO_printf(bp, "%s", x->psk_identity ? x->psk_identity : "None") <= 0) goto err;
+	if (BIO_puts(bp,"\n    PSK identity hint: ") <= 0) goto err;
+	if (BIO_printf(bp, "%s", x->psk_identity_hint ? x->psk_identity_hint : "None") <= 0) goto err;
+#endif
+#ifndef OPENSSL_NO_TLSEXT
+	if (x->tlsext_tick_lifetime_hint)
+		{
+		if (BIO_printf(bp,
+			"\n    TLS session ticket lifetime hint: %ld (seconds)",
+			x->tlsext_tick_lifetime_hint) <=0)
+			goto err;
+		}
+	if (x->tlsext_tick)
+		{
+		if (BIO_puts(bp, "\n    TLS session ticket:\n") <= 0) goto err;
+		if (BIO_dump_indent(bp, (char *)x->tlsext_tick, x->tlsext_ticklen, 4) <= 0)
+			goto err;
+		}
+#endif
+
+#ifndef OPENSSL_NO_COMP
+	if (x->compress_meth != 0)
+		{
+		SSL_COMP *comp = NULL;
+
+		ssl_cipher_get_evp(x,NULL,NULL,NULL,NULL,&comp);
+		if (comp == NULL)
+			{
+			if (BIO_printf(bp,"\n    Compression: %d",x->compress_meth) <= 0) goto err;
+			}
+		else
+			{
+			if (BIO_printf(bp,"\n    Compression: %d (%s)", comp->id,comp->method->name) <= 0) goto err;
+			}
+		}	
+#endif
+	if (x->time != 0L)
+		{
+		if (BIO_printf(bp, "\n    Start Time: %ld",x->time) <= 0) goto err;
+		}
+	if (x->timeout != 0L)
+		{
+		if (BIO_printf(bp, "\n    Timeout   : %ld (sec)",x->timeout) <= 0) goto err;
+		}
+	if (BIO_puts(bp,"\n") <= 0) goto err;
+
+	if (BIO_puts(bp, "    Verify return code: ") <= 0) goto err;
+	if (BIO_printf(bp, "%ld (%s)\n", x->verify_result,
+		X509_verify_cert_error_string(x->verify_result)) <= 0) goto err;
+		
+	return(1);
+err:
+	return(0);
+	}
+
diff --git a/lib/openssl/ssl/ssltest.c b/lib/openssl/ssl/ssltest.c
new file mode 100644
index 0000000..e21ebda
--- /dev/null
+++ b/lib/openssl/ssl/ssltest.c
@@ -0,0 +1,2506 @@
+/* ssl/ssltest.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECC cipher suite support in OpenSSL originally developed by 
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#define _BSD_SOURCE 1		/* Or gethostname won't be declared properly
+				   on Linux and GNU platforms. */
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#define USE_SOCKETS
+#include "e_os.h"
+
+#ifdef OPENSSL_SYS_VMS
+#define _XOPEN_SOURCE 500	/* Or isascii won't be declared properly on
+				   VMS (at least with DECompHP C).  */
+#endif
+
+#include <ctype.h>
+
+#include <openssl/bio.h>
+#include <openssl/crypto.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/ssl.h>
+#ifndef OPENSSL_NO_ENGINE
+#include <openssl/engine.h>
+#endif
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#ifndef OPENSSL_NO_RSA
+#include <openssl/rsa.h>
+#endif
+#ifndef OPENSSL_NO_DSA
+#include <openssl/dsa.h>
+#endif
+#ifndef OPENSSL_NO_DH
+#include <openssl/dh.h>
+#endif
+#include <openssl/bn.h>
+
+#define _XOPEN_SOURCE_EXTENDED	1 /* Or gethostname won't be declared properly
+				     on Compaq platforms (at least with DEC C).
+				     Do not try to put it earlier, or IPv6 includes
+				     get screwed...
+				  */
+
+#ifdef OPENSSL_SYS_WINDOWS
+#include <winsock.h>
+#else
+#include OPENSSL_UNISTD
+#endif
+
+#ifdef OPENSSL_SYS_VMS
+#  define TEST_SERVER_CERT "SYS$DISK:[-.APPS]SERVER.PEM"
+#  define TEST_CLIENT_CERT "SYS$DISK:[-.APPS]CLIENT.PEM"
+#elif defined(OPENSSL_SYS_WINCE)
+#  define TEST_SERVER_CERT "\\OpenSSL\\server.pem"
+#  define TEST_CLIENT_CERT "\\OpenSSL\\client.pem"
+#elif defined(OPENSSL_SYS_NETWARE)
+#  define TEST_SERVER_CERT "\\openssl\\apps\\server.pem"
+#  define TEST_CLIENT_CERT "\\openssl\\apps\\client.pem"
+#else
+#  define TEST_SERVER_CERT "../apps/server.pem"
+#  define TEST_CLIENT_CERT "../apps/client.pem"
+#endif
+
+/* There is really no standard for this, so let's assign some tentative
+   numbers.  In any case, these numbers are only for this test */
+#define COMP_RLE	255
+#define COMP_ZLIB	1
+
+static int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx);
+#ifndef OPENSSL_NO_RSA
+static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export,int keylength);
+static void free_tmp_rsa(void);
+#endif
+static int MS_CALLBACK app_verify_callback(X509_STORE_CTX *ctx, void *arg);
+#define APP_CALLBACK_STRING "Test Callback Argument"
+struct app_verify_arg
+	{
+	char *string;
+	int app_verify;
+	int allow_proxy_certs;
+	char *proxy_auth;
+	char *proxy_cond;
+	};
+
+#ifndef OPENSSL_NO_DH
+static DH *get_dh512(void);
+static DH *get_dh1024(void);
+static DH *get_dh1024dsa(void);
+#endif
+
+
+static char *psk_key=NULL; /* by default PSK is not used */
+#ifndef OPENSSL_NO_PSK
+static unsigned int psk_client_callback(SSL *ssl, const char *hint, char *identity,
+	unsigned int max_identity_len, unsigned char *psk,
+	unsigned int max_psk_len);
+static unsigned int psk_server_callback(SSL *ssl, const char *identity, unsigned char *psk,
+	unsigned int max_psk_len);
+#endif
+
+static BIO *bio_err=NULL;
+static BIO *bio_stdout=NULL;
+
+static char *cipher=NULL;
+static int verbose=0;
+static int debug=0;
+#if 0
+/* Not used yet. */
+#ifdef FIONBIO
+static int s_nbio=0;
+#endif
+#endif
+
+static const char rnd_seed[] = "string to make the random number generator think it has entropy";
+
+int doit_biopair(SSL *s_ssl,SSL *c_ssl,long bytes,clock_t *s_time,clock_t *c_time);
+int doit(SSL *s_ssl,SSL *c_ssl,long bytes);
+static int do_test_cipherlist(void);
+static void sv_usage(void)
+	{
+	fprintf(stderr,"usage: ssltest [args ...]\n");
+	fprintf(stderr,"\n");
+	fprintf(stderr," -server_auth  - check server certificate\n");
+	fprintf(stderr," -client_auth  - do client authentication\n");
+	fprintf(stderr," -proxy        - allow proxy certificates\n");
+	fprintf(stderr," -proxy_auth <val> - set proxy policy rights\n");
+	fprintf(stderr," -proxy_cond <val> - experssion to test proxy policy rights\n");
+	fprintf(stderr," -v            - more output\n");
+	fprintf(stderr," -d            - debug output\n");
+	fprintf(stderr," -reuse        - use session-id reuse\n");
+	fprintf(stderr," -num <val>    - number of connections to perform\n");
+	fprintf(stderr," -bytes <val>  - number of bytes to swap between client/server\n");
+#ifndef OPENSSL_NO_DH
+	fprintf(stderr," -dhe1024      - use 1024 bit key (safe prime) for DHE\n");
+	fprintf(stderr," -dhe1024dsa   - use 1024 bit key (with 160-bit subprime) for DHE\n");
+	fprintf(stderr," -no_dhe       - disable DHE\n");
+#endif
+#ifndef OPENSSL_NO_ECDH
+	fprintf(stderr," -no_ecdhe     - disable ECDHE\n");
+#endif
+#ifndef OPENSSL_NO_PSK
+	fprintf(stderr," -psk arg      - PSK in hex (without 0x)\n");
+#endif
+#ifndef OPENSSL_NO_SSL2
+	fprintf(stderr," -ssl2         - use SSLv2\n");
+#endif
+#ifndef OPENSSL_NO_SSL3
+	fprintf(stderr," -ssl3         - use SSLv3\n");
+#endif
+#ifndef OPENSSL_NO_TLS1
+	fprintf(stderr," -tls1         - use TLSv1\n");
+#endif
+	fprintf(stderr," -CApath arg   - PEM format directory of CA's\n");
+	fprintf(stderr," -CAfile arg   - PEM format file of CA's\n");
+	fprintf(stderr," -cert arg     - Server certificate file\n");
+	fprintf(stderr," -key arg      - Server key file (default: same as -cert)\n");
+	fprintf(stderr," -c_cert arg   - Client certificate file\n");
+	fprintf(stderr," -c_key arg    - Client key file (default: same as -c_cert)\n");
+	fprintf(stderr," -cipher arg   - The cipher list\n");
+	fprintf(stderr," -bio_pair     - Use BIO pairs\n");
+	fprintf(stderr," -f            - Test even cases that can't work\n");
+	fprintf(stderr," -time         - measure processor time used by client and server\n");
+	fprintf(stderr," -zlib         - use zlib compression\n");
+	fprintf(stderr," -rle          - use rle compression\n");
+#ifndef OPENSSL_NO_ECDH
+	fprintf(stderr," -named_curve arg  - Elliptic curve name to use for ephemeral ECDH keys.\n" \
+	               "                 Use \"openssl ecparam -list_curves\" for all names\n"  \
+	               "                 (default is sect163r2).\n");
+#endif
+	fprintf(stderr," -test_cipherlist - verifies the order of the ssl cipher lists\n");
+	fprintf(stderr," -c_small_records - enable client side use of small SSL record buffers\n");
+	fprintf(stderr," -s_small_records - enable server side use of small SSL record buffers\n");
+	fprintf(stderr," -cutthrough      - enable 1-RTT full-handshake for strong ciphers\n");
+	}
+
+static void print_details(SSL *c_ssl, const char *prefix)
+	{
+	const SSL_CIPHER *ciph;
+	X509 *cert;
+		
+	ciph=SSL_get_current_cipher(c_ssl);
+	BIO_printf(bio_stdout,"%s%s, cipher %s %s",
+		prefix,
+		SSL_get_version(c_ssl),
+		SSL_CIPHER_get_version(ciph),
+		SSL_CIPHER_get_name(ciph));
+	cert=SSL_get_peer_certificate(c_ssl);
+	if (cert != NULL)
+		{
+		EVP_PKEY *pkey = X509_get_pubkey(cert);
+		if (pkey != NULL)
+			{
+			if (0) 
+				;
+#ifndef OPENSSL_NO_RSA
+			else if (pkey->type == EVP_PKEY_RSA && pkey->pkey.rsa != NULL
+				&& pkey->pkey.rsa->n != NULL)
+				{
+				BIO_printf(bio_stdout, ", %d bit RSA",
+					BN_num_bits(pkey->pkey.rsa->n));
+				}
+#endif
+#ifndef OPENSSL_NO_DSA
+			else if (pkey->type == EVP_PKEY_DSA && pkey->pkey.dsa != NULL
+				&& pkey->pkey.dsa->p != NULL)
+				{
+				BIO_printf(bio_stdout, ", %d bit DSA",
+					BN_num_bits(pkey->pkey.dsa->p));
+				}
+#endif
+			EVP_PKEY_free(pkey);
+			}
+		X509_free(cert);
+		}
+	/* The SSL API does not allow us to look at temporary RSA/DH keys,
+	 * otherwise we should print their lengths too */
+	BIO_printf(bio_stdout,"\n");
+	}
+
+static void lock_dbg_cb(int mode, int type, const char *file, int line)
+	{
+	static int modes[CRYPTO_NUM_LOCKS]; /* = {0, 0, ... } */
+	const char *errstr = NULL;
+	int rw;
+	
+	rw = mode & (CRYPTO_READ|CRYPTO_WRITE);
+	if (!((rw == CRYPTO_READ) || (rw == CRYPTO_WRITE)))
+		{
+		errstr = "invalid mode";
+		goto err;
+		}
+
+	if (type < 0 || type >= CRYPTO_NUM_LOCKS)
+		{
+		errstr = "type out of bounds";
+		goto err;
+		}
+
+	if (mode & CRYPTO_LOCK)
+		{
+		if (modes[type])
+			{
+			errstr = "already locked";
+			/* must not happen in a single-threaded program
+			 * (would deadlock) */
+			goto err;
+			}
+
+		modes[type] = rw;
+		}
+	else if (mode & CRYPTO_UNLOCK)
+		{
+		if (!modes[type])
+			{
+			errstr = "not locked";
+			goto err;
+			}
+		
+		if (modes[type] != rw)
+			{
+			errstr = (rw == CRYPTO_READ) ?
+				"CRYPTO_r_unlock on write lock" :
+				"CRYPTO_w_unlock on read lock";
+			}
+
+		modes[type] = 0;
+		}
+	else
+		{
+		errstr = "invalid mode";
+		goto err;
+		}
+
+ err:
+	if (errstr)
+		{
+		/* we cannot use bio_err here */
+		fprintf(stderr, "openssl (lock_dbg_cb): %s (mode=%d, type=%d) at %s:%d\n",
+			errstr, mode, type, file, line);
+		}
+	}
+
+#ifdef TLSEXT_TYPE_opaque_prf_input
+struct cb_info_st { void *input; size_t len; int ret; };
+struct cb_info_st co1 = { "C", 1, 1 }; /* try to negotiate oqaque PRF input */
+struct cb_info_st co2 = { "C", 1, 2 }; /* insist on oqaque PRF input */
+struct cb_info_st so1 = { "S", 1, 1 }; /* try to negotiate oqaque PRF input */
+struct cb_info_st so2 = { "S", 1, 2 }; /* insist on oqaque PRF input */
+
+int opaque_prf_input_cb(SSL *ssl, void *peerinput, size_t len, void *arg_)
+	{
+	struct cb_info_st *arg = arg_;
+
+	if (arg == NULL)
+		return 1;
+	
+	if (!SSL_set_tlsext_opaque_prf_input(ssl, arg->input, arg->len))
+		return 0;
+	return arg->ret;
+	}
+#endif
+	int ssl_mode = 0;
+	int c_small_records=0;
+	int s_small_records=0;
+	int cutthrough = 0;
+
+int main(int argc, char *argv[])
+	{
+	char *CApath=NULL,*CAfile=NULL;
+	int badop=0;
+	int bio_pair=0;
+	int force=0;
+	int tls1=0,ssl2=0,ssl3=0,ret=1;
+	int client_auth=0;
+	int server_auth=0,i;
+	struct app_verify_arg app_verify_arg =
+		{ APP_CALLBACK_STRING, 0, 0, NULL, NULL };
+	char *server_cert=TEST_SERVER_CERT;
+	char *server_key=NULL;
+	char *client_cert=TEST_CLIENT_CERT;
+	char *client_key=NULL;
+#ifndef OPENSSL_NO_ECDH
+	char *named_curve = NULL;
+#endif
+	SSL_CTX *s_ctx=NULL;
+	SSL_CTX *c_ctx=NULL;
+	const SSL_METHOD *meth=NULL;
+	SSL *c_ssl,*s_ssl;
+	int number=1,reuse=0;
+	long bytes=256L;
+#ifndef OPENSSL_NO_DH
+	DH *dh;
+	int dhe1024 = 0, dhe1024dsa = 0;
+#endif
+#ifndef OPENSSL_NO_ECDH
+	EC_KEY *ecdh = NULL;
+#endif
+	int no_dhe = 0;
+	int no_ecdhe = 0;
+	int no_psk = 0;
+	int print_time = 0;
+	clock_t s_time = 0, c_time = 0;
+	int comp = 0;
+#ifndef OPENSSL_NO_COMP
+	COMP_METHOD *cm = NULL;
+#endif
+	STACK_OF(SSL_COMP) *ssl_comp_methods = NULL;
+	int test_cipherlist = 0;
+
+	verbose = 0;
+	debug = 0;
+	cipher = 0;
+
+	bio_err=BIO_new_fp(stderr,BIO_NOCLOSE|BIO_FP_TEXT);	
+
+	CRYPTO_set_locking_callback(lock_dbg_cb);
+
+	/* enable memory leak checking unless explicitly disabled */
+	if (!((getenv("OPENSSL_DEBUG_MEMORY") != NULL) && (0 == strcmp(getenv("OPENSSL_DEBUG_MEMORY"), "off"))))
+		{
+		CRYPTO_malloc_debug_init();
+		CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
+		}
+	else
+		{
+		/* OPENSSL_DEBUG_MEMORY=off */
+		CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0);
+		}
+	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
+
+	RAND_seed(rnd_seed, sizeof rnd_seed);
+
+	bio_stdout=BIO_new_fp(stdout,BIO_NOCLOSE|BIO_FP_TEXT);
+
+	argc--;
+	argv++;
+
+	while (argc >= 1)
+		{
+		if	(strcmp(*argv,"-server_auth") == 0)
+			server_auth=1;
+		else if	(strcmp(*argv,"-client_auth") == 0)
+			client_auth=1;
+		else if (strcmp(*argv,"-proxy_auth") == 0)
+			{
+			if (--argc < 1) goto bad;
+			app_verify_arg.proxy_auth= *(++argv);
+			}
+		else if (strcmp(*argv,"-proxy_cond") == 0)
+			{
+			if (--argc < 1) goto bad;
+			app_verify_arg.proxy_cond= *(++argv);
+			}
+		else if	(strcmp(*argv,"-v") == 0)
+			verbose=1;
+		else if	(strcmp(*argv,"-d") == 0)
+			debug=1;
+		else if	(strcmp(*argv,"-reuse") == 0)
+			reuse=1;
+		else if	(strcmp(*argv,"-dhe1024") == 0)
+			{
+#ifndef OPENSSL_NO_DH
+			dhe1024=1;
+#else
+			fprintf(stderr,"ignoring -dhe1024, since I'm compiled without DH\n");
+#endif
+			}
+		else if	(strcmp(*argv,"-dhe1024dsa") == 0)
+			{
+#ifndef OPENSSL_NO_DH
+			dhe1024dsa=1;
+#else
+			fprintf(stderr,"ignoring -dhe1024, since I'm compiled without DH\n");
+#endif
+			}
+		else if	(strcmp(*argv,"-no_dhe") == 0)
+			no_dhe=1;
+		else if	(strcmp(*argv,"-no_ecdhe") == 0)
+			no_ecdhe=1;
+		else if (strcmp(*argv,"-psk") == 0)
+			{
+			if (--argc < 1) goto bad;
+			psk_key=*(++argv);
+#ifndef OPENSSL_NO_PSK
+			if (strspn(psk_key, "abcdefABCDEF1234567890") != strlen(psk_key))
+				{
+				BIO_printf(bio_err,"Not a hex number '%s'\n",*argv);
+				goto bad;
+				}
+#else
+			no_psk=1;
+#endif
+			}
+		else if	(strcmp(*argv,"-ssl2") == 0)
+			ssl2=1;
+		else if	(strcmp(*argv,"-tls1") == 0)
+			tls1=1;
+		else if	(strcmp(*argv,"-ssl3") == 0)
+			ssl3=1;
+		else if	(strncmp(*argv,"-num",4) == 0)
+			{
+			if (--argc < 1) goto bad;
+			number= atoi(*(++argv));
+			if (number == 0) number=1;
+			}
+		else if	(strcmp(*argv,"-bytes") == 0)
+			{
+			if (--argc < 1) goto bad;
+			bytes= atol(*(++argv));
+			if (bytes == 0L) bytes=1L;
+			i=strlen(argv[0]);
+			if (argv[0][i-1] == 'k') bytes*=1024L;
+			if (argv[0][i-1] == 'm') bytes*=1024L*1024L;
+			}
+		else if	(strcmp(*argv,"-cert") == 0)
+			{
+			if (--argc < 1) goto bad;
+			server_cert= *(++argv);
+			}
+		else if	(strcmp(*argv,"-s_cert") == 0)
+			{
+			if (--argc < 1) goto bad;
+			server_cert= *(++argv);
+			}
+		else if	(strcmp(*argv,"-key") == 0)
+			{
+			if (--argc < 1) goto bad;
+			server_key= *(++argv);
+			}
+		else if	(strcmp(*argv,"-s_key") == 0)
+			{
+			if (--argc < 1) goto bad;
+			server_key= *(++argv);
+			}
+		else if	(strcmp(*argv,"-c_cert") == 0)
+			{
+			if (--argc < 1) goto bad;
+			client_cert= *(++argv);
+			}
+		else if	(strcmp(*argv,"-c_key") == 0)
+			{
+			if (--argc < 1) goto bad;
+			client_key= *(++argv);
+			}
+		else if	(strcmp(*argv,"-cipher") == 0)
+			{
+			if (--argc < 1) goto bad;
+			cipher= *(++argv);
+			}
+		else if	(strcmp(*argv,"-CApath") == 0)
+			{
+			if (--argc < 1) goto bad;
+			CApath= *(++argv);
+			}
+		else if	(strcmp(*argv,"-CAfile") == 0)
+			{
+			if (--argc < 1) goto bad;
+			CAfile= *(++argv);
+			}
+		else if	(strcmp(*argv,"-bio_pair") == 0)
+			{
+			bio_pair = 1;
+			}
+		else if	(strcmp(*argv,"-f") == 0)
+			{
+			force = 1;
+			}
+		else if	(strcmp(*argv,"-time") == 0)
+			{
+			print_time = 1;
+			}
+		else if	(strcmp(*argv,"-zlib") == 0)
+			{
+			comp = COMP_ZLIB;
+			}
+		else if	(strcmp(*argv,"-rle") == 0)
+			{
+			comp = COMP_RLE;
+			}
+		else if	(strcmp(*argv,"-named_curve") == 0)
+			{
+			if (--argc < 1) goto bad;
+#ifndef OPENSSL_NO_ECDH		
+			named_curve = *(++argv);
+#else
+			fprintf(stderr,"ignoring -named_curve, since I'm compiled without ECDH\n");
+			++argv;
+#endif
+			}
+		else if	(strcmp(*argv,"-app_verify") == 0)
+			{
+			app_verify_arg.app_verify = 1;
+			}
+		else if	(strcmp(*argv,"-proxy") == 0)
+			{
+			app_verify_arg.allow_proxy_certs = 1;
+			}
+		else if (strcmp(*argv,"-test_cipherlist") == 0)
+			{
+			test_cipherlist = 1;
+			}
+		else if (strcmp(*argv, "-c_small_records") == 0)
+			{
+			c_small_records = 1;
+			}
+		else if (strcmp(*argv, "-s_small_records") == 0)
+			{
+			s_small_records = 1;
+			}
+		else if (strcmp(*argv, "-cutthrough") == 0)
+			{
+			cutthrough = 1;
+			}
+		else
+			{
+			fprintf(stderr,"unknown option %s\n",*argv);
+			badop=1;
+			break;
+			}
+		argc--;
+		argv++;
+		}
+	if (badop)
+		{
+bad:
+		sv_usage();
+		goto end;
+		}
+
+	if (test_cipherlist == 1)
+		{
+		/* ensure that the cipher list are correctly sorted and exit */
+		if (do_test_cipherlist() == 0)
+			EXIT(1);
+		ret = 0;
+		goto end;
+		}
+
+	if (!ssl2 && !ssl3 && !tls1 && number > 1 && !reuse && !force)
+		{
+		fprintf(stderr, "This case cannot work.  Use -f to perform "
+			"the test anyway (and\n-d to see what happens), "
+			"or add one of -ssl2, -ssl3, -tls1, -reuse\n"
+			"to avoid protocol mismatch.\n");
+		EXIT(1);
+		}
+
+	if (print_time)
+		{
+		if (!bio_pair)
+			{
+			fprintf(stderr, "Using BIO pair (-bio_pair)\n");
+			bio_pair = 1;
+			}
+		if (number < 50 && !force)
+			fprintf(stderr, "Warning: For accurate timings, use more connections (e.g. -num 1000)\n");
+		}
+
+/*	if (cipher == NULL) cipher=getenv("SSL_CIPHER"); */
+
+	SSL_library_init();
+	SSL_load_error_strings();
+
+#ifndef OPENSSL_NO_COMP
+	if (comp == COMP_ZLIB) cm = COMP_zlib();
+	if (comp == COMP_RLE) cm = COMP_rle();
+	if (cm != NULL)
+		{
+		if (cm->type != NID_undef)
+			{
+			if (SSL_COMP_add_compression_method(comp, cm) != 0)
+				{
+				fprintf(stderr,
+					"Failed to add compression method\n");
+				ERR_print_errors_fp(stderr);
+				}
+			}
+		else
+			{
+			fprintf(stderr,
+				"Warning: %s compression not supported\n",
+				(comp == COMP_RLE ? "rle" :
+					(comp == COMP_ZLIB ? "zlib" :
+						"unknown")));
+			ERR_print_errors_fp(stderr);
+			}
+		}
+	ssl_comp_methods = SSL_COMP_get_compression_methods();
+	fprintf(stderr, "Available compression methods:\n");
+	{
+	int j, n = sk_SSL_COMP_num(ssl_comp_methods);
+	if (n == 0)
+		fprintf(stderr, "  NONE\n");
+	else
+		for (j = 0; j < n; j++)
+			{
+			SSL_COMP *c = sk_SSL_COMP_value(ssl_comp_methods, j);
+			fprintf(stderr, "  %d: %s\n", c->id, c->name);
+			}
+	}
+#endif
+
+#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
+	if (ssl2)
+		meth=SSLv2_method();
+	else 
+	if (tls1)
+		meth=TLSv1_method();
+	else
+	if (ssl3)
+		meth=SSLv3_method();
+	else
+		meth=SSLv23_method();
+#else
+#ifdef OPENSSL_NO_SSL2
+	meth=SSLv3_method();
+#else
+	meth=SSLv2_method();
+#endif
+#endif
+
+	c_ctx=SSL_CTX_new(meth);
+	s_ctx=SSL_CTX_new(meth);
+	if ((c_ctx == NULL) || (s_ctx == NULL))
+		{
+		ERR_print_errors(bio_err);
+		goto end;
+		}
+
+	if (cipher != NULL)
+		{
+		SSL_CTX_set_cipher_list(c_ctx,cipher);
+		SSL_CTX_set_cipher_list(s_ctx,cipher);
+		}
+
+	ssl_mode = 0;
+	if (c_small_records)
+		{
+		ssl_mode = SSL_CTX_get_mode(c_ctx);
+		ssl_mode |= SSL_MODE_SMALL_BUFFERS;
+		SSL_CTX_set_mode(c_ctx, ssl_mode);
+		}
+	ssl_mode = 0;
+	if (s_small_records)
+		{
+		ssl_mode = SSL_CTX_get_mode(s_ctx);
+		ssl_mode |= SSL_MODE_SMALL_BUFFERS;
+		SSL_CTX_set_mode(s_ctx, ssl_mode);
+		}
+	ssl_mode = 0;
+	if (cutthrough)
+		{
+		ssl_mode = SSL_CTX_get_mode(c_ctx);
+		ssl_mode = SSL_MODE_HANDSHAKE_CUTTHROUGH;
+		SSL_CTX_set_mode(c_ctx, ssl_mode);
+		}
+
+#ifndef OPENSSL_NO_DH
+	if (!no_dhe)
+		{
+		if (dhe1024dsa)
+			{
+			/* use SSL_OP_SINGLE_DH_USE to avoid small subgroup attacks */
+			SSL_CTX_set_options(s_ctx, SSL_OP_SINGLE_DH_USE);
+			dh=get_dh1024dsa();
+			}
+		else if (dhe1024)
+			dh=get_dh1024();
+		else
+			dh=get_dh512();
+		SSL_CTX_set_tmp_dh(s_ctx,dh);
+		DH_free(dh);
+		}
+#else
+	(void)no_dhe;
+#endif
+
+#ifndef OPENSSL_NO_ECDH
+	if (!no_ecdhe)
+		{
+		int nid;
+
+		if (named_curve != NULL)
+			{
+			nid = OBJ_sn2nid(named_curve);
+			if (nid == 0)
+			{
+				BIO_printf(bio_err, "unknown curve name (%s)\n", named_curve);
+				goto end;
+				}
+			}
+		else
+			nid = NID_sect163r2;
+
+		ecdh = EC_KEY_new_by_curve_name(nid);
+		if (ecdh == NULL)
+			{
+			BIO_printf(bio_err, "unable to create curve\n");
+			goto end;
+			}
+
+		SSL_CTX_set_tmp_ecdh(s_ctx, ecdh);
+		SSL_CTX_set_options(s_ctx, SSL_OP_SINGLE_ECDH_USE);
+		EC_KEY_free(ecdh);
+		}
+#else
+	(void)no_ecdhe;
+#endif
+
+#ifndef OPENSSL_NO_RSA
+	SSL_CTX_set_tmp_rsa_callback(s_ctx,tmp_rsa_cb);
+#endif
+
+#ifdef TLSEXT_TYPE_opaque_prf_input
+	SSL_CTX_set_tlsext_opaque_prf_input_callback(c_ctx, opaque_prf_input_cb);
+	SSL_CTX_set_tlsext_opaque_prf_input_callback(s_ctx, opaque_prf_input_cb);
+	SSL_CTX_set_tlsext_opaque_prf_input_callback_arg(c_ctx, &co1); /* or &co2 or NULL */
+	SSL_CTX_set_tlsext_opaque_prf_input_callback_arg(s_ctx, &so1); /* or &so2 or NULL */
+#endif
+
+	if (!SSL_CTX_use_certificate_file(s_ctx,server_cert,SSL_FILETYPE_PEM))
+		{
+		ERR_print_errors(bio_err);
+		}
+	else if (!SSL_CTX_use_PrivateKey_file(s_ctx,
+		(server_key?server_key:server_cert), SSL_FILETYPE_PEM))
+		{
+		ERR_print_errors(bio_err);
+		goto end;
+		}
+
+	if (client_auth)
+		{
+		SSL_CTX_use_certificate_file(c_ctx,client_cert,
+			SSL_FILETYPE_PEM);
+		SSL_CTX_use_PrivateKey_file(c_ctx,
+			(client_key?client_key:client_cert),
+			SSL_FILETYPE_PEM);
+		}
+
+	if (	(!SSL_CTX_load_verify_locations(s_ctx,CAfile,CApath)) ||
+		(!SSL_CTX_set_default_verify_paths(s_ctx)) ||
+		(!SSL_CTX_load_verify_locations(c_ctx,CAfile,CApath)) ||
+		(!SSL_CTX_set_default_verify_paths(c_ctx)))
+		{
+		/* fprintf(stderr,"SSL_load_verify_locations\n"); */
+		ERR_print_errors(bio_err);
+		/* goto end; */
+		}
+
+	if (client_auth)
+		{
+		BIO_printf(bio_err,"client authentication\n");
+		SSL_CTX_set_verify(s_ctx,
+			SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
+			verify_callback);
+		SSL_CTX_set_cert_verify_callback(s_ctx, app_verify_callback, &app_verify_arg);
+		}
+	if (server_auth)
+		{
+		BIO_printf(bio_err,"server authentication\n");
+		SSL_CTX_set_verify(c_ctx,SSL_VERIFY_PEER,
+			verify_callback);
+		SSL_CTX_set_cert_verify_callback(c_ctx, app_verify_callback, &app_verify_arg);
+		}
+	
+	{
+		int session_id_context = 0;
+		SSL_CTX_set_session_id_context(s_ctx, (void *)&session_id_context, sizeof session_id_context);
+	}
+
+	/* Use PSK only if PSK key is given */
+	if (psk_key != NULL)
+		{
+		/* no_psk is used to avoid putting psk command to openssl tool */
+		if (no_psk)
+			{
+			/* if PSK is not compiled in and psk key is
+			 * given, do nothing and exit successfully */
+			ret=0;
+			goto end;
+			}
+#ifndef OPENSSL_NO_PSK
+		SSL_CTX_set_psk_client_callback(c_ctx, psk_client_callback);
+		SSL_CTX_set_psk_server_callback(s_ctx, psk_server_callback);
+		if (debug)
+			BIO_printf(bio_err,"setting PSK identity hint to s_ctx\n");
+		if (!SSL_CTX_use_psk_identity_hint(s_ctx, "ctx server identity_hint"))
+			{
+			BIO_printf(bio_err,"error setting PSK identity hint to s_ctx\n");
+			ERR_print_errors(bio_err);
+			goto end;
+			}
+#endif
+		}
+
+	c_ssl=SSL_new(c_ctx);
+	s_ssl=SSL_new(s_ctx);
+
+#ifndef OPENSSL_NO_KRB5
+	if (c_ssl  &&  c_ssl->kssl_ctx)
+                {
+                char	localhost[MAXHOSTNAMELEN+2];
+
+		if (gethostname(localhost, sizeof localhost-1) == 0)
+                        {
+			localhost[sizeof localhost-1]='\0';
+			if(strlen(localhost) == sizeof localhost-1)
+				{
+				BIO_printf(bio_err,"localhost name too long\n");
+				goto end;
+				}
+			kssl_ctx_setstring(c_ssl->kssl_ctx, KSSL_SERVER,
+                                localhost);
+			}
+		}
+#endif    /* OPENSSL_NO_KRB5  */
+
+	for (i=0; i<number; i++)
+		{
+		if (!reuse) SSL_set_session(c_ssl,NULL);
+		if (bio_pair)
+			ret=doit_biopair(s_ssl,c_ssl,bytes,&s_time,&c_time);
+		else
+			ret=doit(s_ssl,c_ssl,bytes);
+		}
+
+	if (!verbose)
+		{
+		print_details(c_ssl, "");
+		}
+	if ((number > 1) || (bytes > 1L))
+		BIO_printf(bio_stdout, "%d handshakes of %ld bytes done\n",number,bytes);
+	if (print_time)
+		{
+#ifdef CLOCKS_PER_SEC
+		/* "To determine the time in seconds, the value returned
+		 * by the clock function should be divided by the value
+		 * of the macro CLOCKS_PER_SEC."
+		 *                                       -- ISO/IEC 9899 */
+		BIO_printf(bio_stdout, "Approximate total server time: %6.2f s\n"
+			"Approximate total client time: %6.2f s\n",
+			(double)s_time/CLOCKS_PER_SEC,
+			(double)c_time/CLOCKS_PER_SEC);
+#else
+		/* "`CLOCKS_PER_SEC' undeclared (first use this function)"
+		 *                            -- cc on NeXTstep/OpenStep */
+		BIO_printf(bio_stdout,
+			"Approximate total server time: %6.2f units\n"
+			"Approximate total client time: %6.2f units\n",
+			(double)s_time,
+			(double)c_time);
+#endif
+		}
+
+	SSL_free(s_ssl);
+	SSL_free(c_ssl);
+
+end:
+	if (s_ctx != NULL) SSL_CTX_free(s_ctx);
+	if (c_ctx != NULL) SSL_CTX_free(c_ctx);
+
+	if (bio_stdout != NULL) BIO_free(bio_stdout);
+
+#ifndef OPENSSL_NO_RSA
+	free_tmp_rsa();
+#endif
+#ifndef OPENSSL_NO_ENGINE
+	ENGINE_cleanup();
+#endif
+	CRYPTO_cleanup_all_ex_data();
+	ERR_free_strings();
+	ERR_remove_thread_state(NULL);
+	EVP_cleanup();
+	CRYPTO_mem_leaks(bio_err);
+	if (bio_err != NULL) BIO_free(bio_err);
+	EXIT(ret);
+	return ret;
+	}
+
+int doit_biopair(SSL *s_ssl, SSL *c_ssl, long count,
+	clock_t *s_time, clock_t *c_time)
+	{
+	long cw_num = count, cr_num = count, sw_num = count, sr_num = count;
+	BIO *s_ssl_bio = NULL, *c_ssl_bio = NULL;
+	BIO *server = NULL, *server_io = NULL, *client = NULL, *client_io = NULL;
+	int ret = 1;
+	
+	size_t bufsiz = 256; /* small buffer for testing */
+
+	if (!BIO_new_bio_pair(&server, bufsiz, &server_io, bufsiz))
+		goto err;
+	if (!BIO_new_bio_pair(&client, bufsiz, &client_io, bufsiz))
+		goto err;
+	
+	s_ssl_bio = BIO_new(BIO_f_ssl());
+	if (!s_ssl_bio)
+		goto err;
+
+	c_ssl_bio = BIO_new(BIO_f_ssl());
+	if (!c_ssl_bio)
+		goto err;
+
+	SSL_set_connect_state(c_ssl);
+	SSL_set_bio(c_ssl, client, client);
+	(void)BIO_set_ssl(c_ssl_bio, c_ssl, BIO_NOCLOSE);
+
+	SSL_set_accept_state(s_ssl);
+	SSL_set_bio(s_ssl, server, server);
+	(void)BIO_set_ssl(s_ssl_bio, s_ssl, BIO_NOCLOSE);
+
+	do
+		{
+		/* c_ssl_bio:          SSL filter BIO
+		 *
+		 * client:             pseudo-I/O for SSL library
+		 *
+		 * client_io:          client's SSL communication; usually to be
+		 *                     relayed over some I/O facility, but in this
+		 *                     test program, we're the server, too:
+		 *
+		 * server_io:          server's SSL communication
+		 *
+		 * server:             pseudo-I/O for SSL library
+		 *
+		 * s_ssl_bio:          SSL filter BIO
+		 *
+		 * The client and the server each employ a "BIO pair":
+		 * client + client_io, server + server_io.
+		 * BIO pairs are symmetric.  A BIO pair behaves similar
+		 * to a non-blocking socketpair (but both endpoints must
+		 * be handled by the same thread).
+		 * [Here we could connect client and server to the ends
+		 * of a single BIO pair, but then this code would be less
+		 * suitable as an example for BIO pairs in general.]
+		 *
+		 * Useful functions for querying the state of BIO pair endpoints:
+		 *
+		 * BIO_ctrl_pending(bio)              number of bytes we can read now
+		 * BIO_ctrl_get_read_request(bio)     number of bytes needed to fulfil
+		 *                                      other side's read attempt
+		 * BIO_ctrl_get_write_guarantee(bio)   number of bytes we can write now
+		 *
+		 * ..._read_request is never more than ..._write_guarantee;
+		 * it depends on the application which one you should use.
+		 */
+
+		/* We have non-blocking behaviour throughout this test program, but
+		 * can be sure that there is *some* progress in each iteration; so
+		 * we don't have to worry about ..._SHOULD_READ or ..._SHOULD_WRITE
+		 * -- we just try everything in each iteration
+		 */
+
+			{
+			/* CLIENT */
+		
+			MS_STATIC char cbuf[1024*8];
+			int i, r;
+			clock_t c_clock = clock();
+
+			memset(cbuf, 0, sizeof(cbuf));
+
+			if (debug)
+				if (SSL_in_init(c_ssl))
+					printf("client waiting in SSL_connect - %s\n",
+						SSL_state_string_long(c_ssl));
+
+			if (cw_num > 0)
+				{
+				/* Write to server. */
+				
+				if (cw_num > (long)sizeof cbuf)
+					i = sizeof cbuf;
+				else
+					i = (int)cw_num;
+				r = BIO_write(c_ssl_bio, cbuf, i);
+				if (r < 0)
+					{
+					if (!BIO_should_retry(c_ssl_bio))
+						{
+						fprintf(stderr,"ERROR in CLIENT\n");
+						goto err;
+						}
+					/* BIO_should_retry(...) can just be ignored here.
+					 * The library expects us to call BIO_write with
+					 * the same arguments again, and that's what we will
+					 * do in the next iteration. */
+					}
+				else if (r == 0)
+					{
+					fprintf(stderr,"SSL CLIENT STARTUP FAILED\n");
+					goto err;
+					}
+				else
+					{
+					if (debug)
+						printf("client wrote %d\n", r);
+					cw_num -= r;				
+					}
+				}
+
+			if (cr_num > 0)
+				{
+				/* Read from server. */
+
+				r = BIO_read(c_ssl_bio, cbuf, sizeof(cbuf));
+				if (r < 0)
+					{
+					if (!BIO_should_retry(c_ssl_bio))
+						{
+						fprintf(stderr,"ERROR in CLIENT\n");
+						goto err;
+						}
+					/* Again, "BIO_should_retry" can be ignored. */
+					}
+				else if (r == 0)
+					{
+					fprintf(stderr,"SSL CLIENT STARTUP FAILED\n");
+					goto err;
+					}
+				else
+					{
+					if (debug)
+						printf("client read %d\n", r);
+					cr_num -= r;
+					}
+				}
+
+			/* c_time and s_time increments will typically be very small
+			 * (depending on machine speed and clock tick intervals),
+			 * but sampling over a large number of connections should
+			 * result in fairly accurate figures.  We cannot guarantee
+			 * a lot, however -- if each connection lasts for exactly
+			 * one clock tick, it will be counted only for the client
+			 * or only for the server or even not at all.
+			 */
+			*c_time += (clock() - c_clock);
+			}
+
+			{
+			/* SERVER */
+		
+			MS_STATIC char sbuf[1024*8];
+			int i, r;
+			clock_t s_clock = clock();
+
+			memset(sbuf, 0, sizeof(sbuf));
+
+			if (debug)
+				if (SSL_in_init(s_ssl))
+					printf("server waiting in SSL_accept - %s\n",
+						SSL_state_string_long(s_ssl));
+
+			if (sw_num > 0)
+				{
+				/* Write to client. */
+				
+				if (sw_num > (long)sizeof sbuf)
+					i = sizeof sbuf;
+				else
+					i = (int)sw_num;
+				r = BIO_write(s_ssl_bio, sbuf, i);
+				if (r < 0)
+					{
+					if (!BIO_should_retry(s_ssl_bio))
+						{
+						fprintf(stderr,"ERROR in SERVER\n");
+						goto err;
+						}
+					/* Ignore "BIO_should_retry". */
+					}
+				else if (r == 0)
+					{
+					fprintf(stderr,"SSL SERVER STARTUP FAILED\n");
+					goto err;
+					}
+				else
+					{
+					if (debug)
+						printf("server wrote %d\n", r);
+					sw_num -= r;				
+					}
+				}
+
+			if (sr_num > 0)
+				{
+				/* Read from client. */
+
+				r = BIO_read(s_ssl_bio, sbuf, sizeof(sbuf));
+				if (r < 0)
+					{
+					if (!BIO_should_retry(s_ssl_bio))
+						{
+						fprintf(stderr,"ERROR in SERVER\n");
+						goto err;
+						}
+					/* blah, blah */
+					}
+				else if (r == 0)
+					{
+					fprintf(stderr,"SSL SERVER STARTUP FAILED\n");
+					goto err;
+					}
+				else
+					{
+					if (debug)
+						printf("server read %d\n", r);
+					sr_num -= r;
+					}
+				}
+
+			*s_time += (clock() - s_clock);
+			}
+			
+			{
+			/* "I/O" BETWEEN CLIENT AND SERVER. */
+
+			size_t r1, r2;
+			BIO *io1 = server_io, *io2 = client_io;
+			/* we use the non-copying interface for io1
+			 * and the standard BIO_write/BIO_read interface for io2
+			 */
+			
+			static int prev_progress = 1;
+			int progress = 0;
+			
+			/* io1 to io2 */
+			do
+				{
+				size_t num;
+				int r;
+
+				r1 = BIO_ctrl_pending(io1);
+				r2 = BIO_ctrl_get_write_guarantee(io2);
+
+				num = r1;
+				if (r2 < num)
+					num = r2;
+				if (num)
+					{
+					char *dataptr;
+
+					if (INT_MAX < num) /* yeah, right */
+						num = INT_MAX;
+					
+					r = BIO_nread(io1, &dataptr, (int)num);
+					assert(r > 0);
+					assert(r <= (int)num);
+					/* possibly r < num (non-contiguous data) */
+					num = r;
+					r = BIO_write(io2, dataptr, (int)num);
+					if (r != (int)num) /* can't happen */
+						{
+						fprintf(stderr, "ERROR: BIO_write could not write "
+							"BIO_ctrl_get_write_guarantee() bytes");
+						goto err;
+						}
+					progress = 1;
+
+					if (debug)
+						printf((io1 == client_io) ?
+							"C->S relaying: %d bytes\n" :
+							"S->C relaying: %d bytes\n",
+							(int)num);
+					}
+				}
+			while (r1 && r2);
+
+			/* io2 to io1 */
+			{
+				size_t num;
+				int r;
+
+				r1 = BIO_ctrl_pending(io2);
+				r2 = BIO_ctrl_get_read_request(io1);
+				/* here we could use ..._get_write_guarantee instead of
+				 * ..._get_read_request, but by using the latter
+				 * we test restartability of the SSL implementation
+				 * more thoroughly */
+				num = r1;
+				if (r2 < num)
+					num = r2;
+				if (num)
+					{
+					char *dataptr;
+					
+					if (INT_MAX < num)
+						num = INT_MAX;
+
+					if (num > 1)
+						--num; /* test restartability even more thoroughly */
+					
+					r = BIO_nwrite0(io1, &dataptr);
+					assert(r > 0);
+					if (r < (int)num)
+						num = r;
+					r = BIO_read(io2, dataptr, (int)num);
+					if (r != (int)num) /* can't happen */
+						{
+						fprintf(stderr, "ERROR: BIO_read could not read "
+							"BIO_ctrl_pending() bytes");
+						goto err;
+						}
+					progress = 1;
+					r = BIO_nwrite(io1, &dataptr, (int)num);
+					if (r != (int)num) /* can't happen */
+						{
+						fprintf(stderr, "ERROR: BIO_nwrite() did not accept "
+							"BIO_nwrite0() bytes");
+						goto err;
+						}
+					
+					if (debug)
+						printf((io2 == client_io) ?
+							"C->S relaying: %d bytes\n" :
+							"S->C relaying: %d bytes\n",
+							(int)num);
+					}
+			} /* no loop, BIO_ctrl_get_read_request now returns 0 anyway */
+
+			if (!progress && !prev_progress)
+				if (cw_num > 0 || cr_num > 0 || sw_num > 0 || sr_num > 0)
+					{
+					fprintf(stderr, "ERROR: got stuck\n");
+					if (strcmp("SSLv2", SSL_get_version(c_ssl)) == 0)
+						{
+						fprintf(stderr, "This can happen for SSL2 because "
+							"CLIENT-FINISHED and SERVER-VERIFY are written \n"
+							"concurrently ...");
+						if (strncmp("2SCF", SSL_state_string(c_ssl), 4) == 0
+							&& strncmp("2SSV", SSL_state_string(s_ssl), 4) == 0)
+							{
+							fprintf(stderr, " ok.\n");
+							goto end;
+							}
+						}
+					fprintf(stderr, " ERROR.\n");
+					goto err;
+					}
+			prev_progress = progress;
+			}
+		}
+	while (cw_num > 0 || cr_num > 0 || sw_num > 0 || sr_num > 0);
+
+	if (verbose)
+		print_details(c_ssl, "DONE via BIO pair: ");
+end:
+	ret = 0;
+
+ err:
+	ERR_print_errors(bio_err);
+	
+	if (server)
+		BIO_free(server);
+	if (server_io)
+		BIO_free(server_io);
+	if (client)
+		BIO_free(client);
+	if (client_io)
+		BIO_free(client_io);
+	if (s_ssl_bio)
+		BIO_free(s_ssl_bio);
+	if (c_ssl_bio)
+		BIO_free(c_ssl_bio);
+
+	return ret;
+	}
+
+
+#define W_READ	1
+#define W_WRITE	2
+#define C_DONE	1
+#define S_DONE	2
+
+int doit(SSL *s_ssl, SSL *c_ssl, long count)
+	{
+	MS_STATIC char cbuf[1024*8],sbuf[1024*8];
+	long cw_num=count,cr_num=count;
+	long sw_num=count,sr_num=count;
+	int ret=1;
+	BIO *c_to_s=NULL;
+	BIO *s_to_c=NULL;
+	BIO *c_bio=NULL;
+	BIO *s_bio=NULL;
+	int c_r,c_w,s_r,s_w;
+	int c_want,s_want;
+	int i,j;
+	int done=0;
+	int c_write,s_write;
+	int do_server=0,do_client=0;
+
+	memset(cbuf,0,sizeof(cbuf));
+	memset(sbuf,0,sizeof(sbuf));
+
+	c_to_s=BIO_new(BIO_s_mem());
+	s_to_c=BIO_new(BIO_s_mem());
+	if ((s_to_c == NULL) || (c_to_s == NULL))
+		{
+		ERR_print_errors(bio_err);
+		goto err;
+		}
+
+	c_bio=BIO_new(BIO_f_ssl());
+	s_bio=BIO_new(BIO_f_ssl());
+	if ((c_bio == NULL) || (s_bio == NULL))
+		{
+		ERR_print_errors(bio_err);
+		goto err;
+		}
+
+	SSL_set_connect_state(c_ssl);
+	SSL_set_bio(c_ssl,s_to_c,c_to_s);
+	BIO_set_ssl(c_bio,c_ssl,BIO_NOCLOSE);
+
+	SSL_set_accept_state(s_ssl);
+	SSL_set_bio(s_ssl,c_to_s,s_to_c);
+	BIO_set_ssl(s_bio,s_ssl,BIO_NOCLOSE);
+
+	c_r=0; s_r=1;
+	c_w=1; s_w=0;
+	c_want=W_WRITE;
+	s_want=0;
+	c_write=1,s_write=0;
+
+	/* We can always do writes */
+	for (;;)
+		{
+		do_server=0;
+		do_client=0;
+
+		i=(int)BIO_pending(s_bio);
+		if ((i && s_r) || s_w) do_server=1;
+
+		i=(int)BIO_pending(c_bio);
+		if ((i && c_r) || c_w) do_client=1;
+
+		if (do_server && debug)
+			{
+			if (SSL_in_init(s_ssl))
+				printf("server waiting in SSL_accept - %s\n",
+					SSL_state_string_long(s_ssl));
+/*			else if (s_write)
+				printf("server:SSL_write()\n");
+			else
+				printf("server:SSL_read()\n"); */
+			}
+
+		if (do_client && debug)
+			{
+			if (SSL_in_init(c_ssl))
+				printf("client waiting in SSL_connect - %s\n",
+					SSL_state_string_long(c_ssl));
+/*			else if (c_write)
+				printf("client:SSL_write()\n");
+			else
+				printf("client:SSL_read()\n"); */
+			}
+
+		if (!do_client && !do_server)
+			{
+			fprintf(stdout,"ERROR IN STARTUP\n");
+			ERR_print_errors(bio_err);
+			break;
+			}
+		if (do_client && !(done & C_DONE))
+			{
+			if (c_write)
+				{
+				j = (cw_num > (long)sizeof(cbuf)) ?
+					(int)sizeof(cbuf) : (int)cw_num;
+				i=BIO_write(c_bio,cbuf,j);
+				if (i < 0)
+					{
+					c_r=0;
+					c_w=0;
+					if (BIO_should_retry(c_bio))
+						{
+						if (BIO_should_read(c_bio))
+							c_r=1;
+						if (BIO_should_write(c_bio))
+							c_w=1;
+						}
+					else
+						{
+						fprintf(stderr,"ERROR in CLIENT\n");
+						ERR_print_errors(bio_err);
+						goto err;
+						}
+					}
+				else if (i == 0)
+					{
+					fprintf(stderr,"SSL CLIENT STARTUP FAILED\n");
+					goto err;
+					}
+				else
+					{
+					if (debug)
+						printf("client wrote %d\n",i);
+					/* ok */
+					s_r=1;
+					c_write=0;
+					cw_num-=i;
+					}
+				}
+			else
+				{
+				i=BIO_read(c_bio,cbuf,sizeof(cbuf));
+				if (i < 0)
+					{
+					c_r=0;
+					c_w=0;
+					if (BIO_should_retry(c_bio))
+						{
+						if (BIO_should_read(c_bio))
+							c_r=1;
+						if (BIO_should_write(c_bio))
+							c_w=1;
+						}
+					else
+						{
+						fprintf(stderr,"ERROR in CLIENT\n");
+						ERR_print_errors(bio_err);
+						goto err;
+						}
+					}
+				else if (i == 0)
+					{
+					fprintf(stderr,"SSL CLIENT STARTUP FAILED\n");
+					goto err;
+					}
+				else
+					{
+					if (debug)
+						printf("client read %d\n",i);
+					cr_num-=i;
+					if (sw_num > 0)
+						{
+						s_write=1;
+						s_w=1;
+						}
+					if (cr_num <= 0)
+						{
+						s_write=1;
+						s_w=1;
+						done=S_DONE|C_DONE;
+						}
+					}
+				}
+			}
+
+		if (do_server && !(done & S_DONE))
+			{
+			if (!s_write)
+				{
+				i=BIO_read(s_bio,sbuf,sizeof(cbuf));
+				if (i < 0)
+					{
+					s_r=0;
+					s_w=0;
+					if (BIO_should_retry(s_bio))
+						{
+						if (BIO_should_read(s_bio))
+							s_r=1;
+						if (BIO_should_write(s_bio))
+							s_w=1;
+						}
+					else
+						{
+						fprintf(stderr,"ERROR in SERVER\n");
+						ERR_print_errors(bio_err);
+						goto err;
+						}
+					}
+				else if (i == 0)
+					{
+					ERR_print_errors(bio_err);
+					fprintf(stderr,"SSL SERVER STARTUP FAILED in SSL_read\n");
+					goto err;
+					}
+				else
+					{
+					if (debug)
+						printf("server read %d\n",i);
+					sr_num-=i;
+					if (cw_num > 0)
+						{
+						c_write=1;
+						c_w=1;
+						}
+					if (sr_num <= 0)
+						{
+						s_write=1;
+						s_w=1;
+						c_write=0;
+						}
+					}
+				}
+			else
+				{
+				j = (sw_num > (long)sizeof(sbuf)) ?
+					(int)sizeof(sbuf) : (int)sw_num;
+				i=BIO_write(s_bio,sbuf,j);
+				if (i < 0)
+					{
+					s_r=0;
+					s_w=0;
+					if (BIO_should_retry(s_bio))
+						{
+						if (BIO_should_read(s_bio))
+							s_r=1;
+						if (BIO_should_write(s_bio))
+							s_w=1;
+						}
+					else
+						{
+						fprintf(stderr,"ERROR in SERVER\n");
+						ERR_print_errors(bio_err);
+						goto err;
+						}
+					}
+				else if (i == 0)
+					{
+					ERR_print_errors(bio_err);
+					fprintf(stderr,"SSL SERVER STARTUP FAILED in SSL_write\n");
+					goto err;
+					}
+				else
+					{
+					if (debug)
+						printf("server wrote %d\n",i);
+					sw_num-=i;
+					s_write=0;
+					c_r=1;
+					if (sw_num <= 0)
+						done|=S_DONE;
+					}
+				}
+			}
+
+		if ((done & S_DONE) && (done & C_DONE)) break;
+		}
+
+	if (verbose)
+		print_details(c_ssl, "DONE: ");
+	ret=0;
+err:
+	/* We have to set the BIO's to NULL otherwise they will be
+	 * OPENSSL_free()ed twice.  Once when th s_ssl is SSL_free()ed and
+	 * again when c_ssl is SSL_free()ed.
+	 * This is a hack required because s_ssl and c_ssl are sharing the same
+	 * BIO structure and SSL_set_bio() and SSL_free() automatically
+	 * BIO_free non NULL entries.
+	 * You should not normally do this or be required to do this */
+	if (s_ssl != NULL)
+		{
+		s_ssl->rbio=NULL;
+		s_ssl->wbio=NULL;
+		}
+	if (c_ssl != NULL)
+		{
+		c_ssl->rbio=NULL;
+		c_ssl->wbio=NULL;
+		}
+
+	if (c_to_s != NULL) BIO_free(c_to_s);
+	if (s_to_c != NULL) BIO_free(s_to_c);
+	if (c_bio != NULL) BIO_free_all(c_bio);
+	if (s_bio != NULL) BIO_free_all(s_bio);
+	return(ret);
+	}
+
+static int get_proxy_auth_ex_data_idx(void)
+	{
+	static volatile int idx = -1;
+	if (idx < 0)
+		{
+		CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
+		if (idx < 0)
+			{
+			idx = X509_STORE_CTX_get_ex_new_index(0,
+				"SSLtest for verify callback", NULL,NULL,NULL);
+			}
+		CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
+		}
+	return idx;
+	}
+
+static int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx)
+	{
+	char *s,buf[256];
+
+	s=X509_NAME_oneline(X509_get_subject_name(ctx->current_cert),buf,
+			    sizeof buf);
+	if (s != NULL)
+		{
+		if (ok)
+			fprintf(stderr,"depth=%d %s\n",
+				ctx->error_depth,buf);
+		else
+			{
+			fprintf(stderr,"depth=%d error=%d %s\n",
+				ctx->error_depth,ctx->error,buf);
+			}
+		}
+
+	if (ok == 0)
+		{
+		fprintf(stderr,"Error string: %s\n",
+			X509_verify_cert_error_string(ctx->error));
+		switch (ctx->error)
+			{
+		case X509_V_ERR_CERT_NOT_YET_VALID:
+		case X509_V_ERR_CERT_HAS_EXPIRED:
+		case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
+			fprintf(stderr,"  ... ignored.\n");
+			ok=1;
+			}
+		}
+
+	if (ok == 1)
+		{
+		X509 *xs = ctx->current_cert;
+#if 0
+		X509 *xi = ctx->current_issuer;
+#endif
+
+		if (xs->ex_flags & EXFLAG_PROXY)
+			{
+			unsigned int *letters =
+				X509_STORE_CTX_get_ex_data(ctx,
+					get_proxy_auth_ex_data_idx());
+
+			if (letters)
+				{
+				int found_any = 0;
+				int i;
+				PROXY_CERT_INFO_EXTENSION *pci =
+					X509_get_ext_d2i(xs, NID_proxyCertInfo,
+						NULL, NULL);
+
+				switch (OBJ_obj2nid(pci->proxyPolicy->policyLanguage))
+					{
+				case NID_Independent:
+					/* Completely meaningless in this
+					   program, as there's no way to
+					   grant explicit rights to a
+					   specific PrC.  Basically, using
+					   id-ppl-Independent is the perfect
+					   way to grant no rights at all. */
+					fprintf(stderr, "  Independent proxy certificate");
+					for (i = 0; i < 26; i++)
+						letters[i] = 0;
+					break;
+				case NID_id_ppl_inheritAll:
+					/* This is basically a NOP, we
+					   simply let the current rights
+					   stand as they are. */
+					fprintf(stderr, "  Proxy certificate inherits all");
+					break;
+				default:
+					s = (char *)
+						pci->proxyPolicy->policy->data;
+					i = pci->proxyPolicy->policy->length;
+
+					/* The algorithm works as follows:
+					   it is assumed that previous
+					   iterations or the initial granted
+					   rights has already set some elements
+					   of `letters'.  What we need to do is
+					   to clear those that weren't granted
+					   by the current PrC as well.  The
+					   easiest way to do this is to add 1
+					   to all the elements whose letters
+					   are given with the current policy.
+					   That way, all elements that are set
+					   by the current policy and were
+					   already set by earlier policies and
+					   through the original grant of rights
+					   will get the value 2 or higher.
+					   The last thing to do is to sweep
+					   through `letters' and keep the
+					   elements having the value 2 as set,
+					   and clear all the others. */
+
+					fprintf(stderr, "  Certificate proxy rights = %*.*s", i, i, s);
+					while(i-- > 0)
+						{
+						int c = *s++;
+						if (isascii(c) && isalpha(c))
+							{
+							if (islower(c))
+								c = toupper(c);
+							letters[c - 'A']++;
+							}
+						}
+					for (i = 0; i < 26; i++)
+						if (letters[i] < 2)
+							letters[i] = 0;
+						else
+							letters[i] = 1;
+					}
+
+				found_any = 0;
+				fprintf(stderr,
+					", resulting proxy rights = ");
+				for(i = 0; i < 26; i++)
+					if (letters[i])
+						{
+						fprintf(stderr, "%c", i + 'A');
+						found_any = 1;
+						}
+				if (!found_any)
+					fprintf(stderr, "none");
+				fprintf(stderr, "\n");
+
+				PROXY_CERT_INFO_EXTENSION_free(pci);
+				}
+			}
+		}
+
+	return(ok);
+	}
+
+static void process_proxy_debug(int indent, const char *format, ...)
+	{
+	static const char indentation[] =
+		">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
+		">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"; /* That's 80 > */
+	char my_format[256];
+	va_list args;
+
+	BIO_snprintf(my_format, sizeof(my_format), "%*.*s %s",
+		indent, indent, indentation, format);
+
+	va_start(args, format);
+	vfprintf(stderr, my_format, args);
+	va_end(args);
+	}
+/* Priority levels:
+   0	[!]var, ()
+   1	& ^
+   2	|
+*/
+static int process_proxy_cond_adders(unsigned int letters[26],
+	const char *cond, const char **cond_end, int *pos, int indent);
+static int process_proxy_cond_val(unsigned int letters[26],
+	const char *cond, const char **cond_end, int *pos, int indent)
+	{
+	int c;
+	int ok = 1;
+	int negate = 0;
+
+	while(isspace((int)*cond))
+		{
+		cond++; (*pos)++;
+		}
+	c = *cond;
+
+	if (debug)
+		process_proxy_debug(indent,
+			"Start process_proxy_cond_val at position %d: %s\n",
+			*pos, cond);
+
+	while(c == '!')
+		{
+		negate = !negate;
+		cond++; (*pos)++;
+		while(isspace((int)*cond))
+			{
+			cond++; (*pos)++;
+			}
+		c = *cond;
+		}
+
+	if (c == '(')
+		{
+		cond++; (*pos)++;
+		ok = process_proxy_cond_adders(letters, cond, cond_end, pos,
+			indent + 1);
+		cond = *cond_end;
+		if (ok < 0)
+			goto end;
+		while(isspace((int)*cond))
+			{
+			cond++; (*pos)++;
+			}
+		c = *cond;
+		if (c != ')')
+			{
+			fprintf(stderr,
+				"Weird condition character in position %d: "
+				"%c\n", *pos, c);
+			ok = -1;
+			goto end;
+			}
+		cond++; (*pos)++;
+		}
+	else if (isascii(c) && isalpha(c))
+		{
+		if (islower(c))
+			c = toupper(c);
+		ok = letters[c - 'A'];
+		cond++; (*pos)++;
+		}
+	else
+		{
+		fprintf(stderr,
+			"Weird condition character in position %d: "
+			"%c\n", *pos, c);
+		ok = -1;
+		goto end;
+		}
+ end:
+	*cond_end = cond;
+	if (ok >= 0 && negate)
+		ok = !ok;
+
+	if (debug)
+		process_proxy_debug(indent,
+			"End process_proxy_cond_val at position %d: %s, returning %d\n",
+			*pos, cond, ok);
+
+	return ok;
+	}
+static int process_proxy_cond_multipliers(unsigned int letters[26],
+	const char *cond, const char **cond_end, int *pos, int indent)
+	{
+	int ok;
+	char c;
+
+	if (debug)
+		process_proxy_debug(indent,
+			"Start process_proxy_cond_multipliers at position %d: %s\n",
+			*pos, cond);
+
+	ok = process_proxy_cond_val(letters, cond, cond_end, pos, indent + 1);
+	cond = *cond_end;
+	if (ok < 0)
+		goto end;
+
+	while(ok >= 0)
+		{
+		while(isspace((int)*cond))
+			{
+			cond++; (*pos)++;
+			}
+		c = *cond;
+
+		switch(c)
+			{
+		case '&':
+		case '^':
+			{
+			int save_ok = ok;
+
+			cond++; (*pos)++;
+			ok = process_proxy_cond_val(letters,
+				cond, cond_end, pos, indent + 1);
+			cond = *cond_end;
+			if (ok < 0)
+				break;
+
+			switch(c)
+				{
+			case '&':
+				ok &= save_ok;
+				break;
+			case '^':
+				ok ^= save_ok;
+				break;
+			default:
+				fprintf(stderr, "SOMETHING IS SERIOUSLY WRONG!"
+					" STOPPING\n");
+				EXIT(1);
+				}
+			}
+			break;
+		default:
+			goto end;
+			}
+		}
+ end:
+	if (debug)
+		process_proxy_debug(indent,
+			"End process_proxy_cond_multipliers at position %d: %s, returning %d\n",
+			*pos, cond, ok);
+
+	*cond_end = cond;
+	return ok;
+	}
+static int process_proxy_cond_adders(unsigned int letters[26],
+	const char *cond, const char **cond_end, int *pos, int indent)
+	{
+	int ok;
+	char c;
+
+	if (debug)
+		process_proxy_debug(indent,
+			"Start process_proxy_cond_adders at position %d: %s\n",
+			*pos, cond);
+
+	ok = process_proxy_cond_multipliers(letters, cond, cond_end, pos,
+		indent + 1);
+	cond = *cond_end;
+	if (ok < 0)
+		goto end;
+
+	while(ok >= 0)
+		{
+		while(isspace((int)*cond))
+			{
+			cond++; (*pos)++;
+			}
+		c = *cond;
+
+		switch(c)
+			{
+		case '|':
+			{
+			int save_ok = ok;
+
+			cond++; (*pos)++;
+			ok = process_proxy_cond_multipliers(letters,
+				cond, cond_end, pos, indent + 1);
+			cond = *cond_end;
+			if (ok < 0)
+				break;
+
+			switch(c)
+				{
+			case '|':
+				ok |= save_ok;
+				break;
+			default:
+				fprintf(stderr, "SOMETHING IS SERIOUSLY WRONG!"
+					" STOPPING\n");
+				EXIT(1);
+				}
+			}
+			break;
+		default:
+			goto end;
+			}
+		}
+ end:
+	if (debug)
+		process_proxy_debug(indent,
+			"End process_proxy_cond_adders at position %d: %s, returning %d\n",
+			*pos, cond, ok);
+
+	*cond_end = cond;
+	return ok;
+	}
+
+static int process_proxy_cond(unsigned int letters[26],
+	const char *cond, const char **cond_end)
+	{
+	int pos = 1;
+	return process_proxy_cond_adders(letters, cond, cond_end, &pos, 1);
+	}
+
+static int MS_CALLBACK app_verify_callback(X509_STORE_CTX *ctx, void *arg)
+	{
+	int ok=1;
+	struct app_verify_arg *cb_arg = arg;
+	unsigned int letters[26]; /* only used with proxy_auth */
+
+	if (cb_arg->app_verify)
+		{
+		char *s = NULL,buf[256];
+
+		fprintf(stderr, "In app_verify_callback, allowing cert. ");
+		fprintf(stderr, "Arg is: %s\n", cb_arg->string);
+		fprintf(stderr, "Finished printing do we have a context? 0x%p a cert? 0x%p\n",
+			(void *)ctx, (void *)ctx->cert);
+		if (ctx->cert)
+			s=X509_NAME_oneline(X509_get_subject_name(ctx->cert),buf,256);
+		if (s != NULL)
+			{
+			fprintf(stderr,"cert depth=%d %s\n",ctx->error_depth,buf);
+			}
+		return(1);
+		}
+	if (cb_arg->proxy_auth)
+		{
+		int found_any = 0, i;
+		char *sp;
+
+		for(i = 0; i < 26; i++)
+			letters[i] = 0;
+		for(sp = cb_arg->proxy_auth; *sp; sp++)
+			{
+			int c = *sp;
+			if (isascii(c) && isalpha(c))
+				{
+				if (islower(c))
+					c = toupper(c);
+				letters[c - 'A'] = 1;
+				}
+			}
+
+		fprintf(stderr,
+			"  Initial proxy rights = ");
+		for(i = 0; i < 26; i++)
+			if (letters[i])
+				{
+				fprintf(stderr, "%c", i + 'A');
+				found_any = 1;
+				}
+		if (!found_any)
+			fprintf(stderr, "none");
+		fprintf(stderr, "\n");
+
+		X509_STORE_CTX_set_ex_data(ctx,
+			get_proxy_auth_ex_data_idx(),letters);
+		}
+	if (cb_arg->allow_proxy_certs)
+		{
+		X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_ALLOW_PROXY_CERTS);
+		}
+
+#ifndef OPENSSL_NO_X509_VERIFY
+# ifdef OPENSSL_FIPS
+	if(s->version == TLS1_VERSION)
+		FIPS_allow_md5(1);
+# endif
+	ok = X509_verify_cert(ctx);
+# ifdef OPENSSL_FIPS
+	if(s->version == TLS1_VERSION)
+		FIPS_allow_md5(0);
+# endif
+#endif
+
+	if (cb_arg->proxy_auth)
+		{
+		if (ok > 0)
+			{
+			const char *cond_end = NULL;
+
+			ok = process_proxy_cond(letters,
+				cb_arg->proxy_cond, &cond_end);
+
+			if (ok < 0)
+				EXIT(3);
+			if (*cond_end)
+				{
+				fprintf(stderr, "Stopped processing condition before it's end.\n");
+				ok = 0;
+				}
+			if (!ok)
+				fprintf(stderr, "Proxy rights check with condition '%s' proved invalid\n",
+					cb_arg->proxy_cond);
+			else
+				fprintf(stderr, "Proxy rights check with condition '%s' proved valid\n",
+					cb_arg->proxy_cond);
+			}
+		}
+	return(ok);
+	}
+
+#ifndef OPENSSL_NO_RSA
+static RSA *rsa_tmp=NULL;
+
+static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export, int keylength)
+	{
+	BIGNUM *bn = NULL;
+	if (rsa_tmp == NULL)
+		{
+		bn = BN_new();
+		rsa_tmp = RSA_new();
+		if(!bn || !rsa_tmp || !BN_set_word(bn, RSA_F4))
+			{
+			BIO_printf(bio_err, "Memory error...");
+			goto end;
+			}
+		BIO_printf(bio_err,"Generating temp (%d bit) RSA key...",keylength);
+		(void)BIO_flush(bio_err);
+		if(!RSA_generate_key_ex(rsa_tmp,keylength,bn,NULL))
+			{
+			BIO_printf(bio_err, "Error generating key.");
+			RSA_free(rsa_tmp);
+			rsa_tmp = NULL;
+			}
+end:
+		BIO_printf(bio_err,"\n");
+		(void)BIO_flush(bio_err);
+		}
+	if(bn) BN_free(bn);
+	return(rsa_tmp);
+	}
+
+static void free_tmp_rsa(void)
+	{
+	if (rsa_tmp != NULL)
+		{
+		RSA_free(rsa_tmp);
+		rsa_tmp = NULL;
+		}
+	}
+#endif
+
+#ifndef OPENSSL_NO_DH
+/* These DH parameters have been generated as follows:
+ *    $ openssl dhparam -C -noout 512
+ *    $ openssl dhparam -C -noout 1024
+ *    $ openssl dhparam -C -noout -dsaparam 1024
+ * (The third function has been renamed to avoid name conflicts.)
+ */
+static DH *get_dh512()
+	{
+	static unsigned char dh512_p[]={
+		0xCB,0xC8,0xE1,0x86,0xD0,0x1F,0x94,0x17,0xA6,0x99,0xF0,0xC6,
+		0x1F,0x0D,0xAC,0xB6,0x25,0x3E,0x06,0x39,0xCA,0x72,0x04,0xB0,
+		0x6E,0xDA,0xC0,0x61,0xE6,0x7A,0x77,0x25,0xE8,0x3B,0xB9,0x5F,
+		0x9A,0xB6,0xB5,0xFE,0x99,0x0B,0xA1,0x93,0x4E,0x35,0x33,0xB8,
+		0xE1,0xF1,0x13,0x4F,0x59,0x1A,0xD2,0x57,0xC0,0x26,0x21,0x33,
+		0x02,0xC5,0xAE,0x23,
+		};
+	static unsigned char dh512_g[]={
+		0x02,
+		};
+	DH *dh;
+
+	if ((dh=DH_new()) == NULL) return(NULL);
+	dh->p=BN_bin2bn(dh512_p,sizeof(dh512_p),NULL);
+	dh->g=BN_bin2bn(dh512_g,sizeof(dh512_g),NULL);
+	if ((dh->p == NULL) || (dh->g == NULL))
+		{ DH_free(dh); return(NULL); }
+	return(dh);
+	}
+
+static DH *get_dh1024()
+	{
+	static unsigned char dh1024_p[]={
+		0xF8,0x81,0x89,0x7D,0x14,0x24,0xC5,0xD1,0xE6,0xF7,0xBF,0x3A,
+		0xE4,0x90,0xF4,0xFC,0x73,0xFB,0x34,0xB5,0xFA,0x4C,0x56,0xA2,
+		0xEA,0xA7,0xE9,0xC0,0xC0,0xCE,0x89,0xE1,0xFA,0x63,0x3F,0xB0,
+		0x6B,0x32,0x66,0xF1,0xD1,0x7B,0xB0,0x00,0x8F,0xCA,0x87,0xC2,
+		0xAE,0x98,0x89,0x26,0x17,0xC2,0x05,0xD2,0xEC,0x08,0xD0,0x8C,
+		0xFF,0x17,0x52,0x8C,0xC5,0x07,0x93,0x03,0xB1,0xF6,0x2F,0xB8,
+		0x1C,0x52,0x47,0x27,0x1B,0xDB,0xD1,0x8D,0x9D,0x69,0x1D,0x52,
+		0x4B,0x32,0x81,0xAA,0x7F,0x00,0xC8,0xDC,0xE6,0xD9,0xCC,0xC1,
+		0x11,0x2D,0x37,0x34,0x6C,0xEA,0x02,0x97,0x4B,0x0E,0xBB,0xB1,
+		0x71,0x33,0x09,0x15,0xFD,0xDD,0x23,0x87,0x07,0x5E,0x89,0xAB,
+		0x6B,0x7C,0x5F,0xEC,0xA6,0x24,0xDC,0x53,
+		};
+	static unsigned char dh1024_g[]={
+		0x02,
+		};
+	DH *dh;
+
+	if ((dh=DH_new()) == NULL) return(NULL);
+	dh->p=BN_bin2bn(dh1024_p,sizeof(dh1024_p),NULL);
+	dh->g=BN_bin2bn(dh1024_g,sizeof(dh1024_g),NULL);
+	if ((dh->p == NULL) || (dh->g == NULL))
+		{ DH_free(dh); return(NULL); }
+	return(dh);
+	}
+
+static DH *get_dh1024dsa()
+	{
+	static unsigned char dh1024_p[]={
+		0xC8,0x00,0xF7,0x08,0x07,0x89,0x4D,0x90,0x53,0xF3,0xD5,0x00,
+		0x21,0x1B,0xF7,0x31,0xA6,0xA2,0xDA,0x23,0x9A,0xC7,0x87,0x19,
+		0x3B,0x47,0xB6,0x8C,0x04,0x6F,0xFF,0xC6,0x9B,0xB8,0x65,0xD2,
+		0xC2,0x5F,0x31,0x83,0x4A,0xA7,0x5F,0x2F,0x88,0x38,0xB6,0x55,
+		0xCF,0xD9,0x87,0x6D,0x6F,0x9F,0xDA,0xAC,0xA6,0x48,0xAF,0xFC,
+		0x33,0x84,0x37,0x5B,0x82,0x4A,0x31,0x5D,0xE7,0xBD,0x52,0x97,
+		0xA1,0x77,0xBF,0x10,0x9E,0x37,0xEA,0x64,0xFA,0xCA,0x28,0x8D,
+		0x9D,0x3B,0xD2,0x6E,0x09,0x5C,0x68,0xC7,0x45,0x90,0xFD,0xBB,
+		0x70,0xC9,0x3A,0xBB,0xDF,0xD4,0x21,0x0F,0xC4,0x6A,0x3C,0xF6,
+		0x61,0xCF,0x3F,0xD6,0x13,0xF1,0x5F,0xBC,0xCF,0xBC,0x26,0x9E,
+		0xBC,0x0B,0xBD,0xAB,0x5D,0xC9,0x54,0x39,
+		};
+	static unsigned char dh1024_g[]={
+		0x3B,0x40,0x86,0xE7,0xF3,0x6C,0xDE,0x67,0x1C,0xCC,0x80,0x05,
+		0x5A,0xDF,0xFE,0xBD,0x20,0x27,0x74,0x6C,0x24,0xC9,0x03,0xF3,
+		0xE1,0x8D,0xC3,0x7D,0x98,0x27,0x40,0x08,0xB8,0x8C,0x6A,0xE9,
+		0xBB,0x1A,0x3A,0xD6,0x86,0x83,0x5E,0x72,0x41,0xCE,0x85,0x3C,
+		0xD2,0xB3,0xFC,0x13,0xCE,0x37,0x81,0x9E,0x4C,0x1C,0x7B,0x65,
+		0xD3,0xE6,0xA6,0x00,0xF5,0x5A,0x95,0x43,0x5E,0x81,0xCF,0x60,
+		0xA2,0x23,0xFC,0x36,0xA7,0x5D,0x7A,0x4C,0x06,0x91,0x6E,0xF6,
+		0x57,0xEE,0x36,0xCB,0x06,0xEA,0xF5,0x3D,0x95,0x49,0xCB,0xA7,
+		0xDD,0x81,0xDF,0x80,0x09,0x4A,0x97,0x4D,0xA8,0x22,0x72,0xA1,
+		0x7F,0xC4,0x70,0x56,0x70,0xE8,0x20,0x10,0x18,0x8F,0x2E,0x60,
+		0x07,0xE7,0x68,0x1A,0x82,0x5D,0x32,0xA2,
+		};
+	DH *dh;
+
+	if ((dh=DH_new()) == NULL) return(NULL);
+	dh->p=BN_bin2bn(dh1024_p,sizeof(dh1024_p),NULL);
+	dh->g=BN_bin2bn(dh1024_g,sizeof(dh1024_g),NULL);
+	if ((dh->p == NULL) || (dh->g == NULL))
+		{ DH_free(dh); return(NULL); }
+	dh->length = 160;
+	return(dh);
+	}
+#endif
+
+#ifndef OPENSSL_NO_PSK
+/* convert the PSK key (psk_key) in ascii to binary (psk) */
+static int psk_key2bn(const char *pskkey, unsigned char *psk,
+	unsigned int max_psk_len)
+	{
+	int ret;
+	BIGNUM *bn = NULL;
+
+	ret = BN_hex2bn(&bn, pskkey);
+	if (!ret)
+		{
+		BIO_printf(bio_err,"Could not convert PSK key '%s' to BIGNUM\n", pskkey); 
+		if (bn)
+			BN_free(bn);
+		return 0;
+		}
+	if (BN_num_bytes(bn) > (int)max_psk_len)
+		{
+		BIO_printf(bio_err,"psk buffer of callback is too small (%d) for key (%d)\n",
+			max_psk_len, BN_num_bytes(bn));
+		BN_free(bn);
+		return 0;
+		}
+	ret = BN_bn2bin(bn, psk);
+	BN_free(bn);
+	return ret;
+	}
+
+static unsigned int psk_client_callback(SSL *ssl, const char *hint, char *identity,
+	unsigned int max_identity_len, unsigned char *psk,
+	unsigned int max_psk_len)
+	{
+	int ret;
+	unsigned int psk_len = 0;
+
+	ret = BIO_snprintf(identity, max_identity_len, "Client_identity");
+	if (ret < 0)
+		goto out_err;
+	if (debug)
+		fprintf(stderr, "client: created identity '%s' len=%d\n", identity, ret);
+	ret = psk_key2bn(psk_key, psk, max_psk_len);
+	if (ret < 0)
+		goto out_err;
+	psk_len = ret;
+out_err:
+	return psk_len;
+	}
+
+static unsigned int psk_server_callback(SSL *ssl, const char *identity,
+	unsigned char *psk, unsigned int max_psk_len)
+	{
+	unsigned int psk_len=0;
+
+	if (strcmp(identity, "Client_identity") != 0)
+		{
+		BIO_printf(bio_err, "server: PSK error: client identity not found\n");
+		return 0;
+		}
+	psk_len=psk_key2bn(psk_key, psk, max_psk_len);
+	return psk_len;
+	}
+#endif
+
+static int do_test_cipherlist(void)
+	{
+	int i = 0;
+	const SSL_METHOD *meth;
+	const SSL_CIPHER *ci, *tci = NULL;
+
+#ifndef OPENSSL_NO_SSL2
+	fprintf(stderr, "testing SSLv2 cipher list order: ");
+	meth = SSLv2_method();
+	while ((ci = meth->get_cipher(i++)) != NULL)
+		{
+		if (tci != NULL)
+			if (ci->id >= tci->id)
+				{
+				fprintf(stderr, "failed %lx vs. %lx\n", ci->id, tci->id);
+				return 0;
+				}
+		tci = ci;
+		}
+	fprintf(stderr, "ok\n");
+#endif
+#ifndef OPENSSL_NO_SSL3
+	fprintf(stderr, "testing SSLv3 cipher list order: ");
+	meth = SSLv3_method();
+	tci = NULL;
+	while ((ci = meth->get_cipher(i++)) != NULL)
+		{
+		if (tci != NULL)
+			if (ci->id >= tci->id)
+				{
+				fprintf(stderr, "failed %lx vs. %lx\n", ci->id, tci->id);
+				return 0;
+				}
+		tci = ci;
+		}
+	fprintf(stderr, "ok\n");
+#endif
+#ifndef OPENSSL_NO_TLS1
+	fprintf(stderr, "testing TLSv1 cipher list order: ");
+	meth = TLSv1_method();
+	tci = NULL;
+	while ((ci = meth->get_cipher(i++)) != NULL)
+		{
+		if (tci != NULL)
+			if (ci->id >= tci->id)
+				{
+				fprintf(stderr, "failed %lx vs. %lx\n", ci->id, tci->id);
+				return 0;
+				}
+		tci = ci;
+		}
+	fprintf(stderr, "ok\n");
+#endif
+
+	return 1;
+	}
diff --git a/lib/openssl/ssl/t1_clnt.c b/lib/openssl/ssl/t1_clnt.c
new file mode 100644
index 0000000..c87af17
--- /dev/null
+++ b/lib/openssl/ssl/t1_clnt.c
@@ -0,0 +1,79 @@
+/* ssl/t1_clnt.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include "ssl_locl.h"
+#include <openssl/buffer.h>
+#include <openssl/rand.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+
+static const SSL_METHOD *tls1_get_client_method(int ver);
+static const SSL_METHOD *tls1_get_client_method(int ver)
+	{
+	if (ver == TLS1_VERSION)
+		return(TLSv1_client_method());
+	else
+		return(NULL);
+	}
+
+IMPLEMENT_tls1_meth_func(TLSv1_client_method,
+			ssl_undefined_function,
+			ssl3_connect,
+			tls1_get_client_method)
+
diff --git a/lib/openssl/ssl/t1_enc.c b/lib/openssl/ssl/t1_enc.c
new file mode 100644
index 0000000..9719541
--- /dev/null
+++ b/lib/openssl/ssl/t1_enc.c
@@ -0,0 +1,1051 @@
+/* ssl/t1_enc.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#include <stdio.h>
+#include "ssl_locl.h"
+#ifndef OPENSSL_NO_COMP
+#include <openssl/comp.h>
+#endif
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/md5.h>
+#ifdef KSSL_DEBUG
+#include <openssl/des.h>
+#endif
+
+/* seed1 through seed5 are virtually concatenated */
+static int tls1_P_hash(const EVP_MD *md, const unsigned char *sec,
+			int sec_len,
+			const void *seed1, int seed1_len,
+			const void *seed2, int seed2_len,
+			const void *seed3, int seed3_len,
+			const void *seed4, int seed4_len,
+			const void *seed5, int seed5_len,
+			unsigned char *out, int olen)
+	{
+	int chunk,n;
+	unsigned int j;
+	HMAC_CTX ctx;
+	HMAC_CTX ctx_tmp;
+	unsigned char A1[EVP_MAX_MD_SIZE];
+	unsigned int A1_len;
+	int ret = 0;
+	
+	chunk=EVP_MD_size(md);
+	OPENSSL_assert(chunk >= 0);
+
+	HMAC_CTX_init(&ctx);
+	HMAC_CTX_init(&ctx_tmp);
+	if (!HMAC_Init_ex(&ctx,sec,sec_len,md, NULL))
+		goto err;
+	if (!HMAC_Init_ex(&ctx_tmp,sec,sec_len,md, NULL))
+		goto err;
+	if (seed1 != NULL && !HMAC_Update(&ctx,seed1,seed1_len))
+		goto err;
+	if (seed2 != NULL && !HMAC_Update(&ctx,seed2,seed2_len))
+		goto err;
+	if (seed3 != NULL && !HMAC_Update(&ctx,seed3,seed3_len))
+		goto err;
+	if (seed4 != NULL && !HMAC_Update(&ctx,seed4,seed4_len))
+		goto err;
+	if (seed5 != NULL && !HMAC_Update(&ctx,seed5,seed5_len))
+		goto err;
+	if (!HMAC_Final(&ctx,A1,&A1_len))
+		goto err;
+
+	n=0;
+	for (;;)
+		{
+		if (!HMAC_Init_ex(&ctx,NULL,0,NULL,NULL)) /* re-init */
+			goto err;
+		if (!HMAC_Init_ex(&ctx_tmp,NULL,0,NULL,NULL)) /* re-init */
+			goto err;
+		if (!HMAC_Update(&ctx,A1,A1_len))
+			goto err;
+		if (!HMAC_Update(&ctx_tmp,A1,A1_len))
+			goto err;
+		if (seed1 != NULL && !HMAC_Update(&ctx,seed1,seed1_len))
+			goto err;
+		if (seed2 != NULL && !HMAC_Update(&ctx,seed2,seed2_len))
+			goto err;
+		if (seed3 != NULL && !HMAC_Update(&ctx,seed3,seed3_len))
+			goto err;
+		if (seed4 != NULL && !HMAC_Update(&ctx,seed4,seed4_len))
+			goto err;
+		if (seed5 != NULL && !HMAC_Update(&ctx,seed5,seed5_len))
+			goto err;
+
+		if (olen > chunk)
+			{
+			if (!HMAC_Final(&ctx,out,&j))
+				goto err;
+			out+=j;
+			olen-=j;
+			if (!HMAC_Final(&ctx_tmp,A1,&A1_len)) /* calc the next A1 value */
+				goto err;
+			}
+		else	/* last one */
+			{
+			if (!HMAC_Final(&ctx,A1,&A1_len))
+				goto err;
+			memcpy(out,A1,olen);
+			break;
+			}
+		}
+	ret = 1;
+err:
+	HMAC_CTX_cleanup(&ctx);
+	HMAC_CTX_cleanup(&ctx_tmp);
+	OPENSSL_cleanse(A1,sizeof(A1));
+	return ret;
+	}
+
+/* seed1 through seed5 are virtually concatenated */
+static int tls1_PRF(long digest_mask,
+		     const void *seed1, int seed1_len,
+		     const void *seed2, int seed2_len,
+		     const void *seed3, int seed3_len,
+		     const void *seed4, int seed4_len,
+		     const void *seed5, int seed5_len,
+		     const unsigned char *sec, int slen,
+		     unsigned char *out1,
+		     unsigned char *out2, int olen)
+	{
+	int len,i,idx,count;
+	const unsigned char *S1;
+	long m;
+	const EVP_MD *md;
+	int ret = 0;
+
+	/* Count number of digests and partition sec evenly */
+	count=0;
+	for (idx=0;ssl_get_handshake_digest(idx,&m,&md);idx++) {
+		if ((m<<TLS1_PRF_DGST_SHIFT) & digest_mask) count++;
+	}	
+	len=slen/count;
+	S1=sec;
+	memset(out1,0,olen);
+	for (idx=0;ssl_get_handshake_digest(idx,&m,&md);idx++) {
+		if ((m<<TLS1_PRF_DGST_SHIFT) & digest_mask) {
+			if (!md) {
+				SSLerr(SSL_F_TLS1_PRF,
+				SSL_R_UNSUPPORTED_DIGEST_TYPE);
+				goto err;				
+			}
+			if (!tls1_P_hash(md ,S1,len+(slen&1),
+					seed1,seed1_len,seed2,seed2_len,seed3,seed3_len,seed4,seed4_len,seed5,seed5_len,
+					out2,olen))
+				goto err;
+			S1+=len;
+			for (i=0; i<olen; i++)
+			{
+				out1[i]^=out2[i];
+			}
+		}
+	}
+	ret = 1;
+err:
+	return ret;
+}
+static int tls1_generate_key_block(SSL *s, unsigned char *km,
+	     unsigned char *tmp, int num)
+	{
+	int ret;
+	ret = tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
+		 TLS_MD_KEY_EXPANSION_CONST,TLS_MD_KEY_EXPANSION_CONST_SIZE,
+		 s->s3->server_random,SSL3_RANDOM_SIZE,
+		 s->s3->client_random,SSL3_RANDOM_SIZE,
+		 NULL,0,NULL,0,
+		 s->session->master_key,s->session->master_key_length,
+		 km,tmp,num);
+#ifdef KSSL_DEBUG
+	printf("tls1_generate_key_block() ==> %d byte master_key =\n\t",
+                s->session->master_key_length);
+	{
+        int i;
+        for (i=0; i < s->session->master_key_length; i++)
+                {
+                printf("%02X", s->session->master_key[i]);
+                }
+        printf("\n");  }
+#endif    /* KSSL_DEBUG */
+	return ret;
+	}
+
+int tls1_change_cipher_state(SSL *s, int which)
+	{
+	static const unsigned char empty[]="";
+	unsigned char *p,*key_block,*mac_secret;
+	unsigned char *exp_label;
+	unsigned char tmp1[EVP_MAX_KEY_LENGTH];
+	unsigned char tmp2[EVP_MAX_KEY_LENGTH];
+	unsigned char iv1[EVP_MAX_IV_LENGTH*2];
+	unsigned char iv2[EVP_MAX_IV_LENGTH*2];
+	unsigned char *ms,*key,*iv,*er1,*er2;
+	int client_write;
+	EVP_CIPHER_CTX *dd;
+	const EVP_CIPHER *c;
+#ifndef OPENSSL_NO_COMP
+	const SSL_COMP *comp;
+#endif
+	const EVP_MD *m;
+	int mac_type;
+	int *mac_secret_size;
+	EVP_MD_CTX *mac_ctx;
+	EVP_PKEY *mac_key;
+	int is_export,n,i,j,k,exp_label_len,cl;
+	int reuse_dd = 0;
+
+	is_export=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher);
+	c=s->s3->tmp.new_sym_enc;
+	m=s->s3->tmp.new_hash;
+	mac_type = s->s3->tmp.new_mac_pkey_type;
+#ifndef OPENSSL_NO_COMP
+	comp=s->s3->tmp.new_compression;
+#endif
+	key_block=s->s3->tmp.key_block;
+
+#ifdef KSSL_DEBUG
+	printf("tls1_change_cipher_state(which= %d) w/\n", which);
+	printf("\talg= %ld/%ld, comp= %p\n",
+	       s->s3->tmp.new_cipher->algorithm_mkey,
+	       s->s3->tmp.new_cipher->algorithm_auth,
+	       comp);
+	printf("\tevp_cipher == %p ==? &d_cbc_ede_cipher3\n", c);
+	printf("\tevp_cipher: nid, blksz= %d, %d, keylen=%d, ivlen=%d\n",
+                c->nid,c->block_size,c->key_len,c->iv_len);
+	printf("\tkey_block: len= %d, data= ", s->s3->tmp.key_block_length);
+	{
+        int i;
+        for (i=0; i<s->s3->tmp.key_block_length; i++)
+		printf("%02x", key_block[i]);  printf("\n");
+        }
+#endif	/* KSSL_DEBUG */
+
+	if (which & SSL3_CC_READ)
+		{
+		if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC)
+			s->mac_flags |= SSL_MAC_FLAG_READ_MAC_STREAM;
+			else
+			s->mac_flags &= ~SSL_MAC_FLAG_READ_MAC_STREAM;
+
+		if (s->enc_read_ctx != NULL)
+			reuse_dd = 1;
+		else if ((s->enc_read_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL)
+			goto err;
+		else
+			/* make sure it's intialized in case we exit later with an error */
+			EVP_CIPHER_CTX_init(s->enc_read_ctx);
+		dd= s->enc_read_ctx;
+		mac_ctx=ssl_replace_hash(&s->read_hash,NULL);
+#ifndef OPENSSL_NO_COMP
+		if (s->expand != NULL)
+			{
+			COMP_CTX_free(s->expand);
+			s->expand=NULL;
+			}
+		if (comp != NULL)
+			{
+			s->expand=COMP_CTX_new(comp->method);
+			if (s->expand == NULL)
+				{
+				SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR);
+				goto err2;
+				}
+			if (s->s3->rrec.comp == NULL)
+				s->s3->rrec.comp=(unsigned char *)
+					OPENSSL_malloc(SSL3_RT_MAX_ENCRYPTED_LENGTH);
+			if (s->s3->rrec.comp == NULL)
+				goto err;
+			}
+#endif
+		/* this is done by dtls1_reset_seq_numbers for DTLS1_VERSION */
+ 		if (s->version != DTLS1_VERSION)
+			memset(&(s->s3->read_sequence[0]),0,8);
+		mac_secret= &(s->s3->read_mac_secret[0]);
+		mac_secret_size=&(s->s3->read_mac_secret_size);
+		}
+	else
+		{
+		if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC)
+			s->mac_flags |= SSL_MAC_FLAG_WRITE_MAC_STREAM;
+			else
+			s->mac_flags &= ~SSL_MAC_FLAG_WRITE_MAC_STREAM;
+		if (s->enc_write_ctx != NULL)
+			reuse_dd = 1;
+		else if ((s->enc_write_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL)
+			goto err;
+		else
+			/* make sure it's intialized in case we exit later with an error */
+			EVP_CIPHER_CTX_init(s->enc_write_ctx);
+		dd= s->enc_write_ctx;
+		mac_ctx = ssl_replace_hash(&s->write_hash,NULL);
+#ifndef OPENSSL_NO_COMP
+		if (s->compress != NULL)
+			{
+			COMP_CTX_free(s->compress);
+			s->compress=NULL;
+			}
+		if (comp != NULL)
+			{
+			s->compress=COMP_CTX_new(comp->method);
+			if (s->compress == NULL)
+				{
+				SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR);
+				goto err2;
+				}
+			}
+#endif
+		/* this is done by dtls1_reset_seq_numbers for DTLS1_VERSION */
+ 		if (s->version != DTLS1_VERSION)
+			memset(&(s->s3->write_sequence[0]),0,8);
+		mac_secret= &(s->s3->write_mac_secret[0]);
+		mac_secret_size = &(s->s3->write_mac_secret_size);
+		}
+
+	if (reuse_dd)
+		EVP_CIPHER_CTX_cleanup(dd);
+
+	p=s->s3->tmp.key_block;
+	i=*mac_secret_size=s->s3->tmp.new_mac_secret_size;
+
+	cl=EVP_CIPHER_key_length(c);
+	j=is_export ? (cl < SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher) ?
+	               cl : SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher)) : cl;
+	/* Was j=(exp)?5:EVP_CIPHER_key_length(c); */
+	k=EVP_CIPHER_iv_length(c);
+	er1= &(s->s3->client_random[0]);
+	er2= &(s->s3->server_random[0]);
+	if (	(which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) ||
+		(which == SSL3_CHANGE_CIPHER_SERVER_READ))
+		{
+		ms=  &(p[ 0]); n=i+i;
+		key= &(p[ n]); n+=j+j;
+		iv=  &(p[ n]); n+=k+k;
+		exp_label=(unsigned char *)TLS_MD_CLIENT_WRITE_KEY_CONST;
+		exp_label_len=TLS_MD_CLIENT_WRITE_KEY_CONST_SIZE;
+		client_write=1;
+		}
+	else
+		{
+		n=i;
+		ms=  &(p[ n]); n+=i+j;
+		key= &(p[ n]); n+=j+k;
+		iv=  &(p[ n]); n+=k;
+		exp_label=(unsigned char *)TLS_MD_SERVER_WRITE_KEY_CONST;
+		exp_label_len=TLS_MD_SERVER_WRITE_KEY_CONST_SIZE;
+		client_write=0;
+		}
+
+	if (n > s->s3->tmp.key_block_length)
+		{
+		SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,ERR_R_INTERNAL_ERROR);
+		goto err2;
+		}
+
+	memcpy(mac_secret,ms,i);
+	mac_key = EVP_PKEY_new_mac_key(mac_type, NULL,
+			mac_secret,*mac_secret_size);
+	EVP_DigestSignInit(mac_ctx,NULL,m,NULL,mac_key);
+	EVP_PKEY_free(mac_key);
+#ifdef TLS_DEBUG
+printf("which = %04X\nmac key=",which);
+{ int z; for (z=0; z<i; z++) printf("%02X%c",ms[z],((z+1)%16)?' ':'\n'); }
+#endif
+	if (is_export)
+		{
+		/* In here I set both the read and write key/iv to the
+		 * same value since only the correct one will be used :-).
+		 */
+		if (!tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
+				exp_label,exp_label_len,
+				s->s3->client_random,SSL3_RANDOM_SIZE,
+				s->s3->server_random,SSL3_RANDOM_SIZE,
+				NULL,0,NULL,0,
+				key,j,tmp1,tmp2,EVP_CIPHER_key_length(c)))
+			goto err2;
+		key=tmp1;
+
+		if (k > 0)
+			{
+			if (!tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
+					TLS_MD_IV_BLOCK_CONST,TLS_MD_IV_BLOCK_CONST_SIZE,
+					s->s3->client_random,SSL3_RANDOM_SIZE,
+					s->s3->server_random,SSL3_RANDOM_SIZE,
+					NULL,0,NULL,0,
+					empty,0,iv1,iv2,k*2))
+				goto err2;
+			if (client_write)
+				iv=iv1;
+			else
+				iv= &(iv1[k]);
+			}
+		}
+
+	s->session->key_arg_length=0;
+#ifdef KSSL_DEBUG
+	{
+        int i;
+	printf("EVP_CipherInit_ex(dd,c,key=,iv=,which)\n");
+	printf("\tkey= "); for (i=0; i<c->key_len; i++) printf("%02x", key[i]);
+	printf("\n");
+	printf("\t iv= "); for (i=0; i<c->iv_len; i++) printf("%02x", iv[i]);
+	printf("\n");
+	}
+#endif	/* KSSL_DEBUG */
+
+	EVP_CipherInit_ex(dd,c,NULL,key,iv,(which & SSL3_CC_WRITE));
+#ifdef TLS_DEBUG
+printf("which = %04X\nkey=",which);
+{ int z; for (z=0; z<EVP_CIPHER_key_length(c); z++) printf("%02X%c",key[z],((z+1)%16)?' ':'\n'); }
+printf("\niv=");
+{ int z; for (z=0; z<k; z++) printf("%02X%c",iv[z],((z+1)%16)?' ':'\n'); }
+printf("\n");
+#endif
+
+	OPENSSL_cleanse(tmp1,sizeof(tmp1));
+	OPENSSL_cleanse(tmp2,sizeof(tmp1));
+	OPENSSL_cleanse(iv1,sizeof(iv1));
+	OPENSSL_cleanse(iv2,sizeof(iv2));
+	return(1);
+err:
+	SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,ERR_R_MALLOC_FAILURE);
+err2:
+	return(0);
+	}
+
+int tls1_setup_key_block(SSL *s)
+	{
+	unsigned char *p1,*p2=NULL;
+	const EVP_CIPHER *c;
+	const EVP_MD *hash;
+	int num;
+	SSL_COMP *comp;
+	int mac_type= NID_undef,mac_secret_size=0;
+	int ret=0;
+
+#ifdef KSSL_DEBUG
+	printf ("tls1_setup_key_block()\n");
+#endif	/* KSSL_DEBUG */
+
+	if (s->s3->tmp.key_block_length != 0)
+		return(1);
+
+	if (!ssl_cipher_get_evp(s->session,&c,&hash,&mac_type,&mac_secret_size,&comp))
+		{
+		SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK,SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
+		return(0);
+		}
+
+	s->s3->tmp.new_sym_enc=c;
+	s->s3->tmp.new_hash=hash;
+	s->s3->tmp.new_mac_pkey_type = mac_type;
+	s->s3->tmp.new_mac_secret_size = mac_secret_size;
+	num=EVP_CIPHER_key_length(c)+mac_secret_size+EVP_CIPHER_iv_length(c);
+	num*=2;
+
+	ssl3_cleanup_key_block(s);
+
+	if ((p1=(unsigned char *)OPENSSL_malloc(num)) == NULL)
+		{
+		SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK,ERR_R_MALLOC_FAILURE);
+		goto err;
+		}
+
+	s->s3->tmp.key_block_length=num;
+	s->s3->tmp.key_block=p1;
+
+	if ((p2=(unsigned char *)OPENSSL_malloc(num)) == NULL)
+		{
+		SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK,ERR_R_MALLOC_FAILURE);
+		goto err;
+		}
+
+#ifdef TLS_DEBUG
+printf("client random\n");
+{ int z; for (z=0; z<SSL3_RANDOM_SIZE; z++) printf("%02X%c",s->s3->client_random[z],((z+1)%16)?' ':'\n'); }
+printf("server random\n");
+{ int z; for (z=0; z<SSL3_RANDOM_SIZE; z++) printf("%02X%c",s->s3->server_random[z],((z+1)%16)?' ':'\n'); }
+printf("pre-master\n");
+{ int z; for (z=0; z<s->session->master_key_length; z++) printf("%02X%c",s->session->master_key[z],((z+1)%16)?' ':'\n'); }
+#endif
+	if (!tls1_generate_key_block(s,p1,p2,num))
+		goto err;
+#ifdef TLS_DEBUG
+printf("\nkey block\n");
+{ int z; for (z=0; z<num; z++) printf("%02X%c",p1[z],((z+1)%16)?' ':'\n'); }
+#endif
+
+	if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS))
+		{
+		/* enable vulnerability countermeasure for CBC ciphers with
+		 * known-IV problem (http://www.openssl.org/~bodo/tls-cbc.txt)
+		 */
+		s->s3->need_empty_fragments = 1;
+
+		if (s->session->cipher != NULL)
+			{
+			if (s->session->cipher->algorithm_enc == SSL_eNULL)
+				s->s3->need_empty_fragments = 0;
+			
+#ifndef OPENSSL_NO_RC4
+			if (s->session->cipher->algorithm_enc == SSL_RC4)
+				s->s3->need_empty_fragments = 0;
+#endif
+			}
+		}
+		
+	ret = 1;
+err:
+	if (p2)
+		{
+		OPENSSL_cleanse(p2,num);
+		OPENSSL_free(p2);
+		}
+	return(ret);
+	}
+
+int tls1_enc(SSL *s, int send)
+	{
+	SSL3_RECORD *rec;
+	EVP_CIPHER_CTX *ds;
+	unsigned long l;
+	int bs,i,ii,j,k,n=0;
+	const EVP_CIPHER *enc;
+
+	if (send)
+		{
+		if (EVP_MD_CTX_md(s->write_hash))
+			{
+			n=EVP_MD_CTX_size(s->write_hash);
+			OPENSSL_assert(n >= 0);
+			}
+		ds=s->enc_write_ctx;
+		rec= &(s->s3->wrec);
+		if (s->enc_write_ctx == NULL)
+			enc=NULL;
+		else
+			enc=EVP_CIPHER_CTX_cipher(s->enc_write_ctx);
+		}
+	else
+		{
+		if (EVP_MD_CTX_md(s->read_hash))
+			{
+			n=EVP_MD_CTX_size(s->read_hash);
+			OPENSSL_assert(n >= 0);
+			}
+		ds=s->enc_read_ctx;
+		rec= &(s->s3->rrec);
+		if (s->enc_read_ctx == NULL)
+			enc=NULL;
+		else
+			enc=EVP_CIPHER_CTX_cipher(s->enc_read_ctx);
+		}
+
+#ifdef KSSL_DEBUG
+	printf("tls1_enc(%d)\n", send);
+#endif    /* KSSL_DEBUG */
+
+	if ((s->session == NULL) || (ds == NULL) ||
+		(enc == NULL))
+		{
+		memmove(rec->data,rec->input,rec->length);
+		rec->input=rec->data;
+		}
+	else
+		{
+		l=rec->length;
+		bs=EVP_CIPHER_block_size(ds->cipher);
+
+		if ((bs != 1) && send)
+			{
+			i=bs-((int)l%bs);
+
+			/* Add weird padding of upto 256 bytes */
+
+			/* we need to add 'i' padding bytes of value j */
+			j=i-1;
+			if (s->options & SSL_OP_TLS_BLOCK_PADDING_BUG)
+				{
+				if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG)
+					j++;
+				}
+			for (k=(int)l; k<(int)(l+i); k++)
+				rec->input[k]=j;
+			l+=i;
+			rec->length+=i;
+			}
+
+#ifdef KSSL_DEBUG
+		{
+                unsigned long ui;
+		printf("EVP_Cipher(ds=%p,rec->data=%p,rec->input=%p,l=%ld) ==>\n",
+                        ds,rec->data,rec->input,l);
+		printf("\tEVP_CIPHER_CTX: %d buf_len, %d key_len [%d %d], %d iv_len\n",
+                        ds->buf_len, ds->cipher->key_len,
+                        DES_KEY_SZ, DES_SCHEDULE_SZ,
+                        ds->cipher->iv_len);
+		printf("\t\tIV: ");
+		for (i=0; i<ds->cipher->iv_len; i++) printf("%02X", ds->iv[i]);
+		printf("\n");
+		printf("\trec->input=");
+		for (ui=0; ui<l; ui++) printf(" %02x", rec->input[ui]);
+		printf("\n");
+		}
+#endif	/* KSSL_DEBUG */
+
+		if (!send)
+			{
+			if (l == 0 || l%bs != 0)
+				{
+				SSLerr(SSL_F_TLS1_ENC,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG);
+				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECRYPTION_FAILED);
+				return 0;
+				}
+			}
+		
+		EVP_Cipher(ds,rec->data,rec->input,l);
+
+#ifdef KSSL_DEBUG
+		{
+                unsigned long i;
+                printf("\trec->data=");
+		for (i=0; i<l; i++)
+                        printf(" %02x", rec->data[i]);  printf("\n");
+                }
+#endif	/* KSSL_DEBUG */
+
+		if ((bs != 1) && !send)
+			{
+			ii=i=rec->data[l-1]; /* padding_length */
+			i++;
+			/* NB: if compression is in operation the first packet
+			 * may not be of even length so the padding bug check
+			 * cannot be performed. This bug workaround has been
+			 * around since SSLeay so hopefully it is either fixed
+			 * now or no buggy implementation supports compression 
+			 * [steve]
+			 */
+			if ( (s->options&SSL_OP_TLS_BLOCK_PADDING_BUG)
+				&& !s->expand)
+				{
+				/* First packet is even in size, so check */
+				if ((memcmp(s->s3->read_sequence,
+					"\0\0\0\0\0\0\0\0",8) == 0) && !(ii & 1))
+					s->s3->flags|=TLS1_FLAGS_TLS_PADDING_BUG;
+				if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG)
+					i--;
+				}
+			/* TLS 1.0 does not bound the number of padding bytes by the block size.
+			 * All of them must have value 'padding_length'. */
+			if (i > (int)rec->length)
+				{
+				/* Incorrect padding. SSLerr() and ssl3_alert are done
+				 * by caller: we don't want to reveal whether this is
+				 * a decryption error or a MAC verification failure
+				 * (see http://www.openssl.org/~bodo/tls-cbc.txt) */
+				return -1;
+				}
+			for (j=(int)(l-i); j<(int)l; j++)
+				{
+				if (rec->data[j] != ii)
+					{
+					/* Incorrect padding */
+					return -1;
+					}
+				}
+			rec->length-=i;
+			}
+		}
+	return(1);
+	}
+int tls1_cert_verify_mac(SSL *s, int md_nid, unsigned char *out)
+	{
+	unsigned int ret;
+	EVP_MD_CTX ctx, *d=NULL;
+	int i;
+
+	if (s->s3->handshake_buffer) 
+		if (!ssl3_digest_cached_records(s))
+			return 0;
+
+	for (i=0;i<SSL_MAX_DIGEST;i++) 
+		{
+		  if (s->s3->handshake_dgst[i]&&EVP_MD_CTX_type(s->s3->handshake_dgst[i])==md_nid) 
+		  	{
+		  	d=s->s3->handshake_dgst[i];
+			break;
+			}
+		}
+	if (!d) {
+		SSLerr(SSL_F_TLS1_CERT_VERIFY_MAC,SSL_R_NO_REQUIRED_DIGEST);
+		return 0;
+	}	
+
+	EVP_MD_CTX_init(&ctx);
+	EVP_MD_CTX_copy_ex(&ctx,d);
+	EVP_DigestFinal_ex(&ctx,out,&ret);
+	EVP_MD_CTX_cleanup(&ctx);
+	return((int)ret);
+	}
+
+int tls1_final_finish_mac(SSL *s,
+	     const char *str, int slen, unsigned char *out)
+	{
+	unsigned int i;
+	EVP_MD_CTX ctx;
+	unsigned char buf[2*EVP_MAX_MD_SIZE];
+	unsigned char *q,buf2[12];
+	int idx;
+	long mask;
+	int err=0;
+	const EVP_MD *md; 
+
+	q=buf;
+
+	if (s->s3->handshake_buffer) 
+		if (!ssl3_digest_cached_records(s))
+			return 0;
+
+	EVP_MD_CTX_init(&ctx);
+
+	for (idx=0;ssl_get_handshake_digest(idx,&mask,&md);idx++)
+		{
+		if (mask & s->s3->tmp.new_cipher->algorithm2)
+			{
+			int hashsize = EVP_MD_size(md);
+			if (hashsize < 0 || hashsize > (int)(sizeof buf - (size_t)(q-buf)))
+				{
+				/* internal error: 'buf' is too small for this cipersuite! */
+				err = 1;
+				}
+			else
+				{
+				EVP_MD_CTX_copy_ex(&ctx,s->s3->handshake_dgst[idx]);
+				EVP_DigestFinal_ex(&ctx,q,&i);
+				if (i != (unsigned int)hashsize) /* can't really happen */
+					err = 1;
+				q+=i;
+				}
+			}
+		}
+		
+	if (!tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
+			str,slen, buf,(int)(q-buf), NULL,0, NULL,0, NULL,0,
+			s->session->master_key,s->session->master_key_length,
+			out,buf2,sizeof buf2))
+		err = 1;
+	EVP_MD_CTX_cleanup(&ctx);
+
+	if (err)
+		return 0;
+	else
+		return sizeof buf2;
+	}
+
+int tls1_mac(SSL *ssl, unsigned char *md, int send)
+	{
+	SSL3_RECORD *rec;
+	unsigned char *mac_sec,*seq;
+	EVP_MD_CTX *hash;
+	size_t md_size;
+	int i;
+	EVP_MD_CTX hmac, *mac_ctx;
+	unsigned char buf[5]; 
+	int stream_mac = (send?(ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_STREAM):(ssl->mac_flags&SSL_MAC_FLAG_READ_MAC_STREAM));
+	int t;
+
+	if (send)
+		{
+		rec= &(ssl->s3->wrec);
+		mac_sec= &(ssl->s3->write_mac_secret[0]);
+		seq= &(ssl->s3->write_sequence[0]);
+		hash=ssl->write_hash;
+		}
+	else
+		{
+		rec= &(ssl->s3->rrec);
+		mac_sec= &(ssl->s3->read_mac_secret[0]);
+		seq= &(ssl->s3->read_sequence[0]);
+		hash=ssl->read_hash;
+		}
+
+	t=EVP_MD_CTX_size(hash);
+	OPENSSL_assert(t >= 0);
+	md_size=t;
+
+	buf[0]=rec->type;
+	buf[1]=(unsigned char)(ssl->version>>8);
+	buf[2]=(unsigned char)(ssl->version);
+	buf[3]=rec->length>>8;
+	buf[4]=rec->length&0xff;
+
+	/* I should fix this up TLS TLS TLS TLS TLS XXXXXXXX */
+	if (stream_mac) 
+		{
+			mac_ctx = hash;
+		}
+		else
+		{
+			EVP_MD_CTX_copy(&hmac,hash);
+			mac_ctx = &hmac;
+		}
+
+	if (ssl->version == DTLS1_VERSION || ssl->version == DTLS1_BAD_VER)
+		{
+		unsigned char dtlsseq[8],*p=dtlsseq;
+
+		s2n(send?ssl->d1->w_epoch:ssl->d1->r_epoch, p);
+		memcpy (p,&seq[2],6);
+
+		EVP_DigestSignUpdate(mac_ctx,dtlsseq,8);
+		}
+	else
+		EVP_DigestSignUpdate(mac_ctx,seq,8);
+
+	EVP_DigestSignUpdate(mac_ctx,buf,5);
+	EVP_DigestSignUpdate(mac_ctx,rec->input,rec->length);
+	t=EVP_DigestSignFinal(mac_ctx,md,&md_size);
+	OPENSSL_assert(t > 0);
+		
+	if (!stream_mac) EVP_MD_CTX_cleanup(&hmac);
+#ifdef TLS_DEBUG
+printf("sec=");
+{unsigned int z; for (z=0; z<md_size; z++) printf("%02X ",mac_sec[z]); printf("\n"); }
+printf("seq=");
+{int z; for (z=0; z<8; z++) printf("%02X ",seq[z]); printf("\n"); }
+printf("buf=");
+{int z; for (z=0; z<5; z++) printf("%02X ",buf[z]); printf("\n"); }
+printf("rec=");
+{unsigned int z; for (z=0; z<rec->length; z++) printf("%02X ",buf[z]); printf("\n"); }
+#endif
+
+	if (ssl->version != DTLS1_VERSION && ssl->version != DTLS1_BAD_VER)
+		{
+		for (i=7; i>=0; i--)
+			{
+			++seq[i];
+			if (seq[i] != 0) break; 
+			}
+		}
+
+#ifdef TLS_DEBUG
+{unsigned int z; for (z=0; z<md_size; z++) printf("%02X ",md[z]); printf("\n"); }
+#endif
+	return(md_size);
+	}
+
+int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
+	     int len)
+	{
+	unsigned char buff[SSL_MAX_MASTER_KEY_LENGTH];
+	const void *co = NULL, *so = NULL;
+	int col = 0, sol = 0;
+
+#ifdef KSSL_DEBUG
+	printf ("tls1_generate_master_secret(%p,%p, %p, %d)\n", s,out, p,len);
+#endif	/* KSSL_DEBUG */
+
+#ifdef TLSEXT_TYPE_opaque_prf_input
+	if (s->s3->client_opaque_prf_input != NULL && s->s3->server_opaque_prf_input != NULL &&
+	    s->s3->client_opaque_prf_input_len > 0 &&
+	    s->s3->client_opaque_prf_input_len == s->s3->server_opaque_prf_input_len)
+		{
+		co = s->s3->client_opaque_prf_input;
+		col = s->s3->server_opaque_prf_input_len;
+		so = s->s3->server_opaque_prf_input;
+		sol = s->s3->client_opaque_prf_input_len; /* must be same as col (see draft-rescorla-tls-opaque-prf-input-00.txt, section 3.1) */
+		}
+#endif
+
+	tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
+		TLS_MD_MASTER_SECRET_CONST,TLS_MD_MASTER_SECRET_CONST_SIZE,
+		s->s3->client_random,SSL3_RANDOM_SIZE,
+		co, col,
+		s->s3->server_random,SSL3_RANDOM_SIZE,
+		so, sol,
+		p,len,
+		s->session->master_key,buff,sizeof buff);
+
+#ifdef KSSL_DEBUG
+	printf ("tls1_generate_master_secret() complete\n");
+#endif	/* KSSL_DEBUG */
+	return(SSL3_MASTER_SECRET_SIZE);
+	}
+
+int tls1_alert_code(int code)
+	{
+	switch (code)
+		{
+	case SSL_AD_CLOSE_NOTIFY:	return(SSL3_AD_CLOSE_NOTIFY);
+	case SSL_AD_UNEXPECTED_MESSAGE:	return(SSL3_AD_UNEXPECTED_MESSAGE);
+	case SSL_AD_BAD_RECORD_MAC:	return(SSL3_AD_BAD_RECORD_MAC);
+	case SSL_AD_DECRYPTION_FAILED:	return(TLS1_AD_DECRYPTION_FAILED);
+	case SSL_AD_RECORD_OVERFLOW:	return(TLS1_AD_RECORD_OVERFLOW);
+	case SSL_AD_DECOMPRESSION_FAILURE:return(SSL3_AD_DECOMPRESSION_FAILURE);
+	case SSL_AD_HANDSHAKE_FAILURE:	return(SSL3_AD_HANDSHAKE_FAILURE);
+	case SSL_AD_NO_CERTIFICATE:	return(-1);
+	case SSL_AD_BAD_CERTIFICATE:	return(SSL3_AD_BAD_CERTIFICATE);
+	case SSL_AD_UNSUPPORTED_CERTIFICATE:return(SSL3_AD_UNSUPPORTED_CERTIFICATE);
+	case SSL_AD_CERTIFICATE_REVOKED:return(SSL3_AD_CERTIFICATE_REVOKED);
+	case SSL_AD_CERTIFICATE_EXPIRED:return(SSL3_AD_CERTIFICATE_EXPIRED);
+	case SSL_AD_CERTIFICATE_UNKNOWN:return(SSL3_AD_CERTIFICATE_UNKNOWN);
+	case SSL_AD_ILLEGAL_PARAMETER:	return(SSL3_AD_ILLEGAL_PARAMETER);
+	case SSL_AD_UNKNOWN_CA:		return(TLS1_AD_UNKNOWN_CA);
+	case SSL_AD_ACCESS_DENIED:	return(TLS1_AD_ACCESS_DENIED);
+	case SSL_AD_DECODE_ERROR:	return(TLS1_AD_DECODE_ERROR);
+	case SSL_AD_DECRYPT_ERROR:	return(TLS1_AD_DECRYPT_ERROR);
+	case SSL_AD_EXPORT_RESTRICTION:	return(TLS1_AD_EXPORT_RESTRICTION);
+	case SSL_AD_PROTOCOL_VERSION:	return(TLS1_AD_PROTOCOL_VERSION);
+	case SSL_AD_INSUFFICIENT_SECURITY:return(TLS1_AD_INSUFFICIENT_SECURITY);
+	case SSL_AD_INTERNAL_ERROR:	return(TLS1_AD_INTERNAL_ERROR);
+	case SSL_AD_USER_CANCELLED:	return(TLS1_AD_USER_CANCELLED);
+	case SSL_AD_NO_RENEGOTIATION:	return(TLS1_AD_NO_RENEGOTIATION);
+	case SSL_AD_UNSUPPORTED_EXTENSION: return(TLS1_AD_UNSUPPORTED_EXTENSION);
+	case SSL_AD_CERTIFICATE_UNOBTAINABLE: return(TLS1_AD_CERTIFICATE_UNOBTAINABLE);
+	case SSL_AD_UNRECOGNIZED_NAME:	return(TLS1_AD_UNRECOGNIZED_NAME);
+	case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE: return(TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE);
+	case SSL_AD_BAD_CERTIFICATE_HASH_VALUE: return(TLS1_AD_BAD_CERTIFICATE_HASH_VALUE);
+	case SSL_AD_UNKNOWN_PSK_IDENTITY:return(TLS1_AD_UNKNOWN_PSK_IDENTITY);
+#if 0 /* not appropriate for TLS, not used for DTLS */
+	case DTLS1_AD_MISSING_HANDSHAKE_MESSAGE: return 
+					  (DTLS1_AD_MISSING_HANDSHAKE_MESSAGE);
+#endif
+	default:			return(-1);
+		}
+	}
+
diff --git a/lib/openssl/ssl/t1_lib.c b/lib/openssl/ssl/t1_lib.c
new file mode 100644
index 0000000..eac2deb
--- /dev/null
+++ b/lib/openssl/ssl/t1_lib.c
@@ -0,0 +1,1739 @@
+/* ssl/t1_lib.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <stdio.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/ocsp.h>
+#include "ssl_locl.h"
+
+const char tls1_version_str[]="TLSv1" OPENSSL_VERSION_PTEXT;
+
+#ifndef OPENSSL_NO_TLSEXT
+static int tls_decrypt_ticket(SSL *s, const unsigned char *tick, int ticklen,
+				const unsigned char *sess_id, int sesslen,
+				SSL_SESSION **psess);
+#endif
+
+SSL3_ENC_METHOD TLSv1_enc_data={
+	tls1_enc,
+	tls1_mac,
+	tls1_setup_key_block,
+	tls1_generate_master_secret,
+	tls1_change_cipher_state,
+	tls1_final_finish_mac,
+	TLS1_FINISH_MAC_LENGTH,
+	tls1_cert_verify_mac,
+	TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE,
+	TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE,
+	tls1_alert_code,
+	};
+
+long tls1_default_timeout(void)
+	{
+	/* 2 hours, the 24 hours mentioned in the TLSv1 spec
+	 * is way too long for http, the cache would over fill */
+	return(60*60*2);
+	}
+
+int tls1_new(SSL *s)
+	{
+	if (!ssl3_new(s)) return(0);
+	s->method->ssl_clear(s);
+	return(1);
+	}
+
+void tls1_free(SSL *s)
+	{
+#ifndef OPENSSL_NO_TLSEXT
+	if (s->tlsext_session_ticket)
+		{
+		OPENSSL_free(s->tlsext_session_ticket);
+		}
+#endif /* OPENSSL_NO_TLSEXT */
+	ssl3_free(s);
+	}
+
+void tls1_clear(SSL *s)
+	{
+	ssl3_clear(s);
+	s->version=TLS1_VERSION;
+	}
+
+#ifndef OPENSSL_NO_EC
+static int nid_list[] =
+	{
+		NID_sect163k1, /* sect163k1 (1) */
+		NID_sect163r1, /* sect163r1 (2) */
+		NID_sect163r2, /* sect163r2 (3) */
+		NID_sect193r1, /* sect193r1 (4) */ 
+		NID_sect193r2, /* sect193r2 (5) */ 
+		NID_sect233k1, /* sect233k1 (6) */
+		NID_sect233r1, /* sect233r1 (7) */ 
+		NID_sect239k1, /* sect239k1 (8) */ 
+		NID_sect283k1, /* sect283k1 (9) */
+		NID_sect283r1, /* sect283r1 (10) */ 
+		NID_sect409k1, /* sect409k1 (11) */ 
+		NID_sect409r1, /* sect409r1 (12) */
+		NID_sect571k1, /* sect571k1 (13) */ 
+		NID_sect571r1, /* sect571r1 (14) */ 
+		NID_secp160k1, /* secp160k1 (15) */
+		NID_secp160r1, /* secp160r1 (16) */ 
+		NID_secp160r2, /* secp160r2 (17) */ 
+		NID_secp192k1, /* secp192k1 (18) */
+		NID_X9_62_prime192v1, /* secp192r1 (19) */ 
+		NID_secp224k1, /* secp224k1 (20) */ 
+		NID_secp224r1, /* secp224r1 (21) */
+		NID_secp256k1, /* secp256k1 (22) */ 
+		NID_X9_62_prime256v1, /* secp256r1 (23) */ 
+		NID_secp384r1, /* secp384r1 (24) */
+		NID_secp521r1  /* secp521r1 (25) */	
+	};
+	
+int tls1_ec_curve_id2nid(int curve_id)
+	{
+	/* ECC curves from draft-ietf-tls-ecc-12.txt (Oct. 17, 2005) */
+	if ((curve_id < 1) || ((unsigned int)curve_id >
+				sizeof(nid_list)/sizeof(nid_list[0])))
+		return 0;
+	return nid_list[curve_id-1];
+	}
+
+int tls1_ec_nid2curve_id(int nid)
+	{
+	/* ECC curves from draft-ietf-tls-ecc-12.txt (Oct. 17, 2005) */
+	switch (nid)
+		{
+	case NID_sect163k1: /* sect163k1 (1) */
+		return 1;
+	case NID_sect163r1: /* sect163r1 (2) */
+		return 2;
+	case NID_sect163r2: /* sect163r2 (3) */
+		return 3;
+	case NID_sect193r1: /* sect193r1 (4) */ 
+		return 4;
+	case NID_sect193r2: /* sect193r2 (5) */ 
+		return 5;
+	case NID_sect233k1: /* sect233k1 (6) */
+		return 6;
+	case NID_sect233r1: /* sect233r1 (7) */ 
+		return 7;
+	case NID_sect239k1: /* sect239k1 (8) */ 
+		return 8;
+	case NID_sect283k1: /* sect283k1 (9) */
+		return 9;
+	case NID_sect283r1: /* sect283r1 (10) */ 
+		return 10;
+	case NID_sect409k1: /* sect409k1 (11) */ 
+		return 11;
+	case NID_sect409r1: /* sect409r1 (12) */
+		return 12;
+	case NID_sect571k1: /* sect571k1 (13) */ 
+		return 13;
+	case NID_sect571r1: /* sect571r1 (14) */ 
+		return 14;
+	case NID_secp160k1: /* secp160k1 (15) */
+		return 15;
+	case NID_secp160r1: /* secp160r1 (16) */ 
+		return 16;
+	case NID_secp160r2: /* secp160r2 (17) */ 
+		return 17;
+	case NID_secp192k1: /* secp192k1 (18) */
+		return 18;
+	case NID_X9_62_prime192v1: /* secp192r1 (19) */ 
+		return 19;
+	case NID_secp224k1: /* secp224k1 (20) */ 
+		return 20;
+	case NID_secp224r1: /* secp224r1 (21) */
+		return 21;
+	case NID_secp256k1: /* secp256k1 (22) */ 
+		return 22;
+	case NID_X9_62_prime256v1: /* secp256r1 (23) */ 
+		return 23;
+	case NID_secp384r1: /* secp384r1 (24) */
+		return 24;
+	case NID_secp521r1:  /* secp521r1 (25) */	
+		return 25;
+	default:
+		return 0;
+		}
+	}
+#endif /* OPENSSL_NO_EC */
+
+#ifndef OPENSSL_NO_TLSEXT
+unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit)
+	{
+	int extdatalen=0;
+	unsigned char *ret = p;
+
+	/* don't add extensions for SSLv3 unless doing secure renegotiation */
+	if (s->client_version == SSL3_VERSION
+					&& !s->s3->send_connection_binding)
+		return p;
+
+	ret+=2;
+
+	if (ret>=limit) return NULL; /* this really never occurs, but ... */
+
+ 	if (s->tlsext_hostname != NULL)
+		{ 
+		/* Add TLS extension servername to the Client Hello message */
+		unsigned long size_str;
+		long lenmax; 
+
+		/* check for enough space.
+		   4 for the servername type and entension length
+		   2 for servernamelist length
+		   1 for the hostname type
+		   2 for hostname length
+		   + hostname length 
+		*/
+		   
+		if ((lenmax = limit - ret - 9) < 0 
+		    || (size_str = strlen(s->tlsext_hostname)) > (unsigned long)lenmax) 
+			return NULL;
+			
+		/* extension type and length */
+		s2n(TLSEXT_TYPE_server_name,ret); 
+		s2n(size_str+5,ret);
+		
+		/* length of servername list */
+		s2n(size_str+3,ret);
+	
+		/* hostname type, length and hostname */
+		*(ret++) = (unsigned char) TLSEXT_NAMETYPE_host_name;
+		s2n(size_str,ret);
+		memcpy(ret, s->tlsext_hostname, size_str);
+		ret+=size_str;
+		}
+
+        /* Add RI if renegotiating */
+        if (s->new_session)
+          {
+          int el;
+          
+          if(!ssl_add_clienthello_renegotiate_ext(s, 0, &el, 0))
+              {
+              SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+              return NULL;
+              }
+
+          if((limit - p - 4 - el) < 0) return NULL;
+          
+          s2n(TLSEXT_TYPE_renegotiate,ret);
+          s2n(el,ret);
+
+          if(!ssl_add_clienthello_renegotiate_ext(s, ret, &el, el))
+              {
+              SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+              return NULL;
+              }
+
+          ret += el;
+        }
+
+#ifndef OPENSSL_NO_EC
+	if (s->tlsext_ecpointformatlist != NULL &&
+	    s->version != DTLS1_VERSION)
+		{
+		/* Add TLS extension ECPointFormats to the ClientHello message */
+		long lenmax; 
+
+		if ((lenmax = limit - ret - 5) < 0) return NULL; 
+		if (s->tlsext_ecpointformatlist_length > (unsigned long)lenmax) return NULL;
+		if (s->tlsext_ecpointformatlist_length > 255)
+			{
+			SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+			return NULL;
+			}
+		
+		s2n(TLSEXT_TYPE_ec_point_formats,ret);
+		s2n(s->tlsext_ecpointformatlist_length + 1,ret);
+		*(ret++) = (unsigned char) s->tlsext_ecpointformatlist_length;
+		memcpy(ret, s->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist_length);
+		ret+=s->tlsext_ecpointformatlist_length;
+		}
+	if (s->tlsext_ellipticcurvelist != NULL &&
+	    s->version != DTLS1_VERSION)
+		{
+		/* Add TLS extension EllipticCurves to the ClientHello message */
+		long lenmax; 
+
+		if ((lenmax = limit - ret - 6) < 0) return NULL; 
+		if (s->tlsext_ellipticcurvelist_length > (unsigned long)lenmax) return NULL;
+		if (s->tlsext_ellipticcurvelist_length > 65532)
+			{
+			SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+			return NULL;
+			}
+		
+		s2n(TLSEXT_TYPE_elliptic_curves,ret);
+		s2n(s->tlsext_ellipticcurvelist_length + 2, ret);
+
+		/* NB: draft-ietf-tls-ecc-12.txt uses a one-byte prefix for
+		 * elliptic_curve_list, but the examples use two bytes.
+		 * http://www1.ietf.org/mail-archive/web/tls/current/msg00538.html
+		 * resolves this to two bytes.
+		 */
+		s2n(s->tlsext_ellipticcurvelist_length, ret);
+		memcpy(ret, s->tlsext_ellipticcurvelist, s->tlsext_ellipticcurvelist_length);
+		ret+=s->tlsext_ellipticcurvelist_length;
+		}
+#endif /* OPENSSL_NO_EC */
+
+	if (!(SSL_get_options(s) & SSL_OP_NO_TICKET))
+		{
+		int ticklen;
+		if (!s->new_session && s->session && s->session->tlsext_tick)
+			ticklen = s->session->tlsext_ticklen;
+		else if (s->session && s->tlsext_session_ticket &&
+			 s->tlsext_session_ticket->data)
+			{
+			ticklen = s->tlsext_session_ticket->length;
+			s->session->tlsext_tick = OPENSSL_malloc(ticklen);
+			if (!s->session->tlsext_tick)
+				return NULL;
+			memcpy(s->session->tlsext_tick,
+			       s->tlsext_session_ticket->data,
+			       ticklen);
+			s->session->tlsext_ticklen = ticklen;
+			}
+		else
+			ticklen = 0;
+		if (ticklen == 0 && s->tlsext_session_ticket &&
+		    s->tlsext_session_ticket->data == NULL)
+			goto skip_ext;
+		/* Check for enough room 2 for extension type, 2 for len
+ 		 * rest for ticket
+  		 */
+		if ((long)(limit - ret - 4 - ticklen) < 0) return NULL;
+		s2n(TLSEXT_TYPE_session_ticket,ret); 
+		s2n(ticklen,ret);
+		if (ticklen)
+			{
+			memcpy(ret, s->session->tlsext_tick, ticklen);
+			ret += ticklen;
+			}
+		}
+		skip_ext:
+
+#ifdef TLSEXT_TYPE_opaque_prf_input
+	if (s->s3->client_opaque_prf_input != NULL &&
+	    s->version != DTLS1_VERSION)
+		{
+		size_t col = s->s3->client_opaque_prf_input_len;
+		
+		if ((long)(limit - ret - 6 - col < 0))
+			return NULL;
+		if (col > 0xFFFD) /* can't happen */
+			return NULL;
+
+		s2n(TLSEXT_TYPE_opaque_prf_input, ret); 
+		s2n(col + 2, ret);
+		s2n(col, ret);
+		memcpy(ret, s->s3->client_opaque_prf_input, col);
+		ret += col;
+		}
+#endif
+
+	if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp &&
+	    s->version != DTLS1_VERSION)
+		{
+		int i;
+		long extlen, idlen, itmp;
+		OCSP_RESPID *id;
+
+		idlen = 0;
+		for (i = 0; i < sk_OCSP_RESPID_num(s->tlsext_ocsp_ids); i++)
+			{
+			id = sk_OCSP_RESPID_value(s->tlsext_ocsp_ids, i);
+			itmp = i2d_OCSP_RESPID(id, NULL);
+			if (itmp <= 0)
+				return NULL;
+			idlen += itmp + 2;
+			}
+
+		if (s->tlsext_ocsp_exts)
+			{
+			extlen = i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, NULL);
+			if (extlen < 0)
+				return NULL;
+			}
+		else
+			extlen = 0;
+			
+		if ((long)(limit - ret - 7 - extlen - idlen) < 0) return NULL;
+		s2n(TLSEXT_TYPE_status_request, ret);
+		if (extlen + idlen > 0xFFF0)
+			return NULL;
+		s2n(extlen + idlen + 5, ret);
+		*(ret++) = TLSEXT_STATUSTYPE_ocsp;
+		s2n(idlen, ret);
+		for (i = 0; i < sk_OCSP_RESPID_num(s->tlsext_ocsp_ids); i++)
+			{
+			/* save position of id len */
+			unsigned char *q = ret;
+			id = sk_OCSP_RESPID_value(s->tlsext_ocsp_ids, i);
+			/* skip over id len */
+			ret += 2;
+			itmp = i2d_OCSP_RESPID(id, &ret);
+			/* write id len */
+			s2n(itmp, q);
+			}
+		s2n(extlen, ret);
+		if (extlen > 0)
+			i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, &ret);
+		}
+
+	if ((extdatalen = ret-p-2)== 0) 
+		return p;
+
+	s2n(extdatalen,p);
+	return ret;
+	}
+
+unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit)
+	{
+	int extdatalen=0;
+	unsigned char *ret = p;
+
+	/* don't add extensions for SSLv3, unless doing secure renegotiation */
+	if (s->version == SSL3_VERSION && !s->s3->send_connection_binding)
+		return p;
+	
+	ret+=2;
+	if (ret>=limit) return NULL; /* this really never occurs, but ... */
+
+	if (!s->hit && s->servername_done == 1 && s->session->tlsext_hostname != NULL)
+		{ 
+		if ((long)(limit - ret - 4) < 0) return NULL; 
+
+		s2n(TLSEXT_TYPE_server_name,ret);
+		s2n(0,ret);
+		}
+
+	if(s->s3->send_connection_binding)
+        {
+          int el;
+          
+          if(!ssl_add_serverhello_renegotiate_ext(s, 0, &el, 0))
+              {
+              SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+              return NULL;
+              }
+
+          if((limit - p - 4 - el) < 0) return NULL;
+          
+          s2n(TLSEXT_TYPE_renegotiate,ret);
+          s2n(el,ret);
+
+          if(!ssl_add_serverhello_renegotiate_ext(s, ret, &el, el))
+              {
+              SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+              return NULL;
+              }
+
+          ret += el;
+        }
+
+#ifndef OPENSSL_NO_EC
+	if (s->tlsext_ecpointformatlist != NULL &&
+	    s->version != DTLS1_VERSION)
+		{
+		/* Add TLS extension ECPointFormats to the ServerHello message */
+		long lenmax; 
+
+		if ((lenmax = limit - ret - 5) < 0) return NULL; 
+		if (s->tlsext_ecpointformatlist_length > (unsigned long)lenmax) return NULL;
+		if (s->tlsext_ecpointformatlist_length > 255)
+			{
+			SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+			return NULL;
+			}
+		
+		s2n(TLSEXT_TYPE_ec_point_formats,ret);
+		s2n(s->tlsext_ecpointformatlist_length + 1,ret);
+		*(ret++) = (unsigned char) s->tlsext_ecpointformatlist_length;
+		memcpy(ret, s->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist_length);
+		ret+=s->tlsext_ecpointformatlist_length;
+
+		}
+	/* Currently the server should not respond with a SupportedCurves extension */
+#endif /* OPENSSL_NO_EC */
+
+	if (s->tlsext_ticket_expected
+		&& !(SSL_get_options(s) & SSL_OP_NO_TICKET)) 
+		{ 
+		if ((long)(limit - ret - 4) < 0) return NULL; 
+		s2n(TLSEXT_TYPE_session_ticket,ret);
+		s2n(0,ret);
+		}
+
+	if (s->tlsext_status_expected)
+		{ 
+		if ((long)(limit - ret - 4) < 0) return NULL; 
+		s2n(TLSEXT_TYPE_status_request,ret);
+		s2n(0,ret);
+		}
+
+#ifdef TLSEXT_TYPE_opaque_prf_input
+	if (s->s3->server_opaque_prf_input != NULL &&
+	    s->version != DTLS1_VERSION)
+		{
+		size_t sol = s->s3->server_opaque_prf_input_len;
+		
+		if ((long)(limit - ret - 6 - sol) < 0)
+			return NULL;
+		if (sol > 0xFFFD) /* can't happen */
+			return NULL;
+
+		s2n(TLSEXT_TYPE_opaque_prf_input, ret); 
+		s2n(sol + 2, ret);
+		s2n(sol, ret);
+		memcpy(ret, s->s3->server_opaque_prf_input, sol);
+		ret += sol;
+		}
+#endif
+	if (((s->s3->tmp.new_cipher->id & 0xFFFF)==0x80 || (s->s3->tmp.new_cipher->id & 0xFFFF)==0x81) 
+		&& (SSL_get_options(s) & SSL_OP_CRYPTOPRO_TLSEXT_BUG))
+		{ const unsigned char cryptopro_ext[36] = {
+			0xfd, 0xe8, /*65000*/
+			0x00, 0x20, /*32 bytes length*/
+			0x30, 0x1e, 0x30, 0x08, 0x06, 0x06, 0x2a, 0x85, 
+			0x03,   0x02, 0x02, 0x09, 0x30, 0x08, 0x06, 0x06, 
+			0x2a, 0x85, 0x03, 0x02, 0x02, 0x16, 0x30, 0x08, 
+			0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x17};
+			if (limit-ret<36) return NULL;
+			memcpy(ret,cryptopro_ext,36);
+			ret+=36;
+
+		}
+
+	if ((extdatalen = ret-p-2)== 0) 
+		return p;
+
+	s2n(extdatalen,p);
+	return ret;
+	}
+
+int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al)
+	{
+	unsigned short type;
+	unsigned short size;
+	unsigned short len;
+	unsigned char *data = *p;
+	int renegotiate_seen = 0;
+
+	s->servername_done = 0;
+	s->tlsext_status_type = -1;
+
+	if (data >= (d+n-2))
+		goto ri_check;
+	n2s(data,len);
+
+	if (data > (d+n-len)) 
+		goto ri_check;
+
+	while (data <= (d+n-4))
+		{
+		n2s(data,type);
+		n2s(data,size);
+
+		if (data+size > (d+n))
+	   		goto ri_check;
+#if 0
+		fprintf(stderr,"Received extension type %d size %d\n",type,size);
+#endif
+		if (s->tlsext_debug_cb)
+			s->tlsext_debug_cb(s, 0, type, data, size,
+						s->tlsext_debug_arg);
+/* The servername extension is treated as follows:
+
+   - Only the hostname type is supported with a maximum length of 255.
+   - The servername is rejected if too long or if it contains zeros,
+     in which case an fatal alert is generated.
+   - The servername field is maintained together with the session cache.
+   - When a session is resumed, the servername call back invoked in order
+     to allow the application to position itself to the right context. 
+   - The servername is acknowledged if it is new for a session or when 
+     it is identical to a previously used for the same session. 
+     Applications can control the behaviour.  They can at any time
+     set a 'desirable' servername for a new SSL object. This can be the
+     case for example with HTTPS when a Host: header field is received and
+     a renegotiation is requested. In this case, a possible servername
+     presented in the new client hello is only acknowledged if it matches
+     the value of the Host: field. 
+   - Applications must  use SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
+     if they provide for changing an explicit servername context for the session,
+     i.e. when the session has been established with a servername extension. 
+   - On session reconnect, the servername extension may be absent. 
+
+*/      
+
+		if (type == TLSEXT_TYPE_server_name)
+			{
+			unsigned char *sdata;
+			int servname_type;
+			int dsize; 
+		
+			if (size < 2) 
+				{
+				*al = SSL_AD_DECODE_ERROR;
+				return 0;
+				}
+			n2s(data,dsize);  
+			size -= 2;
+			if (dsize > size  ) 
+				{
+				*al = SSL_AD_DECODE_ERROR;
+				return 0;
+				} 
+
+			sdata = data;
+			while (dsize > 3) 
+				{
+	 			servname_type = *(sdata++); 
+				n2s(sdata,len);
+				dsize -= 3;
+
+				if (len > dsize) 
+					{
+					*al = SSL_AD_DECODE_ERROR;
+					return 0;
+					}
+				if (s->servername_done == 0)
+				switch (servname_type)
+					{
+				case TLSEXT_NAMETYPE_host_name:
+					if (!s->hit)
+						{
+						if(s->session->tlsext_hostname)
+							{
+							*al = SSL_AD_DECODE_ERROR;
+							return 0;
+							}
+						if (len > TLSEXT_MAXLEN_host_name)
+							{
+							*al = TLS1_AD_UNRECOGNIZED_NAME;
+							return 0;
+							}
+						if ((s->session->tlsext_hostname = OPENSSL_malloc(len+1)) == NULL)
+							{
+							*al = TLS1_AD_INTERNAL_ERROR;
+							return 0;
+							}
+						memcpy(s->session->tlsext_hostname, sdata, len);
+						s->session->tlsext_hostname[len]='\0';
+						if (strlen(s->session->tlsext_hostname) != len) {
+							OPENSSL_free(s->session->tlsext_hostname);
+							s->session->tlsext_hostname = NULL;
+							*al = TLS1_AD_UNRECOGNIZED_NAME;
+							return 0;
+						}
+						s->servername_done = 1; 
+
+						}
+					else 
+						s->servername_done = s->session->tlsext_hostname
+							&& strlen(s->session->tlsext_hostname) == len 
+							&& strncmp(s->session->tlsext_hostname, (char *)sdata, len) == 0;
+					
+					break;
+
+				default:
+					break;
+					}
+				 
+				dsize -= len;
+				}
+			if (dsize != 0) 
+				{
+				*al = SSL_AD_DECODE_ERROR;
+				return 0;
+				}
+
+			}
+
+#ifndef OPENSSL_NO_EC
+		else if (type == TLSEXT_TYPE_ec_point_formats &&
+	             s->version != DTLS1_VERSION)
+			{
+			unsigned char *sdata = data;
+			int ecpointformatlist_length = *(sdata++);
+
+			if (ecpointformatlist_length != size - 1)
+				{
+				*al = TLS1_AD_DECODE_ERROR;
+				return 0;
+				}
+			if (!s->hit)
+				{
+				if(s->session->tlsext_ecpointformatlist)
+					{
+					*al = TLS1_AD_DECODE_ERROR;
+					return 0;
+					}
+				s->session->tlsext_ecpointformatlist_length = 0;
+				if ((s->session->tlsext_ecpointformatlist = OPENSSL_malloc(ecpointformatlist_length)) == NULL)
+					{
+					*al = TLS1_AD_INTERNAL_ERROR;
+					return 0;
+					}
+				s->session->tlsext_ecpointformatlist_length = ecpointformatlist_length;
+				memcpy(s->session->tlsext_ecpointformatlist, sdata, ecpointformatlist_length);
+				}
+#if 0
+			fprintf(stderr,"ssl_parse_clienthello_tlsext s->session->tlsext_ecpointformatlist (length=%i) ", s->session->tlsext_ecpointformatlist_length);
+			sdata = s->session->tlsext_ecpointformatlist;
+			for (i = 0; i < s->session->tlsext_ecpointformatlist_length; i++)
+				fprintf(stderr,"%i ",*(sdata++));
+			fprintf(stderr,"\n");
+#endif
+			}
+		else if (type == TLSEXT_TYPE_elliptic_curves &&
+	             s->version != DTLS1_VERSION)
+			{
+			unsigned char *sdata = data;
+			int ellipticcurvelist_length = (*(sdata++) << 8);
+			ellipticcurvelist_length += (*(sdata++));
+
+			if (ellipticcurvelist_length != size - 2)
+				{
+				*al = TLS1_AD_DECODE_ERROR;
+				return 0;
+				}
+			if (!s->hit)
+				{
+				if(s->session->tlsext_ellipticcurvelist)
+					{
+					*al = TLS1_AD_DECODE_ERROR;
+					return 0;
+					}
+				s->session->tlsext_ellipticcurvelist_length = 0;
+				if ((s->session->tlsext_ellipticcurvelist = OPENSSL_malloc(ellipticcurvelist_length)) == NULL)
+					{
+					*al = TLS1_AD_INTERNAL_ERROR;
+					return 0;
+					}
+				s->session->tlsext_ellipticcurvelist_length = ellipticcurvelist_length;
+				memcpy(s->session->tlsext_ellipticcurvelist, sdata, ellipticcurvelist_length);
+				}
+#if 0
+			fprintf(stderr,"ssl_parse_clienthello_tlsext s->session->tlsext_ellipticcurvelist (length=%i) ", s->session->tlsext_ellipticcurvelist_length);
+			sdata = s->session->tlsext_ellipticcurvelist;
+			for (i = 0; i < s->session->tlsext_ellipticcurvelist_length; i++)
+				fprintf(stderr,"%i ",*(sdata++));
+			fprintf(stderr,"\n");
+#endif
+			}
+#endif /* OPENSSL_NO_EC */
+#ifdef TLSEXT_TYPE_opaque_prf_input
+		else if (type == TLSEXT_TYPE_opaque_prf_input &&
+	             s->version != DTLS1_VERSION)
+			{
+			unsigned char *sdata = data;
+
+			if (size < 2)
+				{
+				*al = SSL_AD_DECODE_ERROR;
+				return 0;
+				}
+			n2s(sdata, s->s3->client_opaque_prf_input_len);
+			if (s->s3->client_opaque_prf_input_len != size - 2)
+				{
+				*al = SSL_AD_DECODE_ERROR;
+				return 0;
+				}
+
+			if (s->s3->client_opaque_prf_input != NULL) /* shouldn't really happen */
+				OPENSSL_free(s->s3->client_opaque_prf_input);
+			if (s->s3->client_opaque_prf_input_len == 0)
+				s->s3->client_opaque_prf_input = OPENSSL_malloc(1); /* dummy byte just to get non-NULL */
+			else
+				s->s3->client_opaque_prf_input = BUF_memdup(sdata, s->s3->client_opaque_prf_input_len);
+			if (s->s3->client_opaque_prf_input == NULL)
+				{
+				*al = TLS1_AD_INTERNAL_ERROR;
+				return 0;
+				}
+			}
+#endif
+		else if (type == TLSEXT_TYPE_session_ticket)
+			{
+			if (s->tls_session_ticket_ext_cb &&
+			    !s->tls_session_ticket_ext_cb(s, data, size, s->tls_session_ticket_ext_cb_arg))
+				{
+				*al = TLS1_AD_INTERNAL_ERROR;
+				return 0;
+				}
+			}
+		else if (type == TLSEXT_TYPE_renegotiate)
+			{
+			if(!ssl_parse_clienthello_renegotiate_ext(s, data, size, al))
+				return 0;
+			renegotiate_seen = 1;
+			}
+		else if (type == TLSEXT_TYPE_status_request &&
+		         s->version != DTLS1_VERSION && s->ctx->tlsext_status_cb)
+			{
+		
+			if (size < 5) 
+				{
+				*al = SSL_AD_DECODE_ERROR;
+				return 0;
+				}
+
+			s->tlsext_status_type = *data++;
+			size--;
+			if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp)
+				{
+				const unsigned char *sdata;
+				int dsize;
+				/* Read in responder_id_list */
+				n2s(data,dsize);
+				size -= 2;
+				if (dsize > size  ) 
+					{
+					*al = SSL_AD_DECODE_ERROR;
+					return 0;
+					}
+				while (dsize > 0)
+					{
+					OCSP_RESPID *id;
+					int idsize;
+					if (dsize < 4)
+						{
+						*al = SSL_AD_DECODE_ERROR;
+						return 0;
+						}
+					n2s(data, idsize);
+					dsize -= 2 + idsize;
+					if (dsize < 0)
+						{
+						*al = SSL_AD_DECODE_ERROR;
+						return 0;
+						}
+					sdata = data;
+					data += idsize;
+					id = d2i_OCSP_RESPID(NULL,
+								&sdata, idsize);
+					if (!id)
+						{
+						*al = SSL_AD_DECODE_ERROR;
+						return 0;
+						}
+					if (data != sdata)
+						{
+						OCSP_RESPID_free(id);
+						*al = SSL_AD_DECODE_ERROR;
+						return 0;
+						}
+					if (!s->tlsext_ocsp_ids
+						&& !(s->tlsext_ocsp_ids =
+						sk_OCSP_RESPID_new_null()))
+						{
+						OCSP_RESPID_free(id);
+						*al = SSL_AD_INTERNAL_ERROR;
+						return 0;
+						}
+					if (!sk_OCSP_RESPID_push(
+							s->tlsext_ocsp_ids, id))
+						{
+						OCSP_RESPID_free(id);
+						*al = SSL_AD_INTERNAL_ERROR;
+						return 0;
+						}
+					}
+
+				/* Read in request_extensions */
+				n2s(data,dsize);
+				size -= 2;
+				if (dsize > size) 
+					{
+					*al = SSL_AD_DECODE_ERROR;
+					return 0;
+					}
+				sdata = data;
+				if (dsize > 0)
+					{
+					s->tlsext_ocsp_exts =
+						d2i_X509_EXTENSIONS(NULL,
+							&sdata, dsize);
+					if (!s->tlsext_ocsp_exts
+						|| (data + dsize != sdata))
+						{
+						*al = SSL_AD_DECODE_ERROR;
+						return 0;
+						}
+					}
+				}
+				/* We don't know what to do with any other type
+ 			 	* so ignore it.
+ 			 	*/
+				else
+					s->tlsext_status_type = -1;
+			}
+
+		/* session ticket processed earlier */
+		data+=size;
+		}
+				
+	*p = data;
+
+	ri_check:
+
+	/* Need RI if renegotiating */
+
+	if (!renegotiate_seen && s->new_session &&
+		!(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
+		{
+		*al = SSL_AD_HANDSHAKE_FAILURE;
+	 	SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT,
+				SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
+		return 0;
+		}
+
+	return 1;
+	}
+
+int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al)
+	{
+	unsigned short type;
+	unsigned short size;
+	unsigned short len;  
+	unsigned char *data = *p;
+	int tlsext_servername = 0;
+	int renegotiate_seen = 0;
+
+	if (data >= (d+n-2))
+		goto ri_check;
+
+	n2s(data,len);
+
+	while(data <= (d+n-4))
+		{
+		n2s(data,type);
+		n2s(data,size);
+
+		if (data+size > (d+n))
+	   		goto ri_check;
+
+		if (s->tlsext_debug_cb)
+			s->tlsext_debug_cb(s, 1, type, data, size,
+						s->tlsext_debug_arg);
+
+		if (type == TLSEXT_TYPE_server_name)
+			{
+			if (s->tlsext_hostname == NULL || size > 0)
+				{
+				*al = TLS1_AD_UNRECOGNIZED_NAME;
+				return 0;
+				}
+			tlsext_servername = 1;   
+			}
+
+#ifndef OPENSSL_NO_EC
+		else if (type == TLSEXT_TYPE_ec_point_formats &&
+	             s->version != DTLS1_VERSION)
+			{
+			unsigned char *sdata = data;
+			int ecpointformatlist_length = *(sdata++);
+
+			if (ecpointformatlist_length != size - 1)
+				{
+				*al = TLS1_AD_DECODE_ERROR;
+				return 0;
+				}
+			s->session->tlsext_ecpointformatlist_length = 0;
+			if (s->session->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->session->tlsext_ecpointformatlist);
+			if ((s->session->tlsext_ecpointformatlist = OPENSSL_malloc(ecpointformatlist_length)) == NULL)
+				{
+				*al = TLS1_AD_INTERNAL_ERROR;
+				return 0;
+				}
+			s->session->tlsext_ecpointformatlist_length = ecpointformatlist_length;
+			memcpy(s->session->tlsext_ecpointformatlist, sdata, ecpointformatlist_length);
+#if 0
+			fprintf(stderr,"ssl_parse_serverhello_tlsext s->session->tlsext_ecpointformatlist ");
+			sdata = s->session->tlsext_ecpointformatlist;
+			for (i = 0; i < s->session->tlsext_ecpointformatlist_length; i++)
+				fprintf(stderr,"%i ",*(sdata++));
+			fprintf(stderr,"\n");
+#endif
+			}
+#endif /* OPENSSL_NO_EC */
+
+		else if (type == TLSEXT_TYPE_session_ticket)
+			{
+			if (s->tls_session_ticket_ext_cb &&
+			    !s->tls_session_ticket_ext_cb(s, data, size, s->tls_session_ticket_ext_cb_arg))
+				{
+				*al = TLS1_AD_INTERNAL_ERROR;
+				return 0;
+				}
+			if ((SSL_get_options(s) & SSL_OP_NO_TICKET)
+				|| (size > 0))
+				{
+				*al = TLS1_AD_UNSUPPORTED_EXTENSION;
+				return 0;
+				}
+			s->tlsext_ticket_expected = 1;
+			}
+#ifdef TLSEXT_TYPE_opaque_prf_input
+		else if (type == TLSEXT_TYPE_opaque_prf_input &&
+	             s->version != DTLS1_VERSION)
+			{
+			unsigned char *sdata = data;
+
+			if (size < 2)
+				{
+				*al = SSL_AD_DECODE_ERROR;
+				return 0;
+				}
+			n2s(sdata, s->s3->server_opaque_prf_input_len);
+			if (s->s3->server_opaque_prf_input_len != size - 2)
+				{
+				*al = SSL_AD_DECODE_ERROR;
+				return 0;
+				}
+			
+			if (s->s3->server_opaque_prf_input != NULL) /* shouldn't really happen */
+				OPENSSL_free(s->s3->server_opaque_prf_input);
+			if (s->s3->server_opaque_prf_input_len == 0)
+				s->s3->server_opaque_prf_input = OPENSSL_malloc(1); /* dummy byte just to get non-NULL */
+			else
+				s->s3->server_opaque_prf_input = BUF_memdup(sdata, s->s3->server_opaque_prf_input_len);
+
+			if (s->s3->server_opaque_prf_input == NULL)
+				{
+				*al = TLS1_AD_INTERNAL_ERROR;
+				return 0;
+				}
+			}
+#endif
+		else if (type == TLSEXT_TYPE_status_request &&
+		         s->version != DTLS1_VERSION)
+			{
+			/* MUST be empty and only sent if we've requested
+			 * a status request message.
+			 */ 
+			if ((s->tlsext_status_type == -1) || (size > 0))
+				{
+				*al = TLS1_AD_UNSUPPORTED_EXTENSION;
+				return 0;
+				}
+			/* Set flag to expect CertificateStatus message */
+			s->tlsext_status_expected = 1;
+			}
+		else if (type == TLSEXT_TYPE_renegotiate)
+			{
+			if(!ssl_parse_serverhello_renegotiate_ext(s, data, size, al))
+				return 0;
+			renegotiate_seen = 1;
+			}
+		data+=size;		
+		}
+
+	if (data != d+n)
+		{
+		*al = SSL_AD_DECODE_ERROR;
+		return 0;
+		}
+
+	if (!s->hit && tlsext_servername == 1)
+		{
+ 		if (s->tlsext_hostname)
+			{
+			if (s->session->tlsext_hostname == NULL)
+				{
+				s->session->tlsext_hostname = BUF_strdup(s->tlsext_hostname);	
+				if (!s->session->tlsext_hostname)
+					{
+					*al = SSL_AD_UNRECOGNIZED_NAME;
+					return 0;
+					}
+				}
+			else 
+				{
+				*al = SSL_AD_DECODE_ERROR;
+				return 0;
+				}
+			}
+		}
+
+	*p = data;
+
+	ri_check:
+
+	/* Determine if we need to see RI. Strictly speaking if we want to
+	 * avoid an attack we should *always* see RI even on initial server
+	 * hello because the client doesn't see any renegotiation during an
+	 * attack. However this would mean we could not connect to any server
+	 * which doesn't support RI so for the immediate future tolerate RI
+	 * absence on initial connect only.
+	 */
+	if (!renegotiate_seen
+		&& !(s->options & SSL_OP_LEGACY_SERVER_CONNECT)
+		&& !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
+		{
+		*al = SSL_AD_HANDSHAKE_FAILURE;
+		SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT,
+				SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
+		return 0;
+		}
+
+	return 1;
+	}
+
+
+int ssl_prepare_clienthello_tlsext(SSL *s)
+	{
+#ifndef OPENSSL_NO_EC
+	/* If we are client and using an elliptic curve cryptography cipher suite, send the point formats 
+	 * and elliptic curves we support.
+	 */
+	int using_ecc = 0;
+	int i;
+	unsigned char *j;
+	unsigned long alg_k, alg_a;
+	STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(s);
+
+	for (i = 0; i < sk_SSL_CIPHER_num(cipher_stack); i++)
+		{
+		SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i);
+
+		alg_k = c->algorithm_mkey;
+		alg_a = c->algorithm_auth;
+		if ((alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe) || (alg_a & SSL_aECDSA)))
+			{
+			using_ecc = 1;
+			break;
+			}
+		}
+	using_ecc = using_ecc && (s->version == TLS1_VERSION);
+	if (using_ecc)
+		{
+		if (s->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->tlsext_ecpointformatlist);
+		if ((s->tlsext_ecpointformatlist = OPENSSL_malloc(3)) == NULL)
+			{
+			SSLerr(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT,ERR_R_MALLOC_FAILURE);
+			return -1;
+			}
+		s->tlsext_ecpointformatlist_length = 3;
+		s->tlsext_ecpointformatlist[0] = TLSEXT_ECPOINTFORMAT_uncompressed;
+		s->tlsext_ecpointformatlist[1] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime;
+		s->tlsext_ecpointformatlist[2] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2;
+
+		/* we support all named elliptic curves in draft-ietf-tls-ecc-12 */
+		if (s->tlsext_ellipticcurvelist != NULL) OPENSSL_free(s->tlsext_ellipticcurvelist);
+		s->tlsext_ellipticcurvelist_length = sizeof(nid_list)/sizeof(nid_list[0]) * 2;
+		if ((s->tlsext_ellipticcurvelist = OPENSSL_malloc(s->tlsext_ellipticcurvelist_length)) == NULL)
+			{
+			s->tlsext_ellipticcurvelist_length = 0;
+			SSLerr(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT,ERR_R_MALLOC_FAILURE);
+			return -1;
+			}
+		for (i = 1, j = s->tlsext_ellipticcurvelist; (unsigned int)i <=
+				sizeof(nid_list)/sizeof(nid_list[0]); i++)
+			s2n(i,j);
+		}
+#endif /* OPENSSL_NO_EC */
+
+#ifdef TLSEXT_TYPE_opaque_prf_input
+ 	{
+		int r = 1;
+	
+		if (s->ctx->tlsext_opaque_prf_input_callback != 0)
+			{
+			r = s->ctx->tlsext_opaque_prf_input_callback(s, NULL, 0, s->ctx->tlsext_opaque_prf_input_callback_arg);
+			if (!r)
+				return -1;
+			}
+
+		if (s->tlsext_opaque_prf_input != NULL)
+			{
+			if (s->s3->client_opaque_prf_input != NULL) /* shouldn't really happen */
+				OPENSSL_free(s->s3->client_opaque_prf_input);
+
+			if (s->tlsext_opaque_prf_input_len == 0)
+				s->s3->client_opaque_prf_input = OPENSSL_malloc(1); /* dummy byte just to get non-NULL */
+			else
+				s->s3->client_opaque_prf_input = BUF_memdup(s->tlsext_opaque_prf_input, s->tlsext_opaque_prf_input_len);
+			if (s->s3->client_opaque_prf_input == NULL)
+				{
+				SSLerr(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT,ERR_R_MALLOC_FAILURE);
+				return -1;
+				}
+			s->s3->client_opaque_prf_input_len = s->tlsext_opaque_prf_input_len;
+			}
+
+		if (r == 2)
+			/* at callback's request, insist on receiving an appropriate server opaque PRF input */
+			s->s3->server_opaque_prf_input_len = s->tlsext_opaque_prf_input_len;
+	}
+#endif
+
+	return 1;
+	}
+
+int ssl_prepare_serverhello_tlsext(SSL *s)
+	{
+#ifndef OPENSSL_NO_EC
+	/* If we are server and using an ECC cipher suite, send the point formats we support 
+	 * if the client sent us an ECPointsFormat extension.  Note that the server is not
+	 * supposed to send an EllipticCurves extension.
+	 */
+
+	unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+	unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+	int using_ecc = (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe)) || (alg_a & SSL_aECDSA);
+	using_ecc = using_ecc && (s->session->tlsext_ecpointformatlist != NULL);
+	
+	if (using_ecc)
+		{
+		if (s->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->tlsext_ecpointformatlist);
+		if ((s->tlsext_ecpointformatlist = OPENSSL_malloc(3)) == NULL)
+			{
+			SSLerr(SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT,ERR_R_MALLOC_FAILURE);
+			return -1;
+			}
+		s->tlsext_ecpointformatlist_length = 3;
+		s->tlsext_ecpointformatlist[0] = TLSEXT_ECPOINTFORMAT_uncompressed;
+		s->tlsext_ecpointformatlist[1] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime;
+		s->tlsext_ecpointformatlist[2] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2;
+		}
+#endif /* OPENSSL_NO_EC */
+
+	return 1;
+	}
+
+int ssl_check_clienthello_tlsext(SSL *s)
+	{
+	int ret=SSL_TLSEXT_ERR_NOACK;
+	int al = SSL_AD_UNRECOGNIZED_NAME;
+
+#ifndef OPENSSL_NO_EC
+	/* The handling of the ECPointFormats extension is done elsewhere, namely in 
+	 * ssl3_choose_cipher in s3_lib.c.
+	 */
+	/* The handling of the EllipticCurves extension is done elsewhere, namely in 
+	 * ssl3_choose_cipher in s3_lib.c.
+	 */
+#endif
+
+	if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0) 
+		ret = s->ctx->tlsext_servername_callback(s, &al, s->ctx->tlsext_servername_arg);
+	else if (s->initial_ctx != NULL && s->initial_ctx->tlsext_servername_callback != 0) 		
+		ret = s->initial_ctx->tlsext_servername_callback(s, &al, s->initial_ctx->tlsext_servername_arg);
+
+	/* If status request then ask callback what to do.
+ 	 * Note: this must be called after servername callbacks in case 
+ 	 * the certificate has changed.
+ 	 */
+	if ((s->tlsext_status_type != -1) && s->ctx && s->ctx->tlsext_status_cb)
+		{
+		int r;
+		r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
+		switch (r)
+			{
+			/* We don't want to send a status request response */
+			case SSL_TLSEXT_ERR_NOACK:
+				s->tlsext_status_expected = 0;
+				break;
+			/* status request response should be sent */
+			case SSL_TLSEXT_ERR_OK:
+				if (s->tlsext_ocsp_resp)
+					s->tlsext_status_expected = 1;
+				else
+					s->tlsext_status_expected = 0;
+				break;
+			/* something bad happened */
+			case SSL_TLSEXT_ERR_ALERT_FATAL:
+				ret = SSL_TLSEXT_ERR_ALERT_FATAL;
+				al = SSL_AD_INTERNAL_ERROR;
+				goto err;
+			}
+		}
+	else
+		s->tlsext_status_expected = 0;
+
+#ifdef TLSEXT_TYPE_opaque_prf_input
+ 	{
+		/* This sort of belongs into ssl_prepare_serverhello_tlsext(),
+		 * but we might be sending an alert in response to the client hello,
+		 * so this has to happen here in ssl_check_clienthello_tlsext(). */
+
+		int r = 1;
+	
+		if (s->ctx->tlsext_opaque_prf_input_callback != 0)
+			{
+			r = s->ctx->tlsext_opaque_prf_input_callback(s, NULL, 0, s->ctx->tlsext_opaque_prf_input_callback_arg);
+			if (!r)
+				{
+				ret = SSL_TLSEXT_ERR_ALERT_FATAL;
+				al = SSL_AD_INTERNAL_ERROR;
+				goto err;
+				}
+			}
+
+		if (s->s3->server_opaque_prf_input != NULL) /* shouldn't really happen */
+			OPENSSL_free(s->s3->server_opaque_prf_input);
+		s->s3->server_opaque_prf_input = NULL;
+
+		if (s->tlsext_opaque_prf_input != NULL)
+			{
+			if (s->s3->client_opaque_prf_input != NULL &&
+				s->s3->client_opaque_prf_input_len == s->tlsext_opaque_prf_input_len)
+				{
+				/* can only use this extension if we have a server opaque PRF input
+				 * of the same length as the client opaque PRF input! */
+
+				if (s->tlsext_opaque_prf_input_len == 0)
+					s->s3->server_opaque_prf_input = OPENSSL_malloc(1); /* dummy byte just to get non-NULL */
+				else
+					s->s3->server_opaque_prf_input = BUF_memdup(s->tlsext_opaque_prf_input, s->tlsext_opaque_prf_input_len);
+				if (s->s3->server_opaque_prf_input == NULL)
+					{
+					ret = SSL_TLSEXT_ERR_ALERT_FATAL;
+					al = SSL_AD_INTERNAL_ERROR;
+					goto err;
+					}
+				s->s3->server_opaque_prf_input_len = s->tlsext_opaque_prf_input_len;
+				}
+			}
+
+		if (r == 2 && s->s3->server_opaque_prf_input == NULL)
+			{
+			/* The callback wants to enforce use of the extension,
+			 * but we can't do that with the client opaque PRF input;
+			 * abort the handshake.
+			 */
+			ret = SSL_TLSEXT_ERR_ALERT_FATAL;
+			al = SSL_AD_HANDSHAKE_FAILURE;
+			}
+	}
+
+#endif
+ err:
+	switch (ret)
+		{
+		case SSL_TLSEXT_ERR_ALERT_FATAL:
+			ssl3_send_alert(s,SSL3_AL_FATAL,al); 
+			return -1;
+
+		case SSL_TLSEXT_ERR_ALERT_WARNING:
+			ssl3_send_alert(s,SSL3_AL_WARNING,al);
+			return 1; 
+					
+		case SSL_TLSEXT_ERR_NOACK:
+			s->servername_done=0;
+			default:
+		return 1;
+		}
+	}
+
+int ssl_check_serverhello_tlsext(SSL *s)
+	{
+	int ret=SSL_TLSEXT_ERR_NOACK;
+	int al = SSL_AD_UNRECOGNIZED_NAME;
+
+#ifndef OPENSSL_NO_EC
+	/* If we are client and using an elliptic curve cryptography cipher suite, then server
+	 * must return a an EC point formats lists containing uncompressed.
+	 */
+	unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+	unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+	if ((s->tlsext_ecpointformatlist != NULL) && (s->tlsext_ecpointformatlist_length > 0) && 
+	    ((alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe)) || (alg_a & SSL_aECDSA)))
+		{
+		/* we are using an ECC cipher */
+		size_t i;
+		unsigned char *list;
+		int found_uncompressed = 0;
+		if ((s->session->tlsext_ecpointformatlist == NULL) || (s->session->tlsext_ecpointformatlist_length == 0))
+			{
+			SSLerr(SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT,SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST);
+			return -1;
+			}
+		list = s->session->tlsext_ecpointformatlist;
+		for (i = 0; i < s->session->tlsext_ecpointformatlist_length; i++)
+			{
+			if (*(list++) == TLSEXT_ECPOINTFORMAT_uncompressed)
+				{
+				found_uncompressed = 1;
+				break;
+				}
+			}
+		if (!found_uncompressed)
+			{
+			SSLerr(SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT,SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST);
+			return -1;
+			}
+		}
+	ret = SSL_TLSEXT_ERR_OK;
+#endif /* OPENSSL_NO_EC */
+
+	if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0) 
+		ret = s->ctx->tlsext_servername_callback(s, &al, s->ctx->tlsext_servername_arg);
+	else if (s->initial_ctx != NULL && s->initial_ctx->tlsext_servername_callback != 0) 		
+		ret = s->initial_ctx->tlsext_servername_callback(s, &al, s->initial_ctx->tlsext_servername_arg);
+
+#ifdef TLSEXT_TYPE_opaque_prf_input
+	if (s->s3->server_opaque_prf_input_len > 0)
+		{
+		/* This case may indicate that we, as a client, want to insist on using opaque PRF inputs.
+		 * So first verify that we really have a value from the server too. */
+
+		if (s->s3->server_opaque_prf_input == NULL)
+			{
+			ret = SSL_TLSEXT_ERR_ALERT_FATAL;
+			al = SSL_AD_HANDSHAKE_FAILURE;
+			}
+		
+		/* Anytime the server *has* sent an opaque PRF input, we need to check
+		 * that we have a client opaque PRF input of the same size. */
+		if (s->s3->client_opaque_prf_input == NULL ||
+		    s->s3->client_opaque_prf_input_len != s->s3->server_opaque_prf_input_len)
+			{
+			ret = SSL_TLSEXT_ERR_ALERT_FATAL;
+			al = SSL_AD_ILLEGAL_PARAMETER;
+			}
+		}
+#endif
+
+	/* If we've requested certificate status and we wont get one
+ 	 * tell the callback
+ 	 */
+	if ((s->tlsext_status_type != -1) && !(s->tlsext_status_expected)
+			&& s->ctx && s->ctx->tlsext_status_cb)
+		{
+		int r;
+		/* Set resp to NULL, resplen to -1 so callback knows
+ 		 * there is no response.
+ 		 */
+		if (s->tlsext_ocsp_resp)
+			{
+			OPENSSL_free(s->tlsext_ocsp_resp);
+			s->tlsext_ocsp_resp = NULL;
+			}
+		s->tlsext_ocsp_resplen = -1;
+		r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
+		if (r == 0)
+			{
+			al = SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE;
+			ret = SSL_TLSEXT_ERR_ALERT_FATAL;
+			}
+		if (r < 0)
+			{
+			al = SSL_AD_INTERNAL_ERROR;
+			ret = SSL_TLSEXT_ERR_ALERT_FATAL;
+			}
+		}
+
+	switch (ret)
+		{
+		case SSL_TLSEXT_ERR_ALERT_FATAL:
+			ssl3_send_alert(s,SSL3_AL_FATAL,al); 
+			return -1;
+
+		case SSL_TLSEXT_ERR_ALERT_WARNING:
+			ssl3_send_alert(s,SSL3_AL_WARNING,al);
+			return 1; 
+					
+		case SSL_TLSEXT_ERR_NOACK:
+			s->servername_done=0;
+			default:
+		return 1;
+		}
+	}
+
+/* Since the server cache lookup is done early on in the processing of client
+ * hello and other operations depend on the result we need to handle any TLS
+ * session ticket extension at the same time.
+ */
+
+int tls1_process_ticket(SSL *s, unsigned char *session_id, int len,
+				const unsigned char *limit, SSL_SESSION **ret)
+	{
+	/* Point after session ID in client hello */
+	const unsigned char *p = session_id + len;
+	unsigned short i;
+
+	/* If tickets disabled behave as if no ticket present
+ 	 * to permit stateful resumption.
+ 	 */
+	if (SSL_get_options(s) & SSL_OP_NO_TICKET)
+		return 1;
+
+	if ((s->version <= SSL3_VERSION) || !limit)
+		return 1;
+	if (p >= limit)
+		return -1;
+	/* Skip past DTLS cookie */
+	if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER)
+		{
+		i = *(p++);
+		p+= i;
+		if (p >= limit)
+			return -1;
+		}
+	/* Skip past cipher list */
+	n2s(p, i);
+	p+= i;
+	if (p >= limit)
+		return -1;
+	/* Skip past compression algorithm list */
+	i = *(p++);
+	p += i;
+	if (p > limit)
+		return -1;
+	/* Now at start of extensions */
+	if ((p + 2) >= limit)
+		return 1;
+	n2s(p, i);
+	while ((p + 4) <= limit)
+		{
+		unsigned short type, size;
+		n2s(p, type);
+		n2s(p, size);
+		if (p + size > limit)
+			return 1;
+		if (type == TLSEXT_TYPE_session_ticket)
+			{
+			/* If tickets disabled indicate cache miss which will
+ 			 * trigger a full handshake
+ 			 */
+			if (SSL_get_options(s) & SSL_OP_NO_TICKET)
+				return 1;
+			/* If zero length note client will accept a ticket
+ 			 * and indicate cache miss to trigger full handshake
+ 			 */
+			if (size == 0)
+				{
+				s->tlsext_ticket_expected = 1;
+				return 0;	/* Cache miss */
+				}
+			if (s->tls_session_secret_cb)
+				{
+				/* Indicate cache miss here and instead of
+				 * generating the session from ticket now,
+				 * trigger abbreviated handshake based on
+				 * external mechanism to calculate the master
+				 * secret later. */
+				return 0;
+				}
+			return tls_decrypt_ticket(s, p, size, session_id, len,
+									ret);
+			}
+		p += size;
+		}
+	return 1;
+	}
+
+static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen,
+				const unsigned char *sess_id, int sesslen,
+				SSL_SESSION **psess)
+	{
+	SSL_SESSION *sess;
+	unsigned char *sdec;
+	const unsigned char *p;
+	int slen, mlen, renew_ticket = 0;
+	unsigned char tick_hmac[EVP_MAX_MD_SIZE];
+	HMAC_CTX hctx;
+	EVP_CIPHER_CTX ctx;
+	SSL_CTX *tctx = s->initial_ctx;
+	/* Need at least keyname + iv + some encrypted data */
+	if (eticklen < 48)
+		goto tickerr;
+	/* Initialize session ticket encryption and HMAC contexts */
+	HMAC_CTX_init(&hctx);
+	EVP_CIPHER_CTX_init(&ctx);
+	if (tctx->tlsext_ticket_key_cb)
+		{
+		unsigned char *nctick = (unsigned char *)etick;
+		int rv = tctx->tlsext_ticket_key_cb(s, nctick, nctick + 16,
+							&ctx, &hctx, 0);
+		if (rv < 0)
+			return -1;
+		if (rv == 0)
+			goto tickerr;
+		if (rv == 2)
+			renew_ticket = 1;
+		}
+	else
+		{
+		/* Check key name matches */
+		if (memcmp(etick, tctx->tlsext_tick_key_name, 16))
+			goto tickerr;
+		HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16,
+					tlsext_tick_md(), NULL);
+		EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
+				tctx->tlsext_tick_aes_key, etick + 16);
+		}
+	/* Attempt to process session ticket, first conduct sanity and
+ 	 * integrity checks on ticket.
+ 	 */
+	mlen = HMAC_size(&hctx);
+	if (mlen < 0)
+		{
+		EVP_CIPHER_CTX_cleanup(&ctx);
+		return -1;
+		}
+	eticklen -= mlen;
+	/* Check HMAC of encrypted ticket */
+	HMAC_Update(&hctx, etick, eticklen);
+	HMAC_Final(&hctx, tick_hmac, NULL);
+	HMAC_CTX_cleanup(&hctx);
+	if (memcmp(tick_hmac, etick + eticklen, mlen))
+		goto tickerr;
+	/* Attempt to decrypt session data */
+	/* Move p after IV to start of encrypted ticket, update length */
+	p = etick + 16 + EVP_CIPHER_CTX_iv_length(&ctx);
+	eticklen -= 16 + EVP_CIPHER_CTX_iv_length(&ctx);
+	sdec = OPENSSL_malloc(eticklen);
+	if (!sdec)
+		{
+		EVP_CIPHER_CTX_cleanup(&ctx);
+		return -1;
+		}
+	EVP_DecryptUpdate(&ctx, sdec, &slen, p, eticklen);
+	if (EVP_DecryptFinal(&ctx, sdec + slen, &mlen) <= 0)
+		goto tickerr;
+	slen += mlen;
+	EVP_CIPHER_CTX_cleanup(&ctx);
+	p = sdec;
+		
+	sess = d2i_SSL_SESSION(NULL, &p, slen);
+	OPENSSL_free(sdec);
+	if (sess)
+		{
+		/* The session ID if non-empty is used by some clients to
+ 		 * detect that the ticket has been accepted. So we copy it to
+ 		 * the session structure. If it is empty set length to zero
+ 		 * as required by standard.
+ 		 */
+		if (sesslen)
+			memcpy(sess->session_id, sess_id, sesslen);
+		sess->session_id_length = sesslen;
+		*psess = sess;
+		s->tlsext_ticket_expected = renew_ticket;
+		return 1;
+		}
+	/* If session decrypt failure indicate a cache miss and set state to
+ 	 * send a new ticket
+ 	 */
+	tickerr:	
+	s->tlsext_ticket_expected = 1;
+	return 0;
+	}
+
+#endif
diff --git a/lib/openssl/ssl/t1_meth.c b/lib/openssl/ssl/t1_meth.c
new file mode 100644
index 0000000..6ce7c0b
--- /dev/null
+++ b/lib/openssl/ssl/t1_meth.c
@@ -0,0 +1,76 @@
+/* ssl/t1_meth.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include <openssl/objects.h>
+#include "ssl_locl.h"
+
+static const SSL_METHOD *tls1_get_method(int ver);
+static const SSL_METHOD *tls1_get_method(int ver)
+	{
+	if (ver == TLS1_VERSION)
+		return(TLSv1_method());
+	else
+		return(NULL);
+	}
+
+IMPLEMENT_tls1_meth_func(TLSv1_method,
+			ssl3_accept,
+			ssl3_connect,
+			tls1_get_method)
+
diff --git a/lib/openssl/ssl/t1_reneg.c b/lib/openssl/ssl/t1_reneg.c
new file mode 100644
index 0000000..9c2cc3c
--- /dev/null
+++ b/lib/openssl/ssl/t1_reneg.c
@@ -0,0 +1,292 @@
+/* ssl/t1_reneg.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2009 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+#include <stdio.h>
+#include <openssl/objects.h>
+#include "ssl_locl.h"
+
+/* Add the client's renegotiation binding */
+int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
+					int maxlen)
+    {
+    if(p)
+        {
+	if((s->s3->previous_client_finished_len+1) > maxlen)
+            {
+            SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATE_EXT_TOO_LONG);
+            return 0;
+            }
+            
+        /* Length byte */
+	*p = s->s3->previous_client_finished_len;
+        p++;
+
+        memcpy(p, s->s3->previous_client_finished,
+	       s->s3->previous_client_finished_len);
+#ifdef OPENSSL_RI_DEBUG
+    fprintf(stderr, "%s RI extension sent by client\n",
+		s->s3->previous_client_finished_len ? "Non-empty" : "Empty");
+#endif
+        }
+    
+    *len=s->s3->previous_client_finished_len + 1;
+
+ 
+    return 1;
+    }
+
+/* Parse the client's renegotiation binding and abort if it's not
+   right */
+int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len,
+					  int *al)
+    {
+    int ilen;
+
+    /* Parse the length byte */
+    if(len < 1)
+        {
+        SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_ENCODING_ERR);
+        *al=SSL_AD_ILLEGAL_PARAMETER;
+        return 0;
+        }
+    ilen = *d;
+    d++;
+
+    /* Consistency check */
+    if((ilen+1) != len)
+        {
+        SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_ENCODING_ERR);
+        *al=SSL_AD_ILLEGAL_PARAMETER;
+        return 0;
+        }
+
+    /* Check that the extension matches */
+    if(ilen != s->s3->previous_client_finished_len)
+        {
+        SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_MISMATCH);
+        *al=SSL_AD_HANDSHAKE_FAILURE;
+        return 0;
+        }
+    
+    if(memcmp(d, s->s3->previous_client_finished,
+	      s->s3->previous_client_finished_len))
+        {
+        SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_MISMATCH);
+        *al=SSL_AD_HANDSHAKE_FAILURE;
+        return 0;
+        }
+#ifdef OPENSSL_RI_DEBUG
+    fprintf(stderr, "%s RI extension received by server\n",
+				ilen ? "Non-empty" : "Empty");
+#endif
+
+    s->s3->send_connection_binding=1;
+
+    return 1;
+    }
+
+/* Add the server's renegotiation binding */
+int ssl_add_serverhello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
+					int maxlen)
+    {
+    if(p)
+        {
+        if((s->s3->previous_client_finished_len +
+            s->s3->previous_server_finished_len + 1) > maxlen)
+            {
+            SSLerr(SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATE_EXT_TOO_LONG);
+            return 0;
+            }
+        
+        /* Length byte */
+        *p = s->s3->previous_client_finished_len + s->s3->previous_server_finished_len;
+        p++;
+
+        memcpy(p, s->s3->previous_client_finished,
+	       s->s3->previous_client_finished_len);
+        p += s->s3->previous_client_finished_len;
+
+        memcpy(p, s->s3->previous_server_finished,
+	       s->s3->previous_server_finished_len);
+#ifdef OPENSSL_RI_DEBUG
+    fprintf(stderr, "%s RI extension sent by server\n",
+    		s->s3->previous_client_finished_len ? "Non-empty" : "Empty");
+#endif
+        }
+    
+    *len=s->s3->previous_client_finished_len
+	+ s->s3->previous_server_finished_len + 1;
+    
+    return 1;
+    }
+
+/* Parse the server's renegotiation binding and abort if it's not
+   right */
+int ssl_parse_serverhello_renegotiate_ext(SSL *s, unsigned char *d, int len,
+					  int *al)
+    {
+    int expected_len=s->s3->previous_client_finished_len
+	+ s->s3->previous_server_finished_len;
+    int ilen;
+
+    /* Check for logic errors */
+    OPENSSL_assert(!expected_len || s->s3->previous_client_finished_len);
+    OPENSSL_assert(!expected_len || s->s3->previous_server_finished_len);
+    
+    /* Parse the length byte */
+    if(len < 1)
+        {
+        SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_ENCODING_ERR);
+        *al=SSL_AD_ILLEGAL_PARAMETER;
+        return 0;
+        }
+    ilen = *d;
+    d++;
+
+    /* Consistency check */
+    if(ilen+1 != len)
+        {
+        SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_ENCODING_ERR);
+        *al=SSL_AD_ILLEGAL_PARAMETER;
+        return 0;
+        }
+    
+    /* Check that the extension matches */
+    if(ilen != expected_len)
+        {
+        SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_MISMATCH);
+        *al=SSL_AD_HANDSHAKE_FAILURE;
+        return 0;
+        }
+
+    if(memcmp(d, s->s3->previous_client_finished,
+	      s->s3->previous_client_finished_len))
+        {
+        SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_MISMATCH);
+        *al=SSL_AD_HANDSHAKE_FAILURE;
+        return 0;
+        }
+    d += s->s3->previous_client_finished_len;
+
+    if(memcmp(d, s->s3->previous_server_finished,
+	      s->s3->previous_server_finished_len))
+        {
+        SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_MISMATCH);
+        *al=SSL_AD_ILLEGAL_PARAMETER;
+        return 0;
+        }
+#ifdef OPENSSL_RI_DEBUG
+    fprintf(stderr, "%s RI extension received by client\n",
+				ilen ? "Non-empty" : "Empty");
+#endif
+    s->s3->send_connection_binding=1;
+
+    return 1;
+    }
diff --git a/lib/openssl/ssl/t1_srvr.c b/lib/openssl/ssl/t1_srvr.c
new file mode 100644
index 0000000..42525e9
--- /dev/null
+++ b/lib/openssl/ssl/t1_srvr.c
@@ -0,0 +1,80 @@
+/* ssl/t1_srvr.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include "ssl_locl.h"
+#include <openssl/buffer.h>
+#include <openssl/rand.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+
+static const SSL_METHOD *tls1_get_server_method(int ver);
+static const SSL_METHOD *tls1_get_server_method(int ver)
+	{
+	if (ver == TLS1_VERSION)
+		return(TLSv1_server_method());
+	else
+		return(NULL);
+	}
+
+IMPLEMENT_tls1_meth_func(TLSv1_server_method,
+			ssl3_accept,
+			ssl_undefined_function,
+			tls1_get_server_method)
+
diff --git a/lib/openssl/ssl/tls1.h b/lib/openssl/ssl/tls1.h
new file mode 100644
index 0000000..b3cc8f0
--- /dev/null
+++ b/lib/openssl/ssl/tls1.h
@@ -0,0 +1,532 @@
+/* ssl/tls1.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * Portions of the attached software ("Contribution") are developed by 
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the OpenSSL open source
+ * license provided above.
+ *
+ * ECC cipher suite support in OpenSSL originally written by
+ * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
+ *
+ */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#ifndef HEADER_TLS1_H 
+#define HEADER_TLS1_H 
+
+#include <openssl/buffer.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#define TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES	0
+
+#define TLS1_VERSION			0x0301
+#define TLS1_VERSION_MAJOR		0x03
+#define TLS1_VERSION_MINOR		0x01
+
+#define TLS1_AD_DECRYPTION_FAILED	21
+#define TLS1_AD_RECORD_OVERFLOW		22
+#define TLS1_AD_UNKNOWN_CA		48	/* fatal */
+#define TLS1_AD_ACCESS_DENIED		49	/* fatal */
+#define TLS1_AD_DECODE_ERROR		50	/* fatal */
+#define TLS1_AD_DECRYPT_ERROR		51
+#define TLS1_AD_EXPORT_RESTRICTION	60	/* fatal */
+#define TLS1_AD_PROTOCOL_VERSION	70	/* fatal */
+#define TLS1_AD_INSUFFICIENT_SECURITY	71	/* fatal */
+#define TLS1_AD_INTERNAL_ERROR		80	/* fatal */
+#define TLS1_AD_USER_CANCELLED		90
+#define TLS1_AD_NO_RENEGOTIATION	100
+/* codes 110-114 are from RFC3546 */
+#define TLS1_AD_UNSUPPORTED_EXTENSION	110
+#define TLS1_AD_CERTIFICATE_UNOBTAINABLE 111
+#define TLS1_AD_UNRECOGNIZED_NAME 	112
+#define TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE 113
+#define TLS1_AD_BAD_CERTIFICATE_HASH_VALUE 114
+#define TLS1_AD_UNKNOWN_PSK_IDENTITY	115	/* fatal */
+
+/* ExtensionType values from RFC3546 / RFC4366 */
+#define TLSEXT_TYPE_server_name			0
+#define TLSEXT_TYPE_max_fragment_length		1
+#define TLSEXT_TYPE_client_certificate_url	2
+#define TLSEXT_TYPE_trusted_ca_keys		3
+#define TLSEXT_TYPE_truncated_hmac		4
+#define TLSEXT_TYPE_status_request		5
+/* ExtensionType values from RFC4492 */
+#define TLSEXT_TYPE_elliptic_curves		10
+#define TLSEXT_TYPE_ec_point_formats		11
+#define TLSEXT_TYPE_session_ticket		35
+/* ExtensionType value from draft-rescorla-tls-opaque-prf-input-00.txt */
+#if 0 /* will have to be provided externally for now ,
+       * i.e. build with -DTLSEXT_TYPE_opaque_prf_input=38183
+       * using whatever extension number you'd like to try */
+# define TLSEXT_TYPE_opaque_prf_input		?? */
+#endif
+
+/* Temporary extension type */
+#define TLSEXT_TYPE_renegotiate                 0xff01
+
+/* NameType value from RFC 3546 */
+#define TLSEXT_NAMETYPE_host_name 0
+/* status request value from RFC 3546 */
+#define TLSEXT_STATUSTYPE_ocsp 1
+
+/* ECPointFormat values from draft-ietf-tls-ecc-12 */
+#define TLSEXT_ECPOINTFORMAT_first			0
+#define TLSEXT_ECPOINTFORMAT_uncompressed		0
+#define TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime	1
+#define TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2	2
+#define TLSEXT_ECPOINTFORMAT_last			2
+
+#ifndef OPENSSL_NO_TLSEXT
+
+#define TLSEXT_MAXLEN_host_name 255
+
+const char *SSL_get_servername(const SSL *s, const int type) ;
+int SSL_get_servername_type(const SSL *s) ;
+
+#define SSL_set_tlsext_host_name(s,name) \
+SSL_ctrl(s,SSL_CTRL_SET_TLSEXT_HOSTNAME,TLSEXT_NAMETYPE_host_name,(char *)name)
+
+#define SSL_set_tlsext_debug_callback(ssl, cb) \
+SSL_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_DEBUG_CB,(void (*)(void))cb)
+
+#define SSL_set_tlsext_debug_arg(ssl, arg) \
+SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_DEBUG_ARG,0, (void *)arg)
+
+#define SSL_set_tlsext_status_type(ssl, type) \
+SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE,type, NULL)
+
+#define SSL_get_tlsext_status_exts(ssl, arg) \
+SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS,0, (void *)arg)
+
+#define SSL_set_tlsext_status_exts(ssl, arg) \
+SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS,0, (void *)arg)
+
+#define SSL_get_tlsext_status_ids(ssl, arg) \
+SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS,0, (void *)arg)
+
+#define SSL_set_tlsext_status_ids(ssl, arg) \
+SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS,0, (void *)arg)
+
+#define SSL_get_tlsext_status_ocsp_resp(ssl, arg) \
+SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP,0, (void *)arg)
+
+#define SSL_set_tlsext_status_ocsp_resp(ssl, arg, arglen) \
+SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP,arglen, (void *)arg)
+
+#define SSL_CTX_set_tlsext_servername_callback(ctx, cb) \
+SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_CB,(void (*)(void))cb)
+
+#define SSL_TLSEXT_ERR_OK 0
+#define SSL_TLSEXT_ERR_ALERT_WARNING 1
+#define SSL_TLSEXT_ERR_ALERT_FATAL 2
+#define SSL_TLSEXT_ERR_NOACK 3
+
+#define SSL_CTX_set_tlsext_servername_arg(ctx, arg) \
+SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG,0, (void *)arg)
+
+#define SSL_CTX_get_tlsext_ticket_keys(ctx, keys, keylen) \
+	SSL_CTX_ctrl((ctx),SSL_CTRL_GET_TLSEXT_TICKET_KEYS,(keylen),(keys))
+#define SSL_CTX_set_tlsext_ticket_keys(ctx, keys, keylen) \
+	SSL_CTX_ctrl((ctx),SSL_CTRL_SET_TLSEXT_TICKET_KEYS,(keylen),(keys))
+
+#define SSL_CTX_set_tlsext_status_cb(ssl, cb) \
+SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB,(void (*)(void))cb)
+
+#define SSL_CTX_set_tlsext_status_arg(ssl, arg) \
+SSL_CTX_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG,0, (void *)arg)
+
+#define SSL_set_tlsext_opaque_prf_input(s, src, len) \
+SSL_ctrl(s,SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT, len, src)
+#define SSL_CTX_set_tlsext_opaque_prf_input_callback(ctx, cb) \
+SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB, (void (*)(void))cb)
+#define SSL_CTX_set_tlsext_opaque_prf_input_callback_arg(ctx, arg) \
+SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB_ARG, 0, arg)
+
+#define SSL_CTX_set_tlsext_ticket_key_cb(ssl, cb) \
+SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
+
+#endif
+
+/* PSK ciphersuites from 4279 */
+#define TLS1_CK_PSK_WITH_RC4_128_SHA                    0x0300008A
+#define TLS1_CK_PSK_WITH_3DES_EDE_CBC_SHA               0x0300008B
+#define TLS1_CK_PSK_WITH_AES_128_CBC_SHA                0x0300008C
+#define TLS1_CK_PSK_WITH_AES_256_CBC_SHA                0x0300008D
+
+/* Additional TLS ciphersuites from expired Internet Draft
+ * draft-ietf-tls-56-bit-ciphersuites-01.txt
+ * (available if TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES is defined, see
+ * s3_lib.c).  We actually treat them like SSL 3.0 ciphers, which we probably
+ * shouldn't.  Note that the first two are actually not in the IDs. */
+#define TLS1_CK_RSA_EXPORT1024_WITH_RC4_56_MD5		0x03000060 /* not in ID */
+#define TLS1_CK_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5	0x03000061 /* not in ID */
+#define TLS1_CK_RSA_EXPORT1024_WITH_DES_CBC_SHA		0x03000062
+#define TLS1_CK_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA	0x03000063
+#define TLS1_CK_RSA_EXPORT1024_WITH_RC4_56_SHA		0x03000064
+#define TLS1_CK_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA	0x03000065
+#define TLS1_CK_DHE_DSS_WITH_RC4_128_SHA		0x03000066
+
+/* AES ciphersuites from RFC3268 */
+
+#define TLS1_CK_RSA_WITH_AES_128_SHA			0x0300002F
+#define TLS1_CK_DH_DSS_WITH_AES_128_SHA			0x03000030
+#define TLS1_CK_DH_RSA_WITH_AES_128_SHA			0x03000031
+#define TLS1_CK_DHE_DSS_WITH_AES_128_SHA		0x03000032
+#define TLS1_CK_DHE_RSA_WITH_AES_128_SHA		0x03000033
+#define TLS1_CK_ADH_WITH_AES_128_SHA			0x03000034
+
+#define TLS1_CK_RSA_WITH_AES_256_SHA			0x03000035
+#define TLS1_CK_DH_DSS_WITH_AES_256_SHA			0x03000036
+#define TLS1_CK_DH_RSA_WITH_AES_256_SHA			0x03000037
+#define TLS1_CK_DHE_DSS_WITH_AES_256_SHA		0x03000038
+#define TLS1_CK_DHE_RSA_WITH_AES_256_SHA		0x03000039
+#define TLS1_CK_ADH_WITH_AES_256_SHA			0x0300003A
+
+/* Camellia ciphersuites from RFC4132 */
+#define TLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA		0x03000041
+#define TLS1_CK_DH_DSS_WITH_CAMELLIA_128_CBC_SHA	0x03000042
+#define TLS1_CK_DH_RSA_WITH_CAMELLIA_128_CBC_SHA	0x03000043
+#define TLS1_CK_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA	0x03000044
+#define TLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA	0x03000045
+#define TLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA		0x03000046
+
+#define TLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA		0x03000084
+#define TLS1_CK_DH_DSS_WITH_CAMELLIA_256_CBC_SHA	0x03000085
+#define TLS1_CK_DH_RSA_WITH_CAMELLIA_256_CBC_SHA	0x03000086
+#define TLS1_CK_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA	0x03000087
+#define TLS1_CK_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA	0x03000088
+#define TLS1_CK_ADH_WITH_CAMELLIA_256_CBC_SHA		0x03000089
+
+/* SEED ciphersuites from RFC4162 */
+#define TLS1_CK_RSA_WITH_SEED_SHA                       0x03000096
+#define TLS1_CK_DH_DSS_WITH_SEED_SHA                    0x03000097
+#define TLS1_CK_DH_RSA_WITH_SEED_SHA                    0x03000098
+#define TLS1_CK_DHE_DSS_WITH_SEED_SHA                   0x03000099
+#define TLS1_CK_DHE_RSA_WITH_SEED_SHA                   0x0300009A
+#define TLS1_CK_ADH_WITH_SEED_SHA                	0x0300009B
+
+/* ECC ciphersuites from draft-ietf-tls-ecc-12.txt with changes soon to be in draft 13 */
+#define TLS1_CK_ECDH_ECDSA_WITH_NULL_SHA                0x0300C001
+#define TLS1_CK_ECDH_ECDSA_WITH_RC4_128_SHA             0x0300C002
+#define TLS1_CK_ECDH_ECDSA_WITH_DES_192_CBC3_SHA        0x0300C003
+#define TLS1_CK_ECDH_ECDSA_WITH_AES_128_CBC_SHA         0x0300C004
+#define TLS1_CK_ECDH_ECDSA_WITH_AES_256_CBC_SHA         0x0300C005
+
+#define TLS1_CK_ECDHE_ECDSA_WITH_NULL_SHA               0x0300C006
+#define TLS1_CK_ECDHE_ECDSA_WITH_RC4_128_SHA            0x0300C007
+#define TLS1_CK_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA       0x0300C008
+#define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA        0x0300C009
+#define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA        0x0300C00A
+
+#define TLS1_CK_ECDH_RSA_WITH_NULL_SHA                  0x0300C00B
+#define TLS1_CK_ECDH_RSA_WITH_RC4_128_SHA               0x0300C00C
+#define TLS1_CK_ECDH_RSA_WITH_DES_192_CBC3_SHA          0x0300C00D
+#define TLS1_CK_ECDH_RSA_WITH_AES_128_CBC_SHA           0x0300C00E
+#define TLS1_CK_ECDH_RSA_WITH_AES_256_CBC_SHA           0x0300C00F
+
+#define TLS1_CK_ECDHE_RSA_WITH_NULL_SHA                 0x0300C010
+#define TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA              0x0300C011
+#define TLS1_CK_ECDHE_RSA_WITH_DES_192_CBC3_SHA         0x0300C012
+#define TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA          0x0300C013
+#define TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA          0x0300C014
+
+#define TLS1_CK_ECDH_anon_WITH_NULL_SHA                 0x0300C015
+#define TLS1_CK_ECDH_anon_WITH_RC4_128_SHA              0x0300C016
+#define TLS1_CK_ECDH_anon_WITH_DES_192_CBC3_SHA         0x0300C017
+#define TLS1_CK_ECDH_anon_WITH_AES_128_CBC_SHA          0x0300C018
+#define TLS1_CK_ECDH_anon_WITH_AES_256_CBC_SHA          0x0300C019
+
+/* XXX
+ * Inconsistency alert:
+ * The OpenSSL names of ciphers with ephemeral DH here include the string
+ * "DHE", while elsewhere it has always been "EDH".
+ * (The alias for the list of all such ciphers also is "EDH".)
+ * The specifications speak of "EDH"; maybe we should allow both forms
+ * for everything. */
+#define TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_MD5		"EXP1024-RC4-MD5"
+#define TLS1_TXT_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5	"EXP1024-RC2-CBC-MD5"
+#define TLS1_TXT_RSA_EXPORT1024_WITH_DES_CBC_SHA	"EXP1024-DES-CBC-SHA"
+#define TLS1_TXT_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA	"EXP1024-DHE-DSS-DES-CBC-SHA"
+#define TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_SHA		"EXP1024-RC4-SHA"
+#define TLS1_TXT_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA	"EXP1024-DHE-DSS-RC4-SHA"
+#define TLS1_TXT_DHE_DSS_WITH_RC4_128_SHA		"DHE-DSS-RC4-SHA"
+
+/* AES ciphersuites from RFC3268 */
+#define TLS1_TXT_RSA_WITH_AES_128_SHA			"AES128-SHA"
+#define TLS1_TXT_DH_DSS_WITH_AES_128_SHA		"DH-DSS-AES128-SHA"
+#define TLS1_TXT_DH_RSA_WITH_AES_128_SHA		"DH-RSA-AES128-SHA"
+#define TLS1_TXT_DHE_DSS_WITH_AES_128_SHA		"DHE-DSS-AES128-SHA"
+#define TLS1_TXT_DHE_RSA_WITH_AES_128_SHA		"DHE-RSA-AES128-SHA"
+#define TLS1_TXT_ADH_WITH_AES_128_SHA			"ADH-AES128-SHA"
+
+#define TLS1_TXT_RSA_WITH_AES_256_SHA			"AES256-SHA"
+#define TLS1_TXT_DH_DSS_WITH_AES_256_SHA		"DH-DSS-AES256-SHA"
+#define TLS1_TXT_DH_RSA_WITH_AES_256_SHA		"DH-RSA-AES256-SHA"
+#define TLS1_TXT_DHE_DSS_WITH_AES_256_SHA		"DHE-DSS-AES256-SHA"
+#define TLS1_TXT_DHE_RSA_WITH_AES_256_SHA		"DHE-RSA-AES256-SHA"
+#define TLS1_TXT_ADH_WITH_AES_256_SHA			"ADH-AES256-SHA"
+
+/* ECC ciphersuites from draft-ietf-tls-ecc-01.txt (Mar 15, 2001) */
+#define TLS1_TXT_ECDH_ECDSA_WITH_NULL_SHA               "ECDH-ECDSA-NULL-SHA"
+#define TLS1_TXT_ECDH_ECDSA_WITH_RC4_128_SHA            "ECDH-ECDSA-RC4-SHA"
+#define TLS1_TXT_ECDH_ECDSA_WITH_DES_192_CBC3_SHA       "ECDH-ECDSA-DES-CBC3-SHA"
+#define TLS1_TXT_ECDH_ECDSA_WITH_AES_128_CBC_SHA        "ECDH-ECDSA-AES128-SHA"
+#define TLS1_TXT_ECDH_ECDSA_WITH_AES_256_CBC_SHA        "ECDH-ECDSA-AES256-SHA"
+
+#define TLS1_TXT_ECDHE_ECDSA_WITH_NULL_SHA              "ECDHE-ECDSA-NULL-SHA"
+#define TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA           "ECDHE-ECDSA-RC4-SHA"
+#define TLS1_TXT_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA      "ECDHE-ECDSA-DES-CBC3-SHA"
+#define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA       "ECDHE-ECDSA-AES128-SHA"
+#define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA       "ECDHE-ECDSA-AES256-SHA"
+
+#define TLS1_TXT_ECDH_RSA_WITH_NULL_SHA                 "ECDH-RSA-NULL-SHA"
+#define TLS1_TXT_ECDH_RSA_WITH_RC4_128_SHA              "ECDH-RSA-RC4-SHA"
+#define TLS1_TXT_ECDH_RSA_WITH_DES_192_CBC3_SHA         "ECDH-RSA-DES-CBC3-SHA"
+#define TLS1_TXT_ECDH_RSA_WITH_AES_128_CBC_SHA          "ECDH-RSA-AES128-SHA"
+#define TLS1_TXT_ECDH_RSA_WITH_AES_256_CBC_SHA          "ECDH-RSA-AES256-SHA"
+
+#define TLS1_TXT_ECDHE_RSA_WITH_NULL_SHA                "ECDHE-RSA-NULL-SHA"
+#define TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA             "ECDHE-RSA-RC4-SHA"
+#define TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA        "ECDHE-RSA-DES-CBC3-SHA"
+#define TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA         "ECDHE-RSA-AES128-SHA"
+#define TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA         "ECDHE-RSA-AES256-SHA"
+
+#define TLS1_TXT_ECDH_anon_WITH_NULL_SHA                "AECDH-NULL-SHA"
+#define TLS1_TXT_ECDH_anon_WITH_RC4_128_SHA             "AECDH-RC4-SHA"
+#define TLS1_TXT_ECDH_anon_WITH_DES_192_CBC3_SHA        "AECDH-DES-CBC3-SHA"
+#define TLS1_TXT_ECDH_anon_WITH_AES_128_CBC_SHA         "AECDH-AES128-SHA"
+#define TLS1_TXT_ECDH_anon_WITH_AES_256_CBC_SHA         "AECDH-AES256-SHA"
+
+/* PSK ciphersuites from RFC 4279 */
+#define TLS1_TXT_PSK_WITH_RC4_128_SHA			"PSK-RC4-SHA"
+#define TLS1_TXT_PSK_WITH_3DES_EDE_CBC_SHA		"PSK-3DES-EDE-CBC-SHA"
+#define TLS1_TXT_PSK_WITH_AES_128_CBC_SHA		"PSK-AES128-CBC-SHA"
+#define TLS1_TXT_PSK_WITH_AES_256_CBC_SHA		"PSK-AES256-CBC-SHA"
+
+/* Camellia ciphersuites from RFC4132 */
+#define TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA		"CAMELLIA128-SHA"
+#define TLS1_TXT_DH_DSS_WITH_CAMELLIA_128_CBC_SHA	"DH-DSS-CAMELLIA128-SHA"
+#define TLS1_TXT_DH_RSA_WITH_CAMELLIA_128_CBC_SHA	"DH-RSA-CAMELLIA128-SHA"
+#define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA	"DHE-DSS-CAMELLIA128-SHA"
+#define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA	"DHE-RSA-CAMELLIA128-SHA"
+#define TLS1_TXT_ADH_WITH_CAMELLIA_128_CBC_SHA		"ADH-CAMELLIA128-SHA"
+
+#define TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA		"CAMELLIA256-SHA"
+#define TLS1_TXT_DH_DSS_WITH_CAMELLIA_256_CBC_SHA	"DH-DSS-CAMELLIA256-SHA"
+#define TLS1_TXT_DH_RSA_WITH_CAMELLIA_256_CBC_SHA	"DH-RSA-CAMELLIA256-SHA"
+#define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA	"DHE-DSS-CAMELLIA256-SHA"
+#define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA	"DHE-RSA-CAMELLIA256-SHA"
+#define TLS1_TXT_ADH_WITH_CAMELLIA_256_CBC_SHA		"ADH-CAMELLIA256-SHA"
+
+/* SEED ciphersuites from RFC4162 */
+#define TLS1_TXT_RSA_WITH_SEED_SHA                      "SEED-SHA"
+#define TLS1_TXT_DH_DSS_WITH_SEED_SHA                   "DH-DSS-SEED-SHA"
+#define TLS1_TXT_DH_RSA_WITH_SEED_SHA                   "DH-RSA-SEED-SHA"
+#define TLS1_TXT_DHE_DSS_WITH_SEED_SHA                  "DHE-DSS-SEED-SHA"
+#define TLS1_TXT_DHE_RSA_WITH_SEED_SHA                  "DHE-RSA-SEED-SHA"
+#define TLS1_TXT_ADH_WITH_SEED_SHA                      "ADH-SEED-SHA"
+
+
+#define TLS_CT_RSA_SIGN			1
+#define TLS_CT_DSS_SIGN			2
+#define TLS_CT_RSA_FIXED_DH		3
+#define TLS_CT_DSS_FIXED_DH		4
+#define TLS_CT_ECDSA_SIGN		64
+#define TLS_CT_RSA_FIXED_ECDH		65
+#define TLS_CT_ECDSA_FIXED_ECDH 	66
+#define TLS_CT_GOST94_SIGN		21
+#define TLS_CT_GOST01_SIGN		22
+/* when correcting this number, correct also SSL3_CT_NUMBER in ssl3.h (see
+ * comment there) */
+#define TLS_CT_NUMBER			9
+
+#define TLS1_FINISH_MAC_LENGTH		12
+
+#define TLS_MD_MAX_CONST_SIZE			20
+#define TLS_MD_CLIENT_FINISH_CONST		"client finished"
+#define TLS_MD_CLIENT_FINISH_CONST_SIZE		15
+#define TLS_MD_SERVER_FINISH_CONST		"server finished"
+#define TLS_MD_SERVER_FINISH_CONST_SIZE		15
+#define TLS_MD_SERVER_WRITE_KEY_CONST		"server write key"
+#define TLS_MD_SERVER_WRITE_KEY_CONST_SIZE	16
+#define TLS_MD_KEY_EXPANSION_CONST		"key expansion"
+#define TLS_MD_KEY_EXPANSION_CONST_SIZE		13
+#define TLS_MD_CLIENT_WRITE_KEY_CONST		"client write key"
+#define TLS_MD_CLIENT_WRITE_KEY_CONST_SIZE	16
+#define TLS_MD_SERVER_WRITE_KEY_CONST		"server write key"
+#define TLS_MD_SERVER_WRITE_KEY_CONST_SIZE	16
+#define TLS_MD_IV_BLOCK_CONST			"IV block"
+#define TLS_MD_IV_BLOCK_CONST_SIZE		8
+#define TLS_MD_MASTER_SECRET_CONST		"master secret"
+#define TLS_MD_MASTER_SECRET_CONST_SIZE		13
+
+#ifdef CHARSET_EBCDIC
+#undef TLS_MD_CLIENT_FINISH_CONST
+#define TLS_MD_CLIENT_FINISH_CONST    "\x63\x6c\x69\x65\x6e\x74\x20\x66\x69\x6e\x69\x73\x68\x65\x64"  /*client finished*/
+#undef TLS_MD_SERVER_FINISH_CONST
+#define TLS_MD_SERVER_FINISH_CONST    "\x73\x65\x72\x76\x65\x72\x20\x66\x69\x6e\x69\x73\x68\x65\x64"  /*server finished*/
+#undef TLS_MD_SERVER_WRITE_KEY_CONST
+#define TLS_MD_SERVER_WRITE_KEY_CONST "\x73\x65\x72\x76\x65\x72\x20\x77\x72\x69\x74\x65\x20\x6b\x65\x79"  /*server write key*/
+#undef TLS_MD_KEY_EXPANSION_CONST
+#define TLS_MD_KEY_EXPANSION_CONST    "\x6b\x65\x79\x20\x65\x78\x70\x61\x6e\x73\x69\x6f\x6e"  /*key expansion*/
+#undef TLS_MD_CLIENT_WRITE_KEY_CONST
+#define TLS_MD_CLIENT_WRITE_KEY_CONST "\x63\x6c\x69\x65\x6e\x74\x20\x77\x72\x69\x74\x65\x20\x6b\x65\x79"  /*client write key*/
+#undef TLS_MD_SERVER_WRITE_KEY_CONST
+#define TLS_MD_SERVER_WRITE_KEY_CONST "\x73\x65\x72\x76\x65\x72\x20\x77\x72\x69\x74\x65\x20\x6b\x65\x79"  /*server write key*/
+#undef TLS_MD_IV_BLOCK_CONST
+#define TLS_MD_IV_BLOCK_CONST         "\x49\x56\x20\x62\x6c\x6f\x63\x6b"  /*IV block*/
+#undef TLS_MD_MASTER_SECRET_CONST
+#define TLS_MD_MASTER_SECRET_CONST    "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74"  /*master secret*/
+#endif
+
+/* TLS Session Ticket extension struct */
+struct tls_session_ticket_ext_st
+	{
+	unsigned short length;
+	void *data;
+	};
+
+#ifdef  __cplusplus
+}
+#endif
+#endif