Import of old SSLeay release: SSLeay 0.8.1b
diff --git a/ssl/Makefile.ssl b/ssl/Makefile.ssl
new file mode 100644
index 0000000..f6f40e4
--- /dev/null
+++ b/ssl/Makefile.ssl
@@ -0,0 +1,98 @@
+#
+# SSLeay/ssl/Makefile
+#
+
+DIR=	ssl
+TOP=	..
+CC=	cc
+INCLUDES= -I../crypto -I../include
+CFLAG=-g
+INSTALLTOP=/usr/local/ssl
+MAKE=		make -f Makefile.ssl
+MAKEDEPEND=	makedepend -f Makefile.ssl
+MAKEFILE=	Makefile.ssl
+AR=		ar r
+
+CFLAGS= $(INCLUDES) $(CFLAG)
+
+ERR=ssl
+ERRC=ssl_err
+GENERAL=Makefile README
+TEST=ssltest.c
+APPS=
+
+LIB=$(TOP)/libssl.a
+LIBSRC=	\
+	s2_meth.c   s2_srvr.c s2_clnt.c  s2_lib.c  s2_pkt.c s2_enc.c \
+	s3_meth.c   s3_srvr.c s3_clnt.c  s3_lib.c  s3_pkt.c s3_enc.c s3_both.c \
+	s23_meth.c s23_srvr.c s23_clnt.c s23_lib.c s23_pkt.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 $(ERRC).c
+LIBOBJ= \
+	s2_meth.o  s2_srvr.o  s2_clnt.o  s2_lib.o  s2_pkt.o s2_enc.o \
+	s3_meth.o  s3_srvr.o  s3_clnt.o  s3_lib.o  s3_pkt.o s3_enc.o s3_both.o \
+	s23_meth.o s23_srvr.o s23_clnt.o s23_lib.o s23_pkt.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 $(ERRC).o
+
+SRC= $(LIBSRC)
+
+EXHEADER= ssl.h ssl2.h ssl3.h ssl23.h
+HEADER=	$(EXHEADER) ssl_locl.h
+
+ALL=    $(GENERAL) $(SRC) $(HEADER)
+
+top:
+	(cd ..; $(MAKE) DIRS=$(DIR) all)
+
+all:	lib
+
+lib:	$(LIBOBJ)
+	$(AR) $(LIB) $(LIBOBJ)
+	sh $(TOP)/util/ranlib.sh $(LIB)
+	@touch lib
+
+files:
+	perl $(TOP)/util/files.pl Makefile.ssl >> $(TOP)/MINFO
+
+links:
+	/bin/rm -f Makefile
+	$(TOP)/util/point.sh Makefile.ssl Makefile ;
+	$(TOP)/util/mklink.sh ../include $(EXHEADER)
+	$(TOP)/util/mklink.sh ../test $(TEST)
+	$(TOP)/util/mklink.sh ../apps $(APPS)
+
+install:
+	@for i in $(EXHEADER) ; \
+	do  \
+	(cp $$i $(INSTALLTOP)/include/$$i; \
+	chmod 644 $(INSTALLTOP)/include/$$i ); \
+	done;
+
+tags:
+	ctags $(SRC)
+
+tests:
+
+lint:
+	lint -DLINT $(INCLUDES) $(SRC)>fluff
+
+depend:
+	$(MAKEDEPEND) $(INCLUDES) $(PROGS) $(LIBSRC)
+
+dclean:
+	perl -pe 'if (/^# DO NOT DELETE THIS LINE/) {print; exit(0);}' $(MAKEFILE) >Makefile.new
+	mv -f Makefile.new $(MAKEFILE)
+
+clean:
+	/bin/rm -f *.o *.obj lib tags core .pure .nfs* *.old *.bak fluff
+
+errors:
+	perl $(TOP)/util/err-ins.pl $(ERR).err $(ERR).h
+	perl ../crypto/err/err_genc.pl $(ERR).h $(ERRC).c
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
diff --git a/ssl/bio_ssl.c b/ssl/bio_ssl.c
new file mode 100644
index 0000000..6c0baba
--- /dev/null
+++ b/ssl/bio_ssl.c
@@ -0,0 +1,432 @@
+/* ssl/bio_ssl.c */
+/* Copyright (C) 1995-1997 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 <string.h>
+#include <errno.h>
+#include "bio.h"
+#include "err.h"
+#include "ssl.h"
+
+#ifndef NOPROTO
+static int ssl_write(BIO *h,char *buf,int num);
+static int ssl_read(BIO *h,char *buf,int size);
+static int ssl_puts(BIO *h,char *str);
+static long ssl_ctrl(BIO *h,int cmd,long arg1,char *arg2);
+static int ssl_new(BIO *h);
+static int ssl_free(BIO *data);
+#else
+static int ssl_write();
+static int ssl_read();
+static int ssl_puts();
+static long ssl_ctrl();
+static int ssl_new();
+static int ssl_free();
+#endif
+
+static BIO_METHOD methods_sslp=
+	{
+	BIO_TYPE_SSL,"ssl",
+	ssl_write,
+	ssl_read,
+	ssl_puts,
+	NULL, /* ssl_gets, */
+	ssl_ctrl,
+	ssl_new,
+	ssl_free,
+	};
+
+BIO_METHOD *BIO_f_ssl()
+	{
+	return(&methods_sslp);
+	}
+
+static int ssl_new(bi)
+BIO *bi;
+	{
+	bi->init=0;
+	bi->ptr=NULL;	/* The SSL structure */
+	bi->flags=0;
+	return(1);
+	}
+
+static int ssl_free(a)
+BIO *a;
+	{
+	if (a == NULL) return(0);
+	if (a->ptr != NULL) SSL_shutdown((SSL *)a->ptr);
+	if (a->shutdown)
+		{
+		if (a->init) SSL_free((SSL *)a->ptr);
+		a->init=0;
+		a->flags=0;
+		a->ptr=NULL;
+		}
+	return(1);
+	}
+	
+static int ssl_read(b,out,outl)
+BIO *b;
+char *out;
+int outl;
+	{
+	int ret=1;
+	int inflags,outflags;
+	SSL *ssl;
+	int retry_reason=0;
+
+	if (out == NULL) return(0);
+	ssl=(SSL *)b->ptr;
+
+	inflags=outflags=b->flags;
+
+	outflags&= ~(BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY);
+
+	if (!SSL_is_init_finished(ssl))
+		{
+		ret=SSL_do_handshake(ssl);
+#if 0
+		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;
+		break;
+	case SSL_ERROR_WANT_READ:
+		outflags=(BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY);
+		break;
+	case SSL_ERROR_WANT_WRITE:
+		outflags=(BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY);
+		break;
+	case SSL_ERROR_WANT_X509_LOOKUP:
+		outflags=(BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY);
+		retry_reason=BIO_RR_SSL_X509_LOOKUP;
+		break;
+	case SSL_ERROR_WANT_CONNECT:
+		outflags=(BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY);
+		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;
+	b->flags=outflags;
+	return(ret);
+	}
+
+static int ssl_write(b,out,outl)
+BIO *b;
+char *out;
+int outl;
+	{
+	int ret;
+	int inflags,outflags,retry_reason=0;
+	SSL *ssl;
+
+	if (out == NULL) return(0);
+	ssl=(SSL *)b->ptr;
+
+	inflags=outflags=b->flags;
+
+	outflags&= ~(BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY);
+
+	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;
+		break;
+	case SSL_ERROR_WANT_WRITE:
+		outflags=(BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY);
+		break;
+	case SSL_ERROR_WANT_READ:
+		outflags=(BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY);
+		break;
+	case SSL_ERROR_WANT_X509_LOOKUP:
+		outflags=(BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY);
+		retry_reason=BIO_RR_SSL_X509_LOOKUP;
+		break;
+	case SSL_ERROR_WANT_CONNECT:
+		outflags=(BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY);
+		retry_reason=BIO_RR_CONNECT;
+	case SSL_ERROR_SYSCALL:
+	case SSL_ERROR_SSL:
+	default:
+		break;
+		}
+
+	b->retry_reason=retry_reason;
+	b->flags=outflags;
+	return(ret);
+	}
+
+static long ssl_ctrl(b,cmd,num,ptr)
+BIO *b;
+int cmd;
+long num;
+char *ptr;
+	{
+	SSL **sslp,*ssl;
+	BIO *dbio,*bio;
+	long ret=1;
+
+	ssl=(SSL *)b->ptr;
+	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_EOF:
+	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:
+		ssl_free(b);
+		b->shutdown=(int)num;
+		b->ptr=ptr;
+		ssl=(SSL *)ptr;
+		bio=SSL_get_rbio(ssl);
+		if (bio != NULL)
+			{
+			if (b->next_bio != NULL)
+				BIO_push(bio,b->next_bio);
+			b->next_bio=bio;
+			}
+		b->init=1;
+		break;
+	case BIO_C_GET_SSL:
+		if (ptr != NULL)
+			{
+			sslp=(SSL **)ptr;
+			*sslp=ssl;
+			}
+		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)
+			{
+			SSL_set_bio(ssl,b->next_bio,b->next_bio);
+			b->next_bio->references++;
+			}
+		break;
+	case BIO_CTRL_POP:
+		/* ugly bit of a hack */
+		if (ssl->rbio != ssl->wbio) /* we are in trouble :-( */
+			{
+			BIO_free_all(ssl->wbio);
+			}
+		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 (dbio->ptr != NULL)
+			SSL_free((SSL *)dbio->ptr);
+		dbio->ptr=(char *)SSL_dup(ssl);
+		ret=(dbio->ptr != NULL);
+		break;
+	default:
+		return(0);
+		break;
+		}
+	return(ret);
+	}
+
+static int ssl_puts(bp,str)
+BIO *bp;
+char *str;
+	{
+	int n,ret;
+
+	n=strlen(str);
+	ret=BIO_write(bp,str,n);
+	return(ret);
+	}
+
+BIO *BIO_new_ssl(ctx,client)
+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(t,f)
+BIO *t,*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 ((t->ptr == NULL) || (f->ptr == NULL))
+		return(0);
+	SSL_copy_session_id((SSL *)t->ptr,(SSL *)f->ptr);
+	return(1);
+	}
+
+void BIO_ssl_shutdown(b)
+BIO *b;
+	{
+	SSL *s;
+
+	while (b != NULL)
+		{
+		if (b->method->type == BIO_TYPE_SSL)
+			{
+			s=(SSL *)b->ptr;
+			SSL_shutdown(s);
+			break;
+			}
+		b=b->next_bio;
+		}
+	}
diff --git a/ssl/bio_ssl.orig.c b/ssl/bio_ssl.orig.c
new file mode 100644
index 0000000..25147d1
--- /dev/null
+++ b/ssl/bio_ssl.orig.c
@@ -0,0 +1,440 @@
+/* ssl/bio_ssl.c */
+/* Copyright (C) 1995-1997 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 <string.h>
+#include <errno.h>
+#include "bio.h"
+#include "err.h"
+#include "ssl.h"
+
+#ifndef NOPROTO
+static int ssl_write(BIO *h,char *buf,int num);
+static int ssl_read(BIO *h,char *buf,int size);
+static int ssl_puts(BIO *h,char *str);
+static long ssl_ctrl(BIO *h,int cmd,long arg1,char *arg2);
+static int ssl_new(BIO *h);
+static int ssl_free(BIO *data);
+#else
+static int ssl_write();
+static int ssl_read();
+static int ssl_puts();
+static long ssl_ctrl();
+static int ssl_new();
+static int ssl_free();
+#endif
+
+static BIO_METHOD methods_sslp=
+	{
+	BIO_TYPE_SSL,"ssl",
+	ssl_write,
+	ssl_read,
+	ssl_puts,
+	NULL, /* ssl_gets, */
+	ssl_ctrl,
+	ssl_new,
+	ssl_free,
+	};
+
+BIO_METHOD *BIO_f_ssl()
+	{
+	return(&methods_sslp);
+	}
+
+static int ssl_new(bi)
+BIO *bi;
+	{
+	bi->init=0;
+	bi->ptr=NULL;	/* The SSL structure */
+	bi->flags=0;
+	return(1);
+	}
+
+static int ssl_free(a)
+BIO *a;
+	{
+	if (a == NULL) return(0);
+	if (a->ptr != NULL) SSL_shutdown((SSL *)a->ptr);
+	if (a->shutdown)
+		{
+		if (a->init) SSL_free((SSL *)a->ptr);
+		a->init=0;
+		a->flags=0;
+		a->ptr=NULL;
+		}
+	return(1);
+	}
+	
+static int ssl_read(b,out,outl)
+BIO *b;
+char *out;
+int outl;
+	{
+	int ret=1,dr,dw;
+	int inflags,outflags;
+	SSL *ssl;
+	int retry_reason=0;
+
+	if (out == NULL) return(0);
+	ssl=(SSL *)b->ptr;
+
+	inflags=outflags=b->flags;
+
+	dr=inflags&BIO_FLAGS_PROTOCOL_DELAYED_READ;
+	dw=inflags&BIO_FLAGS_PROTOCOL_DELAYED_WRITE;
+
+	outflags&= ~(BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY|
+		BIO_FLAGS_PROTOCOL_DELAYED_WRITE|
+		BIO_FLAGS_PROTOCOL_DELAYED_READ);
+
+	if (!SSL_is_init_finished(ssl))
+		{
+		ret=SSL_do_handshake(ssl);
+#if 0
+		if (ret > 0)
+			{
+			outflags=(BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY|
+				BIO_FLAGS_PROTOCOL_DELAYED_READ|dw);
+			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 (dw)
+			outflags|=(BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY);
+		break;
+	case SSL_ERROR_WANT_READ:
+		outflags=(BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY|
+			BIO_FLAGS_PROTOCOL_DELAYED_READ|dw);
+		break;
+	case SSL_ERROR_WANT_WRITE:
+		outflags=(BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY|
+			BIO_FLAGS_PROTOCOL_DELAYED_READ|dw);
+		break;
+	case SSL_ERROR_WANT_X509_LOOKUP:
+		outflags=(BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY|
+			BIO_FLAGS_PROTOCOL_DELAYED_READ|dw);
+		retry_reason=BIO_RR_SSL_X509_LOOKUP;
+		break;
+	case SSL_ERROR_WANT_CONNECT:
+		outflags=(BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY|
+			BIO_FLAGS_PROTOCOL_DELAYED_READ|dw);
+		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;
+	b->flags=outflags;
+	return(ret);
+	}
+
+static int ssl_write(b,out,outl)
+BIO *b;
+char *out;
+int outl;
+	{
+	int ret,dr,dw;
+	int inflags,outflags,retry_reason=0;
+	SSL *ssl;
+
+	if (out == NULL) return(0);
+	ssl=(SSL *)b->ptr;
+
+	inflags=outflags=b->flags;
+
+	dr=inflags&BIO_FLAGS_PROTOCOL_DELAYED_READ;
+	dw=inflags&BIO_FLAGS_PROTOCOL_DELAYED_WRITE;
+
+	outflags&= ~(BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY|
+		BIO_FLAGS_PROTOCOL_DELAYED_WRITE|
+		BIO_FLAGS_PROTOCOL_DELAYED_READ);
+
+	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 (dr)
+			outflags|=(BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY);
+		break;
+	case SSL_ERROR_WANT_WRITE:
+		outflags=(BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY|
+			BIO_FLAGS_PROTOCOL_DELAYED_WRITE|dr);
+		break;
+	case SSL_ERROR_WANT_READ:
+		outflags=(BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY|
+			BIO_FLAGS_PROTOCOL_DELAYED_WRITE|dr);
+		break;
+	case SSL_ERROR_WANT_X509_LOOKUP:
+		outflags=(BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY|
+			BIO_FLAGS_PROTOCOL_DELAYED_WRITE|dr);
+		retry_reason=BIO_RR_SSL_X509_LOOKUP;
+		break;
+	case SSL_ERROR_WANT_CONNECT:
+		outflags=(BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY|
+			BIO_FLAGS_PROTOCOL_DELAYED_READ|dw);
+		retry_reason=BIO_RR_CONNECT;
+	case SSL_ERROR_SYSCALL:
+	case SSL_ERROR_SSL:
+	default:
+		break;
+		}
+
+	b->retry_reason=retry_reason;
+	b->flags=outflags;
+	return(ret);
+	}
+
+static long ssl_ctrl(b,cmd,num,ptr)
+BIO *b;
+int cmd;
+long num;
+char *ptr;
+	{
+	SSL **sslp,*ssl;
+	BIO *dbio,*bio;
+	long ret=1;
+
+	ssl=(SSL *)b->ptr;
+	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_EOF:
+	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:
+		ssl_free(b);
+		b->shutdown=(int)num;
+		b->ptr=ptr;
+		ssl=(SSL *)ptr;
+		bio=SSL_get_rbio(ssl);
+		if (bio != NULL)
+			{
+			if (b->next_bio != NULL)
+				BIO_push(bio,b->next_bio);
+			b->next_bio=bio;
+			}
+		b->init=1;
+		break;
+	case BIO_C_GET_SSL:
+		if (ptr != NULL)
+			{
+			sslp=(SSL **)ptr;
+			*sslp=ssl;
+			}
+		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)
+			{
+			SSL_set_bio(ssl,b->next_bio,b->next_bio);
+			b->next_bio->references++;
+			}
+		break;
+	case BIO_CTRL_POP:
+		/* ugly bit of a hack */
+		if (ssl->rbio != ssl->wbio) /* we are in trouble :-( */
+			{
+			BIO_free_all(ssl->wbio);
+			}
+		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,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 (dbio->ptr != NULL)
+			SSL_free((SSL *)dbio->ptr);
+		dbio->ptr=(char *)SSL_dup(ssl);
+		ret=(dbio->ptr != NULL);
+		break;
+	default:
+		return(0);
+		break;
+		}
+	return(ret);
+	}
+
+static int ssl_puts(bp,str)
+BIO *bp;
+char *str;
+	{
+	int n,ret;
+
+	n=strlen(str);
+	ret=BIO_write(bp,str,n);
+	return(ret);
+	}
+
+BIO *BIO_new_ssl(ctx,client)
+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(t,f)
+BIO *t,*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 ((t->ptr == NULL) || (f->ptr == NULL))
+		return(0);
+	SSL_copy_session_id((SSL *)t->ptr,(SSL *)f->ptr);
+	return(1);
+	}
+
+
diff --git a/ssl/build b/ssl/build
new file mode 100644
index 0000000..d330835
--- /dev/null
+++ b/ssl/build
@@ -0,0 +1,6 @@
+#!/bin/sh
+for i in BUILD_SSLV23 BUILD_SSLV2 BUILD_SSLV3 BUILD_SSL_COMMON BUILD_SSL_BIO BUILD_SSL_OPTIONAL
+do
+time gcc -D$i -o $i.o -c -I. -I../include -O3 -fomit-frame-pointer ssl.c
+done
+
diff --git a/ssl/changes.ssl b/ssl/changes.ssl
new file mode 100644
index 0000000..ab94b95
--- /dev/null
+++ b/ssl/changes.ssl
@@ -0,0 +1,10 @@
+
+Must do a 
+SSL_init_eay_ciphers();
+before calls to SSL_CTX_new()
+
+SSL_CTX *SSL_CTX_new(void ) -> SSL_CTX *SSL_CTX_new(SSL_METHOD *meth);
+
+SSL_CTX_set_cert_verify_cb -> the callback is now
+int callback(char *arg,SSL *s,X509 *xs,STACK *cert_chain);
+where the 'cert_chain' has been added.
diff --git a/ssl/f b/ssl/f
new file mode 100644
index 0000000..8730ef5
--- /dev/null
+++ b/ssl/f
@@ -0,0 +1,40 @@
+/* return the actual cipher being used */
+char *SSL_CIPHER_get_name(c)
+SSL_CIPHER *c;
+	{
+	if (c != NULL)
+		return(c->name);
+	return("UNKNOWN");
+	}
+
+/* number of bits for symetric cipher */
+int SSL_CIPHER_get_bits(c,alg_bits)
+SSL_CIPHER *c;
+int *alg_bits;
+	{
+	int ret=0,a=0;
+	EVP_CIPHER *enc;
+
+	if (c != NULL)
+		{
+		if (!ssl_cipher_get_evp(c,&enc,NULL))
+			return(0);
+
+		a=EVP_CIPHER_key_length(enc)*8;
+
+		if (s->session->cipher->algorithms & SSL_EXP)
+			{
+			if (c->algorithm2 & SSL2_CF_8_BYTE_ENC)
+				ret=64;
+			else
+				ret=40;
+			}
+		else
+			ret=a;
+		}
+
+	if (alg_bits != NULL) *alg_bits=a;
+	
+	return(ret);
+	}
+
diff --git a/ssl/readme b/ssl/readme
new file mode 100644
index 0000000..ca17484
--- /dev/null
+++ b/ssl/readme
@@ -0,0 +1,277 @@
+22 Jun 1996
+This file belongs in ../apps, but I'll leave it here because it deals
+with SSL :-)  It is rather dated but it gives you an idea of how
+things work.
+===
+
+17 Jul 1995
+I have been changing things quite a bit and have not fully updated
+this file, so take what you read with a grain of salt
+eric
+===
+The s_client and s_server programs can be used to test SSL capable
+IP/port addresses and the verification of the X509 certificates in use
+by these services.  I strongly advise having a look at the code to get
+an idea of how to use the authentication under SSLeay.  Any feedback
+on changes and improvements would be greatly accepted.
+
+This file will probably be gibberish unless you have read
+rfc1421, rfc1422, rfc1423 and rfc1424 which describe PEM
+authentication.
+
+A Brief outline (and examples) how to use them to do so.
+
+NOTE:
+The environment variable SSL_CIPER is used to specify the prefered
+cipher to use, play around with setting it's value to combinations of
+RC4-MD5, EXP-RC4-MD5, CBC-DES-MD5, CBC3-DES-MD5, CFB-DES-NULL
+in a : separated list.
+
+This directory contains 3 X509 certificates which can be used by these programs.
+client.pem: a file containing a certificate and private key to be used
+	by s_client.
+server.pem :a file containing a certificate and private key to be used
+	by s_server.
+eay1024.pem:the certificate used to sign client.pem and server.pem.
+	This would be your CA's certificate.  There is also a link
+	from the file a8556381.0 to eay1024.PEM.  The value a8556381
+	is returned by 'x509 -hash -noout <eay1024.pem' and is the
+	value used by X509 verification routines to 'find' this
+	certificte when search a directory for it.
+	[the above is not true any more, the CA cert is 
+	 ../certs/testca.pem which is signed by ../certs/mincomca.pem]
+
+When testing the s_server, you may get
+bind: Address already in use
+errors.  These indicate the port is still being held by the unix
+kernel and you are going to have to wait for it to let go of it.  If
+this is the case, remember to use the port commands on the s_server and
+s_client to talk on an alternative port.
+
+=====
+s_client.
+This program can be used to connect to any IP/hostname:port that is
+talking SSL.  Once connected, it will attempt to authenticate the
+certificate it was passed and if everything works as expected, a 2
+directional channel will be open.  Any text typed will be sent to the
+other end.  type Q<cr> to exit.  Flags are as follows.
+-host arg	: Arg is the host or IP address to connect to.
+-port arg	: Arg is the port to connect to (https is 443).
+-verify arg	: Turn on authentication of the server certificate.
+		: Arg specifies the 'depth', this will covered below.
+-cert arg	: The optional certificate to use.  This certificate
+		: will be returned to the server if the server
+		: requests it for client authentication.
+-key arg	: The private key that matches the certificate
+		: specified by the -cert option.  If this is not
+		: specified (but -cert is), the -cert file will be
+		: searched for the Private key.  Both files are
+		: assumed to be in PEM format.
+-CApath arg	: When to look for certificates when 'verifying' the
+		: certificate from the server.
+-CAfile arg	: A file containing certificates to be used for
+		: 'verifying' the server certificate.
+-reconnect	: Once a connection has been made, drop it and
+		: reconnect with same session-id.  This is for testing :-).
+
+The '-verify n' parameter specifies not only to verify the servers
+certificate but to also only take notice of 'n' levels.  The best way
+to explain is to show via examples.
+Given
+s_server -cert server.PEM is running.
+
+s_client
+	CONNECTED
+	depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo server
+	issuer= /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA
+	verify error:num=1:unable to get issuer certificate
+	verify return:1
+	CIPHER is CBC-DES-MD5
+What has happened is that the 'SSLeay demo server' certificate's
+issuer ('CA') could not be found but because verify is not on, we
+don't care and the connection has been made anyway.  It is now 'up'
+using CBC-DES-MD5 mode.  This is an unauthenticate secure channel.
+You may not be talking to the right person but the data going to them
+is encrypted.
+
+s_client -verify 0
+	CONNECTED
+	depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo server
+	issuer= /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA
+	verify error:num=1:unable to get issuer certificate
+	verify return:1
+	CIPHER is CBC-DES-MD5
+We are 'verifying' but only to depth 0, so since the 'SSLeay demo server'
+certificate passed the date and checksum, we are happy to proceed.
+
+s_client -verify 1
+	CONNECTED
+	depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo server
+	issuer= /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA
+	verify error:num=1:unable to get issuer certificate
+	verify return:0
+	ERROR
+	verify error:unable to get issuer certificate
+In this case we failed to make the connection because we could not
+authenticate the certificate because we could not find the
+'CA' certificate.
+
+s_client -verify 1 -CAfile eay1024.PEM
+	CONNECTED
+	depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo server
+	verify return:1
+	depth=1 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA
+	verify return:1
+	CIPHER is CBC-DES-MD5
+We loaded the certificates from the file eay1024.PEM.  Everything
+checked out and so we made the connection.
+
+s_client -verify 1 -CApath .
+	CONNECTED
+	depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo server
+	verify return:1
+	depth=1 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA
+	verify return:1
+	CIPHER is CBC-DES-MD5
+We looked in out local directory for issuer certificates and 'found'
+a8556381.0 and so everything is ok.
+
+It is worth noting that 'CA' is a self certified certificate.  If you
+are passed one of these, it will fail to 'verify' at depth 0 because
+we need to lookup the certifier of a certificate from some information
+that we trust and keep locally.
+
+SSL_CIPHER=CBC3-DES-MD5:RC4-MD5
+export SSL_CIPHER
+s_client -verify 10 -CApath . -reconnect
+	CONNECTED
+	depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo server
+	verify return:1
+	depth=1 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA
+	verify return:1
+	drop the connection and reconnect with the same session id
+	CIPHER is CBC3-DES-MD5
+This has done a full connection and then re-estabished it with the
+same session id but a new socket.  No RSA stuff occures on the second
+connection.  Note that we said we would prefer to use CBC3-DES-MD5
+encryption and so, since the server supports it, we are.
+
+=====
+s_server
+This program accepts SSL connections on a specified port
+Once connected, it will estabish an SSL connection and optionaly
+attempt to authenticate the client.  A 2 directional channel will be
+open.  Any text typed will be sent to the other end.  Type Q<cr> to exit.
+Flags are as follows.
+-port arg	: Arg is the port to listen on.
+-verify arg	: Turn on authentication of the client if they have a
+		: certificate.  Arg specifies the 'depth'.
+-Verify arg	: Turn on authentication of the client. If they don't
+		: have a valid certificate, drop the connection.
+-cert arg	: The certificate to use.  This certificate
+		: will be passed to the client.  If it is not
+		: specified, it will default to server.PEM
+-key arg	: The private key that matches the certificate
+		: specified by the -cert option.  If this is not
+		: specified (but -cert is), the -cert file will be
+		: searched for the Private key.  Both files are
+		: assumed to be in PEM format.  Default is server.PEM
+-CApath arg	: When to look for certificates when 'verifying' the
+		: certificate from the client.
+-CAfile arg	: A file containing certificates to be used for
+		: 'verifying' the client certificate.
+
+For the following 'demo'  I will specify the s_server command and
+the s_client command and then list the output from the s_server.
+s_server
+s_client
+	CONNECTED
+	CIPHER is CBC-DES-MD5
+Everything up and running
+
+s_server -verify 0
+s_client  
+	CONNECTED
+	CIPHER is CBC-DES-MD5
+Ok since no certificate was returned and we don't care.
+
+s_server -verify 0
+./s_client -cert client.PEM
+	CONNECTED
+	depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo client
+	issuer= /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA
+	verify error:num=1:unable to get issuer certificate
+	verify return:1
+	CIPHER is CBC-DES-MD5
+Ok since we were only verifying to level 0
+
+s_server -verify 4
+s_client -cert client.PEM
+	CONNECTED
+	depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo client
+	issuer= /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA
+	verify error:num=1:unable to get issuer certificate
+	verify return:0
+	ERROR
+	verify error:unable to get issuer certificate
+Bad because we could not authenticate the returned certificate.
+
+s_server -verify 4 -CApath .
+s_client -cert client.PEM
+	CONNECTED
+	depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo client
+	verify return:1
+	depth=1 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA
+	verify return:1
+	CIPHER is CBC-DES-MD5
+Ok because we could authenticate the returned certificate :-).
+
+s_server -Verify 0 -CApath .
+s_client
+	CONNECTED
+	ERROR
+	SSL error:function is:REQUEST_CERTIFICATE
+		 :error is   :client end did not return a certificate
+Error because no certificate returned.
+
+s_server -Verify 4 -CApath .
+s_client -cert client.PEM
+	CONNECTED
+	depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo client
+	verify return:1
+	depth=1 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA
+	verify return:1
+	CIPHER is CBC-DES-MD5
+Full authentication of the client.
+
+So in summary to do full authentication of both ends
+s_server -Verify 9 -CApath .
+s_client -cert client.PEM -CApath . -verify 9
+From the server side
+	CONNECTED
+	depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo client
+	verify return:1
+	depth=1 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA
+	verify return:1
+	CIPHER is CBC-DES-MD5
+From the client side
+	CONNECTED
+	depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo server
+	verify return:1
+	depth=1 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA
+	verify return:1
+	CIPHER is CBC-DES-MD5
+
+For general probing of the 'internet https' servers for the
+distribution area, run
+s_client -host www.netscape.com -port 443 -verify 4 -CApath ../rsa/hash
+Then enter
+GET /
+and you should be talking to the https server on that host.
+
+www.rsa.com was refusing to respond to connections on 443 when I was
+testing.
+
+have fun :-).
+
+eric
diff --git a/ssl/s23_clnt.c b/ssl/s23_clnt.c
new file mode 100644
index 0000000..57d3623
--- /dev/null
+++ b/ssl/s23_clnt.c
@@ -0,0 +1,444 @@
+/* ssl/s23_clnt.c */
+/* Copyright (C) 1995-1997 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 "buffer.h"
+#include "rand.h"
+#include "objects.h"
+#include "evp.h"
+#include "ssl_locl.h"
+
+#define BREAK break
+
+#ifndef NOPROTO
+static int ssl23_client_hello(SSL *s);
+static int ssl23_get_server_hello(SSL *s);
+#else
+static int ssl23_client_hello();
+static int ssl23_get_server_hello();
+#endif
+
+static SSL_METHOD *ssl23_get_client_method(ver)
+int ver;
+	{
+	if (ver == 2)
+		return(SSLv2_client_method());
+	else if (ver == 3)
+		return(SSLv3_client_method());
+	else
+		return(NULL);
+	}
+
+SSL_METHOD *SSLv23_client_method()
+	{
+	static int init=1;
+	static SSL_METHOD SSLv23_client_data;
+
+	if (init)
+		{
+		init=0;
+		memcpy((char *)&SSLv23_client_data,
+			(char *)sslv23_base_method(),sizeof(SSL_METHOD));
+		SSLv23_client_data.ssl_connect=ssl23_connect;
+		SSLv23_client_data.get_ssl_method=ssl23_get_client_method;
+		}
+	return(&SSLv23_client_data);
+	}
+
+int ssl23_connect(s)
+SSL *s;
+	{
+	BUF_MEM *buf;
+	unsigned long Time=time(NULL);
+	void (*cb)()=NULL;
+	int ret= -1;
+	int new_state,state;
+
+	RAND_seed((unsigned char *)&Time,sizeof(Time));
+	ERR_clear_error();
+	errno=0;
+
+	if (s->info_callback != NULL)
+		cb=s->info_callback;
+	else if (s->ctx->info_callback != NULL)
+		cb=s->ctx->info_callback;
+	
+	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); 
+	s->in_handshake++;
+
+	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 (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
+
+			s->version=3;
+			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;
+				}
+
+			if (!ssl3_setup_buffers(s)) { ret= -1; goto end; }
+
+			ssl3_init_finished_mac(s);
+
+			s->state=SSL23_ST_CW_CLNT_HELLO_A;
+			s->ctx->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) 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 (cb != NULL)
+		cb(s,SSL_CB_CONNECT_EXIT,ret);
+	return(ret);
+	}
+
+
+static int ssl23_client_hello(s)
+SSL *s;
+	{
+	unsigned char *buf;
+	unsigned char *p,*d;
+	int i,ch_len;
+
+	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;
+		RAND_bytes(p,SSL3_RANDOM_SIZE);
+
+		/* Do the message type and length last */
+		d= &(buf[2]);
+		p=d+9;
+
+		*(d++)=SSL2_MT_CLIENT_HELLO;
+		*(d++)=SSL3_VERSION_MAJOR;
+		*(d++)=SSL3_VERSION_MINOR;
+
+		/* Ciphers supported */
+		i=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),p);
+		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, zero since there is no
+		 * reuse. */
+#if 0
+		s->session->session_id_length=0;
+#endif
+		s2n(0,d);
+
+		if (s->ctx->options & SSL_OP_NETSCAPE_CHALLENGE_BUG)
+			ch_len=SSL2_CHALLENGE_LENGTH;
+		else
+			ch_len=SSL2_MAX_CHALLENGE_LENGTH;
+
+		/* write out sslv2 challenge */
+		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);
+		RAND_bytes(&(s->s3->client_random[SSL3_RANDOM_SIZE-i]),i);
+		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);
+
+		s->state=SSL23_ST_CW_CLNT_HELLO_B;
+		/* number of bytes to write */
+		s->init_num=i+2;
+		s->init_off=0;
+
+		ssl3_finish_mac(s,&(buf[2]),i);
+		}
+
+	/* SSL3_ST_CW_CLNT_HELLO_B */
+	return(ssl23_write_bytes(s));
+	}
+
+static int ssl23_get_server_hello(s)
+SSL *s;
+	{
+	char buf[8];
+	unsigned char *p;
+	int i,ch_len;
+	int n;
+	BIO *bbio;
+
+	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))
+		{
+		/* we are talking sslv2 */
+		/* we need to clean up the SSLv3 setup and put in the
+		 * sslv2 stuff. */
+
+		if (s->s2 == NULL)
+			{
+			if (!ssl2_new(s))
+				goto err;
+			}
+		else
+			ssl2_clear(s);
+
+		if (s->ctx->options & SSL_OP_NETSCAPE_CHALLENGE_BUG)
+			ch_len=SSL2_CHALLENGE_LENGTH;
+		else
+			ch_len=SSL2_MAX_CHALLENGE_LENGTH;
+
+		/* write out sslv2 challenge */
+		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(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;
+		s->s2->ssl2_rollback=1;
+
+		/* setup the 5 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;
+		}
+	else if ((p[0] == SSL3_RT_HANDSHAKE) &&
+		 (p[1] == SSL3_VERSION_MAJOR) &&
+		 (p[2] == SSL3_VERSION_MINOR) &&
+		 (p[5] == SSL3_MT_SERVER_HELLO))
+		{
+		/* we have sslv3 */
+
+		if (s->bbio == NULL)
+			{
+			bbio=BIO_new(BIO_f_buffer());
+			if (bbio == NULL)
+				{
+				SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,ERR_R_BUF_LIB);
+				goto err;
+				}
+			s->bbio=bbio;
+			}
+		else
+			bbio=s->bbio;
+
+		BIO_reset(bbio);
+		if (!BIO_set_write_buffer_size(bbio,16*1024))
+			{
+			SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,ERR_R_BUF_LIB);
+			goto err;
+			}
+
+		/* start the buffering */
+		s->wbio=BIO_push(s->bbio,s->wbio);
+
+		/* we are in this state */
+		s->state=SSL3_ST_CR_SRVR_HELLO_A;
+
+		/* put the 5 bytes we have read into the input buffer
+		 * for SSLv3 */
+		s->rstate=SSL_ST_READ_HEADER;
+		s->packet_length=n;
+		s->packet= &(s->s3->rbuf.buf[0]);
+		memcpy(s->packet,buf,n);
+		s->s3->rbuf.left=n;
+		s->s3->rbuf.offset=0;
+
+		s->method=SSLv3_client_method();
+		s->handshake_func=s->method->ssl_connect;
+		}
+	else if ((p[0] == SSL3_RT_ALERT) &&
+		 (p[1] == SSL3_VERSION_MAJOR) &&
+		 (p[2] == SSL3_VERSION_MINOR) &&
+		 (p[3] == 0) &&
+		 (p[4] == 2))
+		{
+		void (*cb)()=NULL;
+		int j;
+
+		/* An alert */
+		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);
+			}
+
+		s->rwstate=SSL_NOTHING;
+		SSLerr(SSL_F_SSL3_READ_BYTES,1000+p[6]);
+		goto err;
+		}
+	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 (!ssl_get_new_session(s,0))
+		goto err;
+
+	s->first_packet=1;
+	return(SSL_connect(s));
+err:
+	return(-1);
+	}
+
diff --git a/ssl/s23_lib.c b/ssl/s23_lib.c
new file mode 100644
index 0000000..ff19adc
--- /dev/null
+++ b/ssl/s23_lib.c
@@ -0,0 +1,232 @@
+/* ssl/s23_lib.c */
+/* Copyright (C) 1995-1997 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 "objects.h"
+#include "ssl_locl.h"
+
+#ifndef NOPROTO
+static int ssl23_num_ciphers(void );
+static SSL_CIPHER *ssl23_get_cipher(unsigned int u);
+static int ssl23_read(SSL *s, char *buf, int len);
+static int ssl23_write(SSL *s, char *buf, int len);
+static long ssl23_default_timeout(void );
+static int ssl23_put_cipher_by_char(SSL_CIPHER *c, unsigned char *p);
+static SSL_CIPHER *ssl23_get_cipher_by_char(unsigned char *p);
+#else
+static int ssl23_num_ciphers();
+static SSL_CIPHER *ssl23_get_cipher();
+static int ssl23_read();
+static int ssl23_write();
+static long ssl23_default_timeout();
+static int ssl23_put_cipher_by_char();
+static SSL_CIPHER *ssl23_get_cipher_by_char();
+#endif
+
+char *SSL23_version_str="SSLv2/3 compatablity part of SSLeay 0.7.0 30-Jan-1997";
+
+static SSL_METHOD SSLv23_data= {
+	3,
+	ssl3_new,
+	ssl3_clear,
+	ssl3_free,
+	ssl_undefined_function,
+	ssl_undefined_function,
+	ssl23_read,
+	ssl_undefined_function,
+	ssl23_write,
+	ssl_undefined_function,
+	ssl_undefined_function,
+	ssl3_ctrl,
+	ssl3_ctx_ctrl,
+	ssl23_get_cipher_by_char,
+	ssl23_put_cipher_by_char,
+	ssl_undefined_function,
+	ssl23_num_ciphers,
+	ssl23_get_cipher,
+	ssl_bad_method,
+	ssl23_default_timeout,
+	};
+
+static long ssl23_default_timeout()
+	{
+	return(300);
+	}
+
+SSL_METHOD *sslv23_base_method()
+	{
+	return(&SSLv23_data);
+	}
+
+static int ssl23_num_ciphers()
+	{
+	return(ssl3_num_ciphers()+ssl2_num_ciphers());
+	}
+
+static SSL_CIPHER *ssl23_get_cipher(u)
+unsigned int u;
+	{
+	unsigned int uu=ssl3_num_ciphers();
+
+	if (u < uu)
+		return(ssl3_get_cipher(u));
+	else
+		return(ssl2_get_cipher(u-uu));
+	}
+
+/* This function needs to check if the ciphers required are actually
+ * available */
+static SSL_CIPHER *ssl23_get_cipher_by_char(p)
+unsigned char *p;
+	{
+	SSL_CIPHER c,*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);
+	if (cp == NULL)
+		cp=ssl2_get_cipher_by_char(p);
+	return(cp);
+	}
+
+static int ssl23_put_cipher_by_char(c,p)
+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);
+	}
+
+static int ssl23_read(s,buf,len)
+SSL *s;
+char *buf;
+int len;
+	{
+	int n;
+
+#if 0
+	if (s->shutdown & SSL_RECEIVED_SHUTDOWN)
+		{
+		s->rwstate=SSL_NOTHING;
+		return(0);
+		}
+#endif
+	errno=0;
+	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);
+		}
+	}
+
+static int ssl23_write(s,buf,len)
+SSL *s;
+char *buf;
+int len;
+	{
+	int n;
+
+#if 0
+	if (s->shutdown & SSL_SENT_SHUTDOWN)
+		{
+		s->rwstate=SSL_NOTHING;
+		return(0);
+		}
+#endif
+	errno=0;
+	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/ssl/s23_meth.c b/ssl/s23_meth.c
new file mode 100644
index 0000000..dbe282b
--- /dev/null
+++ b/ssl/s23_meth.c
@@ -0,0 +1,90 @@
+/* ssl/s23_meth.c */
+/* Copyright (C) 1995-1997 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 "objects.h"
+#include "ssl_locl.h"
+
+static SSL_METHOD *ssl23_get_method(ver)
+int ver;
+	{
+	if (ver == 2)
+		return(SSLv23_method());
+	else if (ver == 3)
+		return(SSLv3_method());
+	else
+		return(NULL);
+	}
+
+SSL_METHOD *SSLv23_method()
+	{
+	static int init=1;
+	static SSL_METHOD SSLv23_data;
+
+	if (init)
+		{
+		init=0;
+		memcpy((char *)&SSLv23_data,(char *)sslv23_base_method(),
+			sizeof(SSL_METHOD));
+		SSLv23_data.ssl_connect=ssl23_connect;
+		SSLv23_data.ssl_accept=ssl23_accept;
+		SSLv23_data.get_ssl_method=ssl23_get_method;
+		}
+	return(&SSLv23_data);
+	}
+
diff --git a/ssl/s23_pkt.c b/ssl/s23_pkt.c
new file mode 100644
index 0000000..e9b2add
--- /dev/null
+++ b/ssl/s23_pkt.c
@@ -0,0 +1,120 @@
+/* ssl/s23_pkt.c */
+/* Copyright (C) 1995-1997 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 "evp.h"
+#include "buffer.h"
+#include "ssl_locl.h"
+
+int ssl23_write_bytes(s)
+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;
+		}
+	}
+
+/* only return when we have read 'n' bytes */
+int ssl23_read_bytes(s,n)
+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/ssl/s23_srvr.c b/ssl/s23_srvr.c
new file mode 100644
index 0000000..398f005
--- /dev/null
+++ b/ssl/s23_srvr.c
@@ -0,0 +1,474 @@
+/* ssl/s23_srvr.c */
+/* Copyright (C) 1995-1997 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 "buffer.h"
+#include "rand.h"
+#include "objects.h"
+#include "evp.h"
+#include "ssl_locl.h"
+
+#define BREAK break
+
+#ifndef NOPROTO
+int ssl23_get_client_hello(SSL *s);
+#else
+int ssl23_get_client_hello();
+#endif
+
+static SSL_METHOD *ssl23_get_server_method(ver)
+int ver;
+	{
+	if (ver == 2)
+		return(SSLv2_server_method());
+	else if (ver == 3)
+		return(SSLv3_server_method());
+	else
+		return(NULL);
+	}
+
+SSL_METHOD *SSLv23_server_method()
+	{
+	static int init=1;
+	static SSL_METHOD SSLv23_server_data;
+
+	if (init)
+		{
+		init=0;
+		memcpy((char *)&SSLv23_server_data,
+			(char *)sslv23_base_method(),sizeof(SSL_METHOD));
+		SSLv23_server_data.ssl_accept=ssl23_accept;
+		SSLv23_server_data.get_ssl_method=ssl23_get_server_method;
+		}
+	return(&SSLv23_server_data);
+	}
+
+int ssl23_accept(s)
+SSL *s;
+	{
+	BUF_MEM *buf;
+	unsigned long Time=time(NULL);
+	void (*cb)()=NULL;
+	int ret= -1;
+	int new_state,state;
+
+	RAND_seed((unsigned char *)&Time,sizeof(Time));
+	ERR_clear_error();
+	errno=0;
+
+	if (s->info_callback != NULL)
+		cb=s->info_callback;
+	else if (s->ctx->info_callback != NULL)
+		cb=s->ctx->info_callback;
+	
+	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); 
+	s->in_handshake++;
+
+	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:
+
+			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
+
+			s->version=3;
+			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->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:
+	if (cb != NULL)
+		cb(s,SSL_CB_ACCEPT_EXIT,ret);
+	s->in_handshake--;
+	return(ret);
+	}
+
+
+int ssl23_get_client_hello(s)
+SSL *s;
+	{
+	char buf_space[8];
+	char *buf= &(buf_space[0]);
+	unsigned char *p,*d,*dd;
+	unsigned int i;
+	unsigned int csl,sil,cl;
+	int n=0,j;
+	BIO *bbio;
+	int type=0,use_sslv2_strong=0;
+
+	/* read the initial header */
+	if (s->state ==	SSL23_ST_SR_CLNT_HELLO_A)
+		{
+		if (!ssl3_setup_buffers(s)) goto err;
+
+		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_CLIENT_HELLO))
+			{
+			/* SSLv2 header */
+			if ((p[3] == 0x00) && (p[4] == 0x02))
+				{
+				/* SSLv2 */
+				type=1;
+				}
+			else if (p[3] == SSL3_VERSION_MAJOR)
+				{
+				if (s->ctx->options & SSL_OP_NON_EXPORT_FIRST)
+					{
+					STACK *sk;
+					SSL_CIPHER *c;
+					int ne2,ne3;
+
+					j=((p[0]&0x7f)<<8)|p[1];
+					if (j > (1024*4))
+						{
+						SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_TOO_LARGE);
+						goto err;
+						}
+
+					n=ssl23_read_bytes(s,j+2);
+					if (n <= 0) return(n);
+					p=s->packet;
+
+					if ((buf=Malloc(n)) == NULL)
+						{
+						SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,ERR_R_MALLOC_FAILURE);
+						goto err;
+						}
+					memcpy(buf,p,n);
+
+					p+=5;
+					n2s(p,csl);
+					p+=4;
+
+					sk=ssl_bytes_to_cipher_list(
+						s,p,csl,NULL);
+					if (sk != NULL)
+						{
+						ne2=ne3=0;
+						for (j=0; j<sk_num(sk); j++)
+							{
+							c=(SSL_CIPHER *)sk_value(sk,j);
+							if (!(c->algorithms & SSL_EXP))
+								{
+								if ((c->id>>24L) == 2L)
+									ne2=1;
+								else
+									ne3=1;
+								}
+							}
+						if (ne2 && !ne3)
+							{
+							type=1;
+							use_sslv2_strong=1;
+							goto next_bit;
+							}
+						}
+					}
+				/* SSLv3 */
+				s->state=SSL23_ST_SR_CLNT_HELLO_B;
+				}
+			}
+		else if ((p[0] == SSL3_RT_HANDSHAKE) &&
+			 (p[1] == SSL3_VERSION_MAJOR) &&
+			 (p[5] == SSL3_MT_CLIENT_HELLO))
+			{
+			/* true SSLv3 */
+			type=3;
+			}
+		/* I will not introduce error codes since that will probably
+		 * disrupt the error codes alread allocated and could play
+		 * havoc with dynamic allocation.  Upgrade to 0.9.x :-)
+		 */
+		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))
+			{
+			goto err;
+			}
+		else if (strncmp("CONNECT",(char *)p,7) == 0)
+			{
+			goto err;
+			}
+		}
+
+next_bit:
+	if (s->state == SSL23_ST_SR_CLNT_HELLO_B)
+		{
+		/* we have a SSLv3 in a SSLv2 header */
+		type=2;
+		p=s->packet;
+		n=((p[0]&0x7f)<<8)|p[1];
+		if (n > (1024*4))
+			{
+			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);
+
+		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)
+			{
+			SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_LENGTH_MISMATCH);
+			goto err;
+			}
+
+		*(d++)=SSL3_VERSION_MAJOR;
+		*(d++)=SSL3_VERSION_MINOR;
+
+		/* lets populate the random area */
+		/* get the chalenge_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;
+		
+		i=(d-(unsigned char *)s->init_buf->data);
+
+		/* 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;
+		}
+
+	if (type == 1)
+		{
+		/* we are talking sslv2 */
+		/* we need to clean up the SSLv3 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(s->init_buf,
+			SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER))
+			{
+			goto err;
+			}
+
+		s->state=SSL2_ST_GET_CLIENT_HELLO_A;
+		if ((s->ctx->options & SSL_OP_MSIE_SSLV2_RSA_PADDING) ||
+			use_sslv2_strong)
+			s->s2->ssl2_rollback=0;
+		else
+			s->s2->ssl2_rollback=1;
+
+		/* setup the 5 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;
+		}
+
+	if ((type == 2) || (type == 3))
+		{
+		/* we have sslv3 */
+
+		if (s->bbio == NULL)
+			{
+			bbio=BIO_new(BIO_f_buffer());
+			if (bbio == NULL)
+				goto err;
+			s->bbio=bbio;
+			}
+		else
+			bbio=s->bbio;
+		BIO_reset(bbio);
+		if (!BIO_set_write_buffer_size(bbio,16*1024))
+			goto err;
+		s->wbio=BIO_push(bbio,s->wbio);
+
+		/* 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;
+			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;
+			}
+
+		s->method=SSLv3_server_method();
+		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) Free(buf);
+	s->first_packet=1;
+	return(SSL_accept(s));
+err:
+	if (buf != buf_space) Free(buf);
+	return(-1);
+	}
+
diff --git a/ssl/s2_clnt.c b/ssl/s2_clnt.c
new file mode 100644
index 0000000..67578a4
--- /dev/null
+++ b/ssl/s2_clnt.c
@@ -0,0 +1,982 @@
+/* ssl/s2_clnt.c */
+/* Copyright (C) 1995-1997 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>
+#ifndef NO_MD5
+#include "md5.h"
+#endif
+#include "rand.h"
+#include "buffer.h"
+#include "objects.h"
+#include "ssl_locl.h"
+#include "evp.h"
+
+#ifndef NOPROTO
+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(CERT *c, int len, unsigned char *from,
+	unsigned char *to,int padding);
+#else
+static int get_server_finished();
+static int get_server_verify();
+static int get_server_hello();
+static int client_hello(); 
+static int client_master_key();
+static int client_finished();
+static int client_certificate();
+static int ssl_rsa_public_encrypt();
+#endif
+
+#define BREAK	break
+
+static SSL_METHOD *ssl2_get_client_method(ver)
+int ver;
+	{
+	if (ver == 2)
+		return(SSLv2_client_method());
+	else
+		return(NULL);
+	}
+
+SSL_METHOD *SSLv2_client_method()
+	{
+	static int init=1;
+	static SSL_METHOD SSLv2_client_data;
+
+	if (init)
+		{
+		init=0;
+		memcpy((char *)&SSLv2_client_data,(char *)sslv2_base_method(),
+			sizeof(SSL_METHOD));
+		SSLv2_client_data.ssl_connect=ssl2_connect;
+		SSLv2_client_data.get_ssl_method=ssl2_get_client_method;
+		}
+	return(&SSLv2_client_data);
+	}
+
+int ssl2_connect(s)
+SSL *s;
+	{
+	unsigned long l=time(NULL);
+	BUF_MEM *buf=NULL;
+	int ret= -1;
+	void (*cb)()=NULL;
+	int new_state,state;
+
+	RAND_seed((unsigned char *)&l,sizeof(l));
+	ERR_clear_error();
+	errno=0;
+
+	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 */
+	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);
+	s->in_handshake++;
+
+	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 (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
+
+			s->version=2;
+			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))
+				{
+				ret= -1;
+				goto end;
+				}
+			s->init_buf=buf;
+			s->init_num=0;
+			s->state=SSL2_ST_SEND_CLIENT_HELLO_A;
+			s->ctx->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:
+			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 sucessfully 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);
+
+			ret=1;
+			/* s->server=0; */
+			s->ctx->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 (cb != NULL) 
+		cb(s,SSL_CB_CONNECT_EXIT,ret);
+	return(ret);
+	}
+
+static int get_server_hello(s)
+SSL *s;
+	{
+	unsigned char *buf;
+	unsigned char *p;
+	int i,j;
+	STACK *sk,*cl;
+
+	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));
+
+		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);
+			}
+		s->hit=(*(p++))?1:0;
+		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;
+		s->init_num=0;
+		}
+
+	/* SSL2_ST_GET_SERVER_HELLO_B */
+	j=s->s2->tmp.cert_length+s->s2->tmp.csl+s->s2->tmp.conn_id_length
+		- 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));
+
+	/* things are looking good */
+
+	p=buf;
+	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->ctx->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 incase 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);
+			}
+
+		sk_set_cmp_func(sk,ssl_cipher_ptr_id_cmp);
+
+		/* get the array of ciphers we will accept */
+		cl=ssl_get_ciphers_by_id(s);
+
+		/* 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 origionally sent and
+		 * for performance reasons we should not bother to match
+		 * the two lists up just to check. */
+		for (i=0; i<sk_num(cl); i++)
+			{
+			if (sk_find(sk,sk_value(cl,i)) >= 0)
+				break;
+			}
+
+		if (i >= sk_num(cl))
+			{
+			ssl2_return_error(s,SSL2_PE_NO_CIPHER);
+			SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_NO_CIPHER_MATCH);
+			return(-1);
+			}
+		s->session->cipher=(SSL_CIPHER *)sk_value(cl,i);
+		}
+
+	if ((s->session != NULL) && (s->session->peer != NULL))
+		X509_free(s->session->peer);
+
+	/* hmmm, can we have the problem of the other session with this
+	 * cert, Free's it before we increment the reference count. */
+	CRYPTO_w_lock(CRYPTO_LOCK_X509);
+	s->session->peer=s->session->cert->key->x509;
+	s->session->peer->references++;
+	CRYPTO_w_unlock(CRYPTO_LOCK_X509);
+
+	s->s2->conn_id_length=s->s2->tmp.conn_id_length;
+	memcpy(s->s2->conn_id,p,s->s2->tmp.conn_id_length);
+	return(1);
+	}
+
+static int client_hello(s)
+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_CLIENT_VERSION,p);		/* version */
+		n=j=0;
+
+		n=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),d);
+		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*/
+		RAND_bytes(s->s2->challenge,SSL2_CHALLENGE_LENGTH);
+		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(s)
+SSL *s;
+	{
+	unsigned char *buf;
+	unsigned char *p,*d;
+	int clear,enc,karg,i;
+	SSL_SESSION *sess;
+	EVP_CIPHER *c;
+	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->cipher,&c,&md))
+			{
+			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 > 0) RAND_bytes(sess->key_arg,i);
+
+		/* make a master key */
+		i=EVP_CIPHER_key_length(c);
+		sess->master_key_length=i;
+		if (i > 0) RAND_bytes(sess->master_key,i);
+
+		if (sess->cipher->algorithm2 & SSL2_CF_8_BYTE_ENC)
+			enc=8;
+		else if (sess->cipher->algorithms & SSL_EXP)
+			enc=5;
+		else
+			enc=i;
+
+		if (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->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);
+			}
+		s2n(enc,p);
+		d+=enc;
+		karg=sess->key_arg_length;	
+		s2n(karg,p); /* key arg size */
+		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(s)
+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;
+		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(s)
+SSL *s;
+	{
+	unsigned char *buf;
+	unsigned char *p,*d;
+	int i;
+	unsigned int n;
+	int cert_ch_len=0;
+	unsigned char *cert_ch;
+
+	buf=(unsigned char *)s->init_buf->data;
+	cert_ch= &(buf[2]);
+
+	/* 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+1-s->init_num);
+		if (i<(SSL2_MIN_CERT_CHALLENGE_LENGTH+1-s->init_num))
+			return(ssl2_part_read(s,SSL_F_CLIENT_CERTIFICATE,i));
+
+		/* 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);
+			}
+		cert_ch_len=i-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;
+		}
+
+	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_SignInit(&ctx,EVP_md5());
+		EVP_SignUpdate(&ctx,s->s2->key_material,
+			(unsigned int)s->s2->key_material_length);
+		EVP_SignUpdate(&ctx,cert_ch,(unsigned int)cert_ch_len);
+		n=i2d_X509(s->session->cert->key->x509,&p);
+		EVP_SignUpdate(&ctx,buf,(unsigned int)n);
+
+		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 contiune with a 0 length signature
+			 */
+			}
+		memset(&ctx,0,sizeof(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(s)
+SSL *s;
+	{
+	unsigned char *p;
+	int i;
+
+	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->state= SSL2_ST_GET_SERVER_VERIFY_B;
+		s->init_num=0;
+		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);
+			return(-1);
+			}
+		}
+	
+	p=(unsigned char *)s->init_buf->data;
+	i=ssl2_read(s,(char *)&(p[s->init_num]),
+		(unsigned int)s->s2->challenge_length-s->init_num);
+	if (i < ((int)s->s2->challenge_length-s->init_num))
+		return(ssl2_part_read(s,SSL_F_GET_SERVER_VERIFY,i));
+	if (memcmp(p,s->s2->challenge,(unsigned int)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(s)
+SSL *s;
+	{
+	unsigned char *buf;
+	unsigned char *p;
+	int i;
+
+	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);
+			return(-1);
+			}
+		s->state=SSL_ST_OK;
+		s->init_num=0;
+		}
+
+	i=ssl2_read(s,(char *)&(buf[s->init_num]),
+		SSL2_SSL_SESSION_ID_LENGTH-s->init_num);
+	if (i < (SSL2_SSL_SESSION_ID_LENGTH-s->init_num))
+		return(ssl2_part_read(s,SSL_F_GET_SERVER_FINISHED,i));
+
+	if (!s->hit) /* new session */
+		{
+		/* new session-id */
+		s->session->session_id_length=SSL2_SSL_SESSION_ID_LENGTH;
+		memcpy(s->session->session_id,p,SSL2_SSL_SESSION_ID_LENGTH);
+		}
+	else
+		{
+		if (!(s->ctx->options & SSL_OP_MICROSOFT_SESS_ID_BUG))
+			{
+			if (memcmp(buf,s->session->session_id,
+				(unsigned int)s->session->session_id_length) != 0)
+				{
+				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+				SSLerr(SSL_F_GET_SERVER_FINISHED,SSL_R_SSL_SESSION_ID_IS_DIFFERENT);
+				return(-1);
+				}
+			}
+		}
+	return(1);
+	}
+
+/* loads in the certificate from the server */
+int ssl2_set_certificate(s, type, len, data)
+SSL *s;
+int type;
+int len;
+unsigned char *data;
+	{
+	STACK *sk=NULL;
+	EVP_PKEY *pkey=NULL;
+	CERT *c=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_new_null()) == NULL) ||
+		(!sk_push(sk,(char *)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))
+		{
+		SSLerr(SSL_F_SSL2_SET_CERTIFICATE,SSL_R_CERTIFICATE_VERIFY_FAILED);
+		goto err;
+		}
+
+	/* cert for ssl */
+	c=ssl_cert_new();
+	if (c == NULL)
+		{
+		ret= -1;
+		goto err;
+		}
+
+	/* cert for session */
+	if (s->session->cert) ssl_cert_free(s->session->cert);
+	s->session->cert=c;
+
+/*	c->cert_type=type; */
+
+	c->pkeys[SSL_PKEY_RSA_ENC].x509=x509;
+	c->key= &(c->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_cert_type(c,SSL2_CT_X509_CERTIFICATE))
+		goto err;
+	ret=1;
+err:
+	if (sk != NULL) sk_free(sk);
+	if (x509 != NULL) X509_free(x509);
+	return(ret);
+	}
+
+static int ssl_rsa_public_encrypt(c, len, from, to, padding)
+CERT *c;
+int len;
+unsigned char *from;
+unsigned char *to;
+int padding;
+	{
+	EVP_PKEY *pkey=NULL;
+	int i= -1;
+
+	if ((c == NULL) || (c->key->x509 == NULL) ||
+		((pkey=X509_get_pubkey(c->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:
+	return(i);
+	}
+
diff --git a/ssl/s2_enc.c b/ssl/s2_enc.c
new file mode 100644
index 0000000..b915f09
--- /dev/null
+++ b/ssl/s2_enc.c
@@ -0,0 +1,187 @@
+/* ssl/s2_enc.c */
+/* Copyright (C) 1995-1997 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"
+
+#define RS	0
+#define WS	1
+
+int ssl2_enc_init(s, client)
+SSL *s;
+int client;
+	{
+	/* Max number of bytes needed */
+	EVP_CIPHER_CTX *rs,*ws;
+	EVP_CIPHER *c;
+	EVP_MD *md;
+	int num;
+
+	if (!ssl_cipher_get_evp(s->session->cipher,&c,&md))
+		{
+		ssl2_return_error(s,SSL2_PE_NO_CIPHER);
+		SSLerr(SSL_F_SSL2_ENC_INIT,SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS);
+		return(0);
+		}
+
+	s->read_hash=md;
+	s->write_hash=md;
+
+	if ((s->enc_read_ctx == NULL) &&
+		((s->enc_read_ctx=(EVP_CIPHER_CTX *)
+		Malloc(sizeof(EVP_CIPHER_CTX))) == NULL))
+		goto err;
+	if ((s->enc_write_ctx == NULL) &&
+		((s->enc_write_ctx=(EVP_CIPHER_CTX *)
+		Malloc(sizeof(EVP_CIPHER_CTX))) == NULL))
+		goto err;
+
+	rs= s->enc_read_ctx;
+	ws= s->enc_write_ctx;
+
+	num=c->key_len;
+	s->s2->key_material_length=num*2;
+
+	ssl2_generate_key_material(s);
+
+	EVP_EncryptInit(ws,c,&(s->s2->key_material[(client)?num:0]),
+		s->session->key_arg);
+	EVP_DecryptInit(rs,c,&(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 the s->s2->padding, s->[rw]length and
+ * s->s2->pad_data ptr if we are encrypting */
+void ssl2_enc(s,send)
+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(s, md,send)
+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_DigestInit(&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(&c,md,NULL);
+	/* some would say I should zero the md context */
+	}
+
diff --git a/ssl/s2_lib.c b/ssl/s2_lib.c
new file mode 100644
index 0000000..fb91582
--- /dev/null
+++ b/ssl/s2_lib.c
@@ -0,0 +1,455 @@
+/* ssl/s2_lib.c */
+/* Copyright (C) 1995-1997 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 "rsa.h"
+#include "objects.h"
+#include "ssl_locl.h"
+
+#ifndef NOPROTO
+static int ssl2_ok(SSL *s);
+static long ssl2_default_timeout(void );
+#else
+static int ssl2_ok();
+static long ssl2_default_timeout();
+#endif
+
+char *ssl2_version_str="SSLv2 part of SSLeay 0.8.1b 29-Jun-1998";
+
+#define SSL2_NUM_CIPHERS (sizeof(ssl2_ciphers)/sizeof(SSL_CIPHER))
+
+SSL_CIPHER ssl2_ciphers[]={
+/* NULL_WITH_MD5 v3 */
+#if 0
+	{
+	1,
+	SSL2_TXT_NULL_WITH_MD5,
+	SSL2_CK_NULL_WITH_MD5,
+	SSL_kRSA|SSL_aRSA|SSL_eNULL|SSL_MD5|SSL_EXP|SSL_SSLV2,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+#endif
+/* 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_EXP|SSL_SSLV2,
+	SSL2_CF_5_BYTE_ENC,
+	SSL_ALL_CIPHERS,
+	},
+/* 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_NOT_EXP|SSL_SSLV2|SSL_MEDIUM,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+/* 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_EXP|SSL_SSLV2,
+	SSL2_CF_5_BYTE_ENC,
+	SSL_ALL_CIPHERS,
+	},
+/* 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_NOT_EXP|SSL_SSLV2|SSL_MEDIUM,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+/* 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_NOT_EXP|SSL_SSLV2|SSL_MEDIUM,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+/* 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_NOT_EXP|SSL_SSLV2|SSL_LOW,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+/* DES_64_CBC_WITH_SHA */
+#if 0
+	{
+	1,
+	SSL2_TXT_DES_64_CBC_WITH_SHA,
+	SSL2_CK_DES_64_CBC_WITH_SHA,
+	SSL_kRSA|SSL_aRSA|SSL_DES|SSL_SHA0|SSL_NOT_EXP|SSL_SSLV2|SSL_LOW,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+#endif
+/* 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_NOT_EXP|SSL_SSLV2|SSL_HIGH,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+/* DES_192_EDE3_CBC_WITH_SHA */
+#if 0
+	{
+	1,
+	SSL2_TXT_DES_192_EDE3_CBC_WITH_SHA,
+	SSL2_CK_DES_192_EDE3_CBC_WITH_SHA,
+	SSL_kRSA|SSL_aRSA|SSL_3DES|SSL_SHA0|SSL_NOT_EXP|SSL_SSLV2|SSL_HIGH,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+#endif
+/* RC4_64_WITH_MD5 */
+#if 1
+	{
+	1,
+	SSL2_TXT_RC4_64_WITH_MD5,
+	SSL2_CK_RC4_64_WITH_MD5,
+	SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5|SSL_SSLV2|SSL_LOW,
+	SSL2_CF_8_BYTE_ENC,
+	SSL_ALL_CIPHERS,
+	},
+#endif
+/* NULL SSLeay (testing) */
+#if 0
+	{	
+	0,
+	SSL2_TXT_NULL,
+	SSL2_CK_NULL,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+#endif
+
+/* end of list :-) */
+	};
+
+static SSL_METHOD SSLv2_data= {
+	2,
+	ssl2_new,	/* local */
+	ssl2_clear,	/* local */
+	ssl2_free,	/* local */
+	ssl_undefined_function,
+	ssl_undefined_function,
+	ssl2_read,
+	ssl2_peek,
+	ssl2_write,
+	ssl2_shutdown,
+	ssl2_ok,
+	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,
+	ssl_bad_method,
+	ssl2_default_timeout,
+	};
+
+static long ssl2_default_timeout()
+	{
+	return(300);
+	}
+
+SSL_METHOD *sslv2_base_method()
+	{
+	return(&SSLv2_data);
+	}
+
+int ssl2_num_ciphers()
+	{
+	return(SSL2_NUM_CIPHERS);
+	}
+
+SSL_CIPHER *ssl2_get_cipher(u)
+unsigned int u;
+	{
+	if (u < SSL2_NUM_CIPHERS)
+		return(&(ssl2_ciphers[SSL2_NUM_CIPHERS-1-u]));
+	else
+		return(NULL);
+	}
+
+int ssl2_pending(s)
+SSL *s;
+	{
+	return(s->s2->ract_data_length);
+	}
+
+int ssl2_new(s)
+SSL *s;
+	{
+	SSL2_CTX *s2;
+
+	if ((s2=(SSL2_CTX *)Malloc(sizeof(SSL2_CTX))) == NULL) goto err;
+
+	if ((s2->rbuf=(unsigned char *)Malloc(
+		SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER+2)) == NULL) goto err;
+	if ((s2->wbuf=(unsigned char *)Malloc(
+		SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER+2)) == NULL) goto err;
+	s->s2=s2;
+
+	ssl2_clear(s);
+	return(1);
+err:
+	if (s2 != NULL)
+		{
+		if (s2->wbuf != NULL) Free(s2->wbuf);
+		if (s2->rbuf != NULL) Free(s2->rbuf);
+		Free(s2);
+		}
+	return(0);
+	}
+
+void ssl2_free(s)
+SSL *s;
+	{
+	SSL2_CTX *s2;
+
+	s2=s->s2;
+	if (s2->rbuf != NULL) Free(s2->rbuf);
+	if (s2->wbuf != NULL) Free(s2->wbuf);
+	memset(s2,0,sizeof(SSL2_CTX));
+	Free(s2);
+	s->s2=NULL;
+	}
+
+void ssl2_clear(s)
+SSL *s;
+	{
+	SSL2_CTX *s2;
+	unsigned char *rbuf,*wbuf;
+
+	s2=s->s2;
+
+	rbuf=s2->rbuf;
+	wbuf=s2->wbuf;
+
+	memset(s2,0,sizeof(SSL2_CTX));
+
+	s2->rbuf=rbuf;
+	s2->wbuf=wbuf;
+	s2->clear_text=1;
+	s2->first_packet=0;
+	s->packet=s2->rbuf;
+	s->version=2;
+	s->packet_length=0;
+	}
+
+long ssl2_ctrl(s,cmd,larg,parg)
+SSL *s;
+int cmd;
+long larg;
+char *parg;
+	{
+	return(0);
+	}
+
+long ssl2_ctx_ctrl(ctx,cmd,larg,parg)
+SSL_CTX *ctx;
+int cmd;
+long larg;
+char *parg;
+	{
+	return(0);
+	}
+
+/* This function needs to check if the ciphers required are actually
+ * available */
+SSL_CIPHER *ssl2_get_cipher_by_char(p)
+unsigned char *p;
+	{
+	static int init=1;
+	static SSL_CIPHER *sorted[SSL2_NUM_CIPHERS];
+	SSL_CIPHER c,*cp= &c,**cpp;
+	unsigned long id;
+	int i;
+
+	if (init)
+		{
+		init=0;
+
+		for (i=0; i<SSL2_NUM_CIPHERS; i++)
+			sorted[i]= &(ssl2_ciphers[i]);
+
+		qsort(  (char *)sorted,
+			SSL2_NUM_CIPHERS,sizeof(SSL_CIPHER *),
+			FP_ICC ssl_cipher_ptr_id_cmp);
+		}
+
+	id=0x02000000L|((unsigned long)p[0]<<16L)|
+		((unsigned long)p[1]<<8L)|(unsigned long)p[2];
+	c.id=id;
+	cpp=(SSL_CIPHER **)OBJ_bsearch((char *)&cp,
+		(char *)sorted,
+		SSL2_NUM_CIPHERS,sizeof(SSL_CIPHER *),
+		(int (*)())ssl_cipher_ptr_id_cmp);
+	if ((cpp == NULL) || !(*cpp)->valid)
+		return(NULL);
+	else
+		return(*cpp);
+	}
+
+int ssl2_put_cipher_by_char(c,p)
+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);
+	}
+
+void ssl2_generate_key_material(s)
+SSL *s;
+	{
+	unsigned int i;
+	MD5_CTX ctx;
+	unsigned char *km;
+	unsigned char c='0';
+
+	km=s->s2->key_material;
+	for (i=0; i<s->s2->key_material_length; i+=MD5_DIGEST_LENGTH)
+		{
+		MD5_Init(&ctx);
+
+		MD5_Update(&ctx,s->session->master_key,s->session->master_key_length);
+		MD5_Update(&ctx,(unsigned char *)&c,1);
+		c++;
+		MD5_Update(&ctx,s->s2->challenge,s->s2->challenge_length);
+		MD5_Update(&ctx,s->s2->conn_id,s->s2->conn_id_length);
+		MD5_Final(km,&ctx);
+		km+=MD5_DIGEST_LENGTH;
+		}
+	}
+
+void ssl2_return_error(s,err)
+SSL *s;
+int err;
+	{
+	if (!s->error)
+		{
+		s->error=3;
+		s->error_code=err;
+
+		ssl2_write_error(s);
+		}
+	}
+
+
+void ssl2_write_error(s)
+SSL *s;
+	{
+	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;
+	s->error=0;
+	i=ssl2_write(s,&(buf[3-error]),error);
+/*	if (i == error) s->rwstate=state; */
+
+	if (i < 0)
+		s->error=error;
+	else if (i != s->error)
+		s->error=error-i;
+	/* else
+		s->error=0; */
+	}
+
+static int ssl2_ok(s)
+SSL *s;
+	{
+	return(1);
+	}
+
+int ssl2_shutdown(s)
+SSL *s;
+	{
+	s->shutdown=(SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
+	return(1);
+	}
+
diff --git a/ssl/s2_meth.c b/ssl/s2_meth.c
new file mode 100644
index 0000000..0b8c2ac
--- /dev/null
+++ b/ssl/s2_meth.c
@@ -0,0 +1,88 @@
+/* ssl/s2_meth.c */
+/* Copyright (C) 1995-1997 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 "objects.h"
+#include "ssl_locl.h"
+
+static SSL_METHOD *ssl2_get_method(ver)
+int ver;
+	{
+	if (ver == 2)
+		return(SSLv2_method());
+	else
+		return(NULL);
+	}
+
+SSL_METHOD *SSLv2_method()
+	{
+	static int init=1;
+	static SSL_METHOD SSLv2_data;
+
+	if (init)
+		{
+		init=0;
+		memcpy((char *)&SSLv2_data,(char *)sslv2_base_method(),
+			sizeof(SSL_METHOD));
+		SSLv2_data.ssl_connect=ssl2_connect;
+		SSLv2_data.ssl_accept=ssl2_accept;
+		SSLv2_data.get_ssl_method=ssl2_get_method;
+		}
+	return(&SSLv2_data);
+	}
+
diff --git a/ssl/s2_pkt.c b/ssl/s2_pkt.c
new file mode 100644
index 0000000..84bea33
--- /dev/null
+++ b/ssl/s2_pkt.c
@@ -0,0 +1,651 @@
+/* ssl/s2_pkt.c */
+/* Copyright (C) 1995-1997 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"
+
+/* SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_PEER_ERROR_NO_CIPHER);
+ * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_PEER_ERROR_NO_CERTIFICATE);
+ * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_PEER_ERROR_CERTIFICATE);
+ * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE);
+ * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_UNKNOWN_REMOTE_ERROR_TYPE);
+ */
+
+#ifndef NOPROTO
+static int read_n(SSL *s,unsigned int n,unsigned int max,unsigned int extend);
+static int do_ssl_write(SSL *s, const char *buf, unsigned int len);
+static int write_pending(SSL *s, const char *buf, unsigned int len);
+static int ssl_mt_error(int n);
+#else
+static int read_n();
+static int do_ssl_write();
+static int write_pending();
+static int ssl_mt_error();
+#endif
+
+int ssl2_peek(s,buf,len)
+SSL *s;
+char *buf;
+int len;
+	{
+	int ret;
+
+	ret=ssl2_read(s,buf,len);
+	if (ret > 0)
+	        {
+		s->s2->ract_data_length+=ret;
+		s->s2->ract_data-=ret;
+		}
+	return(ret);
+	}
+
+/* SSL_read -
+ * This routine will return 0 to len bytes, decrypted etc if required.
+ */
+int ssl2_read(s, buf, len)
+SSL *s;
+char *buf;
+int len;
+	{
+	int n;
+	unsigned char mac[MAX_MAC_SIZE];
+	unsigned char *p;
+	int i;
+	unsigned int mac_size=0;
+
+	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,SSL_R_SSL_HANDSHAKE_FAILURE);
+			return(-1);
+			}
+		}
+
+	errno=0;
+	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);
+		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);
+		}
+
+	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,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)
+			{
+			s->s2->mac_data=p;
+			s->s2->ract_data=p;
+			s->s2->pad_data=NULL;
+			}
+		else
+			{
+			mac_size=EVP_MD_size(s->read_hash);
+			s->s2->mac_data=p;
+			s->s2->ract_data= &p[mac_size];
+			s->s2->pad_data= &p[mac_size+
+				s->s2->rlength-s->s2->padding];
+			}
+
+		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 >= 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,SSL_R_BAD_MAC_DECODE);
+				return(SSL_RWERR_BAD_MAC_DECODE);
+				}
+			}
+		INC32(s->s2->read_sequence); /* expect next number */
+		/* s->s2->ract_data is now available for processing */
+
+		/* If a 0 byte packet was sent, return 0, otherwise
+		 * we play havoc with people using select with
+		 * blocking sockets.  Let them handle a packet at a time,
+		 * they should really be using non-blocking sockets. */
+		if (s->s2->ract_data_length == 0)
+			return(0);
+		return(ssl2_read(s,buf,len));
+		}
+	else
+		{
+		SSLerr(SSL_F_SSL2_READ,SSL_R_BAD_STATE);
+			return(SSL_RWERR_INTERNAL_ERROR);
+		}
+	}
+
+static int read_n(s, n, max, extend)
+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)
+		{
+		errno=0;
+		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(s, buf, len)
+SSL *s;
+const char *buf;
+int len;
+	{
+	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);
+		}
+
+	errno=0;
+	s->rwstate=SSL_NOTHING;
+	if (len <= 0) return(len);
+
+	tot=s->s2->wnum;
+	s->s2->wnum=0;
+
+	n=(len-tot);
+	for (;;)
+		{
+		i=do_ssl_write(s,&(buf[tot]),n);
+		if (i <= 0)
+			{
+			s->s2->wnum=tot;
+			return(i);
+			}
+		if (i == (int)n) return(tot+i);
+
+		n-=i;
+		tot+=i;
+		}
+	}
+
+static int write_pending(s,buf,len)
+SSL *s;
+const 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))
+		{
+		SSLerr(SSL_F_WRITE_PENDING,SSL_R_BAD_WRITE_RETRY);
+		return(SSL_RWERR_BAD_WRITE_RETRY);
+		}
+
+	for (;;)
+		{
+		errno=0;
+		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 do_ssl_write(s, buf, len)
+SSL *s;
+const char *buf;
+unsigned int len;
+	{
+	unsigned int j,k,olen,p,mac_size,bs;
+	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_size(s->write_hash);
+
+	/* 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;
+		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))
+			{
+			/* len=len; */
+			s->s2->three_byte_header=0;
+			p=0;
+			}
+		else /* 3 byte header */
+			{
+			/*len=len; */
+			p=(j%bs);
+			p=(p == 0)?0:(bs-p);
+			if (s->s2->escape)
+				s->s2->three_byte_header=1;
+			else
+				s->s2->three_byte_header=(p == 0)?0:1;
+			}
+		}
+	/* 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 p == 0, it is a 2 byte header */
+
+	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);
+#ifdef PURIFY
+	if (p)
+		memset(&(s->s2->wact_data[len]),0,p);
+#endif
+
+	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=(char *)buf;
+
+	s->s2->wpend_ret=len;
+
+	s->s2->wpend_off=0;
+	return(write_pending(s,buf,olen));
+	}
+
+int ssl2_part_read(s,f,i)
+SSL *s;
+unsigned long f;
+int i;
+	{
+	unsigned char *p;
+	int j;
+
+	/* check for error */
+	if ((s->init_num == 0) && (i >= 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));
+			}
+		}
+
+	if (i < 0)
+		{
+		/* ssl2_return_error(s); */
+		/* for non-blocking io,
+		 * this is not fatal */
+		return(i);
+		}
+	else
+		{
+		s->init_num+=i;
+		return(0);
+		}
+	}
+
+int ssl2_do_write(s)
+SSL *s;
+	{
+	int ret;
+
+	ret=ssl2_write(s,(char *)&(s->init_buf->data[s->init_off]),
+		s->init_num);
+	if (ret == s->init_num)
+		return(1);
+	if (ret < 0)
+		return(-1);
+	s->init_off+=ret;
+	s->init_num-=ret;
+	return(0);
+	}
+
+static int ssl_mt_error(n)
+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);
+	}
diff --git a/ssl/s2_srvr.c b/ssl/s2_srvr.c
new file mode 100644
index 0000000..0112397
--- /dev/null
+++ b/ssl/s2_srvr.c
@@ -0,0 +1,983 @@
+/* ssl/s2_srvr.c */
+/* Copyright (C) 1995-1997 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>
+#ifdef NO_MD5
+#include "md5.h"
+#endif
+#include "bio.h"
+#include "rand.h"
+#include "objects.h"
+#include "ssl_locl.h"
+#include "evp.h"
+
+#ifndef NOPROTO
+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);
+#else
+static int get_client_master_key();
+static int get_client_hello();
+static int server_hello(); 
+static int get_client_finished();
+static int server_verify();
+static int server_finish();
+static int request_certificate();
+static int ssl_rsa_private_decrypt();
+#endif
+
+#define BREAK	break
+
+static SSL_METHOD *ssl2_get_server_method(ver)
+int ver;
+	{
+	if (ver == 2)
+		return(SSLv2_server_method());
+	else
+		return(NULL);
+	}
+
+SSL_METHOD *SSLv2_server_method()
+	{
+	static int init=1;
+	static SSL_METHOD SSLv2_server_data;
+
+	if (init)
+		{
+		init=0;
+		memcpy((char *)&SSLv2_server_data,(char *)sslv2_base_method(),
+			sizeof(SSL_METHOD));
+		SSLv2_server_data.ssl_accept=ssl2_accept;
+		SSLv2_server_data.get_ssl_method=ssl2_get_server_method;
+		}
+	return(&SSLv2_server_data);
+	}
+
+int ssl2_accept(s)
+SSL *s;
+	{
+	unsigned long l=time(NULL);
+	BUF_MEM *buf=NULL;
+	int ret= -1;
+	long num1;
+	void (*cb)()=NULL;
+	int new_state,state;
+
+	RAND_seed((unsigned char *)&l,sizeof(l));
+	ERR_clear_error();
+	errno=0;
+
+	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 */
+	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);
+	s->in_handshake++;
+
+	if (((s->session == NULL) || (s->session->cert == NULL)) &&
+		(s->cert == NULL))
+		{
+		SSLerr(SSL_F_SSL2_ACCEPT,SSL_R_NO_CERTIFICATE_SET);
+		return(-1);
+		}
+
+	errno=0;
+	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:
+
+			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
+
+			s->version=2;
+			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->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);
+			s->init_buf=NULL;
+			s->init_num=0;
+		/*	ERR_clear_error();*/
+
+			ssl_update_cache(s,SSL_SESS_CACHE_SERVER);
+
+			s->ctx->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(s)
+SSL *s;
+	{
+	int export,i,n,keya,ek;
+	unsigned char *p;
+	SSL_CIPHER *cp;
+	EVP_CIPHER *c;
+	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));
+		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;
+		s->state=SSL2_ST_GET_CLIENT_MASTER_KEY_B;
+		s->init_num=0;
+		}
+
+	/* SSL2_ST_GET_CLIENT_MASTER_KEY_B */
+	p=(unsigned char *)s->init_buf->data;
+	keya=s->session->key_arg_length;
+	n=s->s2->tmp.clear+s->s2->tmp.enc+keya - 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));
+
+	memcpy(s->session->key_arg,&(p[s->s2->tmp.clear+s->s2->tmp.enc]),
+		(unsigned int)keya);
+
+	if (s->session->cert->key->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);
+
+	export=(s->session->cipher->algorithms & SSL_EXP)?1:0;
+	
+	if (!ssl_cipher_get_evp(s->session->cipher,&c,&md))
+		{
+		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)
+		{
+		export=1;
+		ek=8;
+		}
+	else
+		ek=5;
+
+	/* bad decrypt */
+#if 1
+	/* If a bad decrypt, continue with protocol but with a
+	 * dud master secret */
+	if ((i < 0) ||
+		((!export && (i != EVP_CIPHER_key_length(c)))
+		|| ( export && ((i != ek) || (s->s2->tmp.clear+i !=
+			EVP_CIPHER_key_length(c))))))
+		{
+		if (export)
+			i=ek;
+		else
+			i=EVP_CIPHER_key_length(c);
+		RAND_bytes(p,i);
+		}
+#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 ((!export && (i != EVP_CIPHER_key_length(c)))
+		|| ( 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 (export) i+=s->s2->tmp.clear;
+	s->session->master_key_length=i;
+	memcpy(s->session->master_key,p,(unsigned int)i);
+	return(1);
+	}
+
+static int get_client_hello(s)
+SSL *s;
+	{
+	int i,n;
+	unsigned char *p;
+	STACK *cs; /* a stack of SSL_CIPHERS */
+	STACK *cl; /* the ones we want to use */
+	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));
+	
+		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))
+			{
+			SSLerr(SSL_F_GET_CLIENT_HELLO,SSL_R_INVALID_CHALLENGE_LENGTH);
+			return(-1);
+			}
+		s->state=SSL2_ST_GET_CLIENT_HELLO_C;
+		s->init_num=0;
+		}
+
+	/* SSL2_ST_GET_CLIENT_HELLO_C */
+	p=(unsigned char *)s->init_buf->data;
+	n=s->s2->tmp.cipher_spec_length+s->s2->challenge_length+
+		s->s2->tmp.session_id_length-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));
+
+	/* 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,s->s2->tmp.session_id_length,
+			&(p[s->s2->tmp.cipher_spec_length]));
+		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_by_id(s);
+
+		for (z=0; z<sk_num(cs); z++)
+			{
+			if (sk_find(cl,sk_value(cs,z)) < 0)
+				{
+				sk_delete(cs,z);
+				z--;
+				}
+			}
+
+		/* 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.
+		 */
+		}
+	p+=s->s2->tmp.cipher_spec_length;
+	/* done cipher selection */
+
+	/* session id extracted already */
+	p+=s->s2->tmp.session_id_length;
+
+	/* challenge */
+	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(s)
+SSL *s;
+	{
+	unsigned char *p,*d;
+	int n,hit;
+	STACK *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 (!hit)
+			{			/* else add cert to session */
+			CRYPTO_add(&s->cert->references,1,CRYPTO_LOCK_SSL_CERT);
+			if (s->session->cert != NULL)
+				ssl_cert_free(s->session->cert);
+			s->session->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->cert == NULL)
+				{
+				CRYPTO_add(&s->cert->references,1,
+					CRYPTO_LOCK_SSL_CERT);
+				s->session->cert=s->cert;
+				}
+			}
+
+		if (s->session->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->key->x509,NULL);
+			s2n(n,p);		/* certificate length */
+			i2d_X509(s->cert->key->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);
+			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;
+		RAND_bytes(s->s2->conn_id,(int)s->s2->conn_id_length);
+		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 performace 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)
+ 		{
+ 		BIO *buf;
+ 
+ 		if (s->bbio == NULL)
+ 			{
+ 			buf=BIO_new(BIO_f_buffer());
+ 			if (buf == NULL)
+ 				{
+ 				SSLerr(SSL_F_SERVER_HELLO,ERR_LIB_BUF);
+ 				return(-1);
+ 				}
+ 			s->bbio=buf;
+ 			}
+ 		else
+ 			buf=s->bbio;
+ 		
+ 		BIO_reset(buf);
+ 		s->wbio=BIO_push(buf,s->wbio);
+ 		}
+ 
+	return(ssl2_do_write(s));
+	}
+
+static int get_client_finished(s)
+SSL *s;
+	{
+	unsigned char *p;
+	int i;
+
+	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));
+
+		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);
+			return(-1);
+			}
+		s->init_num=0;
+		s->state=SSL2_ST_GET_CLIENT_FINISHED_B;
+		}
+
+	/* SSL2_ST_GET_CLIENT_FINISHED_B */
+	i=ssl2_read(s,(char *)&(p[s->init_num]),s->s2->conn_id_length-s->init_num);
+	if (i < (int)s->s2->conn_id_length-s->init_num)
+		{
+		return(ssl2_part_read(s,SSL_F_GET_CLIENT_FINISHED,i));
+		}
+	if (memcmp(p,s->s2->conn_id,(unsigned int)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(s)
+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;
+		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(s)
+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;
+
+		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(s)
+SSL *s;
+	{
+	unsigned char *p,*p2,*buf2;
+	unsigned char *ccd;
+	int i,j,ctype,ret= -1;
+	X509 *x509=NULL;
+	STACK *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;
+		RAND_bytes(ccd,SSL2_MIN_CERT_CHALLENGE_LENGTH);
+		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);
+		if (i < 3)
+			{
+			ret=ssl2_part_read(s,SSL_F_REQUEST_CERTIFICATE,i);
+			goto end;
+			}
+
+		if ((*p == SSL2_MT_ERROR) && (i >= 3))
+			{
+			n2s(p,i);
+			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) || (i < 6))
+			{
+			ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+			SSLerr(SSL_F_REQUEST_CERTIFICATE,SSL_R_SHORT_READ);
+			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;
+		s->init_num=0;
+		}
+
+	/* SSL2_ST_SEND_REQUEST_CERTIFICATE_D */
+	p=(unsigned char *)s->init_buf->data;
+	j=s->s2->tmp.clen+s->s2->tmp.rlen-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;
+		}
+
+	x509=(X509 *)d2i_X509(NULL,&p,(long)s->s2->tmp.clen);
+	if (x509 == NULL)
+		{
+		SSLerr(SSL_F_REQUEST_CERTIFICATE,ERR_R_X509_LIB);
+		goto msg_end;
+		}
+
+	if (((sk=sk_new_null()) == NULL) || (!sk_push(sk,(char *)x509)))
+		{
+		SSLerr(SSL_F_REQUEST_CERTIFICATE,ERR_R_MALLOC_FAILURE);
+		goto msg_end;
+		}
+
+	i=ssl_verify_cert_chain(s,sk);
+
+	if (i)	/* we like the packet, now check the chksum */
+		{
+		EVP_MD_CTX ctx;
+		EVP_PKEY *pkey=NULL;
+
+		EVP_VerifyInit(&ctx,EVP_md5());
+		EVP_VerifyUpdate(&ctx,s->s2->key_material,
+			(unsigned int)s->s2->key_material_length);
+		EVP_VerifyUpdate(&ctx,ccd,SSL2_MIN_CERT_CHALLENGE_LENGTH);
+
+		i=i2d_X509(s->session->cert->key->x509,NULL);
+		buf2=(unsigned char *)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->session->cert->key->x509,&p2);
+		EVP_VerifyUpdate(&ctx,buf2,(unsigned int)i);
+		Free(buf2);
+
+		pkey=X509_get_pubkey(x509);
+		if (pkey == NULL) goto end;
+		i=EVP_VerifyFinal(&ctx,p,s->s2->tmp.rlen,pkey);
+		memset(&ctx,0,sizeof(ctx));
+
+		if (i) 
+			{
+			if (s->session->peer != NULL)
+				X509_free(s->session->peer);
+			s->session->peer=x509;
+			CRYPTO_add(&x509->references,1,CRYPTO_LOCK_X509);
+			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:
+	if (sk != NULL) sk_free(sk);
+	if (x509 != NULL) X509_free(x509);
+	return(ret);
+	}
+
+static int ssl_rsa_private_decrypt(c, len, from, to,padding)
+CERT *c;
+int len;
+unsigned char *from;
+unsigned char *to;
+int padding;
+	{
+	RSA *rsa;
+	int i;
+
+	if ((c == NULL) || (c->key->privatekey == NULL))
+		{
+		SSLerr(SSL_F_SSL_RSA_PRIVATE_DECRYPT,SSL_R_NO_PRIVATEKEY);
+		return(-1);
+		}
+	if (c->key->privatekey->type != EVP_PKEY_RSA)
+		{
+		SSLerr(SSL_F_SSL_RSA_PRIVATE_DECRYPT,SSL_R_PUBLIC_KEY_IS_NOT_RSA);
+		return(-1);
+		}
+	rsa=c->key->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);
+	}
+
diff --git a/ssl/s3_both.c b/ssl/s3_both.c
new file mode 100644
index 0000000..1d710ee
--- /dev/null
+++ b/ssl/s3_both.c
@@ -0,0 +1,444 @@
+/* ssl/s3_both.c */
+/* Copyright (C) 1995-1997 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 "buffer.h"
+#include "rand.h"
+#include "objects.h"
+#include "evp.h"
+#include "x509.h"
+#include "ssl_locl.h"
+
+#define BREAK	break
+
+/* SSL3err(SSL_F_SSL3_GET_FINISHED,SSL_R_EXCESSIVE_MESSAGE_SIZE);
+ */
+
+unsigned char ssl3_server_finished_const[4]=
+	{SSL3_MD_SERVER_FINISHED_CONST};
+unsigned char ssl3_client_finished_const[4]=
+	{SSL3_MD_CLIENT_FINISHED_CONST};
+
+int ssl3_send_finished(s,a,b,sender)
+SSL *s;
+int a;
+int b;
+unsigned char *sender;
+	{
+	unsigned char *p,*d;
+	int i;
+	unsigned long l;
+
+	if (s->state == a)
+		{
+		d=(unsigned char *)s->init_buf->data;
+		p= &(d[4]);
+
+		i=ssl3_final_finish_mac(s,&(s->s3->finish_dgst1),sender,p);
+		p+=i;
+		l=i;
+		i=ssl3_final_finish_mac(s,&(s->s3->finish_dgst2),sender,p);
+		l+=i;
+
+		*(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(s,a,b,sender)
+SSL *s;
+int a;
+int b;
+unsigned char *sender;
+	{
+	int al,i,j,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.in_dgst[12]
+	 */ 
+
+	n=ssl3_get_message(s,
+		a,
+		b,
+		SSL3_MT_FINISHED,
+		64, /* should actually be 36+4 :-) */
+		&ok);
+
+	if (!ok) return((int)n);
+
+	/* If this occurs if we has missed a message */
+	if (!s->s3->change_cipher_spec)
+		{
+		al=SSL3_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_buf->data;
+
+	i=EVP_MD_CTX_size(&(s->s3->finish_dgst1));
+	j=EVP_MD_CTX_size(&(s->s3->finish_dgst2));
+
+	if ((i+j) != n)
+		{
+		al=SSL3_AD_ILLEGAL_PARAMETER;
+		SSLerr(SSL_F_SSL3_GET_FINISHED,SSL_R_BAD_DIGEST_LENGTH);
+		goto f_err;
+		}
+
+	if (	(memcmp(  p,    &(s->s3->tmp.finish_md1[0]),i) != 0) ||
+		(memcmp(&(p[i]),&(s->s3->tmp.finish_md2[0]),j) != 0))
+		{
+		al=SSL3_AD_ILLEGAL_PARAMETER;
+		SSLerr(SSL_F_SSL3_GET_FINISHED,SSL_R_DIGEST_CHECK_FAILED);
+		goto f_err;
+		}
+
+	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(s,a,b)
+SSL *s;
+int a,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));
+	}
+
+unsigned long ssl3_output_cert_chain(s,x)
+SSL *s;
+X509 *x;
+	{
+	unsigned char *p;
+	int n,i;
+	unsigned long l=7;
+	BUF_MEM *buf;
+	X509_STORE_CTX xs_ctx;
+	X509_OBJECT obj;
+
+	X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,NULL,NULL);
+
+	buf=s->init_buf;
+	for (;;)
+		{
+		n=i2d_X509(x,NULL);
+		if (!BUF_MEM_grow(buf,(int)(n+l+3)))
+			{
+			SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB);
+			return(0);
+			}
+		p=(unsigned char *)&(buf->data[l]);
+		l2n3(n,p);
+		i2d_X509(x,&p);
+		l+=n+3;
+		if (X509_NAME_cmp(X509_get_subject_name(x),
+			X509_get_issuer_name(x)) == 0) break;
+
+		i=X509_STORE_get_by_subject(&xs_ctx,X509_LU_X509,
+			X509_get_issuer_name(x),&obj);
+		if (i <= 0) break;
+		x=obj.data.x509;
+		/* Count is one too high since the X509_STORE_get uped the
+		 * ref count */
+		X509_free(x);
+		}
+
+	X509_STORE_CTX_cleanup(&xs_ctx);
+
+	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);
+	}
+
+long ssl3_get_message(s,st1,stn,mt,max,ok)
+SSL *s;
+int st1,stn,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=SSL3_AD_UNEXPECTED_MESSAGE;
+			SSLerr(SSL_F_SSL3_GET_MESSAGE,SSL_R_UNEXPECTED_MESSAGE);
+			goto f_err;
+			}
+		*ok=1;
+		return((int)s->s3->tmp.message_size);
+		}
+
+	p=(unsigned char *)s->init_buf->data;
+
+	if (s->state == st1)
+		{
+		i=ssl3_read_bytes(s,SSL3_RT_HANDSHAKE,
+			(char *)&(p[s->init_num]),
+			4-s->init_num);
+		if (i < (4-s->init_num))
+			{
+			*ok=0;
+			return(ssl3_part_read(s,i));
+			}
+
+		if ((mt >= 0) && (*p != mt))
+			{
+			al=SSL3_AD_UNEXPECTED_MESSAGE;
+			SSLerr(SSL_F_SSL3_GET_MESSAGE,SSL_R_UNEXPECTED_MESSAGE);
+			goto f_err;
+			}
+		s->s3->tmp.message_type= *(p++);
+
+		n2l3(p,l);
+		if (l > (unsigned long)max)
+			{
+			al=SSL3_AD_ILLEGAL_PARAMETER;
+			SSLerr(SSL_F_SSL3_GET_MESSAGE,SSL_R_EXCESSIVE_MESSAGE_SIZE);
+			goto f_err;
+			}
+		if (l && !BUF_MEM_grow(s->init_buf,(int)l))
+			{
+			SSLerr(SSL_F_SSL3_GET_MESSAGE,ERR_R_BUF_LIB);
+			goto err;
+			}
+		s->s3->tmp.message_size=l;
+		s->state=stn;
+
+		s->init_num=0;
+		}
+
+	/* next state (stn) */
+	p=(unsigned char *)s->init_buf->data;
+	n=s->s3->tmp.message_size;
+	if (n > 0)
+		{
+		i=ssl3_read_bytes(s,SSL3_RT_HANDSHAKE,
+			(char *)&(p[s->init_num]),(int)n);
+		if (i != (int)n)
+			{
+			*ok=0;
+			return(ssl3_part_read(s,i));
+			}
+		}
+	*ok=1;
+	return(n);
+f_err:
+	ssl3_send_alert(s,SSL3_AL_FATAL,al);
+err:
+	*ok=0;
+	return(-1);
+	}
+
+int ssl_cert_type(x,pkey)
+X509 *x;
+EVP_PKEY *pkey;
+	{
+	EVP_PKEY *pk;
+	int ret= -1,i,j;
+
+	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;
+		if (x != NULL)
+			{
+			j=X509_get_ext_count(x);
+			/* check to see if this is a signing only certificate */
+			/* EAY EAY EAY EAY */
+			}
+		}
+	else if (i == EVP_PKEY_DSA)
+		{
+		ret=SSL_PKEY_DSA_SIGN;
+		}
+	else if (i == EVP_PKEY_DH)
+		{
+		/* if we just have a key, we needs to be guess */
+
+		if (x == NULL)
+			ret=SSL_PKEY_DH_DSA;
+		else
+			{
+			j=X509_get_signature_type(x);
+			if (j == EVP_PKEY_RSA)
+				ret=SSL_PKEY_DH_RSA;
+			else if (j== EVP_PKEY_DSA)
+				ret=SSL_PKEY_DH_DSA;
+			else ret= -1;
+			}
+		}
+	else
+		ret= -1;
+
+err:
+	return(ret);
+	}
+
+int ssl_verify_alarm_type(type)
+int type;
+	{
+	int al;
+
+	switch(type)
+		{
+	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
+
+	case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
+	case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
+	case X509_V_ERR_CERT_SIGNATURE_FAILURE:
+	case X509_V_ERR_CERT_NOT_YET_VALID:
+	case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
+	case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
+	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:
+		al=SSL3_AD_BAD_CERTIFICATE;
+		break;
+	case X509_V_ERR_CERT_HAS_EXPIRED:
+		al=SSL3_AD_CERTIFICATE_EXPIRED;
+		break;
+	default:
+		al=SSL3_AD_CERTIFICATE_UNKNOWN;
+		break;
+		}
+	return(al);
+	}
+
+int ssl3_setup_buffers(s)
+SSL *s;
+	{
+	unsigned char *p;
+	unsigned int extra;
+
+	if (s->s3->rbuf.buf == NULL)
+		{
+		if (s->ctx->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER)
+			extra=SSL3_RT_MAX_EXTRA;
+		else
+			extra=0;
+		if ((p=(unsigned char *)Malloc(SSL3_RT_MAX_PACKET_SIZE+extra))
+			== NULL)
+			goto err;
+		s->s3->rbuf.buf=p;
+		}
+
+	if (s->s3->wbuf.buf == NULL)
+		{
+		if ((p=(unsigned char *)Malloc(SSL3_RT_MAX_PACKET_SIZE))
+			== NULL)
+			goto err;
+		s->s3->wbuf.buf=p;
+		}
+	s->packet= &(s->s3->rbuf.buf[0]);
+	return(1);
+err:
+	SSLerr(SSL_F_SSL3_SETUP_BUFFERS,ERR_R_MALLOC_FAILURE);
+	return(0);
+	}
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
new file mode 100644
index 0000000..4f551d2
--- /dev/null
+++ b/ssl/s3_clnt.c
@@ -0,0 +1,1642 @@
+/* ssl/s3_clnt.c */
+/* Copyright (C) 1995-1997 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 "buffer.h"
+#include "rand.h"
+#include "objects.h"
+#include "evp.h"
+#include "ssl_locl.h"
+
+#define BREAK break
+/* SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,ERR_R_MALLOC_FAILURE);
+ * SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,ERR_R_MALLOC_FAILURE);
+ * SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,ERR_R_MALLOC_FAILURE);
+ * SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
+ * SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,ERR_R_MALLOC_FAILURE);
+ * SSLerr(SSL_F_SSL3_GET_SERVER_DONE,ERR_R_MALLOC_FAILURE);
+SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_SSL3_SESSION_ID_TOO_SHORT);
+ */
+
+#ifndef NOPROTO
+static int ssl3_client_hello(SSL *s);
+static int ssl3_get_server_hello(SSL *s);
+static int ssl3_get_certificate_request(SSL *s);
+static int ca_dn_cmp(X509_NAME **a,X509_NAME **b);
+static int ssl3_get_server_done(SSL *s);
+static int ssl3_send_client_verify(SSL *s);
+static int ssl3_send_client_certificate(SSL *s);
+static int ssl3_send_client_key_exchange(SSL *s);
+static int ssl3_get_key_exchange(SSL *s);
+static int ssl3_get_server_certificate(SSL *s);
+static int ssl3_check_cert_and_algorithm(SSL *s);
+#else
+static int ssl3_client_hello();
+static int ssl3_get_server_hello();
+static int ssl3_get_certificate_request();
+static int ca_dn_cmp();
+static int ssl3_get_server_done();
+static int ssl3_send_client_verify();
+static int ssl3_send_client_certificate();
+static int ssl3_send_client_key_exchange();
+static int ssl3_get_key_exchange();
+static int ssl3_get_server_certificate();
+static int ssl3_check_cert_and_algorithm();
+#endif
+
+static SSL_METHOD *ssl3_get_client_method(ver)
+int ver;
+	{
+	if (ver == 3)
+		return(SSLv3_client_method());
+	else
+		return(NULL);
+	}
+
+SSL_METHOD *SSLv3_client_method()
+	{
+	static int init=1;
+	static SSL_METHOD SSLv3_client_data;
+
+	if (init)
+		{
+		init=0;
+		memcpy((char *)&SSLv3_client_data,(char *)sslv3_base_method(),
+			sizeof(SSL_METHOD));
+		SSLv3_client_data.ssl_connect=ssl3_connect;
+		SSLv3_client_data.get_ssl_method=ssl3_get_client_method;
+		}
+	return(&SSLv3_client_data);
+	}
+
+int ssl3_connect(s)
+SSL *s;
+	{
+	BUF_MEM *buf;
+	unsigned long Time=time(NULL),l;
+	long num1;
+	void (*cb)()=NULL;
+	int ret= -1;
+	BIO *bbio,*under;
+	int new_state,state,skip=0;;
+
+	RAND_seed((unsigned char *)&Time,sizeof(Time));
+	ERR_clear_error();
+	errno=0;
+
+	if (s->info_callback != NULL)
+		cb=s->info_callback;
+	else if (s->ctx->info_callback != NULL)
+		cb=s->ctx->info_callback;
+	
+	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); 
+	s->in_handshake++;
+
+	for (;;)
+		{
+		state=s->state;
+
+		switch(s->state)
+			{
+		case SSL_ST_RENEGOTIATE:
+			s->new_session=1;
+			s->state=SSL_ST_CONNECT;
+			/* break */
+		case SSL_ST_BEFORE:
+		case SSL_ST_CONNECT:
+		case SSL_ST_BEFORE|SSL_ST_CONNECT:
+		case SSL_ST_OK|SSL_ST_CONNECT:
+
+			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
+
+			s->version=3;
+			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;
+				}
+
+			if (!ssl3_setup_buffers(s)) { ret= -1; goto end; }
+
+			/* setup buffing BIO */
+			if (s->bbio == NULL)
+				{
+				bbio=BIO_new(BIO_f_buffer());
+				if (bbio == NULL)
+					{
+					SSLerr(SSL_F_SSL3_CONNECT,ERR_LIB_BUF);
+					ret= -1;
+					goto end;
+					}
+				s->bbio=bbio;
+				}
+			else
+				bbio=s->bbio;
+
+			BIO_reset(bbio);
+			if (!BIO_set_write_buffer_size(bbio,16*1024))
+				{
+				SSLerr(SSL_F_SSL3_CONNECT,ERR_LIB_BUF);
+				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->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 */
+			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:
+			/* Check if it is anon DH */
+			if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL))
+				{
+				ret=ssl3_get_server_certificate(s);
+				if (ret <= 0) goto end;
+				}
+			else
+				skip=1;
+			s->state=SSL3_ST_CR_KEY_EXCH_A;
+			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:
+			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;
+			l=s->s3->tmp.new_cipher->algorithms;
+			/* EAY EAY EAY need to check for DH fix cert
+			 * sent back */
+			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:
+			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;
+			if (!ssl3_setup_key_block(s))
+				{
+				ret= -1;
+				goto end;
+				}
+
+			if (!ssl3_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,
+				&(ssl3_client_finished_const[0]));
+			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
+				{
+				s->s3->tmp.next_state=SSL3_ST_CR_FINISHED_A;
+				}
+			s->init_num=0;
+			break;
+
+		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,
+				&(ssl3_server_finished_const[0]));
+			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:
+			/* number of bytes to be flushed */
+			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;
+				}
+
+			s->state=s->s3->tmp.next_state;
+			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;
+
+			if (!(s->s3->flags & SSL3_FLAGS_POP_BUFFER))
+				{
+				/* remove buffering */
+				under=BIO_pop(s->wbio);
+				if (under != NULL)
+					s->wbio=under;
+				else
+					abort(); /* ok */
+
+				BIO_free(s->bbio);
+				s->bbio=NULL;
+				}
+			/* else do it later */
+
+			s->init_num=0;
+			s->new_session=0;
+
+			ssl_update_cache(s,SSL_SESS_CACHE_CLIENT);
+
+			ret=1;
+			/* s->server=0; */
+			s->handshake_func=ssl3_connect;
+			s->ctx->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) 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;
+				}
+			}
+		skip=0;
+		}
+end:
+	if (cb != NULL)
+		cb(s,SSL_CB_CONNECT_EXIT,ret);
+	s->in_handshake--;
+	return(ret);
+	}
+
+
+static int ssl3_client_hello(s)
+SSL *s;
+	{
+	unsigned char *buf;
+	unsigned char *p,*d;
+	int i;
+	unsigned long Time,l;
+
+	buf=(unsigned char *)s->init_buf->data;
+	if (s->state == SSL3_ST_CW_CLNT_HELLO_A)
+		{
+		if ((s->session == NULL) ||
+			(s->session->ssl_version != s->version))
+			{
+			if (!ssl_get_new_session(s,0))
+				goto err;
+			}
+		/* else use the pre-loaded session */
+
+		p=s->s3->client_random;
+		Time=time(NULL);			/* Time */
+		l2n(Time,p);
+		RAND_bytes(&(p[4]),SSL3_RANDOM_SIZE-sizeof(Time));
+
+		/* Do the message type and length last */
+		d=p= &(buf[4]);
+
+		*(p++)=SSL3_VERSION_MAJOR;
+		*(p++)=SSL3_VERSION_MINOR;
+
+		/* 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)
+			{
+			memcpy(p,s->session->session_id,i);
+			p+=i;
+			}
+		
+		/* Ciphers supported */
+		i=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),&(p[2]));
+		if (i == 0)
+			{
+			SSLerr(SSL_F_SSL3_CLIENT_HELLO,SSL_R_NO_CIPHERS_AVAILABLE);
+			goto err;
+			}
+		s2n(i,p);
+		p+=i;
+
+		/* hardwire in the NULL compression algorithm. */
+		*(p++)=1;
+		*(p++)=0;
+		
+		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);
+	}
+
+static int ssl3_get_server_hello(s)
+SSL *s;
+	{
+	STACK *sk;
+	SSL_CIPHER *c;
+	unsigned char *p,*d;
+	int i,al,ok;
+	unsigned int j;
+	long n;
+
+	n=ssl3_get_message(s,
+		SSL3_ST_CR_SRVR_HELLO_A,
+		SSL3_ST_CR_SRVR_HELLO_B,
+		SSL3_MT_SERVER_HELLO,
+		300, /* ?? */
+		&ok);
+
+	if (!ok) return((int)n);
+	d=p=(unsigned char *)s->init_buf->data;
+
+	if ((p[0] != SSL3_VERSION_MAJOR) && (p[1] != SSL3_VERSION_MINOR))
+		{
+		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_SSL_VERSION);
+		goto 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 != 0) && (j != SSL3_SESSION_ID_SIZE))
+		{
+		/* SSLref returns 16 :-( */
+		if (j < SSL2_SSL_SESSION_ID_LENGTH)
+			{
+			al=SSL3_AD_ILLEGAL_PARAMETER;
+			SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_SSL3_SESSION_ID_TOO_SHORT);
+			goto f_err;
+			}
+		}
+	if (j == 0)
+		{
+		s->hit=0;
+		memset(s->session->session_id,0,SSL_MAX_SSL_SESSION_ID_LENGTH);
+		s->session->session_id_length=0;
+		}
+	else if ((j == s->session->session_id_length) &&
+		(memcmp(p,s->session->session_id,j) == 0))
+		s->hit=1;
+	else
+		{
+		memcpy(s->session->session_id,p,j);
+		s->session->session_id_length=j;
+		s->hit=0;
+		}
+	p+=j;
+	c=ssl_get_cipher_by_char(s,p);
+	if (c == NULL)
+		{
+		/* unknown cipher */
+		al=SSL3_AD_HANDSHAKE_FAILURE;
+		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_find(sk,(char *)c);
+	if (i < 0)
+		{
+		/* we did not say we would use this cipher */
+		al=SSL3_AD_ILLEGAL_PARAMETER;
+		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_CIPHER_RETURNED);
+		goto f_err;
+		}
+
+	if (s->hit && (s->session->cipher != c))
+		{
+		if (!(s->ctx->options &
+			SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG))
+			{
+			al=SSL3_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;
+
+	/* lets get the compression algorithm */
+	j= *(p++);
+	if (j != 0)
+		{
+		al=SSL3_AD_HANDSHAKE_FAILURE;
+		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
+		goto f_err;
+		}
+
+	if (p != (d+n))
+		{
+		/* wrong packet length */
+		al=SSL3_AD_ILLEGAL_PARAMETER;
+		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);
+	}
+
+static int ssl3_get_server_certificate(s)
+SSL *s;
+	{
+	int al,i,ok,ret= -1;
+	unsigned long n,nc,llen,l;
+	X509 *x=NULL;
+	unsigned char *p,*d,*q;
+	STACK *sk=NULL;
+	CERT *c;
+	EVP_PKEY *pkey=NULL;
+
+	n=ssl3_get_message(s,
+		SSL3_ST_CR_CERT_A,
+		SSL3_ST_CR_CERT_B,
+		-1,
+#if defined(MSDOS) && !defined(WIN32)
+		1024*30, /* 30k max cert list :-) */
+#else
+		1024*100, /* 100k max cert list :-) */
+#endif
+		&ok);
+
+	if (!ok) return((int)n);
+
+	if (s->s3->tmp.message_type == SSL3_MT_SERVER_KEY_EXCHANGE)
+		{
+		s->s3->tmp.reuse_message=1;
+		return(1);
+		}
+
+	if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE)
+		{
+		al=SSL3_AD_UNEXPECTED_MESSAGE;
+		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_BAD_MESSAGE_TYPE);
+		goto f_err;
+		}
+	d=p=(unsigned char *)s->init_buf->data;
+
+	if ((sk=sk_new_null()) == NULL)
+		{
+		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,ERR_R_MALLOC_FAILURE);
+		goto err;
+		}
+
+	n2l3(p,llen);
+	if (llen+3 != n)
+		{
+		al=SSL3_AD_ILLEGAL_PARAMETER;
+		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=SSL3_AD_ILLEGAL_PARAMETER;
+			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=SSL3_AD_ILLEGAL_PARAMETER;
+			SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,ERR_R_ASN1_LIB);
+			goto f_err;
+			}
+		if (q != (p+l))
+			{
+			al=SSL3_AD_ILLEGAL_PARAMETER;
+			SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH);
+			goto f_err;
+			}
+		if (!sk_push(sk,(char *)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))
+		{
+		al=ssl_verify_alarm_type(s->verify_result);
+		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_CERTIFICATE_VERIFY_FAILED);
+		goto f_err; 
+		}
+
+	c=ssl_cert_new();
+	if (c == NULL) goto err;
+
+	if (s->session->cert) ssl_cert_free(s->session->cert);
+	s->session->cert=c;
+
+	c->cert_chain=sk;
+	x=(X509 *)sk_value(sk,0);
+	sk=NULL;
+
+	pkey=X509_get_pubkey(x);
+
+	if (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 (i < 0)
+		{
+		x=NULL;
+		al=SSL3_AL_FATAL;
+		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+		goto f_err;
+		}
+
+	c->cert_type=i;
+	x->references++;
+	if (c->pkeys[i].x509 != NULL)
+		X509_free(c->pkeys[i].x509);
+	c->pkeys[i].x509=x;
+	c->key= &(c->pkeys[i]);
+
+	if ((s->session != NULL) && (s->session->peer != NULL)) 
+		X509_free(s->session->peer);
+	x->references++;
+	s->session->peer=x;
+
+	x=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_pop_free(sk,X509_free);
+	return(ret);
+	}
+
+static int ssl3_get_key_exchange(s)
+SSL *s;
+	{
+#ifndef 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;
+	EVP_PKEY *pkey=NULL;
+	RSA *rsa=NULL;
+	DH *dh=NULL;
+
+	n=ssl3_get_message(s,
+		SSL3_ST_CR_KEY_EXCH_A,
+		SSL3_ST_CR_KEY_EXCH_B,
+		-1,
+		1024*8, /* ?? */
+		&ok);
+
+	if (!ok) return((int)n);
+
+	if (s->s3->tmp.message_type != SSL3_MT_SERVER_KEY_EXCHANGE)
+		{
+		s->s3->tmp.reuse_message=1;
+		return(1);
+		}
+
+	param=p=(unsigned char *)s->init_buf->data;
+
+	if (s->session->cert != NULL)
+		{
+#ifndef NO_RSA
+		if (s->session->cert->rsa_tmp != NULL)
+			{
+			RSA_free(s->session->cert->rsa_tmp);
+			s->session->cert->rsa_tmp=NULL;
+			}
+#endif
+#ifndef NO_DH
+		if (s->session->cert->dh_tmp)
+			{
+			DH_free(s->session->cert->dh_tmp);
+			s->session->cert->dh_tmp=NULL;
+			}
+#endif
+		}
+	else
+		{
+		s->session->cert=ssl_cert_new();
+		}
+
+	param_len=0;
+	alg=s->s3->tmp.new_cipher->algorithms;
+
+#ifndef NO_RSA
+	if (alg & 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=SSL3_AD_ILLEGAL_PARAMETER;
+			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=SSL3_AD_ILLEGAL_PARAMETER;
+			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;
+
+/*		s->session->cert->rsa_tmp=rsa;*/
+		/* this should be because we are using an export cipher */
+		if (alg & SSL_aRSA)
+			pkey=X509_get_pubkey(s->session->cert->pkeys[SSL_PKEY_RSA_ENC].x509);
+		else
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_INTERNAL_ERROR);
+			goto err;
+			}
+		s->session->cert->rsa_tmp=rsa;
+		}
+	else
+#endif
+#ifndef NO_DH
+		if (alg & 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=SSL3_AD_ILLEGAL_PARAMETER;
+			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=SSL3_AD_ILLEGAL_PARAMETER;
+			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=SSL3_AD_ILLEGAL_PARAMETER;
+			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 NO_RSA
+		if (alg & SSL_aRSA)
+			pkey=X509_get_pubkey(s->session->cert->pkeys[SSL_PKEY_RSA_ENC].x509);
+		else
+#endif
+#ifndef NO_DSA
+		if (alg & SSL_aDSS)
+			pkey=X509_get_pubkey(s->session->cert->pkeys[SSL_PKEY_DSA_SIGN].x509);
+#endif
+		/* else anonymous DH, so no certificate or pkey. */
+
+		s->session->cert->dh_tmp=dh;
+		}
+	else if ((alg & SSL_kDHr) || (alg & SSL_kDHd))
+		{
+		al=SSL3_AD_HANDSHAKE_FAILURE;
+		SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER);
+		goto f_err;
+		}
+#endif
+
+	/* 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=SSL3_AD_ILLEGAL_PARAMETER;
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_WRONG_SIGNATURE_LENGTH);
+			goto err;
+			}
+
+#ifndef NO_RSA
+		if (pkey->type == EVP_PKEY_RSA)
+			{
+			int num;
+
+			j=0;
+			q=md_buf;
+			for (num=2; num > 0; num--)
+				{
+				EVP_DigestInit(&md_ctx,(num == 2)?EVP_md5():EVP_sha1());
+				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(&md_ctx,q,(unsigned int *)&i);
+				q+=i;
+				j+=i;
+				}
+			i=RSA_public_decrypt((int)n,p,p,pkey->pkey.rsa,
+				RSA_PKCS1_PADDING);
+			if (i <= 0)
+				{
+				al=SSL3_AD_ILLEGAL_PARAMETER;
+				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_RSA_DECRYPT);
+				goto f_err;
+				}
+			if ((j != i) || (memcmp(p,md_buf,i) != 0))
+				{
+				/* bad signature */
+				al=SSL3_AD_ILLEGAL_PARAMETER;
+				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SIGNATURE);
+				goto f_err;
+				}
+			}
+		else
+#endif
+#ifndef NO_DSA
+			if (pkey->type == EVP_PKEY_DSA)
+			{
+			/* lets do DSS */
+			EVP_VerifyInit(&md_ctx,EVP_dss1());
+			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))
+				{
+				/* bad signature */
+				al=SSL3_AD_ILLEGAL_PARAMETER;
+				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SIGNATURE);
+				goto f_err;
+				}
+			}
+		else
+#endif
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_INTERNAL_ERROR);
+			goto err;
+			}
+		}
+	else
+		{
+		/* still data left over */
+		if (!(alg & SSL_aNULL))
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_INTERNAL_ERROR);
+			goto err;
+			}
+		if (n != 0)
+			{
+			al=SSL3_AD_ILLEGAL_PARAMETER;
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_EXTRA_DATA_IN_MESSAGE);
+			goto f_err;
+			}
+		}
+
+	return(1);
+f_err:
+	ssl3_send_alert(s,SSL3_AL_FATAL,al);
+err:
+	return(-1);
+	}
+
+static int ssl3_get_certificate_request(s)
+SSL *s;
+	{
+	int ok,ret=0;
+	unsigned long n,nc;
+	unsigned int llen,l,ctype_num,i;
+	X509_NAME *xn=NULL;
+	unsigned char *p,*d,*q;
+	STACK *ca_sk=NULL;
+
+	n=ssl3_get_message(s,
+		SSL3_ST_CR_CERT_REQ_A,
+		SSL3_ST_CR_CERT_REQ_B,
+		-1,
+#if defined(MSDOS) && !defined(WIN32)
+		1024*30,  /* 30k max cert list :-) */
+#else
+		1024*100, /* 100k max cert list :-) */
+#endif
+		&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,SSL3_AD_UNEXPECTED_MESSAGE);
+		SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_WRONG_MESSAGE_TYPE);
+		goto err;
+		}
+
+	d=p=(unsigned char *)s->init_buf->data;
+
+	if ((ca_sk=sk_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 ((llen+ctype_num+2+1) != n)
+		{
+		ssl3_send_alert(s,SSL3_AL_FATAL,SSL3_AD_ILLEGAL_PARAMETER);
+		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->ctx->options & SSL_OP_NETSCAPE_CA_DN_BUG))
+				goto cont; /* netscape bugs */
+			ssl3_send_alert(s,SSL3_AL_FATAL,SSL3_AD_ILLEGAL_PARAMETER);
+			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 tollerance is on, ignore errors */
+			if (s->ctx->options & SSL_OP_NETSCAPE_CA_DN_BUG)
+				goto cont;
+			else
+				{
+				ssl3_send_alert(s,SSL3_AL_FATAL,SSL3_AD_ILLEGAL_PARAMETER);
+				SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,ERR_R_ASN1_LIB);
+				goto err;
+				}
+			}
+
+		if (q != (p+l))
+			{
+			ssl3_send_alert(s,SSL3_AL_FATAL,SSL3_AD_ILLEGAL_PARAMETER);
+			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_CA_DN_LENGTH_MISMATCH);
+			goto err;
+			}
+		if (!sk_push(ca_sk,(char *)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 certficate to return.... */
+	s->s3->tmp.cert_req=1;
+	s->s3->tmp.ctype_num=ctype_num;
+	if (s->s3->tmp.ca_names != NULL)
+		sk_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_pop_free(ca_sk,X509_NAME_free);
+	return(ret);
+	}
+
+static int ca_dn_cmp(a,b)
+X509_NAME **a,**b;
+	{
+	return(X509_NAME_cmp(*a,*b));
+	}
+
+static int ssl3_get_server_done(s)
+SSL *s;
+	{
+	int ok,ret=0;
+	long n;
+
+	n=ssl3_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,SSL3_AD_ILLEGAL_PARAMETER);
+		SSLerr(SSL_F_SSL3_GET_SERVER_DONE,SSL_R_LENGTH_MISMATCH);
+		}
+	ret=1;
+	return(ret);
+	}
+
+static int ssl3_send_client_key_exchange(s)
+SSL *s;
+	{
+	unsigned char *p,*d;
+	int n;
+	unsigned long l;
+	EVP_PKEY *pkey=NULL;
+
+	if (s->state == SSL3_ST_CW_KEY_EXCH_A)
+		{
+		d=(unsigned char *)s->init_buf->data;
+		p= &(d[4]);
+
+		l=s->s3->tmp.new_cipher->algorithms;
+
+#ifndef NO_RSA
+		if (l & SSL_kRSA)
+			{
+			RSA *rsa;
+			unsigned char tmp_buf[48];
+
+			if (s->session->cert->rsa_tmp != NULL)
+				rsa=s->session->cert->rsa_tmp;
+			else
+				{
+				pkey=X509_get_pubkey(s->session->cert->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,SSL_R_INTERNAL_ERROR);
+					goto err;
+					}
+				rsa=pkey->pkey.rsa;
+				}
+				
+			tmp_buf[0]=SSL3_VERSION_MAJOR;
+			tmp_buf[1]=SSL3_VERSION_MINOR;
+			RAND_bytes(&(tmp_buf[2]),SSL_MAX_MASTER_KEY_LENGTH-2);
+
+			s->session->master_key_length=SSL_MAX_MASTER_KEY_LENGTH;
+
+			n=RSA_public_encrypt(48,tmp_buf,p,rsa,
+				RSA_PKCS1_PADDING);
+			if (n <= 0)
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_ENCRYPT);
+				goto err;
+				}
+
+			s->session->master_key_length=
+				ssl3_generate_master_secret(s,
+					s->session->master_key,
+					tmp_buf,48);
+			memset(tmp_buf,0,48);
+			}
+		else
+#endif
+#ifndef NO_DH
+		if (l & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
+			{
+			DH *dh_srvr,*dh_clnt;
+
+			if (s->session->cert->dh_tmp != NULL)
+				dh_srvr=s->session->cert->dh_tmp;
+			else
+				{
+				/* we get them from the cert */
+				ssl3_send_alert(s,SSL3_AL_FATAL,SSL3_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=
+				ssl3_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*/
+			}
+		else
+#endif
+			{
+			ssl3_send_alert(s,SSL3_AL_FATAL,SSL3_AD_HANDSHAKE_FAILURE);
+			SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_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:
+	return(-1);
+	}
+
+static int ssl3_send_client_verify(s)
+SSL *s;
+	{
+	unsigned char *p,*d;
+	unsigned char data[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH];
+	EVP_PKEY *pkey;
+	int i=0,j;
+	unsigned long n;
+
+	if (s->state == SSL3_ST_CW_CERT_VRFY_A)
+		{
+		d=(unsigned char *)s->init_buf->data;
+		p= &(d[4]);
+		pkey=s->cert->key->privatekey;
+
+		ssl3_final_finish_mac(s,&(s->s3->finish_dgst2),
+			NULL,&(data[MD5_DIGEST_LENGTH]));
+
+#ifndef NO_RSA
+		if (pkey->type == EVP_PKEY_RSA)
+			{
+			ssl3_final_finish_mac(s,&(s->s3->finish_dgst1),
+				NULL,&(data[0]));
+			i=RSA_private_encrypt(
+				MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH,
+				data,&(p[2]),pkey->pkey.rsa,
+				RSA_PKCS1_PADDING);
+			if (i <= 0)
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_RSA_LIB);
+				goto err;
+				}
+			s2n(i,p);
+			n=i+2;
+			}
+		else
+#endif
+#ifndef 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
+			{
+			SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,SSL_R_INTERNAL_ERROR);
+			goto err;
+			}
+		*(d++)=SSL3_MT_CERTIFICATE_VERIFY;
+		l2n3(n,d);
+
+		s->init_num=(int)n+4;
+		s->init_off=0;
+		}
+	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+err:
+	return(-1);
+	}
+
+static int ssl3_send_client_certificate(s)
+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;
+		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=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)
+			{
+			s->s3->tmp.cert_req=0;
+			ssl3_send_alert(s,SSL3_AL_WARNING,SSL3_AD_NO_CERTIFICATE);
+			return(1);
+			}
+
+		/* 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->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))
+
+static int ssl3_check_cert_and_algorithm(s)
+SSL *s;
+	{
+	int i,idx;
+	long algs;
+	EVP_PKEY *pkey=NULL;
+	CERT *c;
+	RSA *rsa;
+	DH *dh;
+
+	c=s->session->cert;
+
+	if (c == NULL)
+		{
+		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_INTERNAL_ERROR);
+		goto err;
+		}
+
+	algs=s->s3->tmp.new_cipher->algorithms;
+
+	/* we don't have a certificate */
+	if (algs & (SSL_aDH|SSL_aNULL))
+		return(1);
+
+	rsa=s->session->cert->rsa_tmp;
+	dh=s->session->cert->dh_tmp;
+
+	/* This is the passed certificate */
+
+	idx=c->cert_type;
+	pkey=X509_get_pubkey(c->pkeys[idx].x509);
+	i=X509_certificate_type(c->pkeys[idx].x509,pkey);
+
+	
+	/* Check that we have a certificate if we require one */
+	if ((algs & 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 NO_DSA
+	else if ((algs & 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
+
+	if ((algs & 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;
+		}
+#ifndef NO_DH
+	else if ((algs & 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 ((algs & 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 NO_DSA
+	else if ((algs & 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 ((algs & SSL_EXP) && !has_bits(i,EVP_PKT_EXP))
+		{
+#ifndef NO_RSA
+		if (algs & SSL_kRSA)
+			{
+			if ((rsa == NULL) || (RSA_size(rsa) > 512))
+				{
+				SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_EXPORT_TMP_RSA_KEY);
+				goto f_err;
+				}
+			}
+		else
+#endif
+#ifndef NO_DH
+			if (algs & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
+			{
+			if ((dh == NULL) || (DH_size(dh) > 512))
+				{
+				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,SSL3_AD_HANDSHAKE_FAILURE);
+err:
+	return(0);
+	}
+
diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c
new file mode 100644
index 0000000..f1cd25e
--- /dev/null
+++ b/ssl/s3_enc.c
@@ -0,0 +1,481 @@
+/* ssl/s3_enc.c */
+/* Copyright (C) 1995-1997 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 "evp.h"
+#include "ssl_locl.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 };
+
+int ssl3_change_cipher_state(s,which)
+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_KEY_LENGTH];
+	unsigned char *ms,*key,*iv,*er1,*er2;
+	EVP_CIPHER_CTX *dd;
+	EVP_CIPHER *c;
+	SSL_COMPRESSION *comp;
+	EVP_MD *m;
+	MD5_CTX md;
+	int exp,n,i,j,k;
+
+	exp=(s->s3->tmp.new_cipher->algorithms & SSL_EXPORT)?1:0;
+	c=s->s3->tmp.new_sym_enc;
+	m=s->s3->tmp.new_hash;
+	comp=s->s3->tmp.new_compression;
+	key_block=s->s3->tmp.key_block;
+
+	if (which & SSL3_CC_READ)
+		{
+		if ((s->enc_read_ctx == NULL) &&
+			((s->enc_read_ctx=(EVP_CIPHER_CTX *)
+			Malloc(sizeof(EVP_CIPHER_CTX))) == NULL))
+			goto err;
+		dd= s->enc_read_ctx;
+		s->read_hash=m;
+		s->read_compression=comp;
+		memset(&(s->s3->read_sequence[0]),0,8);
+		mac_secret= &(s->s3->read_mac_secret[0]);
+		}
+	else
+		{
+		if ((s->enc_write_ctx == NULL) &&
+			((s->enc_write_ctx=(EVP_CIPHER_CTX *)
+			Malloc(sizeof(EVP_CIPHER_CTX))) == NULL))
+			goto err;
+		dd= s->enc_write_ctx;
+		s->write_hash=m;
+		s->write_compression=comp;
+		memset(&(s->s3->write_sequence[0]),0,8);
+		mac_secret= &(s->s3->write_mac_secret[0]);
+		}
+
+	p=s->s3->tmp.key_block;
+	i=EVP_MD_size(m);
+	j=(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,SSL_R_INTERNAL_ERROR);
+		goto err2;
+		}
+
+	memcpy(mac_secret,ms,i);
+	if (exp)
+		{
+		/* In here I set both the read and write key/iv to the
+		 * same value since only the correct one will be used :-).
+		 */
+		MD5_Init(&md);
+		MD5_Update(&md,key,j);
+		MD5_Update(&md,er1,SSL3_RANDOM_SIZE);
+		MD5_Update(&md,er2,SSL3_RANDOM_SIZE);
+		MD5_Final(&(exp_key[0]),&md);
+		key= &(exp_key[0]);
+
+		MD5_Init(&md);
+		MD5_Update(&md,er1,SSL3_RANDOM_SIZE);
+		MD5_Update(&md,er2,SSL3_RANDOM_SIZE);
+		MD5_Final(&(exp_iv[0]),&md);
+		iv= &(exp_iv[0]);
+		}
+
+	s->session->key_arg_length=k;
+	if (k > 0)
+		memcpy(&(s->session->key_arg[0]),iv,k);
+
+	EVP_CipherInit(dd,c,key,iv,(which & SSL3_CC_WRITE));
+	memset(&(exp_key[0]),0,sizeof(exp_key));
+	memset(&(exp_iv[0]),0,sizeof(exp_iv));
+	return(1);
+err:
+	SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE,ERR_R_MALLOC_FAILURE);
+err2:
+	return(0);
+	}
+
+int ssl3_setup_key_block(s)
+SSL *s;
+	{
+	unsigned char *p;
+	EVP_CIPHER *c;
+	EVP_MD *hash;
+	int num,exp;
+
+	if (s->s3->tmp.key_block_length != 0)
+		return(1);
+
+	if (!ssl_cipher_get_evp(s->session->cipher,&c,&hash))
+		{
+		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;
+
+	exp=(s->session->cipher->algorithms & SSL_EXPORT)?1:0;
+
+	num=EVP_CIPHER_key_length(c)+EVP_MD_size(hash)+EVP_CIPHER_iv_length(c);
+	num*=2;
+
+	ssl3_cleanup_key_block(s);
+
+	if ((p=(unsigned char *)Malloc(num)) == NULL)
+		goto err;
+
+	s->s3->tmp.key_block_length=num;
+	s->s3->tmp.key_block=p;
+
+	ssl3_generate_key_block(s,p,num);
+
+	return(1);
+err:
+	SSLerr(SSL_F_SSL3_SETUP_KEY_BLOCK,ERR_R_MALLOC_FAILURE);
+	return(0);
+	}
+
+void ssl3_cleanup_key_block(s)
+SSL *s;
+	{
+	if (s->s3->tmp.key_block != NULL)
+		{
+		memset(s->s3->tmp.key_block,0,
+			s->s3->tmp.key_block_length);
+		Free(s->s3->tmp.key_block);
+		s->s3->tmp.key_block=NULL;
+		}
+	s->s3->tmp.key_block_length=0;
+	}
+
+int ssl3_enc(s,send)
+SSL *s;
+int send;
+	{
+	SSL3_RECORD *rec;
+	EVP_CIPHER_CTX *ds;
+	unsigned long l;
+	int bs,i;
+	EVP_CIPHER *enc;
+	SSL_COMPRESSION *comp;
+
+	if (send)
+		{
+		ds=s->enc_write_ctx;
+		rec= &(s->s3->wrec);
+		if (s->enc_write_ctx == NULL)
+			{ enc=NULL; comp=NULL; }
+		else
+			{
+			enc=EVP_CIPHER_CTX_cipher(s->enc_write_ctx);
+			comp=s->write_compression;
+			}
+		}
+	else
+		{
+		ds=s->enc_read_ctx;
+		rec= &(s->s3->rrec);
+		if (s->enc_read_ctx == NULL)
+			{ enc=NULL; comp=NULL; }
+		else
+			{
+			enc=EVP_CIPHER_CTX_cipher(s->enc_read_ctx);
+			comp=s->read_compression;
+			}
+		}
+
+	if ((s->session == NULL) || (ds == NULL) ||
+		((enc == NULL) && (comp == NULL)))
+		{
+		memcpy(rec->data,rec->input,rec->length);
+		rec->input=rec->data;
+		}
+	else
+		{
+		l=rec->length;
+		bs=EVP_CIPHER_block_size(ds->cipher);
+
+		/* This should be using (bs-1) and bs instead of 7 and 8 */
+		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);
+			}
+
+		EVP_Cipher(ds,rec->data,rec->input,l);
+
+		if ((bs != 1) && !send)
+			{
+			i=rec->data[l-1]+1;
+			if (i > bs)
+				{
+				SSLerr(SSL_F_SSL3_ENC,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG);
+				ssl3_send_alert(s,SSL3_AL_FATAL,SSL3_AD_BAD_RECORD_MAC);
+				return(0);
+				}
+			rec->length-=i;
+			}
+		}
+	return(1);
+	}
+
+void ssl3_init_finished_mac(s)
+SSL *s;
+	{
+	EVP_DigestInit(&(s->s3->finish_dgst1),EVP_md5());
+	EVP_DigestInit(&(s->s3->finish_dgst2),EVP_sha1());
+	}
+
+void ssl3_finish_mac(s,buf,len)
+SSL *s;
+unsigned char *buf;
+int len;
+	{
+	EVP_DigestUpdate(&(s->s3->finish_dgst1),buf,len);
+	EVP_DigestUpdate(&(s->s3->finish_dgst2),buf,len);
+	}
+
+int ssl3_final_finish_mac(s,in_ctx,sender,p)
+SSL *s;
+EVP_MD_CTX *in_ctx;
+unsigned char *sender;
+unsigned char *p;
+	{
+	unsigned int ret;
+	int npad,n;
+	unsigned int i;
+	unsigned char md_buf[EVP_MAX_MD_SIZE];
+	EVP_MD_CTX ctx;
+
+	memcpy(&ctx,in_ctx,sizeof(EVP_MD_CTX));
+
+	n=EVP_MD_CTX_size(&ctx);
+	npad=(48/n)*n;
+
+	if (sender != NULL)
+		EVP_DigestUpdate(&ctx,sender,4);
+	EVP_DigestUpdate(&ctx,s->session->master_key,
+		s->session->master_key_length);
+	EVP_DigestUpdate(&ctx,ssl3_pad_1,npad);
+	EVP_DigestFinal(&ctx,md_buf,&i);
+
+	EVP_DigestInit(&ctx,EVP_MD_CTX_type(&ctx));
+	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(&ctx,p,&ret);
+
+	memset(&ctx,0,sizeof(EVP_MD_CTX));
+
+	return((int)ret);
+	}
+
+int ssl3_mac(ssl,md,send)
+SSL *ssl;
+unsigned char *md;
+int send;
+	{
+	SSL3_RECORD *rec;
+	unsigned char *mac_sec,*seq;
+	EVP_MD_CTX md_ctx;
+	EVP_MD *hash;
+	unsigned char *p,rec_char;
+	unsigned int md_size;
+	int npad,i;
+
+	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;
+		}
+
+	md_size=EVP_MD_size(hash);
+	npad=(48/md_size)*md_size;
+
+#ifdef MAC_DEBUG
+printf("npad=%d md_size=%d",npad,md_size);
+printf("\nmsec=");
+for (i=0; i<md_size; i++) printf("%02X ",mac_sec[i]);
+printf("\npad1=");
+for (i=0; i<npad; i++) printf("%02X ",ssl3_pad_1[i]);
+printf("\nseq =");
+for (i=0; i<8; i++) printf("%02X ",seq[i]);
+printf("\nreqt=%02X len=%04X\n",rec->type,rec->length);
+for (i=0; i<rec->length; i++) printf("%02X",rec->input[i]);
+printf("\n");
+#endif
+
+	/* Chop the digest off the end :-) */
+
+	EVP_DigestInit(  &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( &md_ctx,md,NULL);
+
+	EVP_DigestInit(  &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( &md_ctx,md,&md_size);
+
+	for (i=7; i>=0; i--)
+		if (++seq[i]) break; 
+
+#ifdef MAC_DEBUG
+printf("md=");
+for (i=0; i<md_size; i++) printf("%02X ",md[i]);
+printf("\n");
+#endif
+
+	return(md_size);
+	}
+
+int ssl3_generate_master_secret(s,out,p,len)
+SSL *s;
+unsigned char *out;
+unsigned char *p;
+int len;
+	{
+	static unsigned char *salt[3]={
+		(unsigned char *)"A",
+		(unsigned char *)"BB",
+		(unsigned char *)"CCC",
+		};
+	unsigned char buf[EVP_MAX_MD_SIZE];
+	EVP_MD_CTX ctx;
+	int i,ret=0;
+	unsigned int n;
+
+	for (i=0; i<3; i++)
+		{
+		EVP_DigestInit(&ctx,EVP_sha1());
+		EVP_DigestUpdate(&ctx,salt[i],strlen((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(&ctx,buf,&n);
+
+		EVP_DigestInit(&ctx,EVP_md5());
+		EVP_DigestUpdate(&ctx,p,len);
+		EVP_DigestUpdate(&ctx,buf,n);
+		EVP_DigestFinal(&ctx,out,&n);
+		out+=n;
+		ret+=n;
+		}
+	return(ret);
+	}
+
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
new file mode 100644
index 0000000..b7bac8e
--- /dev/null
+++ b/ssl/s3_lib.c
@@ -0,0 +1,915 @@
+/* ssl/s3_lib.c */
+/* Copyright (C) 1995-1997 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 "objects.h"
+#include "ssl_locl.h"
+
+char *ssl3_version_str="SSLv3 part of SSLeay 0.8.1b 29-Jun-1998";
+
+#define SSL3_NUM_CIPHERS	(sizeof(ssl3_ciphers)/sizeof(SSL_CIPHER))
+
+#ifndef NOPROTO
+static long ssl3_default_timeout(void );
+#else
+static long ssl3_default_timeout();
+#endif
+
+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_NOT_EXP|SSL_SSLV3,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+/* Cipher 02 */
+	{
+	1,
+	SSL3_TXT_RSA_NULL_SHA,
+	SSL3_CK_RSA_NULL_SHA,
+	SSL_kRSA|SSL_aRSA|SSL_eNULL |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+
+/* anon DH */
+/* Cipher 17 */
+	{
+	1,
+	SSL3_TXT_ADH_RC4_40_MD5,
+	SSL3_CK_ADH_RC4_40_MD5,
+	SSL_kEDH |SSL_aNULL|SSL_RC4  |SSL_MD5 |SSL_EXP|SSL_SSLV3,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+/* Cipher 18 */
+	{
+	1,
+	SSL3_TXT_ADH_RC4_128_MD5,
+	SSL3_CK_ADH_RC4_128_MD5,
+	SSL_kEDH |SSL_aNULL|SSL_RC4  |SSL_MD5|SSL_NOT_EXP|SSL_SSLV3,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+/* 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_EXP|SSL_SSLV3,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+/* 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_NOT_EXP|SSL_SSLV3,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+/* Cipher 1B */
+	{
+	1,
+	SSL3_TXT_ADH_DES_196_CBC_SHA,
+	SSL3_CK_ADH_DES_196_CBC_SHA,
+	SSL_kEDH |SSL_aNULL|SSL_3DES |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+
+/* RSA again */
+/* Cipher 03 */
+	{
+	1,
+	SSL3_TXT_RSA_RC4_40_MD5,
+	SSL3_CK_RSA_RC4_40_MD5,
+	SSL_kRSA|SSL_aRSA|SSL_RC4  |SSL_MD5 |SSL_EXP|SSL_SSLV3,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+/* Cipher 04 */
+	{
+	1,
+	SSL3_TXT_RSA_RC4_128_MD5,
+	SSL3_CK_RSA_RC4_128_MD5,
+	SSL_kRSA|SSL_aRSA|SSL_RC4  |SSL_MD5|SSL_NOT_EXP|SSL_SSLV3|SSL_MEDIUM,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+/* Cipher 05 */
+	{
+	1,
+	SSL3_TXT_RSA_RC4_128_SHA,
+	SSL3_CK_RSA_RC4_128_SHA,
+	SSL_kRSA|SSL_aRSA|SSL_RC4  |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3|SSL_MEDIUM,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+/* Cipher 06 */
+	{
+	1,
+	SSL3_TXT_RSA_RC2_40_MD5,
+	SSL3_CK_RSA_RC2_40_MD5,
+	SSL_kRSA|SSL_aRSA|SSL_RC2  |SSL_MD5 |SSL_EXP|SSL_SSLV3,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+/* Cipher 07 */
+	{
+	1,
+	SSL3_TXT_RSA_IDEA_128_SHA,
+	SSL3_CK_RSA_IDEA_128_SHA,
+	SSL_kRSA|SSL_aRSA|SSL_IDEA |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3|SSL_MEDIUM,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+/* 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_EXP|SSL_SSLV3,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+/* 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_NOT_EXP|SSL_SSLV3|SSL_LOW,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+/* 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_NOT_EXP|SSL_SSLV3|SSL_HIGH,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+
+/*  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_EXP|SSL_SSLV3,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+/* Cipher 0C */
+	{
+	0,
+	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_NOT_EXP|SSL_SSLV3|SSL_LOW,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+/* Cipher 0D */
+	{
+	0,
+	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_NOT_EXP|SSL_SSLV3|SSL_HIGH,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+/* Cipher 0E */
+	{
+	0,
+	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_EXP|SSL_SSLV3,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+/* Cipher 0F */
+	{
+	0,
+	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_NOT_EXP|SSL_SSLV3|SSL_LOW,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+/* Cipher 10 */
+	{
+	0,
+	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_NOT_EXP|SSL_SSLV3|SSL_HIGH,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+
+/* 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_EXP|SSL_SSLV3,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+/* 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_NOT_EXP|SSL_SSLV3|SSL_LOW,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+/* 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_NOT_EXP|SSL_SSLV3|SSL_HIGH,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+/* 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_EXP|SSL_SSLV3,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+/* 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_NOT_EXP|SSL_SSLV3|SSL_LOW,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+/* 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_NOT_EXP|SSL_SSLV3|SSL_HIGH,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+
+/* Fortezza */
+/* Cipher 1C */
+	{
+	0,
+	SSL3_TXT_FZA_DMS_NULL_SHA,
+	SSL3_CK_FZA_DMS_NULL_SHA,
+	SSL_kFZA|SSL_aFZA |SSL_eNULL |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+
+/* Cipher 1D */
+	{
+	0,
+	SSL3_TXT_FZA_DMS_FZA_SHA,
+	SSL3_CK_FZA_DMS_FZA_SHA,
+	SSL_kFZA|SSL_aFZA |SSL_eFZA |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+
+/* Cipher 1E */
+	{
+	0,
+	SSL3_TXT_FZA_DMS_RC4_SHA,
+	SSL3_CK_FZA_DMS_RC4_SHA,
+	SSL_kFZA|SSL_aFZA |SSL_RC4  |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3,
+	0,
+	SSL_ALL_CIPHERS,
+	},
+
+/* end of list */
+	};
+
+static SSL_METHOD SSLv3_data= {
+	3,
+	ssl3_new,
+	ssl3_clear,
+	ssl3_free,
+	ssl_undefined_function,
+	ssl_undefined_function,
+	ssl3_read,
+	ssl3_peek,
+	ssl3_write,
+	ssl3_shutdown,
+	ssl3_renegotiate,
+	ssl3_ctrl,
+	ssl3_ctx_ctrl,
+	ssl3_get_cipher_by_char,
+	ssl3_put_cipher_by_char,
+	ssl3_pending,
+	ssl3_num_ciphers,
+	ssl3_get_cipher,
+	ssl_bad_method,
+	ssl3_default_timeout,
+	};
+
+static long ssl3_default_timeout()
+	{
+	/* 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);
+	}
+
+SSL_METHOD *sslv3_base_method()
+	{
+	return(&SSLv3_data);
+	}
+
+int ssl3_num_ciphers()
+	{
+	return(SSL3_NUM_CIPHERS);
+	}
+
+SSL_CIPHER *ssl3_get_cipher(u)
+unsigned int u;
+	{
+	if (u < SSL3_NUM_CIPHERS)
+		return(&(ssl3_ciphers[SSL3_NUM_CIPHERS-1-u]));
+	else
+		return(NULL);
+	}
+
+/* The problem is that it may not be the correct record type */
+int ssl3_pending(s)
+SSL *s;
+	{
+	return(s->s3->rrec.length);
+	}
+
+int ssl3_new(s)
+SSL *s;
+	{
+	SSL3_CTX *s3;
+
+	if ((s3=(SSL3_CTX *)Malloc(sizeof(SSL3_CTX))) == NULL) goto err;
+
+	s->s3=s3;
+	s->s3->tmp.ca_names=NULL;
+	s->s3->tmp.key_block=NULL;
+	s->s3->rbuf.buf=NULL;
+	s->s3->wbuf.buf=NULL;
+
+	ssl3_clear(s);
+	return(1);
+err:
+	return(0);
+	}
+
+void ssl3_free(s)
+SSL *s;
+	{
+	ssl3_cleanup_key_block(s);
+	if (s->s3->rbuf.buf != NULL)
+		Free(s->s3->rbuf.buf);
+	if (s->s3->wbuf.buf != NULL)
+		Free(s->s3->wbuf.buf);
+#ifndef NO_DH
+	if (s->s3->tmp.dh != NULL)
+		DH_free(s->s3->tmp.dh);
+#endif
+	if (s->s3->tmp.ca_names != NULL)
+		sk_pop_free(s->s3->tmp.ca_names,X509_NAME_free);
+	memset(s->s3,0,sizeof(SSL3_CTX));
+	Free(s->s3);
+	s->s3=NULL;
+	}
+
+void ssl3_clear(s)
+SSL *s;
+	{
+	unsigned char *rp,*wp;
+
+	ssl3_cleanup_key_block(s);
+	if (s->s3->tmp.ca_names != NULL)
+		sk_pop_free(s->s3->tmp.ca_names,X509_NAME_free);
+
+	rp=s->s3->rbuf.buf;
+	wp=s->s3->wbuf.buf;
+
+	memset(s->s3,0,sizeof(SSL3_CTX));
+	if (rp != NULL)
+		{
+		s->packet= &(s->s3->rbuf.buf[0]);
+		s->s3->rbuf.buf=rp;
+		s->s3->wbuf.buf=wp;
+		}
+	else
+		s->packet=NULL;
+	s->packet_length=0;
+	s->version=3;
+	}
+
+long ssl3_ctrl(s,cmd,larg,parg)
+SSL *s;
+int cmd;
+long larg;
+char *parg;
+	{
+	return(0);
+	}
+
+long ssl3_ctx_ctrl(ctx,cmd,larg,parg)
+SSL_CTX *ctx;
+int cmd;
+long larg;
+char *parg;
+	{
+	CERT *cert;
+
+	cert=ctx->default_cert;
+
+	switch (cmd)
+		{
+#ifndef 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:
+		cert->rsa_tmp_cb=(RSA *(*)())parg;
+		break;
+#endif
+#ifndef NO_DH
+	case SSL_CTRL_SET_TMP_DH:
+		{
+		DH *new=NULL,*dh;
+
+		dh=(DH *)parg;
+		if (	((new=DHparams_dup(dh)) == NULL) ||
+			(!DH_generate_key(new)))
+			{
+			SSLerr(SSL_F_SSL3_CTX_CTRL,ERR_R_DH_LIB);
+			if (new != NULL) DH_free(new);
+			return(0);
+			}
+		else
+			{
+			if (cert->dh_tmp != NULL)
+				DH_free(cert->dh_tmp);
+			cert->dh_tmp=new;
+			return(1);
+			}
+		}
+		break;
+	case SSL_CTRL_SET_TMP_DH_CB:
+		cert->dh_tmp_cb=(DH *(*)())parg;
+		break;
+#endif
+	default:
+		return(0);
+		}
+	return(1);
+	}
+
+/* This function needs to check if the ciphers required are actually
+ * available */
+SSL_CIPHER *ssl3_get_cipher_by_char(p)
+unsigned char *p;
+	{
+	static int init=1;
+	static SSL_CIPHER *sorted[SSL3_NUM_CIPHERS];
+	SSL_CIPHER c,*cp= &c,**cpp;
+	unsigned long id;
+	int i;
+
+	if (init)
+		{
+		init=0;
+
+		for (i=0; i<SSL3_NUM_CIPHERS; i++)
+			sorted[i]= &(ssl3_ciphers[i]);
+
+		qsort(	(char *)sorted,
+			SSL3_NUM_CIPHERS,sizeof(SSL_CIPHER *),
+			FP_ICC ssl_cipher_ptr_id_cmp);
+		}
+
+	id=0x03000000L|((unsigned long)p[0]<<8L)|(unsigned long)p[1];
+	c.id=id;
+	cpp=(SSL_CIPHER **)OBJ_bsearch((char *)&cp,
+		(char *)sorted,
+		SSL3_NUM_CIPHERS,sizeof(SSL_CIPHER *),
+		(int (*)())ssl_cipher_ptr_id_cmp);
+	if ((cpp == NULL) || !(*cpp)->valid)
+		return(NULL);
+	else
+		return(*cpp);
+	}
+
+int ssl3_put_cipher_by_char(c,p)
+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);
+	}
+
+void ssl3_generate_key_block(s,km,num)
+SSL *s;
+unsigned char *km;
+int num;
+	{
+	MD5_CTX m5;
+	SHA_CTX s1;
+	unsigned char buf[8],smd[SHA_DIGEST_LENGTH];
+	unsigned char c='A';
+	int i,j,k;
+
+	k=0;
+	for (i=0; i<num; i+=MD5_DIGEST_LENGTH)
+		{
+		k++;
+		for (j=0; j<k; j++)
+			buf[j]=c;
+		c++;
+		SHA1_Init(  &s1);
+		SHA1_Update(&s1,buf,k);
+		SHA1_Update(&s1,s->session->master_key,
+			s->session->master_key_length);
+		SHA1_Update(&s1,s->s3->server_random,SSL3_RANDOM_SIZE);
+		SHA1_Update(&s1,s->s3->client_random,SSL3_RANDOM_SIZE);
+		SHA1_Final( smd,&s1);
+
+		MD5_Init(  &m5);
+		MD5_Update(&m5,s->session->master_key,
+			s->session->master_key_length);
+		MD5_Update(&m5,smd,SHA_DIGEST_LENGTH);
+		if ((i+MD5_DIGEST_LENGTH) > num)
+			{
+			MD5_Final(smd,&m5);
+			memcpy(km,smd,(num-i));
+			}
+		else
+			MD5_Final(km,&m5);
+
+		km+=MD5_DIGEST_LENGTH;
+		}
+	memset(smd,0,SHA_DIGEST_LENGTH);
+	}
+
+int ssl3_part_read(s,i)
+SSL *s;
+int i;
+	{
+	s->rwstate=SSL_READING;
+
+	if (i < 0)
+		{
+		return(i);
+		}
+	else
+		{
+		s->init_num+=i;
+		return(0);
+		}
+	}
+
+SSL_CIPHER *ssl3_choose_cipher(s,have,pref)
+SSL *s;
+STACK *have,*pref;
+	{
+	SSL_CIPHER *c,*ret=NULL;
+	int i,j,ok;
+	CERT *cert;
+	unsigned long alg,mask,emask;
+
+	/* Lets see which ciphers we can supported */
+	if (s->cert != NULL)
+		cert=s->cert;
+	else
+		cert=s->ctx->default_cert;
+
+	ssl_set_cert_masks(cert);
+	mask=cert->mask;
+	emask=cert->export_mask;
+			
+	sk_set_cmp_func(pref,ssl_cipher_ptr_id_cmp);
+
+	for (i=0; i<sk_num(have); i++)
+		{
+		c=(SSL_CIPHER *)sk_value(have,i);
+		alg=c->algorithms&(SSL_MKEY_MASK|SSL_AUTH_MASK);
+		if (alg & SSL_EXPORT)
+			{
+			ok=((alg & emask) == alg)?1:0;
+#ifdef CIPHER_DEBUG
+			printf("%d:[%08lX:%08lX]%s\n",ok,alg,mask,c->name);
+#endif
+			}
+		else
+			{
+			ok=((alg & mask) == alg)?1:0;
+#ifdef CIPHER_DEBUG
+			printf("%d:[%08lX:%08lX]%s\n",ok,alg,mask,c->name);
+#endif
+			}
+
+		if (!ok) continue;
+	
+		j=sk_find(pref,(char *)c);
+		if (j >= 0)
+			{
+			ret=(SSL_CIPHER *)sk_value(pref,j);
+			break;
+			}
+		}
+	return(ret);
+	}
+
+int ssl3_get_req_cert_type(s,p)
+SSL *s;
+unsigned char *p;
+	{
+	int ret=0;
+	unsigned long alg;
+
+	alg=s->s3->tmp.new_cipher->algorithms;
+
+#ifndef NO_DH
+	if (alg & (SSL_kDHr|SSL_kEDH))
+		{
+#ifndef NO_RSA
+		p[ret++]=SSL3_CT_RSA_FIXED_DH;
+#endif
+#ifndef NO_DSA
+		p[ret++]=SSL3_CT_DSS_FIXED_DH;
+#endif
+		}
+	if (alg & (SSL_kEDH|SSL_kDHd|SSL_kDHr))
+		{
+#ifndef NO_RSA
+		p[ret++]=SSL3_CT_RSA_EPHEMERAL_DH;
+#endif
+#ifndef NO_DSA
+		p[ret++]=SSL3_CT_DSS_EPHEMERAL_DH;
+#endif
+		}
+#endif /* !NO_DH */
+#ifndef NO_RSA
+	p[ret++]=SSL3_CT_RSA_SIGN;
+#endif
+/*	p[ret++]=SSL3_CT_DSS_SIGN; */
+	return(ret);
+	}
+
+int ssl3_shutdown(s)
+SSL *s;
+	{
+
+	/* 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,SSL3_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 */
+		}
+	else if (s->s3->alert_dispatch)
+		{
+		/* resend it if not sent */
+#if 1
+		ssl3_dispatch_alert(s);
+#endif
+		}
+	else if (!(s->shutdown & SSL_RECEIVED_SHUTDOWN))
+		{
+		/* If we are waiting for a close from our peer, we are closed */
+		ssl3_read_bytes(s,0,NULL,0);
+		}
+
+	if ((s->shutdown == (SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN)) &&
+		!s->s3->alert_dispatch)
+		return(1);
+	else
+		return(0);
+	}
+
+int ssl3_write(s,buf,len)
+SSL *s;
+const char *buf;
+int len;
+	{
+	int ret,n;
+	BIO *under;
+
+#if 0
+	if (s->shutdown & SSL_SEND_SHUTDOWN)
+		{
+		s->rwstate=SSL_NOTHING;
+		return(0);
+		}
+#endif
+	errno=0;
+
+	/* 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,
+				(char *)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 */
+		under=BIO_pop(s->wbio);
+		s->wbio=under;
+		BIO_free(s->bbio);
+		s->bbio=NULL;
+		ret=s->s3->delay_buf_pop_ret;
+		s->s3->delay_buf_pop_ret=0;
+
+		s->s3->flags&= ~SSL3_FLAGS_POP_BUFFER;
+		}
+	else
+		{
+		ret=ssl3_write_bytes(s,SSL3_RT_APPLICATION_DATA,
+			(char *)buf,len);
+		if (ret <= 0) return(ret);
+		}
+	return(ret);
+	}
+
+int ssl3_read(s,buf,len)
+SSL *s;
+char *buf;
+int len;
+	{
+	errno=0;
+	return(ssl3_read_bytes(s,SSL3_RT_APPLICATION_DATA,buf,len));
+	}
+
+int ssl3_peek(s,buf,len)
+SSL *s;
+char *buf;
+int len;
+	{
+	SSL3_RECORD *rr;
+	int n;
+
+	rr= &(s->s3->rrec);
+	if ((rr->length == 0) || (rr->type != SSL3_RT_APPLICATION_DATA))
+		return(0);
+
+	if ((unsigned int)len > rr->length)
+		n=rr->length;
+	else
+		n=len;
+	memcpy(buf,&(rr->data[rr->off]),(unsigned int)n);
+	return(n);
+	}
+
+int ssl3_renegotiate(s)
+SSL *s;
+	{
+	if (s->handshake_func == NULL)
+		return(1);
+
+	if (s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)
+		return(0);
+
+	if (!SSL_in_init(s))
+		s->state=SSL_ST_RENEGOTIATE;
+	return(1);
+	}
+
diff --git a/ssl/s3_meth.c b/ssl/s3_meth.c
new file mode 100644
index 0000000..4762b21
--- /dev/null
+++ b/ssl/s3_meth.c
@@ -0,0 +1,88 @@
+/* ssl/s3_meth.c */
+/* Copyright (C) 1995-1997 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 "objects.h"
+#include "ssl_locl.h"
+
+static SSL_METHOD *ssl3_get_method(ver)
+int ver;
+	{
+	if (ver == 3)
+		return(SSLv3_method());
+	else
+		return(NULL);
+	}
+
+SSL_METHOD *SSLv3_method()
+	{
+	static int init=1;
+	static SSL_METHOD SSLv3_data;
+
+	if (init)
+		{
+		init=0;
+		memcpy((char *)&SSLv3_data,(char *)sslv3_base_method(),
+			sizeof(SSL_METHOD));
+		SSLv3_data.ssl_connect=ssl3_connect;
+		SSLv3_data.ssl_accept=ssl3_accept;
+		SSLv3_data.get_ssl_method=ssl3_get_method;
+		}
+	return(&SSLv3_data);
+	}
+
diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c
new file mode 100644
index 0000000..3be69ef
--- /dev/null
+++ b/ssl/s3_pkt.c
@@ -0,0 +1,963 @@
+/* ssl/s3_pkt.c */
+/* Copyright (C) 1995-1997 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 "evp.h"
+#include "buffer.h"
+#include "ssl_locl.h"
+
+/* SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_PEER_ERROR_NO_CIPHER);
+ * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_PEER_ERROR_NO_CERTIFICATE);
+ * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_PEER_ERROR_CERTIFICATE);
+ * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE);
+ * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_UNKNOWN_REMOTE_ERROR_TYPE);
+ * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE);
+ * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_BAD_RECORD_MAC);
+ * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE);
+ * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE);
+ * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_NO_CERTIFICATE);
+ * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_BAD_CERTIFICATE);
+ * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE);
+ * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED);
+ * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED);
+ * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN);
+ * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER);
+ */
+
+#ifndef NOPROTO
+static int do_ssl3_write(SSL *s, int type, char *buf, unsigned int len);
+static int ssl3_write_pending(SSL *s, int type, char *buf, unsigned int len);
+static int ssl3_get_record(SSL *s);
+static int do_compress(SSL *ssl);
+static int do_uncompress(SSL *ssl);
+#else
+static int do_ssl3_write();
+static int ssl3_write_pending();
+static int ssl3_get_record();
+static int do_compress();
+static int do_uncompress();
+#endif
+
+static int ssl3_read_n(s,n,max,extend)
+SSL *s;
+int n;
+int max;
+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->s3->rbuf.left >= (int)n)
+		{
+		if (extend)
+			s->packet_length+=n;
+		else
+			{
+			s->packet= &(s->s3->rbuf.buf[s->s3->rbuf.offset]);
+			s->packet_length=n;
+			}
+		s->s3->rbuf.left-=n;
+		s->s3->rbuf.offset+=n;
+		return(n);
+		}
+
+	/* else we need to read more data */
+	if (!s->read_ahead) max=n;
+	if (max > SSL3_RT_MAX_PACKET_SIZE)
+		max=SSL3_RT_MAX_PACKET_SIZE;
+
+	/* First check if there is some left or we want to extend */
+	off=0;
+	if (	(s->s3->rbuf.left != 0) ||
+		((s->packet_length != 0) && extend))
+		{
+		newb=s->s3->rbuf.left;
+		if (extend)
+			{
+			/* Copy bytes back to the front of the buffer 
+			 * Take the bytes already pointed to by 'packet'
+			 * and take the extra ones on the end. */
+			off=s->packet_length;
+			if (s->packet != s->s3->rbuf.buf)
+				memcpy(s->s3->rbuf.buf,s->packet,newb+off);
+			}
+		else if (s->s3->rbuf.offset != 0)
+			{ /* so the data is not at the start of the buffer */
+			memcpy(s->s3->rbuf.buf,
+				&(s->s3->rbuf.buf[s->s3->rbuf.offset]),newb);
+			s->s3->rbuf.offset=0;
+			}
+
+		s->s3->rbuf.left=0;
+		}
+	else
+		newb=0;
+
+	/* So we now have 'newb' bytes at the front of 
+	 * s->s3->rbuf.buf and need to read some more in on the end
+	 * We start reading into the buffer at 's->s3->rbuf.offset'
+	 */
+	s->packet=s->s3->rbuf.buf;
+
+	while (newb < n)
+		{
+		errno=0;
+		if (s->rbio != NULL)
+			{
+			s->rwstate=SSL_READING;
+			i=BIO_read(s->rbio,
+				(char *)&(s->s3->rbuf.buf[off+newb]),
+				max-newb);
+			}
+		else
+			{
+			SSLerr(SSL_F_SSL3_READ_N,SSL_R_READ_BIO_NOT_SET);
+			i= -1;
+			}
+
+		if (i <= 0)
+			{
+			s->s3->rbuf.left+=newb;
+			return(i);
+			}
+		newb+=i;
+		}
+
+	/* record used data read */
+	if (newb > n)
+		{
+		s->s3->rbuf.offset=n+off;
+		s->s3->rbuf.left=newb-n;
+		}
+	else
+		{
+		s->s3->rbuf.offset=0;
+		s->s3->rbuf.left=0;
+		}
+
+	if (extend)
+		s->packet_length+=n;
+	else
+		s->packet_length+=n;
+	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
+ */
+static int ssl3_get_record(s)
+SSL *s;
+	{
+	int ssl_major,ssl_minor,al;
+	int n,i,ret= -1;
+	SSL3_BUFFER *rb;
+	SSL3_RECORD *rr;
+	SSL_SESSION *sess;
+	unsigned char *p;
+	unsigned char md[EVP_MAX_MD_SIZE];
+	short version;
+	unsigned int mac_size;
+	int clear=0,extra;
+
+	rr= &(s->s3->rrec);
+	rb= &(s->s3->rbuf);
+	sess=s->session;
+
+	if (s->ctx->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER)
+		extra=SSL3_RT_MAX_EXTRA;
+	else
+		extra=0;
+
+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,
+			SSL3_RT_MAX_PACKET_SIZE,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);
+
+		/* Lets check version */
+		if (s->first_packet)
+			{
+			s->first_packet=0;
+			}
+		else
+			{
+		if (	(ssl_major != SSL3_VERSION_MAJOR) ||
+			(ssl_minor != SSL3_VERSION_MINOR))
+			{
+			al=SSL3_AD_ILLEGAL_PARAMETER;
+			SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER);
+			goto f_err;
+			}
+			}
+
+		if (s->version != SSL3_VERSION_MAJOR)
+			{
+			SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_INTERNAL_ERROR);
+			goto err;
+			}
+
+		if (rr->length > 
+			(unsigned int)SSL3_RT_MAX_ENCRYPTED_LENGTH+extra)
+			{
+			al=SSL3_AD_ILLEGAL_PARAMETER;
+			SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_PACKET_LENGTH_TOO_LONG);
+			goto f_err;
+			}
+
+		s->rstate=SSL_ST_READ_BODY;
+		}
+
+	/* get and decode the data */
+	if (s->rstate == SSL_ST_READ_BODY)
+		{
+		if (rr->length > (s->packet_length-SSL3_RT_HEADER_LENGTH))
+			{
+			i=rr->length;
+			/*-(s->packet_length-SSL3_RT_HEADER_LENGTH); */
+			n=ssl3_read_n(s,i,i,1);
+			if (n <= 0) return(n); /* error or non-blocking io */
+			}
+		s->rstate=SSL_ST_READ_HEADER;
+		}
+
+	/* At this point, we have the data in s->packet and there should be
+	 * s->packet_length bytes, we must not 'overrun' this buffer :-)
+	 * One of the following functions will copy the data from the
+	 * s->packet buffer */
+
+	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 */ 
+
+	/* Set the state for the following operations */
+	s->rstate=SSL_ST_READ_HEADER;
+
+	/* We now have - encrypted [ MAC [ compressed [ plain ] ] ]
+	 * rr->length bytes of encrypted compressed stuff. */
+
+	/* check is not needed I belive */
+	if (rr->length > (unsigned int)SSL3_RT_MAX_ENCRYPTED_LENGTH+extra)
+		{
+		al=SSL3_AD_ILLEGAL_PARAMETER;
+		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;
+
+	if (!ssl3_enc(s,0))
+		{
+		al=SSL3_AD_ILLEGAL_PARAMETER;
+		goto f_err;
+		}
+
+	/* 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)
+		{
+		mac_size=EVP_MD_size(s->read_hash);
+
+		if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra+mac_size)
+			{
+			al=SSL3_AD_ILLEGAL_PARAMETER;
+			SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_PRE_MAC_LENGTH_TOO_LONG);
+			goto f_err;
+			}
+		/* check MAC for rr->input' */
+		if (rr->length < mac_size)
+			{
+			al=SSL3_AD_ILLEGAL_PARAMETER;
+			SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_LENGTH_TOO_SHORT);
+			goto f_err;
+			}
+		rr->length-=mac_size;
+		i=ssl3_mac(s,md,0);
+		if (memcmp(md,&(rr->data[rr->length]),mac_size) != 0)
+			{
+			al=SSL3_AD_BAD_RECORD_MAC;
+			SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_BAD_MAC_DECODE);
+			ret=SSL_RWERR_BAD_MAC_DECODE;
+			goto f_err;
+			}
+		}
+
+	/* r->length is now just compressed */
+	if ((sess != NULL) && (sess->read_compression != NULL))
+		{
+		if (rr->length > 
+			(unsigned int)SSL3_RT_MAX_COMPRESSED_LENGTH+extra)
+			{
+			al=SSL3_AD_ILLEGAL_PARAMETER;
+			SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_COMPRESSED_LENGTH_TOO_LONG);
+			goto f_err;
+			}
+		if (!do_uncompress(s))
+			{
+			al=SSL3_AD_DECOMPRESSION_FAILURE;
+			SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_BAD_DECOMPRESSION);
+			goto f_err;
+			}
+		}
+
+	if (rr->length > (unsigned int)SSL3_RT_MAX_PLAIN_LENGTH+extra)
+		{
+		al=SSL3_AD_DECOMPRESSION_FAILURE;
+		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;
+
+	return(1);
+f_err:
+	ssl3_send_alert(s,SSL3_AL_FATAL,al);
+err:
+	return(ret);
+	}
+
+static int do_uncompress(ssl)
+SSL *ssl;
+	{
+	return(1);
+	}
+
+static int do_compress(ssl)
+SSL *ssl;
+	{
+	return(1);
+	}
+
+/* Call this write a data
+ * It will return <= 0 if not all data has been sent or non-blocking IO.
+ */
+int ssl3_write_bytes(s,type,buf,len)
+SSL *s;
+int type;
+char *buf;
+int len;
+	{
+	unsigned int tot,n,nw;
+	int i;
+
+	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 (n > SSL3_RT_MAX_PLAIN_LENGTH)
+			nw=SSL3_RT_MAX_PLAIN_LENGTH;
+		else
+			nw=n;
+
+		i=do_ssl3_write(s,type,&(buf[tot]),nw);
+		if (i <= 0)
+			{
+			s->s3->wnum=tot;
+			return(i);
+			}
+
+		if (type == SSL3_RT_HANDSHAKE)
+			ssl3_finish_mac(s,(unsigned char *)&(buf[tot]),i);
+
+		if (i == (int)n) return(tot+i);
+
+		n-=i;
+		tot+=i;
+		}
+	}
+
+static int do_ssl3_write(s,type,buf,len)
+SSL *s;
+int type;
+char *buf;
+unsigned int len;
+	{
+	unsigned char *p,*plen;
+	int i,mac_size,clear=0;
+	SSL3_RECORD *wr;
+	SSL3_BUFFER *wb;
+	SSL_SESSION *sess;
+
+	/* first check is there is a SSL3_RECORD still being written
+	 * out.  This will happen with non blocking IO */
+	if (s->s3->wbuf.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=ssl3_dispatch_alert(s);
+		if (i <= 0)
+			return(i);
+		/* if it went, fall through and send more stuff */
+		}
+
+	if (len <= 0) return(len);
+	
+	wr= &(s->s3->wrec);
+	wb= &(s->s3->wbuf);
+	sess=s->session;
+
+	if (	(sess == NULL) ||
+		(s->enc_write_ctx == NULL) ||
+		(s->write_hash == NULL))
+		clear=1;
+
+	if (clear)
+		mac_size=0;
+	else
+		mac_size=EVP_MD_size(s->write_hash);
+
+	p=wb->buf;
+
+	/* write the header */
+	*(p++)=type&0xff;
+	wr->type=type;
+
+	*(p++)=SSL3_VERSION_MAJOR;
+	*(p++)=SSL3_VERSION_MINOR;
+	
+	/* record 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 ((sess != NULL) && (sess->write_compression != NULL))
+		{
+		if (!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)
+		{
+		ssl3_mac(s,&(p[wr->length]),1);
+		wr->length+=mac_size;
+		wr->input=p;
+		wr->data=p;
+		}
+
+	/* ssl3_enc can only have an error on read */
+	ssl3_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;
+
+	/* Now lets setup wb */
+	wb->left=wr->length;
+	wb->offset=0;
+
+	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 */
+static int ssl3_write_pending(s,type,buf,len)
+SSL *s;
+int type;
+char *buf;
+unsigned int len;
+	{
+	int i;
+
+	if ((s->s3->wpend_tot != (int)len) || (s->s3->wpend_buf != buf)
+		|| (s->s3->wpend_type != type))
+		{
+		SSLerr(SSL_F_SSL3_WRITE_PENDING,SSL_R_BAD_WRITE_RETRY);
+		return(SSL_RWERR_BAD_WRITE_RETRY);
+		}
+
+	for (;;)
+		{
+		errno=0;
+		if (s->wbio != NULL)
+			{
+			s->rwstate=SSL_WRITING;
+			i=BIO_write(s->wbio,
+				(char *)&(s->s3->wbuf.buf[s->s3->wbuf.offset]),
+				(unsigned int)s->s3->wbuf.left);
+			}
+		else
+			{
+			SSLerr(SSL_F_SSL3_WRITE_PENDING,SSL_R_BIO_NOT_SET);
+			i= -1;
+			}
+		if (i == s->s3->wbuf.left)
+			{
+			s->s3->wbuf.left=0;
+			s->rwstate=SSL_NOTHING;
+			return(s->s3->wpend_ret);
+			}
+		else if (i <= 0)
+			return(i);
+		s->s3->wbuf.offset+=i;
+		s->s3->wbuf.left-=i;
+		}
+	}
+
+int ssl3_read_bytes(s,type,buf,len)
+SSL *s;
+int type;
+char *buf;
+int len;
+	{
+	int al,i,j,n,ret;
+	SSL3_RECORD *rr;
+	unsigned char *sender;
+	void (*cb)()=NULL;
+
+	if (s->s3->rbuf.buf == NULL) /* Not initalised yet */
+		if (!ssl3_setup_buffers(s))
+			return(-1);
+
+	if (!s->in_handshake && SSL_in_before(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);
+			}
+		}
+start:
+	s->rwstate=SSL_NOTHING;
+
+	/* s->s3->rrec.type	- is the type of record
+	 * s->s3->rrec.data, 	- data
+	 * s->s3->rrec.off, 	- ofset into 'data' for next read
+	 * s->s3->rrec.length,	- number of bytes. */
+	rr= &(s->s3->rrec);
+
+	/* get new packet */
+	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 && (rr->type != SSL3_RT_HANDSHAKE))
+		{
+		al=SSL3_AD_UNEXPECTED_MESSAGE;
+		SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_DATA_BETWEEN_CCS_AND_FINISHED);
+		goto err;
+		}
+
+	/* If the other end has shutdown, throw anything we read away */
+	if (s->shutdown & SSL_RECEIVED_SHUTDOWN)
+		{
+		rr->length=0;
+		s->rwstate=SSL_NOTHING;
+		return(0);
+		}
+
+	/* Check for an incoming 'Client Request' message */
+	if ((rr->type == SSL3_RT_HANDSHAKE) && (rr->length == 4) &&
+		(rr->data[0] == SSL3_MT_CLIENT_REQUEST) &&
+		(s->session != NULL) && (s->session->cipher != NULL))
+		{
+		if ((rr->data[1] != 0) || (rr->data[2] != 0) ||
+			(rr->data[3] != 0))
+			{
+			al=SSL3_AD_ILLEGAL_PARAMETER;
+			SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_CLIENT_REQUEST);
+			goto err;
+			}
+
+		if (SSL_is_init_finished(s) &&
+			!(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS))
+			{
+			ssl3_renegotiate(s);
+			n=s->handshake_func(s);
+			if (n < 0) return(n);
+			if (n == 0)
+				{
+				SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
+				return(-1);
+				}
+			}
+		rr->length=0;
+/* ZZZ */	goto start;
+		}
+
+	/* if it is not the type we want, or we have shutdown and want
+	 * the peer shutdown */
+	if ((rr->type != type) || (s->shutdown & SSL_SENT_SHUTDOWN))
+		{
+		if (rr->type == SSL3_RT_ALERT)
+			{
+			if ((rr->length != 2) || (rr->off != 0))
+				{
+				al=SSL3_AD_ILLEGAL_PARAMETER;
+				SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_ALERT_RECORD);
+				goto f_err;
+				}
+
+			i=rr->data[0];
+			n=rr->data[1];
+
+			/* clear from buffer */
+			rr->length=0;
+
+			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=(i<<8)|n;
+				cb(s,SSL_CB_READ_ALERT,j);
+				}
+
+			if (i == 1)
+				{
+				s->s3->warn_alert=n;
+				if (n == SSL3_AD_CLOSE_NOTIFY)
+					{
+					s->shutdown|=SSL_RECEIVED_SHUTDOWN;
+					return(0);
+					}
+				}
+			else if (i == 2)
+				{
+				s->rwstate=SSL_NOTHING;
+				s->s3->fatal_alert=n;
+				SSLerr(SSL_F_SSL3_READ_BYTES,1000+n);
+				s->shutdown|=SSL_RECEIVED_SHUTDOWN;
+				SSL_CTX_remove_session(s->ctx,s->session);
+				return(0);
+				}
+			else
+				{
+				al=SSL3_AD_ILLEGAL_PARAMETER;
+				SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNKNOWN_ALERT_TYPE);
+				goto f_err;
+				}
+
+			rr->length=0;
+			goto start;
+			}
+
+		if (s->shutdown & SSL_SENT_SHUTDOWN)
+			{
+			s->rwstate=SSL_NOTHING;
+			rr->length=0;
+			return(0);
+			}
+
+		if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC)
+			{
+			if (	(rr->length != 1) || (rr->off != 0) ||
+				(rr->data[0] != SSL3_MT_CCS))
+				{
+				i=SSL3_AD_ILLEGAL_PARAMETER;
+				SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC);
+				goto err;
+				}
+
+			rr->length=0;
+
+			s->s3->change_cipher_spec=1;
+
+			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)
+				{
+				s->session->cipher=s->s3->tmp.new_cipher;
+				if (!ssl3_setup_key_block(s))
+					goto err;
+				}
+
+			if (!ssl3_change_cipher_state(s,i))
+				goto err;
+
+			/* we have to record the message digest at
+			 * this point so we can get it before we read
+			 * the finished message */
+			sender=(s->state & SSL_ST_CONNECT)
+				?&(ssl3_server_finished_const[0])
+				:&(ssl3_client_finished_const[0]);
+
+			ssl3_final_finish_mac(s,&(s->s3->finish_dgst1),
+				sender,&(s->s3->tmp.finish_md1[0]));
+			ssl3_final_finish_mac(s,&(s->s3->finish_dgst2),
+				sender,&(s->s3->tmp.finish_md2[0]));
+
+			goto start;
+			}
+
+		/* else we have a handshake */
+		if ((rr->type == SSL3_RT_HANDSHAKE) &&
+			!s->in_handshake)
+			{
+			if (((s->state&SSL_ST_MASK) == SSL_ST_OK) &&
+				!(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS))
+				{
+				s->state=SSL_ST_BEFORE;
+				s->new_session=1;
+				}
+			n=s->handshake_func(s);
+			if (n < 0) return(n);
+			if (n == 0)
+				{
+				SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
+				return(-1);
+				}
+			goto start;
+			}
+
+		al=SSL3_AD_UNEXPECTED_MESSAGE;
+		SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
+		goto f_err;
+		}
+
+	/* 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=SSL3_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=len;
+
+	memcpy(buf,&(rr->data[rr->off]),(unsigned int)n);
+	rr->length-=n;
+	rr->off+=n;
+	if (rr->length <= 0)
+		s->rstate=SSL_ST_READ_HEADER;
+
+	if (type == SSL3_RT_HANDSHAKE)
+		ssl3_finish_mac(s,(unsigned char *)buf,n);
+	return(n);
+f_err:
+	ssl3_send_alert(s,SSL3_AL_FATAL,al);
+err:
+	return(-1);
+	}
+
+int ssl3_do_write(s,type)
+SSL *s;
+int type;
+	{
+	int ret;
+
+	ret=ssl3_write_bytes(s,type,(char *)
+		&(s->init_buf->data[s->init_off]),s->init_num);
+	if (ret == s->init_num)
+		return(1);
+	if (ret < 0) return(-1);
+	s->init_off+=ret;
+	s->init_num-=ret;
+	return(0);
+	}
+
+void ssl3_send_alert(s,level,desc)
+SSL *s;
+int level;
+int desc;
+	{
+	/* 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 */
+		ssl3_dispatch_alert(s);
+	/* else data is still being written out, we will get written
+	 * some time in the future */
+	}
+
+int ssl3_dispatch_alert(s)
+SSL *s;
+	{
+	int i,j;
+	void (*cb)()=NULL;
+
+	s->s3->alert_dispatch=0;
+	i=do_ssl3_write(s,SSL3_RT_ALERT,&(s->s3->send_alert[0]),2);
+	if (i <= 0)
+		{
+		s->s3->alert_dispatch=1;
+		}
+	else
+		{
+		/* If it is important, send 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)
+			BIO_flush(s->wbio);
+
+		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/ssl/s3_srvr.c b/ssl/s3_srvr.c
new file mode 100644
index 0000000..ebff575
--- /dev/null
+++ b/ssl/s3_srvr.c
@@ -0,0 +1,1629 @@
+/* ssl/s3_srvr.c */
+/* Copyright (C) 1995-1997 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.]
+ */
+
+#define REUSE_CIPHER_BUG
+
+#include <stdio.h>
+#include "buffer.h"
+#include "rand.h"
+#include "objects.h"
+#include "evp.h"
+#include "x509.h"
+#include "ssl_locl.h"
+
+#define BREAK	break
+/* SSLerr(SSL_F_SSL3_ACCEPT,ERR_R_MALLOC_FAILURE);
+ * SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,ERR_R_MALLOC_FAILURE);
+ * SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
+ * SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,ERR_R_MALLOC_FAILURE);
+ * SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_MALLOC_FAILURE);
+ */
+
+#ifndef NOPROTO
+static int ssl3_get_client_hello(SSL *s);
+static int ssl3_send_server_hello(SSL *s);
+static int ssl3_send_server_key_exchange(SSL *s);
+static int ssl3_send_certificate_request(SSL *s);
+static int ssl3_send_server_done(SSL *s);
+static int ssl3_get_cert_verify(SSL *s);
+static int ssl3_get_client_key_exchange(SSL *s);
+static int ssl3_get_client_certificate(SSL *s);
+static int ssl3_send_hello_request(SSL *s);
+
+#else
+
+static int ssl3_get_client_hello();
+static int ssl3_send_server_hello();
+static int ssl3_send_server_key_exchange();
+static int ssl3_send_certificate_request();
+static int ssl3_send_server_done();
+static int ssl3_get_cert_verify();
+static int ssl3_get_client_key_exchange();
+static int ssl3_get_client_certificate();
+static int ssl3_send_hello_request();
+static SSL_METHOD *ssl3_get_server_method();
+
+#endif
+
+static SSL_METHOD *ssl3_get_server_method(ver)
+int ver;
+	{
+	if (ver == 3)
+		return(SSLv3_server_method());
+	else
+		return(NULL);
+	}
+
+SSL_METHOD *SSLv3_server_method()
+	{
+	static int init=1;
+	static SSL_METHOD SSLv3_server_data;
+
+	if (init)
+		{
+		init=0;
+		memcpy((char *)&SSLv3_server_data,(char *)sslv3_base_method(),
+			sizeof(SSL_METHOD));
+		SSLv3_server_data.ssl_accept=ssl3_accept;
+		SSLv3_server_data.get_ssl_method=ssl3_get_server_method;
+		}
+	return(&SSLv3_server_data);
+	}
+
+int ssl3_accept(s)
+SSL *s;
+	{
+	BUF_MEM *buf;
+	unsigned long l,Time=time(NULL);
+	void (*cb)()=NULL;
+	long num1;
+	int ret= -1;
+	CERT *ct;
+	BIO *bbio,*under;
+	int new_state,state,skip=0;
+
+	RAND_seed((unsigned char *)&Time,sizeof(Time));
+	ERR_clear_error();
+	errno=0;
+
+	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 */
+	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);
+	s->in_handshake++;
+
+#ifdef undef
+	/* FIX THIS EAY EAY EAY */
+	/* we don't actually need a cert, we just need a cert or a DH_tmp */
+	if (((s->session == NULL) || (s->session->cert == NULL)) &&
+		(s->cert == NULL))
+		{
+		SSLerr(SSL_F_SSL3_ACCEPT,SSL_R_NO_CERTIFICATE_SET);
+		ret= -1;
+		goto end;
+		}
+#endif
+
+	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:
+
+			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
+
+			s->version=3;
+			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;
+				}
+
+			/* Ok, we now need to push on a buffering BIO so that
+			 * the output is sent in a way that TCP likes :-)
+			 */
+			if (s->bbio == NULL)
+				{
+				bbio=BIO_new(BIO_f_buffer());
+				if (bbio == NULL)
+					{
+					SSLerr(SSL_F_SSL3_ACCEPT,ERR_LIB_BUF);
+					ret= -1;
+					goto end;
+					}
+				s->bbio=bbio;
+				}
+			else
+				bbio=s->bbio;
+			BIO_reset(bbio);
+			if (!BIO_set_write_buffer_size(bbio,16*1024))
+				{
+				SSLerr(SSL_F_SSL3_ACCEPT,ERR_LIB_BUF);
+				ret= -1;
+				goto end;
+				}
+
+			s->wbio=BIO_push(bbio,s->wbio);
+
+			s->ctx->sess_accept++;
+			s->init_num=0;
+
+			if (s->state != SSL_ST_RENEGOTIATE)
+				{
+				s->state=SSL3_ST_SR_CLNT_HELLO_A;
+				ssl3_init_finished_mac(s);
+				}
+			else
+				{
+				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:
+			/* remove buffering on output */
+			under=BIO_pop(s->wbio);
+			if (under != NULL)
+				s->wbio=under;
+			else
+				abort(); /* ok */
+			BIO_free(s->bbio);
+			s->bbio=NULL;
+
+			s->state=SSL_ST_OK;
+			ret=1;
+			goto end;
+			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->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;
+
+			if (s->hit)
+				s->state=SSL3_ST_SW_CHANGE_A;
+			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 */
+			if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL))
+				{
+				ret=ssl3_send_server_certificate(s);
+				if (ret <= 0) goto end;
+				}
+			else
+				skip=1;
+			s->state=SSL3_ST_SW_KEY_EXCH_A;
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_SW_KEY_EXCH_A:
+		case SSL3_ST_SW_KEY_EXCH_B:
+			l=s->s3->tmp.new_cipher->algorithms;
+			if (s->session->cert == NULL)
+				{
+				if (s->cert != NULL)
+					{
+					CRYPTO_add(&s->cert->references,1,CRYPTO_LOCK_SSL_CERT);
+					s->session->cert=s->cert;
+					}
+				else
+					{
+					CRYPTO_add(&s->ctx->default_cert->references,1,CRYPTO_LOCK_SSL_CERT);
+					s->session->cert=s->ctx->default_cert;
+					}
+				}
+			ct=s->session->cert;
+
+			/* clear this, it may get reset by
+			 * send_server_key_exchange */
+			if (s->ctx->options & SSL_OP_EPHEMERAL_RSA)
+				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 */
+			if ( s->s3->tmp.use_rsa_tmp ||
+			    (l & (SSL_DH|SSL_kFZA)) ||
+			    ((l & SSL_kRSA) &&
+			     ((ct->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL)||
+			      ((l & SSL_EXPORT) &&
+			       (EVP_PKEY_size(ct->pkeys[SSL_PKEY_RSA_ENC].privatekey)*8 > 512)
+			      )
+			     )
+			    )
+			   )
+				{
+				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 (!(s->verify_mode & SSL_VERIFY_PEER) ||
+				((s->session->peer != NULL) &&
+				 (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)))
+				{
+				/* no cert request */
+				skip=1;
+				s->state=SSL3_ST_SW_SRVR_DONE_A;
+				}
+			else
+				{
+				ret=ssl3_send_certificate_request(s);
+				if (ret <= 0) goto end;
+				s->state=SSL3_ST_SW_SRVR_DONE_A;
+				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:
+			/* number of bytes to be flushed */
+			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;
+				}
+
+			s->state=s->s3->tmp.next_state;
+			break;
+
+		case SSL3_ST_SR_CERT_A:
+		case SSL3_ST_SR_CERT_B:
+			/* 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;
+			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;
+			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 */ 
+			ssl3_final_finish_mac(s,&(s->s3->finish_dgst1),
+				NULL,&(s->s3->tmp.finish_md1[0]));
+			ssl3_final_finish_mac(s,&(s->s3->finish_dgst2),
+				NULL,&(s->s3->tmp.finish_md2[0]));
+
+			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,
+				&(ssl3_client_finished_const[0]));
+			if (ret <= 0) goto end;
+			if (s->hit)
+				s->state=SSL_ST_OK;
+			else
+				s->state=SSL3_ST_SW_CHANGE_A;
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_SW_CHANGE_A:
+		case SSL3_ST_SW_CHANGE_B:
+
+			s->session->cipher=s->s3->tmp.new_cipher;
+			if (!ssl3_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 (!ssl3_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,
+				&(ssl3_server_finished_const[0]));
+			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 */
+			under=BIO_pop(s->wbio);
+			if (under != NULL)
+				s->wbio=under;
+			else
+				abort(); /* ok */
+			BIO_free(s->bbio);
+			s->bbio=NULL;
+
+			s->new_session=0;
+			s->init_num=0;
+
+			ssl_update_cache(s,SSL_SESS_CACHE_SERVER);
+
+			s->ctx->sess_accept_good++;
+			/* s->server=1; */
+			s->handshake_func=ssl3_accept;
+			ret=1;
+
+			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,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) BIO_flush(s->wbio);
+
+			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); */
+
+	if (cb != NULL)
+		cb(s,SSL_CB_ACCEPT_EXIT,ret);
+	s->in_handshake--;
+	return(ret);
+	}
+
+static int ssl3_send_hello_request(s)
+SSL *s;
+	{
+	unsigned char *p;
+
+	if (s->state == SSL3_ST_SW_HELLO_REQ_A)
+		{
+		p=(unsigned char *)s->init_buf->data;
+		*(p++)=SSL3_MT_CLIENT_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));
+	}
+
+static int ssl3_get_client_hello(s)
+SSL *s;
+	{
+	int i,j,ok,al,ret= -1;
+	long n;
+	unsigned long id;
+	unsigned char *p,*d;
+	SSL_CIPHER *c;
+	STACK *ciphers=NULL;
+
+	if (s->state == SSL3_ST_SR_CLNT_HELLO_A)
+		{
+		s->first_packet=1;
+		s->state=SSL3_ST_SR_CLNT_HELLO_B;
+		}
+	n=ssl3_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);
+	d=p=(unsigned char *)s->init_buf->data;
+
+	if (p[0] != SSL3_VERSION_MAJOR)
+		{
+		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_WRONG_SSL_VERSION);
+		goto err;
+		}
+	p+=2;
+
+	/* 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;
+	if (j == 0)
+		{
+		if (!ssl_get_new_session(s,1))
+			goto err;
+		}
+	else
+		{
+		i=ssl_get_prev_session(s,j,p);
+		if (i == 1)
+			{ /* previous session */
+			s->hit=1;
+			}
+		else
+			{
+			if (!ssl_get_new_session(s,1))
+				goto err;
+			}
+		}
+
+	p+=j;
+	n2s(p,i);
+	if ((i == 0) && (j != 0))
+		{
+		/* we need a cipher if we are not resuming a session */
+		al=SSL3_AD_ILLEGAL_PARAMETER;
+		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_CIPHERS_SPECIFIED);
+		goto f_err;
+		}
+	if ((i+p) > (d+n))
+		{
+		/* not enough data */
+		al=SSL3_AD_ILLEGAL_PARAMETER;
+		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;
+
+		for (i=0; i<sk_num(ciphers); i++)
+			{
+			c=(SSL_CIPHER *)sk_value(ciphers,i);
+			if (c->id == id)
+				{
+				j=1;
+				break;
+				}
+			}
+		if (j == 0)
+			{
+			if ((s->ctx->options & SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) && (sk_num(ciphers) == 1))
+				{
+				/* Very bad for multi-threading.... */
+				s->session->cipher=
+					(SSL_CIPHER *)sk_value(ciphers,0);
+				}
+			else
+				{
+				/* we need to have the cipher in the cipher
+				 * list if we are asked to reuse it */
+				al=SSL3_AD_ILLEGAL_PARAMETER;
+				SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_REQUIRED_CIPHER_MISSING);
+				goto f_err;
+				}
+			}
+		}
+
+	/* compression */
+	i= *(p++);
+	for (j=0; j<i; j++)
+		if (p[j] == 0) break;
+
+	p+=i;
+	if (j >= i)
+		{
+		/* no compress */
+		al=SSL3_AD_ILLEGAL_PARAMETER;
+		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_COMPRESSION_SPECIFIED);
+		goto f_err;
+		}
+
+	if (p > (d+n))
+		{
+		/* wrong number of bytes,
+		 * there could be more to follow */
+		al=SSL3_AD_ILLEGAL_PARAMETER;
+		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_LENGTH_MISMATCH);
+		goto f_err;
+		}
+
+	/* do nothing with compression */
+
+	/* Given s->session->ciphers and ssl_get_ciphers_by_id(s), we must
+	 * pick a cipher */
+
+	if (!s->hit)
+		{
+		if (s->session->ciphers != NULL)
+			sk_free(s->session->ciphers);
+		s->session->ciphers=ciphers;
+		if (ciphers == NULL)
+			{
+			al=SSL3_AD_HANDSHAKE_FAILURE;
+			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_by_id(s));
+
+		if (c == NULL)
+			{
+			al=SSL3_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 *sk;
+		SSL_CIPHER *nc=NULL;
+		SSL_CIPHER *ec=NULL;
+
+		if (s->ctx->options & SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG)
+			{
+			sk=s->session->ciphers;
+			for (i=0; i<sk_num(sk); i++)
+				{
+				c=(SSL_CIPHER *)sk_value(sk,i);
+				if (c->algorithms & SSL_eNULL)
+					nc=c;
+				if (c->algorithms & SSL_EXP)
+					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;
+		}
+	
+	/* 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		- sesson reuse flag
+	 * s->tmp.new_cipher	- the new cipher to use.
+	 */
+
+	ret=1;
+	if (0)
+		{
+f_err:
+		ssl3_send_alert(s,SSL3_AL_FATAL,al);
+		}
+err:
+	if (ciphers != NULL) sk_free(ciphers);
+	return(ret);
+	}
+
+static int ssl3_send_server_hello(s)
+SSL *s;
+	{
+	unsigned char *buf;
+	unsigned char *p,*d;
+	int i,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=time(NULL);			/* Time */
+		l2n(Time,p);
+		RAND_bytes(p,SSL3_RANDOM_SIZE-sizeof(Time));
+		/* Do the message type and length last */
+		d=p= &(buf[4]);
+
+		*(p++)=SSL3_VERSION_MAJOR;
+		*(p++)=SSL3_VERSION_MINOR;
+
+		/* 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
+		 */
+
+		sl=s->session->session_id_length;
+		*(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 */
+		*(p++)=0;
+
+		/* do the header */
+		l=(p-d);
+		d=buf;
+		*(d++)=SSL3_MT_SERVER_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));
+	}
+
+static int ssl3_send_server_done(s)
+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_CW_CLNT_HELLO_B */
+	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+	}
+
+static int ssl3_send_server_key_exchange(s)
+SSL *s;
+	{
+#ifndef NO_RSA
+	unsigned char *q;
+	int j,num;
+	RSA *rsa;
+	unsigned char md_buf[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH];
+#endif
+#ifndef NO_DH
+	DH *dh,*dhp;
+#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;
+
+	if (s->state == SSL3_ST_SW_KEY_EXCH_A)
+		{
+		type=s->s3->tmp.new_cipher->algorithms & SSL_MKEY_MASK;
+		cert=s->session->cert;
+
+		buf=s->init_buf;
+
+		r[0]=r[1]=r[2]=r[3]=NULL;
+		n=0;
+#ifndef NO_RSA
+		if (type & SSL_kRSA)
+			{
+			rsa=cert->rsa_tmp;
+			if ((rsa == NULL) && (s->ctx->default_cert->rsa_tmp_cb != NULL))
+				{
+				rsa=s->ctx->default_cert->rsa_tmp_cb(s,
+					(s->s3->tmp.new_cipher->algorithms|
+					SSL_NOT_EXP)?0:1);
+				CRYPTO_add(&rsa->references,1,CRYPTO_LOCK_RSA);
+				cert->rsa_tmp=rsa;
+				}
+			if (rsa == NULL)
+				{
+				al=SSL3_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 NO_DH
+			if (type & SSL_kEDH)
+			{
+			dhp=cert->dh_tmp;
+			if ((dhp == NULL) && (cert->dh_tmp_cb != NULL))
+				dhp=cert->dh_tmp_cb(s,
+					(s->s3->tmp.new_cipher->algorithms|
+					SSL_NOT_EXP)?0:1);
+			if (dhp == NULL)
+				{
+				al=SSL3_AD_HANDSHAKE_FAILURE;
+				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_DH_KEY);
+				goto f_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->ctx->options & SSL_OP_SINGLE_DH_USE)) &&
+			    (!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
+			{
+			al=SSL3_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->algorithms & SSL_aNULL))
+			{
+			if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher))
+				== NULL)
+				{
+				al=SSL3_AD_HANDSHAKE_FAILURE;
+				goto f_err;
+				}
+			kn=EVP_PKEY_size(pkey);
+			}
+		else
+			{
+			pkey=NULL;
+			kn=0;
+			}
+
+		if (!BUF_MEM_grow(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];
+			}
+
+		/* 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 NO_RSA
+			if (pkey->type == EVP_PKEY_RSA)
+				{
+				q=md_buf;
+				j=0;
+				for (num=2; num > 0; num--)
+					{
+					EVP_DigestInit(&md_ctx,(num == 2)?EVP_md5():EVP_sha1());
+					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(&md_ctx,q,
+						(unsigned int *)&i);
+					q+=i;
+					j+=i;
+					}
+				i=RSA_private_encrypt(j,md_buf,&(p[2]),
+					pkey->pkey.rsa,RSA_PKCS1_PADDING);
+				if (i <= 0)
+					{
+					SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_RSA);
+					goto err;
+					}
+				s2n(i,p);
+				n+=i+2;
+				}
+			else
+#endif
+#if !defined(NO_DSA)
+				if (pkey->type == EVP_PKEY_DSA)
+				{
+				/* lets do DSS */
+				EVP_SignInit(&md_ctx,EVP_dss1());
+				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
+				{
+				/* Is this error check actually needed? */
+				al=SSL3_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;
+		}
+
+	/* SSL3_ST_SW_KEY_EXCH_B */
+	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+f_err:
+	ssl3_send_alert(s,SSL3_AL_FATAL,al);
+err:
+	return(-1);
+	}
+
+static int ssl3_send_certificate_request(s)
+SSL *s;
+	{
+	unsigned char *p,*d;
+	int i,j,nl,off,n;
+	STACK *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_num(sk); i++)
+				{
+				name=(X509_NAME *)sk_value(sk,i);
+				j=i2d_X509_NAME(name,NULL);
+				if (!BUF_MEM_grow(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->ctx->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;
+		}
+
+	/* SSL3_ST_SW_CERT_REQ_B */
+	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+err:
+	return(-1);
+	}
+
+static int ssl3_get_client_key_exchange(s)
+SSL *s;
+	{
+	int i,al,ok;
+	long n;
+	unsigned long l;
+	unsigned char *p;
+	RSA *rsa=NULL;
+	BIGNUM *pub=NULL;
+	EVP_PKEY *pkey=NULL;
+	DH *dh_srvr;
+
+	n=ssl3_get_message(s,
+		SSL3_ST_SR_KEY_EXCH_A,
+		SSL3_ST_SR_KEY_EXCH_B,
+		SSL3_MT_CLIENT_KEY_EXCHANGE,
+		400, /* ???? */
+		&ok);
+
+	if (!ok) return((int)n);
+	p=(unsigned char *)s->init_buf->data;
+
+	l=s->s3->tmp.new_cipher->algorithms;
+
+#ifndef NO_RSA
+	if (l & SSL_kRSA)
+		{
+		/* FIX THIS UP EAY EAY EAY EAY */
+		if (s->s3->tmp.use_rsa_tmp)
+			{
+			if ((s->session->cert != NULL) &&
+				(s->session->cert->rsa_tmp != NULL))
+				rsa=s->session->cert->rsa_tmp;
+			else if ((s->ctx->default_cert != NULL) &&
+				(s->ctx->default_cert->rsa_tmp != NULL))
+				rsa=s->ctx->default_cert->rsa_tmp;
+			/* Don't do a callback because rsa_tmp should
+			 * be sent already */
+			if (rsa == NULL)
+				{
+				al=SSL3_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=SSL3_AD_HANDSHAKE_FAILURE;
+				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_RSA_CERTIFICATE);
+				goto f_err;
+				}
+			rsa=pkey->pkey.rsa;
+			}
+
+		i=RSA_private_decrypt((int)n,p,p,rsa,RSA_PKCS1_PADDING);
+#if 1
+		/* If a bad decrypt, use a dud master key */
+		if ((i != SSL_MAX_MASTER_KEY_LENGTH) ||
+			(p[0] != 3) ||
+			 (p[1] != 0))
+			{
+			p[0]=3;
+			p[1]=0;
+			RAND_bytes(&(p[2]),SSL_MAX_MASTER_KEY_LENGTH-2);
+			i=SSL_MAX_MASTER_KEY_LENGTH;
+			}
+#else
+		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);
+			goto f_err;
+			}
+
+		if ((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);
+			goto f_err;
+			}
+#endif
+
+		s->session->master_key_length=
+			ssl3_generate_master_secret(s,
+				s->session->master_key,
+				p,i);
+		memset(p,0,i);
+		}
+	else
+#endif
+#ifndef NO_DH
+		if (l & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
+		{
+
+		n2s(p,i);
+		if (n != i+2)
+			{
+			if (!(s->ctx->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=SSL3_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=SSL3_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=
+			ssl3_generate_master_secret(s,
+				s->session->master_key,p,i);
+		}
+	else
+#endif
+		{
+		al=SSL3_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);
+err:
+	return(-1);
+	}
+
+static int ssl3_get_cert_verify(s)
+SSL *s;
+	{
+	EVP_PKEY *pkey=NULL;
+	unsigned char *p;
+	int al,ok,ret=0;
+	long n;
+	int type=0,i,j;
+	X509 *peer;
+
+	n=ssl3_get_message(s,
+		SSL3_ST_SR_CERT_VRFY_A,
+		SSL3_ST_SR_CERT_VRFY_B,
+		-1,
+		512, /* 512? */
+		&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))
+			{
+			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_MISSING_VERIFY_MESSAGE);
+			al=SSL3_AD_UNEXPECTED_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=SSL3_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=SSL3_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=SSL3_AD_UNEXPECTED_MESSAGE;
+		goto f_err;
+		}
+
+	/* we now have a signature that we need to verify */
+	p=(unsigned char *)s->init_buf->data;
+	n2s(p,i);
+	n-=2;
+	if (i > n)
+		{
+		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_LENGTH_MISMATCH);
+		al=SSL3_AD_ILLEGAL_PARAMETER;
+		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=SSL3_AD_ILLEGAL_PARAMETER;
+		goto f_err;
+		}
+
+#ifndef NO_RSA 
+	if (pkey->type == EVP_PKEY_RSA)
+		{
+		i=RSA_public_decrypt(i,p,p,pkey->pkey.rsa,RSA_PKCS1_PADDING);
+		if (i < 0)
+			{
+			al=SSL3_AD_ILLEGAL_PARAMETER;
+			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_RSA_DECRYPT);
+			goto f_err;
+			}
+		if ((i != (MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH)) ||
+			memcmp(&(s->s3->tmp.finish_md1[0]),
+				p,MD5_DIGEST_LENGTH) ||
+			memcmp(&(s->s3->tmp.finish_md2[0]),
+				&(p[MD5_DIGEST_LENGTH]),SHA_DIGEST_LENGTH))
+			{
+			al=SSL3_AD_ILLEGAL_PARAMETER;
+			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_RSA_SIGNATURE);
+			goto f_err;
+			}
+		}
+	else
+#endif
+#ifndef NO_DSA
+		if (pkey->type == EVP_PKEY_DSA)
+		{
+		j=DSA_verify(pkey->save_type,s->s3->tmp.finish_md2,
+			SHA_DIGEST_LENGTH,p,i,pkey->pkey.dsa);
+		if (j <= 0)
+			{
+			/* bad signature */
+			al=SSL3_AD_ILLEGAL_PARAMETER;
+			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_DSA_SIGNATURE);
+			goto f_err;
+			}
+		}
+	else
+#endif
+		{
+		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_INTERNAL_ERROR);
+		al=SSL3_AD_UNSUPPORTED_CERTIFICATE;
+		goto f_err;
+		}
+
+
+	ret=1;
+	if (0)
+		{
+f_err:
+		ssl3_send_alert(s,SSL3_AL_FATAL,al);
+		}
+end:
+	return(ret);
+	}
+
+static int ssl3_get_client_certificate(s)
+SSL *s;
+	{
+	int i,ok,al,ret= -1;
+	X509 *x=NULL;
+	unsigned long l,nc,llen,n;
+	unsigned char *p,*d,*q;
+	STACK *sk=NULL;
+
+	n=ssl3_get_message(s,
+		SSL3_ST_SR_CERT_A,
+		SSL3_ST_SR_CERT_B,
+		-1,
+#if defined(MSDOS) && !defined(WIN32)
+		1024*30, /* 30k max cert list :-) */
+#else
+		1024*100, /* 100k max cert list :-) */
+#endif
+		&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=SSL3_AD_NO_CERTIFICATE;
+			goto f_err;
+			}
+		s->s3->tmp.reuse_message=1;
+		return(1);
+		}
+
+	if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE)
+		{
+		al=SSL3_AD_UNEXPECTED_MESSAGE;
+		SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_WRONG_MESSAGE_TYPE);
+		goto f_err;
+		}
+	d=p=(unsigned char *)s->init_buf->data;
+
+	if ((sk=sk_new_null()) == NULL)
+		{
+		SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_MALLOC_FAILURE);
+		goto err;
+		}
+
+	n2l3(p,llen);
+	if (llen+3 != n)
+		{
+		al=SSL3_AD_ILLEGAL_PARAMETER;
+		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=SSL3_AD_ILLEGAL_PARAMETER;
+			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=SSL3_AD_ILLEGAL_PARAMETER;
+			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH);
+			goto f_err;
+			}
+		if (!sk_push(sk,(char *)x))
+			{
+			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+		x=NULL;
+		nc+=l+3;
+		}
+
+	if (sk_num(sk) <= 0)
+		{
+		al=SSL3_AD_ILLEGAL_PARAMETER;
+		SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_NO_CERTIFICATES_PASSED);
+		goto f_err;
+		}
+	i=ssl_verify_cert_chain(s,sk);
+	if (!i)
+		{
+		al=ssl_verify_alarm_type(s->verify_result);
+		SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_NO_CERTIFICATE_RETURNED);
+		goto f_err;
+		}
+
+	/* This should not be needed */
+	if (s->session->peer != NULL)
+		X509_free(s->session->peer);
+	
+	s->session->peer=(X509 *)sk_shift(sk);
+
+	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_pop_free(sk,X509_free);
+	return(ret);
+	}
+
+int ssl3_send_server_certificate(s)
+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)
+			{
+			SSLerr(SSL_F_SSL3_SEND_SERVER_CERTIFICATE,SSL_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));
+	}
diff --git a/ssl/ssl.c b/ssl/ssl.c
new file mode 100644
index 0000000..fcc29b0
--- /dev/null
+++ b/ssl/ssl.c
@@ -0,0 +1,162 @@
+/* ssl/ssl.c */
+/* Copyright (C) 1995-1997 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>
+
+#define USE_SOCKETS
+#include "../e_os.h"
+
+#include "buffer.h"
+#include "stack.h"
+#include "lhash.h"
+
+#include "bio.h"
+#include "err.h"
+
+#include "bn.h"
+
+#include "rand.h"
+#include "conf.h"
+#include "txt_db.h"
+
+#include "err.h"
+#include "evp.h"
+
+#include "x509.h"
+#include "pkcs7.h"
+#include "pem.h"
+#include "asn1.h"
+#include "objects.h"
+
+#include "ssl_locl.h"
+
+#if !(BUILD_SSLV23) && !defined(BUILD_SSLV2) && !defined(BUILD_SSLV3) && !defined(BUILD_SSL_COMMON) && !defined(BUILD_SSL_BIO) && !defined(BUILD_SSL_OPTIONAL)
+#define BUILD_SSLV23
+#define BUILD_SSLV2
+#define BUILD_SSLV3
+#define BUILD_SSL_COMMON
+#define BUILD_SSL_BIO
+#define BUILD_SSL_OPTIONAL
+#endif
+
+#ifdef NO_RSA
+#undef BUILD_SSLV2
+#undef BUILD_SSLV23
+#endif
+
+#ifdef NO_SSL2
+#undef BUILD_SSLV2
+#undef BUILD_SSLV23
+#endif
+
+#ifdef NO_SSL3
+#undef BUILD_SSL3
+#undef BUILD_SSLV23
+#endif
+
+#ifdef BUILD_SSLV23
+#include "s23_clnt.c"
+#include "s23_srvr.c"
+#include "s23_pkt.c"
+#include "s23_lib.c"
+#include "s23_meth.c"
+#endif
+
+#ifdef BUILD_SSLV2
+#include "s2_clnt.c"
+#include "s2_srvr.c"
+#include "s2_pkt.c"
+#include "s2_enc.c"
+#include "s2_lib.c"
+#include "s2_meth.c"
+#endif
+
+#ifdef BUILD_SSLV3
+#include "s3_clnt.c"
+#include "s3_both.c"
+#include "s3_srvr.c"
+#include "s3_pkt.c"
+#include "s3_enc.c"
+#include "s3_lib.c"
+#include "s3_meth.c"
+#endif
+
+#ifdef BUILD_SSL_COMMON
+#include "ssl_lib.c"
+#include "ssl_algs.c"
+#include "ssl_cert.c"
+#include "ssl_ciph.c"
+#include "ssl_sess.c"
+#include "ssl_rsa.c"
+#endif
+
+/* Extra things */
+#ifdef BUILD_SSL_BIO
+#include "bio_ssl.c"
+#endif
+
+#ifdef BUILD_SSL_OPTIONAL
+#include "ssl_asn1.c"
+#include "ssl_txt.c"
+#include "ssl_stat.c"
+#include "ssl_err.c"
+#include "ssl_err2.c"
+#endif
+
diff --git a/ssl/ssl.err b/ssl/ssl.err
new file mode 100644
index 0000000..f3bc5d3
--- /dev/null
+++ b/ssl/ssl.err
@@ -0,0 +1,272 @@
+/* Error codes for the SSL functions. */
+
+/* Function codes. */
+#define SSL_F_CLIENT_CERTIFICATE			 100
+#define SSL_F_CLIENT_HELLO				 101
+#define SSL_F_CLIENT_MASTER_KEY				 102
+#define SSL_F_D2I_SSL_SESSION				 103
+#define SSL_F_DO_SSL3_WRITE				 104
+#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_HELLO				 114
+#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_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_READ					 125
+#define SSL_F_SSL2_SET_CERTIFICATE			 126
+#define SSL_F_SSL2_WRITE				 127
+#define SSL_F_SSL3_ACCEPT				 128
+#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_CTX_CTRL				 133
+#define SSL_F_SSL3_ENC					 134
+#define SSL_F_SSL3_GET_CERTIFICATE_REQUEST		 135
+#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_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_OUTPUT_CERT_CHAIN			 147
+#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_KEY_EXCHANGE		 155
+#define SSL_F_SSL3_SETUP_BUFFERS			 156
+#define SSL_F_SSL3_SETUP_KEY_BLOCK			 157
+#define SSL_F_SSL3_WRITE_BYTES				 158
+#define SSL_F_SSL3_WRITE_PENDING			 159
+#define SSL_F_SSL_BAD_METHOD				 160
+#define SSL_F_SSL_BYTES_TO_CIPHER_LIST			 161
+#define SSL_F_SSL_CERT_NEW				 162
+#define SSL_F_SSL_CHECK_PRIVATE_KEY			 163
+#define SSL_F_SSL_CREATE_CIPHER_LIST			 164
+#define SSL_F_SSL_CTX_CHECK_PRIVATE_KEY			 165
+#define SSL_F_SSL_CTX_NEW				 166
+#define SSL_F_SSL_CTX_SET_SSL_VERSION			 167
+#define SSL_F_SSL_CTX_USE_CERTIFICATE			 168
+#define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1		 169
+#define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE		 170
+#define SSL_F_SSL_CTX_USE_PRIVATEKEY			 171
+#define SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1		 172
+#define SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE		 173
+#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY			 174
+#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1		 175
+#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE		 176
+#define SSL_F_SSL_DO_HANDSHAKE				 177
+#define SSL_F_SSL_GET_NEW_SESSION			 178
+#define SSL_F_SSL_GET_SERVER_SEND_CERT			 179
+#define SSL_F_SSL_GET_SIGN_PKEY				 180
+#define SSL_F_SSL_LOAD_CLIENT_CA_FILE			 181
+#define SSL_F_SSL_NEW					 182
+#define SSL_F_SSL_RSA_PRIVATE_DECRYPT			 183
+#define SSL_F_SSL_RSA_PUBLIC_ENCRYPT			 184
+#define SSL_F_SSL_SESSION_NEW				 185
+#define SSL_F_SSL_SESSION_PRINT_FP			 186
+#define SSL_F_SSL_SET_FD				 187
+#define SSL_F_SSL_SET_PKEY				 188
+#define SSL_F_SSL_SET_RFD				 189
+#define SSL_F_SSL_SET_SESSION				 190
+#define SSL_F_SSL_SET_WFD				 191
+#define SSL_F_SSL_UNDEFINED_FUNCTION			 192
+#define SSL_F_SSL_USE_CERTIFICATE			 193
+#define SSL_F_SSL_USE_CERTIFICATE_ASN1			 194
+#define SSL_F_SSL_USE_CERTIFICATE_FILE			 195
+#define SSL_F_SSL_USE_PRIVATEKEY			 196
+#define SSL_F_SSL_USE_PRIVATEKEY_ASN1			 197
+#define SSL_F_SSL_USE_PRIVATEKEY_FILE			 198
+#define SSL_F_SSL_USE_RSAPRIVATEKEY			 199
+#define SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1		 200
+#define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE		 201
+#define SSL_F_SSL_WRITE					 202
+#define SSL_F_WRITE_PENDING				 203
+
+/* Reason codes. */
+#define SSL_R_APP_DATA_IN_HANDSHAKE			 100
+#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_CLIENT_REQUEST			 105
+#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_MAC_DECODE				 113
+#define SSL_R_BAD_MESSAGE_TYPE				 114
+#define SSL_R_BAD_PACKET_LENGTH				 115
+#define SSL_R_BAD_RESPONSE_ARGUMENT			 116
+#define SSL_R_BAD_RSA_DECRYPT				 117
+#define SSL_R_BAD_RSA_ENCRYPT				 118
+#define SSL_R_BAD_RSA_E_LENGTH				 119
+#define SSL_R_BAD_RSA_MODULUS_LENGTH			 120
+#define SSL_R_BAD_RSA_SIGNATURE				 121
+#define SSL_R_BAD_SIGNATURE				 122
+#define SSL_R_BAD_SSL_FILETYPE				 123
+#define SSL_R_BAD_SSL_SESSION_ID_LENGTH			 124
+#define SSL_R_BAD_STATE					 125
+#define SSL_R_BAD_WRITE_RETRY				 126
+#define SSL_R_BIO_NOT_SET				 127
+#define SSL_R_BLOCK_CIPHER_PAD_IS_WRONG			 128
+#define SSL_R_BN_LIB					 129
+#define SSL_R_CA_DN_LENGTH_MISMATCH			 130
+#define SSL_R_CA_DN_TOO_LONG				 131
+#define SSL_R_CCS_RECEIVED_EARLY			 132
+#define SSL_R_CERTIFICATE_VERIFY_FAILED			 133
+#define SSL_R_CERT_LENGTH_MISMATCH			 134
+#define SSL_R_CHALLENGE_IS_DIFFERENT			 135
+#define SSL_R_CIPHER_CODE_WRONG_LENGTH			 136
+#define SSL_R_CIPHER_OR_HASH_UNAVAILABLE		 137
+#define SSL_R_CIPHER_TABLE_SRC_ERROR			 138
+#define SSL_R_COMPRESSED_LENGTH_TOO_LONG		 139
+#define SSL_R_COMPRESSION_FAILURE			 140
+#define SSL_R_CONNECTION_ID_IS_DIFFERENT		 141
+#define SSL_R_DATA_BETWEEN_CCS_AND_FINISHED		 142
+#define SSL_R_DATA_LENGTH_TOO_LONG			 143
+#define SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG		 144
+#define SSL_R_DIGEST_CHECK_FAILED			 145
+#define SSL_R_ENCRYPTED_LENGTH_TOO_LONG			 146
+#define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST		 147
+#define SSL_R_EXCESSIVE_MESSAGE_SIZE			 148
+#define SSL_R_EXTRA_DATA_IN_MESSAGE			 149
+#define SSL_R_GOT_A_FIN_BEFORE_A_CCS			 150
+#define SSL_R_INTERNAL_ERROR				 151
+#define SSL_R_INVALID_CHALLENGE_LENGTH			 152
+#define SSL_R_LENGTH_MISMATCH				 153
+#define SSL_R_LENGTH_TOO_SHORT				 154
+#define SSL_R_LIBRARY_HAS_NO_CIPHERS			 155
+#define SSL_R_MISSING_DH_DSA_CERT			 156
+#define SSL_R_MISSING_DH_KEY				 157
+#define SSL_R_MISSING_DH_RSA_CERT			 158
+#define SSL_R_MISSING_DSA_SIGNING_CERT			 159
+#define SSL_R_MISSING_EXPORT_TMP_DH_KEY			 160
+#define SSL_R_MISSING_EXPORT_TMP_RSA_KEY		 161
+#define SSL_R_MISSING_RSA_CERTIFICATE			 162
+#define SSL_R_MISSING_RSA_ENCRYPTING_CERT		 163
+#define SSL_R_MISSING_RSA_SIGNING_CERT			 164
+#define SSL_R_MISSING_TMP_DH_KEY			 165
+#define SSL_R_MISSING_TMP_RSA_KEY			 166
+#define SSL_R_MISSING_TMP_RSA_PKEY			 167
+#define SSL_R_MISSING_VERIFY_MESSAGE			 168
+#define SSL_R_NON_SSLV2_INITIAL_PACKET			 169
+#define SSL_R_NO_CERTIFICATES_PASSED			 170
+#define SSL_R_NO_CERTIFICATE_ASSIGNED			 171
+#define SSL_R_NO_CERTIFICATE_RETURNED			 172
+#define SSL_R_NO_CERTIFICATE_SET			 173
+#define SSL_R_NO_CERTIFICATE_SPECIFIED			 174
+#define SSL_R_NO_CIPHERS_AVAILABLE			 175
+#define SSL_R_NO_CIPHERS_PASSED				 176
+#define SSL_R_NO_CIPHERS_SPECIFIED			 177
+#define SSL_R_NO_CIPHER_LIST				 178
+#define SSL_R_NO_CIPHER_MATCH				 179
+#define SSL_R_NO_CLIENT_CERT_RECEIVED			 180
+#define SSL_R_NO_COMPRESSION_SPECIFIED			 181
+#define SSL_R_NO_PRIVATEKEY				 182
+#define SSL_R_NO_PRIVATE_KEY_ASSIGNED			 183
+#define SSL_R_NO_PUBLICKEY				 184
+#define SSL_R_NO_SHARED_CIPHER				 185
+#define SSL_R_NULL_SSL_CTX				 186
+#define SSL_R_NULL_SSL_METHOD_PASSED			 187
+#define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED		 188
+#define SSL_R_PACKET_LENGTH_TOO_LONG			 189
+#define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE		 190
+#define SSL_R_PEER_ERROR				 191
+#define SSL_R_PEER_ERROR_CERTIFICATE			 192
+#define SSL_R_PEER_ERROR_NO_CERTIFICATE			 193
+#define SSL_R_PEER_ERROR_NO_CIPHER			 194
+#define SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE	 195
+#define SSL_R_PRE_MAC_LENGTH_TOO_LONG			 196
+#define SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS		 197
+#define SSL_R_PROTOCOL_IS_SHUTDOWN			 198
+#define SSL_R_PUBLIC_KEY_ENCRYPT_ERROR			 199
+#define SSL_R_PUBLIC_KEY_IS_NOT_RSA			 200
+#define SSL_R_PUBLIC_KEY_NOT_RSA			 201
+#define SSL_R_READ_BIO_NOT_SET				 202
+#define SSL_R_READ_WRONG_PACKET_TYPE			 203
+#define SSL_R_RECORD_LENGTH_MISMATCH			 204
+#define SSL_R_RECORD_TOO_LARGE				 205
+#define SSL_R_REQUIRED_CIPHER_MISSING			 206
+#define SSL_R_REUSE_CERT_LENGTH_NOT_ZERO		 207
+#define SSL_R_REUSE_CERT_TYPE_NOT_ZERO			 208
+#define SSL_R_REUSE_CIPHER_LIST_NOT_ZERO		 209
+#define SSL_R_SHORT_READ				 210
+#define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE	 211
+#define SSL_R_SSL3_SESSION_ID_TOO_SHORT			 212
+#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_PEER_ERROR_CERTIFICATE	 213
+#define SSL_R_SSLV3_ALERT_PEER_ERROR_NO_CERTIFICATE	 214
+#define SSL_R_SSLV3_ALERT_PEER_ERROR_NO_CIPHER		 215
+#define SSL_R_SSLV3_ALERT_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE 216
+#define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE		 1010
+#define SSL_R_SSLV3_ALERT_UNKNOWN_REMOTE_ERROR_TYPE	 217
+#define SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE	 1043
+#define SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION	 218
+#define SSL_R_SSL_HANDSHAKE_FAILURE			 219
+#define SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS		 220
+#define SSL_R_SSL_SESSION_ID_IS_DIFFERENT		 221
+#define SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER		 222
+#define SSL_R_UNABLE_TO_DECODE_DH_CERTS			 223
+#define SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY		 224
+#define SSL_R_UNABLE_TO_FIND_DH_PARAMETERS		 225
+#define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS	 226
+#define SSL_R_UNABLE_TO_FIND_SSL_METHOD			 227
+#define SSL_R_UNEXPECTED_MESSAGE			 228
+#define SSL_R_UNEXPECTED_RECORD				 229
+#define SSL_R_UNKNOWN_ALERT_TYPE			 230
+#define SSL_R_UNKNOWN_CERTIFICATE_TYPE			 231
+#define SSL_R_UNKNOWN_CIPHER_RETURNED			 232
+#define SSL_R_UNKNOWN_CIPHER_TYPE			 233
+#define SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE			 234
+#define SSL_R_UNKNOWN_PKEY_TYPE				 235
+#define SSL_R_UNKNOWN_PROTOCOL				 236
+#define SSL_R_UNKNOWN_REMOTE_ERROR_TYPE			 237
+#define SSL_R_UNKNOWN_SSL_VERSION			 238
+#define SSL_R_UNKNOWN_STATE				 239
+#define SSL_R_UNSUPPORTED_CIPHER			 240
+#define SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM		 241
+#define SSL_R_UNSUPPORTED_SSL_VERSION			 242
+#define SSL_R_WRITE_BIO_NOT_SET				 243
+#define SSL_R_WRONG_CIPHER_RETURNED			 244
+#define SSL_R_WRONG_MESSAGE_TYPE			 245
+#define SSL_R_WRONG_NUMBER_OF_KEY_BITS			 246
+#define SSL_R_WRONG_SIGNATURE_LENGTH			 247
+#define SSL_R_WRONG_SIGNATURE_SIZE			 248
+#define SSL_R_WRONG_SSL_VERSION				 249
+#define SSL_R_WRONG_VERSION_NUMBER			 250
+#define SSL_R_X509_LIB					 251
diff --git a/ssl/ssl.h b/ssl/ssl.h
new file mode 100644
index 0000000..594295d
--- /dev/null
+++ b/ssl/ssl.h
@@ -0,0 +1,1290 @@
+/* ssl/ssl.h */
+/* Copyright (C) 1995-1997 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_SSL_H 
+#define HEADER_SSL_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	
+
+#define SSL_MAX_SSL_SESSION_ID_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_LOW		"LOW"
+#define SSL_TXT_MEDIUM		"MEDIUM"
+#define SSL_TXT_HIGH		"HIGH"
+#define SSL_TXT_kFZA		"kFZA"
+#define	SSL_TXT_aFZA		"aFZA"
+#define SSL_TXT_eFZA		"eFZA"
+#define SSL_TXT_FZA		"FZA"
+
+#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"
+#define SSL_TXT_kDHd		"kDHd"
+#define SSL_TXT_kEDH		"kEDH"
+#define	SSL_TXT_aRSA		"aRSA"
+#define	SSL_TXT_aDSS		"aDSS"
+#define	SSL_TXT_aDH		"aDH"
+#define	SSL_TXT_DSS		"DSS"
+#define SSL_TXT_DH		"DH"
+#define SSL_TXT_EDH		"EDH"
+#define SSL_TXT_ADH		"ADH"
+#define SSL_TXT_RSA		"RSA"
+#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_MD5		"MD5"
+#define SSL_TXT_SHA0		"SHA0"
+#define SSL_TXT_SHA1		"SHA1"
+#define SSL_TXT_SHA		"SHA"
+#define SSL_TXT_EXP		"EXP"
+#define SSL_TXT_EXPORT		"EXPORT"
+#define SSL_TXT_SSLV2		"SSLv2"
+#define SSL_TXT_SSLV3		"SSLv3"
+#define SSL_TXT_ALL		"ALL"
+
+/* 'DEFAULT' at the start of the cipher list insert the following string
+ * in addition to this being the default cipher string */
+#ifndef NO_RSA
+#define SSL_DEFAULT_CIPHER_LIST	"!ADH:RC4+RSA:HIGH:MEDIUM:LOW:EXP:+SSLv2:+EXP"
+#else
+#define SSL_ALLOW_ADH
+#define SSL_DEFAULT_CIPHER_LIST	"HIGH:MEDIUM:LOW:ADH+3DES:ADH+RC4:ADH+DES:+EXP"
+#endif
+
+#define SSL_SENT_SHUTDOWN	1
+#define SSL_RECEIVED_SHUTDOWN	2
+#define SSL_CTX_set_quiet_shutdown(ctx,y) ((ctx)->quiet_shutdown=(y));
+#define SSL_CTX_get_quiet_shutdown(ctx) ((ctx)->quiet_shutdown);
+#define SSL_set_quiet_shutdown(s,y)	((s)->quiet_shutdown=(y));
+#define SSL_get_quiet_shutdown(s)	((s)->quiet_shutdown);
+#define SSL_set_shutdown(s,mode)	((s)->shutdown=(mode))
+#define SSL_get_shutdown(s)		((s)->shutdown)
+#define SSL_version(s)			((s)->version)
+
+#include "buffer.h"
+#include "bio.h"
+#include "x509.h"
+
+#define SSL_FILETYPE_ASN1	X509_FILETYPE_ASN1
+#define SSL_FILETYPE_PEM	X509_FILETYPE_PEM
+
+typedef struct ssl_st *ssl_crock_st;
+
+/* used to hold info on the particular ciphers used */
+typedef struct ssl_cipher_st
+	{
+	int valid;
+	char *name;			/* text name */
+	unsigned long id;		/* id, 4 bytes, first is version */
+	unsigned long algorithms;	/* what ciphers are used */
+	unsigned long algorithm2;	/* Extra flags */
+	unsigned long mask;		/* used for matching */
+	} SSL_CIPHER;
+
+/* Used to hold functions for SSLv2 or SSLv3 functions */
+typedef struct ssl_method_st
+	{
+	int version;
+	int (*ssl_new)();
+	void (*ssl_clear)();
+	void (*ssl_free)();
+	int (*ssl_accept)();
+	int (*ssl_connect)();
+	int (*ssl_read)();
+	int (*ssl_peek)();
+	int (*ssl_write)();
+	int (*ssl_shutdown)();
+	int (*ssl_renegotiate)();
+	long (*ssl_ctrl)();
+	long (*ssl_ctx_ctrl)();
+	SSL_CIPHER *(*get_cipher_by_char)();
+	int (*put_cipher_by_char)();
+	int (*ssl_pending)();
+	int (*num_ciphers)();
+	SSL_CIPHER *(*get_cipher)();
+	struct ssl_method_st *(*get_ssl_method)();
+	long (*get_timeout)();
+	} SSL_METHOD;
+
+typedef struct ssl_compression_st
+	{
+	char *stuff;
+	} SSL_COMPRESSION;
+
+/* 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
+ *	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
+ *	}
+ * 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];
+
+	int not_resumable;
+
+	/* The cert is the certificate used to establish this connection */
+	struct cert_st /* CERT */ *cert;
+
+	/* This is the cert for the other end.  On servers, it will be
+	 * the same as cert->x509 */
+	X509 *peer;
+
+	int references;
+	long timeout;
+	long time;
+
+	SSL_COMPRESSION *read_compression;
+	SSL_COMPRESSION *write_compression;
+
+	SSL_CIPHER *cipher;
+	unsigned long cipher_id;	/* when ASN.1 loaded, this
+					 * needs to be used to load
+					 * the 'cipher' structure */
+
+	STACK /* SSL_CIPHER */ *ciphers; /* shared ciphers? */
+
+	char *app_data; /* application specific data */
+	} SSL_SESSION;
+
+#define SSL_OP_MICROSOFT_SESS_ID_BUG			0x00000001L
+#define SSL_OP_NETSCAPE_CHALLENGE_BUG			0x00000002L
+#define SSL_OP_NETSCAPE_CA_DN_BUG			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
+#define SSL_OP_SSLEAY_080_CLIENT_DH_BUG			0x00000080L
+
+/* If set, only use tmp_dh parameters once */
+#define SSL_OP_SINGLE_DH_USE				0x00100000L
+/* Set to also use the tmp_rsa key when doing RSA operations. */
+#define SSL_OP_EPHEMERAL_RSA				0x00200000L
+
+#define SSL_OP_NON_EXPORT_FIRST 			0x40000000L
+#define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG		0x80000000L
+#define SSL_OP_ALL					0x000FFFFFL
+
+#define SSL_CTX_set_options(ctx,op)	((ctx)->options|=(op))
+
+/* Normally you will only use these if your application wants to use
+ * the certificate store in other places, perhaps PKCS7 */
+#define SSL_CTX_get_cert_store(ctx)     ((ctx)->cert_store)
+#define SSL_CTX_set_cert_store(ctx,cs) \
+                (X509_STORE_free((ctx)->cert_store),(ctx)->cert_store=(cs))
+
+
+typedef struct ssl_ctx_st
+	{
+	SSL_METHOD *method;
+	unsigned long options;
+
+	STACK /* SSL_CIPHER */ *cipher_list;
+	/* same as above but sorted for lookup */
+	STACK /* SSL_CIPHER */ *cipher_list_by_id;
+
+	struct x509_store_st /* X509_STORE */ *cert_store;
+	struct lhash_st /* LHASH */ *sessions;	/* a set of SSL_SESSION's */
+
+	/* 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.  Again, a return
+	 * of 0 mens that SSLeay should not SSL_SESSION_free() since
+	 * the application is doing something with it. */
+#ifndef NOPROTO
+	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);
+#else
+	int (*new_session_cb)();
+	void (*remove_session_cb)();
+	SSL_SESSION *(*get_session_cb)();
+#endif
+
+	int sess_connect;	/* SSL new (expensive) connection - started */
+	int sess_connect_good;	/* SSL new (expensive) connection - finished */
+	int sess_accept;	/* SSL new (expensive) accept - started */
+	int sess_accept_good;	/* SSL new (expensive) accept - finished */
+	int sess_miss;		/* session lookup misses  */
+	int sess_timeout;	/* session reuse attempt on timeouted session */
+	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 :-) */
+
+	int references;
+
+	void (*info_callback)();
+
+	/* if defined, these override the X509_verify_cert() calls */
+	int (*app_verify_callback)();
+	char *app_verify_arg;
+
+	/* default values to use in SSL structures */
+	struct cert_st /* CERT */ *default_cert;
+	int default_read_ahead;
+	int default_verify_mode;
+	int (*default_verify_callback)();
+
+	/* Default password callback. */
+	int (*default_passwd_callback)();
+
+	/* get client cert callback */
+	int (*client_cert_cb)(/* SSL *ssl, X509 **x509, EVP_PKEY **pkey */);
+
+	/* what we put in client requests */
+	STACK *client_CA;
+
+	int quiet_shutdown;
+
+	char *app_data;
+	} SSL_CTX;
+
+#define SSL_SESS_CACHE_OFF	0x00
+#define SSL_SESS_CACHE_CLIENT	0x01
+#define SSL_SESS_CACHE_SERVER	0x02
+#define SSL_SESS_CACHE_BOTH	(SSL_SESS_CACHE_CLIENT|SSL_SESS_CACHE_SERVER)
+#define SSL_SESS_CACHE_NO_AUTO_CLEAR	0x80
+
+#define SSL_session_reused(s)	((s)->hit)
+
+#define SSL_CTX_sessions(ctx)		((ctx)->sessions)
+/* You will need to include lhash.h to access the following #define */
+#define SSL_CTX_sess_number(ctx)	((ctx)->sessions->num_items)
+#define SSL_CTX_sess_connect(ctx)	((ctx)->sess_connect)
+#define SSL_CTX_sess_connect_good(ctx)	((ctx)->sess_connect_good)
+#define SSL_CTX_sess_accept(ctx)	((ctx)->sess_accept)
+#define SSL_CTX_sess_accept_good(ctx)	((ctx)->sess_accept_good)
+#define SSL_CTX_sess_hits(ctx)		((ctx)->sess_hit)
+#define SSL_CTX_sess_cb_hits(ctx)	((ctx)->sess_cb_hit)
+#define SSL_CTX_sess_misses(ctx)	((ctx)->sess_miss)
+#define SSL_CTX_sess_timeouts(ctx)	((ctx)->sess_timeout)
+
+#define SSL_CTX_sess_set_new_cb(ctx,cb)	((ctx)->new_session_cb=(cb))
+#define SSL_CTX_sess_get_new_cb(ctx)	((ctx)->new_session_cb)
+#define SSL_CTX_sess_set_remove_cb(ctx,cb)	((ctx)->remove_session_cb=(cb))
+#define SSL_CTX_sess_get_remove_cb(ctx)	((ctx)->remove_session_cb)
+#define SSL_CTX_sess_set_get_cb(ctx,cb)	((ctx)->get_session_cb=(cb))
+#define SSL_CTX_sess_get_get_cb(ctx)	((ctx)->get_session_cb)
+#define SSL_CTX_set_session_cache_mode(ctx,m)	((ctx)->session_cache_mode=(m))
+#define SSL_CTX_get_session_cache_mode(ctx)	((ctx)->session_cache_mode)
+#define SSL_CTX_set_timeout(ctx,t)	((ctx)->session_timeout=(t))
+#define SSL_CTX_get_timeout(ctx)	((ctx)->session_timeout)
+
+#define SSL_CTX_set_info_callback(ctx,cb)	((ctx)->info_callback=(cb))
+#define SSL_CTX_get_info_callback(ctx)		((ctx)->info_callback)
+#define SSL_CTX_set_default_read_ahead(ctx,m) (((ctx)->default_read_ahead)=(m))
+
+#define SSL_CTX_set_client_cert_cb(ctx,cb)	((ctx)->client_cert_cb=(cb))
+#define SSL_CTX_get_client_cert_cb(ctx)		((ctx)->client_cert_cb)
+
+#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(s)		((s)->rwstate)
+#define SSL_want_nothing(s)	((s)->rwstate == SSL_NOTHING)
+#define SSL_want_read(s)	((s)->rwstate == SSL_READING)
+#define SSL_want_write(s)	((s)->rwstate == SSL_WRITING)
+#define SSL_want_x509_lookup(s)	((s)->rwstate == SSL_X509_LOOKUP)
+
+typedef struct ssl_st
+	{
+	/* procol version
+	 * 2 for SSLv2
+	 * 3 for SSLv3
+	 * -3 for SSLv3 but accept SSLv2 */
+	int version;
+	int type; /* SSL_ST_CONNECT or SSL_ST_ACCEPT */
+
+	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 */
+
+#ifdef HEADER_BIO_H
+	BIO *rbio; /* used by SSL_read */
+	BIO *wbio; /* used by SSL_write */
+	BIO *bbio; /* used during session-id reuse to concatinate
+		    * 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)();
+
+/*	int server;*/	/* are we the server side? */
+
+	int new_session;/* 1 if we are to use a new session */
+	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 */
+	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_ctx_st *s2;	/* SSLv2 variables */
+	struct ssl3_ctx_st *s3;	/* SSLv3 variables */
+
+	int read_ahead;		/* Read as many input bytes as possible */
+	int hit;		/* reusing a previous session */
+
+	/* crypto */
+	STACK /* SSL_CIPHER */ *cipher_list;
+	STACK /* SSL_CIPHER */ *cipher_list_by_id;
+
+	/* These are the ones being used, the ones is SSL_SESSION are
+	 * the ones to be 'copied' into these ones */
+
+	EVP_CIPHER_CTX *enc_read_ctx;		/* cryptographic state */
+	EVP_MD *read_hash;			/* used for mac generation */
+	SSL_COMPRESSION *read_compression;	/* compression */
+
+	EVP_CIPHER_CTX *enc_write_ctx;		/* cryptographic state */
+	EVP_MD *write_hash;			/* used for mac generation */
+	SSL_COMPRESSION *write_compression;	/* compression */
+
+	/* session info */
+
+	/* client cert? */
+	/* This is used to hold the server certificate used */
+	struct cert_st /* CERT */ *cert;
+
+	/* This can also be in the session once a session is established */
+	SSL_SESSION *session;
+
+	/* Used in SSL2 and SSL3 */
+	int verify_mode;	/* 0 don't care about verify failure.
+				 * 1 fail if verify fails */
+	int (*verify_callback)(); /* fail if callback returns 0 */
+	void (*info_callback)(); /* optional informational callback */
+
+	int error;		/* error bytes to be written */
+	int error_code;		/* actual code */
+
+	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 */
+	int verify_result;
+	char *app_data;
+
+	/* for server side, keep the list of CA_dn we can use */
+	STACK /* X509_NAME */ *client_CA;
+
+	int first_packet;
+	} SSL;
+
+#include "ssl2.h"
+#include "ssl3.h"
+#include "ssl23.h"
+
+/* application stuff */
+#define SSL_set_verify_result(s,arg)	((s)->verify_result=(long)arg)
+#define SSL_get_verify_result(s)	((s)->verify_result)
+#define SSL_set_app_data(s,arg)		((s)->app_data=(char *)arg)
+#define SSL_get_app_data(s)		((s)->app_data)
+
+#define SSL_SESSION_set_app_data(s,arg)		((s)->app_data=(char *)arg)
+#define SSL_SESSION_get_app_data(s)		((s)->app_data)
+
+#define SSL_CTX_set_app_data(ctx,arg)	((ctx)->app_data=(char *)arg)
+#define SSL_CTX_get_app_data(ctx)	((ctx)->app_data)
+
+/* The following are the possible values for ssl->state are are
+ * used to indicate where we are upto 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_state(a)			((a)->state)
+#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)
+
+/* SSL info callback functions */
+#define SSL_set_info_callback(ssl,cb)	((ssl)->info_callback=(cb))
+#define SSL_get_info_callback(ssl)	((ssl)->info_callback)
+
+#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_is_init_finished(a)		((a)->state == SSL_ST_OK)
+#define SSL_in_init(a)			((a)->state&SSL_ST_INIT)
+#define SSL_in_before(a)		((a)->state&SSL_ST_BEFORE)
+#define SSL_in_connect_init(a)		((a)->state&SSL_ST_CONNECT)
+#define SSL_in_accept_init(a)		((a)->state&SSL_ST_ACCEPT)
+
+/* 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
+
+/* 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 SSL_RWERR_BAD_WRITE_RETRY	(-2)
+#define SSL_RWERR_BAD_MAC_DECODE	(-3)
+#define SSL_RWERR_INTERNAL_ERROR	(-4) /* should not get this one */
+#define SSL_RWERR_WRONG_RECORD_TYPE	(-5) /* used internally */
+
+#define SSL_CTX_set_default_verify_paths(ctx) \
+		X509_STORE_set_default_paths((ctx)->cert_store)
+#define SSL_CTX_load_verify_locations(ctx,CAfile,CApath) \
+		X509_STORE_load_locations((ctx)->cert_store,\
+		(CAfile),(CApath))
+
+#define SSL_get_session(s)	((s)->session)
+#define SSL_get_SSL_CTX(s)	((s)->ctx)
+
+/* this is for backward compatablility */
+#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 compatablity */
+#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))
+
+/* VMS linker has a 31 char name limit */
+#define SSL_CTX_set_cert_verify_callback(a,b,c) \
+		SSL_CTX_set_cert_verify_cb((a),(b),(c))
+
+#if 1 /*SSLEAY_MACROS*/
+#define d2i_SSL_SESSION_bio(bp,s_id) (SSL_SESSION *)ASN1_d2i_bio( \
+	(char *(*)())SSL_SESSION_new,(char *(*)())d2i_SSL_SESSION, \
+	(bp),(unsigned char **)(s_id))
+#define i2d_SSL_SESSION_bio(bp,s_id) ASN1_i2d_bio(i2d_SSL_SESSION, \
+	bp,(unsigned char *)s_id)
+#define PEM_read_SSL_SESSION(fp,x,cb) (SSL_SESSION *)PEM_ASN1_read( \
+	(char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,fp,(char **)x,cb)
+#define PEM_read_bio_SSL_SESSION(bp,x,cb) (SSL_SESSION *)PEM_ASN1_read_bio( \
+	(char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,bp,(char **)x,cb)
+#define PEM_write_SSL_SESSION(fp,x) \
+	PEM_ASN1_write((int (*)())i2d_SSL_SESSION, \
+		PEM_STRING_SSL_SESSION,fp, (char *)x, NULL,NULL,0,NULL)
+#define PEM_write_bio_SSL_SESSION(bp,x) \
+	PEM_ASN1_write_bio((int (*)())i2d_SSL_SESSION, \
+		PEM_STRING_SSL_SESSION,bp, (char *)x, NULL,NULL,0,NULL)
+#endif
+
+#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 errno */
+#define SSL_ERROR_ZERO_RETURN		6
+#define SSL_ERROR_WANT_CONNECT		7
+
+#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_RSA_CB		4
+#define SSL_CTRL_SET_TMP_DH_CB		5
+
+#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)
+
+/* For the next 2, the callbacks are 
+ * RSA *tmp_rsa_cb(int export)
+ * DH *tmp_dh_cb(int export)
+ */
+#define SSL_CTX_set_tmp_rsa_callback(ctx,cb) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_RSA_CB,0,(char *)cb)
+#define SSL_CTX_set_tmp_dh_callback(ctx,dh) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH_CB,0,(char *)cb)
+
+#ifndef NOPROTO
+
+#ifdef HEADER_BIO_H
+BIO_METHOD *BIO_f_ssl(void);
+BIO *BIO_new_ssl(SSL_CTX *ctx,int client);
+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 *,char *str);
+SSL_CTX *SSL_CTX_new(SSL_METHOD *meth);
+void	SSL_CTX_free(SSL_CTX *);
+void	SSL_clear(SSL *s);
+void	SSL_CTX_flush_sessions(SSL_CTX *ctx,long tm);
+
+SSL_CIPHER *SSL_get_current_cipher(SSL *s);
+int	SSL_CIPHER_get_bits(SSL_CIPHER *c,int *alg_bits);
+char *	SSL_CIPHER_get_version(SSL_CIPHER *c);
+char *	SSL_CIPHER_get_name(SSL_CIPHER *c);
+
+int	SSL_get_fd(SSL *s);
+char  * SSL_get_cipher_list(SSL *s,int n);
+char *	SSL_get_shared_ciphers(SSL *s, char *buf, int len);
+int	SSL_get_read_ahead(SSL * s);
+int	SSL_pending(SSL *s);
+#ifndef 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
+#ifdef HEADER_BIO_H
+void	SSL_set_bio(SSL *s, BIO *rbio,BIO *wbio);
+BIO *	SSL_get_rbio(SSL *s);
+BIO *	SSL_get_wbio(SSL *s);
+#endif
+int	SSL_set_cipher_list(SSL *s, char *str);
+void	SSL_set_read_ahead(SSL *s, int yes);
+int	SSL_get_verify_mode(SSL *s);
+int	(*SSL_get_verify_callback(SSL *s))();
+void	SSL_set_verify(SSL *s, int mode, int (*callback) ());
+int	SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa);
+int	SSL_use_RSAPrivateKey_ASN1(SSL *ssl, unsigned char *d, long len);
+int	SSL_use_RSAPrivateKey_file(SSL *ssl, char *file, int type);
+int	SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey);
+int	SSL_use_PrivateKey_ASN1(int pk,SSL *ssl, unsigned char *d, long len);
+int	SSL_use_PrivateKey_file(SSL *ssl, char *file, int type);
+int	SSL_use_certificate(SSL *ssl, X509 *x);
+int	SSL_use_certificate_ASN1(SSL *ssl, int len, unsigned char *d);
+int	SSL_use_certificate_file(SSL *ssl, char *file, int type);
+void	ERR_load_SSL_strings(void );
+void	SSL_load_error_strings(void );
+char * 	SSL_state_string(SSL *s);
+char * 	SSL_rstate_string(SSL *s);
+char * 	SSL_state_string_long(SSL *s);
+char * 	SSL_rstate_string_long(SSL *s);
+long	SSL_get_time(SSL_SESSION *s);
+long	SSL_set_time(SSL_SESSION *s, long t);
+long	SSL_get_timeout(SSL_SESSION *s);
+long	SSL_set_timeout(SSL_SESSION *s, long t);
+void	SSL_copy_session_id(SSL *to,SSL *from);
+
+SSL_SESSION *SSL_SESSION_new(void);
+#ifndef WIN16
+int	SSL_SESSION_print_fp(FILE *fp,SSL_SESSION *ses);
+#endif
+#ifdef HEADER_BIO_H
+int	SSL_SESSION_print(BIO *fp,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);
+int	SSL_CTX_add_session(SSL_CTX *s, SSL_SESSION *c);
+int	SSL_CTX_remove_session(SSL_CTX *,SSL_SESSION *c);
+SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a,unsigned char **pp,long length);
+
+#ifdef HEADER_X509_H
+X509 *	SSL_get_peer_certificate(SSL *s);
+#endif
+
+STACK *	SSL_get_peer_cert_chain(SSL *s);
+
+int SSL_CTX_get_verify_mode(SSL_CTX *ctx);
+int (*SSL_CTX_get_verify_callback(SSL_CTX *ctx))();
+void SSL_CTX_set_verify(SSL_CTX *ctx,int mode,int (*callback)());
+void SSL_CTX_set_cert_verify_cb(SSL_CTX *ctx, int (*cb)(),char *arg);
+int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa);
+int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, unsigned char *d, long len);
+int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, char *file, int type);
+int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey);
+int SSL_CTX_use_PrivateKey_ASN1(int pk,SSL_CTX *ctx,
+	unsigned char *d, long len);
+int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, char *file, int type);
+int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x);
+int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, unsigned char *d);
+int SSL_CTX_use_certificate_file(SSL_CTX *ctx, char *file, int type);
+
+void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx,int (*cb)());
+
+int SSL_CTX_check_private_key(SSL_CTX *ctx);
+int SSL_check_private_key(SSL *ctx);
+
+SSL *	SSL_new(SSL_CTX *ctx);
+void    SSL_clear(SSL *s);
+void	SSL_free(SSL *ssl);
+int 	SSL_accept(SSL *ssl);
+int 	SSL_connect(SSL *ssl);
+int 	SSL_read(SSL *ssl,char *buf,int num);
+int 	SSL_peek(SSL *ssl,char *buf,int num);
+int 	SSL_write(SSL *ssl,char *buf,int num);
+long	SSL_ctrl(SSL *ssl,int cmd, long larg, char *parg);
+long	SSL_CTX_ctrl(SSL_CTX *ctx,int cmd, long larg, char *parg);
+
+int	SSL_get_error(SSL *s,int ret_code);
+char *	SSL_get_version(SSL *s);
+
+/* This sets the 'default' SSL version that SSL_new() will create */
+int SSL_CTX_set_ssl_version(SSL_CTX *ctx,SSL_METHOD *meth);
+
+SSL_METHOD *SSLv2_method(void);		/* sslv2 */
+SSL_METHOD *SSLv2_server_method(void);	/* sslv2 */
+SSL_METHOD *SSLv2_client_method(void);	/* sslv2 */
+
+SSL_METHOD *SSLv3_method(void);		/* sslv3 */
+SSL_METHOD *SSLv3_server_method(void);	/* sslv3 */
+SSL_METHOD *SSLv3_client_method(void);	/* sslv3 */
+
+SSL_METHOD *SSLv23_method(void);	/* sslv3 but can rollback to v2 */
+SSL_METHOD *SSLv23_server_method(void);	/* sslv3 but can rollback to v2 */
+SSL_METHOD *SSLv23_client_method(void);	/* sslv3 but can rollback to v2 */
+
+STACK *SSL_get_ciphers(SSL *s);
+
+int SSL_do_handshake(SSL *s);
+int SSL_renegotiate(SSL *s);
+int SSL_shutdown(SSL *s);
+
+SSL_METHOD *SSL_get_ssl_method(SSL *s);
+int SSL_set_ssl_method(SSL *s,SSL_METHOD *method);
+char *SSL_alert_type_string_long(int value);
+char *SSL_alert_type_string(int value);
+char *SSL_alert_desc_string_long(int value);
+char *SSL_alert_desc_string(int value);
+
+STACK *SSL_load_client_CA_file(char *file);
+void SSL_set_client_CA_list(SSL *s, STACK *list);
+void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK *list);
+STACK *SSL_get_client_CA_list(SSL *s);
+STACK *SSL_CTX_get_client_CA_list(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(SSL *s);
+
+void SSLeay_add_ssl_algorithms(void );
+
+char *SSL_CIPHER_description(SSL_CIPHER *,char *buf,int size);
+STACK *SSL_dup_CA_list(STACK *sk);
+
+SSL *SSL_dup(SSL *ssl);
+
+X509 *SSL_get_certificate(SSL *ssl);
+/* EVP_PKEY */ struct evp_pkey_st *SSL_get_privatekey(SSL *ssl);
+
+#else
+
+BIO_METHOD *BIO_f_ssl();
+BIO *BIO_new_ssl();
+int BIO_ssl_copy_session_id();
+void BIO_ssl_shutdown();
+
+int	SSL_CTX_set_cipher_list();
+SSL_CTX *SSL_CTX_new();
+void	SSL_CTX_free();
+void	SSL_clear();
+void	SSL_CTX_flush_sessions();
+
+SSL_CIPHER *SSL_get_current_cipher();
+int	SSL_CIPHER_get_bits();
+char *	SSL_CIPHER_get_version();
+char *	SSL_CIPHER_get_name();
+
+int	SSL_get_fd();
+char  * SSL_get_cipher_list();
+char *	SSL_get_shared_ciphers();
+int	SSL_get_read_ahead();
+int	SSL_pending();
+#ifndef NO_SOCK
+int	SSL_set_fd();
+int	SSL_set_rfd();
+int	SSL_set_wfd();
+#endif
+#ifdef HEADER_BIO_H
+void	SSL_set_bio();
+BIO *	SSL_get_rbio();
+BIO *	SSL_get_wbio();
+#endif
+int	SSL_set_cipher_list();
+void	SSL_set_read_ahead();
+int	SSL_get_verify_mode();
+
+void	SSL_set_verify();
+int	SSL_use_RSAPrivateKey();
+int	SSL_use_RSAPrivateKey_ASN1();
+int	SSL_use_RSAPrivateKey_file();
+int	SSL_use_PrivateKey();
+int	SSL_use_PrivateKey_ASN1();
+int	SSL_use_PrivateKey_file();
+int	SSL_use_certificate();
+int	SSL_use_certificate_ASN1();
+int	SSL_use_certificate_file();
+void	ERR_load_SSL_strings();
+void	SSL_load_error_strings();
+char * 	SSL_state_string();
+char * 	SSL_rstate_string();
+char * 	SSL_state_string_long();
+char * 	SSL_rstate_string_long();
+long	SSL_get_time();
+long	SSL_set_time();
+long	SSL_get_timeout();
+long	SSL_set_timeout();
+void	SSL_copy_session_id();
+
+SSL_SESSION *SSL_SESSION_new();
+#ifndef WIN16
+int	SSL_SESSION_print_fp();
+#endif
+#ifdef HEADER_BIO_H
+int	SSL_SESSION_print();
+#endif
+void	SSL_SESSION_free();
+int	i2d_SSL_SESSION();
+int	SSL_set_session();
+int	SSL_CTX_add_session();
+int	SSL_CTX_remove_session();
+SSL_SESSION *d2i_SSL_SESSION();
+
+#ifdef HEADER_X509_H
+X509 *	SSL_get_peer_certificate();
+#endif
+
+STACK *	SSL_get_peer_cert_chain();
+
+int SSL_CTX_get_verify_mode();
+int (*SSL_CTX_get_verify_callback())();
+void SSL_CTX_set_verify();
+void SSL_CTX_set_cert_verify_cb();
+int SSL_CTX_use_RSAPrivateKey();
+int SSL_CTX_use_RSAPrivateKey_ASN1();
+int SSL_CTX_use_RSAPrivateKey_file();
+int SSL_CTX_use_PrivateKey();
+int SSL_CTX_use_PrivateKey_ASN1();
+int SSL_CTX_use_PrivateKey_file();
+int SSL_CTX_use_certificate();
+int SSL_CTX_use_certificate_ASN1();
+int SSL_CTX_use_certificate_file();
+
+void SSL_CTX_set_default_passwd_cb();
+
+int SSL_CTX_check_private_key();
+int SSL_check_private_key();
+
+SSL *	SSL_new();
+void    SSL_clear();
+void	SSL_free();
+int 	SSL_accept();
+int 	SSL_connect();
+int 	SSL_read();
+int 	SSL_peek();
+int 	SSL_write();
+long	SSL_ctrl();
+long	SSL_CTX_ctrl();
+
+int	SSL_get_error();
+char *	SSL_get_version();
+
+int SSL_CTX_set_ssl_version();
+
+SSL_METHOD *SSLv2_method();
+SSL_METHOD *SSLv2_server_method();
+SSL_METHOD *SSLv2_client_method();
+
+SSL_METHOD *SSLv3_method();
+SSL_METHOD *SSLv3_server_method();
+SSL_METHOD *SSLv3_client_method();
+
+SSL_METHOD *SSLv23_method();
+SSL_METHOD *SSLv23_server_method();
+SSL_METHOD *SSLv23_client_method();
+
+STACK *SSL_get_ciphers();
+
+int SSL_do_handshake();
+int SSL_renegotiate();
+int SSL_shutdown();
+
+SSL_METHOD *SSL_get_ssl_method();
+int SSL_set_ssl_method();
+char *SSL_alert_type_string_long();
+char *SSL_alert_type_string();
+char *SSL_alert_desc_string_long();
+char *SSL_alert_desc_string();
+
+STACK *SSL_load_client_CA_file();
+void SSL_set_client_CA_list();
+void SSL_CTX_set_client_CA_list();
+STACK *SSL_get_client_CA_list();
+STACK *SSL_CTX_get_client_CA_list();
+int SSL_add_client_CA();
+int SSL_CTX_add_client_CA();
+
+void SSL_set_connect_state();
+void SSL_set_accept_state();
+
+long SSL_get_default_timeout();
+
+void SSLeay_add_ssl_algorithms();
+
+char *SSL_CIPHER_description();
+STACK *SSL_dup_CA_list();
+
+SSL *SSL_dup();
+
+X509 *SSL_get_certificate();
+/* EVP * */ struct evp_pkey_st *SSL_get_privatekey();
+
+#ifdef this_is_for_mk1mf_pl
+EVP *SSL_get_privatekey();
+#endif
+
+#endif
+
+/* BEGIN ERROR CODES */
+/* Error codes for the SSL functions. */
+
+/* Function codes. */
+#define SSL_F_CLIENT_CERTIFICATE			 100
+#define SSL_F_CLIENT_HELLO				 101
+#define SSL_F_CLIENT_MASTER_KEY				 102
+#define SSL_F_D2I_SSL_SESSION				 103
+#define SSL_F_DO_SSL3_WRITE				 104
+#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_HELLO				 114
+#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_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_READ					 125
+#define SSL_F_SSL2_SET_CERTIFICATE			 126
+#define SSL_F_SSL2_WRITE				 127
+#define SSL_F_SSL3_ACCEPT				 128
+#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_CTX_CTRL				 133
+#define SSL_F_SSL3_ENC					 134
+#define SSL_F_SSL3_GET_CERTIFICATE_REQUEST		 135
+#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_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_OUTPUT_CERT_CHAIN			 147
+#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_KEY_EXCHANGE		 155
+#define SSL_F_SSL3_SETUP_BUFFERS			 156
+#define SSL_F_SSL3_SETUP_KEY_BLOCK			 157
+#define SSL_F_SSL3_WRITE_BYTES				 158
+#define SSL_F_SSL3_WRITE_PENDING			 159
+#define SSL_F_SSL_BAD_METHOD				 160
+#define SSL_F_SSL_BYTES_TO_CIPHER_LIST			 161
+#define SSL_F_SSL_CERT_NEW				 162
+#define SSL_F_SSL_CHECK_PRIVATE_KEY			 163
+#define SSL_F_SSL_CREATE_CIPHER_LIST			 164
+#define SSL_F_SSL_CTX_CHECK_PRIVATE_KEY			 165
+#define SSL_F_SSL_CTX_NEW				 166
+#define SSL_F_SSL_CTX_SET_SSL_VERSION			 167
+#define SSL_F_SSL_CTX_USE_CERTIFICATE			 168
+#define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1		 169
+#define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE		 170
+#define SSL_F_SSL_CTX_USE_PRIVATEKEY			 171
+#define SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1		 172
+#define SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE		 173
+#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY			 174
+#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1		 175
+#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE		 176
+#define SSL_F_SSL_DO_HANDSHAKE				 177
+#define SSL_F_SSL_GET_NEW_SESSION			 178
+#define SSL_F_SSL_GET_SERVER_SEND_CERT			 179
+#define SSL_F_SSL_GET_SIGN_PKEY				 180
+#define SSL_F_SSL_LOAD_CLIENT_CA_FILE			 181
+#define SSL_F_SSL_NEW					 182
+#define SSL_F_SSL_RSA_PRIVATE_DECRYPT			 183
+#define SSL_F_SSL_RSA_PUBLIC_ENCRYPT			 184
+#define SSL_F_SSL_SESSION_NEW				 185
+#define SSL_F_SSL_SESSION_PRINT_FP			 186
+#define SSL_F_SSL_SET_FD				 187
+#define SSL_F_SSL_SET_PKEY				 188
+#define SSL_F_SSL_SET_RFD				 189
+#define SSL_F_SSL_SET_SESSION				 190
+#define SSL_F_SSL_SET_WFD				 191
+#define SSL_F_SSL_UNDEFINED_FUNCTION			 192
+#define SSL_F_SSL_USE_CERTIFICATE			 193
+#define SSL_F_SSL_USE_CERTIFICATE_ASN1			 194
+#define SSL_F_SSL_USE_CERTIFICATE_FILE			 195
+#define SSL_F_SSL_USE_PRIVATEKEY			 196
+#define SSL_F_SSL_USE_PRIVATEKEY_ASN1			 197
+#define SSL_F_SSL_USE_PRIVATEKEY_FILE			 198
+#define SSL_F_SSL_USE_RSAPRIVATEKEY			 199
+#define SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1		 200
+#define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE		 201
+#define SSL_F_SSL_WRITE					 202
+#define SSL_F_WRITE_PENDING				 203
+
+/* Reason codes. */
+#define SSL_R_APP_DATA_IN_HANDSHAKE			 100
+#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_CLIENT_REQUEST			 105
+#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_MAC_DECODE				 113
+#define SSL_R_BAD_MESSAGE_TYPE				 114
+#define SSL_R_BAD_PACKET_LENGTH				 115
+#define SSL_R_BAD_RESPONSE_ARGUMENT			 116
+#define SSL_R_BAD_RSA_DECRYPT				 117
+#define SSL_R_BAD_RSA_ENCRYPT				 118
+#define SSL_R_BAD_RSA_E_LENGTH				 119
+#define SSL_R_BAD_RSA_MODULUS_LENGTH			 120
+#define SSL_R_BAD_RSA_SIGNATURE				 121
+#define SSL_R_BAD_SIGNATURE				 122
+#define SSL_R_BAD_SSL_FILETYPE				 123
+#define SSL_R_BAD_SSL_SESSION_ID_LENGTH			 124
+#define SSL_R_BAD_STATE					 125
+#define SSL_R_BAD_WRITE_RETRY				 126
+#define SSL_R_BIO_NOT_SET				 127
+#define SSL_R_BLOCK_CIPHER_PAD_IS_WRONG			 128
+#define SSL_R_BN_LIB					 129
+#define SSL_R_CA_DN_LENGTH_MISMATCH			 130
+#define SSL_R_CA_DN_TOO_LONG				 131
+#define SSL_R_CCS_RECEIVED_EARLY			 132
+#define SSL_R_CERTIFICATE_VERIFY_FAILED			 133
+#define SSL_R_CERT_LENGTH_MISMATCH			 134
+#define SSL_R_CHALLENGE_IS_DIFFERENT			 135
+#define SSL_R_CIPHER_CODE_WRONG_LENGTH			 136
+#define SSL_R_CIPHER_OR_HASH_UNAVAILABLE		 137
+#define SSL_R_CIPHER_TABLE_SRC_ERROR			 138
+#define SSL_R_COMPRESSED_LENGTH_TOO_LONG		 139
+#define SSL_R_COMPRESSION_FAILURE			 140
+#define SSL_R_CONNECTION_ID_IS_DIFFERENT		 141
+#define SSL_R_DATA_BETWEEN_CCS_AND_FINISHED		 142
+#define SSL_R_DATA_LENGTH_TOO_LONG			 143
+#define SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG		 144
+#define SSL_R_DIGEST_CHECK_FAILED			 145
+#define SSL_R_ENCRYPTED_LENGTH_TOO_LONG			 146
+#define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST		 147
+#define SSL_R_EXCESSIVE_MESSAGE_SIZE			 148
+#define SSL_R_EXTRA_DATA_IN_MESSAGE			 149
+#define SSL_R_GOT_A_FIN_BEFORE_A_CCS			 150
+#define SSL_R_INTERNAL_ERROR				 151
+#define SSL_R_INVALID_CHALLENGE_LENGTH			 152
+#define SSL_R_LENGTH_MISMATCH				 153
+#define SSL_R_LENGTH_TOO_SHORT				 154
+#define SSL_R_LIBRARY_HAS_NO_CIPHERS			 155
+#define SSL_R_MISSING_DH_DSA_CERT			 156
+#define SSL_R_MISSING_DH_KEY				 157
+#define SSL_R_MISSING_DH_RSA_CERT			 158
+#define SSL_R_MISSING_DSA_SIGNING_CERT			 159
+#define SSL_R_MISSING_EXPORT_TMP_DH_KEY			 160
+#define SSL_R_MISSING_EXPORT_TMP_RSA_KEY		 161
+#define SSL_R_MISSING_RSA_CERTIFICATE			 162
+#define SSL_R_MISSING_RSA_ENCRYPTING_CERT		 163
+#define SSL_R_MISSING_RSA_SIGNING_CERT			 164
+#define SSL_R_MISSING_TMP_DH_KEY			 165
+#define SSL_R_MISSING_TMP_RSA_KEY			 166
+#define SSL_R_MISSING_TMP_RSA_PKEY			 167
+#define SSL_R_MISSING_VERIFY_MESSAGE			 168
+#define SSL_R_NON_SSLV2_INITIAL_PACKET			 169
+#define SSL_R_NO_CERTIFICATES_PASSED			 170
+#define SSL_R_NO_CERTIFICATE_ASSIGNED			 171
+#define SSL_R_NO_CERTIFICATE_RETURNED			 172
+#define SSL_R_NO_CERTIFICATE_SET			 173
+#define SSL_R_NO_CERTIFICATE_SPECIFIED			 174
+#define SSL_R_NO_CIPHERS_AVAILABLE			 175
+#define SSL_R_NO_CIPHERS_PASSED				 176
+#define SSL_R_NO_CIPHERS_SPECIFIED			 177
+#define SSL_R_NO_CIPHER_LIST				 178
+#define SSL_R_NO_CIPHER_MATCH				 179
+#define SSL_R_NO_CLIENT_CERT_RECEIVED			 180
+#define SSL_R_NO_COMPRESSION_SPECIFIED			 181
+#define SSL_R_NO_PRIVATEKEY				 182
+#define SSL_R_NO_PRIVATE_KEY_ASSIGNED			 183
+#define SSL_R_NO_PUBLICKEY				 184
+#define SSL_R_NO_SHARED_CIPHER				 185
+#define SSL_R_NULL_SSL_CTX				 186
+#define SSL_R_NULL_SSL_METHOD_PASSED			 187
+#define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED		 188
+#define SSL_R_PACKET_LENGTH_TOO_LONG			 189
+#define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE		 190
+#define SSL_R_PEER_ERROR				 191
+#define SSL_R_PEER_ERROR_CERTIFICATE			 192
+#define SSL_R_PEER_ERROR_NO_CERTIFICATE			 193
+#define SSL_R_PEER_ERROR_NO_CIPHER			 194
+#define SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE	 195
+#define SSL_R_PRE_MAC_LENGTH_TOO_LONG			 196
+#define SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS		 197
+#define SSL_R_PROTOCOL_IS_SHUTDOWN			 198
+#define SSL_R_PUBLIC_KEY_ENCRYPT_ERROR			 199
+#define SSL_R_PUBLIC_KEY_IS_NOT_RSA			 200
+#define SSL_R_PUBLIC_KEY_NOT_RSA			 201
+#define SSL_R_READ_BIO_NOT_SET				 202
+#define SSL_R_READ_WRONG_PACKET_TYPE			 203
+#define SSL_R_RECORD_LENGTH_MISMATCH			 204
+#define SSL_R_RECORD_TOO_LARGE				 205
+#define SSL_R_REQUIRED_CIPHER_MISSING			 206
+#define SSL_R_REUSE_CERT_LENGTH_NOT_ZERO		 207
+#define SSL_R_REUSE_CERT_TYPE_NOT_ZERO			 208
+#define SSL_R_REUSE_CIPHER_LIST_NOT_ZERO		 209
+#define SSL_R_SHORT_READ				 210
+#define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE	 211
+#define SSL_R_SSL3_SESSION_ID_TOO_SHORT			 212
+#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_PEER_ERROR_CERTIFICATE	 213
+#define SSL_R_SSLV3_ALERT_PEER_ERROR_NO_CERTIFICATE	 214
+#define SSL_R_SSLV3_ALERT_PEER_ERROR_NO_CIPHER		 215
+#define SSL_R_SSLV3_ALERT_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE 216
+#define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE		 1010
+#define SSL_R_SSLV3_ALERT_UNKNOWN_REMOTE_ERROR_TYPE	 217
+#define SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE	 1043
+#define SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION	 218
+#define SSL_R_SSL_HANDSHAKE_FAILURE			 219
+#define SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS		 220
+#define SSL_R_SSL_SESSION_ID_IS_DIFFERENT		 221
+#define SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER		 222
+#define SSL_R_UNABLE_TO_DECODE_DH_CERTS			 223
+#define SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY		 224
+#define SSL_R_UNABLE_TO_FIND_DH_PARAMETERS		 225
+#define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS	 226
+#define SSL_R_UNABLE_TO_FIND_SSL_METHOD			 227
+#define SSL_R_UNEXPECTED_MESSAGE			 228
+#define SSL_R_UNEXPECTED_RECORD				 229
+#define SSL_R_UNKNOWN_ALERT_TYPE			 230
+#define SSL_R_UNKNOWN_CERTIFICATE_TYPE			 231
+#define SSL_R_UNKNOWN_CIPHER_RETURNED			 232
+#define SSL_R_UNKNOWN_CIPHER_TYPE			 233
+#define SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE			 234
+#define SSL_R_UNKNOWN_PKEY_TYPE				 235
+#define SSL_R_UNKNOWN_PROTOCOL				 236
+#define SSL_R_UNKNOWN_REMOTE_ERROR_TYPE			 237
+#define SSL_R_UNKNOWN_SSL_VERSION			 238
+#define SSL_R_UNKNOWN_STATE				 239
+#define SSL_R_UNSUPPORTED_CIPHER			 240
+#define SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM		 241
+#define SSL_R_UNSUPPORTED_SSL_VERSION			 242
+#define SSL_R_WRITE_BIO_NOT_SET				 243
+#define SSL_R_WRONG_CIPHER_RETURNED			 244
+#define SSL_R_WRONG_MESSAGE_TYPE			 245
+#define SSL_R_WRONG_NUMBER_OF_KEY_BITS			 246
+#define SSL_R_WRONG_SIGNATURE_LENGTH			 247
+#define SSL_R_WRONG_SIGNATURE_SIZE			 248
+#define SSL_R_WRONG_SSL_VERSION				 249
+#define SSL_R_WRONG_VERSION_NUMBER			 250
+#define SSL_R_X509_LIB					 251
+ 
+#ifdef  __cplusplus
+}
+#endif
+#endif
+
diff --git a/ssl/ssl2.h b/ssl/ssl2.h
new file mode 100644
index 0000000..db353f5
--- /dev/null
+++ b/ssl/ssl2.h
@@ -0,0 +1,263 @@
+/* ssl/ssl2.h */
+/* Copyright (C) 1995-1997 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_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
+#define SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER	(unsigned int)32767 
+#define SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER	16383 /**/
+
+#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_ctx_st
+	{
+	int first_packet;	/* enable first packet checking in server */
+	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;
+	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 *pad_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;
+		int csl; 
+		int clear;
+		unsigned int enc; 
+		unsigned char ccl[SSL2_MAX_CERT_CHALLENGE_LENGTH];
+		int cipher_spec_length;
+		unsigned int session_id_length;
+		unsigned int clen;
+		unsigned int rlen;
+		} tmp;
+	} SSL2_CTX;
+
+/* 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/ssl/ssl23.h b/ssl/ssl23.h
new file mode 100644
index 0000000..6e6f26b
--- /dev/null
+++ b/ssl/ssl23.h
@@ -0,0 +1,83 @@
+/* ssl/ssl23.h */
+/* Copyright (C) 1995-1997 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/ssl/ssl3.h b/ssl/ssl3.h
new file mode 100644
index 0000000..9675ec2
--- /dev/null
+++ b/ssl/ssl3.h
@@ -0,0 +1,417 @@
+/* ssl/ssl3.h */
+/* Copyright (C) 1995-1997 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_SSL3_H 
+#define HEADER_SSL3_H 
+
+#include "buffer.h"
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#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_196_CBC_SHA		0x0300001B
+
+#define SSL3_CK_FZA_DMS_NULL_SHA		0x0300001C
+#define SSL3_CK_FZA_DMS_FZA_SHA			0x0300001D
+#define SSL3_CK_FZA_DMS_RC4_SHA			0x0300001E
+
+#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-MD5"
+#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"
+#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_196_CBC_SHA		"ADH-DES-CBC3-SHA"
+
+#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"
+
+#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
+
+/* Due to MS stuffing up, this can change.... */
+#if defined(WIN16) || (defined(MSDOS) && !defined(WIN32))
+#define SSL3_RT_MAX_EXTRA			(14000)
+#else
+#define SSL3_RT_MAX_EXTRA			(16384)
+#endif
+
+#define SSL3_RT_MAX_PLAIN_LENGTH		16384
+#define SSL3_RT_MAX_COMPRESSED_LENGTH	(1024+SSL3_RT_MAX_PLAIN_LENGTH)
+#define SSL3_RT_MAX_ENCRYPTED_LENGTH	(1024+SSL3_RT_MAX_COMPRESSED_LENGTH)
+#define SSL3_RT_MAX_PACKET_SIZE		(SSL3_RT_MAX_ENCRYPTED_LENGTH+SSL3_RT_HEADER_LENGTH)
+#define SSL3_RT_MAX_DATA_SIZE			(1024*1024)
+
+/* the states that a SSL3_RECORD can be in
+ * For SSL_read it goes
+ * rbuf->ENCODED	-> read 
+ * ENCODED		-> we need to decode everything - call decode_record
+ */
+ 
+#define SSL3_RS_BLANK			1
+#define SSL3_RS_DATA
+
+#define SSL3_RS_ENCODED			2
+#define SSL3_RS_READ_MORE		3
+#define SSL3_RS_WRITE_MORE
+#define SSL3_RS_PLAIN			3
+#define SSL3_RS_PART_READ		4
+#define SSL3_RS_PART_WRITE		5
+
+#define SSL3_MD_CLIENT_FINISHED_CONST	0x43,0x4C,0x4E,0x54
+#define SSL3_MD_SERVER_FINISHED_CONST	0x53,0x52,0x56,0x52
+
+#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 */
+/*  */	/*int state;*/		/* any data in it? */
+/*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 */
+/*rw*/	unsigned char *comp;	/* only used with decompression */
+	} SSL3_RECORD;
+
+typedef struct ssl3_buffer_st
+	{
+/*r */	int total;		/* used in non-blocking writes */
+/*r */	int wanted;		/* how many more bytes we need */
+/*rw*/	int left;		/* how many bytes left */
+/*rw*/	int offset;		/* where to 'copy from' */
+/*rw*/	unsigned char *buf;	/* SSL3_RT_MAX_PACKET_SIZE bytes */
+	} SSL3_BUFFER;
+
+typedef struct ssl3_compression_st {
+	int nothing;
+	} SSL3_COMPRESSION;
+
+#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
+#define SSL3_CT_NUMBER				7
+
+#define SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS	0x0001
+#define SSL3_FLAGS_DELAY_CLIENT_FINISHED	0x0002
+#define SSL3_FLAGS_POP_BUFFER			0x0004
+
+typedef struct ssl3_ctx_st
+	{
+	long flags;
+	int delay_buf_pop_ret;
+
+	unsigned char read_sequence[8];
+	unsigned char read_mac_secret[EVP_MAX_MD_SIZE];
+	unsigned char write_sequence[8];
+	unsigned char write_mac_secret[EVP_MAX_MD_SIZE];
+
+	unsigned char server_random[SSL3_RANDOM_SIZE];
+	unsigned char client_random[SSL3_RANDOM_SIZE];
+
+	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 */
+				/* Used by ssl3_read_n to point
+				 * to input data packet */
+
+	/* 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 */
+	char *wpend_buf;
+
+	/* used during startup, digest all incoming/outgoing packets */
+	EVP_MD_CTX finish_dgst1;
+	EVP_MD_CTX finish_dgst2;
+
+	/* 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 alow one fatal and one warning alert to be outstanding,
+	 * send close alert via the warning alert */
+	int alert_dispatch;
+	char send_alert[2];
+
+	struct	{
+		unsigned char finish_md1[EVP_MAX_MD_SIZE];
+		unsigned char finish_md2[EVP_MAX_MD_SIZE];
+		
+		unsigned long message_size;
+		int message_type;
+
+		/* used to hold the new cipher we are going to use */
+		SSL_CIPHER *new_cipher;
+		DH *dh;
+
+		/* 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 *ca_names;
+
+		int use_rsa_tmp;
+
+		int key_block_length;
+		unsigned char *key_block;
+
+		EVP_CIPHER *new_sym_enc;
+		EVP_MD *new_hash;
+		SSL_COMPRESSION *new_compression;
+		} tmp;
+	} SSL3_CTX;
+
+/* SSLv3 */
+/*client */
+/* extra state */
+#define SSL3_ST_CW_FLUSH		(0x100|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 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)
+
+/* server */
+/* extra state */
+#define SSL3_ST_SW_FLUSH		(0x100|SSL_ST_ACCEPT)
+/* read from client */
+#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 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_MT_CLIENT_REQUEST			0
+#define SSL3_MT_CLIENT_HELLO			1
+#define SSL3_MT_SERVER_HELLO			2
+#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_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/ssl/ssl_algs.c b/ssl/ssl_algs.c
new file mode 100644
index 0000000..36b0333
--- /dev/null
+++ b/ssl/ssl_algs.c
@@ -0,0 +1,99 @@
+/* ssl/ssl_algs.c */
+/* Copyright (C) 1995-1997 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 "objects.h"
+#include "lhash.h"
+#include "ssl_locl.h"
+
+void SSLeay_add_ssl_algorithms()
+	{
+#ifndef NO_DES
+	EVP_add_cipher(EVP_des_cbc());
+	EVP_add_cipher(EVP_des_ede3_cbc());
+#endif
+#ifndef NO_IDEA
+	EVP_add_cipher(EVP_idea_cbc());
+#endif
+#ifndef NO_RC4
+        EVP_add_cipher(EVP_rc4());
+#endif  
+#ifndef NO_RC2
+        EVP_add_cipher(EVP_rc2_cbc());
+#endif  
+
+#ifndef NO_MD2
+        EVP_add_digest(EVP_md2());
+#endif
+#ifndef NO_MD5
+	EVP_add_digest(EVP_md5());
+#endif
+#ifndef NO_SHA1
+	EVP_add_digest(EVP_sha1()); /* RSA with sha1 */
+#endif
+#if !defined(NO_SHA1) && !defined(NO_DSA)
+	EVP_add_digest(EVP_dss1()); /* DSA with sha1 */
+#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
+	}
+
diff --git a/ssl/ssl_asn1.c b/ssl/ssl_asn1.c
new file mode 100644
index 0000000..873497a
--- /dev/null
+++ b/ssl/ssl_asn1.c
@@ -0,0 +1,313 @@
+/* ssl/ssl_asn1.c */
+/* Copyright (C) 1995-1997 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 "asn1_mac.h"
+#include "objects.h"
+#include "ssl_locl.h"
+
+typedef struct ssl_session_asn1_st
+	{
+	ASN1_INTEGER version;
+	ASN1_INTEGER ssl_version;
+	ASN1_OCTET_STRING cipher;
+	ASN1_OCTET_STRING master_key;
+	ASN1_OCTET_STRING session_id;
+	ASN1_OCTET_STRING key_arg;
+	ASN1_INTEGER time;
+	ASN1_INTEGER timeout;
+	} SSL_SESSION_ASN1;
+
+/*
+ * SSLerr(SSL_F_I2D_SSL_SESSION,SSL_R_CIPHER_CODE_WRONG_LENGTH);
+ * SSLerr(SSL_F_D2I_SSL_SESSION,SSL_R_UNSUPPORTED_CIPHER);
+ */
+
+int i2d_SSL_SESSION(in,pp)
+SSL_SESSION *in;
+unsigned char **pp;
+	{
+#define LSIZE2 (sizeof(long)*2)
+	int v1=0,v2=0,v3=0;
+	unsigned char buf[4],ibuf1[LSIZE2],ibuf2[LSIZE2];
+	unsigned char ibuf3[LSIZE2],ibuf4[LSIZE2];
+	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_INTERGER passed to ASN1_INTEGER_set
+	 * is > sizeof(long)+1, the buffer will not be re-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 == 2)
+		{
+		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;
+		}
+
+	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.key_arg.length=in->key_arg_length;
+	a.key_arg.type=V_ASN1_OCTET_STRING;
+	a.key_arg.data=in->key_arg;
+
+	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);
+		}
+
+	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);
+	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_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);
+	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_finish();
+	}
+
+SSL_SESSION *d2i_SSL_SESSION(a,pp,length)
+SSL_SESSION **a;
+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(aip,d2i_ASN1_INTEGER);
+	version=(int)ASN1_INTEGER_get(aip);
+	if (ai.data != NULL) { Free(ai.data); ai.data=NULL; ai.length=0; }
+
+	/* we don't care about the version right now :-) */
+	M_ASN1_D2I_get(aip,d2i_ASN1_INTEGER);
+	ssl_version=(int)ASN1_INTEGER_get(aip);
+	ret->ssl_version=ssl_version;
+	if (ai.data != NULL) { Free(ai.data); ai.data=NULL; ai.length=0; }
+
+	os.data=NULL; os.length=0;
+	M_ASN1_D2I_get(osp,d2i_ASN1_OCTET_STRING);
+	if (ssl_version == 2)
+		{
+		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 == 3)
+		{
+		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
+		{
+		SSLerr(SSL_F_D2I_SSL_SESSION,SSL_R_UNKNOWN_SSL_VERSION);
+		return(NULL);
+		}
+	
+	ret->cipher=NULL;
+	ret->cipher_id=id;
+
+	M_ASN1_D2I_get(osp,d2i_ASN1_OCTET_STRING);
+	if (ssl_version == 3)
+		i=SSL3_MAX_SSL_SESSION_ID_LENGTH;
+	else /* if (ssl_version == 2) */
+		i=SSL2_MAX_SSL_SESSION_ID_LENGTH;
+
+	if (os.length > i)
+		os.length=i;
+
+	ret->session_id_length=os.length;
+	memcpy(ret->session_id,os.data,os.length);
+
+	M_ASN1_D2I_get(osp,d2i_ASN1_OCTET_STRING);
+	if (ret->master_key_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;
+	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) 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);
+		Free(ai.data); ai.data=NULL; ai.length=0;
+		}
+	else
+		ret->time=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);
+		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);
+
+	M_ASN1_D2I_Finish(a,SSL_SESSION_free,SSL_F_D2I_SSL_SESSION);
+	}
+
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
new file mode 100644
index 0000000..0c040d9
--- /dev/null
+++ b/ssl/ssl_cert.c
@@ -0,0 +1,326 @@
+/* ssl/ssl_cert.c */
+/* Copyright (C) 1995-1997 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 "objects.h"
+#include "bio.h"
+#include "pem.h"
+#include "ssl_locl.h"
+
+CERT *ssl_cert_new()
+	{
+	CERT *ret;
+
+	ret=(CERT *)Malloc(sizeof(CERT));
+	if (ret == NULL)
+		{
+		SSLerr(SSL_F_SSL_CERT_NEW,ERR_R_MALLOC_FAILURE);
+		return(NULL);
+		}
+	memset(ret,0,sizeof(CERT));
+/*
+	ret->valid=0;
+	ret->mask=0;
+	ret->export_mask=0;
+	ret->cert_type=0;
+	ret->key->x509=NULL;
+	ret->key->publickey=NULL;
+	ret->key->privatekey=NULL; */
+
+	ret->key= &(ret->pkeys[SSL_PKEY_RSA_ENC]);
+	ret->references=1;
+
+	return(ret);
+	}
+
+void ssl_cert_free(c)
+CERT *c;
+	{
+	int i;
+
+	i=CRYPTO_add(&c->references,-1,CRYPTO_LOCK_SSL_CERT);
+	if (i > 0) return;
+#ifdef REF_CHECK
+	if (i < 0)
+		{
+		fprintf(stderr,"ssl_cert_free, bad reference count\n");
+		abort(); /* ok */
+		}
+#endif
+
+#ifndef NO_RSA
+	if (c->rsa_tmp) RSA_free(c->rsa_tmp);
+#endif
+#ifndef NO_DH
+	if (c->dh_tmp) DH_free(c->dh_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
+		}
+	if (c->cert_chain != NULL)
+		sk_pop_free(c->cert_chain,X509_free);
+	Free(c);
+	}
+
+int ssl_set_cert_type(c, type)
+CERT *c;
+int type;
+	{
+	c->cert_type=type;
+	return(1);
+	}
+
+int ssl_verify_cert_chain(s,sk)
+SSL *s;
+STACK *sk;
+	{
+	X509 *x;
+	int i;
+	X509_STORE_CTX ctx;
+
+	if ((sk == NULL) || (sk_num(sk) == 0))
+		return(0);
+
+	x=(X509 *)sk_value(sk,0);
+	X509_STORE_CTX_init(&ctx,s->ctx->cert_store,x,sk);
+	X509_STORE_CTX_set_app_data(&ctx,(char *)s);
+
+	if (s->ctx->app_verify_callback != NULL)
+		i=s->ctx->app_verify_callback(&ctx);
+	else
+		i=X509_verify_cert(&ctx);
+
+	X509_STORE_CTX_cleanup(&ctx);
+	s->verify_result=ctx.error;
+
+	return(i);
+	}
+
+static void set_client_CA_list(ca_list,list)
+STACK **ca_list;
+STACK *list;
+	{
+	if (*ca_list != NULL)
+		sk_pop_free(*ca_list,X509_NAME_free);
+
+	*ca_list=list;
+	}
+
+STACK *SSL_dup_CA_list(sk)
+STACK *sk;
+	{
+	int i;
+	STACK *ret;
+	X509_NAME *name;
+
+	ret=sk_new_null();
+	for (i=0; i<sk_num(sk); i++)
+		{
+		name=X509_NAME_dup((X509_NAME *)sk_value(sk,i));
+		if ((name == NULL) || !sk_push(ret,(char *)name))
+			{
+			sk_pop_free(ret,X509_NAME_free);
+			return(NULL);
+			}
+		}
+	return(ret);
+	}
+
+void SSL_set_client_CA_list(s,list)
+SSL *s;
+STACK *list;
+	{
+	set_client_CA_list(&(s->client_CA),list);
+	}
+
+void SSL_CTX_set_client_CA_list(ctx,list)
+SSL_CTX *ctx;
+STACK *list;
+	{
+	set_client_CA_list(&(ctx->client_CA),list);
+	}
+
+STACK *SSL_CTX_get_client_CA_list(ctx)
+SSL_CTX *ctx;
+	{
+	return(ctx->client_CA);
+	}
+
+STACK *SSL_get_client_CA_list(s)
+SSL *s;
+	{
+	if (s->type == SSL_ST_CONNECT)
+		{ /* we are in the client */
+		if ((s->version == 3) && (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(sk,x)
+STACK **sk;
+X509 *x;
+	{
+	X509_NAME *name;
+
+	if (x == NULL) return(0);
+	if ((*sk == NULL) && ((*sk=sk_new_null()) == NULL))
+		return(0);
+		
+	if ((name=X509_NAME_dup(X509_get_subject_name(x))) == NULL)
+		return(0);
+
+	if (!sk_push(*sk,(char *)name))
+		{
+		X509_NAME_free(name);
+		return(0);
+		}
+	return(1);
+	}
+
+int SSL_add_client_CA(ssl,x)
+SSL *ssl;
+X509 *x;
+	{
+	return(add_client_CA(&(ssl->client_CA),x));
+	}
+
+int SSL_CTX_add_client_CA(ctx,x)
+SSL_CTX *ctx;
+X509 *x;
+	{
+	return(add_client_CA(&(ctx->client_CA),x));
+	}
+
+static int name_cmp(a,b)
+X509_NAME **a,**b;
+	{
+	return(X509_NAME_cmp(*a,*b));
+	}
+
+STACK *SSL_load_client_CA_file(file)
+char *file;
+	{
+	BIO *in;
+	X509 *x=NULL;
+	X509_NAME *xn=NULL;
+	STACK *ret,*sk;
+
+	ret=sk_new(NULL);
+	sk=sk_new(name_cmp);
+#ifdef WIN16
+	in=BIO_new(BIO_s_file_internal_w16());
+#else
+	in=BIO_new(BIO_s_file());
+#endif
+	if ((ret == NULL) || (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)
+			break;
+		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_find(sk,(char *)xn) >= 0)
+			X509_NAME_free(xn);
+		else
+			{
+			sk_push(sk,(char *)xn);
+			sk_push(ret,(char *)xn);
+			}
+		}
+
+	if (0)
+		{
+err:
+		if (ret != NULL) sk_pop_free(ret,X509_NAME_free);
+		ret=NULL;
+		}
+	if (sk != NULL) sk_free(sk);
+	if (in != NULL) BIO_free(in);
+	if (x != NULL) X509_free(x);
+	return(ret);
+	}
+
+
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
new file mode 100644
index 0000000..9fed3ad
--- /dev/null
+++ b/ssl/ssl_ciph.c
@@ -0,0 +1,721 @@
+/* ssl/ssl_ciph.c */
+/* Copyright (C) 1995-1997 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 "objects.h"
+#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_eFZA_IDX	5
+#define SSL_ENC_NULL_IDX	6
+#define SSL_ENC_NUM_IDX		7
+
+static EVP_CIPHER *ssl_cipher_methods[SSL_ENC_NUM_IDX]={
+	NULL,NULL,NULL,NULL,NULL,NULL,
+	};
+
+#define SSL_MD_MD5_IDX	0
+#define SSL_MD_SHA0_IDX	1
+#define SSL_MD_SHA1_IDX	2
+#define SSL_MD_NUM_IDX	3
+static EVP_MD *ssl_digest_methods[SSL_MD_NUM_IDX]={
+	NULL,NULL,NULL,
+	};
+
+typedef struct cipher_sort_st
+	{
+	SSL_CIPHER *cipher;
+	int pref;
+	} CIPHER_SORT;
+
+#define CIPHER_ADD	1
+#define CIPHER_KILL	2
+#define CIPHER_DEL	3
+#define CIPHER_ORDER	4
+
+typedef struct cipher_choice_st
+	{
+	int type;
+	unsigned long algorithms;
+	unsigned long mask;
+	STACK *order;
+	} CIPHER_CHOICE;
+
+static SSL_CIPHER cipher_aliases[]={
+	{0,SSL_TXT_ALL, 0,SSL_ALL,   0,SSL_ALL},	/* must be first */
+	{0,SSL_TXT_kRSA,0,SSL_kRSA,  0,SSL_MKEY_MASK},
+	{0,SSL_TXT_kDHr,0,SSL_kDHr,  0,SSL_MKEY_MASK},
+	{0,SSL_TXT_kDHd,0,SSL_kDHd,  0,SSL_MKEY_MASK},
+	{0,SSL_TXT_kEDH,0,SSL_kEDH,  0,SSL_MKEY_MASK},
+	{0,SSL_TXT_kFZA,0,SSL_kFZA,  0,SSL_MKEY_MASK},
+	{0,SSL_TXT_DH,	0,SSL_DH,    0,SSL_MKEY_MASK},
+	{0,SSL_TXT_EDH,	0,SSL_EDH,   0,SSL_MKEY_MASK|SSL_AUTH_MASK},
+
+	{0,SSL_TXT_aRSA,0,SSL_aRSA,  0,SSL_AUTH_MASK},
+	{0,SSL_TXT_aDSS,0,SSL_aDSS,  0,SSL_AUTH_MASK},
+	{0,SSL_TXT_aFZA,0,SSL_aFZA,  0,SSL_AUTH_MASK},
+	{0,SSL_TXT_aNULL,0,SSL_aNULL,0,SSL_AUTH_MASK},
+	{0,SSL_TXT_aDH, 0,SSL_aDH,   0,SSL_AUTH_MASK},
+	{0,SSL_TXT_DSS,	0,SSL_DSS,   0,SSL_AUTH_MASK},
+
+	{0,SSL_TXT_DES,	0,SSL_DES,   0,SSL_ENC_MASK},
+	{0,SSL_TXT_3DES,0,SSL_3DES,  0,SSL_ENC_MASK},
+	{0,SSL_TXT_RC4,	0,SSL_RC4,   0,SSL_ENC_MASK},
+	{0,SSL_TXT_RC2,	0,SSL_RC2,   0,SSL_ENC_MASK},
+	{0,SSL_TXT_IDEA,0,SSL_IDEA,  0,SSL_ENC_MASK},
+	{0,SSL_TXT_eNULL,0,SSL_eNULL,0,SSL_ENC_MASK},
+	{0,SSL_TXT_eFZA,0,SSL_eFZA,  0,SSL_ENC_MASK},
+
+	{0,SSL_TXT_MD5,	0,SSL_MD5,   0,SSL_MAC_MASK},
+	{0,SSL_TXT_SHA0,0,SSL_SHA0,  0,SSL_MAC_MASK},
+	{0,SSL_TXT_SHA1,0,SSL_SHA1,  0,SSL_MAC_MASK},
+	{0,SSL_TXT_SHA,	0,SSL_SHA,   0,SSL_MAC_MASK},
+
+	{0,SSL_TXT_NULL,0,SSL_NULL,  0,SSL_ENC_MASK},
+	{0,SSL_TXT_RSA,	0,SSL_RSA,   0,SSL_AUTH_MASK|SSL_MKEY_MASK},
+	{0,SSL_TXT_ADH,	0,SSL_ADH,   0,SSL_AUTH_MASK|SSL_MKEY_MASK},
+	{0,SSL_TXT_FZA,	0,SSL_FZA,   0,SSL_AUTH_MASK|SSL_MKEY_MASK|SSL_ENC_MASK},
+
+	{0,SSL_TXT_EXP,	0,SSL_EXP,   0,SSL_EXP_MASK},
+	{0,SSL_TXT_EXPORT,0,SSL_EXPORT,0,SSL_EXP_MASK},
+	{0,SSL_TXT_SSLV2,0,SSL_SSLV2,0,SSL_SSL_MASK},
+	{0,SSL_TXT_SSLV3,0,SSL_SSLV3,0,SSL_SSL_MASK},
+	{0,SSL_TXT_LOW,  0,SSL_LOW,0,SSL_STRONG_MASK},
+	{0,SSL_TXT_MEDIUM,0,SSL_MEDIUM,0,SSL_STRONG_MASK},
+	{0,SSL_TXT_HIGH, 0,SSL_HIGH,0,SSL_STRONG_MASK},
+	};
+
+static int init_ciphers=1;
+static void load_ciphers();
+
+static int cmp_by_name(a,b)
+SSL_CIPHER **a,**b;
+	{
+	return(strcmp((*a)->name,(*b)->name));
+	}
+
+static void load_ciphers()
+	{
+	init_ciphers=0;
+	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);
+	ssl_cipher_methods[SSL_ENC_IDEA_IDX]= 
+		EVP_get_cipherbyname(SN_idea_cbc);
+
+	ssl_digest_methods[SSL_MD_MD5_IDX]=
+		EVP_get_digestbyname(SN_md5);
+	ssl_digest_methods[SSL_MD_SHA0_IDX]=
+		EVP_get_digestbyname(SN_sha);
+	ssl_digest_methods[SSL_MD_SHA1_IDX]=
+		EVP_get_digestbyname(SN_sha1);
+	}
+
+int ssl_cipher_get_evp(c,enc,md)
+SSL_CIPHER *c;
+EVP_CIPHER **enc;
+EVP_MD **md;
+	{
+	int i;
+
+	if (c == NULL) return(0);
+
+	switch (c->algorithms & SSL_ENC_MASK)
+		{
+	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;
+		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->algorithms & SSL_MAC_MASK)
+		{
+	case SSL_MD5:
+		i=SSL_MD_MD5_IDX;
+		break;
+	case SSL_SHA0:
+		i=SSL_MD_SHA0_IDX;
+		break;
+	case SSL_SHA1:
+		i=SSL_MD_SHA1_IDX;
+		break;
+	default:
+		i= -1;
+		break;
+		}
+	if ((i < 0) || (i > SSL_MD_NUM_IDX))
+		*md=NULL;
+	else
+		*md=ssl_digest_methods[i];
+
+	if ((*enc != NULL) && (*md != NULL))
+		return(1);
+	else
+		return(0);
+	}
+
+STACK *ssl_create_cipher_list(ssl_method,cipher_list,cipher_list_by_id,str)
+SSL_METHOD *ssl_method;
+STACK **cipher_list,**cipher_list_by_id;
+char *str;
+	{
+	SSL_CIPHER *c;
+	char *l;
+	STACK *ret=NULL,*ok=NULL;
+#define CL_BUF	40
+	char buf[CL_BUF];
+	char *tmp_str=NULL;
+	unsigned long mask,algorithms,ma;
+	char *start;
+	int i,j,k,num=0,ch,multi;
+	unsigned long al;
+	STACK *ca_list=NULL;
+	STACK *c_list=NULL;
+	int old_x,old_y,current_x,num_x;
+	CIPHER_CHOICE *ops=NULL;
+	SSL_CIPHER c_tmp,*cp;
+
+	if (str == NULL) return(NULL);
+
+	if (strncmp(str,"DEFAULT",7) == 0)
+		{
+		i=strlen(str)+2+strlen(SSL_DEFAULT_CIPHER_LIST);
+		if ((tmp_str=Malloc(i)) == NULL)
+			{
+			SSLerr(SSL_F_SSL_CREATE_CIPHER_LIST,ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+		strcpy(tmp_str,SSL_DEFAULT_CIPHER_LIST);
+		strcat(tmp_str,&(str[7]));
+		str=tmp_str;
+		}
+	if (init_ciphers) load_ciphers();
+
+	num=ssl_method->num_ciphers();
+
+	if ((ret=(STACK *)sk_new(NULL)) == NULL) goto err;
+	if ((c_list=(STACK *)sk_new(NULL)) == NULL) goto err;
+	if ((ca_list=(STACK *)sk_new(cmp_by_name)) == NULL) goto err;
+
+	mask =SSL_kFZA;
+#ifdef NO_RSA
+	mask|=SSL_aRSA|SSL_kRSA;
+#endif
+#ifdef NO_DSA
+	mask|=SSL_aDSS;
+#endif
+#ifdef NO_DH
+	mask|=SSL_kDHr|SSL_kDHd|SSL_kEDH|SSL_aDH;
+#endif
+
+#ifndef SSL_ALLOW_ENULL
+	mask|=SSL_eNULL;
+#endif
+
+	mask|=(ssl_cipher_methods[SSL_ENC_DES_IDX ] == NULL)?SSL_DES :0;
+	mask|=(ssl_cipher_methods[SSL_ENC_3DES_IDX] == NULL)?SSL_3DES:0;
+	mask|=(ssl_cipher_methods[SSL_ENC_RC4_IDX ] == NULL)?SSL_RC4 :0;
+	mask|=(ssl_cipher_methods[SSL_ENC_RC2_IDX ] == NULL)?SSL_RC2 :0;
+	mask|=(ssl_cipher_methods[SSL_ENC_IDEA_IDX] == NULL)?SSL_IDEA:0;
+	mask|=(ssl_cipher_methods[SSL_ENC_eFZA_IDX] == NULL)?SSL_eFZA:0;
+
+	mask|=(ssl_digest_methods[SSL_MD_MD5_IDX ] == NULL)?SSL_MD5 :0;
+	mask|=(ssl_digest_methods[SSL_MD_SHA0_IDX] == NULL)?SSL_SHA0:0;
+	mask|=(ssl_digest_methods[SSL_MD_SHA1_IDX] == NULL)?SSL_SHA1:0;
+
+	/* Get the initial list of ciphers */
+	for (i=0; i<num; i++)
+		{
+		c=ssl_method->get_cipher((unsigned int)i);
+		/* drop those that use any of that is not available */
+		if ((c != NULL) && c->valid && !(c->algorithms & mask))
+			{
+			if (!sk_push(c_list,(char *)c)) goto err;
+			if (!sk_push(ca_list,(char *)c)) goto err;
+			}
+		}
+
+	/* special case */
+	cipher_aliases[0].algorithms= ~mask;
+
+	/* get the aliases */
+	k=sizeof(cipher_aliases)/sizeof(SSL_CIPHER);
+	for (j=0; j<k; j++)
+		{
+		al=cipher_aliases[j].algorithms;
+		/* Drop those that are not relevent */
+		if ((al & mask) == al) continue;
+		if (!sk_push(ca_list,(char *)&(cipher_aliases[j]))) goto err;
+		}
+
+	/* ca_list now holds a 'stack' of SSL_CIPHERS, some real, some
+	 * 'aliases' */
+
+	/* how many parameters are there? */
+	num=1;
+	for (l=str; *l; l++)
+		if (*l == ':') num++;
+	ops=(CIPHER_CHOICE *)Malloc(sizeof(CIPHER_CHOICE)*num);
+	if (ops == NULL) goto err;
+	memset(ops,0,sizeof(CIPHER_CHOICE)*num);
+	for (i=0; i<num; i++)
+		if ((ops[i].order=sk_new_null()) == NULL) goto err;
+
+	/* we now parse the input string and create our operations */
+	l=str;
+	i=0;
+	current_x=0;
+
+	for (;;)
+		{
+		ch= *l;
+		if (ch == '-')
+			{ j=CIPHER_DEL; l++; }
+		else if (ch == '+')
+			{ j=CIPHER_ORDER; l++; }
+		else if (ch == '!')
+			{ j=CIPHER_KILL; l++; }
+		else	
+			{ j=CIPHER_ADD; }
+
+		if (*l == ':')
+			{
+			l++;
+			continue;
+			}
+		ops[current_x].type=j;
+		ops[current_x].algorithms=0;
+		ops[current_x].mask=0;
+
+		start=l;
+		for (;;)
+			{
+			ch= *l;
+			i=0;
+			while (	((ch >= 'A') && (ch <= 'Z')) ||
+				((ch >= '0') && (ch <= '9')) ||
+				((ch >= 'a') && (ch <= 'z')) ||
+				 (ch == '-'))
+				 {
+				 buf[i]=ch;
+				 ch= *(++l);
+				 i++;
+				 if (i >= (CL_BUF-2)) break;
+				 }
+			buf[i]='\0';
+			if (ch != '\0') l++;
+
+			/* check for multi-part specification */
+			multi=(ch == '+')?1:0;
+
+			c_tmp.name=buf;
+			j=sk_find(ca_list,(char *)&c_tmp);
+			if (j < 0)
+				{
+				if (ch == '\0')
+					break;
+				else
+					continue;
+				}
+
+			cp=(SSL_CIPHER *)sk_value(ca_list,j);
+			ops[current_x].algorithms|=cp->algorithms;
+			/* We add the SSL_SSL_MASK so we can match the
+			 * SSLv2 and SSLv3 versions of RC4-MD5 */
+			ops[current_x].mask|=cp->mask;
+			if (!multi) break;
+			}
+		current_x++;
+		if (ch == '\0') break;
+		}
+
+	num_x=current_x;
+	current_x=0;
+
+#ifdef CIPHER_DEBUG
+	printf("<--->\n");
+#endif
+
+	for (i=0; i<sk_num(c_list); i++)
+		{
+		old_x= -1;
+		old_y= -1;
+		cp=(SSL_CIPHER *)sk_value(c_list,i);
+#ifdef CIPHER_DEBUG
+		printf("[%s]\n",cp->name);
+#endif
+		for (j=0; j<num_x; j++)
+			{
+			algorithms=ops[j].algorithms;
+			ma=ops[j].mask & cp->algorithms;
+#ifdef CIPHER_DEBUG
+			printf("  %s %08lX&%08lX==0 || %08lX != %08lX \n",
+				cp->name,ops[j].mask,cp->algorithms,ma,algorithms);
+#endif
+			if ((ma == 0) || ((ma & algorithms) != ma))
+				{
+				continue;
+				}
+			k=ops[j].type;
+#ifdef CIPHER_DEBUG
+			printf(">>%s\n",cp->name);
+#endif
+
+			/* add the cipher if it has not been added yet. */
+			if (k == CIPHER_ADD)
+				{
+				if (old_x < 0)
+					{
+					old_x=j;
+					old_y=sk_num(ops[j].order);
+					sk_push(ops[j].order,(char *)cp);
+					}
+				}
+			/* Move the added cipher to this location */
+			else if (k == CIPHER_ORDER)
+				{
+				if (old_x >= 0)
+					{
+					sk_value(ops[old_x].order,old_y)=NULL;
+					old_y=sk_num(ops[j].order);
+					sk_push(ops[j].order,(char *)cp);
+					old_x=j;
+					}
+				}
+			/* Remove added cipher */
+			else if ((k == CIPHER_DEL) || (k == CIPHER_KILL))
+				{
+				if (old_x >= 0)
+					{
+					sk_value(ops[old_x].order,old_y)=NULL;
+					old_x= -1;
+					}
+				if (k == CIPHER_KILL)
+					break;
+				}
+			}
+		}
+
+	for (i=0; i<num_x; i++)
+		{
+		for (j=0; j<sk_num(ops[i].order); j++)
+			{
+			cp=(SSL_CIPHER *)sk_value(ops[i].order,j);
+			if (cp != NULL)
+				{
+				sk_push(ret,(char *)cp);
+#ifdef CIPHER_DEBUG
+				printf("<%s>\n",cp->name);
+#endif
+				}
+			}
+		}
+
+	if (cipher_list != NULL)
+		{
+		if (*cipher_list != NULL)
+			sk_free(*cipher_list);
+		*cipher_list=ret;
+		}
+
+	if (cipher_list_by_id != NULL)
+		{
+		if (*cipher_list_by_id != NULL)
+			sk_free(*cipher_list_by_id);
+		*cipher_list_by_id=sk_dup(ret);
+		}
+
+	if (	(cipher_list_by_id == NULL) ||
+		(*cipher_list_by_id == NULL) ||
+		(cipher_list == NULL) ||
+		(*cipher_list == NULL))
+		goto err;
+	sk_set_cmp_func(*cipher_list_by_id,ssl_cipher_ptr_id_cmp);
+
+	ok=ret;
+	ret=NULL;
+err:
+	if (tmp_str) Free(tmp_str);
+	if (ops != NULL)
+		{
+		for (i=0; i<num; i++)
+			if (ops[i].order != NULL)
+				sk_free(ops[i].order);
+		Free(ops);
+		}
+	if (ret != NULL) sk_free(ret);
+	if (c_list != NULL) sk_free(c_list);
+	if (ca_list != NULL) sk_free(ca_list);
+	return(ok);
+	}
+
+char *SSL_CIPHER_description(cipher,buf,len)
+SSL_CIPHER *cipher;
+char *buf;
+int len;
+	{
+	int export;
+	char *ver,*exp;
+	char *kx,*au,*enc,*mac;
+	unsigned long alg,alg2;
+	static char *format="%-23s %s Kx=%-8s Au=%-4s Enc=%-9s Mac=%-4s%s\n";
+	
+	alg=cipher->algorithms;
+	alg2=cipher->algorithm2;
+
+	export=(alg&SSL_EXP)?1:0;
+	exp=(export)?" export":"";
+
+	if (alg & SSL_SSLV2)
+		ver="SSLv2";
+	else if (alg & SSL_SSLV3)
+		ver="SSLv3";
+	else
+		ver="unknown";
+
+	switch (alg&SSL_MKEY_MASK)
+		{
+	case SSL_kRSA:
+		kx=(export)?"RSA(512)":"RSA";
+		break;
+	case SSL_kDHr:
+		kx="DH/RSA";
+		break;
+	case SSL_kDHd:
+		kx="DH/DSS";
+		break;
+	case SSL_kFZA:
+		kx="Fortezza";
+		break;
+	case SSL_kEDH:
+		kx=(export)?"DH(512)":"DH";
+		break;
+	default:
+		kx="unknown";
+		}
+
+	switch (alg&SSL_AUTH_MASK)
+		{
+	case SSL_aRSA:
+		au="RSA";
+		break;
+	case SSL_aDSS:
+		au="DSS";
+		break;
+	case SSL_aDH:
+		au="DH";
+		break;
+	case SSL_aFZA:
+	case SSL_aNULL:
+		au="None";
+		break;
+	default:
+		au="unknown";
+		break;
+		}
+
+	switch (alg&SSL_ENC_MASK)
+		{
+	case SSL_DES:
+		enc=export?"DES(40)":"DES(56)";
+		break;
+	case SSL_3DES:
+		enc="3DES(168)";
+		break;
+	case SSL_RC4:
+		enc=export?"RC4(40)":((alg2&SSL2_CF_8_BYTE_ENC)?"RC4(64)":"RC4(128)");
+		break;
+	case SSL_RC2:
+		enc=export?"RC2(40)":"RC2(128)";
+		break;
+	case SSL_IDEA:
+		enc="IDEA(128)";
+		break;
+	case SSL_eFZA:
+		enc="Fortezza";
+		break;
+	case SSL_eNULL:
+		enc="None";
+		break;
+	default:
+		enc="unknown";
+		break;
+		}
+
+	switch (alg&SSL_MAC_MASK)
+		{
+	case SSL_MD5:
+		mac="MD5";
+		break;
+	case SSL_SHA0:
+		mac="SHA0";
+		break;
+	case SSL_SHA1:
+		mac="SHA1";
+		break;
+	default:
+		mac="unknown";
+		break;
+		}
+
+	if (buf == NULL)
+		{
+		buf=Malloc(128);
+		if (buf == NULL) return("Malloc Error");
+		}
+	else if (len < 128)
+		return("Buffer too small");
+
+	sprintf(buf,format,cipher->name,ver,kx,au,enc,mac,exp);
+	return(buf);
+	}
+
+char *SSL_CIPHER_get_version(c)
+SSL_CIPHER *c;
+	{
+	int i;
+
+	i=(int)(c->id>>24L);
+	if (i == 3)
+		return("SSLv3");
+	else if (i == 2)
+		return("SSLv2");
+	else
+		return("unknown");
+	}
+
+/* return the actual cipher being used */
+char *SSL_CIPHER_get_name(c)
+SSL_CIPHER *c;
+	{
+	if (c != NULL)
+		return(c->name);
+	return("(NONE)");
+	}
+
+/* number of bits for symetric cipher */
+int SSL_CIPHER_get_bits(c,alg_bits)
+SSL_CIPHER *c;
+int *alg_bits;
+	{
+	int ret=0,a=0;
+	EVP_CIPHER *enc;
+	EVP_MD *md;
+
+	if (c != NULL)
+		{
+		if (!ssl_cipher_get_evp(c,&enc,&md))
+			return(0);
+
+		a=EVP_CIPHER_key_length(enc)*8;
+
+		if (c->algorithms & SSL_EXP)
+			{
+			ret=40;
+			}
+		else
+			{
+			if (c->algorithm2 & SSL2_CF_8_BYTE_ENC)
+				ret=64;
+			else
+				ret=a;
+			}
+		}
+
+	if (alg_bits != NULL) *alg_bits=a;
+	
+	return(ret);
+	}
+
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
new file mode 100644
index 0000000..18a1a22
--- /dev/null
+++ b/ssl/ssl_err.c
@@ -0,0 +1,350 @@
+/* lib/ssl/ssl_err.c */
+/* Copyright (C) 1995-1997 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 "err.h"
+#include "ssl.h"
+
+/* BEGIN ERROR CODES */
+static ERR_STRING_DATA SSL_str_functs[]=
+	{
+{ERR_PACK(0,SSL_F_CLIENT_CERTIFICATE,0),	"CLIENT_CERTIFICATE"},
+{ERR_PACK(0,SSL_F_CLIENT_HELLO,0),	"CLIENT_HELLO"},
+{ERR_PACK(0,SSL_F_CLIENT_MASTER_KEY,0),	"CLIENT_MASTER_KEY"},
+{ERR_PACK(0,SSL_F_D2I_SSL_SESSION,0),	"d2i_SSL_SESSION"},
+{ERR_PACK(0,SSL_F_DO_SSL3_WRITE,0),	"DO_SSL3_WRITE"},
+{ERR_PACK(0,SSL_F_GET_CLIENT_FINISHED,0),	"GET_CLIENT_FINISHED"},
+{ERR_PACK(0,SSL_F_GET_CLIENT_HELLO,0),	"GET_CLIENT_HELLO"},
+{ERR_PACK(0,SSL_F_GET_CLIENT_MASTER_KEY,0),	"GET_CLIENT_MASTER_KEY"},
+{ERR_PACK(0,SSL_F_GET_SERVER_FINISHED,0),	"GET_SERVER_FINISHED"},
+{ERR_PACK(0,SSL_F_GET_SERVER_HELLO,0),	"GET_SERVER_HELLO"},
+{ERR_PACK(0,SSL_F_GET_SERVER_VERIFY,0),	"GET_SERVER_VERIFY"},
+{ERR_PACK(0,SSL_F_I2D_SSL_SESSION,0),	"i2d_SSL_SESSION"},
+{ERR_PACK(0,SSL_F_READ_N,0),	"READ_N"},
+{ERR_PACK(0,SSL_F_REQUEST_CERTIFICATE,0),	"REQUEST_CERTIFICATE"},
+{ERR_PACK(0,SSL_F_SERVER_HELLO,0),	"SERVER_HELLO"},
+{ERR_PACK(0,SSL_F_SSL23_ACCEPT,0),	"SSL23_ACCEPT"},
+{ERR_PACK(0,SSL_F_SSL23_CLIENT_HELLO,0),	"SSL23_CLIENT_HELLO"},
+{ERR_PACK(0,SSL_F_SSL23_CONNECT,0),	"SSL23_CONNECT"},
+{ERR_PACK(0,SSL_F_SSL23_GET_CLIENT_HELLO,0),	"SSL23_GET_CLIENT_HELLO"},
+{ERR_PACK(0,SSL_F_SSL23_GET_SERVER_HELLO,0),	"SSL23_GET_SERVER_HELLO"},
+{ERR_PACK(0,SSL_F_SSL23_READ,0),	"SSL23_READ"},
+{ERR_PACK(0,SSL_F_SSL23_WRITE,0),	"SSL23_WRITE"},
+{ERR_PACK(0,SSL_F_SSL2_ACCEPT,0),	"SSL2_ACCEPT"},
+{ERR_PACK(0,SSL_F_SSL2_CONNECT,0),	"SSL2_CONNECT"},
+{ERR_PACK(0,SSL_F_SSL2_ENC_INIT,0),	"SSL2_ENC_INIT"},
+{ERR_PACK(0,SSL_F_SSL2_READ,0),	"SSL2_READ"},
+{ERR_PACK(0,SSL_F_SSL2_SET_CERTIFICATE,0),	"SSL2_SET_CERTIFICATE"},
+{ERR_PACK(0,SSL_F_SSL2_WRITE,0),	"SSL2_WRITE"},
+{ERR_PACK(0,SSL_F_SSL3_ACCEPT,0),	"SSL3_ACCEPT"},
+{ERR_PACK(0,SSL_F_SSL3_CHANGE_CIPHER_STATE,0),	"SSL3_CHANGE_CIPHER_STATE"},
+{ERR_PACK(0,SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,0),	"SSL3_CHECK_CERT_AND_ALGORITHM"},
+{ERR_PACK(0,SSL_F_SSL3_CLIENT_HELLO,0),	"SSL3_CLIENT_HELLO"},
+{ERR_PACK(0,SSL_F_SSL3_CONNECT,0),	"SSL3_CONNECT"},
+{ERR_PACK(0,SSL_F_SSL3_CTX_CTRL,0),	"SSL3_CTX_CTRL"},
+{ERR_PACK(0,SSL_F_SSL3_ENC,0),	"SSL3_ENC"},
+{ERR_PACK(0,SSL_F_SSL3_GET_CERTIFICATE_REQUEST,0),	"SSL3_GET_CERTIFICATE_REQUEST"},
+{ERR_PACK(0,SSL_F_SSL3_GET_CERT_VERIFY,0),	"SSL3_GET_CERT_VERIFY"},
+{ERR_PACK(0,SSL_F_SSL3_GET_CLIENT_CERTIFICATE,0),	"SSL3_GET_CLIENT_CERTIFICATE"},
+{ERR_PACK(0,SSL_F_SSL3_GET_CLIENT_HELLO,0),	"SSL3_GET_CLIENT_HELLO"},
+{ERR_PACK(0,SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,0),	"SSL3_GET_CLIENT_KEY_EXCHANGE"},
+{ERR_PACK(0,SSL_F_SSL3_GET_FINISHED,0),	"SSL3_GET_FINISHED"},
+{ERR_PACK(0,SSL_F_SSL3_GET_KEY_EXCHANGE,0),	"SSL3_GET_KEY_EXCHANGE"},
+{ERR_PACK(0,SSL_F_SSL3_GET_MESSAGE,0),	"SSL3_GET_MESSAGE"},
+{ERR_PACK(0,SSL_F_SSL3_GET_RECORD,0),	"SSL3_GET_RECORD"},
+{ERR_PACK(0,SSL_F_SSL3_GET_SERVER_CERTIFICATE,0),	"SSL3_GET_SERVER_CERTIFICATE"},
+{ERR_PACK(0,SSL_F_SSL3_GET_SERVER_DONE,0),	"SSL3_GET_SERVER_DONE"},
+{ERR_PACK(0,SSL_F_SSL3_GET_SERVER_HELLO,0),	"SSL3_GET_SERVER_HELLO"},
+{ERR_PACK(0,SSL_F_SSL3_OUTPUT_CERT_CHAIN,0),	"SSL3_OUTPUT_CERT_CHAIN"},
+{ERR_PACK(0,SSL_F_SSL3_READ_BYTES,0),	"SSL3_READ_BYTES"},
+{ERR_PACK(0,SSL_F_SSL3_READ_N,0),	"SSL3_READ_N"},
+{ERR_PACK(0,SSL_F_SSL3_SEND_CERTIFICATE_REQUEST,0),	"SSL3_SEND_CERTIFICATE_REQUEST"},
+{ERR_PACK(0,SSL_F_SSL3_SEND_CLIENT_CERTIFICATE,0),	"SSL3_SEND_CLIENT_CERTIFICATE"},
+{ERR_PACK(0,SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,0),	"SSL3_SEND_CLIENT_KEY_EXCHANGE"},
+{ERR_PACK(0,SSL_F_SSL3_SEND_CLIENT_VERIFY,0),	"SSL3_SEND_CLIENT_VERIFY"},
+{ERR_PACK(0,SSL_F_SSL3_SEND_SERVER_CERTIFICATE,0),	"SSL3_SEND_SERVER_CERTIFICATE"},
+{ERR_PACK(0,SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,0),	"SSL3_SEND_SERVER_KEY_EXCHANGE"},
+{ERR_PACK(0,SSL_F_SSL3_SETUP_BUFFERS,0),	"SSL3_SETUP_BUFFERS"},
+{ERR_PACK(0,SSL_F_SSL3_SETUP_KEY_BLOCK,0),	"SSL3_SETUP_KEY_BLOCK"},
+{ERR_PACK(0,SSL_F_SSL3_WRITE_BYTES,0),	"SSL3_WRITE_BYTES"},
+{ERR_PACK(0,SSL_F_SSL3_WRITE_PENDING,0),	"SSL3_WRITE_PENDING"},
+{ERR_PACK(0,SSL_F_SSL_BAD_METHOD,0),	"SSL_BAD_METHOD"},
+{ERR_PACK(0,SSL_F_SSL_BYTES_TO_CIPHER_LIST,0),	"SSL_BYTES_TO_CIPHER_LIST"},
+{ERR_PACK(0,SSL_F_SSL_CERT_NEW,0),	"SSL_CERT_NEW"},
+{ERR_PACK(0,SSL_F_SSL_CHECK_PRIVATE_KEY,0),	"SSL_check_private_key"},
+{ERR_PACK(0,SSL_F_SSL_CREATE_CIPHER_LIST,0),	"SSL_CREATE_CIPHER_LIST"},
+{ERR_PACK(0,SSL_F_SSL_CTX_CHECK_PRIVATE_KEY,0),	"SSL_CTX_check_private_key"},
+{ERR_PACK(0,SSL_F_SSL_CTX_NEW,0),	"SSL_CTX_new"},
+{ERR_PACK(0,SSL_F_SSL_CTX_SET_SSL_VERSION,0),	"SSL_CTX_set_ssl_version"},
+{ERR_PACK(0,SSL_F_SSL_CTX_USE_CERTIFICATE,0),	"SSL_CTX_use_certificate"},
+{ERR_PACK(0,SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1,0),	"SSL_CTX_use_certificate_ASN1"},
+{ERR_PACK(0,SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,0),	"SSL_CTX_use_certificate_file"},
+{ERR_PACK(0,SSL_F_SSL_CTX_USE_PRIVATEKEY,0),	"SSL_CTX_use_PrivateKey"},
+{ERR_PACK(0,SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1,0),	"SSL_CTX_use_PrivateKey_ASN1"},
+{ERR_PACK(0,SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE,0),	"SSL_CTX_use_PrivateKey_file"},
+{ERR_PACK(0,SSL_F_SSL_CTX_USE_RSAPRIVATEKEY,0),	"SSL_CTX_use_RSAPrivateKey"},
+{ERR_PACK(0,SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1,0),	"SSL_CTX_use_RSAPrivateKey_ASN1"},
+{ERR_PACK(0,SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE,0),	"SSL_CTX_use_RSAPrivateKey_file"},
+{ERR_PACK(0,SSL_F_SSL_DO_HANDSHAKE,0),	"SSL_do_handshake"},
+{ERR_PACK(0,SSL_F_SSL_GET_NEW_SESSION,0),	"SSL_GET_NEW_SESSION"},
+{ERR_PACK(0,SSL_F_SSL_GET_SERVER_SEND_CERT,0),	"SSL_GET_SERVER_SEND_CERT"},
+{ERR_PACK(0,SSL_F_SSL_GET_SIGN_PKEY,0),	"SSL_GET_SIGN_PKEY"},
+{ERR_PACK(0,SSL_F_SSL_LOAD_CLIENT_CA_FILE,0),	"SSL_load_client_CA_file"},
+{ERR_PACK(0,SSL_F_SSL_NEW,0),	"SSL_new"},
+{ERR_PACK(0,SSL_F_SSL_RSA_PRIVATE_DECRYPT,0),	"SSL_RSA_PRIVATE_DECRYPT"},
+{ERR_PACK(0,SSL_F_SSL_RSA_PUBLIC_ENCRYPT,0),	"SSL_RSA_PUBLIC_ENCRYPT"},
+{ERR_PACK(0,SSL_F_SSL_SESSION_NEW,0),	"SSL_SESSION_new"},
+{ERR_PACK(0,SSL_F_SSL_SESSION_PRINT_FP,0),	"SSL_SESSION_print_fp"},
+{ERR_PACK(0,SSL_F_SSL_SET_FD,0),	"SSL_set_fd"},
+{ERR_PACK(0,SSL_F_SSL_SET_PKEY,0),	"SSL_SET_PKEY"},
+{ERR_PACK(0,SSL_F_SSL_SET_RFD,0),	"SSL_set_rfd"},
+{ERR_PACK(0,SSL_F_SSL_SET_SESSION,0),	"SSL_set_session"},
+{ERR_PACK(0,SSL_F_SSL_SET_WFD,0),	"SSL_set_wfd"},
+{ERR_PACK(0,SSL_F_SSL_UNDEFINED_FUNCTION,0),	"SSL_UNDEFINED_FUNCTION"},
+{ERR_PACK(0,SSL_F_SSL_USE_CERTIFICATE,0),	"SSL_use_certificate"},
+{ERR_PACK(0,SSL_F_SSL_USE_CERTIFICATE_ASN1,0),	"SSL_use_certificate_ASN1"},
+{ERR_PACK(0,SSL_F_SSL_USE_CERTIFICATE_FILE,0),	"SSL_use_certificate_file"},
+{ERR_PACK(0,SSL_F_SSL_USE_PRIVATEKEY,0),	"SSL_use_PrivateKey"},
+{ERR_PACK(0,SSL_F_SSL_USE_PRIVATEKEY_ASN1,0),	"SSL_use_PrivateKey_ASN1"},
+{ERR_PACK(0,SSL_F_SSL_USE_PRIVATEKEY_FILE,0),	"SSL_use_PrivateKey_file"},
+{ERR_PACK(0,SSL_F_SSL_USE_RSAPRIVATEKEY,0),	"SSL_use_RSAPrivateKey"},
+{ERR_PACK(0,SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1,0),	"SSL_use_RSAPrivateKey_ASN1"},
+{ERR_PACK(0,SSL_F_SSL_USE_RSAPRIVATEKEY_FILE,0),	"SSL_use_RSAPrivateKey_file"},
+{ERR_PACK(0,SSL_F_SSL_WRITE,0),	"SSL_write"},
+{ERR_PACK(0,SSL_F_WRITE_PENDING,0),	"WRITE_PENDING"},
+{0,NULL},
+	};
+
+static ERR_STRING_DATA SSL_str_reasons[]=
+	{
+{SSL_R_APP_DATA_IN_HANDSHAKE             ,"app data in handshake"},
+{SSL_R_BAD_ALERT_RECORD                  ,"bad alert record"},
+{SSL_R_BAD_AUTHENTICATION_TYPE           ,"bad authentication type"},
+{SSL_R_BAD_CHANGE_CIPHER_SPEC            ,"bad change cipher spec"},
+{SSL_R_BAD_CHECKSUM                      ,"bad checksum"},
+{SSL_R_BAD_CLIENT_REQUEST                ,"bad client request"},
+{SSL_R_BAD_DATA_RETURNED_BY_CALLBACK     ,"bad data returned by callback"},
+{SSL_R_BAD_DECOMPRESSION                 ,"bad decompression"},
+{SSL_R_BAD_DH_G_LENGTH                   ,"bad dh g length"},
+{SSL_R_BAD_DH_PUB_KEY_LENGTH             ,"bad dh pub key length"},
+{SSL_R_BAD_DH_P_LENGTH                   ,"bad dh p length"},
+{SSL_R_BAD_DIGEST_LENGTH                 ,"bad digest length"},
+{SSL_R_BAD_DSA_SIGNATURE                 ,"bad dsa signature"},
+{SSL_R_BAD_MAC_DECODE                    ,"bad mac decode"},
+{SSL_R_BAD_MESSAGE_TYPE                  ,"bad message type"},
+{SSL_R_BAD_PACKET_LENGTH                 ,"bad packet length"},
+{SSL_R_BAD_RESPONSE_ARGUMENT             ,"bad response argument"},
+{SSL_R_BAD_RSA_DECRYPT                   ,"bad rsa decrypt"},
+{SSL_R_BAD_RSA_ENCRYPT                   ,"bad rsa encrypt"},
+{SSL_R_BAD_RSA_E_LENGTH                  ,"bad rsa e length"},
+{SSL_R_BAD_RSA_MODULUS_LENGTH            ,"bad rsa modulus length"},
+{SSL_R_BAD_RSA_SIGNATURE                 ,"bad rsa signature"},
+{SSL_R_BAD_SIGNATURE                     ,"bad signature"},
+{SSL_R_BAD_SSL_FILETYPE                  ,"bad ssl filetype"},
+{SSL_R_BAD_SSL_SESSION_ID_LENGTH         ,"bad ssl session id length"},
+{SSL_R_BAD_STATE                         ,"bad state"},
+{SSL_R_BAD_WRITE_RETRY                   ,"bad write retry"},
+{SSL_R_BIO_NOT_SET                       ,"bio not set"},
+{SSL_R_BLOCK_CIPHER_PAD_IS_WRONG         ,"block cipher pad is wrong"},
+{SSL_R_BN_LIB                            ,"bn lib"},
+{SSL_R_CA_DN_LENGTH_MISMATCH             ,"ca dn length mismatch"},
+{SSL_R_CA_DN_TOO_LONG                    ,"ca dn too long"},
+{SSL_R_CCS_RECEIVED_EARLY                ,"ccs received early"},
+{SSL_R_CERTIFICATE_VERIFY_FAILED         ,"certificate verify failed"},
+{SSL_R_CERT_LENGTH_MISMATCH              ,"cert length mismatch"},
+{SSL_R_CHALLENGE_IS_DIFFERENT            ,"challenge is different"},
+{SSL_R_CIPHER_CODE_WRONG_LENGTH          ,"cipher code wrong length"},
+{SSL_R_CIPHER_OR_HASH_UNAVAILABLE        ,"cipher or hash unavailable"},
+{SSL_R_CIPHER_TABLE_SRC_ERROR            ,"cipher table src error"},
+{SSL_R_COMPRESSED_LENGTH_TOO_LONG        ,"compressed length too long"},
+{SSL_R_COMPRESSION_FAILURE               ,"compression failure"},
+{SSL_R_CONNECTION_ID_IS_DIFFERENT        ,"connection id is different"},
+{SSL_R_DATA_BETWEEN_CCS_AND_FINISHED     ,"data between ccs and finished"},
+{SSL_R_DATA_LENGTH_TOO_LONG              ,"data length too long"},
+{SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG   ,"dh public value length is wrong"},
+{SSL_R_DIGEST_CHECK_FAILED               ,"digest check failed"},
+{SSL_R_ENCRYPTED_LENGTH_TOO_LONG         ,"encrypted length too long"},
+{SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST     ,"error in received cipher list"},
+{SSL_R_EXCESSIVE_MESSAGE_SIZE            ,"excessive message size"},
+{SSL_R_EXTRA_DATA_IN_MESSAGE             ,"extra data in message"},
+{SSL_R_GOT_A_FIN_BEFORE_A_CCS            ,"got a fin before a ccs"},
+{SSL_R_INTERNAL_ERROR                    ,"internal error"},
+{SSL_R_INVALID_CHALLENGE_LENGTH          ,"invalid challenge length"},
+{SSL_R_LENGTH_MISMATCH                   ,"length mismatch"},
+{SSL_R_LENGTH_TOO_SHORT                  ,"length too short"},
+{SSL_R_LIBRARY_HAS_NO_CIPHERS            ,"library has no ciphers"},
+{SSL_R_MISSING_DH_DSA_CERT               ,"missing dh dsa cert"},
+{SSL_R_MISSING_DH_KEY                    ,"missing dh key"},
+{SSL_R_MISSING_DH_RSA_CERT               ,"missing dh rsa cert"},
+{SSL_R_MISSING_DSA_SIGNING_CERT          ,"missing dsa signing cert"},
+{SSL_R_MISSING_EXPORT_TMP_DH_KEY         ,"missing export tmp dh key"},
+{SSL_R_MISSING_EXPORT_TMP_RSA_KEY        ,"missing export tmp rsa key"},
+{SSL_R_MISSING_RSA_CERTIFICATE           ,"missing rsa certificate"},
+{SSL_R_MISSING_RSA_ENCRYPTING_CERT       ,"missing rsa encrypting cert"},
+{SSL_R_MISSING_RSA_SIGNING_CERT          ,"missing rsa signing cert"},
+{SSL_R_MISSING_TMP_DH_KEY                ,"missing tmp dh key"},
+{SSL_R_MISSING_TMP_RSA_KEY               ,"missing tmp rsa key"},
+{SSL_R_MISSING_TMP_RSA_PKEY              ,"missing tmp rsa pkey"},
+{SSL_R_MISSING_VERIFY_MESSAGE            ,"missing verify message"},
+{SSL_R_NON_SSLV2_INITIAL_PACKET          ,"non sslv2 initial packet"},
+{SSL_R_NO_CERTIFICATES_PASSED            ,"no certificates passed"},
+{SSL_R_NO_CERTIFICATE_ASSIGNED           ,"no certificate assigned"},
+{SSL_R_NO_CERTIFICATE_RETURNED           ,"no certificate returned"},
+{SSL_R_NO_CERTIFICATE_SET                ,"no certificate set"},
+{SSL_R_NO_CERTIFICATE_SPECIFIED          ,"no certificate specified"},
+{SSL_R_NO_CIPHERS_AVAILABLE              ,"no ciphers available"},
+{SSL_R_NO_CIPHERS_PASSED                 ,"no ciphers passed"},
+{SSL_R_NO_CIPHERS_SPECIFIED              ,"no ciphers specified"},
+{SSL_R_NO_CIPHER_LIST                    ,"no cipher list"},
+{SSL_R_NO_CIPHER_MATCH                   ,"no cipher match"},
+{SSL_R_NO_CLIENT_CERT_RECEIVED           ,"no client cert received"},
+{SSL_R_NO_COMPRESSION_SPECIFIED          ,"no compression specified"},
+{SSL_R_NO_PRIVATEKEY                     ,"no privatekey"},
+{SSL_R_NO_PRIVATE_KEY_ASSIGNED           ,"no private key assigned"},
+{SSL_R_NO_PUBLICKEY                      ,"no publickey"},
+{SSL_R_NO_SHARED_CIPHER                  ,"no shared cipher"},
+{SSL_R_NULL_SSL_CTX                      ,"null ssl ctx"},
+{SSL_R_NULL_SSL_METHOD_PASSED            ,"null ssl method passed"},
+{SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED   ,"old session cipher not returned"},
+{SSL_R_PACKET_LENGTH_TOO_LONG            ,"packet length too long"},
+{SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE ,"peer did not return a certificate"},
+{SSL_R_PEER_ERROR                        ,"peer error"},
+{SSL_R_PEER_ERROR_CERTIFICATE            ,"peer error certificate"},
+{SSL_R_PEER_ERROR_NO_CERTIFICATE         ,"peer error no certificate"},
+{SSL_R_PEER_ERROR_NO_CIPHER              ,"peer error no cipher"},
+{SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE,"peer error unsupported certificate type"},
+{SSL_R_PRE_MAC_LENGTH_TOO_LONG           ,"pre mac length too long"},
+{SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS ,"problems mapping cipher functions"},
+{SSL_R_PROTOCOL_IS_SHUTDOWN              ,"protocol is shutdown"},
+{SSL_R_PUBLIC_KEY_ENCRYPT_ERROR          ,"public key encrypt error"},
+{SSL_R_PUBLIC_KEY_IS_NOT_RSA             ,"public key is not rsa"},
+{SSL_R_PUBLIC_KEY_NOT_RSA                ,"public key not rsa"},
+{SSL_R_READ_BIO_NOT_SET                  ,"read bio not set"},
+{SSL_R_READ_WRONG_PACKET_TYPE            ,"read wrong packet type"},
+{SSL_R_RECORD_LENGTH_MISMATCH            ,"record length mismatch"},
+{SSL_R_RECORD_TOO_LARGE                  ,"record too large"},
+{SSL_R_REQUIRED_CIPHER_MISSING           ,"required cipher missing"},
+{SSL_R_REUSE_CERT_LENGTH_NOT_ZERO        ,"reuse cert length not zero"},
+{SSL_R_REUSE_CERT_TYPE_NOT_ZERO          ,"reuse cert type not zero"},
+{SSL_R_REUSE_CIPHER_LIST_NOT_ZERO        ,"reuse cipher list not zero"},
+{SSL_R_SHORT_READ                        ,"short read"},
+{SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE,"signature for non signing certificate"},
+{SSL_R_SSL3_SESSION_ID_TOO_SHORT         ,"ssl3 session id too short"},
+{SSL_R_SSLV3_ALERT_BAD_CERTIFICATE       ,"sslv3 alert bad certificate"},
+{SSL_R_SSLV3_ALERT_BAD_RECORD_MAC        ,"sslv3 alert bad record mac"},
+{SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED   ,"sslv3 alert certificate expired"},
+{SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED   ,"sslv3 alert certificate revoked"},
+{SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN   ,"sslv3 alert certificate unknown"},
+{SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE ,"sslv3 alert decompression failure"},
+{SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE     ,"sslv3 alert handshake failure"},
+{SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER     ,"sslv3 alert illegal parameter"},
+{SSL_R_SSLV3_ALERT_NO_CERTIFICATE        ,"sslv3 alert no certificate"},
+{SSL_R_SSLV3_ALERT_PEER_ERROR_CERTIFICATE,"sslv3 alert peer error certificate"},
+{SSL_R_SSLV3_ALERT_PEER_ERROR_NO_CERTIFICATE,"sslv3 alert peer error no certificate"},
+{SSL_R_SSLV3_ALERT_PEER_ERROR_NO_CIPHER  ,"sslv3 alert peer error no cipher"},
+{SSL_R_SSLV3_ALERT_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE,"sslv3 alert peer error unsupported certificate type"},
+{SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE    ,"sslv3 alert unexpected message"},
+{SSL_R_SSLV3_ALERT_UNKNOWN_REMOTE_ERROR_TYPE,"sslv3 alert unknown remote error type"},
+{SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE,"sslv3 alert unsupported certificate"},
+{SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION,"ssl ctx has no default ssl version"},
+{SSL_R_SSL_HANDSHAKE_FAILURE             ,"ssl handshake failure"},
+{SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS        ,"ssl library has no ciphers"},
+{SSL_R_SSL_SESSION_ID_IS_DIFFERENT       ,"ssl session id is different"},
+{SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER   ,"tried to use unsupported cipher"},
+{SSL_R_UNABLE_TO_DECODE_DH_CERTS         ,"unable to decode dh certs"},
+{SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY      ,"unable to extract public key"},
+{SSL_R_UNABLE_TO_FIND_DH_PARAMETERS      ,"unable to find dh parameters"},
+{SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS,"unable to find public key parameters"},
+{SSL_R_UNABLE_TO_FIND_SSL_METHOD         ,"unable to find ssl method"},
+{SSL_R_UNEXPECTED_MESSAGE                ,"unexpected message"},
+{SSL_R_UNEXPECTED_RECORD                 ,"unexpected record"},
+{SSL_R_UNKNOWN_ALERT_TYPE                ,"unknown alert type"},
+{SSL_R_UNKNOWN_CERTIFICATE_TYPE          ,"unknown certificate type"},
+{SSL_R_UNKNOWN_CIPHER_RETURNED           ,"unknown cipher returned"},
+{SSL_R_UNKNOWN_CIPHER_TYPE               ,"unknown cipher type"},
+{SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE         ,"unknown key exchange type"},
+{SSL_R_UNKNOWN_PKEY_TYPE                 ,"unknown pkey type"},
+{SSL_R_UNKNOWN_PROTOCOL                  ,"unknown protocol"},
+{SSL_R_UNKNOWN_REMOTE_ERROR_TYPE         ,"unknown remote error type"},
+{SSL_R_UNKNOWN_SSL_VERSION               ,"unknown ssl version"},
+{SSL_R_UNKNOWN_STATE                     ,"unknown state"},
+{SSL_R_UNSUPPORTED_CIPHER                ,"unsupported cipher"},
+{SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM ,"unsupported compression algorithm"},
+{SSL_R_UNSUPPORTED_SSL_VERSION           ,"unsupported ssl version"},
+{SSL_R_WRITE_BIO_NOT_SET                 ,"write bio not set"},
+{SSL_R_WRONG_CIPHER_RETURNED             ,"wrong cipher returned"},
+{SSL_R_WRONG_MESSAGE_TYPE                ,"wrong message type"},
+{SSL_R_WRONG_NUMBER_OF_KEY_BITS          ,"wrong number of key bits"},
+{SSL_R_WRONG_SIGNATURE_LENGTH            ,"wrong signature length"},
+{SSL_R_WRONG_SIGNATURE_SIZE              ,"wrong signature size"},
+{SSL_R_WRONG_SSL_VERSION                 ,"wrong ssl version"},
+{SSL_R_WRONG_VERSION_NUMBER              ,"wrong version number"},
+{SSL_R_X509_LIB                          ,"x509 lib"},
+{0,NULL},
+	};
+
+void ERR_load_SSL_strings()
+	{
+	static int init=1;
+
+	if (init)
+		{
+		init=0;
+		ERR_load_strings(ERR_LIB_SSL,SSL_str_functs);
+		ERR_load_strings(ERR_LIB_SSL,SSL_str_reasons);
+		}
+	}
diff --git a/ssl/ssl_err2.c b/ssl/ssl_err2.c
new file mode 100644
index 0000000..a159fbb
--- /dev/null
+++ b/ssl/ssl_err2.c
@@ -0,0 +1,70 @@
+/* ssl/ssl_err2.c */
+/* Copyright (C) 1995-1997 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 "err.h"
+#include "ssl.h"
+
+void SSL_load_error_strings()
+	{
+#ifndef NO_ERR
+	ERR_load_crypto_strings();
+	ERR_load_SSL_strings();
+#endif
+	}
+
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
new file mode 100644
index 0000000..be091b1
--- /dev/null
+++ b/ssl/ssl_lib.c
@@ -0,0 +1,1433 @@
+/* ssl/ssl_lib.c */
+/* Copyright (C) 1995-1997 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 "objects.h"
+#include "lhash.h"
+#include "ssl_locl.h"
+
+#ifndef NOPROTO
+static unsigned long conn_hash(SSL_SESSION *a);
+#else
+static unsigned long conn_hash();
+#endif
+
+char *SSL_version_str="SSLeay 0.8.1b 29-Jun-1998";
+
+void SSL_clear(s)
+SSL *s;
+	{
+	int state;
+
+	if (s->method == NULL) return;
+
+	s->error=0;
+	s->hit=0;
+
+	/* 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;
+
+	state=s->state; /* Keep to check if we throw away the session-id */
+	s->type=0;
+
+	s->version=s->method->version;
+	s->rwstate=SSL_NOTHING;
+	s->state=SSL_ST_BEFORE;
+	s->rstate=SSL_ST_READ_HEADER;
+	s->read_ahead=s->ctx->default_read_ahead;
+
+/*	s->shutdown=(SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN); */
+
+	if (s->init_buf != NULL)
+		{
+		BUF_MEM_free(s->init_buf);
+		s->init_buf=NULL;
+		}
+
+	ssl_clear_cipher_ctx(s);
+
+	if (ssl_clear_bad_session(s))
+		{
+		SSL_SESSION_free(s->session);
+		s->session=NULL;
+		}
+
+	s->shutdown=(SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
+	s->first_packet=0;
+
+	s->method->ssl_clear(s);
+	}
+
+/* Used to change an SSL_CTXs default SSL method type */
+int SSL_CTX_set_ssl_version(ctx,meth)
+SSL_CTX *ctx;
+SSL_METHOD *meth;
+	{
+	STACK *sk;
+
+	ctx->method=meth;
+
+	sk=ssl_create_cipher_list(ctx->method,&(ctx->cipher_list),
+		&(ctx->cipher_list_by_id),SSL_DEFAULT_CIPHER_LIST);
+	if ((sk == NULL) || (sk_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(ctx)
+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 *)Malloc(sizeof(SSL));
+	if (s == NULL) goto err;
+	memset(s,0,sizeof(SSL));
+
+	if (ctx->default_cert != NULL)
+		{
+		CRYPTO_add(&ctx->default_cert->references,1,
+			CRYPTO_LOCK_SSL_CERT);
+		s->cert=ctx->default_cert;
+		}
+	else
+		s->cert=NULL;
+	s->verify_mode=ctx->default_verify_mode;
+	s->verify_callback=ctx->default_verify_callback;
+	CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX);
+	s->ctx=ctx;
+
+	s->verify_result=X509_V_OK;
+
+	s->method=ctx->method;
+
+	if (!s->method->ssl_new(s))
+		{
+		SSL_CTX_free(ctx);
+		Free(s);
+		goto err;
+		}
+
+	s->quiet_shutdown=ctx->quiet_shutdown;
+	SSL_clear(s);
+	return(s);
+err:
+	SSLerr(SSL_F_SSL_NEW,ERR_R_MALLOC_FAILURE);
+	return(NULL);
+	}
+
+void SSL_free(s)
+SSL *s;
+	{
+	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);
+		}
+	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_free(s->cipher_list);
+	if (s->cipher_list_by_id != NULL) sk_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);
+
+	if (s->cert != NULL) ssl_cert_free(s->cert);
+	/* Free up if allocated */
+
+	if (s->ctx) SSL_CTX_free(s->ctx);
+
+	if (s->client_CA != NULL)
+		sk_pop_free(s->client_CA,X509_NAME_free);
+
+	if (s->method != NULL) s->method->ssl_free(s);
+
+	Free((char *)s);
+	}
+
+void SSL_set_bio(s, rbio,wbio)
+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(s)
+SSL *s;
+	{ return(s->rbio); }
+
+BIO *SSL_get_wbio(s)
+SSL *s;
+	{ return(s->wbio); }
+
+int SSL_get_fd(s)
+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);
+	}
+
+#ifndef NO_SOCK
+int SSL_set_fd(s, 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(s, 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_WFD,ERR_R_BUF_LIB); goto err; }
+	BIO_set_fd(bio,fd,BIO_NOCLOSE);
+	SSL_set_bio(s,SSL_get_rbio(s),bio);
+	ret=1;
+err:
+	return(ret);
+	}
+
+int SSL_set_rfd(s, 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_RFD,ERR_R_BUF_LIB);
+		goto err;
+		}
+	BIO_set_fd(bio,fd,BIO_NOCLOSE);
+	SSL_set_bio(s,bio,SSL_get_wbio(s));
+	ret=1;
+err:
+	return(ret);
+	}
+#endif
+
+int SSL_get_verify_mode(s)
+SSL *s;
+	{
+	return(s->verify_mode);
+	}
+
+int (*SSL_get_verify_callback(s))()
+SSL *s;
+	{
+	return(s->verify_callback);
+	}
+
+int SSL_CTX_get_verify_mode(ctx)
+SSL_CTX *ctx;
+	{
+	return(ctx->default_verify_mode);
+	}
+
+int (*SSL_CTX_get_verify_callback(ctx))()
+SSL_CTX *ctx;
+	{
+	return(ctx->default_verify_callback);
+	}
+
+void SSL_set_verify(s, mode, callback)
+SSL *s;
+int mode;
+int (*callback)();
+	{
+	s->verify_mode=mode;
+	if (callback != NULL)
+		s->verify_callback=callback;
+	}
+
+void SSL_set_read_ahead(s, yes)
+SSL *s;
+int yes;
+	{
+	s->read_ahead=yes;
+	}
+
+int SSL_get_read_ahead(s)
+SSL *s;
+	{
+	return(s->read_ahead);
+	}
+
+int SSL_pending(s)
+SSL *s;
+	{
+	return(s->method->ssl_pending(s));
+	}
+
+X509 *SSL_get_peer_certificate(s)
+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 *SSL_get_peer_cert_chain(s)
+SSL *s;
+	{
+	STACK *r;
+	
+	if ((s == NULL) || (s->session == NULL) || (s->session->cert == NULL))
+		r=NULL;
+	else
+		r=s->session->cert->cert_chain;
+
+	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(t,f)
+SSL *t,*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);
+	}
+
+int SSL_CTX_check_private_key(ctx)
+SSL_CTX *ctx;
+	{
+	if (	(ctx == NULL) ||
+		(ctx->default_cert == NULL) ||
+		(ctx->default_cert->key->x509 == NULL))
+		{
+		SSLerr(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY,SSL_R_NO_CERTIFICATE_ASSIGNED);
+		return(0);
+		}
+	if 	(ctx->default_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->default_cert->key->x509, ctx->default_cert->key->privatekey));
+	}
+
+int SSL_check_private_key(ssl)
+SSL *ssl;
+	{
+	if (ssl == NULL)
+		{
+		SSLerr(SSL_F_SSL_CHECK_PRIVATE_KEY,ERR_R_PASSED_NULL_PARAMETER);
+		return(0);
+		}
+	if (ssl->cert == NULL)
+		return(SSL_CTX_check_private_key(ssl->ctx));
+	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(s)
+SSL *s;
+	{
+	return(s->method->ssl_accept(s));
+	}
+
+int SSL_connect(s)
+SSL *s;
+	{
+	return(s->method->ssl_connect(s));
+	}
+
+long SSL_get_default_timeout(s)
+SSL *s;
+	{
+	return(s->method->get_timeout());
+	}
+
+int SSL_read(s,buf,num)
+SSL *s;
+char *buf;
+int num;
+	{
+	if (s->shutdown & SSL_RECEIVED_SHUTDOWN)
+		{
+		s->rwstate=SSL_NOTHING;
+		return(0);
+		}
+	return(s->method->ssl_read(s,buf,num));
+	}
+
+int SSL_peek(s,buf,num)
+SSL *s;
+char *buf;
+int num;
+	{
+	if (s->shutdown & SSL_RECEIVED_SHUTDOWN)
+		{
+		return(0);
+		}
+	return(s->method->ssl_peek(s,buf,num));
+	}
+
+int SSL_write(s,buf,num)
+SSL *s;
+char *buf;
+int num;
+	{
+	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(s)
+SSL *s;
+	{
+	if ((s != NULL) && !SSL_in_init(s))
+		return(s->method->ssl_shutdown(s));
+	else
+		return(1);
+	}
+
+int SSL_renegotiate(s)
+SSL *s;
+	{
+	return(s->method->ssl_renegotiate(s));
+	}
+
+long SSL_ctrl(s,cmd,larg,parg)
+SSL *s;
+int cmd;
+long larg;
+char *parg;
+	{
+	return(s->method->ssl_ctrl(s,cmd,larg,parg));
+	}
+
+long SSL_CTX_ctrl(ctx,cmd,larg,parg)
+SSL_CTX *ctx;
+int cmd;
+long larg;
+char *parg;
+	{
+	return(ctx->method->ssl_ctx_ctrl(ctx,cmd,larg,parg));
+	}
+
+int ssl_cipher_id_cmp(a,b)
+SSL_CIPHER *a,*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(ap,bp)
+SSL_CIPHER **ap,**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 *SSL_get_ciphers(s)
+SSL *s;
+	{
+	if ((s != NULL) && (s->cipher_list != NULL))
+		{
+		return(s->cipher_list);
+		}
+	else if ((s != NULL) && (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 *ssl_get_ciphers_by_id(s)
+SSL *s;
+	{
+	if ((s != NULL) && (s->cipher_list_by_id != NULL))
+		{
+		return(s->cipher_list_by_id);
+		}
+	else if ((s != NULL) && (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() */
+char *SSL_get_cipher_list(s,n)
+SSL *s;
+int n;
+	{
+	SSL_CIPHER *c;
+	STACK *sk;
+
+	if (s == NULL) return(NULL);
+	sk=SSL_get_ciphers(s);
+	if ((sk == NULL) || (sk_num(sk) <= n))
+		return(NULL);
+	c=(SSL_CIPHER *)sk_value(sk,n);
+	if (c == NULL) return(NULL);
+	return(c->name);
+	}
+
+/* specify the ciphers to be used by defaut by the SSL_CTX */
+int SSL_CTX_set_cipher_list(ctx,str)
+SSL_CTX *ctx;
+char *str;
+	{
+	STACK *sk;
+	
+	sk=ssl_create_cipher_list(ctx->method,&ctx->cipher_list,
+		&ctx->cipher_list_by_id,str);
+/* XXXX */
+	return((sk == NULL)?0:1);
+	}
+
+/* specify the ciphers to be used by the SSL */
+int SSL_set_cipher_list(s, str)
+SSL *s;
+char *str;
+	{
+	STACK *sk;
+	
+	sk=ssl_create_cipher_list(s->ctx->method,&s->cipher_list,
+		&s->cipher_list_by_id,str);
+/* XXXX */
+	return((sk == NULL)?0:1);
+	}
+
+/* works well for SSLv2, not so good for SSLv3 */
+char *SSL_get_shared_ciphers(s,buf,len)
+SSL *s;
+char *buf;
+int len;
+	{
+	char *p,*cp;
+	STACK *sk;
+	SSL_CIPHER *c;
+	int i;
+
+	if ((s->session == NULL) || (s->session->ciphers == NULL) ||
+		(len < 2))
+		return(NULL);
+
+	p=buf;
+	sk=s->session->ciphers;
+	len--;
+	for (i=0; i<sk_num(sk); i++)
+		{
+		c=(SSL_CIPHER *)sk_value(sk,i);
+		for (cp=c->name; *cp; )
+			{
+			if (--len == 0)
+				{
+				*p='\0';
+				return(buf);
+				}
+			else
+				*(p++)= *(cp++);
+			}
+		*(p++)=':';
+		}
+	p[-1]='\0';
+	return(buf);
+	}
+
+int ssl_cipher_list_to_bytes(s,sk,p)
+SSL *s;
+STACK *sk;
+unsigned char *p;
+	{
+	int i,j=0;
+	SSL_CIPHER *c;
+	unsigned char *q;
+
+	if (sk == NULL) return(0);
+	q=p;
+
+	for (i=0; i<sk_num(sk); i++)
+		{
+		c=(SSL_CIPHER *)sk_value(sk,i);
+		j=ssl_put_cipher_by_char(s,c,p);
+		p+=j;
+		}
+	return(p-q);
+	}
+
+STACK *ssl_bytes_to_cipher_list(s,p,num,skp)
+SSL *s;
+unsigned char *p;
+int num;
+STACK **skp;
+	{
+	SSL_CIPHER *c;
+	STACK *sk;
+	int i,n;
+
+	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_new(NULL); /* change perhaps later */
+	else
+		{
+		sk= *skp;
+		sk_zero(sk);
+		}
+
+	for (i=0; i<num; i+=n)
+		{
+		c=ssl_get_cipher_by_char(s,p);
+		p+=n;
+		if (c != NULL)
+			{
+			if (!sk_push(sk,(char *)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_free(sk);
+	return(NULL);
+	}
+
+static unsigned long conn_hash(a)
+SSL_SESSION *a;
+	{
+	unsigned long l;
+
+	l=      (a->session_id[0]     )|(a->session_id[1]<< 8L)|
+		(a->session_id[1]<<16L)|(a->session_id[2]<<24L);
+	return(l);
+	}
+
+static int session_cmp(a, b)
+SSL_SESSION *a;
+SSL_SESSION *b;
+	{
+	int i;
+
+	i=a->session_id_length - b->session_id_length;
+	if (i == 0)
+		return(memcmp(a->session_id,b->session_id,
+			a->session_id_length));
+	else    return(1);
+	}
+
+SSL_CTX *SSL_CTX_new(meth)
+SSL_METHOD *meth;
+	{
+	SSL_CTX *ret;
+	
+	if (meth == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_NULL_SSL_METHOD_PASSED);
+		return(NULL);
+		}
+	ret=(SSL_CTX *)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;
+
+	/* We take the system default */
+	ret->session_timeout=meth->get_timeout();
+
+	ret->new_session_cb=NULL;
+	ret->remove_session_cb=NULL;
+	ret->get_session_cb=NULL;
+
+	ret->sess_connect=0;
+	ret->sess_connect_good=0;
+	ret->sess_accept=0;
+	ret->sess_accept_good=0;
+	ret->sess_miss=0;
+	ret->sess_timeout=0;
+	ret->sess_hit=0;
+	ret->sess_cb_hit=0;
+
+	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=NULL;
+	ret->app_verify_arg=NULL;
+
+	ret->default_read_ahead=0;
+	ret->default_verify_mode=SSL_VERIFY_NONE;
+	ret->default_verify_callback=NULL;
+	if ((ret->default_cert=ssl_cert_new()) == NULL)
+		goto err;
+
+	ret->default_passwd_callback=NULL;
+	ret->client_cert_cb=NULL;
+
+	ret->sessions=lh_new(conn_hash,session_cmp);
+	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,
+		SSL_DEFAULT_CIPHER_LIST);
+	if ((ret->cipher_list == NULL) || (sk_num(ret->cipher_list) <= 0))
+		{
+		SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_LIBRARY_HAS_NO_CIPHERS);
+		goto err2;
+		}
+
+	if ((ret->client_CA=sk_new_null()) == NULL)
+		goto err;
+
+	return(ret);
+err:
+	SSLerr(SSL_F_SSL_CTX_NEW,ERR_R_MALLOC_FAILURE);
+err2:
+	if (ret != NULL) SSL_CTX_free(ret);
+	return(NULL);
+	}
+
+void SSL_CTX_free(a)
+SSL_CTX *a;
+	{
+	int i;
+
+	if (a == NULL) return;
+
+	i=CRYPTO_add(&a->references,-1,CRYPTO_LOCK_SSL_CTX);
+	if (i > 0) return;
+#ifdef REF_CHECK
+	if (i < 0)
+		{
+		fprintf(stderr,"SSL_CTX_free, bad reference count\n");
+		abort(); /* ok */
+		}
+#endif
+
+	if (a->sessions != NULL)
+		{
+		SSL_CTX_flush_sessions(a,0);
+		lh_free(a->sessions);
+		}
+	if (a->cert_store != NULL)
+		X509_STORE_free(a->cert_store);
+	if (a->cipher_list != NULL)
+		sk_free(a->cipher_list);
+	if (a->cipher_list_by_id != NULL)
+		sk_free(a->cipher_list_by_id);
+	if (a->default_cert != NULL)
+		ssl_cert_free(a->default_cert);
+	if (a->client_CA != NULL)
+		sk_pop_free(a->client_CA,X509_NAME_free);
+	Free((char *)a);
+	}
+
+void SSL_CTX_set_default_passwd_cb(ctx,cb)
+SSL_CTX *ctx;
+int (*cb)();
+	{
+	ctx->default_passwd_callback=cb;
+	}
+
+void SSL_CTX_set_cert_verify_cb(ctx,cb,arg)
+SSL_CTX *ctx;
+int (*cb)();
+char *arg;
+	{
+	ctx->app_verify_callback=cb;
+	ctx->app_verify_arg=arg;
+	}
+
+void SSL_CTX_set_verify(ctx,mode,cb)
+SSL_CTX *ctx;
+int mode;
+int (*cb)();
+	{
+	ctx->default_verify_mode=mode;
+	ctx->default_verify_callback=cb;
+	/* This needs cleaning up EAY EAY EAY */
+	X509_STORE_set_verify_cb_func(ctx->cert_store,cb);
+	}
+
+void ssl_set_cert_masks(c)
+CERT *c;
+	{
+	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;
+	unsigned long mask,emask;
+
+	if ((c == NULL) || (c->valid)) return;
+
+#ifndef NO_RSA
+	rsa_tmp=((c->rsa_tmp != NULL) || (c->rsa_tmp_cb != NULL))?1:0;
+	rsa_tmp_export=((c->rsa_tmp_cb != NULL) ||
+		(rsa_tmp && (RSA_size(c->rsa_tmp)*8 <= 512)))?1:0;
+#else
+	rsa_tmp=rsa_tmp_export=0;
+#endif
+#ifndef NO_DH
+	dh_tmp=((c->dh_tmp != NULL) || (c->dh_tmp_cb != NULL))?1:0;
+	dh_tmp_export=((c->dh_tmp_cb != NULL) ||
+		(dh_tmp && (DH_size(c->dh_tmp)*8 <= 512)))?1:0;
+#else
+	dh_tmp=dh_tmp_export=0;
+#endif
+
+	cpk= &(c->pkeys[SSL_PKEY_RSA_ENC]);
+	rsa_enc= ((cpk->x509 != NULL) && (cpk->privatekey != NULL))?1:0;
+	rsa_enc_export=(rsa_enc && (EVP_PKEY_size(cpk->privatekey)*8 <= 512))?1:0;
+	cpk= &(c->pkeys[SSL_PKEY_RSA_SIGN]);
+	rsa_sign=((cpk->x509 != NULL) && (cpk->privatekey != NULL))?1:0;
+	cpk= &(c->pkeys[SSL_PKEY_DSA_SIGN]);
+	dsa_sign=((cpk->x509 != NULL) && (cpk->privatekey != NULL))?1:0;
+	cpk= &(c->pkeys[SSL_PKEY_DH_RSA]);
+	dh_rsa=  ((cpk->x509 != NULL) && (cpk->privatekey != NULL))?1:0;
+	dh_rsa_export=(dh_rsa && (EVP_PKEY_size(cpk->privatekey)*8 <= 512))?1:0;
+	cpk= &(c->pkeys[SSL_PKEY_DH_DSA]);
+/* FIX THIS EAY EAY EAY */
+	dh_dsa=  ((cpk->x509 != NULL) && (cpk->privatekey != NULL))?1:0;
+	dh_dsa_export=(dh_dsa && (EVP_PKEY_size(cpk->privatekey)*8 <= 512))?1:0;
+
+	mask=0;
+	emask=0;
+
+#ifdef CIPHER_DEBUG
+	printf("rt=%d dht=%d re=%d rs=%d ds=%d dhr=%d dhd=%d\n",
+		rsa_tmp,dh_tmp,
+		rsa_enc,rsa_sign,dsa_sign,dh_rsa,dh_dsa);
+#endif
+
+	if (rsa_enc || (rsa_tmp && rsa_sign))
+		mask|=SSL_kRSA;
+	if (rsa_enc_export || (rsa_tmp_export && rsa_sign))
+		emask|=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|=SSL_kEDH;
+	if ((dh_tmp_export || dh_rsa_export || dh_dsa_export) &&
+		(rsa_enc || rsa_sign || dsa_sign))
+		emask|=SSL_kEDH;
+#endif
+
+	if (dh_tmp_export) 
+		emask|=SSL_kEDH;
+
+	if (dh_tmp)
+		mask|=SSL_kEDH;
+
+	if (dh_rsa) mask|=SSL_kDHr;
+	if (dh_rsa_export) emask|=SSL_kDHr;
+
+	if (dh_dsa) mask|=SSL_kDHd;
+	if (dh_dsa_export) emask|=SSL_kDHd;
+
+	if (rsa_enc || rsa_sign)
+		{
+		mask|=SSL_aRSA;
+		emask|=SSL_aRSA;
+		}
+
+	if (dsa_sign)
+		{
+		mask|=SSL_aDSS;
+		emask|=SSL_aDSS;
+		}
+
+#ifdef SSL_ALLOW_ADH
+	mask|=SSL_aNULL;
+	emask|=SSL_aNULL;
+#endif
+
+	c->mask=mask;
+	c->export_mask=emask;
+	c->valid=1;
+	}
+
+/* THIS NEEDS CLEANING UP */
+X509 *ssl_get_server_send_cert(s)
+SSL *s;
+	{
+	unsigned long alg,mask,kalg;
+	CERT *c;
+	int i,export;
+
+	c=s->cert;
+	ssl_set_cert_masks(c);
+	alg=s->s3->tmp.new_cipher->algorithms;
+	export=(alg & SSL_EXPORT)?1:0;
+	mask=(export)?c->export_mask:c->mask;
+	kalg=alg&(SSL_MKEY_MASK|SSL_AUTH_MASK);
+
+	if 	(kalg & SSL_kDHr)
+		i=SSL_PKEY_DH_RSA;
+	else if (kalg & SSL_kDHd)
+		i=SSL_PKEY_DH_DSA;
+	else if (kalg & SSL_aDSS)
+		i=SSL_PKEY_DSA_SIGN;
+	else if (kalg & SSL_aRSA)
+		{
+		if (c->pkeys[SSL_PKEY_RSA_ENC].x509 == NULL)
+			i=SSL_PKEY_RSA_SIGN;
+		else
+			i=SSL_PKEY_RSA_ENC;
+		}
+	else /* if (kalg & SSL_aNULL) */
+		{
+		SSLerr(SSL_F_SSL_GET_SERVER_SEND_CERT,SSL_R_INTERNAL_ERROR);
+		return(NULL);
+		}
+	if (c->pkeys[i].x509 == NULL) return(NULL);
+	return(c->pkeys[i].x509);
+	}
+
+EVP_PKEY *ssl_get_sign_pkey(s,cipher)
+SSL *s;
+SSL_CIPHER *cipher;
+	{
+	unsigned long alg;
+	CERT *c;
+
+	alg=cipher->algorithms;
+	c=s->cert;
+
+	if ((alg & SSL_aDSS) &&
+		(c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL))
+		return(c->pkeys[SSL_PKEY_DSA_SIGN].privatekey);
+	else if (alg & 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 & SSL_aNULL) */
+		{
+		SSLerr(SSL_F_SSL_GET_SIGN_PKEY,SSL_R_INTERNAL_ERROR);
+		return(NULL);
+		}
+	}
+
+void ssl_update_cache(s,mode)
+SSL *s;
+int mode;
+	{
+	if ((s->ctx->session_cache_mode & mode)
+		&& (!s->hit)
+		&& SSL_CTX_add_session(s->ctx,s->session)
+		&& (s->ctx->new_session_cb != NULL))
+		{
+		CRYPTO_add(&s->session->references,1,
+			CRYPTO_LOCK_SSL_SESSION);
+		if (!s->ctx->new_session_cb(s,s->session))
+			SSL_SESSION_free(s->session);
+		}
+
+	/* auto flush every 255 connections */
+	if ((!(s->ctx->session_cache_mode &
+		SSL_SESS_CACHE_NO_AUTO_CLEAR)) &&
+		((s->ctx->sess_connect_good & 0xff) == 0))
+		SSL_CTX_flush_sessions(s->ctx,time(NULL));
+	}
+
+SSL_METHOD *SSL_get_ssl_method(s)
+SSL *s;
+	{
+	return(s->method);
+	}
+
+int SSL_set_ssl_method(s,meth)
+SSL *s;
+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(s,i)
+SSL *s;
+int i;
+	{
+	int reason;
+	BIO *bio;
+
+	if (i > 0) return(SSL_ERROR_NONE);
+
+	if (ERR_peek_error() != 0)
+		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))
+			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
+				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))
+			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
+				return(SSL_ERROR_SYSCALL);
+			}
+		}
+	if ((i < 0) && SSL_want_x509_lookup(s))
+		{
+		return(SSL_ERROR_WANT_X509_LOOKUP);
+		}
+
+	if (i == 0)
+		{
+		if (s->version == 2)
+			{
+			/* assume it is the socket being closed */
+			return(SSL_ERROR_ZERO_RETURN);
+			}
+		else
+			{
+			if ((s->shutdown & SSL_RECEIVED_SHUTDOWN) &&
+				(s->s3->warn_alert == SSL3_AD_CLOSE_NOTIFY))
+				return(SSL_ERROR_ZERO_RETURN);
+			}
+		}
+	return(SSL_ERROR_SYSCALL);
+	}
+
+int SSL_do_handshake(s)
+SSL *s;
+	{
+	if (s->handshake_func == NULL)
+		{
+		SSLerr(SSL_F_SSL_DO_HANDSHAKE,SSL_R_INTERNAL_ERROR);
+		return(-1);
+		}
+	if (SSL_in_init(s) || SSL_in_before(s))
+		return(s->handshake_func(s));
+	else
+		return(1);
+	}
+
+/* For the next 2 functions, SSL_clear() sets shutdown and so
+ * one of these calls will reset it */
+void SSL_set_accept_state(s)
+SSL *s;
+	{
+	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);
+	}
+
+void SSL_set_connect_state(s)
+SSL *s;
+	{
+	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);
+	}
+
+int ssl_undefined_function(s)
+SSL *s;
+	{
+	SSLerr(SSL_F_SSL_UNDEFINED_FUNCTION,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+	return(0);
+	}
+
+SSL_METHOD *ssl_bad_method(ver)
+int ver;
+	{
+	SSLerr(SSL_F_SSL_BAD_METHOD,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+	return(NULL);
+	}
+
+char *SSL_get_version(s)
+SSL *s;
+	{
+	if (s->version == 3)
+		return("SSLv3");
+	else if (s->version == 2)
+		return("SSLv2");
+	else
+		return("unknown");
+	}
+
+SSL *SSL_dup(s)
+SSL *s;
+        {
+	STACK *sk;
+	X509_NAME *xn;
+        SSL *ret;
+	int i;
+		 
+	if ((ret=SSL_new(SSL_get_SSL_CTX(s))) == NULL) return(NULL);
+			  
+	/* This copies version, session-id, SSL_METHOD and 'cert' */
+	SSL_copy_session_id(ret,s);
+
+	SSL_set_read_ahead(ret,SSL_get_read_ahead(s));
+	SSL_set_verify(ret,SSL_get_verify_mode(s),
+		SSL_get_verify_callback(s));
+
+	SSL_set_info_callback(ret,SSL_get_info_callback(s));
+	
+	ret->debug=s->debug;
+
+	/* copy app data, a little dangerous perhaps */
+	SSL_set_app_data(ret,SSL_get_app_data(s));
+
+	/* 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->rbio))
+				goto err;
+			}
+		else
+			ret->wbio=ret->rbio;
+		}
+
+	/* dup the cipher_list and cipher_list_by_id stacks */
+	if (s->cipher_list != NULL)
+		{
+		if ((ret->cipher_list=sk_dup(s->cipher_list)) == NULL)
+			goto err;
+		}
+	if (s->cipher_list_by_id != NULL)
+		if ((ret->cipher_list_by_id=sk_dup(s->cipher_list_by_id))
+			== NULL)
+			goto err;
+
+	/* Dup the client_CA list */
+	if (s->client_CA != NULL)
+		{
+		if ((sk=sk_dup(s->client_CA)) == NULL) goto err;
+		ret->client_CA=sk;
+		for (i=0; i<sk_num(sk); i++)
+			{
+			xn=(X509_NAME *)sk_value(sk,i);
+			if ((sk_value(sk,i)=(char *)X509_NAME_dup(xn)) == NULL)
+				{
+				X509_NAME_free(xn);
+				goto err;
+				}
+			}
+		}
+
+	ret->shutdown=s->shutdown;
+	ret->state=s->state;
+	ret->handshake_func=s->handshake_func;
+
+	if (0)
+		{
+err:
+		if (ret != NULL) SSL_free(ret);
+		ret=NULL;
+		}
+	return(ret);
+	}
+
+void ssl_clear_cipher_ctx(s)
+SSL *s;
+	{
+        if (s->enc_read_ctx != NULL)
+                {
+                EVP_CIPHER_CTX_cleanup(s->enc_read_ctx);
+                Free(s->enc_read_ctx);
+                s->enc_read_ctx=NULL;
+                }
+        if (s->enc_write_ctx != NULL)
+                {
+                EVP_CIPHER_CTX_cleanup(s->enc_write_ctx);
+                Free(s->enc_write_ctx);
+                s->enc_write_ctx=NULL;
+                }
+	}
+
+X509 *SSL_get_certificate(s)
+SSL *s;
+	{
+	if (s->cert != NULL)
+		return(s->cert->key->x509);
+	else
+		return(NULL);
+	}
+
+EVP_PKEY *SSL_get_privatekey(s)
+SSL *s;
+	{
+	if (s->cert != NULL)
+		return(s->cert->key->privatekey);
+	else
+		return(NULL);
+	}
+
+SSL_CIPHER *SSL_get_current_cipher(s)
+SSL *s;
+	{
+        if ((s->session != NULL) && (s->session->cipher != NULL))
+                return(s->session->cipher);
+        return(NULL);
+	}
+
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
new file mode 100644
index 0000000..ef3a70e
--- /dev/null
+++ b/ssl/ssl_locl.h
@@ -0,0 +1,520 @@
+/* ssl/ssl_locl.h */
+/* Copyright (C) 1995-1997 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_SSL_LOCL_H
+#define HEADER_SSL_LOCL_H
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef FLAT_INC
+#include "e_os.h"
+#else
+#include "../e_os.h"
+#endif
+
+#include "buffer.h"
+#include "bio.h"
+#include "crypto.h"
+#include "evp.h"
+#include "stack.h"
+#include "x509.h"
+#include "err.h"
+#include "ssl.h"
+
+
+#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))
+
+/* 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)++)))<< 8, \
+			 s|=((unsigned int)(*((c)++))))
+#define s2n(s,c)	(*((c)++)=(unsigned char)(((s)>> 8)&0xff), \
+			 *((c)++)=(unsigned char)(((s)    )&0xff))
+
+#define n2l3(c,l)	(l =((unsigned long)(*((c)++)))<<16, \
+			 l|=((unsigned long)(*((c)++)))<< 8, \
+			 l|=((unsigned long)(*((c)++))))
+
+#define l2n3(l,c)	(*((c)++)=(unsigned char)(((l)>>16)&0xff), \
+			 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
+			 *((c)++)=(unsigned char)(((l)    )&0xff))
+
+/* 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 SSL_MKEY_MASK		0x0000001FL
+#define SSL_kRSA		0x00000001L /* RSA key exchange */
+#define SSL_kDHr		0x00000002L /* DH cert RSA CA cert */
+#define SSL_kDHd		0x00000004L /* DH cert DSA CA cert */
+#define SSL_kFZA		0x00000008L
+#define SSL_kEDH		0x00000010L /* tmp DH key no DH cert */
+#define SSL_EDH			(SSL_kEDH|(SSL_AUTH_MASK^SSL_aNULL))
+
+#define SSL_AUTH_MASK		0x000003e0L
+#define SSL_aRSA		0x00000020L /* Authenticate with RSA */
+#define SSL_aDSS 		0x00000040L /* Authenticate with DSS */
+#define SSL_DSS 		SSL_aDSS
+#define SSL_aFZA 		0x00000080L
+#define SSL_aNULL 		0x00000100L /* no Authenticate, ADH */
+#define SSL_aDH 		0x00000200L /* no Authenticate, ADH */
+
+#define SSL_NULL		(SSL_eNULL)
+#define SSL_ADH			(SSL_kEDH|SSL_aNULL)
+#define SSL_RSA			(SSL_kRSA|SSL_aRSA)
+#define SSL_DH			(SSL_kDHr|SSL_kDHd|SSL_kEDH)
+#define SSL_FZA			(SSL_aFZA|SSL_kFZA|SSL_eFZA)
+
+#define SSL_ENC_MASK		0x0001Fc00L
+#define SSL_DES			0x00000400L
+#define SSL_3DES		0x00000800L
+#define SSL_RC4			0x00001000L
+#define SSL_RC2			0x00002000L
+#define SSL_IDEA		0x00004000L
+#define SSL_eFZA		0x00008000L
+#define SSL_eNULL		0x00010000L
+
+#define SSL_MAC_MASK		0x000e0000L
+#define SSL_MD5			0x00020000L
+#define SSL_SHA0		0x00040000L
+#define SSL_SHA1		0x00080000L
+#define SSL_SHA			(SSL_SHA0|SSL_SHA1)
+
+#define SSL_EXP_MASK		0x00300000L
+#define SSL_EXP			0x00100000L
+#define SSL_NOT_EXP		0x00200000L
+#define SSL_EXPORT		SSL_EXP
+
+#define SSL_SSL_MASK		0x00c00000L
+#define SSL_SSLV2		0x00400000L
+#define SSL_SSLV3		0x00800000L
+
+#define SSL_STRONG_MASK		0x07000000L
+#define SSL_LOW			0x01000000L
+#define SSL_MEDIUM		0x02000000L
+#define SSL_HIGH		0x04000000L
+
+/* we have used 0fffffff - 4 bits left to go */
+#define SSL_ALL			0xffffffffL
+#define SSL_ALL_CIPHERS		(SSL_MKEY_MASK|SSL_AUTH_MASK|SSL_ENC_MASK|\
+				SSL_MAC_MASK|SSL_EXP_MASK)
+
+/* 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_NUM		5
+
+/* 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
+*/
+
+typedef struct cert_pkey_st
+	{
+	X509 *x509;
+/*	EVP_PKEY *publickey; *//* when extracted */
+	EVP_PKEY *privatekey;
+	} CERT_PKEY;
+
+typedef struct cert_st
+	{
+	int cert_type;
+
+#ifdef undef
+	X509 *x509;
+	EVP_PKEY *publickey; /* when extracted */
+	EVP_PKEY *privatekey;
+
+	pkeys[SSL_PKEY_RSA_ENC].x509
+/*	pkeys[SSL_PKEY_RSA_ENC].publickey */
+	pkeys[SSL_PKEY_RSA_ENC].privatekey
+#endif
+
+	/* Current active set */
+	CERT_PKEY *key;
+
+	/* The following masks are for the key and auth
+	 * algorithms that are supported by the certs below */
+	int valid;
+	unsigned long mask;
+	unsigned long export_mask;
+
+	RSA *rsa_tmp;
+	DH *dh_tmp;
+	RSA *(*rsa_tmp_cb)();
+	DH *(*dh_tmp_cb)();
+	CERT_PKEY pkeys[SSL_PKEY_NUM];
+
+	STACK *cert_chain;
+
+	int references;
+	} 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	*/ 
+
+#ifndef NOPROTO
+#define FP_ICC  (int (*)(const void *,const void *))
+#else
+#define FP_ICC
+#endif
+
+#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))
+
+extern unsigned char ssl3_client_finished_const[4];
+extern unsigned char ssl3_server_finished_const[4];
+
+extern SSL_CIPHER ssl2_ciphers[];
+extern SSL_CIPHER ssl3_ciphers[];
+
+#ifndef NOPROTO
+
+SSL_METHOD *ssl_bad_method(int ver);
+SSL_METHOD *sslv2_base_method(void);
+SSL_METHOD *sslv23_base_method(void);
+SSL_METHOD *sslv3_base_method(void);
+
+void ssl_clear_cipher_ctx(SSL *s);
+int ssl_clear_bad_session(SSL *s);
+CERT *ssl_cert_new(void);
+void ssl_cert_free(CERT *c);
+int ssl_set_cert_type(CERT *c, int type);
+int ssl_get_new_session(SSL *s, int session);
+int ssl_get_prev_session(SSL *s, int len, unsigned char *session);
+int ssl_cipher_id_cmp(SSL_CIPHER *a,SSL_CIPHER *b);
+int ssl_cipher_ptr_id_cmp(SSL_CIPHER **ap,SSL_CIPHER **bp);
+STACK *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num,STACK **skp);
+int ssl_cipher_list_to_bytes(SSL *s,STACK *sk,unsigned char *p);
+STACK *ssl_create_cipher_list(SSL_METHOD *meth,STACK **pref,
+	STACK **sorted,char *str);
+void ssl_update_cache(SSL *s, int mode);
+int ssl_cipher_get_evp(SSL_CIPHER *c, EVP_CIPHER **enc, EVP_MD **md);
+int ssl_verify_cert_chain(SSL *s,STACK *sk);
+int ssl_undefined_function(SSL *s);
+X509 *ssl_get_server_send_cert(SSL *);
+EVP_PKEY *ssl_get_sign_pkey(SSL *,SSL_CIPHER *);
+int ssl_cert_type(X509 *x,EVP_PKEY *pkey);
+void ssl_set_cert_masks(CERT *c);
+STACK *ssl_get_ciphers_by_id(SSL *s);
+int ssl_verify_alarm_type(int type);
+
+int ssl2_enc_init(SSL *s, int client);
+void 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);
+SSL_CIPHER *ssl2_get_cipher_by_char(unsigned char *p);
+int ssl2_put_cipher_by_char(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, unsigned char *data);
+void ssl2_return_error(SSL *s,int reason);
+void ssl2_write_error(SSL *s);
+int ssl2_num_ciphers(void);
+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, char *buf, int len);
+int	ssl2_peek(SSL *s, char *buf, int len);
+int	ssl2_write(SSL *s, const char *buf, int len);
+int	ssl2_shutdown(SSL *s);
+void	ssl2_clear(SSL *s);
+long	ssl2_ctrl(SSL *s,int cmd, long larg, char *parg);
+long	ssl2_ctx_ctrl(SSL_CTX *s,int cmd, long larg, char *parg);
+int	ssl2_pending(SSL *s);
+
+SSL_CIPHER *ssl3_get_cipher_by_char(unsigned char *p);
+int ssl3_put_cipher_by_char(SSL_CIPHER *c,unsigned char *p);
+void ssl3_init_finished_mac(SSL *s);
+int ssl3_send_server_certificate(SSL *s);
+int ssl3_get_finished(SSL *s,int state_a,int state_b,unsigned char *sender);
+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);
+void 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, unsigned char *sender);
+int ssl3_num_ciphers(void);
+SSL_CIPHER *ssl3_get_cipher(unsigned int u);
+int ssl3_renegotiate(SSL *ssl); 
+int ssl3_dispatch_alert(SSL *s);
+int ssl3_read_bytes(SSL *s, int type, char *buf, int len);
+void ssl3_generate_key_block(SSL *s, unsigned char *km, int num);
+int ssl3_part_read(SSL *s, int i);
+int ssl3_write_bytes(SSL *s, int type, char *buf, int len);
+int ssl3_final_finish_mac(SSL *s, EVP_MD_CTX *in_ctx,
+	unsigned char *sender, unsigned char *p);
+void ssl3_finish_mac(SSL *s, unsigned char *buf, int len);
+int ssl3_enc(SSL *s, int send_data);
+int ssl3_mac(SSL *ssl, unsigned char *md, int send_data);
+unsigned long ssl3_output_cert_chain(SSL *s, X509 *x);
+SSL_CIPHER *ssl3_choose_cipher(SSL *ssl,STACK *have,STACK *pref);
+int	ssl3_setup_buffers(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, char *buf, int len);
+int	ssl3_peek(SSL *s,char *buf, int len);
+int	ssl3_write(SSL *s, const char *buf, int len);
+int	ssl3_shutdown(SSL *s);
+void	ssl3_clear(SSL *s);
+long	ssl3_ctrl(SSL *s,int cmd, long larg, char *parg);
+long	ssl3_ctx_ctrl(SSL_CTX *s,int cmd, long larg, char *parg);
+int	ssl3_pending(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);
+
+#else
+
+SSL_METHOD *ssl_bad_method();
+SSL_METHOD *sslv2_base_method();
+SSL_METHOD *sslv23_base_method();
+SSL_METHOD *sslv3_base_method();
+
+void ssl_clear_cipher_ctx();
+int ssl_clear_bad_session();
+CERT *ssl_cert_new();
+void ssl_cert_free();
+int ssl_set_cert_type();
+int ssl_get_new_session();
+int ssl_get_prev_session();
+int ssl_cipher_id_cmp();
+int ssl_cipher_ptr_id_cmp();
+STACK *ssl_bytes_to_cipher_list();
+int ssl_cipher_list_to_bytes();
+STACK *ssl_create_cipher_list();
+void ssl_update_cache();
+int ssl_session_get_ciphers();
+int ssl_verify_cert_chain();
+int ssl_undefined_function();
+X509 *ssl_get_server_send_cert();
+EVP_PKEY *ssl_get_sign_pkey();
+int ssl_cert_type();
+void ssl_set_cert_masks();
+STACK *ssl_get_ciphers_by_id();
+int ssl_verify_alarm_type();
+
+int ssl2_enc_init();
+void ssl2_generate_key_material();
+void ssl2_enc();
+void ssl2_mac();
+SSL_CIPHER *ssl2_get_cipher_by_char();
+int ssl2_put_cipher_by_char();
+int ssl2_part_read();
+int ssl2_do_write();
+int ssl2_set_certificate();
+void ssl2_return_error();
+void ssl2_write_error();
+int ssl2_num_ciphers();
+SSL_CIPHER *ssl2_get_cipher();
+int	ssl2_new();
+void	ssl2_free();
+int	ssl2_accept();
+int	ssl2_connect();
+int	ssl2_read();
+int	ssl2_peek();
+int	ssl2_write();
+int	ssl2_shutdown();
+void	ssl2_clear();
+long	ssl2_ctrl();
+long	ssl2_ctx_ctrl();
+int	ssl2_pending();
+
+SSL_CIPHER *ssl3_get_cipher_by_char();
+int ssl3_put_cipher_by_char();
+void ssl3_init_finished_mac();
+int ssl3_send_server_certificate();
+int ssl3_get_finished();
+int ssl3_setup_key_block();
+int ssl3_send_change_cipher_spec();
+int ssl3_change_cipher_state();
+void ssl3_cleanup_key_block();
+int ssl3_do_write();
+void ssl3_send_alert();
+int ssl3_generate_master_secret();
+int ssl3_get_req_cert_type();
+long ssl3_get_message();
+int ssl3_send_finished();
+int ssl3_num_ciphers();
+SSL_CIPHER *ssl3_get_cipher();
+int ssl3_renegotiate();
+int ssl3_dispatch_alert();
+int ssl3_read_bytes();
+void ssl3_generate_key_block();
+int ssl3_part_read();
+int ssl3_write_bytes();
+int ssl3_final_finish_mac();
+void ssl3_finish_mac();
+int ssl3_enc();
+int ssl3_mac();
+unsigned long ssl3_output_cert_chain();
+SSL_CIPHER *ssl3_choose_cipher();
+int	ssl3_setup_buffers();
+int	ssl3_new();
+void	ssl3_free();
+int	ssl3_accept();
+int	ssl3_connect();
+int	ssl3_read();
+int	ssl3_peek();
+int	ssl3_write();
+int	ssl3_shutdown();
+void	ssl3_clear();
+long	ssl3_ctrl();
+long	ssl3_ctx_ctrl();
+int	ssl3_pending();
+
+int ssl23_accept();
+int ssl23_connect();
+int ssl23_read_bytes();
+int ssl23_write_bytes();
+
+#endif
+
+#endif
diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c
new file mode 100644
index 0000000..3a7b8d3
--- /dev/null
+++ b/ssl/ssl_rsa.c
@@ -0,0 +1,840 @@
+/* ssl/ssl_rsa.c */
+/* Copyright (C) 1995-1997 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 "bio.h"
+#include "objects.h"
+#include "evp.h"
+#include "x509.h"
+#include "pem.h"
+#include "ssl_locl.h"
+
+#ifndef NOPROTO
+static int ssl_set_cert(CERT *c, X509 *x509);
+static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey);
+#else
+static int ssl_set_cert();
+static int ssl_set_pkey();
+#endif
+
+int SSL_use_certificate(ssl, x)
+SSL *ssl;
+X509 *x;
+	{
+	CERT *c;
+
+	if (x == NULL)
+		{
+		SSLerr(SSL_F_SSL_USE_CERTIFICATE,ERR_R_PASSED_NULL_PARAMETER);
+		return(0);
+		}
+	if ((ssl->cert == NULL) || (ssl->cert == ssl->ctx->default_cert))
+		{
+		c=ssl_cert_new();
+		if (c == NULL)
+			{
+			SSLerr(SSL_F_SSL_USE_CERTIFICATE,ERR_R_MALLOC_FAILURE);
+			return(0);
+			}
+		if (ssl->cert != NULL) ssl_cert_free(ssl->cert);
+		ssl->cert=c;
+		}
+	c=ssl->cert;
+
+	return(ssl_set_cert(c,x));
+	}
+
+int SSL_use_certificate_file(ssl, file, type)
+SSL *ssl;
+char *file;
+int type;
+	{
+	int j;
+	BIO *in;
+	int ret=0;
+	X509 *x=NULL;
+
+#ifdef WIN16
+	in=BIO_new(BIO_s_file_internal_w16());
+#else
+	in=BIO_new(BIO_s_file());
+#endif
+	if (in == NULL)
+		{
+		SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE,ERR_R_BUF_LIB);
+		goto end;
+		}
+
+	if (BIO_read_filename(in,file) <= 0)
+		{
+		SYSerr(SYS_F_FOPEN,errno);
+		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);
+		}
+	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);
+	}
+
+int SSL_use_certificate_ASN1(ssl, len, d)
+SSL *ssl;
+int len;
+unsigned char *d;
+	{
+	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 NO_RSA
+int SSL_use_RSAPrivateKey(ssl, rsa)
+SSL *ssl;
+RSA *rsa;
+	{
+	CERT *c;
+	EVP_PKEY *pkey;
+	int ret;
+
+	if (rsa == NULL)
+		{
+		SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER);
+		return(0);
+		}
+
+        if ((ssl->cert == NULL) || (ssl->cert == ssl->ctx->default_cert))
+                {
+                c=ssl_cert_new();
+		if (c == NULL)
+			{
+			SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY,ERR_R_MALLOC_FAILURE);
+			return(0);
+			}
+                if (ssl->cert != NULL) ssl_cert_free(ssl->cert);
+		ssl->cert=c;
+		}
+	c=ssl->cert;
+	if ((pkey=EVP_PKEY_new()) == NULL)
+		{
+		SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY,ERR_R_EVP_LIB);
+		return(0);
+		}
+
+	CRYPTO_add(&rsa->references,1,CRYPTO_LOCK_RSA);
+	EVP_PKEY_assign_RSA(pkey,rsa);
+
+	ret=ssl_set_pkey(c,pkey);
+	EVP_PKEY_free(pkey);
+	return(ret);
+	}
+#endif
+
+static int ssl_set_pkey(c,pkey)
+CERT *c;
+EVP_PKEY *pkey;
+	{
+	int i,ok=0,bad=0;
+
+	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)
+		{
+		if (!X509_check_private_key(c->pkeys[i].x509,pkey))
+			{
+			if ((i == SSL_PKEY_DH_RSA) || (i == SSL_PKEY_DH_DSA))
+				{
+				i=(i == SSL_PKEY_DH_RSA)?
+					SSL_PKEY_DH_DSA:SSL_PKEY_DH_RSA;
+
+				if (c->pkeys[i].x509 == NULL)
+					ok=1;
+				else
+					{
+					if (!X509_check_private_key(
+						c->pkeys[i].x509,pkey))
+						bad=1;
+					else
+						ok=1;
+					}
+				}
+			else
+				bad=1;
+			}
+		else
+			ok=1;
+		}
+	else
+		ok=1;
+
+	if (bad)
+		{
+		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 NO_RSA
+int SSL_use_RSAPrivateKey_file(ssl, file, type)
+SSL *ssl;
+char *file;
+int type;
+	{
+	int j,ret=0;
+	BIO *in;
+	RSA *rsa=NULL;
+
+#ifdef WIN16
+	in=BIO_new(BIO_s_file_internal_w16());
+#else
+	in=BIO_new(BIO_s_file());
+#endif
+	if (in == NULL)
+		{
+		SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE,ERR_R_BUF_LIB);
+		goto end;
+		}
+
+	if (BIO_read_filename(in,file) <= 0)
+		{
+		SYSerr(SYS_F_FOPEN,errno);
+		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);
+		}
+	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);
+	}
+
+int SSL_use_RSAPrivateKey_ASN1(ssl,d,len)
+SSL *ssl;
+unsigned char *d;
+long len;
+	{
+	int ret;
+	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 /* !NO_RSA */
+
+int SSL_use_PrivateKey(ssl, pkey)
+SSL *ssl;
+EVP_PKEY *pkey;
+	{
+	CERT *c;
+	int ret;
+
+	if (pkey == NULL)
+		{
+		SSLerr(SSL_F_SSL_USE_PRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER);
+		return(0);
+		}
+
+        if ((ssl->cert == NULL) || (ssl->cert == ssl->ctx->default_cert))
+                {
+                c=ssl_cert_new();
+		if (c == NULL)
+			{
+			SSLerr(SSL_F_SSL_USE_PRIVATEKEY,ERR_R_MALLOC_FAILURE);
+			return(0);
+			}
+                if (ssl->cert != NULL) ssl_cert_free(ssl->cert);
+		ssl->cert=c;
+		}
+	c=ssl->cert;
+
+	ret=ssl_set_pkey(c,pkey);
+	return(ret);
+	}
+
+int SSL_use_PrivateKey_file(ssl, file, type)
+SSL *ssl;
+char *file;
+int type;
+	{
+	int j,ret=0;
+	BIO *in;
+	EVP_PKEY *pkey=NULL;
+
+#ifdef WIN16
+	in=BIO_new(BIO_s_file_internal_w16());
+#else
+	in=BIO_new(BIO_s_file());
+#endif
+	if (in == NULL)
+		{
+		SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE,ERR_R_BUF_LIB);
+		goto end;
+		}
+
+	if (BIO_read_filename(in,file) <= 0)
+		{
+		SYSerr(SYS_F_FOPEN,errno);
+		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);
+		}
+	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);
+	}
+
+int SSL_use_PrivateKey_ASN1(type,ssl,d,len)
+int type;
+SSL *ssl;
+unsigned char *d;
+long len;
+	{
+	int ret;
+	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(ctx, x)
+SSL_CTX *ctx;
+X509 *x;
+	{
+	CERT *c;
+
+	if (x == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE,ERR_R_PASSED_NULL_PARAMETER);
+		return(0);
+		}
+
+	if (ctx->default_cert == NULL)
+		{
+		c=ssl_cert_new();
+		if (c == NULL)
+			{
+			SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE,ERR_R_MALLOC_FAILURE);
+			return(0);
+			}
+		ctx->default_cert=c;
+		}
+	c=ctx->default_cert;
+
+	return(ssl_set_cert(c,x));
+	}
+
+static int ssl_set_cert(c,x)
+CERT *c;
+X509 *x;
+	{
+	EVP_PKEY *pkey;
+	int i,ok=0,bad=0;
+
+	pkey=X509_get_pubkey(x);
+	if (pkey == NULL)
+		{
+		SSLerr(SSL_F_SSL_SET_PKEY,SSL_R_X509_LIB);
+		return(0);
+		}
+
+	i=ssl_cert_type(x,pkey);
+	if (i < 0)
+		{
+		SSLerr(SSL_F_SSL_SET_PKEY,SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+		return(0);
+		}
+
+	if (c->pkeys[i].privatekey != NULL)
+		{
+		if (!X509_check_private_key(x,c->pkeys[i].privatekey))
+			{
+			if ((i == SSL_PKEY_DH_RSA) || (i == SSL_PKEY_DH_DSA))
+				{
+				i=(i == SSL_PKEY_DH_RSA)?
+					SSL_PKEY_DH_DSA:SSL_PKEY_DH_RSA;
+
+				if (c->pkeys[i].privatekey == NULL)
+					ok=1;
+				else
+					{
+					if (!X509_check_private_key(x,
+						c->pkeys[i].privatekey))
+						bad=1;
+					else
+						ok=1;
+					}
+				}
+			else
+				bad=1;
+			}
+		else
+			ok=1;
+		}
+	else
+		ok=1;
+
+	if (bad)
+		{
+		EVP_PKEY_free(c->pkeys[i].privatekey);
+		c->pkeys[i].privatekey=NULL;
+		}
+
+	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);
+	}
+
+int SSL_CTX_use_certificate_file(ctx, file, type)
+SSL_CTX *ctx;
+char *file;
+int type;
+	{
+	int j;
+	BIO *in;
+	int ret=0;
+	X509 *x=NULL;
+
+#ifdef WIN16
+	in=BIO_new(BIO_s_file_internal_w16());
+#else
+	in=BIO_new(BIO_s_file());
+#endif
+	if (in == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,ERR_R_BUF_LIB);
+		goto end;
+		}
+
+	if (BIO_read_filename(in,file) <= 0)
+		{
+		SYSerr(SYS_F_FOPEN,errno);
+		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);
+		}
+	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);
+	}
+
+int SSL_CTX_use_certificate_ASN1(ctx, len, d)
+SSL_CTX *ctx;
+int len;
+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 NO_RSA
+int SSL_CTX_use_RSAPrivateKey(ctx, rsa)
+SSL_CTX *ctx;
+RSA *rsa;
+	{
+	int ret;
+	CERT *c;
+	EVP_PKEY *pkey;
+
+	if (rsa == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER);
+		return(0);
+		}
+	if (ctx->default_cert == NULL)
+		{
+		c=ssl_cert_new();
+		if (c == NULL)
+			{
+			SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY,ERR_R_MALLOC_FAILURE);
+			return(0);
+			}
+		ctx->default_cert=c;
+		}
+	c=ctx->default_cert;
+
+	if ((pkey=EVP_PKEY_new()) == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY,ERR_R_EVP_LIB);
+		return(0);
+		}
+
+	CRYPTO_add(&rsa->references,1,CRYPTO_LOCK_RSA);
+	EVP_PKEY_assign_RSA(pkey,rsa);
+
+	ret=ssl_set_pkey(c,pkey);
+	EVP_PKEY_free(pkey);
+	return(ret);
+	}
+
+int SSL_CTX_use_RSAPrivateKey_file(ctx, file, type)
+SSL_CTX *ctx;
+char *file;
+int type;
+	{
+	int j,ret=0;
+	BIO *in;
+	RSA *rsa=NULL;
+
+#ifdef WIN16
+	in=BIO_new(BIO_s_file_internal_w16());
+#else
+	in=BIO_new(BIO_s_file());
+#endif
+	if (in == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE,ERR_R_BUF_LIB);
+		goto end;
+		}
+
+	if (BIO_read_filename(in,file) <= 0)
+		{
+		SYSerr(SYS_F_FOPEN,errno);
+		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);
+		}
+	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);
+	}
+
+int SSL_CTX_use_RSAPrivateKey_ASN1(ctx,d,len)
+SSL_CTX *ctx;
+unsigned char *d;
+long len;
+	{
+	int ret;
+	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 /* !NO_RSA */
+
+int SSL_CTX_use_PrivateKey(ctx, pkey)
+SSL_CTX *ctx;
+EVP_PKEY *pkey;
+	{
+	CERT *c;
+
+	if (pkey == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER);
+		return(0);
+		}
+		
+	if (ctx->default_cert == NULL)
+		{
+		c=ssl_cert_new();
+		if (c == NULL)
+			{
+			SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY,ERR_R_MALLOC_FAILURE);
+			return(0);
+			}
+		ctx->default_cert=c;
+		}
+	c=ctx->default_cert;
+
+	return(ssl_set_pkey(c,pkey));
+	}
+
+int SSL_CTX_use_PrivateKey_file(ctx, file, type)
+SSL_CTX *ctx;
+char *file;
+int type;
+	{
+	int j,ret=0;
+	BIO *in;
+	EVP_PKEY *pkey=NULL;
+
+#ifdef WIN16
+	in=BIO_new(BIO_s_file_internal_w16());
+#else
+	in=BIO_new(BIO_s_file());
+#endif
+	if (in == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE,ERR_R_BUF_LIB);
+		goto end;
+		}
+
+	if (BIO_read_filename(in,file) <= 0)
+		{
+		SYSerr(SYS_F_FOPEN,errno);
+		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);
+		}
+	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);
+	}
+
+int SSL_CTX_use_PrivateKey_ASN1(type,ctx,d,len)
+int type;
+SSL_CTX *ctx;
+unsigned char *d;
+long len;
+	{
+	int ret;
+	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);
+	}
+
+
diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c
new file mode 100644
index 0000000..af65c65
--- /dev/null
+++ b/ssl/ssl_sess.c
@@ -0,0 +1,425 @@
+/* ssl/ssl_sess.c */
+/* Copyright (C) 1995-1997 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 "lhash.h"
+#include "rand.h"
+#include "ssl_locl.h"
+
+SSL_SESSION *SSL_SESSION_new()
+	{
+	SSL_SESSION *ss;
+
+	ss=(SSL_SESSION *)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->references=1;
+	ss->timeout=60*5+4; /* 5 minute timeout by default */
+	ss->time=time(NULL);
+	return(ss);
+	}
+
+int ssl_get_new_session(s, session)
+SSL *s;
+int session;
+	{
+	SSL_SESSION *ss=NULL;
+
+	if ((ss=SSL_SESSION_new()) == NULL) return(0);
+
+	/* If the context has a default timeout, use it */
+	if (s->ctx->session_timeout != 0)
+		ss->timeout=SSL_get_default_timeout(s);
+
+	if (s->session != NULL)
+		{
+		SSL_SESSION_free(s->session);
+		s->session=NULL;
+		}
+
+	if (session)
+		{
+		if (s->version == SSL2_CLIENT_VERSION)
+			{
+			ss->ssl_version=2;
+			ss->session_id_length=SSL2_SSL_SESSION_ID_LENGTH;
+			}
+		else if (s->version == SSL3_VERSION_MAJOR)
+			{
+			ss->ssl_version=3;
+			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);
+			}
+
+		for (;;)
+			{
+			SSL_SESSION *r;
+
+			RAND_bytes(ss->session_id,ss->session_id_length);
+			CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
+			r=(SSL_SESSION *)lh_retrieve(s->ctx->sessions,
+				(char *)ss);
+			CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
+			if (r == NULL) break;
+			/* else - woops a session_id match */
+			}
+		}
+	else
+		{
+		ss->session_id_length=0;
+		}
+
+	s->session=ss;
+	ss->ssl_version=s->version;
+
+	return(1);
+	}
+
+int ssl_get_prev_session(s, len, session)
+SSL *s;
+int len;
+unsigned char *session;
+	{
+	SSL_SESSION *ret,data;
+
+	/* conn_init();*/
+	data.ssl_version=s->version;
+	data.session_id_length=len;
+	if (len > SSL_MAX_SSL_SESSION_ID_LENGTH)
+		return(0);
+	memcpy(data.session_id,session,len);;
+
+	CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
+	ret=(SSL_SESSION *)lh_retrieve(s->ctx->sessions,(char *)&data);
+	CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
+
+	if (ret == NULL)
+		{
+		int copy=1;
+
+		s->ctx->sess_miss++;
+		ret=NULL;
+		if ((s->ctx->get_session_cb != NULL) &&
+			((ret=s->ctx->get_session_cb(s,session,len,&copy))
+				!= NULL))
+			{
+			s->ctx->sess_cb_hit++;
+
+			/* The following should not return 1, otherwise,
+			 * things are very strange */
+			SSL_CTX_add_session(s->ctx,ret);
+			/* auto free it */
+			if (!copy)
+				SSL_SESSION_free(ret);
+			}
+		if (ret == NULL) return(0);
+		}
+
+	if (ret->cipher == NULL)
+		{
+		char buf[5],*p;
+		unsigned long l;
+
+		p=buf;
+		l=ret->cipher_id;
+		l2n(l,p);
+		if (ret->ssl_version == 3)
+			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)
+			return(0);
+		}
+
+	/* If a thread got the session, then 'swaped', and another got
+	 * it and then due to a time-out decided to '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);
+
+	if ((long)(ret->time+ret->timeout) < (long)time(NULL)) /* timeout */
+		{
+		s->ctx->sess_timeout++;
+		/* remove it from the cache */
+		SSL_CTX_remove_session(s->ctx,ret);
+		SSL_SESSION_free(ret);		/* again to actually Free it */
+		return(0);
+		}
+
+	s->ctx->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;
+	return(1);
+	}
+
+int SSL_CTX_add_session(ctx,c)
+SSL_CTX *ctx;
+SSL_SESSION *c;
+	{
+	SSL_SESSION *s;
+
+	/* conn_init(); */
+	CRYPTO_add(&c->references,1,CRYPTO_LOCK_SSL_SESSION);
+
+	CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
+	s=(SSL_SESSION *)lh_insert(ctx->sessions,(char *)c);
+	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
+
+	/* If the same session if is being 're-added', Free the old
+	 * one when the last person stops using it.
+	 * This will also work if it is alread in the cache.
+	 * The references will go up and then down :-) */
+	if (s != NULL)
+		{
+		SSL_SESSION_free(s);
+		return(0);
+		}
+	else
+		return(1);
+	}
+
+int SSL_CTX_remove_session(ctx,c)
+SSL_CTX *ctx;
+SSL_SESSION *c;
+	{
+	SSL_SESSION *r;
+	int ret=0;
+
+	if ((c->session_id_length != 0) && (c != NULL))
+		{
+		CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
+		r=(SSL_SESSION *)lh_delete(ctx->sessions,(char *)c);
+		if (r != NULL) ret=1;
+
+		CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
+
+		if (ret)
+			{
+			r->not_resumable=1;
+			if (ctx->remove_session_cb != NULL)
+				ctx->remove_session_cb(ctx,c);
+			SSL_SESSION_free(r);
+			}
+		}
+	else
+		ret=0;
+	return(ret);
+	}
+
+void SSL_SESSION_free(ss)
+SSL_SESSION *ss;
+	{
+	int i;
+
+	i=CRYPTO_add(&ss->references,-1,CRYPTO_LOCK_SSL_SESSION);
+	if (i > 0) return;
+#ifdef REF_CHECK
+	if (i < 0)
+		{
+		fprintf(stderr,"SSL_SESSION_free, bad reference count\n");
+		abort(); /* ok */
+		}
+#endif
+
+	memset(ss->key_arg,0,SSL_MAX_KEY_ARG_LENGTH);
+	memset(ss->master_key,0,SSL_MAX_MASTER_KEY_LENGTH);
+	memset(ss->session_id,0,SSL_MAX_SSL_SESSION_ID_LENGTH);
+	if (ss->cert != NULL) ssl_cert_free(ss->cert);
+	if (ss->peer != NULL) X509_free(ss->peer);
+	if (ss->ciphers != NULL) sk_free(ss->ciphers);
+	memset(ss,0,sizeof(*ss));
+	Free(ss);
+	}
+
+int SSL_set_session(s, session)
+SSL *s;
+SSL_SESSION *session;
+	{
+	int ret=0;
+	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);
+			session->timeout=SSL_get_default_timeout(s);
+			}
+
+		/* 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;
+		/* CRYPTO_w_unlock(CRYPTO_LOCK_SSL);*/
+		ret=1;
+		}
+	return(ret);
+	}
+
+long SSL_set_timeout(s,t)
+SSL_SESSION *s;
+long t;
+	{
+	if (s == NULL) return(0);
+	s->timeout=t;
+	return(1);
+	}
+
+long SSL_get_timeout(s)
+SSL_SESSION *s;
+	{
+	if (s == NULL) return(0);
+	return(s->timeout);
+	}
+
+long SSL_get_time(s)
+SSL_SESSION *s;
+	{
+	if (s == NULL) return(0);
+	return(s->time);
+	}
+
+long SSL_set_time(s,t)
+SSL_SESSION *s;
+long t;
+	{
+	if (s == NULL) return(0);
+	s->time=t;
+	return(t);
+	}
+
+typedef struct timeout_param_st
+	{
+	SSL_CTX *ctx;
+	long time;
+	LHASH *cache;
+	} TIMEOUT_PARAM;
+
+static void timeout(s,p)
+SSL_SESSION *s;
+TIMEOUT_PARAM *p;
+	{
+	if ((p->time == 0) || (p->time > (s->time+s->timeout))) /* timeout */
+		{
+		lh_delete(p->cache,(char *)s);
+		s->not_resumable=1;
+		if (p->ctx->remove_session_cb != NULL)
+			p->ctx->remove_session_cb(p->ctx,s);
+		SSL_SESSION_free(s);
+		}
+	}
+
+void SSL_CTX_flush_sessions(s,t)
+SSL_CTX *s;
+long t;
+	{
+	unsigned long i;
+	TIMEOUT_PARAM tp;
+
+	tp.ctx=s;
+	tp.cache=SSL_CTX_sessions(s);
+	if (tp.cache == NULL) return;
+	tp.time=t;
+	CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
+	i=tp.cache->down_load;
+	tp.cache->down_load=0;
+	lh_doall_arg(tp.cache,(void (*)())timeout,(char *)&tp);
+	tp.cache->down_load=i;
+	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
+	}
+
+int ssl_clear_bad_session(s)
+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);
+	}
diff --git a/ssl/ssl_stat.c b/ssl/ssl_stat.c
new file mode 100644
index 0000000..328ccc9
--- /dev/null
+++ b/ssl/ssl_stat.c
@@ -0,0 +1,457 @@
+/* ssl/ssl_stat.c */
+/* Copyright (C) 1995-1997 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"
+
+char *SSL_state_string_long(s)
+SSL *s;
+	{
+	char *str;
+
+	switch (s->state)
+		{
+case SSL_ST_BEFORE: str="before SSL initalisation"; break;
+case SSL_ST_ACCEPT: str="before accept initalisation"; break;
+case SSL_ST_CONNECT: str="before connect initalisation"; 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 initalisation"; break;
+case SSL_ST_OK|SSL_ST_CONNECT: str="ok/connect SSL initalisation"; break;
+case SSL_ST_BEFORE|SSL_ST_ACCEPT: str="before/accept initalisation"; break;
+case SSL_ST_OK|SSL_ST_ACCEPT: str="ok/accept SSL initalisation"; break;
+#ifndef 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 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_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_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 A"; 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 A"; 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_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(NO_SSL2) && !defined(NO_SSL3)
+/* SSLv2/v3 compatablitity 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
+
+default:	str="unknown state"; break;
+		}
+	return(str);
+	}
+
+char *SSL_rstate_string_long(s)
+SSL *s;
+	{
+	char *str;
+
+	switch (s->rstate)
+		{
+	case SSL_ST_READ_HEADER: str="read header"; break;
+	case SSL_ST_READ_BODY: str="read body"; break;
+	default: str="unknown"; break;
+		}
+	return(str);
+	}
+
+char *SSL_state_string(s)
+SSL *s;
+	{
+	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 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 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_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(NO_SSL2) && !defined(NO_SSL3)
+/* SSLv2/v3 compatablitity 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
+
+default:					str="UNKWN "; break;
+		}
+	return(str);
+	}
+
+char *SSL_alert_type_string_long(value)
+int value;
+	{
+	value>>=8;
+	if (value == SSL3_AL_WARNING)
+		return("warning");
+	else if (value == SSL3_AL_FATAL)
+		return("fatal");
+	else
+		return("unknown");
+	}
+
+char *SSL_alert_type_string(value)
+int value;
+	{
+	value>>=8;
+	if (value == SSL3_AL_WARNING)
+		return("W");
+	else if (value == SSL3_AL_FATAL)
+		return("F");
+	else
+		return("U");
+	}
+
+char *SSL_alert_desc_string(value)
+int value;
+	{
+	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;
+	default:				str="UK"; break;
+		}
+	return(str);
+	}
+
+char *SSL_alert_desc_string_long(value)
+int value;
+	{
+	char *str;
+
+	switch (value & 0xff)
+		{
+	case SSL3_AD_CLOSE_NOTIFY:
+		str="close notify";
+		break;
+	case SSL3_AD_UNEXPECTED_MESSAGE:
+		str="unexected_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="certifcate unknown";
+		break;
+	case SSL3_AD_ILLEGAL_PARAMETER:
+		str="illegal parameter";
+		break;
+	default: str="unknown"; break;
+		}
+	return(str);
+	}
+
+char *SSL_rstate_string(s)
+SSL *s;
+	{
+	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/ssl/ssl_task.c b/ssl/ssl_task.c
new file mode 100644
index 0000000..c27ce91
--- /dev/null
+++ b/ssl/ssl_task.c
@@ -0,0 +1,359 @@
+/* ssl/ssl_task.c */
+/* Copyright (C) 1995-1997 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 "buffer.h"
+#include "../e_os.h"
+#include "x509.h"
+#include "ssl.h"
+#include "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();
+
+	s_ctx=SSL_CTX_new(SSLv2());
+
+	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;
+	static char cbuf[200],sbuf[200];
+	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;
+	BIO_set_fd ( c_to_s, "", chan );
+	BIO_set_fd ( s_to_c, "", 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/ssl/ssl_txt.c b/ssl/ssl_txt.c
new file mode 100644
index 0000000..b9cb9ef
--- /dev/null
+++ b/ssl/ssl_txt.c
@@ -0,0 +1,133 @@
+/* ssl/ssl_txt.c */
+/* Copyright (C) 1995-1997 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 "buffer.h"
+#include "ssl_locl.h"
+
+#ifndef WIN16
+int SSL_SESSION_print_fp(fp, x)
+FILE *fp;
+SSL_SESSION *x;
+        {
+        BIO *b;
+        int ret;
+
+        if ((b=BIO_new(BIO_s_file())) == 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(bp,x)
+BIO *bp;
+SSL_SESSION *x;
+	{
+	int i;
+	char str[128];
+
+	if (x == NULL) goto err;
+	if (BIO_puts(bp,"SSL-Session:\n") <= 0) goto err;
+	sprintf(str,"    Cipher    : %s\n",(x->cipher == NULL)?"unknown":x->cipher->name);
+	if (BIO_puts(bp,str) <= 0) goto err;
+	if (BIO_puts(bp,"    Session-ID: ") <= 0) goto err;
+	for (i=0; i<(int)x->session_id_length; i++)
+		{
+		sprintf(str,"%02X",x->session_id[i]);
+		if (BIO_puts(bp,str) <= 0) goto err;
+		}
+	if (BIO_puts(bp,"\n    Master-Key: ") <= 0) goto err;
+	for (i=0; i<(int)x->master_key_length; i++)
+		{
+		sprintf(str,"%02X",x->master_key[i]);
+		if (BIO_puts(bp,str) <= 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<(int)x->key_arg_length; i++)
+			{
+			sprintf(str,"%02X",x->key_arg[i]);
+			if (BIO_puts(bp,str) <= 0) goto err;
+			}
+	if (x->time != 0L)
+		{
+		sprintf(str,"\n    Start Time: %ld",x->time);
+		if (BIO_puts(bp,str) <= 0) goto err;
+		}
+	if (x->timeout != 0L)
+		{
+		sprintf(str,"\n    Timeout   : %ld (sec)",x->timeout);
+		if (BIO_puts(bp,str) <= 0) goto err;
+		}
+	if (BIO_puts(bp,"\n") <= 0) goto err;
+		
+	return(1);
+err:
+	return(0);
+	}
+
diff --git a/ssl/ssltest.c b/ssl/ssltest.c
new file mode 100644
index 0000000..b8d657f
--- /dev/null
+++ b/ssl/ssltest.c
@@ -0,0 +1,635 @@
+/* ssl/ssltest.c */
+/* Copyright (C) 1995-1997 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>
+#ifdef WIN16
+#define APPS_WIN16
+#endif
+#include "bio.h"
+#include "crypto.h"
+#include "../e_os.h"
+#include "x509.h"
+#include "ssl.h"
+#include "err.h"
+
+#ifdef WIN16
+#define APPS_WIN16
+#include "../crypto/bio/bss_file.c"
+#endif
+
+#define TEST_SERVER_CERT "../apps/server.pem"
+#define TEST_CLIENT_CERT "../apps/client.pem"
+
+#ifndef NOPROTO
+int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx);
+static DH *get_dh512(void);
+#else
+int MS_CALLBACK verify_callback();
+static DH *get_dh512();
+#endif
+
+BIO *bio_err=NULL;
+BIO *bio_stdout=NULL;
+
+static char *cipher=NULL;
+int verbose=0;
+#ifdef FIONBIO
+static int s_nbio=0;
+#endif
+
+
+#ifndef  NOPROTO
+int doit(SSL_CTX *s_ctx,SSL_CTX *c_ctx);
+#else
+int doit();
+#endif
+
+static void sv_usage()
+	{
+	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," -v            - more output\n");
+#ifndef NO_SSL2
+	fprintf(stderr," -ssl2         - use SSLv2\n");
+#endif
+#ifndef NO_SSL3
+	fprintf(stderr," -ssl3         - use SSLv3\n");
+#endif
+	fprintf(stderr," -CApath arg   - PEM format directory of CA's\n");
+	fprintf(stderr," -CAfile arg   - PEM format file of CA's\n");
+	}
+
+int main(argc, argv)
+int argc;
+char *argv[];
+	{
+	char *CApath=NULL,*CAfile=NULL;
+	int badop=0;
+	int ssl2=0,ssl3=0,ret=1;
+	int client_auth=0;
+	int server_auth=0;
+	char *server_cert=TEST_SERVER_CERT;
+	char *client_cert=TEST_CLIENT_CERT;
+	SSL_CTX *s_ctx=NULL;
+	SSL_CTX *c_ctx=NULL;
+	SSL_METHOD *meth=NULL;
+	DH *dh;
+
+	bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
+	bio_stdout=BIO_new_fp(stdout,BIO_NOCLOSE);
+
+	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
+
+	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,"-v") == 0)
+			verbose=1;
+		else if	(strcmp(*argv,"-ssl2") == 0)
+			ssl2=1;
+		else if	(strcmp(*argv,"-ssl3") == 0)
+			ssl3=1;
+		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,"-c_cert") == 0)
+			{
+			if (--argc < 1) goto bad;
+			client_cert= *(++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
+			{
+			fprintf(stderr,"unknown option %s\n",*argv);
+			badop=1;
+			break;
+			}
+		argc--;
+		argv++;
+		}
+	if (badop)
+		{
+bad:
+		sv_usage();
+		goto end;
+		}
+
+/*	if (cipher == NULL) cipher=getenv("SSL_CIPHER"); */
+
+	SSLeay_add_ssl_algorithms();
+	SSL_load_error_strings();
+
+#if !defined(NO_SSL2) && !defined(NO_SSL3)
+	if (ssl2)
+		meth=SSLv2_method();
+	else 
+	if (ssl3)
+		meth=SSLv3_method();
+	else
+		meth=SSLv23_method();
+#else
+#ifdef 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);
+		}
+
+#ifndef NO_DH
+	dh=get_dh512();
+	SSL_CTX_set_tmp_dh(s_ctx,dh);
+        DH_free(dh);
+#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_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_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)
+		{
+		fprintf(stderr,"client authentication\n");
+		SSL_CTX_set_verify(s_ctx,
+			SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
+			verify_callback);
+		}
+	if (server_auth)
+		{
+		fprintf(stderr,"server authentication\n");
+		SSL_CTX_set_verify(c_ctx,SSL_VERIFY_PEER,
+			verify_callback);
+		}
+
+	ret=doit(s_ctx,c_ctx);
+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);
+
+	ERR_remove_state(0);
+	EVP_cleanup();
+	CRYPTO_mem_leaks(bio_err);
+	EXIT(ret);
+	}
+
+#define W_READ	1
+#define W_WRITE	2
+#define C_DONE	1
+#define S_DONE	2
+
+int doit(s_ctx,c_ctx)
+SSL_CTX *s_ctx,*c_ctx;
+	{
+	static char cbuf[200],sbuf[200];
+	int ret=1;
+	SSL *c_ssl=NULL;
+	SSL *s_ssl=NULL;
+	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;
+	int done=0;
+	int c_write,s_write;
+	int do_server=0,do_client=0;
+	SSL_CIPHER *ciph;
+
+	c_ssl=SSL_new(c_ctx);
+	s_ssl=SSL_new(s_ctx);
+	if ((s_ssl == NULL) || (c_ssl == NULL))
+		{
+		ERR_print_errors(bio_err);
+		goto err;
+		}
+
+	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_CLOSE);
+
+	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);
+
+	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 && verbose)
+			{
+			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 && verbose)
+			{
+			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)
+				{
+				i=BIO_write(c_bio,"hello from client\n",18);
+				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
+					{
+					/* ok */
+					c_write=0;
+					}
+				}
+			else
+				{
+				i=BIO_read(c_bio,cbuf,100);
+				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
+					{
+					done|=C_DONE;
+					fprintf(stdout,"CLIENT:from server:");
+					fwrite(cbuf,1,i,stdout);
+					fflush(stdout);
+					}
+				}
+			}
+
+		if (do_server && !(done & S_DONE))
+			{
+			if (!s_write)
+				{
+				i=BIO_read(s_bio,sbuf,100);
+				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
+					{
+					s_write=1;
+					s_w=1;
+					fprintf(stdout,"SERVER:from client:");
+					fwrite(sbuf,1,i,stdout);
+					fflush(stdout);
+					}
+				}
+			else
+				{
+				i=BIO_write(s_bio,"hello from server\n",18);
+				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
+					{
+					s_write=0;
+					s_r=1;
+					done|=S_DONE;
+					}
+				}
+			}
+
+		if ((done & S_DONE) && (done & C_DONE)) break;
+		}
+
+	ciph=SSL_get_current_cipher(c_ssl);
+	fprintf(stdout,"DONE, used %s, %s\n",SSL_CIPHER_get_version(ciph),
+		SSL_CIPHER_get_name(ciph));
+	ret=0;
+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 */
+	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(c_bio);
+	if (s_bio != NULL) BIO_free(s_bio);
+	return(ret);
+	}
+
+int MS_CALLBACK verify_callback(ok, ctx)
+int ok;
+X509_STORE_CTX *ctx;
+	{
+	char *s,buf[256];
+
+	s=X509_NAME_oneline(X509_get_subject_name(ctx->current_cert),buf,256);
+	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)
+		{
+		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:
+			ok=1;
+			}
+		}
+
+	return(ok);
+	}
+
+static unsigned char dh512_p[]={
+	0xDA,0x58,0x3C,0x16,0xD9,0x85,0x22,0x89,0xD0,0xE4,0xAF,0x75,
+	0x6F,0x4C,0xCA,0x92,0xDD,0x4B,0xE5,0x33,0xB8,0x04,0xFB,0x0F,
+	0xED,0x94,0xEF,0x9C,0x8A,0x44,0x03,0xED,0x57,0x46,0x50,0xD3,
+	0x69,0x99,0xDB,0x29,0xD7,0x76,0x27,0x6B,0xA2,0xD3,0xD4,0x12,
+	0xE2,0x18,0xF4,0xDD,0x1E,0x08,0x4C,0xF6,0xD8,0x00,0x3E,0x7C,
+	0x47,0x74,0xE8,0x33,
+	};
+static unsigned char dh512_g[]={
+	0x02,
+	};
+
+static DH *get_dh512()
+	{
+	DH *dh=NULL;
+
+#ifndef NO_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))
+		return(NULL);
+#endif
+	return(dh);
+	}
+
diff --git a/ssl/zz b/ssl/zz
new file mode 100644
index 0000000..47c570e
--- /dev/null
+++ b/ssl/zz
@@ -0,0 +1,402 @@
+/* ssl/s23_srvr.c */
+/* Copyright (C) 1995-1997 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 "buffer.h"
+#include "rand.h"
+#include "objects.h"
+#include "evp.h"
+#include "ssl_locl.h"
+
+#define BREAK break
+
+#ifndef NOPROTO
+int ssl23_get_client_hello(SSL *s);
+#else
+int ssl23_get_client_hello();
+#endif
+
+static SSL_METHOD *ssl23_get_server_method(ver)
+int ver;
+	{
+	if (ver == 2)
+		return(SSLv2_server_method());
+	else if (ver == 3)
+		return(SSLv3_server_method());
+	else
+		return(NULL);
+	}
+
+SSL_METHOD *SSLv23_server_method()
+	{
+	static int init=1;
+	static SSL_METHOD SSLv23_server_data;
+
+	if (init)
+		{
+		init=0;
+		memcpy((char *)&SSLv23_server_data,
+			(char *)sslv23_base_method(),sizeof(SSL_METHOD));
+		SSLv23_server_data.ssl_accept=ssl23_accept;
+		SSLv23_server_data.get_ssl_method=ssl23_get_server_method;
+		}
+	return(&SSLv23_server_data);
+	}
+
+int ssl23_accept(s)
+SSL *s;
+	{
+	BUF_MEM *buf;
+	unsigned long Time=time(NULL);
+	void (*cb)()=NULL;
+	int ret= -1;
+	int new_state,state;
+
+	RAND_seed((unsigned char *)&Time,sizeof(Time));
+	ERR_clear_error();
+	errno=0;
+
+	if (s->info_callback != NULL)
+		cb=s->info_callback;
+	else if (s->ctx->info_callback != NULL)
+		cb=s->ctx->info_callback;
+	
+	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); 
+	s->in_handshake++;
+
+	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:
+
+			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
+
+			s->version=3;
+			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->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:
+	if (cb != NULL)
+		cb(s,SSL_CB_ACCEPT_EXIT,ret);
+	s->in_handshake--;
+	return(ret);
+	}
+
+
+int ssl23_get_client_hello(s)
+SSL *s;
+	{
+	char buf[8];
+	unsigned char *p,*d,*dd;
+	unsigned int i;
+	unsigned int csl,sil,cl;
+	int n=0,j;
+	BIO *bbio;
+	int type=0;
+
+	/* read the initial header */
+	if (s->state ==	SSL23_ST_SR_CLNT_HELLO_A)
+		{
+		if (!ssl3_setup_buffers(s)) goto err;
+
+		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_CLIENT_HELLO))
+			{
+			/* SSLv2 header */
+			if ((p[3] == 0x00) && (p[4] == 0x02))
+				{
+				/* SSLv2 */
+				type=1;
+				}
+			else if ((p[3] == SSL3_VERSION_MAJOR) &&
+				 (p[4] == SSL3_VERSION_MINOR))
+				{
+				/* SSLv3 */
+				s->state=SSL23_ST_SR_CLNT_HELLO_B;
+				}
+			}
+		else if ((p[0] == SSL3_RT_HANDSHAKE) &&
+			 (p[1] == SSL3_VERSION_MAJOR) &&
+			 (p[2] == SSL3_VERSION_MINOR) &&
+			 (p[5] == SSL3_MT_CLIENT_HELLO))
+			{
+			/* true SSLv3 */
+			type=3;
+			}
+		}
+
+	if (s->state == SSL23_ST_SR_CLNT_HELLO_B)
+		{
+		/* we have a SSLv3 in a SSLv2 header */
+		type=2;
+		p=s->packet;
+		n=((p[0]&0x7f)<<8)|p[1];
+		if (n > (1024*4))
+			{
+			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);
+
+		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)
+			{
+			SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_LENGTH_MISMATCH);
+			goto err;
+			}
+
+		*(d++)=SSL3_VERSION_MAJOR;
+		*(d++)=SSL3_VERSION_MINOR;
+
+		/* lets populate the random area */
+		/* get the chalenge_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;
+		
+		i=(d-(unsigned char *)s->init_buf->data);
+
+		/* 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;
+		}
+
+	if (type == 1)
+		{
+		/* we are talking sslv2 */
+		/* we need to clean up the SSLv3 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(s->init_buf,
+			SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER))
+			{
+			goto err;
+			}
+
+		s->state=SSL2_ST_GET_CLIENT_HELLO_A;
+		if (s->ctx->options & SSL_OP_MSIE_SSLV2_RSA_PADDING)
+			s->s2->ssl2_rollback=0;
+		else
+			s->s2->ssl2_rollback=1;
+
+		/* setup the 5 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;
+		}
+
+	if ((type == 2) || (type == 3))
+		{
+		/* we have sslv3 */
+
+		if (s->bbio == NULL)
+			{
+			bbio=BIO_new(BIO_f_buffer());
+			if (bbio == NULL)
+				goto err;
+			s->bbio=bbio;
+			}
+		else
+			bbio=s->bbio;
+		BIO_reset(bbio);
+		if (!BIO_set_write_buffer_size(bbio,16*1024))
+			goto err;
+		s->wbio=BIO_push(bbio,s->wbio);
+
+		/* 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;
+			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;
+			}
+
+		s->method=SSLv3_server_method();
+		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;
+	return(SSL_accept(s));
+err:
+	return(-1);
+	}
+