Import of old SSLeay release: SSLeay 0.9.0b
diff --git a/ssl/Makefile.ssl b/ssl/Makefile.ssl
index f6f40e4..f4b13bf 100644
--- a/ssl/Makefile.ssl
+++ b/ssl/Makefile.ssl
@@ -23,17 +23,19 @@
 
 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 \
+	s2_meth.c   s2_srvr.c s2_clnt.c  s2_lib.c  s2_enc.c s2_pkt.c \
+	s3_meth.c   s3_srvr.c s3_clnt.c  s3_lib.c  s3_enc.c s3_pkt.c s3_both.c \
+	s23_meth.c s23_srvr.c s23_clnt.c s23_lib.c          s23_pkt.c \
+	t1_meth.c   t1_srvr.c t1_clnt.c  t1_lib.c  t1_enc.c \
 	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 \
+	s2_meth.o  s2_srvr.o  s2_clnt.o  s2_lib.o  s2_enc.o s2_pkt.o \
+	s3_meth.o  s3_srvr.o  s3_clnt.o  s3_lib.o  s3_enc.o s3_pkt.o s3_both.o \
+	s23_meth.o s23_srvr.o s23_clnt.o s23_lib.o          s23_pkt.o \
+	t1_meth.o   t1_srvr.o t1_clnt.o  t1_lib.o  t1_enc.o \
 	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 \
@@ -41,7 +43,7 @@
 
 SRC= $(LIBSRC)
 
-EXHEADER= ssl.h ssl2.h ssl3.h ssl23.h
+EXHEADER= ssl.h ssl2.h ssl3.h ssl23.h tls1.h
 HEADER=	$(EXHEADER) ssl_locl.h
 
 ALL=    $(GENERAL) $(SRC) $(HEADER)
@@ -93,6 +95,6 @@
 
 errors:
 	perl $(TOP)/util/err-ins.pl $(ERR).err $(ERR).h
-	perl ../crypto/err/err_genc.pl $(ERR).h $(ERRC).c
+	perl ../crypto/err/err_genc.pl -s $(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
index 6c0baba..58a6d69 100644
--- a/ssl/bio_ssl.c
+++ b/ssl/bio_ssl.c
@@ -1,5 +1,5 @@
 /* ssl/bio_ssl.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -57,8 +57,10 @@
  */
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include "crypto.h"
 #include "bio.h"
 #include "err.h"
 #include "ssl.h"
@@ -79,6 +81,17 @@
 static int ssl_free();
 #endif
 
+typedef struct bio_ssl_st
+	{
+	SSL *ssl; /* The ssl handle :-) */
+	/* re-negotiate every time the total number of bytes is this size */
+	int num_renegotiates;
+	unsigned long renegotiate_count;
+	unsigned long byte_count;
+	unsigned long renegotiate_timeout;
+	unsigned long last_time;
+	} BIO_SSL;
+
 static BIO_METHOD methods_sslp=
 	{
 	BIO_TYPE_SSL,"ssl",
@@ -99,8 +112,17 @@
 static int ssl_new(bi)
 BIO *bi;
 	{
+	BIO_SSL *bs;
+
+	bs=(BIO_SSL *)Malloc(sizeof(BIO_SSL));
+	if (bs == NULL)
+		{
+		BIOerr(BIO_F_SSL_NEW,ERR_R_MALLOC_FAILURE);
+		return(0);
+		}
+	memset(bs,0,sizeof(BIO_SSL));
 	bi->init=0;
-	bi->ptr=NULL;	/* The SSL structure */
+	bi->ptr=(char *)bs;
 	bi->flags=0;
 	return(1);
 	}
@@ -108,15 +130,20 @@
 static int ssl_free(a)
 BIO *a;
 	{
+	BIO_SSL *bs;
+
 	if (a == NULL) return(0);
-	if (a->ptr != NULL) SSL_shutdown((SSL *)a->ptr);
+	bs=(BIO_SSL *)a->ptr;
+	if (bs->ssl != NULL) SSL_shutdown(bs->ssl);
 	if (a->shutdown)
 		{
-		if (a->init) SSL_free((SSL *)a->ptr);
+		if (a->init && (bs->ssl != NULL))
+			SSL_free(bs->ssl);
 		a->init=0;
 		a->flags=0;
-		a->ptr=NULL;
 		}
+	if (a->ptr != NULL)
+		Free(a->ptr);
 	return(1);
 	}
 	
@@ -126,49 +153,74 @@
 int outl;
 	{
 	int ret=1;
-	int inflags,outflags;
+	BIO_SSL *sb;
 	SSL *ssl;
 	int retry_reason=0;
+	int r=0;
 
 	if (out == NULL) return(0);
-	ssl=(SSL *)b->ptr;
+	sb=(BIO_SSL *)b->ptr;
+	ssl=sb->ssl;
 
-	inflags=outflags=b->flags;
+	BIO_clear_retry_flags(b);
 
-	outflags&= ~(BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY);
-
+#if 0
 	if (!SSL_is_init_finished(ssl))
 		{
-		ret=SSL_do_handshake(ssl);
-#if 0
+/*		ret=SSL_do_handshake(ssl); */
 		if (ret > 0)
 			{
+
 			outflags=(BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY);
 			ret= -1;
 			goto end;
 			}
-#endif
 		}
-	if (ret > 0)
-		ret=SSL_read(ssl,out,outl);
+#endif
+/*	if (ret > 0) */
+	ret=SSL_read(ssl,out,outl);
 
 	switch (SSL_get_error(ssl,ret))
 		{
 	case SSL_ERROR_NONE:
 		if (ret <= 0) break;
+		if (sb->renegotiate_count > 0)
+			{
+			sb->byte_count+=ret;
+			if (sb->byte_count > sb->renegotiate_count)
+				{
+				sb->byte_count=0;
+				sb->num_renegotiates++;
+				SSL_renegotiate(ssl);
+				r=1;
+				}
+			}
+		if ((sb->renegotiate_timeout > 0) && (!r))
+			{
+			unsigned long tm;
+
+			tm=(unsigned long)time(NULL);
+			if (tm > sb->last_time+sb->renegotiate_timeout)
+				{
+				sb->last_time=tm;
+				sb->num_renegotiates++;
+				SSL_renegotiate(ssl);
+				}
+			}
+
 		break;
 	case SSL_ERROR_WANT_READ:
-		outflags=(BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY);
+		BIO_set_retry_read(b);
 		break;
 	case SSL_ERROR_WANT_WRITE:
-		outflags=(BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY);
+		BIO_set_retry_write(b);
 		break;
 	case SSL_ERROR_WANT_X509_LOOKUP:
-		outflags=(BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY);
+		BIO_set_retry_special(b);
 		retry_reason=BIO_RR_SSL_X509_LOOKUP;
 		break;
 	case SSL_ERROR_WANT_CONNECT:
-		outflags=(BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY);
+		BIO_set_retry_special(b);
 		retry_reason=BIO_RR_CONNECT;
 		break;
 	case SSL_ERROR_SYSCALL:
@@ -179,7 +231,6 @@
 		}
 
 	b->retry_reason=retry_reason;
-	b->flags=outflags;
 	return(ret);
 	}
 
@@ -188,38 +239,61 @@
 char *out;
 int outl;
 	{
-	int ret;
-	int inflags,outflags,retry_reason=0;
+	int ret,r=0;
+	int retry_reason=0;
 	SSL *ssl;
+	BIO_SSL *bs;
 
 	if (out == NULL) return(0);
-	ssl=(SSL *)b->ptr;
+	bs=(BIO_SSL *)b->ptr;
+	ssl=bs->ssl;
 
-	inflags=outflags=b->flags;
+	BIO_clear_retry_flags(b);
 
-	outflags&= ~(BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY);
-
-	ret=SSL_do_handshake(ssl);
-	if (ret > 0)
-		ret=SSL_write(ssl,out,outl);
+/*	ret=SSL_do_handshake(ssl);
+	if (ret > 0) */
+	ret=SSL_write(ssl,out,outl);
 
 	switch (SSL_get_error(ssl,ret))
 		{
 	case SSL_ERROR_NONE:
 		if (ret <= 0) break;
+		if (bs->renegotiate_count > 0)
+			{
+			bs->byte_count+=ret;
+			if (bs->byte_count > bs->renegotiate_count)
+				{
+				bs->byte_count=0;
+				bs->num_renegotiates++;
+				SSL_renegotiate(ssl);
+				r=1;
+				}
+			}
+		if ((bs->renegotiate_timeout > 0) && (!r))
+			{
+			unsigned long tm;
+
+			tm=(unsigned long)time(NULL);
+			if (tm > bs->last_time+bs->renegotiate_timeout)
+				{
+				bs->last_time=tm;
+				bs->num_renegotiates++;
+				SSL_renegotiate(ssl);
+				}
+			}
 		break;
 	case SSL_ERROR_WANT_WRITE:
-		outflags=(BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY);
+		BIO_set_retry_write(b);
 		break;
 	case SSL_ERROR_WANT_READ:
-		outflags=(BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY);
+		BIO_set_retry_read(b);
 		break;
 	case SSL_ERROR_WANT_X509_LOOKUP:
-		outflags=(BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY);
+		BIO_set_retry_special(b);
 		retry_reason=BIO_RR_SSL_X509_LOOKUP;
 		break;
 	case SSL_ERROR_WANT_CONNECT:
-		outflags=(BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY);
+		BIO_set_retry_special(b);
 		retry_reason=BIO_RR_CONNECT;
 	case SSL_ERROR_SYSCALL:
 	case SSL_ERROR_SSL:
@@ -228,7 +302,6 @@
 		}
 
 	b->retry_reason=retry_reason;
-	b->flags=outflags;
 	return(ret);
 	}
 
@@ -239,10 +312,14 @@
 char *ptr;
 	{
 	SSL **sslp,*ssl;
+	BIO_SSL *bs;
 	BIO *dbio,*bio;
 	long ret=1;
 
-	ssl=(SSL *)b->ptr;
+	bs=(BIO_SSL *)b->ptr;
+	ssl=bs->ssl;
+	if ((ssl == NULL)  && (cmd != BIO_C_SET_SSL))
+		return(0);
 	switch (cmd)
 		{
 	case BIO_CTRL_RESET:
@@ -262,7 +339,6 @@
 		else
 			ret=1;
 		break;
-	case BIO_CTRL_EOF:
 	case BIO_CTRL_INFO:
 		ret=0;
 		break;
@@ -272,17 +348,33 @@
 		else
 			SSL_set_accept_state(ssl);
 		break;
+	case BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT:
+		ret=bs->renegotiate_timeout;
+		if (num < 60) num=5;
+		bs->renegotiate_timeout=(unsigned long)num;
+		bs->last_time=(unsigned long)time(NULL);
+		break;
+	case BIO_C_SET_SSL_RENEGOTIATE_BYTES:
+		ret=bs->renegotiate_count;
+		if ((long)num >=512)
+			bs->renegotiate_count=(unsigned long)num;
+		break;
+	case BIO_C_GET_SSL_NUM_RENEGOTIATES:
+		ret=bs->num_renegotiates;
+		break;
 	case BIO_C_SET_SSL:
-		ssl_free(b);
+		if (ssl != NULL)
+			ssl_free(b);
 		b->shutdown=(int)num;
-		b->ptr=ptr;
 		ssl=(SSL *)ptr;
+		((BIO_SSL *)b->ptr)->ssl=ssl;
 		bio=SSL_get_rbio(ssl);
 		if (bio != NULL)
 			{
 			if (b->next_bio != NULL)
 				BIO_push(bio,b->next_bio);
 			b->next_bio=bio;
+			CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO);
 			}
 		b->init=1;
 		break;
@@ -292,6 +384,8 @@
 			sslp=(SSL **)ptr;
 			*sslp=ssl;
 			}
+		else
+			ret=0;
 		break;
 	case BIO_CTRL_GET_CLOSE:
 		ret=b->shutdown;
@@ -313,10 +407,10 @@
 		BIO_copy_next_retry(b);
 		break;
 	case BIO_CTRL_PUSH:
-		if (b->next_bio != NULL)
+		if ((b->next_bio != NULL) && (b->next_bio != ssl->rbio))
 			{
 			SSL_set_bio(ssl,b->next_bio,b->next_bio);
-			b->next_bio->references++;
+			CRYPTO_add(&b->next_bio->references,1,CRYPTO_LOCK_BIO);
 			}
 		break;
 	case BIO_CTRL_POP:
@@ -355,13 +449,35 @@
 		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);
+		if (((BIO_SSL *)dbio->ptr)->ssl != NULL)
+			SSL_free(((BIO_SSL *)dbio->ptr)->ssl);
+		((BIO_SSL *)dbio->ptr)->ssl=SSL_dup(ssl);
+		((BIO_SSL *)dbio->ptr)->renegotiate_count=
+			((BIO_SSL *)b->ptr)->renegotiate_count;
+		((BIO_SSL *)dbio->ptr)->byte_count=
+			((BIO_SSL *)b->ptr)->byte_count;
+		((BIO_SSL *)dbio->ptr)->renegotiate_timeout=
+			((BIO_SSL *)b->ptr)->renegotiate_timeout;
+		((BIO_SSL *)dbio->ptr)->last_time=
+			((BIO_SSL *)b->ptr)->last_time;
+		ret=(((BIO_SSL *)dbio->ptr)->ssl != NULL);
+		break;
+	case BIO_C_GET_FD:
+		ret=BIO_ctrl(ssl->rbio,cmd,num,ptr);
+		break;
+	case BIO_CTRL_SET_CALLBACK:
+		SSL_set_info_callback(ssl,(void (*)())ptr);
+		break;
+	case BIO_CTRL_GET_CALLBACK:
+		{
+		void (**fptr)();
+
+		fptr=(void (**)())ptr;
+		*fptr=SSL_get_info_callback(ssl);
+		}
 		break;
 	default:
-		return(0);
+		ret=BIO_ctrl(ssl->rbio,cmd,num,ptr);
 		break;
 		}
 	return(ret);
@@ -378,6 +494,42 @@
 	return(ret);
 	}
 
+BIO *BIO_new_buffer_ssl_connect(ctx)
+SSL_CTX *ctx;
+	{
+	BIO *ret=NULL,*buf=NULL,*ssl=NULL;
+
+	if ((buf=BIO_new(BIO_f_buffer())) == NULL)
+		return(NULL);
+	if ((ssl=BIO_new_ssl_connect(ctx)) == NULL)
+		goto err;
+	if ((ret=BIO_push(buf,ssl)) == NULL)
+		goto err;
+	return(ret);
+err:
+	if (buf != NULL) BIO_free(buf);
+	if (ssl != NULL) BIO_free(ssl);
+	return(NULL);
+	}
+
+BIO *BIO_new_ssl_connect(ctx)
+SSL_CTX *ctx;
+	{
+	BIO *ret=NULL,*con=NULL,*ssl=NULL;
+
+	if ((con=BIO_new(BIO_s_connect())) == NULL)
+		return(NULL);
+	if ((ssl=BIO_new_ssl(ctx,1)) == NULL)
+		goto err;
+	if ((ret=BIO_push(ssl,con)) == NULL)
+		goto err;
+	return(ret);
+err:
+	if (con != NULL) BIO_free(con);
+	if (ret != NULL) BIO_free(ret);
+	return(NULL);
+	}
+
 BIO *BIO_new_ssl(ctx,client)
 SSL_CTX *ctx;
 int client;
@@ -408,9 +560,10 @@
 	f=BIO_find_type(f,BIO_TYPE_SSL);
 	if ((t == NULL) || (f == NULL))
 		return(0);
-	if ((t->ptr == NULL) || (f->ptr == NULL))
+	if (	(((BIO_SSL *)t->ptr)->ssl == NULL) || 
+		(((BIO_SSL *)f->ptr)->ssl == NULL))
 		return(0);
-	SSL_copy_session_id((SSL *)t->ptr,(SSL *)f->ptr);
+	SSL_copy_session_id(((BIO_SSL *)t->ptr)->ssl,((BIO_SSL *)f->ptr)->ssl);
 	return(1);
 	}
 
@@ -423,7 +576,7 @@
 		{
 		if (b->method->type == BIO_TYPE_SSL)
 			{
-			s=(SSL *)b->ptr;
+			s=((BIO_SSL *)b->ptr)->ssl;
 			SSL_shutdown(s);
 			break;
 			}
diff --git a/ssl/s23_clnt.c b/ssl/s23_clnt.c
index 57d3623..a4661eb 100644
--- a/ssl/s23_clnt.c
+++ b/ssl/s23_clnt.c
@@ -1,5 +1,5 @@
 /* ssl/s23_clnt.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -76,10 +76,12 @@
 static SSL_METHOD *ssl23_get_client_method(ver)
 int ver;
 	{
-	if (ver == 2)
+	if (ver == SSL2_VERSION)
 		return(SSLv2_client_method());
-	else if (ver == 3)
+	else if (ver == SSL3_VERSION)
 		return(SSLv3_client_method());
+	else if (ver == TLS1_VERSION)
+		return(TLSv1_client_method());
 	else
 		return(NULL);
 	}
@@ -111,7 +113,7 @@
 
 	RAND_seed((unsigned char *)&Time,sizeof(Time));
 	ERR_clear_error();
-	errno=0;
+	clear_sys_error();
 
 	if (s->info_callback != NULL)
 		cb=s->info_callback;
@@ -134,7 +136,7 @@
 
 			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
 
-			s->version=3;
+			/* s->version=TLS1_VERSION; */
 			s->type=SSL_ST_CONNECT;
 
 			if (s->init_buf == NULL)
@@ -230,8 +232,26 @@
 		p=d+9;
 
 		*(d++)=SSL2_MT_CLIENT_HELLO;
-		*(d++)=SSL3_VERSION_MAJOR;
-		*(d++)=SSL3_VERSION_MINOR;
+		if (!(s->options & SSL_OP_NO_TLSv1))
+			{
+			*(d++)=TLS1_VERSION_MAJOR;
+			*(d++)=TLS1_VERSION_MINOR;
+			}
+		else if (!(s->options & SSL_OP_NO_SSLv3))
+			{
+			*(d++)=SSL3_VERSION_MAJOR;
+			*(d++)=SSL3_VERSION_MINOR;
+			}
+		else if (!(s->options & SSL_OP_NO_SSLv2))
+			{
+			*(d++)=SSL2_VERSION_MAJOR;
+			*(d++)=SSL2_VERSION_MINOR;
+			}
+		else
+			{
+			SSLerr(SSL_F_SSL23_CLIENT_HELLO,SSL_R_NO_PROTOCOLS_AVAILABLE);
+			return(-1);
+			}
 
 		/* Ciphers supported */
 		i=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),p);
@@ -251,7 +271,7 @@
 #endif
 		s2n(0,d);
 
-		if (s->ctx->options & SSL_OP_NETSCAPE_CHALLENGE_BUG)
+		if (s->options & SSL_OP_NETSCAPE_CHALLENGE_BUG)
 			ch_len=SSL2_CHALLENGE_LENGTH;
 		else
 			ch_len=SSL2_MAX_CHALLENGE_LENGTH;
@@ -290,7 +310,6 @@
 	unsigned char *p;
 	int i,ch_len;
 	int n;
-	BIO *bbio;
 
 	n=ssl23_read_bytes(s,7);
 
@@ -306,6 +325,11 @@
 		/* we need to clean up the SSLv3 setup and put in the
 		 * sslv2 stuff. */
 
+		if (s->options & SSL_OP_NO_SSLv2)
+			{
+			SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_PROTOCOL);
+			goto err;
+			}
 		if (s->s2 == NULL)
 			{
 			if (!ssl2_new(s))
@@ -314,7 +338,7 @@
 		else
 			ssl2_clear(s);
 
-		if (s->ctx->options & SSL_OP_NETSCAPE_CHALLENGE_BUG)
+		if (s->options & SSL_OP_NETSCAPE_CHALLENGE_BUG)
 			ch_len=SSL2_CHALLENGE_LENGTH;
 		else
 			ch_len=SSL2_MAX_CHALLENGE_LENGTH;
@@ -355,33 +379,13 @@
 		}
 	else if ((p[0] == SSL3_RT_HANDSHAKE) &&
 		 (p[1] == SSL3_VERSION_MAJOR) &&
-		 (p[2] == SSL3_VERSION_MINOR) &&
+		 ((p[2] == SSL3_VERSION_MINOR) ||
+		  (p[2] == TLS1_VERSION_MINOR)) &&
 		 (p[5] == SSL3_MT_SERVER_HELLO))
 		{
-		/* we have sslv3 */
+		/* we have sslv3 or tls1 */
 
-		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);
+		if (!ssl_init_wbio_buffer(s,1)) goto err;
 
 		/* we are in this state */
 		s->state=SSL3_ST_CR_SRVR_HELLO_A;
@@ -395,12 +399,30 @@
 		s->s3->rbuf.left=n;
 		s->s3->rbuf.offset=0;
 
-		s->method=SSLv3_client_method();
+		if ((p[2] == SSL3_VERSION_MINOR) &&
+			!(s->options & SSL_OP_NO_SSLv3))
+			{
+			s->version=SSL3_VERSION;
+			s->method=SSLv3_client_method();
+			}
+		else if ((p[2] == TLS1_VERSION_MINOR) &&
+			!(s->options & SSL_OP_NO_TLSv1))
+			{
+			s->version=TLS1_VERSION;
+			s->method=TLSv1_client_method();
+			}
+		else
+			{
+			SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_PROTOCOL);
+			goto err;
+			}
+			
 		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[2] == SSL3_VERSION_MINOR) ||
+		  (p[2] == TLS1_VERSION_MINOR)) &&
 		 (p[3] == 0) &&
 		 (p[4] == 2))
 		{
@@ -421,7 +443,7 @@
 			}
 
 		s->rwstate=SSL_NOTHING;
-		SSLerr(SSL_F_SSL3_READ_BYTES,1000+p[6]);
+		SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,1000+p[6]);
 		goto err;
 		}
 	else
diff --git a/ssl/s23_lib.c b/ssl/s23_lib.c
index ff19adc..e16f641 100644
--- a/ssl/s23_lib.c
+++ b/ssl/s23_lib.c
@@ -1,5 +1,5 @@
 /* ssl/s23_lib.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -81,10 +81,10 @@
 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,
+	TLS1_VERSION,
+	tls1_new,
+	tls1_clear,
+	tls1_free,
 	ssl_undefined_function,
 	ssl_undefined_function,
 	ssl23_read,
@@ -101,6 +101,7 @@
 	ssl23_get_cipher,
 	ssl_bad_method,
 	ssl23_default_timeout,
+	&ssl3_undef_enc_method,
 	};
 
 static long ssl23_default_timeout()
@@ -179,7 +180,7 @@
 		return(0);
 		}
 #endif
-	errno=0;
+	clear_sys_error();
 	if (SSL_in_init(s) && (!s->in_handshake))
 		{
 		n=s->handshake_func(s);
@@ -212,7 +213,7 @@
 		return(0);
 		}
 #endif
-	errno=0;
+	clear_sys_error();
 	if (SSL_in_init(s) && (!s->in_handshake))
 		{
 		n=s->handshake_func(s);
diff --git a/ssl/s23_meth.c b/ssl/s23_meth.c
index dbe282b..1eed7a5 100644
--- a/ssl/s23_meth.c
+++ b/ssl/s23_meth.c
@@ -1,5 +1,5 @@
 /* ssl/s23_meth.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -63,10 +63,12 @@
 static SSL_METHOD *ssl23_get_method(ver)
 int ver;
 	{
-	if (ver == 2)
+	if (ver == SSL2_VERSION)
 		return(SSLv23_method());
-	else if (ver == 3)
+	else if (ver == SSL3_VERSION)
 		return(SSLv3_method());
+	else if (ver == TLS1_VERSION)
+		return(TLSv1_method());
 	else
 		return(NULL);
 	}
diff --git a/ssl/s23_pkt.c b/ssl/s23_pkt.c
index e9b2add..c25c312 100644
--- a/ssl/s23_pkt.c
+++ b/ssl/s23_pkt.c
@@ -1,5 +1,5 @@
 /* ssl/s23_pkt.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
diff --git a/ssl/s23_srvr.c b/ssl/s23_srvr.c
index 398f005..c7b9ecb 100644
--- a/ssl/s23_srvr.c
+++ b/ssl/s23_srvr.c
@@ -1,5 +1,5 @@
 /* ssl/s23_srvr.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -74,10 +74,12 @@
 static SSL_METHOD *ssl23_get_server_method(ver)
 int ver;
 	{
-	if (ver == 2)
+	if (ver == SSL2_VERSION)
 		return(SSLv2_server_method());
-	else if (ver == 3)
+	else if (ver == SSL3_VERSION)
 		return(SSLv3_server_method());
+	else if (ver == TLS1_VERSION)
+		return(TLSv1_server_method());
 	else
 		return(NULL);
 	}
@@ -109,7 +111,7 @@
 
 	RAND_seed((unsigned char *)&Time,sizeof(Time));
 	ERR_clear_error();
-	errno=0;
+	clear_sys_error();
 
 	if (s->info_callback != NULL)
 		cb=s->info_callback;
@@ -132,7 +134,7 @@
 
 			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
 
-			s->version=3;
+			/* s->version=SSL3_VERSION; */
 			s->type=SSL_ST_ACCEPT;
 
 			if (s->init_buf == NULL)
@@ -197,8 +199,7 @@
 	unsigned char *p,*d,*dd;
 	unsigned int i;
 	unsigned int csl,sil,cl;
-	int n=0,j;
-	BIO *bbio;
+	int n=0,j,tls1=0;
 	int type=0,use_sslv2_strong=0;
 
 	/* read the initial header */
@@ -219,11 +220,28 @@
 			if ((p[3] == 0x00) && (p[4] == 0x02))
 				{
 				/* SSLv2 */
-				type=1;
+				if (!(s->options & SSL_OP_NO_SSLv2))
+					type=1;
 				}
 			else if (p[3] == SSL3_VERSION_MAJOR)
 				{
-				if (s->ctx->options & SSL_OP_NON_EXPORT_FIRST)
+				/* SSLv3/TLSv1 */
+				if (p[4] >= TLS1_VERSION_MINOR)
+					{
+					if (!(s->options & SSL_OP_NO_TLSv1))
+						{
+						tls1=1;
+						s->state=SSL23_ST_SR_CLNT_HELLO_B;
+						}
+					else if (!(s->options & SSL_OP_NO_SSLv3))
+						{
+						s->state=SSL23_ST_SR_CLNT_HELLO_B;
+						}
+					}
+				else if (!(s->options & SSL_OP_NO_SSLv3))
+					s->state=SSL23_ST_SR_CLNT_HELLO_B;
+
+				if (s->options & SSL_OP_NON_EXPORT_FIRST)
 					{
 					STACK *sk;
 					SSL_CIPHER *c;
@@ -275,30 +293,37 @@
 							}
 						}
 					}
-				/* 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;
+			/* true SSLv3 or tls1 */
+			if (p[2] >= TLS1_VERSION_MINOR)
+				{
+				if (!(s->options & SSL_OP_NO_TLSv1))
+					{
+					type=3;
+					tls1=1;
+					}
+				else if (!(s->options & SSL_OP_NO_SSLv3))
+					type=3;
+				}
+			else if (!(s->options & SSL_OP_NO_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))
+		else if ((strncmp("GET ", p,4) == 0) ||
+			 (strncmp("POST ",p,5) == 0) ||
+			 (strncmp("HEAD ",p,5) == 0) ||
+			 (strncmp("PUT ", p,4) == 0))
 			{
+			SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_HTTP_REQUEST);
 			goto err;
 			}
-		else if (strncmp("CONNECT",(char *)p,7) == 0)
+		else if (strncmp("CONNECT",p,7) == 0)
 			{
+			SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_HTTPS_PROXY_REQUEST);
 			goto err;
 			}
 		}
@@ -306,7 +331,7 @@
 next_bit:
 	if (s->state == SSL23_ST_SR_CLNT_HELLO_B)
 		{
-		/* we have a SSLv3 in a SSLv2 header */
+		/* we have a SSLv3/TLSv1 in a SSLv2 header */
 		type=2;
 		p=s->packet;
 		n=((p[0]&0x7f)<<8)|p[1];
@@ -334,7 +359,10 @@
 			}
 
 		*(d++)=SSL3_VERSION_MAJOR;
-		*(d++)=SSL3_VERSION_MINOR;
+		if (tls1)
+			*(d++)=TLS1_VERSION_MINOR;
+		else
+			*(d++)=SSL3_VERSION_MINOR;
 
 		/* lets populate the random area */
 		/* get the chalenge_length */
@@ -374,7 +402,7 @@
 	if (type == 1)
 		{
 		/* we are talking sslv2 */
-		/* we need to clean up the SSLv3 setup and put in the
+		/* we need to clean up the SSLv3/TLSv1 setup and put in the
 		 * sslv2 stuff. */
 
 		if (s->s2 == NULL)
@@ -394,7 +422,7 @@
 			}
 
 		s->state=SSL2_ST_GET_CLIENT_HELLO_A;
-		if ((s->ctx->options & SSL_OP_MSIE_SSLV2_RSA_PADDING) ||
+		if ((s->options & SSL_OP_MSIE_SSLV2_RSA_PADDING) ||
 			use_sslv2_strong)
 			s->s2->ssl2_rollback=0;
 		else
@@ -415,21 +443,9 @@
 
 	if ((type == 2) || (type == 3))
 		{
-		/* we have sslv3 */
+		/* we have SSLv3/TLSv1 */
 
-		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);
+		if (!ssl_init_wbio_buffer(s,1)) goto err;
 
 		/* we are in this state */
 		s->state=SSL3_ST_SR_CLNT_HELLO_A;
@@ -452,7 +468,16 @@
 			s->s3->rbuf.offset=0;
 			}
 
-		s->method=SSLv3_server_method();
+		if (tls1)
+			{
+			s->version=TLS1_VERSION;
+			s->method=TLSv1_server_method();
+			}
+		else
+			{
+			s->version=SSL3_VERSION;
+			s->method=SSLv3_server_method();
+			}
 		s->handshake_func=s->method->ssl_accept;
 		}
 	
diff --git a/ssl/s2_clnt.c b/ssl/s2_clnt.c
index 67578a4..16df9ec 100644
--- a/ssl/s2_clnt.c
+++ b/ssl/s2_clnt.c
@@ -1,5 +1,5 @@
 /* ssl/s2_clnt.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -57,9 +57,6 @@
  */
 
 #include <stdio.h>
-#ifndef NO_MD5
-#include "md5.h"
-#endif
 #include "rand.h"
 #include "buffer.h"
 #include "objects.h"
@@ -92,7 +89,7 @@
 static SSL_METHOD *ssl2_get_client_method(ver)
 int ver;
 	{
-	if (ver == 2)
+	if (ver == SSL2_VERSION)
 		return(SSLv2_client_method());
 	else
 		return(NULL);
@@ -125,7 +122,7 @@
 
 	RAND_seed((unsigned char *)&l,sizeof(l));
 	ERR_clear_error();
-	errno=0;
+	clear_sys_error();
 
 	if (s->info_callback != NULL)
 		cb=s->info_callback;
@@ -149,7 +146,7 @@
 
 			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
 
-			s->version=2;
+			s->version=SSL2_VERSION;
 			s->type=SSL_ST_CONNECT;
 
 			buf=s->init_buf;
@@ -262,6 +259,7 @@
 			 */
 
 			ssl_update_cache(s,SSL_SESS_CACHE_CLIENT);
+			if (s->hit) s->ctx->sess_hit++;
 
 			ret=1;
 			/* s->server=0; */
@@ -298,7 +296,7 @@
 	unsigned char *buf;
 	unsigned char *p;
 	int i,j;
-	STACK *sk,*cl;
+	STACK *sk=NULL,*cl;
 
 	buf=(unsigned char *)s->init_buf->data;
 	p=buf;
@@ -350,7 +348,7 @@
 			}
 		if (s->s2->tmp.cert_type != 0)
 			{
-			if (!(s->ctx->options &
+			if (!(s->options &
 				SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG))
 				{
 				SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_REUSE_CERT_TYPE_NOT_ZERO);
@@ -448,7 +446,7 @@
 	 * 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_add(&s->session->peer->references,1,CRYPTO_LOCK_X509);
 	CRYPTO_w_unlock(CRYPTO_LOCK_X509);
 
 	s->s2->conn_id_length=s->s2->tmp.conn_id_length;
@@ -736,7 +734,7 @@
 		/* ok, now we calculate the checksum
 		 * do it first so we can reuse buf :-) */
 		p=buf;
-		EVP_SignInit(&ctx,EVP_md5());
+		EVP_SignInit(&ctx,s->ctx->rsa_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);
@@ -856,12 +854,15 @@
 	if (!s->hit) /* new session */
 		{
 		/* new session-id */
+		/* Make sure we were not trying to re-use an old SSL_SESSION
+		 * or bad things can happen */
+		/* ZZZZZZZZZZZZZ */
 		s->session->session_id_length=SSL2_SSL_SESSION_ID_LENGTH;
 		memcpy(s->session->session_id,p,SSL2_SSL_SESSION_ID_LENGTH);
 		}
 	else
 		{
-		if (!(s->ctx->options & SSL_OP_MICROSOFT_SESS_ID_BUG))
+		if (!(s->options & SSL_OP_MICROSOFT_SESS_ID_BUG))
 			{
 			if (memcmp(buf,s->session->session_id,
 				(unsigned int)s->session->session_id_length) != 0)
diff --git a/ssl/s2_enc.c b/ssl/s2_enc.c
index b915f09..b43056f 100644
--- a/ssl/s2_enc.c
+++ b/ssl/s2_enc.c
@@ -1,5 +1,5 @@
 /* ssl/s2_enc.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -59,9 +59,6 @@
 #include <stdio.h>
 #include "ssl_locl.h"
 
-#define RS	0
-#define WS	1
-
 int ssl2_enc_init(s, client)
 SSL *s;
 int client;
@@ -94,6 +91,9 @@
 	rs= s->enc_read_ctx;
 	ws= s->enc_write_ctx;
 
+	EVP_CIPHER_CTX_init(rs);
+	EVP_CIPHER_CTX_init(ws);
+
 	num=c->key_len;
 	s->s2->key_material_length=num*2;
 
diff --git a/ssl/s2_lib.c b/ssl/s2_lib.c
index fb91582..275eb52 100644
--- a/ssl/s2_lib.c
+++ b/ssl/s2_lib.c
@@ -1,5 +1,5 @@
 /* ssl/s2_lib.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -69,7 +69,7 @@
 static long ssl2_default_timeout();
 #endif
 
-char *ssl2_version_str="SSLv2 part of SSLeay 0.8.1b 29-Jun-1998";
+char *ssl2_version_str="SSLv2 part of SSLeay 0.9.0b 29-Jun-1998";
 
 #define SSL2_NUM_CIPHERS (sizeof(ssl2_ciphers)/sizeof(SSL_CIPHER))
 
@@ -139,17 +139,6 @@
 	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,
@@ -159,17 +148,6 @@
 	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
 	{
@@ -196,7 +174,7 @@
 	};
 
 static SSL_METHOD SSLv2_data= {
-	2,
+	SSL2_VERSION,
 	ssl2_new,	/* local */
 	ssl2_clear,	/* local */
 	ssl2_free,	/* local */
@@ -216,6 +194,7 @@
 	ssl2_get_cipher,
 	ssl_bad_method,
 	ssl2_default_timeout,
+	&ssl3_undef_enc_method,
 	};
 
 static long ssl2_default_timeout()
@@ -254,6 +233,7 @@
 	SSL2_CTX *s2;
 
 	if ((s2=(SSL2_CTX *)Malloc(sizeof(SSL2_CTX))) == NULL) goto err;
+	memset(s2,0,sizeof(SSL2_CTX));
 
 	if ((s2->rbuf=(unsigned char *)Malloc(
 		SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER+2)) == NULL) goto err;
@@ -302,9 +282,8 @@
 	s2->rbuf=rbuf;
 	s2->wbuf=wbuf;
 	s2->clear_text=1;
-	s2->first_packet=0;
 	s->packet=s2->rbuf;
-	s->version=2;
+	s->version=SSL2_VERSION;
 	s->packet_length=0;
 	}
 
@@ -314,7 +293,17 @@
 long larg;
 char *parg;
 	{
-	return(0);
+	int ret=0;
+
+	switch(cmd)
+		{
+	case SSL_CTRL_GET_SESSION_REUSED:
+		ret=s->hit;
+		break;
+	default:
+		break;
+		}
+	return(ret);
 	}
 
 long ssl2_ctx_ctrl(ctx,cmd,larg,parg)
diff --git a/ssl/s2_meth.c b/ssl/s2_meth.c
index 0b8c2ac..cfc8828 100644
--- a/ssl/s2_meth.c
+++ b/ssl/s2_meth.c
@@ -1,5 +1,5 @@
 /* ssl/s2_meth.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -63,7 +63,7 @@
 static SSL_METHOD *ssl2_get_method(ver)
 int ver;
 	{
-	if (ver == 2)
+	if (ver == SSL2_VERSION)
 		return(SSLv2_method());
 	else
 		return(NULL);
diff --git a/ssl/s2_pkt.c b/ssl/s2_pkt.c
index 84bea33..e4167b5 100644
--- a/ssl/s2_pkt.c
+++ b/ssl/s2_pkt.c
@@ -1,5 +1,5 @@
 /* ssl/s2_pkt.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -70,8 +70,8 @@
 
 #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 do_ssl_write(SSL *s, char *buf, unsigned int len);
+static int write_pending(SSL *s, char *buf, unsigned int len);
 static int ssl_mt_error(int n);
 #else
 static int read_n();
@@ -121,7 +121,7 @@
 			}
 		}
 
-	errno=0;
+	clear_sys_error();
 	s->rwstate=SSL_NOTHING;
 	if (len <= 0) return(len);
 
@@ -231,7 +231,7 @@
 				(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);
+				return(-1);
 				}
 			}
 		INC32(s->s2->read_sequence); /* expect next number */
@@ -248,7 +248,7 @@
 	else
 		{
 		SSLerr(SSL_F_SSL2_READ,SSL_R_BAD_STATE);
-			return(SSL_RWERR_INTERNAL_ERROR);
+			return(-1);
 		}
 	}
 
@@ -312,7 +312,7 @@
 	s->packet=s->s2->rbuf;
 	while (newb < (int)n)
 		{
-		errno=0;
+		clear_sys_error();
 		if (s->rbio != NULL)
 			{
 			s->rwstate=SSL_READING;
@@ -356,7 +356,7 @@
 
 int ssl2_write(s, buf, len)
 SSL *s;
-const char *buf;
+char *buf;
 int len;
 	{
 	unsigned int n,tot;
@@ -380,7 +380,7 @@
 			return(-1);
 		}
 
-	errno=0;
+	clear_sys_error();
 	s->rwstate=SSL_NOTHING;
 	if (len <= 0) return(len);
 
@@ -405,7 +405,7 @@
 
 static int write_pending(s,buf,len)
 SSL *s;
-const char *buf;
+char *buf;
 unsigned int len;
 	{
 	int i;
@@ -414,15 +414,15 @@
 
 	/* check that they have given us the same buffer to
 	 * write */
-	if ((s->s2->wpend_tot != (int)len) || (s->s2->wpend_buf != buf))
+	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);
+		return(-1);
 		}
 
 	for (;;)
 		{
-		errno=0;
+		clear_sys_error();
 		if (s->wbio != NULL)
 			{
 			s->rwstate=SSL_WRITING;
@@ -453,7 +453,7 @@
 
 static int do_ssl_write(s, buf, len)
 SSL *s;
-const char *buf;
+char *buf;
 unsigned int len;
 	{
 	unsigned int j,k,olen,p,mac_size,bs;
diff --git a/ssl/s2_srvr.c b/ssl/s2_srvr.c
index 0112397..c6c8ea3 100644
--- a/ssl/s2_srvr.c
+++ b/ssl/s2_srvr.c
@@ -1,5 +1,5 @@
 /* ssl/s2_srvr.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -57,9 +57,6 @@
  */
 
 #include <stdio.h>
-#ifdef NO_MD5
-#include "md5.h"
-#endif
 #include "bio.h"
 #include "rand.h"
 #include "objects.h"
@@ -92,7 +89,7 @@
 static SSL_METHOD *ssl2_get_server_method(ver)
 int ver;
 	{
-	if (ver == 2)
+	if (ver == SSL2_VERSION)
 		return(SSLv2_server_method());
 	else
 		return(NULL);
@@ -126,7 +123,7 @@
 
 	RAND_seed((unsigned char *)&l,sizeof(l));
 	ERR_clear_error();
-	errno=0;
+	clear_sys_error();
 
 	if (s->info_callback != NULL)
 		cb=s->info_callback;
@@ -144,7 +141,7 @@
 		return(-1);
 		}
 
-	errno=0;
+	clear_sys_error();
 	for (;;)
 		{
 		state=s->state;
@@ -158,7 +155,7 @@
 
 			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
 
-			s->version=2;
+			s->version=SSL2_VERSION;
 			s->type=SSL_ST_ACCEPT;
 
 			buf=s->init_buf;
@@ -309,13 +306,13 @@
 			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1);
 
 			goto end;
-			BREAK;
+			/* BREAK; */
 
 		default:
 			SSLerr(SSL_F_SSL2_ACCEPT,SSL_R_UNKNOWN_STATE);
 			ret= -1;
 			goto end;
-			BREAK;
+			/* BREAK; */
 			}
 		
 		if ((cb != NULL) && (s->state != state))
@@ -336,7 +333,7 @@
 static int get_client_master_key(s)
 SSL *s;
 	{
-	int export,i,n,keya,ek;
+	int export,i,n,keya,error=0,ek;
 	unsigned char *p;
 	SSL_CIPHER *cp;
 	EVP_CIPHER *c;
@@ -390,7 +387,7 @@
 	memcpy(s->session->key_arg,&(p[s->s2->tmp.clear+s->s2->tmp.enc]),
 		(unsigned int)keya);
 
-	if (s->session->cert->key->privatekey == NULL)
+	if (s->session->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL)
 		{
 		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
 		SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_NO_PRIVATEKEY);
@@ -537,8 +534,8 @@
 		}
 	else
 		{
-		i=ssl_get_prev_session(s,s->s2->tmp.session_id_length,
-			&(p[s->s2->tmp.cipher_spec_length]));
+		i=ssl_get_prev_session(s,&(p[s->s2->tmp.cipher_spec_length]),
+			s->s2->tmp.session_id_length);
 		if (i == 1)
 			{ /* previous session */
 			s->hit=1;
@@ -656,9 +653,9 @@
 			/* put certificate type */
 			*(p++)=SSL2_CT_X509_CERTIFICATE;
 			s2n(s->version,p);	/* version */
-			n=i2d_X509(s->cert->key->x509,NULL);
+			n=i2d_X509(s->cert->pkeys[SSL_PKEY_RSA_ENC].x509,NULL);
 			s2n(n,p);		/* certificate length */
-			i2d_X509(s->cert->key->x509,&d);
+			i2d_X509(s->cert->pkeys[SSL_PKEY_RSA_ENC].x509,&d);
 			n=0;
 			
 			/* lets send out the ciphers we like in the
@@ -687,23 +684,7 @@
  	 */
  	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);
+		if (!ssl_init_wbio_buffer(s,1)) return(-1);
  		}
  
 	return(ssl2_do_write(s));
@@ -904,12 +885,12 @@
 		EVP_MD_CTX ctx;
 		EVP_PKEY *pkey=NULL;
 
-		EVP_VerifyInit(&ctx,EVP_md5());
+		EVP_VerifyInit(&ctx,s->ctx->rsa_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);
+		i=i2d_X509(s->session->cert->pkeys[SSL_PKEY_RSA_ENC].x509,NULL);
 		buf2=(unsigned char *)Malloc((unsigned int)i);
 		if (buf2 == NULL)
 			{
@@ -917,7 +898,7 @@
 			goto msg_end;
 			}
 		p2=buf2;
-		i=i2d_X509(s->session->cert->key->x509,&p2);
+		i=i2d_X509(s->session->cert->pkeys[SSL_PKEY_RSA_ENC].x509,&p2);
 		EVP_VerifyUpdate(&ctx,buf2,(unsigned int)i);
 		Free(buf2);
 
@@ -962,17 +943,17 @@
 	RSA *rsa;
 	int i;
 
-	if ((c == NULL) || (c->key->privatekey == NULL))
+	if ((c == NULL) || (c->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL))
 		{
 		SSLerr(SSL_F_SSL_RSA_PRIVATE_DECRYPT,SSL_R_NO_PRIVATEKEY);
 		return(-1);
 		}
-	if (c->key->privatekey->type != EVP_PKEY_RSA)
+	if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey->type != EVP_PKEY_RSA)
 		{
 		SSLerr(SSL_F_SSL_RSA_PRIVATE_DECRYPT,SSL_R_PUBLIC_KEY_IS_NOT_RSA);
 		return(-1);
 		}
-	rsa=c->key->privatekey->pkey.rsa;
+	rsa=c->pkeys[SSL_PKEY_RSA_ENC].privatekey->pkey.rsa;
 
 	/* we have the public key */
 	i=RSA_private_decrypt(len,from,to,rsa,padding);
diff --git a/ssl/s3_both.c b/ssl/s3_both.c
index 1d710ee..6de62e1 100644
--- a/ssl/s3_both.c
+++ b/ssl/s3_both.c
@@ -1,5 +1,5 @@
 /* ssl/s3_both.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -69,16 +69,12 @@
 /* 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)
+int ssl3_send_finished(s,a,b,sender,slen)
 SSL *s;
 int a;
 int b;
 unsigned char *sender;
+int slen;
 	{
 	unsigned char *p,*d;
 	int i;
@@ -89,11 +85,12 @@
 		d=(unsigned char *)s->init_buf->data;
 		p= &(d[4]);
 
-		i=ssl3_final_finish_mac(s,&(s->s3->finish_dgst1),sender,p);
+		i=s->method->ssl3_enc->final_finish_mac(s,
+			&(s->s3->finish_dgst1),
+			&(s->s3->finish_dgst2),
+			sender,slen,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);
@@ -107,13 +104,12 @@
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 	}
 
-int ssl3_get_finished(s,a,b,sender)
+int ssl3_get_finished(s,a,b)
 SSL *s;
 int a;
 int b;
-unsigned char *sender;
 	{
-	int al,i,j,ok;
+	int al,i,ok;
 	long n;
 	unsigned char *p;
 
@@ -133,7 +129,7 @@
 	/* If this occurs if we has missed a message */
 	if (!s->s3->change_cipher_spec)
 		{
-		al=SSL3_AD_UNEXPECTED_MESSAGE;
+		al=SSL_AD_UNEXPECTED_MESSAGE;
 		SSLerr(SSL_F_SSL3_GET_FINISHED,SSL_R_GOT_A_FIN_BEFORE_A_CCS);
 		goto f_err;
 		}
@@ -141,20 +137,18 @@
 
 	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));
+	i=s->method->ssl3_enc->finish_mac_length;
 
-	if ((i+j) != n)
+	if (i != n)
 		{
-		al=SSL3_AD_ILLEGAL_PARAMETER;
+		al=SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_FINISHED,SSL_R_BAD_DIGEST_LENGTH);
 		goto f_err;
 		}
 
-	if (	(memcmp(  p,    &(s->s3->tmp.finish_md1[0]),i) != 0) ||
-		(memcmp(&(p[i]),&(s->s3->tmp.finish_md2[0]),j) != 0))
+	if (memcmp(  p,    (char *)&(s->s3->tmp.finish_md[0]),i) != 0)
 		{
-		al=SSL3_AD_ILLEGAL_PARAMETER;
+		al=SSL_AD_DECRYPT_ERROR;
 		SSLerr(SSL_F_SSL3_GET_FINISHED,SSL_R_DIGEST_CHECK_FAILED);
 		goto f_err;
 		}
@@ -204,34 +198,43 @@
 	X509_STORE_CTX xs_ctx;
 	X509_OBJECT obj;
 
-	X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,NULL,NULL);
-
+	/* TLSv1 sends a chain with nothing in it, instead of an alert */
 	buf=s->init_buf;
-	for (;;)
+	if (!BUF_MEM_grow(buf,(int)(10)))
 		{
-		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);
+		SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB);
+		return(0);
 		}
+	if (x != NULL)
+		{
+		X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,NULL,NULL);
 
-	X509_STORE_CTX_cleanup(&xs_ctx);
+		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]);
@@ -260,7 +263,7 @@
 		s->s3->tmp.reuse_message=0;
 		if ((mt >= 0) && (s->s3->tmp.message_type != mt))
 			{
-			al=SSL3_AD_UNEXPECTED_MESSAGE;
+			al=SSL_AD_UNEXPECTED_MESSAGE;
 			SSLerr(SSL_F_SSL3_GET_MESSAGE,SSL_R_UNEXPECTED_MESSAGE);
 			goto f_err;
 			}
@@ -283,7 +286,7 @@
 
 		if ((mt >= 0) && (*p != mt))
 			{
-			al=SSL3_AD_UNEXPECTED_MESSAGE;
+			al=SSL_AD_UNEXPECTED_MESSAGE;
 			SSLerr(SSL_F_SSL3_GET_MESSAGE,SSL_R_UNEXPECTED_MESSAGE);
 			goto f_err;
 			}
@@ -292,7 +295,7 @@
 		n2l3(p,l);
 		if (l > (unsigned long)max)
 			{
-			al=SSL3_AD_ILLEGAL_PARAMETER;
+			al=SSL_AD_ILLEGAL_PARAMETER;
 			SSLerr(SSL_F_SSL3_GET_MESSAGE,SSL_R_EXCESSIVE_MESSAGE_SIZE);
 			goto f_err;
 			}
@@ -381,31 +384,53 @@
 	}
 
 int ssl_verify_alarm_type(type)
-int type;
+long type;
 	{
 	int al;
 
 	switch(type)
 		{
 	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
-
+	case X509_V_ERR_UNABLE_TO_GET_CRL:
+		al=SSL_AD_UNKNOWN_CA;
+		break;
 	case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
+	case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
 	case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
-	case X509_V_ERR_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_ERROR_IN_CRL_LAST_UPDATE_FIELD:
+	case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
+	case X509_V_ERR_CERT_NOT_YET_VALID:
+	case X509_V_ERR_CRL_NOT_YET_VALID:
+		al=SSL_AD_BAD_CERTIFICATE;
+		break;
+	case X509_V_ERR_CERT_SIGNATURE_FAILURE:
+	case X509_V_ERR_CRL_SIGNATURE_FAILURE:
+		al=SSL_AD_DECRYPT_ERROR;
+		break;
+	case X509_V_ERR_CERT_HAS_EXPIRED:
+	case X509_V_ERR_CRL_HAS_EXPIRED:
+		al=SSL_AD_CERTIFICATE_EXPIRED;
+		break;
+	case X509_V_ERR_CERT_REVOKED:
+		al=SSL_AD_CERTIFICATE_REVOKED;
+		break;
+	case X509_V_ERR_OUT_OF_MEM:
+		al=SSL_AD_INTERNAL_ERROR;
+		break;
 	case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
 	case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
 	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
 	case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
-		al=SSL3_AD_BAD_CERTIFICATE;
+	case X509_V_ERR_CERT_CHAIN_TOO_LONG:
+		al=SSL_AD_UNKNOWN_CA;
 		break;
-	case X509_V_ERR_CERT_HAS_EXPIRED:
-		al=SSL3_AD_CERTIFICATE_EXPIRED;
+	case X509_V_ERR_APPLICATION_VERIFICATION:
+		al=SSL_AD_HANDSHAKE_FAILURE;
 		break;
 	default:
-		al=SSL3_AD_CERTIFICATE_UNKNOWN;
+		al=SSL_AD_CERTIFICATE_UNKNOWN;
 		break;
 		}
 	return(al);
@@ -419,7 +444,7 @@
 
 	if (s->s3->rbuf.buf == NULL)
 		{
-		if (s->ctx->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER)
+		if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER)
 			extra=SSL3_RT_MAX_EXTRA;
 		else
 			extra=0;
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 4f551d2..940c6a4 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -1,5 +1,5 @@
 /* ssl/s3_clnt.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -102,7 +102,7 @@
 static SSL_METHOD *ssl3_get_client_method(ver)
 int ver;
 	{
-	if (ver == 3)
+	if (ver == SSL3_VERSION)
 		return(SSLv3_client_method());
 	else
 		return(NULL);
@@ -132,12 +132,12 @@
 	long num1;
 	void (*cb)()=NULL;
 	int ret= -1;
-	BIO *bbio,*under;
+	BIO *under;
 	int new_state,state,skip=0;;
 
 	RAND_seed((unsigned char *)&Time,sizeof(Time));
 	ERR_clear_error();
-	errno=0;
+	clear_sys_error();
 
 	if (s->info_callback != NULL)
 		cb=s->info_callback;
@@ -156,6 +156,7 @@
 		case SSL_ST_RENEGOTIATE:
 			s->new_session=1;
 			s->state=SSL_ST_CONNECT;
+			s->ctx->sess_connect_renegotiate++;
 			/* break */
 		case SSL_ST_BEFORE:
 		case SSL_ST_CONNECT:
@@ -164,7 +165,9 @@
 
 			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
 
-			s->version=3;
+			if ((s->version & 0xff00 ) != 0x0300)
+				abort();
+			/* s->version=SSL3_VERSION; */
 			s->type=SSL_ST_CONNECT;
 
 			if (s->init_buf == NULL)
@@ -185,27 +188,7 @@
 			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;
-				}
+			if (!ssl_init_wbio_buffer(s,0)) { ret= -1; goto end; }
 
 			/* don't push the buffering BIO quite yet */
 
@@ -226,7 +209,8 @@
 			s->init_num=0;
 
 			/* turn on buffering for the next lot of output */
-			s->wbio=BIO_push(s->bbio,s->wbio);
+			if (s->bbio != s->wbio)
+				s->wbio=BIO_push(s->bbio,s->wbio);
 
 			break;
 
@@ -307,7 +291,9 @@
 			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)
+			/* For TLS, cert_req is set to 2, so a cert chain
+			 * of nothing is sent, but no verify packet is sent */
+			if (s->s3->tmp.cert_req == 1)
 				{
 				s->state=SSL3_ST_CW_CERT_VRFY_A;
 				}
@@ -338,13 +324,13 @@
 			s->init_num=0;
 
 			s->session->cipher=s->s3->tmp.new_cipher;
-			if (!ssl3_setup_key_block(s))
+			if (!s->method->ssl3_enc->setup_key_block(s))
 				{
 				ret= -1;
 				goto end;
 				}
 
-			if (!ssl3_change_cipher_state(s,
+			if (!s->method->ssl3_enc->change_cipher_state(s,
 				SSL3_CHANGE_CIPHER_CLIENT_WRITE))
 				{
 				ret= -1;
@@ -357,7 +343,8 @@
 		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]));
+				s->method->ssl3_enc->client_finished,
+				s->method->ssl3_enc->client_finished_len);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_CW_FLUSH;
 
@@ -384,8 +371,7 @@
 		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]));
+				SSL3_ST_CR_FINISHED_B);
 			if (ret <= 0) goto end;
 
 			if (s->hit)
@@ -434,6 +420,7 @@
 			s->new_session=0;
 
 			ssl_update_cache(s,SSL_SESS_CACHE_CLIENT);
+			if (s->hit) s->ctx->sess_hit++;
 
 			ret=1;
 			/* s->server=0; */
@@ -455,7 +442,11 @@
 		/* did we do anything */
 		if (!s->s3->tmp.reuse_message && !skip)
 			{
-			if (s->debug) BIO_flush(s->wbio);
+			if (s->debug)
+				{
+				if ((ret=BIO_flush(s->wbio)) <= 0)
+					goto end;
+				}
 
 			if ((cb != NULL) && (s->state != state))
 				{
@@ -502,8 +493,8 @@
 		/* Do the message type and length last */
 		d=p= &(buf[4]);
 
-		*(p++)=SSL3_VERSION_MAJOR;
-		*(p++)=SSL3_VERSION_MINOR;
+		*(p++)=s->version>>8;
+		*(p++)=s->version&0xff;
 
 		/* Random stuff */
 		memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE);
@@ -572,10 +563,12 @@
 	if (!ok) return((int)n);
 	d=p=(unsigned char *)s->init_buf->data;
 
-	if ((p[0] != SSL3_VERSION_MAJOR) && (p[1] != SSL3_VERSION_MINOR))
+	if ((p[0] != (s->version>>8)) || (p[1] != (s->version&0xff)))
 		{
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_SSL_VERSION);
-		goto err;
+		s->version=(s->version&0xff00)|p[1];
+		al=SSL_AD_PROTOCOL_VERSION;
+		goto f_err;
 		}
 	p+=2;
 
@@ -592,32 +585,36 @@
 		/* SSLref returns 16 :-( */
 		if (j < SSL2_SSL_SESSION_ID_LENGTH)
 			{
-			al=SSL3_AD_ILLEGAL_PARAMETER;
+			al=SSL_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) &&
+	if ((j != 0) && (j == s->session->session_id_length) &&
 		(memcmp(p,s->session->session_id,j) == 0))
 		s->hit=1;
-	else
+	else	/* a miss or crap from the other end */
 		{
-		memcpy(s->session->session_id,p,j);
-		s->session->session_id_length=j;
+		/* If we were trying for session-id reuse, make a new
+		 * SSL_SESSION so we don't stuff up other people */
 		s->hit=0;
+		if (s->session->session_id_length > 0)
+			{
+			if (!ssl_get_new_session(s,0))
+				{
+				al=SSL_AD_INTERNAL_ERROR;
+				goto f_err;
+				}
+			}
+		s->session->session_id_length=j;
+		memcpy(s->session->session_id,p,j); /* j could be 0 */
 		}
 	p+=j;
 	c=ssl_get_cipher_by_char(s,p);
 	if (c == NULL)
 		{
 		/* unknown cipher */
-		al=SSL3_AD_HANDSHAKE_FAILURE;
+		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNKNOWN_CIPHER_RETURNED);
 		goto f_err;
 		}
@@ -628,17 +625,17 @@
 	if (i < 0)
 		{
 		/* we did not say we would use this cipher */
-		al=SSL3_AD_ILLEGAL_PARAMETER;
+		al=SSL_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 &
+		if (!(s->options &
 			SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG))
 			{
-			al=SSL3_AD_ILLEGAL_PARAMETER;
+			al=SSL_AD_ILLEGAL_PARAMETER;
 			SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED);
 			goto f_err;
 			}
@@ -649,7 +646,7 @@
 	j= *(p++);
 	if (j != 0)
 		{
-		al=SSL3_AD_HANDSHAKE_FAILURE;
+		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
 		goto f_err;
 		}
@@ -657,7 +654,7 @@
 	if (p != (d+n))
 		{
 		/* wrong packet length */
-		al=SSL3_AD_ILLEGAL_PARAMETER;
+		al=SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_BAD_PACKET_LENGTH);
 		goto err;
 		}
@@ -701,7 +698,7 @@
 
 	if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE)
 		{
-		al=SSL3_AD_UNEXPECTED_MESSAGE;
+		al=SSL_AD_UNEXPECTED_MESSAGE;
 		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_BAD_MESSAGE_TYPE);
 		goto f_err;
 		}
@@ -716,7 +713,7 @@
 	n2l3(p,llen);
 	if (llen+3 != n)
 		{
-		al=SSL3_AD_ILLEGAL_PARAMETER;
+		al=SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_LENGTH_MISMATCH);
 		goto f_err;
 		}
@@ -725,7 +722,7 @@
 		n2l3(p,l);
 		if ((l+nc+3) > llen)
 			{
-			al=SSL3_AD_ILLEGAL_PARAMETER;
+			al=SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH);
 			goto f_err;
 			}
@@ -734,13 +731,13 @@
 		x=d2i_X509(NULL,&q,l);
 		if (x == NULL)
 			{
-			al=SSL3_AD_ILLEGAL_PARAMETER;
+			al=SSL_AD_BAD_CERTIFICATE;
 			SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,ERR_R_ASN1_LIB);
 			goto f_err;
 			}
 		if (q != (p+l))
 			{
-			al=SSL3_AD_ILLEGAL_PARAMETER;
+			al=SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH);
 			goto f_err;
 			}
@@ -792,7 +789,7 @@
 		}
 
 	c->cert_type=i;
-	x->references++;
+	CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509);
 	if (c->pkeys[i].x509 != NULL)
 		X509_free(c->pkeys[i].x509);
 	c->pkeys[i].x509=x;
@@ -800,7 +797,7 @@
 
 	if ((s->session != NULL) && (s->session->peer != NULL)) 
 		X509_free(s->session->peer);
-	x->references++;
+	CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509);
 	s->session->peer=x;
 
 	x=NULL;
@@ -829,7 +826,9 @@
 	long n,alg;
 	EVP_PKEY *pkey=NULL;
 	RSA *rsa=NULL;
+#ifndef NO_DH
 	DH *dh=NULL;
+#endif
 
 	n=ssl3_get_message(s,
 		SSL3_ST_CR_KEY_EXCH_A,
@@ -885,7 +884,7 @@
 		param_len=i+2;
 		if (param_len > n)
 			{
-			al=SSL3_AD_ILLEGAL_PARAMETER;
+			al=SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_RSA_MODULUS_LENGTH);
 			goto f_err;
 			}
@@ -900,7 +899,7 @@
 		param_len+=i+2;
 		if (param_len > n)
 			{
-			al=SSL3_AD_ILLEGAL_PARAMETER;
+			al=SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_RSA_E_LENGTH);
 			goto f_err;
 			}
@@ -937,7 +936,7 @@
 		param_len=i+2;
 		if (param_len > n)
 			{
-			al=SSL3_AD_ILLEGAL_PARAMETER;
+			al=SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_DH_P_LENGTH);
 			goto f_err;
 			}
@@ -952,7 +951,7 @@
 		param_len+=i+2;
 		if (param_len > n)
 			{
-			al=SSL3_AD_ILLEGAL_PARAMETER;
+			al=SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_DH_G_LENGTH);
 			goto f_err;
 			}
@@ -967,7 +966,7 @@
 		param_len+=i+2;
 		if (param_len > n)
 			{
-			al=SSL3_AD_ILLEGAL_PARAMETER;
+			al=SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_DH_PUB_KEY_LENGTH);
 			goto f_err;
 			}
@@ -994,7 +993,7 @@
 		}
 	else if ((alg & SSL_kDHr) || (alg & SSL_kDHd))
 		{
-		al=SSL3_AD_HANDSHAKE_FAILURE;
+		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER);
 		goto f_err;
 		}
@@ -1013,7 +1012,7 @@
 		if ((i != n) || (n > j) || (n <= 0))
 			{
 			/* wrong packet length */
-			al=SSL3_AD_ILLEGAL_PARAMETER;
+			al=SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_WRONG_SIGNATURE_LENGTH);
 			goto err;
 			}
@@ -1027,7 +1026,8 @@
 			q=md_buf;
 			for (num=2; num > 0; num--)
 				{
-				EVP_DigestInit(&md_ctx,(num == 2)?EVP_md5():EVP_sha1());
+				EVP_DigestInit(&md_ctx,(num == 2)
+					?s->ctx->md5:s->ctx->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);
@@ -1039,14 +1039,14 @@
 				RSA_PKCS1_PADDING);
 			if (i <= 0)
 				{
-				al=SSL3_AD_ILLEGAL_PARAMETER;
+				al=SSL_AD_DECRYPT_ERROR;
 				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;
+				al=SSL_AD_DECRYPT_ERROR;
 				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SIGNATURE);
 				goto f_err;
 				}
@@ -1064,7 +1064,7 @@
 			if (!EVP_VerifyFinal(&md_ctx,p,(int)n,pkey))
 				{
 				/* bad signature */
-				al=SSL3_AD_ILLEGAL_PARAMETER;
+				al=SSL_AD_DECRYPT_ERROR;
 				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SIGNATURE);
 				goto f_err;
 				}
@@ -1086,7 +1086,7 @@
 			}
 		if (n != 0)
 			{
-			al=SSL3_AD_ILLEGAL_PARAMETER;
+			al=SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_EXTRA_DATA_IN_MESSAGE);
 			goto f_err;
 			}
@@ -1103,8 +1103,8 @@
 SSL *s;
 	{
 	int ok,ret=0;
-	unsigned long n,nc;
-	unsigned int llen,l,ctype_num,i;
+	unsigned long n,nc,l;
+	unsigned int llen,ctype_num,i;
 	X509_NAME *xn=NULL;
 	unsigned char *p,*d,*q;
 	STACK *ca_sk=NULL;
@@ -1132,11 +1132,23 @@
 
 	if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE_REQUEST)
 		{
-		ssl3_send_alert(s,SSL3_AL_FATAL,SSL3_AD_UNEXPECTED_MESSAGE);
+		ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
 		SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_WRONG_MESSAGE_TYPE);
 		goto err;
 		}
 
+	/* TLS does not like anon-DH with client cert */
+	if (s->version > SSL3_VERSION)
+		{
+		l=s->s3->tmp.new_cipher->algorithms;
+		if (l & SSL_aNULL)
+			{
+			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
+			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER);
+			goto err;
+			}
+		}
+
 	d=p=(unsigned char *)s->init_buf->data;
 
 	if ((ca_sk=sk_new(ca_dn_cmp)) == NULL)
@@ -1157,7 +1169,7 @@
 	n2s(p,llen);
 	if ((llen+ctype_num+2+1) != n)
 		{
-		ssl3_send_alert(s,SSL3_AL_FATAL,SSL3_AD_ILLEGAL_PARAMETER);
+		ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
 		SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_LENGTH_MISMATCH);
 		goto err;
 		}
@@ -1167,9 +1179,9 @@
 		n2s(p,l);
 		if ((l+nc+2) > llen)
 			{
-			if ((s->ctx->options & SSL_OP_NETSCAPE_CA_DN_BUG))
+			if ((s->options & SSL_OP_NETSCAPE_CA_DN_BUG))
 				goto cont; /* netscape bugs */
-			ssl3_send_alert(s,SSL3_AL_FATAL,SSL3_AD_ILLEGAL_PARAMETER);
+			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
 			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_CA_DN_TOO_LONG);
 			goto err;
 			}
@@ -1179,11 +1191,11 @@
 		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)
+			if (s->options & SSL_OP_NETSCAPE_CA_DN_BUG)
 				goto cont;
 			else
 				{
-				ssl3_send_alert(s,SSL3_AL_FATAL,SSL3_AD_ILLEGAL_PARAMETER);
+				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
 				SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,ERR_R_ASN1_LIB);
 				goto err;
 				}
@@ -1191,7 +1203,7 @@
 
 		if (q != (p+l))
 			{
-			ssl3_send_alert(s,SSL3_AL_FATAL,SSL3_AD_ILLEGAL_PARAMETER);
+			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
 			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_CA_DN_LENGTH_MISMATCH);
 			goto err;
 			}
@@ -1248,7 +1260,7 @@
 	if (n > 0)
 		{
 		/* should contain no data */
-		ssl3_send_alert(s,SSL3_AL_FATAL,SSL3_AD_ILLEGAL_PARAMETER);
+		ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
 		SSLerr(SSL_F_SSL3_GET_SERVER_DONE,SSL_R_LENGTH_MISMATCH);
 		}
 	ret=1;
@@ -1258,7 +1270,7 @@
 static int ssl3_send_client_key_exchange(s)
 SSL *s;
 	{
-	unsigned char *p,*d;
+	unsigned char *p,*q,*d;
 	int n;
 	unsigned long l;
 	EVP_PKEY *pkey=NULL;
@@ -1291,22 +1303,33 @@
 				rsa=pkey->pkey.rsa;
 				}
 				
-			tmp_buf[0]=SSL3_VERSION_MAJOR;
-			tmp_buf[1]=SSL3_VERSION_MINOR;
+			tmp_buf[0]=s->version>>8;
+			tmp_buf[1]=s->version&0xff;
 			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);
+			q=p;
+			/* Fix buf for TLS and beyond */
+			if (s->version > SSL3_VERSION)
+				p+=2;
+			n=RSA_public_encrypt(SSL_MAX_MASTER_KEY_LENGTH,
+				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;
 				}
 
+			/* Fix buf for TLS and beyond */
+			if (s->version > SSL3_VERSION)
+				{
+				s2n(n,q);
+				n+=2;
+				}
+
 			s->session->master_key_length=
-				ssl3_generate_master_secret(s,
+				s->method->ssl3_enc->generate_master_secret(s,
 					s->session->master_key,
 					tmp_buf,48);
 			memset(tmp_buf,0,48);
@@ -1323,7 +1346,7 @@
 			else
 				{
 				/* we get them from the cert */
-				ssl3_send_alert(s,SSL3_AL_FATAL,SSL3_AD_HANDSHAKE_FAILURE);
+				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNABLE_TO_FIND_DH_PARAMETERS);
 				goto err;
 				}
@@ -1342,7 +1365,9 @@
 
 			/* 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);
@@ -1351,7 +1376,7 @@
 
 			/* generate master key from the result */
 			s->session->master_key_length=
-				ssl3_generate_master_secret(s,
+				s->method->ssl3_enc->generate_master_secret(s,
 					s->session->master_key,p,n);
 			/* clean up */
 			memset(p,0,n);
@@ -1369,7 +1394,7 @@
 		else
 #endif
 			{
-			ssl3_send_alert(s,SSL3_AL_FATAL,SSL3_AD_HANDSHAKE_FAILURE);
+			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
 			SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_INTERNAL_ERROR);
 			goto err;
 			}
@@ -1395,8 +1420,11 @@
 	unsigned char *p,*d;
 	unsigned char data[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH];
 	EVP_PKEY *pkey;
-	int i=0,j;
+	int i=0;
 	unsigned long n;
+#ifndef NO_DSA
+	int j;
+#endif
 
 	if (s->state == SSL3_ST_CW_CERT_VRFY_A)
 		{
@@ -1404,14 +1432,14 @@
 		p= &(d[4]);
 		pkey=s->cert->key->privatekey;
 
-		ssl3_final_finish_mac(s,&(s->s3->finish_dgst2),
-			NULL,&(data[MD5_DIGEST_LENGTH]));
+		s->method->ssl3_enc->cert_verify_mac(s,&(s->s3->finish_dgst2),
+			&(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]));
+			s->method->ssl3_enc->cert_verify_mac(s,
+				&(s->s3->finish_dgst1),&(data[0]));
 			i=RSA_private_encrypt(
 				MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH,
 				data,&(p[2]),pkey->pkey.rsa,
@@ -1507,9 +1535,16 @@
 		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);
+			if (s->version == SSL3_VERSION)
+				{
+				s->s3->tmp.cert_req=0;
+				ssl3_send_alert(s,SSL3_AL_WARNING,SSL_AD_NO_CERTIFICATE);
+				return(1);
+				}
+			else
+				{
+				s->s3->tmp.cert_req=2;
+				}
 			}
 
 		/* Ok, we have a cert */
@@ -1519,7 +1554,8 @@
 	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);
+		l=ssl3_output_cert_chain(s,
+			(s->s3->tmp.cert_req == 2)?NULL:s->cert->key->x509);
 		s->init_num=(int)l;
 		s->init_off=0;
 		}
@@ -1635,7 +1671,7 @@
 		}
 	return(1);
 f_err:
-	ssl3_send_alert(s,SSL3_AL_FATAL,SSL3_AD_HANDSHAKE_FAILURE);
+	ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
 err:
 	return(0);
 	}
diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c
index f1cd25e..bbd9b63 100644
--- a/ssl/s3_enc.c
+++ b/ssl/s3_enc.c
@@ -1,5 +1,5 @@
 /* ssl/s3_enc.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -76,6 +76,56 @@
 	0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,
 	0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c };
 
+#ifndef NO_PROTO
+static int ssl3_handshake_mac(SSL *s, EVP_MD_CTX *in_ctx,
+	unsigned char *sender, int len, unsigned char *p);
+#else
+static int ssl3_handshake_mac();
+#endif
+
+static 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_change_cipher_state(s,which)
 SSL *s;
 int which;
@@ -122,6 +172,8 @@
 		mac_secret= &(s->s3->write_mac_secret[0]);
 		}
 
+	EVP_CIPHER_CTX_init(dd);
+
 	p=s->s3->tmp.key_block;
 	i=EVP_MD_size(m);
 	j=(exp)?5:EVP_CIPHER_key_length(c);
@@ -164,18 +216,20 @@
 		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]);
+		if (k > 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);
+	s->session->key_arg_length=0;
 
 	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);
@@ -305,7 +359,7 @@
 			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);
+				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECRYPT_ERROR);
 				return(0);
 				}
 			rec->length-=i;
@@ -317,8 +371,8 @@
 void ssl3_init_finished_mac(s)
 SSL *s;
 	{
-	EVP_DigestInit(&(s->s3->finish_dgst1),EVP_md5());
-	EVP_DigestInit(&(s->s3->finish_dgst2),EVP_sha1());
+	EVP_DigestInit(&(s->s3->finish_dgst1),s->ctx->md5);
+	EVP_DigestInit(&(s->s3->finish_dgst2),s->ctx->sha1);
 	}
 
 void ssl3_finish_mac(s,buf,len)
@@ -330,10 +384,34 @@
 	EVP_DigestUpdate(&(s->s3->finish_dgst2),buf,len);
 	}
 
-int ssl3_final_finish_mac(s,in_ctx,sender,p)
+int ssl3_cert_verify_mac(s,ctx,p)
+SSL *s;
+EVP_MD_CTX *ctx;
+unsigned char *p;
+	{
+	return(ssl3_handshake_mac(s,ctx,NULL,0,p));
+	}
+
+int ssl3_final_finish_mac(s,ctx1,ctx2,sender,len,p)
+SSL *s;
+EVP_MD_CTX *ctx1,*ctx2;
+unsigned char *sender;
+int len;
+unsigned char *p;
+	{
+	int ret;
+
+	ret=ssl3_handshake_mac(s,ctx1,sender,len,p);
+	p+=ret;
+	ret+=ssl3_handshake_mac(s,ctx2,sender,len,p);
+	return(ret);
+	}
+
+static int ssl3_handshake_mac(s,in_ctx,sender,len,p)
 SSL *s;
 EVP_MD_CTX *in_ctx;
 unsigned char *sender;
+int len;
 unsigned char *p;
 	{
 	unsigned int ret;
@@ -348,7 +426,7 @@
 	npad=(48/n)*n;
 
 	if (sender != NULL)
-		EVP_DigestUpdate(&ctx,sender,4);
+		EVP_DigestUpdate(&ctx,sender,len);
 	EVP_DigestUpdate(&ctx,s->session->master_key,
 		s->session->master_key_length);
 	EVP_DigestUpdate(&ctx,ssl3_pad_1,npad);
@@ -397,19 +475,6 @@
 	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);
@@ -433,12 +498,6 @@
 	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);
 	}
 
@@ -460,7 +519,7 @@
 
 	for (i=0; i<3; i++)
 		{
-		EVP_DigestInit(&ctx,EVP_sha1());
+		EVP_DigestInit(&ctx,s->ctx->sha1);
 		EVP_DigestUpdate(&ctx,salt[i],strlen((char *)salt[i]));
 		EVP_DigestUpdate(&ctx,p,len);
 		EVP_DigestUpdate(&ctx,&(s->s3->client_random[0]),
@@ -469,7 +528,7 @@
 			SSL3_RANDOM_SIZE);
 		EVP_DigestFinal(&ctx,buf,&n);
 
-		EVP_DigestInit(&ctx,EVP_md5());
+		EVP_DigestInit(&ctx,s->ctx->md5);
 		EVP_DigestUpdate(&ctx,p,len);
 		EVP_DigestUpdate(&ctx,buf,n);
 		EVP_DigestFinal(&ctx,out,&n);
@@ -479,3 +538,36 @@
 	return(ret);
 	}
 
+int ssl3_alert_code(code)
+int code;
+	{
+	switch (code)
+		{
+	case SSL_AD_CLOSE_NOTIFY:	return(SSL3_AD_CLOSE_NOTIFY);
+	case SSL_AD_UNEXPECTED_MESSAGE:	return(SSL3_AD_UNEXPECTED_MESSAGE);
+	case SSL_AD_BAD_RECORD_MAC:	return(SSL3_AD_BAD_RECORD_MAC);
+	case SSL_AD_DECRYPTION_FAILED:	return(SSL3_AD_BAD_RECORD_MAC);
+	case SSL_AD_RECORD_OVERFLOW:	return(SSL3_AD_BAD_RECORD_MAC);
+	case SSL_AD_DECOMPRESSION_FAILURE:return(SSL3_AD_DECOMPRESSION_FAILURE);
+	case SSL_AD_HANDSHAKE_FAILURE:	return(SSL3_AD_HANDSHAKE_FAILURE);
+	case SSL_AD_NO_CERTIFICATE:	return(SSL3_AD_NO_CERTIFICATE);
+	case SSL_AD_BAD_CERTIFICATE:	return(SSL3_AD_BAD_CERTIFICATE);
+	case SSL_AD_UNSUPPORTED_CERTIFICATE:return(SSL3_AD_UNSUPPORTED_CERTIFICATE);
+	case SSL_AD_CERTIFICATE_REVOKED:return(SSL3_AD_CERTIFICATE_REVOKED);
+	case SSL_AD_CERTIFICATE_EXPIRED:return(SSL3_AD_CERTIFICATE_EXPIRED);
+	case SSL_AD_CERTIFICATE_UNKNOWN:return(SSL3_AD_CERTIFICATE_UNKNOWN);
+	case SSL_AD_ILLEGAL_PARAMETER:	return(SSL3_AD_ILLEGAL_PARAMETER);
+	case SSL_AD_UNKNOWN_CA:		return(SSL3_AD_BAD_CERTIFICATE);
+	case SSL_AD_ACCESS_DENIED:	return(SSL3_AD_HANDSHAKE_FAILURE);
+	case SSL_AD_DECODE_ERROR:	return(SSL3_AD_HANDSHAKE_FAILURE);
+	case SSL_AD_DECRYPT_ERROR:	return(SSL3_AD_HANDSHAKE_FAILURE);
+	case SSL_AD_EXPORT_RESTRICION:	return(SSL3_AD_HANDSHAKE_FAILURE);
+	case SSL_AD_PROTOCOL_VERSION:	return(SSL3_AD_HANDSHAKE_FAILURE);
+	case SSL_AD_INSUFFICIENT_SECURITY:return(SSL3_AD_HANDSHAKE_FAILURE);
+	case SSL_AD_INTERNAL_ERROR:	return(SSL3_AD_HANDSHAKE_FAILURE);
+	case SSL_AD_USER_CANCLED:	return(SSL3_AD_HANDSHAKE_FAILURE);
+	case SSL_AD_NO_RENEGOTIATION:	return(-1); /* Don't send it :-) */
+	default:			return(-1);
+		}
+	}
+
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index b7bac8e..0fd9450 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -1,5 +1,5 @@
 /* ssl/s3_lib.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -60,7 +60,7 @@
 #include "objects.h"
 #include "ssl_locl.h"
 
-char *ssl3_version_str="SSLv3 part of SSLeay 0.8.1b 29-Jun-1998";
+char *ssl3_version_str="SSLv3 part of SSLeay 0.9.0b 29-Jun-1998";
 
 #define SSL3_NUM_CIPHERS	(sizeof(ssl3_ciphers)/sizeof(SSL_CIPHER))
 
@@ -131,8 +131,8 @@
 /* Cipher 1B */
 	{
 	1,
-	SSL3_TXT_ADH_DES_196_CBC_SHA,
-	SSL3_CK_ADH_DES_196_CBC_SHA,
+	SSL3_TXT_ADH_DES_192_CBC_SHA,
+	SSL3_CK_ADH_DES_192_CBC_SHA,
 	SSL_kEDH |SSL_aNULL|SSL_3DES |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3,
 	0,
 	SSL_ALL_CIPHERS,
@@ -358,8 +358,22 @@
 /* end of list */
 	};
 
+static SSL3_ENC_METHOD SSLv3_enc_data={
+	ssl3_enc,
+	ssl3_mac,
+	ssl3_setup_key_block,
+	ssl3_generate_master_secret,
+	ssl3_change_cipher_state,
+	ssl3_final_finish_mac,
+	MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH,
+	ssl3_cert_verify_mac,
+	SSL3_MD_CLIENT_FINISHED_CONST,4,
+	SSL3_MD_SERVER_FINISHED_CONST,4,
+	ssl3_alert_code,
+	};
+
 static SSL_METHOD SSLv3_data= {
-	3,
+	SSL3_VERSION,
 	ssl3_new,
 	ssl3_clear,
 	ssl3_free,
@@ -379,6 +393,7 @@
 	ssl3_get_cipher,
 	ssl_bad_method,
 	ssl3_default_timeout,
+	&SSLv3_enc_data,
 	};
 
 static long ssl3_default_timeout()
@@ -420,14 +435,18 @@
 	SSL3_CTX *s3;
 
 	if ((s3=(SSL3_CTX *)Malloc(sizeof(SSL3_CTX))) == NULL) goto err;
+	memset(s3,0,sizeof(SSL3_CTX));
 
 	s->s3=s3;
+	/*
 	s->s3->tmp.ca_names=NULL;
 	s->s3->tmp.key_block=NULL;
+	s->s3->tmp.key_block_length=0;
 	s->s3->rbuf.buf=NULL;
 	s->s3->wbuf.buf=NULL;
+	*/
 
-	ssl3_clear(s);
+	s->method->ssl_clear(s);
 	return(1);
 err:
 	return(0);
@@ -465,16 +484,14 @@
 	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;
+	if (rp != NULL) s->s3->rbuf.buf=rp;
+	if (wp != NULL) s->s3->wbuf.buf=wp;
 	s->packet_length=0;
-	s->version=3;
+	s->s3->renegotiate=0;
+	s->s3->total_renegotiations=0;
+	s->s3->num_renegotiations=0;
+	s->s3->in_read_app_data=0;
+	s->version=SSL3_VERSION;
 	}
 
 long ssl3_ctrl(s,cmd,larg,parg)
@@ -483,7 +500,29 @@
 long larg;
 char *parg;
 	{
-	return(0);
+	int ret=0;
+
+	switch (cmd)
+		{
+	case SSL_CTRL_GET_SESSION_REUSED:
+		ret=s->hit;
+		break;
+	case SSL_CTRL_GET_CLIENT_CERT_REQUEST:
+		break;
+	case SSL_CTRL_GET_NUM_RENEGOTIATIONS:
+		ret=s->s3->num_renegotiations;
+		break;
+	case SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS:
+		ret=s->s3->num_renegotiations;
+		s->s3->num_renegotiations=0;
+		break;
+	case SSL_CTRL_GET_TOTAL_RENEGOTIATIONS:
+		ret=s->s3->total_renegotiations;
+		break;
+	default:
+		break;
+		}
+	return(ret);
 	}
 
 long ssl3_ctx_ctrl(ctx,cmd,larg,parg)
@@ -623,49 +662,6 @@
 	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;
@@ -754,7 +750,8 @@
 		p[ret++]=SSL3_CT_DSS_FIXED_DH;
 #endif
 		}
-	if (alg & (SSL_kEDH|SSL_kDHd|SSL_kDHr))
+	if ((s->version == SSL3_VERSION) &&
+		(alg & (SSL_kEDH|SSL_kDHd|SSL_kDHr)))
 		{
 #ifndef NO_RSA
 		p[ret++]=SSL3_CT_RSA_EPHEMERAL_DH;
@@ -767,7 +764,7 @@
 #ifndef NO_RSA
 	p[ret++]=SSL3_CT_RSA_SIGN;
 #endif
-/*	p[ret++]=SSL3_CT_DSS_SIGN; */
+	p[ret++]=SSL3_CT_DSS_SIGN;
 	return(ret);
 	}
 
@@ -787,7 +784,7 @@
 		{
 		s->shutdown|=SSL_SENT_SHUTDOWN;
 #if 1
-		ssl3_send_alert(s,SSL3_AL_WARNING,SSL3_AD_CLOSE_NOTIFY);
+		ssl3_send_alert(s,SSL3_AL_WARNING,SSL_AD_CLOSE_NOTIFY);
 #endif
 		/* our shutdown alert has been sent now, and if it still needs
 	 	 * to be written, s->s3->alert_dispatch will be true */
@@ -814,7 +811,7 @@
 
 int ssl3_write(s,buf,len)
 SSL *s;
-const char *buf;
+char *buf;
 int len;
 	{
 	int ret,n;
@@ -827,7 +824,8 @@
 		return(0);
 		}
 #endif
-	errno=0;
+	clear_sys_error();
+	if (s->s3->renegotiate) ssl3_renegotiate_check(s);
 
 	/* This is an experimental flag that sends the
 	 * last handshake message in the same packet as the first
@@ -867,6 +865,7 @@
 			(char *)buf,len);
 		if (ret <= 0) return(ret);
 		}
+
 	return(ret);
 	}
 
@@ -875,8 +874,24 @@
 char *buf;
 int len;
 	{
-	errno=0;
-	return(ssl3_read_bytes(s,SSL3_RT_APPLICATION_DATA,buf,len));
+	int ret;
+	
+	clear_sys_error();
+	if (s->s3->renegotiate) ssl3_renegotiate_check(s);
+	s->s3->in_read_app_data=1;
+	ret=ssl3_read_bytes(s,SSL3_RT_APPLICATION_DATA,buf,len);
+	if ((ret == -1) && (s->s3->in_read_app_data == 0))
+		{
+		ERR_get_error(); /* clear the error */
+		s->s3->in_read_app_data=0;
+		s->in_handshake++;
+		ret=ssl3_read_bytes(s,SSL3_RT_APPLICATION_DATA,buf,len);
+		s->in_handshake--;
+		}
+	else
+		s->s3->in_read_app_data=0;
+
+	return(ret);
 	}
 
 int ssl3_peek(s,buf,len)
@@ -889,7 +904,12 @@
 
 	rr= &(s->s3->rrec);
 	if ((rr->length == 0) || (rr->type != SSL3_RT_APPLICATION_DATA))
-		return(0);
+		{
+		n=ssl3_read(s,buf,1);
+		if (n <= 0) return(n);
+		rr->length++;
+		rr->off--;
+		}
 
 	if ((unsigned int)len > rr->length)
 		n=rr->length;
@@ -908,8 +928,34 @@
 	if (s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)
 		return(0);
 
-	if (!SSL_in_init(s))
-		s->state=SSL_ST_RENEGOTIATE;
+	s->s3->renegotiate=1;
 	return(1);
 	}
 
+int ssl3_renegotiate_check(s)
+SSL *s;
+	{
+	int ret=0;
+
+	if (s->s3->renegotiate)
+		{
+		if (	(s->s3->rbuf.left == 0) &&
+			(s->s3->wbuf.left == 0) &&
+			!SSL_in_init(s))
+			{
+/*
+if we are the server, and we have sent a 'RENEGOTIATE' message, we
+need to go to SSL_ST_ACCEPT.
+*/
+			/* SSL_ST_ACCEPT */
+			s->state=SSL_ST_RENEGOTIATE;
+			s->s3->renegotiate=0;
+			s->s3->num_renegotiations++;
+			s->s3->total_renegotiations++;
+			ret=1;
+			}
+		}
+	return(ret);
+	}
+
+
diff --git a/ssl/s3_meth.c b/ssl/s3_meth.c
index 4762b21..3d66b46 100644
--- a/ssl/s3_meth.c
+++ b/ssl/s3_meth.c
@@ -1,5 +1,5 @@
 /* ssl/s3_meth.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -63,9 +63,9 @@
 static SSL_METHOD *ssl3_get_method(ver)
 int ver;
 	{
-	if (ver == 3)
+	if (ver == SSL3_VERSION)
 		return(SSLv3_method());
-	else
+	else 
 		return(NULL);
 	}
 
diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c
index 3be69ef..2385080 100644
--- a/ssl/s3_pkt.c
+++ b/ssl/s3_pkt.c
@@ -1,5 +1,5 @@
 /* ssl/s3_pkt.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -87,12 +87,14 @@
 static int ssl3_get_record(SSL *s);
 static int do_compress(SSL *ssl);
 static int do_uncompress(SSL *ssl);
+static int do_change_cipher_spec(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();
+static int do_change_cipher_spec();
 #endif
 
 static int ssl3_read_n(s,n,max,extend)
@@ -159,7 +161,7 @@
 
 	while (newb < n)
 		{
-		errno=0;
+		clear_sys_error();
 		if (s->rbio != NULL)
 			{
 			s->rwstate=SSL_READING;
@@ -211,6 +213,7 @@
 static int ssl3_get_record(s)
 SSL *s;
 	{
+	char tmp_buf[512];
 	int ssl_major,ssl_minor,al;
 	int n,i,ret= -1;
 	SSL3_BUFFER *rb;
@@ -226,7 +229,7 @@
 	rb= &(s->s3->rbuf);
 	sess=s->session;
 
-	if (s->ctx->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER)
+	if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER)
 		extra=SSL3_RT_MAX_EXTRA;
 	else
 		extra=0;
@@ -257,25 +260,27 @@
 			}
 		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 (version != s->version)
+				{
+				SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER);
+				/* Send back error using their
+				 * version number :-) */
+				s->version=version;
+				al=SSL_AD_PROTOCOL_VERSION;
+				goto f_err;
+				}
 			}
 
-		if (s->version != SSL3_VERSION_MAJOR)
+		if ((version>>8) != SSL3_VERSION_MAJOR)
 			{
-			SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_INTERNAL_ERROR);
+			SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER);
 			goto err;
 			}
 
 		if (rr->length > 
 			(unsigned int)SSL3_RT_MAX_ENCRYPTED_LENGTH+extra)
 			{
-			al=SSL3_AD_ILLEGAL_PARAMETER;
+			al=SSL_AD_RECORD_OVERFLOW;
 			SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_PACKET_LENGTH_TOO_LONG);
 			goto f_err;
 			}
@@ -319,20 +324,25 @@
 	/* check is not needed I belive */
 	if (rr->length > (unsigned int)SSL3_RT_MAX_ENCRYPTED_LENGTH+extra)
 		{
-		al=SSL3_AD_ILLEGAL_PARAMETER;
+		al=SSL_AD_RECORD_OVERFLOW;
 		SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
 		goto f_err;
 		}
 
 	/* decrypt in place in 'rr->input' */
 	rr->data=rr->input;
+	memcpy(tmp_buf,rr->input,(rr->length > 512)?512:rr->length);
 
-	if (!ssl3_enc(s,0))
+	if (!s->method->ssl3_enc->enc(s,0))
 		{
-		al=SSL3_AD_ILLEGAL_PARAMETER;
+		al=SSL_AD_DECRYPT_ERROR;
 		goto f_err;
 		}
-
+#ifdef TLS_DEBUG
+printf("dec %d\n",rr->length);
+{ int z; for (z=0; z<rr->length; z++) printf("%02X%c",rr->data[z],((z+1)%16)?' ':'\n'); }
+printf("\n");
+#endif
 	/* r->length is now the compressed data plus mac */
 	if (	(sess == NULL) ||
 		(s->enc_read_ctx == NULL) ||
@@ -345,24 +355,24 @@
 
 		if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra+mac_size)
 			{
-			al=SSL3_AD_ILLEGAL_PARAMETER;
+			al=SSL_AD_RECORD_OVERFLOW;
 			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;
+			al=SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_LENGTH_TOO_SHORT);
 			goto f_err;
 			}
 		rr->length-=mac_size;
-		i=ssl3_mac(s,md,0);
+		i=s->method->ssl3_enc->mac(s,md,0);
 		if (memcmp(md,&(rr->data[rr->length]),mac_size) != 0)
 			{
-			al=SSL3_AD_BAD_RECORD_MAC;
+			al=SSL_AD_BAD_RECORD_MAC;
 			SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_BAD_MAC_DECODE);
-			ret=SSL_RWERR_BAD_MAC_DECODE;
+			ret= -1;
 			goto f_err;
 			}
 		}
@@ -373,13 +383,13 @@
 		if (rr->length > 
 			(unsigned int)SSL3_RT_MAX_COMPRESSED_LENGTH+extra)
 			{
-			al=SSL3_AD_ILLEGAL_PARAMETER;
+			al=SSL_AD_RECORD_OVERFLOW;
 			SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_COMPRESSED_LENGTH_TOO_LONG);
 			goto f_err;
 			}
 		if (!do_uncompress(s))
 			{
-			al=SSL3_AD_DECOMPRESSION_FAILURE;
+			al=SSL_AD_DECOMPRESSION_FAILURE;
 			SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_BAD_DECOMPRESSION);
 			goto f_err;
 			}
@@ -387,7 +397,7 @@
 
 	if (rr->length > (unsigned int)SSL3_RT_MAX_PLAIN_LENGTH+extra)
 		{
-		al=SSL3_AD_DECOMPRESSION_FAILURE;
+		al=SSL_AD_RECORD_OVERFLOW;
 		SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_DATA_LENGTH_TOO_LONG);
 		goto f_err;
 		}
@@ -426,7 +436,7 @@
 	return(1);
 	}
 
-/* Call this write a data
+/* Call this to write data
  * It will return <= 0 if not all data has been sent or non-blocking IO.
  */
 int ssl3_write_bytes(s,type,buf,len)
@@ -460,7 +470,7 @@
 			nw=SSL3_RT_MAX_PLAIN_LENGTH;
 		else
 			nw=n;
-
+			
 		i=do_ssl3_write(s,type,&(buf[tot]),nw);
 		if (i <= 0)
 			{
@@ -526,8 +536,8 @@
 	*(p++)=type&0xff;
 	wr->type=type;
 
-	*(p++)=SSL3_VERSION_MAJOR;
-	*(p++)=SSL3_VERSION_MINOR;
+	*(p++)=(s->version>>8);
+	*(p++)=s->version&0xff;
 	
 	/* record where we are to write out packet length */
 	plen=p; 
@@ -562,14 +572,14 @@
 
 	if (mac_size != 0)
 		{
-		ssl3_mac(s,&(p[wr->length]),1);
+		s->method->ssl3_enc->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);
+	s->method->ssl3_enc->enc(s,1);
 
 	/* record length after mac and block padding */
 	s2n(wr->length,plen);
@@ -604,16 +614,17 @@
 	{
 	int i;
 
-	if ((s->s3->wpend_tot != (int)len) || (s->s3->wpend_buf != buf)
+/* XXXX */
+	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);
+		return(-1);
 		}
 
 	for (;;)
 		{
-		errno=0;
+		clear_sys_error();
 		if (s->wbio != NULL)
 			{
 			s->rwstate=SSL_WRITING;
@@ -647,14 +658,14 @@
 	{
 	int al,i,j,n,ret;
 	SSL3_RECORD *rr;
-	unsigned char *sender;
 	void (*cb)()=NULL;
+	BIO *bio;
 
 	if (s->s3->rbuf.buf == NULL) /* Not initalised yet */
 		if (!ssl3_setup_buffers(s))
 			return(-1);
 
-	if (!s->in_handshake && SSL_in_before(s))
+	if (!s->in_handshake && SSL_in_init(s))
 		{
 		i=s->handshake_func(s);
 		if (i < 0) return(i);
@@ -684,7 +695,7 @@
 
 	if (s->s3->change_cipher_spec && (rr->type != SSL3_RT_HANDSHAKE))
 		{
-		al=SSL3_AD_UNEXPECTED_MESSAGE;
+		al=SSL_AD_UNEXPECTED_MESSAGE;
 		SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_DATA_BETWEEN_CCS_AND_FINISHED);
 		goto err;
 		}
@@ -705,21 +716,25 @@
 		if ((rr->data[1] != 0) || (rr->data[2] != 0) ||
 			(rr->data[3] != 0))
 			{
-			al=SSL3_AD_ILLEGAL_PARAMETER;
+			al=SSL_AD_DECODE_ERROR;
 			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))
+			!(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) &&
+			!s->s3->renegotiate)
 			{
 			ssl3_renegotiate(s);
-			n=s->handshake_func(s);
-			if (n < 0) return(n);
-			if (n == 0)
+			if (ssl3_renegotiate_check(s))
 				{
-				SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
-				return(-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);
+					}
 				}
 			}
 		rr->length=0;
@@ -734,7 +749,7 @@
 			{
 			if ((rr->length != 2) || (rr->off != 0))
 				{
-				al=SSL3_AD_ILLEGAL_PARAMETER;
+				al=SSL_AD_DECODE_ERROR;
 				SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_ALERT_RECORD);
 				goto f_err;
 				}
@@ -759,7 +774,7 @@
 			if (i == 1)
 				{
 				s->s3->warn_alert=n;
-				if (n == SSL3_AD_CLOSE_NOTIFY)
+				if (n == SSL_AD_CLOSE_NOTIFY)
 					{
 					s->shutdown|=SSL_RECEIVED_SHUTDOWN;
 					return(0);
@@ -767,16 +782,20 @@
 				}
 			else if (i == 2)
 				{
+				char tmp[16];
+
 				s->rwstate=SSL_NOTHING;
 				s->s3->fatal_alert=n;
 				SSLerr(SSL_F_SSL3_READ_BYTES,1000+n);
+				sprintf(tmp,"%d",n);
+				ERR_add_error_data(2,"SSL alert number ",tmp);
 				s->shutdown|=SSL_RECEIVED_SHUTDOWN;
 				SSL_CTX_remove_session(s->ctx,s->session);
 				return(0);
 				}
 			else
 				{
-				al=SSL3_AD_ILLEGAL_PARAMETER;
+				al=SSL_AD_ILLEGAL_PARAMETER;
 				SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNKNOWN_ALERT_TYPE);
 				goto f_err;
 				}
@@ -797,43 +816,17 @@
 			if (	(rr->length != 1) || (rr->off != 0) ||
 				(rr->data[0] != SSL3_MT_CCS))
 				{
-				i=SSL3_AD_ILLEGAL_PARAMETER;
+				i=SSL_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))
+			if (!do_change_cipher_spec(s))
 				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
+				goto start;
 			}
 
 		/* else we have a handshake */
@@ -853,12 +846,68 @@
 				SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
 				return(-1);
 				}
-			goto start;
+
+			/* In the case where we try to read application data
+			 * the first time, but we trigger an SSL handshake, we
+			 * return -1 with the retry option set.  I do this
+			 * otherwise renegotiation can cause nasty problems 
+			 * in the non-blocking world */
+
+			s->rwstate=SSL_READING;
+			bio=SSL_get_rbio(s);
+			BIO_clear_retry_flags(bio);
+			BIO_set_retry_read(bio);
+			return(-1);
 			}
 
-		al=SSL3_AD_UNEXPECTED_MESSAGE;
-		SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
-		goto f_err;
+		switch (rr->type)
+			{
+		default:
+#ifndef NO_TLS
+			/* TLS just ignores unknown message types */
+			if (s->version == TLS1_VERSION)
+				{
+				goto start;
+				}
+#endif
+		case SSL3_RT_CHANGE_CIPHER_SPEC:
+		case SSL3_RT_ALERT:
+		case SSL3_RT_HANDSHAKE:
+			al=SSL_AD_UNEXPECTED_MESSAGE;
+			SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
+			goto f_err;
+		case SSL3_RT_APPLICATION_DATA:
+			/* At this point, we were expecting something else,
+			 * but have application data.  What we do is set the
+			 * error, and return -1.  On the way out, if the
+			 * library was running inside ssl3_read() and it makes
+			 * sense to read application data at this point, we
+			 * will indulge it.  This will mostly happen during
+			 * session renegotiation.
+			 */
+			if (s->s3->in_read_app_data &&
+				(s->s3->total_renegotiations != 0) &&
+				((
+				  (s->state & SSL_ST_CONNECT) &&
+				  (s->state >= SSL3_ST_CW_CLNT_HELLO_A) &&
+				  (s->state <= SSL3_ST_CR_SRVR_HELLO_A)
+				 ) || (
+				  (s->state & SSL_ST_ACCEPT) &&
+				  (s->state <= SSL3_ST_SW_HELLO_REQ_A) &&
+				  (s->state >= SSL3_ST_SR_CLNT_HELLO_A)
+				 )
+				))
+				{
+				s->s3->in_read_app_data=0;
+				return(-1);
+				}
+			else
+				{
+				al=SSL_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
@@ -866,7 +915,7 @@
 	if (SSL_in_init(s) && (type == SSL3_RT_APPLICATION_DATA) &&
 		(s->enc_read_ctx == NULL))
 		{
-		al=SSL3_AD_UNEXPECTED_MESSAGE;
+		al=SSL_AD_UNEXPECTED_MESSAGE;
 		SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_APP_DATA_IN_HANDSHAKE);
 		goto f_err;
 		}
@@ -882,7 +931,10 @@
 	rr->length-=n;
 	rr->off+=n;
 	if (rr->length <= 0)
+		{
 		s->rstate=SSL_ST_READ_HEADER;
+		rr->off=0;
+		}
 
 	if (type == SSL3_RT_HANDSHAKE)
 		ssl3_finish_mac(s,(unsigned char *)buf,n);
@@ -893,6 +945,49 @@
 	return(-1);
 	}
 
+static int do_change_cipher_spec(s)
+SSL *s;
+	{
+	int i;
+	unsigned char *sender;
+	int slen;
+
+	if (s->state & SSL_ST_ACCEPT)
+		i=SSL3_CHANGE_CIPHER_SERVER_READ;
+	else
+		i=SSL3_CHANGE_CIPHER_CLIENT_READ;
+
+	if (s->s3->tmp.key_block == NULL)
+		{
+		s->session->cipher=s->s3->tmp.new_cipher;
+		if (!s->method->ssl3_enc->setup_key_block(s)) return(0);
+		}
+
+	if (!s->method->ssl3_enc->change_cipher_state(s,i))
+		return(0);
+
+	/* we have to record the message digest at
+	 * this point so we can get it before we read
+	 * the finished message */
+	if (s->state & SSL_ST_CONNECT)
+		{
+		sender=s->method->ssl3_enc->server_finished;
+		slen=s->method->ssl3_enc->server_finished_len;
+		}
+	else
+		{
+		sender=s->method->ssl3_enc->client_finished;
+		slen=s->method->ssl3_enc->client_finished_len;
+		}
+
+	s->method->ssl3_enc->final_finish_mac(s,
+		&(s->s3->finish_dgst1),
+		&(s->s3->finish_dgst2),
+		sender,slen,&(s->s3->tmp.finish_md[0]));
+
+	return(1);
+	}
+
 int ssl3_do_write(s,type)
 SSL *s;
 int type;
@@ -914,6 +1009,9 @@
 int level;
 int desc;
 	{
+	/* Map tls/ssl alert value to correct one */
+	desc=s->method->ssl3_enc->alert_value(desc);
+	if (desc < 0) return;
 	/* If a fatal one, remove from cache */
 	if ((level == 2) && (s->session != NULL))
 		SSL_CTX_remove_session(s->ctx,s->session);
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index ebff575..64903af 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -1,5 +1,5 @@
 /* ssl/s3_srvr.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -96,14 +96,13 @@
 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)
+	if (ver == SSL3_VERSION)
 		return(SSLv3_server_method());
 	else
 		return(NULL);
@@ -134,12 +133,12 @@
 	long num1;
 	int ret= -1;
 	CERT *ct;
-	BIO *bbio,*under;
+	BIO *under;
 	int new_state,state,skip=0;
 
 	RAND_seed((unsigned char *)&Time,sizeof(Time));
 	ERR_clear_error();
-	errno=0;
+	clear_sys_error();
 
 	if (s->info_callback != NULL)
 		cb=s->info_callback;
@@ -179,7 +178,9 @@
 
 			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
 
-			s->version=3;
+			if ((s->version>>8) != 3)
+				abort();
+			/* s->version=SSL3_VERSION; */
 			s->type=SSL_ST_ACCEPT;
 
 			if (s->init_buf == NULL)
@@ -206,39 +207,19 @@
 			/* 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;
-				}
+			if (!ssl_init_wbio_buffer(s,1)) { 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);
+				s->ctx->sess_accept++;
 				}
 			else
 				{
+				s->ctx->sess_accept_renegotiate++;
 				s->state=SSL3_ST_SW_HELLO_REQ_A;
 				}
 			break;
@@ -269,7 +250,7 @@
 			s->state=SSL_ST_OK;
 			ret=1;
 			goto end;
-			break;
+			/* break; */
 
 		case SSL3_ST_SR_CLNT_HELLO_A:
 		case SSL3_ST_SR_CLNT_HELLO_B:
@@ -328,7 +309,7 @@
 
 			/* clear this, it may get reset by
 			 * send_server_key_exchange */
-			if (s->ctx->options & SSL_OP_EPHEMERAL_RSA)
+			if (s->options & SSL_OP_EPHEMERAL_RSA)
 				s->s3->tmp.use_rsa_tmp=1;
 			else
 				s->s3->tmp.use_rsa_tmp=0;
@@ -364,10 +345,12 @@
 				{
 				/* no cert request */
 				skip=1;
+				s->s3->tmp.cert_request=0;
 				s->state=SSL3_ST_SW_SRVR_DONE_A;
 				}
 			else
 				{
+				s->s3->tmp.cert_request=1;
 				ret=ssl3_send_certificate_request(s);
 				if (ret <= 0) goto end;
 				s->state=SSL3_ST_SW_SRVR_DONE_A;
@@ -417,10 +400,12 @@
 
 			/* 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]));
+			s->method->ssl3_enc->cert_verify_mac(s,
+				&(s->s3->finish_dgst1),
+				&(s->s3->tmp.finish_md[0]));
+			s->method->ssl3_enc->cert_verify_mac(s,
+				&(s->s3->finish_dgst2),
+				&(s->s3->tmp.finish_md[MD5_DIGEST_LENGTH]));
 
 			break;
 
@@ -438,8 +423,7 @@
 		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]));
+				SSL3_ST_SR_FINISHED_B);
 			if (ret <= 0) goto end;
 			if (s->hit)
 				s->state=SSL_ST_OK;
@@ -452,7 +436,8 @@
 		case SSL3_ST_SW_CHANGE_B:
 
 			s->session->cipher=s->s3->tmp.new_cipher;
-			if (!ssl3_setup_key_block(s)) { ret= -1; goto end; }
+			if (!s->method->ssl3_enc->setup_key_block(s))
+				{ ret= -1; goto end; }
 
 			ret=ssl3_send_change_cipher_spec(s,
 				SSL3_ST_SW_CHANGE_A,SSL3_ST_SW_CHANGE_B);
@@ -461,7 +446,7 @@
 			s->state=SSL3_ST_SW_FINISHED_A;
 			s->init_num=0;
 
-			if (!ssl3_change_cipher_state(s,
+			if (!s->method->ssl3_enc->change_cipher_state(s,
 				SSL3_CHANGE_CIPHER_SERVER_WRITE))
 				{
 				ret= -1;
@@ -474,7 +459,8 @@
 		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]));
+				s->method->ssl3_enc->server_finished,
+				s->method->ssl3_enc->server_finished_len);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_SW_FLUSH;
 			if (s->hit)
@@ -513,18 +499,23 @@
 			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1);
 
 			goto end;
-			break;
+			/* break; */
 
 		default:
 			SSLerr(SSL_F_SSL3_ACCEPT,SSL_R_UNKNOWN_STATE);
 			ret= -1;
 			goto end;
-			break;
+			/* break; */
 			}
 		
 		if (!s->s3->tmp.reuse_message && !skip)
 			{
-			if (s->debug) BIO_flush(s->wbio);
+			if (s->debug)
+				{
+				if ((ret=BIO_flush(s->wbio)) <= 0)
+					goto end;
+				}
+
 
 			if ((cb != NULL) && (s->state != state))
 				{
@@ -578,6 +569,12 @@
 	SSL_CIPHER *c;
 	STACK *ciphers=NULL;
 
+	/* We do this so that we will respond with our native type.
+	 * If we are TLSv1 and we get SSLv3, we will respond with TLSv1,
+	 * This down switching should be handled by a different method.
+	 * If we are SSLv3, we will respond with SSLv3, even if prompted with
+	 * TLSv1.
+	 */
 	if (s->state == SSL3_ST_SR_CLNT_HELLO_A)
 		{
 		s->first_packet=1;
@@ -593,11 +590,9 @@
 	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;
-		}
+	/* The version number has already been checked in ssl3_get_message.
+	 * I a native TLSv1/SSLv3 method, the match must be correct except
+	 * perhaps for the first message */
 	p+=2;
 
 	/* load the client random */
@@ -615,7 +610,7 @@
 		}
 	else
 		{
-		i=ssl_get_prev_session(s,j,p);
+		i=ssl_get_prev_session(s,p,j);
 		if (i == 1)
 			{ /* previous session */
 			s->hit=1;
@@ -632,14 +627,14 @@
 	if ((i == 0) && (j != 0))
 		{
 		/* we need a cipher if we are not resuming a session */
-		al=SSL3_AD_ILLEGAL_PARAMETER;
+		al=SSL_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;
+		al=SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_LENGTH_MISMATCH);
 		goto f_err;
 		}
@@ -667,7 +662,7 @@
 			}
 		if (j == 0)
 			{
-			if ((s->ctx->options & SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) && (sk_num(ciphers) == 1))
+			if ((s->options & SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) && (sk_num(ciphers) == 1))
 				{
 				/* Very bad for multi-threading.... */
 				s->session->cipher=
@@ -677,7 +672,7 @@
 				{
 				/* we need to have the cipher in the cipher
 				 * list if we are asked to reuse it */
-				al=SSL3_AD_ILLEGAL_PARAMETER;
+				al=SSL_AD_ILLEGAL_PARAMETER;
 				SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_REQUIRED_CIPHER_MISSING);
 				goto f_err;
 				}
@@ -693,18 +688,22 @@
 	if (j >= i)
 		{
 		/* no compress */
-		al=SSL3_AD_ILLEGAL_PARAMETER;
+		al=SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_COMPRESSION_SPECIFIED);
 		goto f_err;
 		}
 
-	if (p > (d+n))
+	/* TLS does not mind if there is extra stuff */
+	if (s->version == SSL3_VERSION)
 		{
-		/* 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;
+		if (p > (d+n))
+			{
+			/* wrong number of bytes,
+			 * there could be more to follow */
+			al=SSL_AD_DECODE_ERROR;
+			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_LENGTH_MISMATCH);
+			goto f_err;
+			}
 		}
 
 	/* do nothing with compression */
@@ -719,7 +718,7 @@
 		s->session->ciphers=ciphers;
 		if (ciphers == NULL)
 			{
-			al=SSL3_AD_HANDSHAKE_FAILURE;
+			al=SSL_AD_ILLEGAL_PARAMETER;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_CIPHERS_PASSED);
 			goto f_err;
 			}
@@ -729,7 +728,7 @@
 
 		if (c == NULL)
 			{
-			al=SSL3_AD_HANDSHAKE_FAILURE;
+			al=SSL_AD_HANDSHAKE_FAILURE;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
 			goto f_err;
 			}
@@ -743,7 +742,7 @@
 		SSL_CIPHER *nc=NULL;
 		SSL_CIPHER *ec=NULL;
 
-		if (s->ctx->options & SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG)
+		if (s->options & SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG)
 			{
 			sk=s->session->ciphers;
 			for (i=0; i<sk_num(sk); i++)
@@ -806,8 +805,8 @@
 		/* Do the message type and length last */
 		d=p= &(buf[4]);
 
-		*(p++)=SSL3_VERSION_MAJOR;
-		*(p++)=SSL3_VERSION_MINOR;
+		*(p++)=s->version>>8;
+		*(p++)=s->version&0xff;
 
 		/* Random stuff */
 		memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE);
@@ -819,7 +818,10 @@
 		 * back the new session-id or we send back a 0 length
 		 * session-id if we want it to be single use.
 		 * Currently I will not implement the '0' length session-id
+		 * 12-Jan-98 - I'll now support the '0' length stuff.
 		 */
+		if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER))
+			s->session->session_id_length=0;
 
 		sl=s->session->session_id_length;
 		*(p++)=sl;
@@ -920,7 +922,7 @@
 				}
 			if (rsa == NULL)
 				{
-				al=SSL3_AD_HANDSHAKE_FAILURE;
+				al=SSL_AD_HANDSHAKE_FAILURE;
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_RSA_KEY);
 				goto f_err;
 				}
@@ -940,7 +942,7 @@
 					SSL_NOT_EXP)?0:1);
 			if (dhp == NULL)
 				{
-				al=SSL3_AD_HANDSHAKE_FAILURE;
+				al=SSL_AD_HANDSHAKE_FAILURE;
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_DH_KEY);
 				goto f_err;
 				}
@@ -953,7 +955,7 @@
 			s->s3->tmp.dh=dh;
 			if (((dhp->pub_key == NULL) ||
 			     (dhp->priv_key == NULL) ||
-			     (s->ctx->options & SSL_OP_SINGLE_DH_USE)) &&
+			     (s->options & SSL_OP_SINGLE_DH_USE)) &&
 			    (!DH_generate_key(dh)))
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_DH_LIB);
@@ -977,7 +979,7 @@
 		else 
 #endif
 			{
-			al=SSL3_AD_HANDSHAKE_FAILURE;
+			al=SSL_AD_HANDSHAKE_FAILURE;
 			SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
 			goto f_err;
 			}
@@ -992,7 +994,7 @@
 			if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher))
 				== NULL)
 				{
-				al=SSL3_AD_HANDSHAKE_FAILURE;
+				al=SSL_AD_DECODE_ERROR;
 				goto f_err;
 				}
 			kn=EVP_PKEY_size(pkey);
@@ -1030,7 +1032,8 @@
 				j=0;
 				for (num=2; num > 0; num--)
 					{
-					EVP_DigestInit(&md_ctx,(num == 2)?EVP_md5():EVP_sha1());
+					EVP_DigestInit(&md_ctx,(num == 2)
+						?s->ctx->md5:s->ctx->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);
@@ -1072,7 +1075,7 @@
 #endif
 				{
 				/* Is this error check actually needed? */
-				al=SSL3_AD_HANDSHAKE_FAILURE;
+				al=SSL_AD_HANDSHAKE_FAILURE;
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_PKEY_TYPE);
 				goto f_err;
 				}
@@ -1135,7 +1138,7 @@
 					goto err;
 					}
 				p=(unsigned char *)&(buf->data[4+n]);
-				if (!(s->ctx->options & SSL_OP_NETSCAPE_CA_DN_BUG))
+				if (!(s->options & SSL_OP_NETSCAPE_CA_DN_BUG))
 					{
 					s2n(j,p);
 					i2d_X509_NAME(name,&p);
@@ -1181,9 +1184,11 @@
 	unsigned long l;
 	unsigned char *p;
 	RSA *rsa=NULL;
-	BIGNUM *pub=NULL;
 	EVP_PKEY *pkey=NULL;
+#ifndef NO_DH
+	BIGNUM *pub=NULL;
 	DH *dh_srvr;
+#endif
 
 	n=ssl3_get_message(s,
 		SSL3_ST_SR_KEY_EXCH_A,
@@ -1213,7 +1218,7 @@
 			 * be sent already */
 			if (rsa == NULL)
 				{
-				al=SSL3_AD_HANDSHAKE_FAILURE;
+				al=SSL_AD_HANDSHAKE_FAILURE;
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_TMP_RSA_PKEY);
 				goto f_err;
 
@@ -1226,22 +1231,41 @@
 				(pkey->type != EVP_PKEY_RSA) ||
 				(pkey->pkey.rsa == NULL))
 				{
-				al=SSL3_AD_HANDSHAKE_FAILURE;
+				al=SSL_AD_HANDSHAKE_FAILURE;
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_RSA_CERTIFICATE);
 				goto f_err;
 				}
 			rsa=pkey->pkey.rsa;
 			}
 
+		/* TLS */
+		if (s->version > SSL3_VERSION)
+			{
+			n2s(p,i);
+			if (n != i+2)
+				{
+				if (!(s->options & SSL_OP_TLS_D5_BUG))
+					{
+					SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG);
+					goto err;
+					}
+				else
+					p-=2;
+				}
+			else
+				n=i;
+			}
+
 		i=RSA_private_decrypt((int)n,p,p,rsa,RSA_PKCS1_PADDING);
+
 #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] != (s->version>>8)) ||
+			 (p[1] != (s->version & 0xff))))
 			{
-			p[0]=3;
-			p[1]=0;
+			p[0]=(s->version>>8);
+			p[1]=(s->version & 0xff);
 			RAND_bytes(&(p[2]),SSL_MAX_MASTER_KEY_LENGTH-2);
 			i=SSL_MAX_MASTER_KEY_LENGTH;
 			}
@@ -1262,7 +1286,7 @@
 #endif
 
 		s->session->master_key_length=
-			ssl3_generate_master_secret(s,
+			s->method->ssl3_enc->generate_master_secret(s,
 				s->session->master_key,
 				p,i);
 		memset(p,0,i);
@@ -1272,11 +1296,10 @@
 #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))
+			if (!(s->options & SSL_OP_SSLEAY_080_CLIENT_DH_BUG))
 				{
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG);
 				goto err;
@@ -1290,7 +1313,7 @@
 
 		if (n == 0L) /* the parameters are in the cert */
 			{
-			al=SSL3_AD_HANDSHAKE_FAILURE;
+			al=SSL_AD_HANDSHAKE_FAILURE;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_UNABLE_TO_DECODE_DH_CERTS);
 			goto f_err;
 			}
@@ -1298,7 +1321,7 @@
 			{
 			if (s->s3->tmp.dh == NULL)
 				{
-				al=SSL3_AD_HANDSHAKE_FAILURE;
+				al=SSL_AD_HANDSHAKE_FAILURE;
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_TMP_DH_KEY);
 				goto f_err;
 				}
@@ -1312,6 +1335,7 @@
 			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)
@@ -1326,13 +1350,13 @@
 		BN_clear_free(pub);
 		pub=NULL;
 		s->session->master_key_length=
-			ssl3_generate_master_secret(s,
+			s->method->ssl3_enc->generate_master_secret(s,
 				s->session->master_key,p,i);
 		}
 	else
 #endif
 		{
-		al=SSL3_AD_HANDSHAKE_FAILURE;
+		al=SSL_AD_HANDSHAKE_FAILURE;
 		SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_UNKNOWN_CIPHER_TYPE);
 		goto f_err;
 		}
@@ -1340,7 +1364,9 @@
 	return(1);
 f_err:
 	ssl3_send_alert(s,SSL3_AL_FATAL,al);
+#if !defined(NO_DH) || !defined(NO_RSA)
 err:
+#endif
 	return(-1);
 	}
 
@@ -1380,8 +1406,8 @@
 		s->s3->tmp.reuse_message=1;
 		if ((peer != NULL) && (type | EVP_PKT_SIGN))
 			{
+			al=SSL_AD_UNEXPECTED_MESSAGE;
 			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_MISSING_VERIFY_MESSAGE);
-			al=SSL3_AD_UNEXPECTED_MESSAGE;
 			goto f_err;
 			}
 		ret=1;
@@ -1391,21 +1417,21 @@
 	if (peer == NULL)
 		{
 		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_NO_CLIENT_CERT_RECEIVED);
-		al=SSL3_AD_UNEXPECTED_MESSAGE;
+		al=SSL_AD_UNEXPECTED_MESSAGE;
 		goto f_err;
 		}
 
 	if (!(type & EVP_PKT_SIGN))
 		{
 		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE);
-		al=SSL3_AD_ILLEGAL_PARAMETER;
+		al=SSL_AD_ILLEGAL_PARAMETER;
 		goto f_err;
 		}
 
 	if (s->s3->change_cipher_spec)
 		{
 		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_CCS_RECEIVED_EARLY);
-		al=SSL3_AD_UNEXPECTED_MESSAGE;
+		al=SSL_AD_UNEXPECTED_MESSAGE;
 		goto f_err;
 		}
 
@@ -1416,7 +1442,7 @@
 	if (i > n)
 		{
 		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_LENGTH_MISMATCH);
-		al=SSL3_AD_ILLEGAL_PARAMETER;
+		al=SSL_AD_DECODE_ERROR;
 		goto f_err;
 		}
 
@@ -1424,7 +1450,7 @@
 	if ((i > j) || (n > j) || (n <= 0))
 		{
 		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_WRONG_SIGNATURE_SIZE);
-		al=SSL3_AD_ILLEGAL_PARAMETER;
+		al=SSL_AD_DECODE_ERROR;
 		goto f_err;
 		}
 
@@ -1434,17 +1460,15 @@
 		i=RSA_public_decrypt(i,p,p,pkey->pkey.rsa,RSA_PKCS1_PADDING);
 		if (i < 0)
 			{
-			al=SSL3_AD_ILLEGAL_PARAMETER;
+			al=SSL_AD_DECRYPT_ERROR;
 			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))
+			memcmp(&(s->s3->tmp.finish_md[0]),p,
+				MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH))
 			{
-			al=SSL3_AD_ILLEGAL_PARAMETER;
+			al=SSL_AD_DECRYPT_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_RSA_SIGNATURE);
 			goto f_err;
 			}
@@ -1454,12 +1478,13 @@
 #ifndef NO_DSA
 		if (pkey->type == EVP_PKEY_DSA)
 		{
-		j=DSA_verify(pkey->save_type,s->s3->tmp.finish_md2,
+		j=DSA_verify(pkey->save_type,
+			&(s->s3->tmp.finish_md[MD5_DIGEST_LENGTH]),
 			SHA_DIGEST_LENGTH,p,i,pkey->pkey.dsa);
 		if (j <= 0)
 			{
 			/* bad signature */
-			al=SSL3_AD_ILLEGAL_PARAMETER;
+			al=SSL_AD_DECRYPT_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_DSA_SIGNATURE);
 			goto f_err;
 			}
@@ -1468,7 +1493,7 @@
 #endif
 		{
 		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_INTERNAL_ERROR);
-		al=SSL3_AD_UNSUPPORTED_CERTIFICATE;
+		al=SSL_AD_UNSUPPORTED_CERTIFICATE;
 		goto f_err;
 		}
 
@@ -1511,7 +1536,14 @@
 			(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;
+			al=SSL_AD_HANDSHAKE_FAILURE;
+			goto f_err;
+			}
+		/* If tls asked for a client cert we must return a 0 list */
+		if ((s->version > SSL3_VERSION) && s->s3->tmp.cert_request)
+			{
+			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST);
+			al=SSL_AD_UNEXPECTED_MESSAGE;
 			goto f_err;
 			}
 		s->s3->tmp.reuse_message=1;
@@ -1520,7 +1552,7 @@
 
 	if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE)
 		{
-		al=SSL3_AD_UNEXPECTED_MESSAGE;
+		al=SSL_AD_UNEXPECTED_MESSAGE;
 		SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_WRONG_MESSAGE_TYPE);
 		goto f_err;
 		}
@@ -1535,7 +1567,7 @@
 	n2l3(p,llen);
 	if (llen+3 != n)
 		{
-		al=SSL3_AD_ILLEGAL_PARAMETER;
+		al=SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_LENGTH_MISMATCH);
 		goto f_err;
 		}
@@ -1544,7 +1576,7 @@
 		n2l3(p,l);
 		if ((l+nc+3) > llen)
 			{
-			al=SSL3_AD_ILLEGAL_PARAMETER;
+			al=SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH);
 			goto f_err;
 			}
@@ -1558,7 +1590,7 @@
 			}
 		if (p != (q+l))
 			{
-			al=SSL3_AD_ILLEGAL_PARAMETER;
+			al=SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH);
 			goto f_err;
 			}
@@ -1573,22 +1605,36 @@
 
 	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;
+		/* TLS does not mind 0 certs returned */
+		if (s->version == SSL3_VERSION)
+			{
+			al=SSL_AD_HANDSHAKE_FAILURE;
+			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_NO_CERTIFICATES_RETURNED);
+			goto f_err;
+			}
+		/* Fail for TLS only if we required a certificate */
+		else if ((s->verify_mode & SSL_VERIFY_PEER) &&
+			 (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT))
+			{
+			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
+			al=SSL_AD_HANDSHAKE_FAILURE;
+			goto f_err;
+			}
 		}
-	i=ssl_verify_cert_chain(s,sk);
-	if (!i)
+	else
 		{
-		al=ssl_verify_alarm_type(s->verify_result);
-		SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_NO_CERTIFICATE_RETURNED);
-		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;
diff --git a/ssl/ssl.c b/ssl/ssl.c
index fcc29b0..1f769a1 100644
--- a/ssl/ssl.c
+++ b/ssl/ssl.c
@@ -1,5 +1,5 @@
 /* ssl/ssl.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
diff --git a/ssl/ssl.err b/ssl/ssl.err
index f3bc5d3..c54326c 100644
--- a/ssl/ssl.err
+++ b/ssl/ssl.err
@@ -82,29 +82,34 @@
 #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
+#define SSL_F_SSL_INIT_WBIO_BUFFER			 181
+#define SSL_F_SSL_LOAD_CLIENT_CA_FILE			 182
+#define SSL_F_SSL_NEW					 183
+#define SSL_F_SSL_RSA_PRIVATE_DECRYPT			 184
+#define SSL_F_SSL_RSA_PUBLIC_ENCRYPT			 185
+#define SSL_F_SSL_SESSION_NEW				 186
+#define SSL_F_SSL_SESSION_PRINT_FP			 187
+#define SSL_F_SSL_SET_CERT				 188
+#define SSL_F_SSL_SET_FD				 189
+#define SSL_F_SSL_SET_PKEY				 190
+#define SSL_F_SSL_SET_RFD				 191
+#define SSL_F_SSL_SET_SESSION				 192
+#define SSL_F_SSL_SET_WFD				 193
+#define SSL_F_SSL_UNDEFINED_FUNCTION			 194
+#define SSL_F_SSL_USE_CERTIFICATE			 195
+#define SSL_F_SSL_USE_CERTIFICATE_ASN1			 196
+#define SSL_F_SSL_USE_CERTIFICATE_FILE			 197
+#define SSL_F_SSL_USE_PRIVATEKEY			 198
+#define SSL_F_SSL_USE_PRIVATEKEY_ASN1			 199
+#define SSL_F_SSL_USE_PRIVATEKEY_FILE			 200
+#define SSL_F_SSL_USE_RSAPRIVATEKEY			 201
+#define SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1		 202
+#define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE		 203
+#define SSL_F_SSL_WRITE					 204
+#define SSL_F_TLS1_CHANGE_CIPHER_STATE			 205
+#define SSL_F_TLS1_ENC					 206
+#define SSL_F_TLS1_SETUP_KEY_BLOCK			 207
+#define SSL_F_WRITE_PENDING				 208
 
 /* Reason codes. */
 #define SSL_R_APP_DATA_IN_HANDSHAKE			 100
@@ -123,103 +128,109 @@
 #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_BAD_PROTOCOL_VERSION_NUMBER		 116
+#define SSL_R_BAD_RESPONSE_ARGUMENT			 117
+#define SSL_R_BAD_RSA_DECRYPT				 118
+#define SSL_R_BAD_RSA_ENCRYPT				 119
+#define SSL_R_BAD_RSA_E_LENGTH				 120
+#define SSL_R_BAD_RSA_MODULUS_LENGTH			 121
+#define SSL_R_BAD_RSA_SIGNATURE				 122
+#define SSL_R_BAD_SIGNATURE				 123
+#define SSL_R_BAD_SSL_FILETYPE				 124
+#define SSL_R_BAD_SSL_SESSION_ID_LENGTH			 125
+#define SSL_R_BAD_STATE					 126
+#define SSL_R_BAD_WRITE_RETRY				 127
+#define SSL_R_BIO_NOT_SET				 128
+#define SSL_R_BLOCK_CIPHER_PAD_IS_WRONG			 129
+#define SSL_R_BN_LIB					 130
+#define SSL_R_CA_DN_LENGTH_MISMATCH			 131
+#define SSL_R_CA_DN_TOO_LONG				 132
+#define SSL_R_CCS_RECEIVED_EARLY			 133
+#define SSL_R_CERTIFICATE_VERIFY_FAILED			 134
+#define SSL_R_CERT_LENGTH_MISMATCH			 135
+#define SSL_R_CHALLENGE_IS_DIFFERENT			 136
+#define SSL_R_CIPHER_CODE_WRONG_LENGTH			 137
+#define SSL_R_CIPHER_OR_HASH_UNAVAILABLE		 138
+#define SSL_R_CIPHER_TABLE_SRC_ERROR			 139
+#define SSL_R_COMPRESSED_LENGTH_TOO_LONG		 140
+#define SSL_R_COMPRESSION_FAILURE			 141
+#define SSL_R_CONNECTION_ID_IS_DIFFERENT		 142
+#define SSL_R_CONNECTION_TYPE_NOT_SET			 143
+#define SSL_R_DATA_BETWEEN_CCS_AND_FINISHED		 144
+#define SSL_R_DATA_LENGTH_TOO_LONG			 145
+#define SSL_R_DECRYPTION_FAILED				 146
+#define SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG		 147
+#define SSL_R_DIGEST_CHECK_FAILED			 148
+#define SSL_R_ENCRYPTED_LENGTH_TOO_LONG			 149
+#define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST		 150
+#define SSL_R_EXCESSIVE_MESSAGE_SIZE			 151
+#define SSL_R_EXTRA_DATA_IN_MESSAGE			 152
+#define SSL_R_GOT_A_FIN_BEFORE_A_CCS			 153
+#define SSL_R_HTTPS_PROXY_REQUEST			 154
+#define SSL_R_HTTP_REQUEST				 155
+#define SSL_R_INTERNAL_ERROR				 156
+#define SSL_R_INVALID_CHALLENGE_LENGTH			 157
+#define SSL_R_LENGTH_MISMATCH				 158
+#define SSL_R_LENGTH_TOO_SHORT				 159
+#define SSL_R_LIBRARY_HAS_NO_CIPHERS			 160
+#define SSL_R_MISSING_DH_DSA_CERT			 161
+#define SSL_R_MISSING_DH_KEY				 162
+#define SSL_R_MISSING_DH_RSA_CERT			 163
+#define SSL_R_MISSING_DSA_SIGNING_CERT			 164
+#define SSL_R_MISSING_EXPORT_TMP_DH_KEY			 165
+#define SSL_R_MISSING_EXPORT_TMP_RSA_KEY		 166
+#define SSL_R_MISSING_RSA_CERTIFICATE			 167
+#define SSL_R_MISSING_RSA_ENCRYPTING_CERT		 168
+#define SSL_R_MISSING_RSA_SIGNING_CERT			 169
+#define SSL_R_MISSING_TMP_DH_KEY			 170
+#define SSL_R_MISSING_TMP_RSA_KEY			 171
+#define SSL_R_MISSING_TMP_RSA_PKEY			 172
+#define SSL_R_MISSING_VERIFY_MESSAGE			 173
+#define SSL_R_NON_SSLV2_INITIAL_PACKET			 174
+#define SSL_R_NO_CERTIFICATES_RETURNED			 175
+#define SSL_R_NO_CERTIFICATE_ASSIGNED			 176
+#define SSL_R_NO_CERTIFICATE_RETURNED			 177
+#define SSL_R_NO_CERTIFICATE_SET			 178
+#define SSL_R_NO_CERTIFICATE_SPECIFIED			 179
+#define SSL_R_NO_CIPHERS_AVAILABLE			 180
+#define SSL_R_NO_CIPHERS_PASSED				 181
+#define SSL_R_NO_CIPHERS_SPECIFIED			 182
+#define SSL_R_NO_CIPHER_LIST				 183
+#define SSL_R_NO_CIPHER_MATCH				 184
+#define SSL_R_NO_CLIENT_CERT_RECEIVED			 185
+#define SSL_R_NO_COMPRESSION_SPECIFIED			 186
+#define SSL_R_NO_PRIVATEKEY				 187
+#define SSL_R_NO_PRIVATE_KEY_ASSIGNED			 188
+#define SSL_R_NO_PROTOCOLS_AVAILABLE			 189
+#define SSL_R_NO_PUBLICKEY				 190
+#define SSL_R_NO_SHARED_CIPHER				 191
+#define SSL_R_NULL_SSL_CTX				 192
+#define SSL_R_NULL_SSL_METHOD_PASSED			 193
+#define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED		 194
+#define SSL_R_PACKET_LENGTH_TOO_LONG			 195
+#define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE		 196
+#define SSL_R_PEER_ERROR				 197
+#define SSL_R_PEER_ERROR_CERTIFICATE			 198
+#define SSL_R_PEER_ERROR_NO_CERTIFICATE			 199
+#define SSL_R_PEER_ERROR_NO_CIPHER			 200
+#define SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE	 201
+#define SSL_R_PRE_MAC_LENGTH_TOO_LONG			 202
+#define SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS		 203
+#define SSL_R_PROTOCOL_IS_SHUTDOWN			 204
+#define SSL_R_PUBLIC_KEY_ENCRYPT_ERROR			 205
+#define SSL_R_PUBLIC_KEY_IS_NOT_RSA			 206
+#define SSL_R_PUBLIC_KEY_NOT_RSA			 207
+#define SSL_R_READ_BIO_NOT_SET				 208
+#define SSL_R_READ_WRONG_PACKET_TYPE			 209
+#define SSL_R_RECORD_LENGTH_MISMATCH			 210
+#define SSL_R_RECORD_TOO_LARGE				 211
+#define SSL_R_REQUIRED_CIPHER_MISSING			 212
+#define SSL_R_REUSE_CERT_LENGTH_NOT_ZERO		 213
+#define SSL_R_REUSE_CERT_TYPE_NOT_ZERO			 214
+#define SSL_R_REUSE_CIPHER_LIST_NOT_ZERO		 215
+#define SSL_R_SHORT_READ				 216
+#define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE	 217
+#define SSL_R_SSL3_SESSION_ID_TOO_SHORT			 218
 #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
@@ -229,44 +240,51 @@
 #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_PEER_ERROR_CERTIFICATE	 219
+#define SSL_R_SSLV3_ALERT_PEER_ERROR_NO_CERTIFICATE	 220
+#define SSL_R_SSLV3_ALERT_PEER_ERROR_NO_CIPHER		 221
+#define SSL_R_SSLV3_ALERT_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE 222
 #define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE		 1010
-#define SSL_R_SSLV3_ALERT_UNKNOWN_REMOTE_ERROR_TYPE	 217
+#define SSL_R_SSLV3_ALERT_UNKNOWN_REMOTE_ERROR_TYPE	 223
 #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
+#define SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION	 224
+#define SSL_R_SSL_HANDSHAKE_FAILURE			 225
+#define SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS		 226
+#define SSL_R_SSL_SESSION_ID_IS_DIFFERENT		 227
+#define SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER	 228
+#define SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST 229
+#define SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG	 230
+#define SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER		 231
+#define SSL_R_UNABLE_TO_DECODE_DH_CERTS			 232
+#define SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY		 233
+#define SSL_R_UNABLE_TO_FIND_DH_PARAMETERS		 234
+#define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS	 235
+#define SSL_R_UNABLE_TO_FIND_SSL_METHOD			 236
+#define SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES		 237
+#define SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES		 238
+#define SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES		 239
+#define SSL_R_UNEXPECTED_MESSAGE			 240
+#define SSL_R_UNEXPECTED_RECORD				 241
+#define SSL_R_UNKNOWN_ALERT_TYPE			 242
+#define SSL_R_UNKNOWN_CERTIFICATE_TYPE			 243
+#define SSL_R_UNKNOWN_CIPHER_RETURNED			 244
+#define SSL_R_UNKNOWN_CIPHER_TYPE			 245
+#define SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE			 246
+#define SSL_R_UNKNOWN_PKEY_TYPE				 247
+#define SSL_R_UNKNOWN_PROTOCOL				 248
+#define SSL_R_UNKNOWN_REMOTE_ERROR_TYPE			 249
+#define SSL_R_UNKNOWN_SSL_VERSION			 250
+#define SSL_R_UNKNOWN_STATE				 251
+#define SSL_R_UNSUPPORTED_CIPHER			 252
+#define SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM		 253
+#define SSL_R_UNSUPPORTED_PROTOCOL			 254
+#define SSL_R_UNSUPPORTED_SSL_VERSION			 255
+#define SSL_R_WRITE_BIO_NOT_SET				 256
+#define SSL_R_WRONG_CIPHER_RETURNED			 257
+#define SSL_R_WRONG_MESSAGE_TYPE			 258
+#define SSL_R_WRONG_NUMBER_OF_KEY_BITS			 259
+#define SSL_R_WRONG_SIGNATURE_LENGTH			 260
+#define SSL_R_WRONG_SIGNATURE_SIZE			 261
+#define SSL_R_WRONG_SSL_VERSION				 262
+#define SSL_R_WRONG_VERSION_NUMBER			 263
+#define SSL_R_X509_LIB					 264
diff --git a/ssl/ssl.h b/ssl/ssl.h
index 594295d..cf8f965 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -1,5 +1,5 @@
 /* ssl/ssl.h */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -118,7 +118,6 @@
 #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"
@@ -130,22 +129,18 @@
 /* '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"
+#define SSL_DEFAULT_CIPHER_LIST	"ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP"
 #else
 #define SSL_ALLOW_ADH
 #define SSL_DEFAULT_CIPHER_LIST	"HIGH:MEDIUM:LOW:ADH+3DES:ADH+RC4:ADH+DES:+EXP"
 #endif
 
+/* Used in SSL_set_shutdown()/SSL_get_shutdown(); */
 #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 "crypto.h"
+#include "lhash.h"
 #include "buffer.h"
 #include "bio.h"
 #include "x509.h"
@@ -153,6 +148,9 @@
 #define SSL_FILETYPE_ASN1	X509_FILETYPE_ASN1
 #define SSL_FILETYPE_PEM	X509_FILETYPE_PEM
 
+/* This is needed to stop compilers complaining about the
+ * 'struct ssl_st *' function parameters used to prototype callbacks
+ * in SSL_CTX. */
 typedef struct ssl_st *ssl_crock_st;
 
 /* used to hold info on the particular ciphers used */
@@ -166,7 +164,7 @@
 	unsigned long mask;		/* used for matching */
 	} SSL_CIPHER;
 
-/* Used to hold functions for SSLv2 or SSLv3 functions */
+/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
 typedef struct ssl_method_st
 	{
 	int version;
@@ -189,6 +187,7 @@
 	SSL_CIPHER *(*get_cipher)();
 	struct ssl_method_st *(*get_ssl_method)();
 	long (*get_timeout)();
+	struct ssl3_enc_method *ssl3_enc; /* Extra SSLv3/TLS stuff */
 	} SSL_METHOD;
 
 typedef struct ssl_compression_st
@@ -248,28 +247,39 @@
 
 	STACK /* SSL_CIPHER */ *ciphers; /* shared ciphers? */
 
-	char *app_data; /* application specific data */
+	CRYPTO_EX_DATA ex_data; /* application specific data */
+
+	/* These are used to make removal of session-ids more
+	 * efficient and to implement a maximum cache size. */
+	struct ssl_session_st *prev,*next;
 	} 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
+#define SSL_OP_TLS_D5_BUG				0x00000100L
+#define	SSL_OP_TLS_BLOCK_PADDING_BUG			0x00000200L
 
 /* 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_NETSCAPE_CA_DN_BUG			0x20000000L
 #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))
+#define SSL_set_options(ssl,op)		((ssl)->options|=(op))
+
+#define SSL_OP_NO_SSLv2					0x01000000L
+#define SSL_OP_NO_SSLv3					0x02000000L
+#define SSL_OP_NO_TLSv1					0x04000000L
 
 /* Normally you will only use these if your application wants to use
  * the certificate store in other places, perhaps PKCS7 */
@@ -278,6 +288,8 @@
                 (X509_STORE_free((ctx)->cert_store),(ctx)->cert_store=(cs))
 
 
+#define SSL_SESSION_CACHE_MAX_SIZE_DEFAULT	(1024*20)
+
 typedef struct ssl_ctx_st
 	{
 	SSL_METHOD *method;
@@ -289,6 +301,11 @@
 
 	struct x509_store_st /* X509_STORE */ *cert_store;
 	struct lhash_st /* LHASH */ *sessions;	/* a set of SSL_SESSION's */
+	/* Most session-ids that will be cached, default is
+	 * SSL_SESSION_CACHE_SIZE_DEFAULT. 0 is unlimited. */
+	unsigned long session_cache_size;
+	struct ssl_session_st *session_cache_head;
+	struct ssl_session_st *session_cache_tail;
 
 	/* This can have one of 2 values, ored together,
 	 * SSL_SESS_CACHE_CLIENT,
@@ -322,12 +339,15 @@
 	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_connect;	/* SSL new connection - started */
+	int sess_connect_renegotiate;/* SSL renegotiatene  - requested */
+	int sess_connect_good;	/* SSL new connection/renegotiate - finished */
+	int sess_accept;	/* SSL new accept - started */
+	int sess_accept_renegotiate;/* SSL renegotiatene - requested */
+	int sess_accept_good;	/* SSL accept/renegotiate - finished */
 	int sess_miss;		/* session lookup misses  */
 	int sess_timeout;	/* session reuse attempt on timeouted session */
+	int sess_cache_full;	/* session removed due to full cache */
 	int sess_hit;		/* session reuse actually done */
 	int sess_cb_hit;	/* session-id that was not in the cache was
 				 * passed back via the callback.  This
@@ -360,16 +380,22 @@
 
 	int quiet_shutdown;
 
-	char *app_data;
+	CRYPTO_EX_DATA ex_data;
+
+	EVP_MD *rsa_md5;/* For SSLv2 - name is 'ssl2-md5' */
+	EVP_MD *md5;	/* For SSLv3/TLSv1 'ssl3-md5' */
+	EVP_MD *sha1;   /* For SSLv3/TLSv1 'ssl3->sha1' */
 	} SSL_CTX;
 
-#define SSL_SESS_CACHE_OFF	0x00
-#define SSL_SESS_CACHE_CLIENT	0x01
-#define SSL_SESS_CACHE_SERVER	0x02
+#define SSL_SESS_CACHE_OFF			0x0000
+#define SSL_SESS_CACHE_CLIENT			0x0001
+#define SSL_SESS_CACHE_SERVER			0x0002
 #define SSL_SESS_CACHE_BOTH	(SSL_SESS_CACHE_CLIENT|SSL_SESS_CACHE_SERVER)
-#define SSL_SESS_CACHE_NO_AUTO_CLEAR	0x80
-
-#define SSL_session_reused(s)	((s)->hit)
+#define SSL_SESS_CACHE_NO_AUTO_CLEAR		0x0080
+/* This one, when set, makes the server session-id lookup not look
+ * in the cache.  If there is an application get_session callback
+ * defined, this will still get called. */
+#define SSL_SESS_CACHE_NO_INTERNAL_LOOKUP	0x0100
 
 #define SSL_CTX_sessions(ctx)		((ctx)->sessions)
 /* You will need to include lhash.h to access the following #define */
@@ -377,11 +403,17 @@
 #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_renegotiate(ctx)	((ctx)->sess_accept_renegotiate)
+#define SSL_CTX_sess_connect_renegotiate(ctx)	((ctx)->sess_connect_renegotiate)
 #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_cache_full(ctx)	((ctx)->sess_cache_full)
+
+#define SSL_CTX_sess_set_cache_size(ctx,t) ((ctx)->session_cache_size=(t))
+#define SSL_CTX_sess_get_cache_size(ctx)   ((ctx)->session_cache_size)
 
 #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)
@@ -510,30 +542,29 @@
 	int debug;	
 
 	/* extra application data */
-	int verify_result;
-	char *app_data;
+	long verify_result;
+	CRYPTO_EX_DATA ex_data;
 
 	/* for server side, keep the list of CA_dn we can use */
 	STACK /* X509_NAME */ *client_CA;
 
+	int references;
+	unsigned long options;
 	int first_packet;
 	} SSL;
 
 #include "ssl2.h"
 #include "ssl3.h"
+#include "tls1.h" /* This is mostly sslv3 with a few tweaks */
 #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)
+/* compatablity */
+#define SSL_set_app_data(s,arg)		(SSL_set_ex_data(s,0,(char *)arg))
+#define SSL_get_app_data(s)		(SSL_get_ex_data(s,0))
+#define SSL_SESSION_set_app_data(s,a)	(SSL_SESSION_set_ex_data(s,0,(char *)a))
+#define SSL_SESSION_get_app_data(s)	(SSL_SESSION_get_ex_data(s,0))
+#define SSL_CTX_get_app_data(ctx)	(SSL_CTX_get_ex_data(ctx,0))
+#define SSL_CTX_set_app_data(ctx,arg)	(SSL_CTX_set_ex_data(ctx,0,(char *)arg))
 
 /* The following are the possible values for ssl->state are are
  * used to indicate where we are upto in the SSL connection establishment.
@@ -542,7 +573,6 @@
  * 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
@@ -551,10 +581,6 @@
 #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
@@ -570,11 +596,12 @@
 #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)
+#define SSL_get_state(a)		SSL_state(a)
+#define SSL_is_init_finished(a)		(SSL_state(a) == SSL_ST_OK)
+#define SSL_in_init(a)			(SSL_state(a)&SSL_ST_INIT)
+#define SSL_in_before(a)		(SSL_state(a)&SSL_ST_BEFORE)
+#define SSL_in_connect_init(a)		(SSL_state(a)&SSL_ST_CONNECT)
+#define SSL_in_accept_init(a)		(SSL_state(a)&SSL_ST_ACCEPT)
 
 /* The following 2 states are kept in ssl->rstate when reads fail,
  * you should not need these */
@@ -589,20 +616,6 @@
 #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)
@@ -620,6 +633,10 @@
 		SSL_CIPHER_get_version(SSL_get_current_cipher(s))
 #define SSL_get_cipher_name(s) \
 		SSL_CIPHER_get_name(SSL_get_current_cipher(s))
+#define SSL_get_time(a)		SSL_SESSION_get_time(a)
+#define SSL_set_time(a,b)	SSL_SESSION_set_time((a),(b))
+#define SSL_get_timeout(a)	SSL_SESSION_get_timeout(a)
+#define SSL_set_timeout(a,b)	SSL_SESSION_set_timeout((a),(b))
 
 /* VMS linker has a 31 char name limit */
 #define SSL_CTX_set_cert_verify_callback(a,b,c) \
@@ -643,6 +660,32 @@
 		PEM_STRING_SSL_SESSION,bp, (char *)x, NULL,NULL,0,NULL)
 #endif
 
+/* These alert types are for SSLv3 and TLSv1 */
+#define SSL_AD_CLOSE_NOTIFY		SSL3_AD_CLOSE_NOTIFY
+#define SSL_AD_UNEXPECTED_MESSAGE	SSL3_AD_UNEXPECTED_MESSAGE /* fatal */
+#define SSL_AD_BAD_RECORD_MAC		SSL3_AD_BAD_RECORD_MAC     /* fatal */
+#define SSL_AD_DECRYPTION_FAILED	TLS1_AD_DECRYPTION_FAILED
+#define SSL_AD_RECORD_OVERFLOW		TLS1_AD_RECORD_OVERFLOW
+#define SSL_AD_DECOMPRESSION_FAILURE	SSL3_AD_DECOMPRESSION_FAILURE/* fatal */
+#define SSL_AD_HANDSHAKE_FAILURE	SSL3_AD_HANDSHAKE_FAILURE/* fatal */
+#define SSL_AD_NO_CERTIFICATE		SSL3_AD_NO_CERTIFICATE /* Not for TLS */
+#define SSL_AD_BAD_CERTIFICATE		SSL3_AD_BAD_CERTIFICATE
+#define SSL_AD_UNSUPPORTED_CERTIFICATE	SSL3_AD_UNSUPPORTED_CERTIFICATE
+#define SSL_AD_CERTIFICATE_REVOKED	SSL3_AD_CERTIFICATE_REVOKED
+#define SSL_AD_CERTIFICATE_EXPIRED	SSL3_AD_CERTIFICATE_EXPIRED
+#define SSL_AD_CERTIFICATE_UNKNOWN	SSL3_AD_CERTIFICATE_UNKNOWN
+#define SSL_AD_ILLEGAL_PARAMETER	SSL3_AD_ILLEGAL_PARAMETER   /* fatal */
+#define SSL_AD_UNKNOWN_CA		TLS1_AD_UNKNOWN_CA	/* fatal */
+#define SSL_AD_ACCESS_DENIED		TLS1_AD_ACCESS_DENIED	/* fatal */
+#define SSL_AD_DECODE_ERROR		TLS1_AD_DECODE_ERROR	/* fatal */
+#define SSL_AD_DECRYPT_ERROR		TLS1_AD_DECRYPT_ERROR
+#define SSL_AD_EXPORT_RESTRICION	TLS1_AD_EXPORT_RESTRICION/* fatal */
+#define SSL_AD_PROTOCOL_VERSION		TLS1_AD_PROTOCOL_VERSION /* fatal */
+#define SSL_AD_INSUFFICIENT_SECURITY	TLS1_AD_INSUFFICIENT_SECURITY/* fatal */
+#define SSL_AD_INTERNAL_ERROR		TLS1_AD_INTERNAL_ERROR	/* fatal */
+#define SSL_AD_USER_CANCLED		TLS1_AD_USER_CANCLED
+#define SSL_AD_NO_RENEGOTIATION		TLS1_AD_NO_RENEGOTIATION
+
 #define SSL_ERROR_NONE			0
 #define SSL_ERROR_SSL			1
 #define SSL_ERROR_WANT_READ		2
@@ -652,11 +695,26 @@
 #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_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
+/* Add these ones */
+#define SSL_CTRL_GET_SESSION_REUSED		6
+#define SSL_CTRL_GET_CLIENT_CERT_REQUEST	7
+#define SSL_CTRL_GET_NUM_RENEGOTIATIONS		8
+#define SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS	9
+#define SSL_CTRL_GET_TOTAL_RENEGOTIATIONS	10
+
+#define SSL_session_reused(ssl) \
+	SSL_ctrl((ssl),SSL_CTRL_GET_SESSION_REUSED,0,NULL)
+#define SSL_num_renegotiations(ssl) \
+	SSL_ctrl((ssl),SSL_CTRL_GET_NUM_RENEGOTIATIONS,0,NULL)
+#define SSL_clear_num_renegotiations(ssl) \
+	SSL_ctrl((ssl),SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS,0,NULL)
+#define SSL_total_renegotiations(ssl) \
+	SSL_ctrl((ssl),SSL_CTRL_GET_TOTAL_RENEGOTIATIONS,0,NULL)
 
 #define SSL_CTX_need_tmp_RSA(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_NEED_TMP_RSA,0,NULL)
@@ -672,13 +730,15 @@
 #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)
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH_CB,0,(char *)dh)
 
 #ifndef NOPROTO
 
 #ifdef HEADER_BIO_H
 BIO_METHOD *BIO_f_ssl(void);
 BIO *BIO_new_ssl(SSL_CTX *ctx,int client);
+BIO *BIO_new_ssl_connect(SSL_CTX *ctx);
+BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx);
 int BIO_ssl_copy_session_id(BIO *to,BIO *from);
 void BIO_ssl_shutdown(BIO *ssl_bio);
 
@@ -717,27 +777,37 @@
 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);
+
+#ifndef NO_STDIO
+int	SSL_use_RSAPrivateKey_file(SSL *ssl, char *file, int type);
+int	SSL_use_PrivateKey_file(SSL *ssl, char *file, int type);
 int	SSL_use_certificate_file(SSL *ssl, char *file, int type);
+int	SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, char *file, int type);
+int	SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, char *file, int type);
+int	SSL_CTX_use_certificate_file(SSL_CTX *ctx, char *file, int type);
+STACK * SSL_load_client_CA_file(char *file);
+#endif
+
 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);
+long	SSL_SESSION_get_time(SSL_SESSION *s);
+long	SSL_SESSION_set_time(SSL_SESSION *s, long t);
+long	SSL_SESSION_get_timeout(SSL_SESSION *s);
+long	SSL_SESSION_set_timeout(SSL_SESSION *s, long t);
 void	SSL_copy_session_id(SSL *to,SSL *from);
 
 SSL_SESSION *SSL_SESSION_new(void);
-#ifndef WIN16
+unsigned long SSL_SESSION_hash(SSL_SESSION *a);
+int	SSL_SESSION_cmp(SSL_SESSION *a,SSL_SESSION *b);
+#ifndef NO_FP_API
 int	SSL_SESSION_print_fp(FILE *fp,SSL_SESSION *ses);
 #endif
 #ifdef HEADER_BIO_H
@@ -762,14 +832,11 @@
 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)());
 
@@ -793,17 +860,21 @@
 /* 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 *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 *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 */
+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 */
+
+SSL_METHOD *TLSv1_method(void);		/* TLSv1.0 */
+SSL_METHOD *TLSv1_server_method(void);	/* TLSv1.0 */
+SSL_METHOD *TLSv1_client_method(void);	/* TLSv1.0 */
 
 STACK *SSL_get_ciphers(SSL *s);
 
@@ -818,7 +889,6 @@
 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);
@@ -841,10 +911,45 @@
 X509 *SSL_get_certificate(SSL *ssl);
 /* EVP_PKEY */ struct evp_pkey_st *SSL_get_privatekey(SSL *ssl);
 
+void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx,int mode);
+int SSL_CTX_get_quiet_shutdown(SSL_CTX *ctx);
+void SSL_set_quiet_shutdown(SSL *ssl,int mode);
+int SSL_get_quiet_shutdown(SSL *ssl);
+void SSL_set_shutdown(SSL *ssl,int mode);
+int SSL_get_shutdown(SSL *ssl);
+int SSL_version(SSL *ssl);
+int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx);
+int SSL_CTX_load_verify_locations(SSL_CTX *ctx,char *CAfile,char *CApath);
+SSL_SESSION *SSL_get_session(SSL *ssl);
+SSL_CTX *SSL_get_SSL_CTX(SSL *ssl);
+void SSL_set_info_callback(SSL *ssl,void (*cb)());
+void (*SSL_get_info_callback(SSL *ssl))();
+int SSL_state(SSL *ssl);
+
+void SSL_set_verify_result(SSL *ssl,long v);
+long SSL_get_verify_result(SSL *ssl);
+
+int SSL_set_ex_data(SSL *ssl,int idx,char *data);
+char *SSL_get_ex_data(SSL *ssl,int idx);
+int SSL_get_ex_new_index(long argl, char *argp, int (*new_func)(),
+	int (*dup_func)(), void (*free_func)());
+
+int SSL_SESSION_set_ex_data(SSL_SESSION *ss,int idx,char *data);
+char *SSL_SESSION_get_ex_data(SSL_SESSION *ss,int idx);
+int SSL_SESSION_get_ex_new_index(long argl, char *argp, int (*new_func)(),
+	int (*dup_func)(), void (*free_func)());
+
+int SSL_CTX_set_ex_data(SSL_CTX *ssl,int idx,char *data);
+char *SSL_CTX_get_ex_data(SSL_CTX *ssl,int idx);
+int SSL_CTX_get_ex_new_index(long argl, char *argp, int (*new_func)(),
+	int (*dup_func)(), void (*free_func)());
+
 #else
 
 BIO_METHOD *BIO_f_ssl();
 BIO *BIO_new_ssl();
+BIO *BIO_new_ssl_connect();
+BIO *BIO_new_buffer_ssl_connect();
 int BIO_ssl_copy_session_id();
 void BIO_ssl_shutdown();
 
@@ -881,27 +986,37 @@
 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();
+
+#ifndef NO_STDIO
+int	SSL_use_RSAPrivateKey_file();
+int	SSL_use_PrivateKey_file();
 int	SSL_use_certificate_file();
+int	SSL_CTX_use_RSAPrivateKey_file();
+int	SSL_CTX_use_PrivateKey_file();
+int	SSL_CTX_use_certificate_file();
+STACK * SSL_load_client_CA_file();
+#endif
+
 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();
+long	SSL_SESSION_get_time();
+long	SSL_SESSION_set_time();
+long	SSL_SESSION_get_timeout();
+long	SSL_SESSION_set_timeout();
 void	SSL_copy_session_id();
 
 SSL_SESSION *SSL_SESSION_new();
-#ifndef WIN16
+unsigned long SSL_SESSION_hash();
+int	SSL_SESSION_cmp();
+#ifndef NO_FP_API
 int	SSL_SESSION_print_fp();
 #endif
 #ifdef HEADER_BIO_H
@@ -926,13 +1041,10 @@
 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();
 
@@ -967,6 +1079,10 @@
 SSL_METHOD *SSLv23_server_method();
 SSL_METHOD *SSLv23_client_method();
 
+SSL_METHOD *TLSv1_method();
+SSL_METHOD *TLSv1_server_method();
+SSL_METHOD *TLSv1_client_method();
+
 STACK *SSL_get_ciphers();
 
 int SSL_do_handshake();
@@ -980,7 +1096,6 @@
 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();
@@ -1005,6 +1120,36 @@
 
 #ifdef this_is_for_mk1mf_pl
 EVP *SSL_get_privatekey();
+
+void SSL_CTX_set_quiet_shutdown();
+int SSL_CTX_get_quiet_shutdown();
+void SSL_set_quiet_shutdown();
+int SSL_get_quiet_shutdown();
+void SSL_set_shutdown();
+int SSL_get_shutdown();
+int SSL_version();
+int SSL_CTX_set_default_verify_paths();
+int SSL_CTX_load_verify_locations();
+SSL_SESSION *SSL_get_session();
+SSL_CTX *SSL_get_SSL_CTX();
+void SSL_set_info_callback();
+int (*SSL_get_info_callback())();
+int SSL_state();
+void SSL_set_verify_result();
+long SSL_get_verify_result();
+
+int SSL_set_ex_data();
+char *SSL_get_ex_data();
+int SSL_get_ex_new_index();
+
+int SSL_SESSION_set_ex_data();
+char *SSL_SESSION_get_ex_data();
+int SSL_SESSION_get_ex_new_index();
+
+int SSL_CTX_set_ex_data();
+char *SSL_CTX_get_ex_data();
+int SSL_CTX_get_ex_new_index();
+
 #endif
 
 #endif
@@ -1094,29 +1239,34 @@
 #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
+#define SSL_F_SSL_INIT_WBIO_BUFFER			 181
+#define SSL_F_SSL_LOAD_CLIENT_CA_FILE			 182
+#define SSL_F_SSL_NEW					 183
+#define SSL_F_SSL_RSA_PRIVATE_DECRYPT			 184
+#define SSL_F_SSL_RSA_PUBLIC_ENCRYPT			 185
+#define SSL_F_SSL_SESSION_NEW				 186
+#define SSL_F_SSL_SESSION_PRINT_FP			 187
+#define SSL_F_SSL_SET_CERT				 188
+#define SSL_F_SSL_SET_FD				 189
+#define SSL_F_SSL_SET_PKEY				 190
+#define SSL_F_SSL_SET_RFD				 191
+#define SSL_F_SSL_SET_SESSION				 192
+#define SSL_F_SSL_SET_WFD				 193
+#define SSL_F_SSL_UNDEFINED_FUNCTION			 194
+#define SSL_F_SSL_USE_CERTIFICATE			 195
+#define SSL_F_SSL_USE_CERTIFICATE_ASN1			 196
+#define SSL_F_SSL_USE_CERTIFICATE_FILE			 197
+#define SSL_F_SSL_USE_PRIVATEKEY			 198
+#define SSL_F_SSL_USE_PRIVATEKEY_ASN1			 199
+#define SSL_F_SSL_USE_PRIVATEKEY_FILE			 200
+#define SSL_F_SSL_USE_RSAPRIVATEKEY			 201
+#define SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1		 202
+#define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE		 203
+#define SSL_F_SSL_WRITE					 204
+#define SSL_F_TLS1_CHANGE_CIPHER_STATE			 205
+#define SSL_F_TLS1_ENC					 206
+#define SSL_F_TLS1_SETUP_KEY_BLOCK			 207
+#define SSL_F_WRITE_PENDING				 208
 
 /* Reason codes. */
 #define SSL_R_APP_DATA_IN_HANDSHAKE			 100
@@ -1135,103 +1285,109 @@
 #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_BAD_PROTOCOL_VERSION_NUMBER		 116
+#define SSL_R_BAD_RESPONSE_ARGUMENT			 117
+#define SSL_R_BAD_RSA_DECRYPT				 118
+#define SSL_R_BAD_RSA_ENCRYPT				 119
+#define SSL_R_BAD_RSA_E_LENGTH				 120
+#define SSL_R_BAD_RSA_MODULUS_LENGTH			 121
+#define SSL_R_BAD_RSA_SIGNATURE				 122
+#define SSL_R_BAD_SIGNATURE				 123
+#define SSL_R_BAD_SSL_FILETYPE				 124
+#define SSL_R_BAD_SSL_SESSION_ID_LENGTH			 125
+#define SSL_R_BAD_STATE					 126
+#define SSL_R_BAD_WRITE_RETRY				 127
+#define SSL_R_BIO_NOT_SET				 128
+#define SSL_R_BLOCK_CIPHER_PAD_IS_WRONG			 129
+#define SSL_R_BN_LIB					 130
+#define SSL_R_CA_DN_LENGTH_MISMATCH			 131
+#define SSL_R_CA_DN_TOO_LONG				 132
+#define SSL_R_CCS_RECEIVED_EARLY			 133
+#define SSL_R_CERTIFICATE_VERIFY_FAILED			 134
+#define SSL_R_CERT_LENGTH_MISMATCH			 135
+#define SSL_R_CHALLENGE_IS_DIFFERENT			 136
+#define SSL_R_CIPHER_CODE_WRONG_LENGTH			 137
+#define SSL_R_CIPHER_OR_HASH_UNAVAILABLE		 138
+#define SSL_R_CIPHER_TABLE_SRC_ERROR			 139
+#define SSL_R_COMPRESSED_LENGTH_TOO_LONG		 140
+#define SSL_R_COMPRESSION_FAILURE			 141
+#define SSL_R_CONNECTION_ID_IS_DIFFERENT		 142
+#define SSL_R_CONNECTION_TYPE_NOT_SET			 143
+#define SSL_R_DATA_BETWEEN_CCS_AND_FINISHED		 144
+#define SSL_R_DATA_LENGTH_TOO_LONG			 145
+#define SSL_R_DECRYPTION_FAILED				 146
+#define SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG		 147
+#define SSL_R_DIGEST_CHECK_FAILED			 148
+#define SSL_R_ENCRYPTED_LENGTH_TOO_LONG			 149
+#define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST		 150
+#define SSL_R_EXCESSIVE_MESSAGE_SIZE			 151
+#define SSL_R_EXTRA_DATA_IN_MESSAGE			 152
+#define SSL_R_GOT_A_FIN_BEFORE_A_CCS			 153
+#define SSL_R_HTTPS_PROXY_REQUEST			 154
+#define SSL_R_HTTP_REQUEST				 155
+#define SSL_R_INTERNAL_ERROR				 156
+#define SSL_R_INVALID_CHALLENGE_LENGTH			 157
+#define SSL_R_LENGTH_MISMATCH				 158
+#define SSL_R_LENGTH_TOO_SHORT				 159
+#define SSL_R_LIBRARY_HAS_NO_CIPHERS			 160
+#define SSL_R_MISSING_DH_DSA_CERT			 161
+#define SSL_R_MISSING_DH_KEY				 162
+#define SSL_R_MISSING_DH_RSA_CERT			 163
+#define SSL_R_MISSING_DSA_SIGNING_CERT			 164
+#define SSL_R_MISSING_EXPORT_TMP_DH_KEY			 165
+#define SSL_R_MISSING_EXPORT_TMP_RSA_KEY		 166
+#define SSL_R_MISSING_RSA_CERTIFICATE			 167
+#define SSL_R_MISSING_RSA_ENCRYPTING_CERT		 168
+#define SSL_R_MISSING_RSA_SIGNING_CERT			 169
+#define SSL_R_MISSING_TMP_DH_KEY			 170
+#define SSL_R_MISSING_TMP_RSA_KEY			 171
+#define SSL_R_MISSING_TMP_RSA_PKEY			 172
+#define SSL_R_MISSING_VERIFY_MESSAGE			 173
+#define SSL_R_NON_SSLV2_INITIAL_PACKET			 174
+#define SSL_R_NO_CERTIFICATES_RETURNED			 175
+#define SSL_R_NO_CERTIFICATE_ASSIGNED			 176
+#define SSL_R_NO_CERTIFICATE_RETURNED			 177
+#define SSL_R_NO_CERTIFICATE_SET			 178
+#define SSL_R_NO_CERTIFICATE_SPECIFIED			 179
+#define SSL_R_NO_CIPHERS_AVAILABLE			 180
+#define SSL_R_NO_CIPHERS_PASSED				 181
+#define SSL_R_NO_CIPHERS_SPECIFIED			 182
+#define SSL_R_NO_CIPHER_LIST				 183
+#define SSL_R_NO_CIPHER_MATCH				 184
+#define SSL_R_NO_CLIENT_CERT_RECEIVED			 185
+#define SSL_R_NO_COMPRESSION_SPECIFIED			 186
+#define SSL_R_NO_PRIVATEKEY				 187
+#define SSL_R_NO_PRIVATE_KEY_ASSIGNED			 188
+#define SSL_R_NO_PROTOCOLS_AVAILABLE			 189
+#define SSL_R_NO_PUBLICKEY				 190
+#define SSL_R_NO_SHARED_CIPHER				 191
+#define SSL_R_NULL_SSL_CTX				 192
+#define SSL_R_NULL_SSL_METHOD_PASSED			 193
+#define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED		 194
+#define SSL_R_PACKET_LENGTH_TOO_LONG			 195
+#define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE		 196
+#define SSL_R_PEER_ERROR				 197
+#define SSL_R_PEER_ERROR_CERTIFICATE			 198
+#define SSL_R_PEER_ERROR_NO_CERTIFICATE			 199
+#define SSL_R_PEER_ERROR_NO_CIPHER			 200
+#define SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE	 201
+#define SSL_R_PRE_MAC_LENGTH_TOO_LONG			 202
+#define SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS		 203
+#define SSL_R_PROTOCOL_IS_SHUTDOWN			 204
+#define SSL_R_PUBLIC_KEY_ENCRYPT_ERROR			 205
+#define SSL_R_PUBLIC_KEY_IS_NOT_RSA			 206
+#define SSL_R_PUBLIC_KEY_NOT_RSA			 207
+#define SSL_R_READ_BIO_NOT_SET				 208
+#define SSL_R_READ_WRONG_PACKET_TYPE			 209
+#define SSL_R_RECORD_LENGTH_MISMATCH			 210
+#define SSL_R_RECORD_TOO_LARGE				 211
+#define SSL_R_REQUIRED_CIPHER_MISSING			 212
+#define SSL_R_REUSE_CERT_LENGTH_NOT_ZERO		 213
+#define SSL_R_REUSE_CERT_TYPE_NOT_ZERO			 214
+#define SSL_R_REUSE_CIPHER_LIST_NOT_ZERO		 215
+#define SSL_R_SHORT_READ				 216
+#define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE	 217
+#define SSL_R_SSL3_SESSION_ID_TOO_SHORT			 218
 #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
@@ -1241,47 +1397,54 @@
 #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_PEER_ERROR_CERTIFICATE	 219
+#define SSL_R_SSLV3_ALERT_PEER_ERROR_NO_CERTIFICATE	 220
+#define SSL_R_SSLV3_ALERT_PEER_ERROR_NO_CIPHER		 221
+#define SSL_R_SSLV3_ALERT_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE 222
 #define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE		 1010
-#define SSL_R_SSLV3_ALERT_UNKNOWN_REMOTE_ERROR_TYPE	 217
+#define SSL_R_SSLV3_ALERT_UNKNOWN_REMOTE_ERROR_TYPE	 223
 #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
+#define SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION	 224
+#define SSL_R_SSL_HANDSHAKE_FAILURE			 225
+#define SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS		 226
+#define SSL_R_SSL_SESSION_ID_IS_DIFFERENT		 227
+#define SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER	 228
+#define SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST 229
+#define SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG	 230
+#define SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER		 231
+#define SSL_R_UNABLE_TO_DECODE_DH_CERTS			 232
+#define SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY		 233
+#define SSL_R_UNABLE_TO_FIND_DH_PARAMETERS		 234
+#define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS	 235
+#define SSL_R_UNABLE_TO_FIND_SSL_METHOD			 236
+#define SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES		 237
+#define SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES		 238
+#define SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES		 239
+#define SSL_R_UNEXPECTED_MESSAGE			 240
+#define SSL_R_UNEXPECTED_RECORD				 241
+#define SSL_R_UNKNOWN_ALERT_TYPE			 242
+#define SSL_R_UNKNOWN_CERTIFICATE_TYPE			 243
+#define SSL_R_UNKNOWN_CIPHER_RETURNED			 244
+#define SSL_R_UNKNOWN_CIPHER_TYPE			 245
+#define SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE			 246
+#define SSL_R_UNKNOWN_PKEY_TYPE				 247
+#define SSL_R_UNKNOWN_PROTOCOL				 248
+#define SSL_R_UNKNOWN_REMOTE_ERROR_TYPE			 249
+#define SSL_R_UNKNOWN_SSL_VERSION			 250
+#define SSL_R_UNKNOWN_STATE				 251
+#define SSL_R_UNSUPPORTED_CIPHER			 252
+#define SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM		 253
+#define SSL_R_UNSUPPORTED_PROTOCOL			 254
+#define SSL_R_UNSUPPORTED_SSL_VERSION			 255
+#define SSL_R_WRITE_BIO_NOT_SET				 256
+#define SSL_R_WRONG_CIPHER_RETURNED			 257
+#define SSL_R_WRONG_MESSAGE_TYPE			 258
+#define SSL_R_WRONG_NUMBER_OF_KEY_BITS			 259
+#define SSL_R_WRONG_SIGNATURE_LENGTH			 260
+#define SSL_R_WRONG_SIGNATURE_SIZE			 261
+#define SSL_R_WRONG_SSL_VERSION				 262
+#define SSL_R_WRONG_VERSION_NUMBER			 263
+#define SSL_R_X509_LIB					 264
  
 #ifdef  __cplusplus
 }
diff --git a/ssl/ssl2.h b/ssl/ssl2.h
index db353f5..3dc94e5 100644
--- a/ssl/ssl2.h
+++ b/ssl/ssl2.h
@@ -1,5 +1,5 @@
 /* ssl/ssl2.h */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -64,6 +64,9 @@
 #endif
 
 /* Protocol Version Codes */
+#define SSL2_VERSION		0x0002
+#define SSL2_VERSION_MAJOR	0x00
+#define SSL2_VERSION_MINOR	0x02
 #define SSL2_CLIENT_VERSION	0x0002
 #define SSL2_SERVER_VERSION	0x0002
 
@@ -150,7 +153,6 @@
 
 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 */
diff --git a/ssl/ssl23.h b/ssl/ssl23.h
index 6e6f26b..d322898 100644
--- a/ssl/ssl23.h
+++ b/ssl/ssl23.h
@@ -1,5 +1,5 @@
 /* ssl/ssl23.h */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
diff --git a/ssl/ssl3.h b/ssl/ssl3.h
index 9675ec2..95772ee 100644
--- a/ssl/ssl3.h
+++ b/ssl/ssl3.h
@@ -1,5 +1,5 @@
 /* ssl/ssl3.h */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -94,7 +94,7 @@
 #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_ADH_DES_192_CBC_SHA		0x0300001B
 
 #define SSL3_CK_FZA_DMS_NULL_SHA		0x0300001C
 #define SSL3_CK_FZA_DMS_FZA_SHA			0x0300001D
@@ -106,7 +106,7 @@
 #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_IDEA_128_SHA		"IDEA-CBC-SHA"
 #define SSL3_TXT_RSA_DES_40_CBC_SHA		"EXP-DES-CBC-SHA"
 #define SSL3_TXT_RSA_DES_64_CBC_SHA		"DES-CBC-SHA"
 #define SSL3_TXT_RSA_DES_192_CBC3_SHA		"DES-CBC3-SHA"
@@ -121,7 +121,7 @@
 #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_40_CBC_SHA		"EXP-EDH-RSA-DES-CBC-SHA"
 #define SSL3_TXT_EDH_RSA_DES_64_CBC_SHA		"EDH-RSA-DES-CBC-SHA"
 #define SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA	"EDH-RSA-DES-CBC3-SHA"
 
@@ -129,7 +129,7 @@
 #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_ADH_DES_192_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"
@@ -172,8 +172,8 @@
 #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_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
@@ -236,6 +236,34 @@
 #define SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS	0x0001
 #define SSL3_FLAGS_DELAY_CLIENT_FINISHED	0x0002
 #define SSL3_FLAGS_POP_BUFFER			0x0004
+#define	TLS1_FLAGS_TLS_PADDING_BUG		0x0008
+
+#if 0
+#define AD_CLOSE_NOTIFY			0
+#define AD_UNEXPECTED_MESSAGE		1
+#define AD_BAD_RECORD_MAC		2
+#define AD_DECRYPTION_FAILED		3
+#define AD_RECORD_OVERFLOW		4
+#define AD_DECOMPRESSION_FAILURE	5	/* fatal */
+#define AD_HANDSHAKE_FAILURE		6	/* fatal */
+#define AD_NO_CERTIFICATE		7	/* Not under TLS */
+#define AD_BAD_CERTIFICATE		8
+#define AD_UNSUPPORTED_CERTIFICATE	9
+#define AD_CERTIFICATE_REVOKED		10	
+#define AD_CERTIFICATE_EXPIRED		11
+#define AD_CERTIFICATE_UNKNOWN		12
+#define AD_ILLEGAL_PARAMETER		13	/* fatal */
+#define AD_UNKNOWN_CA			14	/* fatal */
+#define AD_ACCESS_DENIED		15	/* fatal */
+#define AD_DECODE_ERROR			16	/* fatal */
+#define AD_DECRYPT_ERROR		17
+#define AD_EXPORT_RESTRICION		18	/* fatal */
+#define AD_PROTOCOL_VERSION		19	/* fatal */
+#define AD_INSUFFICIENT_SECURITY	20	/* fatal */
+#define AD_INTERNAL_ERROR		21	/* fatal */
+#define AD_USER_CANCLED			22
+#define AD_NO_RENEGOTIATION		23
+#endif
 
 typedef struct ssl3_ctx_st
 	{
@@ -279,9 +307,17 @@
 	int alert_dispatch;
 	char send_alert[2];
 
+	/* This flag is set when we should renegotiate ASAP, basically when
+	 * there is no more data in the read or write buffers */
+	int renegotiate;
+	int total_renegotiations;
+	int num_renegotiations;
+
+	int in_read_app_data;
+
 	struct	{
-		unsigned char finish_md1[EVP_MAX_MD_SIZE];
-		unsigned char finish_md2[EVP_MAX_MD_SIZE];
+		/* Actually only needs to be 16+20 for SSLv3 and 12 for TLS */
+		unsigned char finish_md[EVP_MAX_MD_SIZE*2];
 		
 		unsigned long message_size;
 		int message_type;
@@ -309,6 +345,7 @@
 		EVP_CIPHER *new_sym_enc;
 		EVP_MD *new_hash;
 		SSL_COMPRESSION *new_compression;
+		int cert_request;
 		} tmp;
 	} SSL3_CTX;
 
@@ -353,6 +390,7 @@
 /* extra state */
 #define SSL3_ST_SW_FLUSH		(0x100|SSL_ST_ACCEPT)
 /* read from client */
+/* Do not change the number values, they do matter */
 #define SSL3_ST_SR_CLNT_HELLO_A		(0x110|SSL_ST_ACCEPT)
 #define SSL3_ST_SR_CLNT_HELLO_B		(0x111|SSL_ST_ACCEPT)
 #define SSL3_ST_SR_CLNT_HELLO_C		(0x112|SSL_ST_ACCEPT)
diff --git a/ssl/ssl_algs.c b/ssl/ssl_algs.c
index 36b0333..65f3a59 100644
--- a/ssl/ssl_algs.c
+++ b/ssl/ssl_algs.c
@@ -1,5 +1,5 @@
 /* ssl/ssl_algs.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -82,9 +82,12 @@
 #endif
 #ifndef NO_MD5
 	EVP_add_digest(EVP_md5());
+	EVP_add_alias(SN_md5,"ssl2-md5");
+	EVP_add_alias(SN_md5,"ssl3-md5");
 #endif
 #ifndef NO_SHA1
 	EVP_add_digest(EVP_sha1()); /* RSA with sha1 */
+	EVP_add_alias(SN_sha1,"ssl3-sha1");
 #endif
 #if !defined(NO_SHA1) && !defined(NO_DSA)
 	EVP_add_digest(EVP_dss1()); /* DSA with sha1 */
diff --git a/ssl/ssl_asn1.c b/ssl/ssl_asn1.c
index 873497a..116a83d 100644
--- a/ssl/ssl_asn1.c
+++ b/ssl/ssl_asn1.c
@@ -1,5 +1,5 @@
 /* ssl/ssl_asn1.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -116,7 +116,7 @@
 		l=in->cipher_id;
 	else
 		l=in->cipher->id;
-	if (in->ssl_version == 2)
+	if (in->ssl_version == SSL2_VERSION)
 		{
 		a.cipher.length=3;
 		buf[0]=((unsigned char)(l>>16L))&0xff;
@@ -221,7 +221,7 @@
 
 	os.data=NULL; os.length=0;
 	M_ASN1_D2I_get(osp,d2i_ASN1_OCTET_STRING);
-	if (ssl_version == 2)
+	if (ssl_version == SSL2_VERSION)
 		{
 		if (os.length != 3)
 			{
@@ -233,7 +233,7 @@
 			((unsigned long)os.data[1]<< 8L)|
 			 (unsigned long)os.data[2];
 		}
-	else if (ssl_version == 3)
+	else if ((ssl_version>>8) == 3)
 		{
 		if (os.length != 2)
 			{
@@ -254,9 +254,9 @@
 	ret->cipher_id=id;
 
 	M_ASN1_D2I_get(osp,d2i_ASN1_OCTET_STRING);
-	if (ssl_version == 3)
+	if ((ssl_version>>8) == SSL3_VERSION)
 		i=SSL3_MAX_SSL_SESSION_ID_LENGTH;
-	else /* if (ssl_version == 2) */
+	else /* if (ssl_version == SSL2_VERSION) */
 		i=SSL2_MAX_SSL_SESSION_ID_LENGTH;
 
 	if (os.length > i)
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index 0c040d9..c1cb86e 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -1,5 +1,5 @@
 /* ssl/ssl_cert.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -94,6 +94,9 @@
 	int i;
 
 	i=CRYPTO_add(&c->references,-1,CRYPTO_LOCK_SSL_CERT);
+#ifdef REF_PRINT
+	REF_PRINT("CERT",c);
+#endif
 	if (i > 0) return;
 #ifdef REF_CHECK
 	if (i < 0)
@@ -215,7 +218,8 @@
 	{
 	if (s->type == SSL_ST_CONNECT)
 		{ /* we are in the client */
-		if ((s->version == 3) && (s->s3 != NULL))
+		if (((s->version>>8) == SSL3_VERSION_MAJOR) &&
+			(s->s3 != NULL))
 			return(s->s3->tmp.ca_names);
 		else
 			return(NULL);
@@ -270,6 +274,7 @@
 	return(X509_NAME_cmp(*a,*b));
 	}
 
+#ifndef NO_STDIO
 STACK *SSL_load_client_CA_file(file)
 char *file;
 	{
@@ -280,11 +285,9 @@
 
 	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
+
+	in=BIO_new(BIO_s_file_internal());
+
 	if ((ret == NULL) || (sk == NULL) || (in == NULL))
 		{
 		SSLerr(SSL_F_SSL_LOAD_CLIENT_CA_FILE,ERR_R_MALLOC_FAILURE);
@@ -322,5 +325,5 @@
 	if (x != NULL) X509_free(x);
 	return(ret);
 	}
-
+#endif
 
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
index 9fed3ad..8209944 100644
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -1,5 +1,5 @@
 /* ssl/ssl_ciph.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -74,11 +74,10 @@
 	};
 
 #define SSL_MD_MD5_IDX	0
-#define SSL_MD_SHA0_IDX	1
-#define SSL_MD_SHA1_IDX	2
-#define SSL_MD_NUM_IDX	3
+#define SSL_MD_SHA1_IDX	1
+#define SSL_MD_NUM_IDX	2
 static EVP_MD *ssl_digest_methods[SSL_MD_NUM_IDX]={
-	NULL,NULL,NULL,
+	NULL,NULL,
 	};
 
 typedef struct cipher_sort_st
@@ -90,16 +89,24 @@
 #define CIPHER_ADD	1
 #define CIPHER_KILL	2
 #define CIPHER_DEL	3
-#define CIPHER_ORDER	4
+#define CIPHER_ORD	4
 
 typedef struct cipher_choice_st
 	{
 	int type;
 	unsigned long algorithms;
 	unsigned long mask;
-	STACK *order;
+	long top;
 	} CIPHER_CHOICE;
 
+typedef struct cipher_order_st
+	{
+	SSL_CIPHER *cipher;
+	int active;
+	int dead;
+	struct cipher_order_st *next,*prev;
+	} CIPHER_ORDER;
+
 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},
@@ -126,7 +133,6 @@
 	{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},
 
@@ -169,8 +175,6 @@
 
 	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);
 	}
@@ -225,9 +229,6 @@
 	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;
@@ -246,6 +247,25 @@
 		return(0);
 	}
 
+#define ITEM_SEP(a) \
+	(((a) == ':') || ((a) == ' ') || ((a) == ';') || ((a) == ','))
+
+static void ll_append_tail(head,curr,tail)
+CIPHER_ORDER **head,*curr,**tail;
+	{
+	if (curr == *tail) return;
+	if (curr == *head)
+		*head=curr->next;
+	if (curr->prev != NULL)
+		curr->prev->next=curr->next;
+	if (curr->next != NULL) /* should always be true */
+		curr->next->prev=curr->prev;
+	(*tail)->next=curr;
+	curr->prev= *tail;
+	curr->next=NULL;
+	*tail=curr;
+	}
+
 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;
@@ -262,9 +282,11 @@
 	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;
+	int current_x,num_x;
 	CIPHER_CHOICE *ops=NULL;
+	CIPHER_ORDER *list=NULL,*head=NULL,*tail=NULL,*curr,*tail2,*curr2;
+	int list_num;
+	int type;
 	SSL_CIPHER c_tmp,*cp;
 
 	if (str == NULL) return(NULL);
@@ -278,6 +300,7 @@
 			goto err;
 			}
 		strcpy(tmp_str,SSL_DEFAULT_CIPHER_LIST);
+		strcat(tmp_str,":");
 		strcat(tmp_str,&(str[7]));
 		str=tmp_str;
 		}
@@ -286,7 +309,6 @@
 	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;
@@ -312,20 +334,42 @@
 	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;
 
+	if ((list=(CIPHER_ORDER *)Malloc(sizeof(CIPHER_ORDER)*num)) == NULL)
+		goto err;
+
 	/* Get the initial list of ciphers */
+	list_num=0;
 	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;
+			list[list_num].cipher=c;
+			list[list_num].next=NULL;
+			list[list_num].prev=NULL;
+			list[list_num].active=0;
+			list_num++;
 			if (!sk_push(ca_list,(char *)c)) goto err;
 			}
 		}
+	
+	for (i=1; i<list_num-1; i++)
+		{
+		list[i].prev= &(list[i-1]);
+		list[i].next= &(list[i+1]);
+		}
+	if (list_num > 0)
+		{
+		head= &(list[0]);
+		head->prev=NULL;
+		head->next= &(list[1]);
+		tail= &(list[list_num-1]);
+		tail->prev= &(list[list_num-2]);
+		tail->next=NULL;
+		}
 
 	/* special case */
 	cipher_aliases[0].algorithms= ~mask;
@@ -346,12 +390,11 @@
 	/* how many parameters are there? */
 	num=1;
 	for (l=str; *l; l++)
-		if (*l == ':') num++;
+		if (ITEM_SEP(*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;
@@ -361,16 +404,19 @@
 	for (;;)
 		{
 		ch= *l;
+
+		if (ch == '\0') break;
+
 		if (ch == '-')
 			{ j=CIPHER_DEL; l++; }
 		else if (ch == '+')
-			{ j=CIPHER_ORDER; l++; }
+			{ j=CIPHER_ORD; l++; }
 		else if (ch == '!')
 			{ j=CIPHER_KILL; l++; }
 		else	
 			{ j=CIPHER_ADD; }
 
-		if (*l == ':')
+		if (ITEM_SEP(ch))
 			{
 			l++;
 			continue;
@@ -395,20 +441,20 @@
 				 if (i >= (CL_BUF-2)) break;
 				 }
 			buf[i]='\0';
-			if (ch != '\0') l++;
 
 			/* check for multi-part specification */
-			multi=(ch == '+')?1:0;
+			if (ch == '+')
+				{
+				multi=1;
+				l++;
+				}
+			else
+				multi=0;
 
 			c_tmp.name=buf;
 			j=sk_find(ca_list,(char *)&c_tmp);
 			if (j < 0)
-				{
-				if (ch == '\0')
-					break;
-				else
-					continue;
-				}
+				goto end_loop;
 
 			cp=(SSL_CIPHER *)sk_value(ca_list,j);
 			ops[current_x].algorithms|=cp->algorithms;
@@ -419,87 +465,86 @@
 			}
 		current_x++;
 		if (ch == '\0') break;
+end_loop:
+		/* Make sure we scan until the next valid start point */
+		while ((*l != '\0') && ITEM_SEP(*l))
+			l++;
 		}
 
 	num_x=current_x;
 	current_x=0;
 
-#ifdef CIPHER_DEBUG
-	printf("<--->\n");
-#endif
-
-	for (i=0; i<sk_num(c_list); i++)
+	/* We will now process the list of ciphers, once for each category, to
+	 * decide what we should do with it. */
+	for (j=0; j<num_x; j++)
 		{
-		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;
+		type=ops[j].type;
+		mask=ops[j].mask;
+
+		curr=head;
+		curr2=head;
+		tail2=tail;
+		for (;;)
 			{
-			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 ((curr == NULL) || (curr == tail2)) break;
+			curr=curr2;
+			curr2=curr->next;
+
+			cp=curr->cipher;
+			ma=mask & cp->algorithms;
 			if ((ma == 0) || ((ma & algorithms) != ma))
 				{
+				/* does not apply */
 				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 (type == CIPHER_ADD)
 				{
-				if (old_x < 0)
+				if (!curr->active)
 					{
-					old_x=j;
-					old_y=sk_num(ops[j].order);
-					sk_push(ops[j].order,(char *)cp);
+					ll_append_tail(&head,curr,&tail);
+					curr->active=1;
 					}
 				}
 			/* Move the added cipher to this location */
-			else if (k == CIPHER_ORDER)
+			else if (type == CIPHER_ORD)
 				{
-				if (old_x >= 0)
+				if (curr->active)
 					{
-					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;
+					ll_append_tail(&head,curr,&tail);
 					}
 				}
-			/* Remove added cipher */
-			else if ((k == CIPHER_DEL) || (k == CIPHER_KILL))
+			else if	(type == CIPHER_DEL)
+				curr->active=0;
+			if (type == CIPHER_KILL)
 				{
-				if (old_x >= 0)
-					{
-					sk_value(ops[old_x].order,old_y)=NULL;
-					old_x= -1;
-					}
-				if (k == CIPHER_KILL)
-					break;
+				if (head == curr)
+					head=curr->next;
+				else
+					curr->prev->next=curr->next;
+				if (tail == curr)
+					tail=curr->prev;
+				curr->active=0;
+				if (curr->next != NULL)
+					curr->next->prev=curr->prev;
+				if (curr->prev != NULL)
+					curr->prev->next=curr->next;
+				curr->next=NULL;
+				curr->prev=NULL;
 				}
 			}
 		}
 
-	for (i=0; i<num_x; i++)
+	for (curr=head; curr != NULL; curr=curr->next)
 		{
-		for (j=0; j<sk_num(ops[i].order); j++)
+		if (curr->active)
 			{
-			cp=(SSL_CIPHER *)sk_value(ops[i].order,j);
-			if (cp != NULL)
-				{
-				sk_push(ret,(char *)cp);
+			sk_push(ret,(char *)curr->cipher);
 #ifdef CIPHER_DEBUG
-				printf("<%s>\n",cp->name);
+			printf("<%s>\n",curr->cipher->name);
 #endif
-				}
 			}
 		}
 
@@ -528,16 +573,10 @@
 	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 (ops != NULL) Free(ops);
 	if (ret != NULL) sk_free(ret);
-	if (c_list != NULL) sk_free(c_list);
 	if (ca_list != NULL) sk_free(ca_list);
+	if (list != NULL) Free(list);
 	return(ok);
 	}
 
@@ -639,9 +678,6 @@
 	case SSL_MD5:
 		mac="MD5";
 		break;
-	case SSL_SHA0:
-		mac="SHA0";
-		break;
 	case SSL_SHA1:
 		mac="SHA1";
 		break;
@@ -667,9 +703,10 @@
 	{
 	int i;
 
+	if (c == NULL) return("(NONE)");
 	i=(int)(c->id>>24L);
 	if (i == 3)
-		return("SSLv3");
+		return("TLSv1/SSLv3");
 	else if (i == 2)
 		return("SSLv2");
 	else
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index 18a1a22..bcbb985 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -60,6 +60,7 @@
 #include "ssl.h"
 
 /* BEGIN ERROR CODES */
+#ifndef NO_ERR
 static ERR_STRING_DATA SSL_str_functs[]=
 	{
 {ERR_PACK(0,SSL_F_CLIENT_CERTIFICATE,0),	"CLIENT_CERTIFICATE"},
@@ -143,12 +144,14 @@
 {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_INIT_WBIO_BUFFER,0),	"SSL_INIT_WBIO_BUFFER"},
 {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_CERT,0),	"SSL_SET_CERT"},
 {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"},
@@ -165,6 +168,9 @@
 {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_TLS1_CHANGE_CIPHER_STATE,0),	"TLS1_CHANGE_CIPHER_STATE"},
+{ERR_PACK(0,SSL_F_TLS1_ENC,0),	"TLS1_ENC"},
+{ERR_PACK(0,SSL_F_TLS1_SETUP_KEY_BLOCK,0),	"TLS1_SETUP_KEY_BLOCK"},
 {ERR_PACK(0,SSL_F_WRITE_PENDING,0),	"WRITE_PENDING"},
 {0,NULL},
 	};
@@ -187,6 +193,7 @@
 {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_PROTOCOL_VERSION_NUMBER       ,"bad protocol version number"},
 {SSL_R_BAD_RESPONSE_ARGUMENT             ,"bad response argument"},
 {SSL_R_BAD_RSA_DECRYPT                   ,"bad rsa decrypt"},
 {SSL_R_BAD_RSA_ENCRYPT                   ,"bad rsa encrypt"},
@@ -213,8 +220,10 @@
 {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_CONNECTION_TYPE_NOT_SET           ,"connection type not set"},
 {SSL_R_DATA_BETWEEN_CCS_AND_FINISHED     ,"data between ccs and finished"},
 {SSL_R_DATA_LENGTH_TOO_LONG              ,"data length too long"},
+{SSL_R_DECRYPTION_FAILED                 ,"decryption failed"},
 {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"},
@@ -222,6 +231,8 @@
 {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_HTTPS_PROXY_REQUEST               ,"https proxy request"},
+{SSL_R_HTTP_REQUEST                      ,"http request"},
 {SSL_R_INTERNAL_ERROR                    ,"internal error"},
 {SSL_R_INVALID_CHALLENGE_LENGTH          ,"invalid challenge length"},
 {SSL_R_LENGTH_MISMATCH                   ,"length mismatch"},
@@ -241,7 +252,7 @@
 {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_CERTIFICATES_RETURNED          ,"no certificates returned"},
 {SSL_R_NO_CERTIFICATE_ASSIGNED           ,"no certificate assigned"},
 {SSL_R_NO_CERTIFICATE_RETURNED           ,"no certificate returned"},
 {SSL_R_NO_CERTIFICATE_SET                ,"no certificate set"},
@@ -255,6 +266,7 @@
 {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_PROTOCOLS_AVAILABLE            ,"no protocols available"},
 {SSL_R_NO_PUBLICKEY                      ,"no publickey"},
 {SSL_R_NO_SHARED_CIPHER                  ,"no shared cipher"},
 {SSL_R_NULL_SSL_CTX                      ,"null ssl ctx"},
@@ -304,12 +316,18 @@
 {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_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER,"tls client cert req with anon cipher"},
+{SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST,"tls peer did not respond with certificate list"},
+{SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG,"tls rsa encrypted value length is wrong"},
 {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_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES  ,"unable to load ssl2 md5 routines"},
+{SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES  ,"unable to load ssl3 md5 routines"},
+{SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES ,"unable to load ssl3 sha1 routines"},
 {SSL_R_UNEXPECTED_MESSAGE                ,"unexpected message"},
 {SSL_R_UNEXPECTED_RECORD                 ,"unexpected record"},
 {SSL_R_UNKNOWN_ALERT_TYPE                ,"unknown alert type"},
@@ -324,6 +342,7 @@
 {SSL_R_UNKNOWN_STATE                     ,"unknown state"},
 {SSL_R_UNSUPPORTED_CIPHER                ,"unsupported cipher"},
 {SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM ,"unsupported compression algorithm"},
+{SSL_R_UNSUPPORTED_PROTOCOL              ,"unsupported protocol"},
 {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"},
@@ -337,14 +356,19 @@
 {0,NULL},
 	};
 
+#endif
+
 void ERR_load_SSL_strings()
 	{
 	static int init=1;
 
-	if (init)
-		{
+	if (init);
+		{;
 		init=0;
+#ifndef NO_ERR
 		ERR_load_strings(ERR_LIB_SSL,SSL_str_functs);
 		ERR_load_strings(ERR_LIB_SSL,SSL_str_reasons);
+#endif
+
 		}
 	}
diff --git a/ssl/ssl_err2.c b/ssl/ssl_err2.c
index a159fbb..0b91f7b 100644
--- a/ssl/ssl_err2.c
+++ b/ssl/ssl_err2.c
@@ -1,5 +1,5 @@
 /* ssl/ssl_err2.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index be091b1..f562ec6 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -1,5 +1,5 @@
 /* ssl/ssl_lib.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -61,13 +61,21 @@
 #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.9.0b 29-Jun-1998";
 
-char *SSL_version_str="SSLeay 0.8.1b 29-Jun-1998";
+static STACK *ssl_meth=NULL;
+static STACK *ssl_ctx_meth=NULL;
+static int ssl_meth_num=0;
+static int ssl_ctx_meth_num=0;
+
+SSL3_ENC_METHOD ssl3_undef_enc_method={
+	ssl_undefined_function,
+	ssl_undefined_function,
+	ssl_undefined_function,
+	ssl_undefined_function,
+	ssl_undefined_function,
+	ssl_undefined_function,
+	};
 
 void SSL_clear(s)
 SSL *s;
@@ -178,7 +186,12 @@
 		}
 
 	s->quiet_shutdown=ctx->quiet_shutdown;
+	s->references=1;
+	s->options=ctx->options;
 	SSL_clear(s);
+
+	CRYPTO_new_ex_data(ssl_meth,(char *)s,&s->ex_data);
+
 	return(s);
 err:
 	SSLerr(SSL_F_SSL_NEW,ERR_R_MALLOC_FAILURE);
@@ -188,6 +201,23 @@
 void SSL_free(s)
 SSL *s;
 	{
+	int i;
+
+	i=CRYPTO_add(&s->references,-1,CRYPTO_LOCK_SSL);
+#ifdef REF_PRINT
+	REF_PRINT("SSL",s);
+#endif
+	if (i > 0) return;
+#ifdef REF_CHECK
+	if (i < 0)
+		{
+		fprintf(stderr,"SSL_free, bad reference count\n");
+		abort(); /* ok */
+		}
+#endif
+
+	CRYPTO_free_ex_data(ssl_meth,(char *)s,&s->ex_data);
+
 	if (s->bbio != NULL)
 		{
 		/* If the buffering BIO is in place, pop it off */
@@ -196,6 +226,7 @@
 			s->wbio=BIO_pop(s->wbio);
 			}
 		BIO_free(s->bbio);
+		s->bbio=NULL;
 		}
 	if (s->rbio != NULL)
 		BIO_free_all(s->rbio);
@@ -303,12 +334,18 @@
 	int ret=0;
 	BIO *bio=NULL;
 
-	bio=BIO_new(BIO_s_socket());
+	if ((s->rbio == NULL) || (BIO_method_type(s->rbio) != BIO_TYPE_SOCKET)
+		|| ((int)BIO_get_fd(s->rbio,NULL) != fd))
+		{
+		bio=BIO_new(BIO_s_socket());
 
-	if (bio == NULL)
-		{ SSLerr(SSL_F_SSL_SET_WFD,ERR_R_BUF_LIB); goto err; }
-	BIO_set_fd(bio,fd,BIO_NOCLOSE);
-	SSL_set_bio(s,SSL_get_rbio(s),bio);
+		if (bio == NULL)
+			{ SSLerr(SSL_F_SSL_SET_WFD,ERR_R_BUF_LIB); goto err; }
+		BIO_set_fd(bio,fd,BIO_NOCLOSE);
+		SSL_set_bio(s,SSL_get_rbio(s),bio);
+		}
+	else
+		SSL_set_bio(s,SSL_get_rbio(s),SSL_get_rbio(s));
 	ret=1;
 err:
 	return(ret);
@@ -321,15 +358,21 @@
 	int ret=0;
 	BIO *bio=NULL;
 
-	bio=BIO_new(BIO_s_socket());
-
-	if (bio == NULL)
+	if ((s->wbio == NULL) || (BIO_method_type(s->wbio) != BIO_TYPE_SOCKET)
+		|| ((int)BIO_get_fd(s->wbio,NULL) != fd))
 		{
-		SSLerr(SSL_F_SSL_SET_RFD,ERR_R_BUF_LIB);
-		goto err;
+		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));
 		}
-	BIO_set_fd(bio,fd,BIO_NOCLOSE);
-	SSL_set_bio(s,bio,SSL_get_wbio(s));
+	else
+		SSL_set_bio(s,SSL_get_wbio(s),SSL_get_wbio(s));
 	ret=1;
 err:
 	return(ret);
@@ -449,6 +492,7 @@
 	if (tmp != NULL) ssl_cert_free(tmp);
 	}
 
+/* Fix this so it checks all the valid key/cert options */
 int SSL_CTX_check_private_key(ctx)
 SSL_CTX *ctx;
 	{
@@ -467,6 +511,7 @@
 	return(X509_check_private_key(ctx->default_cert->key->x509, ctx->default_cert->key->privatekey));
 	}
 
+/* Fix this function so that it takes an optional type parameter */
 int SSL_check_private_key(ssl)
 SSL *ssl;
 	{
@@ -560,6 +605,7 @@
 int SSL_renegotiate(s)
 SSL *s;
 	{
+	s->new_session=1;
 	return(s->method->ssl_renegotiate(s));
 	}
 
@@ -614,7 +660,7 @@
 		{
 		return(s->cipher_list);
 		}
-	else if ((s != NULL) && (s->ctx != NULL) &&
+	else if ((s->ctx != NULL) &&
 		(s->ctx->cipher_list != NULL))
 		{
 		return(s->ctx->cipher_list);
@@ -699,13 +745,14 @@
 
 	p=buf;
 	sk=s->session->ciphers;
-	len--;
 	for (i=0; i<sk_num(sk); i++)
 		{
+		/* Decrement for either the ':' or a '\0' */
+		len--;
 		c=(SSL_CIPHER *)sk_value(sk,i);
 		for (cp=c->name; *cp; )
 			{
-			if (--len == 0)
+			if (len-- == 0)
 				{
 				*p='\0';
 				return(buf);
@@ -787,27 +834,25 @@
 	return(NULL);
 	}
 
-static unsigned long conn_hash(a)
+unsigned long SSL_SESSION_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);
+		(a->session_id[2]<<16L)|(a->session_id[3]<<24L);
 	return(l);
 	}
 
-static int session_cmp(a, b)
+int SSL_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);
+	if (a->ssl_version != b->ssl_version)
+		return(1);
+	if (a->session_id_length != b->session_id_length)
+		return(1);
+	return(memcmp(a->session_id,b->session_id,a->session_id_length));
 	}
 
 SSL_CTX *SSL_CTX_new(meth)
@@ -830,6 +875,9 @@
 
 	ret->cert_store=NULL;
 	ret->session_cache_mode=SSL_SESS_CACHE_SERVER;
+	ret->session_cache_size=SSL_SESSION_CACHE_MAX_SIZE_DEFAULT;
+	ret->session_cache_head=NULL;
+	ret->session_cache_tail=NULL;
 
 	/* We take the system default */
 	ret->session_timeout=meth->get_timeout();
@@ -841,9 +889,12 @@
 	ret->sess_connect=0;
 	ret->sess_connect_good=0;
 	ret->sess_accept=0;
+	ret->sess_accept_renegotiate=0;
+	ret->sess_connect_renegotiate=0;
 	ret->sess_accept_good=0;
 	ret->sess_miss=0;
 	ret->sess_timeout=0;
+	ret->sess_cache_full=0;
 	ret->sess_hit=0;
 	ret->sess_cb_hit=0;
 
@@ -870,7 +921,7 @@
 	ret->default_passwd_callback=NULL;
 	ret->client_cert_cb=NULL;
 
-	ret->sessions=lh_new(conn_hash,session_cmp);
+	ret->sessions=lh_new(SSL_SESSION_hash,SSL_SESSION_cmp);
 	if (ret->sessions == NULL) goto err;
 	ret->cert_store=X509_STORE_new();
 	if (ret->cert_store == NULL) goto err;
@@ -884,9 +935,27 @@
 		goto err2;
 		}
 
+	if ((ret->rsa_md5=EVP_get_digestbyname("ssl2-md5")) == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES);
+		goto err2;
+		}
+	if ((ret->md5=EVP_get_digestbyname("ssl3-md5")) == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES);
+		goto err2;
+		}
+	if ((ret->sha1=EVP_get_digestbyname("ssl3-sha1")) == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES);
+		goto err2;
+		}
+
 	if ((ret->client_CA=sk_new_null()) == NULL)
 		goto err;
 
+	CRYPTO_new_ex_data(ssl_ctx_meth,(char *)ret,&ret->ex_data);
+
 	return(ret);
 err:
 	SSLerr(SSL_F_SSL_CTX_NEW,ERR_R_MALLOC_FAILURE);
@@ -903,6 +972,9 @@
 	if (a == NULL) return;
 
 	i=CRYPTO_add(&a->references,-1,CRYPTO_LOCK_SSL_CTX);
+#ifdef REF_PRINT
+	REF_PRINT("SSL_CTX",a);
+#endif
 	if (i > 0) return;
 #ifdef REF_CHECK
 	if (i < 0)
@@ -911,6 +983,7 @@
 		abort(); /* ok */
 		}
 #endif
+	CRYPTO_free_ex_data(ssl_ctx_meth,(char *)a,&a->ex_data);
 
 	if (a->sessions != NULL)
 		{
@@ -1126,22 +1199,34 @@
 SSL *s;
 int mode;
 	{
+	int i;
+
+	/* If the session_id_length is 0, we are not supposed to cache it,
+	 * and it would be rather hard to do anyway :-) */
+	if (s->session->session_id_length == 0) return;
+
 	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);
+		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));
+	i=s->ctx->session_cache_mode;
+	if ((!(i & SSL_SESS_CACHE_NO_AUTO_CLEAR)) &&
+		((i & mode) == mode))
+		{
+		if (  (((mode & SSL_SESS_CACHE_CLIENT)
+			?s->ctx->sess_connect_good
+			:s->ctx->sess_accept_good) & 0xff) == 0xff)
+			{
+			SSL_CTX_flush_sessions(s->ctx,time(NULL));
+			}
+		}
 	}
 
 SSL_METHOD *SSL_get_ssl_method(s)
@@ -1231,7 +1316,7 @@
 
 	if (i == 0)
 		{
-		if (s->version == 2)
+		if (s->version == SSL2_VERSION)
 			{
 			/* assume it is the socket being closed */
 			return(SSL_ERROR_ZERO_RETURN);
@@ -1239,7 +1324,7 @@
 		else
 			{
 			if ((s->shutdown & SSL_RECEIVED_SHUTDOWN) &&
-				(s->s3->warn_alert == SSL3_AD_CLOSE_NOTIFY))
+				(s->s3->warn_alert == SSL_AD_CLOSE_NOTIFY))
 				return(SSL_ERROR_ZERO_RETURN);
 			}
 		}
@@ -1249,15 +1334,19 @@
 int SSL_do_handshake(s)
 SSL *s;
 	{
+	int ret=1;
+
 	if (s->handshake_func == NULL)
 		{
-		SSLerr(SSL_F_SSL_DO_HANDSHAKE,SSL_R_INTERNAL_ERROR);
+		SSLerr(SSL_F_SSL_DO_HANDSHAKE,SSL_R_CONNECTION_TYPE_NOT_SET);
 		return(-1);
 		}
+	if (s->s3->renegotiate) ssl3_renegotiate_check(s);
 	if (SSL_in_init(s) || SSL_in_before(s))
-		return(s->handshake_func(s));
-	else
-		return(1);
+		{
+		ret=s->handshake_func(s);
+		}
+	return(ret);
 	}
 
 /* For the next 2 functions, SSL_clear() sets shutdown and so
@@ -1299,9 +1388,11 @@
 char *SSL_get_version(s)
 SSL *s;
 	{
-	if (s->version == 3)
+	if (s->version == TLS1_VERSION)
+		return("TLSv1");
+	else if (s->version == SSL3_VERSION)
 		return("SSLv3");
-	else if (s->version == 2)
+	else if (s->version == SSL2_VERSION)
 		return("SSLv2");
 	else
 		return("unknown");
@@ -1327,9 +1418,11 @@
 	SSL_set_info_callback(ret,SSL_get_info_callback(s));
 	
 	ret->debug=s->debug;
+	ret->options=s->options;
 
 	/* copy app data, a little dangerous perhaps */
-	SSL_set_app_data(ret,SSL_get_app_data(s));
+	if (!CRYPTO_dup_ex_data(ssl_meth,&ret->ex_data,&s->ex_data))
+		goto err;
 
 	/* setup rbio, and wbio */
 	if (s->rbio != NULL)
@@ -1341,7 +1434,7 @@
 		{
 		if (s->wbio != s->rbio)
 			{
-			if (!BIO_dup_state(s->wbio,(char *)&ret->rbio))
+			if (!BIO_dup_state(s->wbio,(char *)&ret->wbio))
 				goto err;
 			}
 		else
@@ -1405,6 +1498,7 @@
                 }
 	}
 
+/* Fix this function so that it takes an optional type parameter */
 X509 *SSL_get_certificate(s)
 SSL *s;
 	{
@@ -1414,6 +1508,7 @@
 		return(NULL);
 	}
 
+/* Fix this function so that it takes an optional type parameter */
 EVP_PKEY *SSL_get_privatekey(s)
 SSL *s;
 	{
@@ -1431,3 +1526,196 @@
         return(NULL);
 	}
 
+int ssl_init_wbio_buffer(s,push)
+SSL *s;
+int push;
+	{
+	BIO *bbio;
+
+	if (s->bbio == NULL)
+		{
+		bbio=BIO_new(BIO_f_buffer());
+		if (bbio == NULL) return(0);
+		s->bbio=bbio;
+		}
+	else
+		{
+		bbio=s->bbio;
+		if (s->bbio == s->wbio)
+			s->wbio=BIO_pop(s->wbio);
+		}
+	BIO_reset(bbio);
+/*	if (!BIO_set_write_buffer_size(bbio,16*1024)) */
+	if (!BIO_set_read_buffer_size(bbio,1))
+		{
+		SSLerr(SSL_F_SSL_INIT_WBIO_BUFFER,ERR_R_BUF_LIB);
+		return(0);
+		}
+	if (push)
+		{
+		if (s->wbio != bbio)
+			s->wbio=BIO_push(bbio,s->wbio);
+		}
+	else
+		{
+		if (s->wbio == bbio)
+			s->wbio=BIO_pop(bbio);
+		}
+	return(1);
+	}
+	
+void SSL_CTX_set_quiet_shutdown(ctx,mode)
+SSL_CTX *ctx;
+int mode;
+	{
+	ctx->quiet_shutdown=mode;
+	}
+
+int SSL_CTX_get_quiet_shutdown(ctx)
+SSL_CTX *ctx;
+	{
+	return(ctx->quiet_shutdown);
+	}
+
+void SSL_set_quiet_shutdown(s,mode)
+SSL *s;
+int mode;
+	{
+	s->quiet_shutdown=mode;
+	}
+
+int SSL_get_quiet_shutdown(s)
+SSL *s;
+	{
+	return(s->quiet_shutdown);
+	}
+
+void SSL_set_shutdown(s,mode)
+SSL *s;
+int mode;
+	{
+	s->shutdown=mode;
+	}
+
+int SSL_get_shutdown(s)
+SSL *s;
+	{
+	return(s->shutdown);
+	}
+
+int SSL_version(s)
+SSL *s;
+	{
+	return(s->version);
+	}
+
+SSL_CTX *SSL_get_SSL_CTX(ssl)
+SSL *ssl;
+	{
+	return(ssl->ctx);
+	}
+
+int SSL_CTX_set_default_verify_paths(ctx)
+SSL_CTX *ctx;
+	{
+	return(X509_STORE_set_default_paths(ctx->cert_store));
+	}
+
+int SSL_CTX_load_verify_locations(ctx,CAfile,CApath)
+SSL_CTX *ctx;
+char *CAfile;
+char *CApath;
+	{
+	return(X509_STORE_load_locations(ctx->cert_store,CAfile,CApath));
+	}
+
+void SSL_set_info_callback(ssl,cb)
+SSL *ssl;
+void (*cb)();
+	{
+	ssl->info_callback=cb;
+	}
+
+void (*SSL_get_info_callback(ssl))()
+SSL *ssl;
+	{
+	return(ssl->info_callback);
+	}
+
+int SSL_state(ssl)
+SSL *ssl;
+	{
+	return(ssl->state);
+	}
+
+void SSL_set_verify_result(ssl,arg)
+SSL *ssl;
+long arg;
+	{
+	ssl->verify_result=arg;
+	}
+
+long SSL_get_verify_result(ssl)
+SSL *ssl;
+	{
+	return(ssl->verify_result);
+	}
+
+int SSL_get_ex_new_index(argl,argp,new_func,dup_func,free_func)
+long argl;
+char *argp;
+int (*new_func)();
+int (*dup_func)();
+void (*free_func)();
+        {
+	ssl_meth_num++;
+	return(CRYPTO_get_ex_new_index(ssl_meth_num-1,
+		&ssl_meth,argl,argp,new_func,dup_func,free_func));
+        }
+
+int SSL_set_ex_data(s,idx,arg)
+SSL *s;
+int idx;
+char *arg;
+	{
+	return(CRYPTO_set_ex_data(&s->ex_data,idx,arg));
+	}
+
+char *SSL_get_ex_data(s,idx)
+SSL *s;
+int idx;
+	{
+	return(CRYPTO_get_ex_data(&s->ex_data,idx));
+	}
+
+int SSL_CTX_get_ex_new_index(argl,argp,new_func,dup_func,free_func)
+long argl;
+char *argp;
+int (*new_func)();
+int (*dup_func)();
+void (*free_func)();
+        {
+	ssl_ctx_meth_num++;
+	return(CRYPTO_get_ex_new_index(ssl_ctx_meth_num-1,
+		&ssl_ctx_meth,argl,argp,new_func,dup_func,free_func));
+        }
+
+int SSL_CTX_set_ex_data(s,idx,arg)
+SSL_CTX *s;
+int idx;
+char *arg;
+	{
+	return(CRYPTO_set_ex_data(&s->ex_data,idx,arg));
+	}
+
+char *SSL_CTX_get_ex_data(s,idx)
+SSL_CTX *s;
+int idx;
+	{
+	return(CRYPTO_get_ex_data(&s->ex_data,idx));
+	}
+
+#if defined(_WINDLL) && defined(WIN16)
+#include "../crypto/bio/bss_file.c"
+#endif
+
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index ef3a70e..b295170 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -1,5 +1,5 @@
 /* ssl/ssl_locl.h */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -63,11 +63,7 @@
 #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"
@@ -188,11 +184,10 @@
 #define SSL_eFZA		0x00008000L
 #define SSL_eNULL		0x00010000L
 
-#define SSL_MAC_MASK		0x000e0000L
+#define SSL_MAC_MASK		0x00060000L
 #define SSL_MD5			0x00020000L
-#define SSL_SHA0		0x00040000L
-#define SSL_SHA1		0x00080000L
-#define SSL_SHA			(SSL_SHA0|SSL_SHA1)
+#define SSL_SHA1		0x00040000L
+#define SSL_SHA			(SSL_SHA1)
 
 #define SSL_EXP_MASK		0x00300000L
 #define SSL_EXP			0x00100000L
@@ -298,9 +293,27 @@
 #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];
+/* This is for the SSLv3/TLSv1.0 differences in crypto/hash stuff
+ * It is a bit of a mess of functions, but hell, think of it as
+ * an opaque strucute :-) */
+typedef struct ssl3_enc_method
+	{
+	int (*enc)();
+	int (*mac)();
+	int (*setup_key_block)();
+	int (*generate_master_secret)();
+	int (*change_cipher_state)();
+	int (*final_finish_mac)();
+	int finish_mac_length;
+	int (*cert_verify_mac)();
+	unsigned char client_finished[20];
+	int client_finished_len;
+	unsigned char server_finished[20];
+	int server_finished_len;
+	int (*alert_value)();
+	} SSL3_ENC_METHOD;
 
+extern SSL3_ENC_METHOD ssl3_undef_enc_method;
 extern SSL_CIPHER ssl2_ciphers[];
 extern SSL_CIPHER ssl3_ciphers[];
 
@@ -317,7 +330,7 @@
 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_get_prev_session(SSL *s, unsigned char *session,int len);
 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);
@@ -333,7 +346,7 @@
 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 ssl_verify_alarm_type(long type);
 
 int ssl2_enc_init(SSL *s, int client);
 void ssl2_generate_key_material(SSL *s);
@@ -354,7 +367,7 @@
 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_write(SSL *s, 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);
@@ -365,7 +378,7 @@
 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_get_finished(SSL *s,int state_a,int state_b);
 int ssl3_setup_key_block(SSL *s);
 int ssl3_send_change_cipher_spec(SSL *s,int state_a,int state_b);
 int ssl3_change_cipher_state(SSL *s,int which);
@@ -376,17 +389,18 @@
 	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_send_finished(SSL *s, int a, int b, unsigned char *sender,int slen);
 int ssl3_num_ciphers(void);
 SSL_CIPHER *ssl3_get_cipher(unsigned int u);
 int ssl3_renegotiate(SSL *ssl); 
+int ssl3_renegotiate_check(SSL *ssl); 
 int ssl3_dispatch_alert(SSL *s);
 int ssl3_read_bytes(SSL *s, int type, 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);
+int ssl3_final_finish_mac(SSL *s, EVP_MD_CTX *ctx1,EVP_MD_CTX *ctx2,
+	unsigned char *sender, int slen,unsigned char *p);
+int ssl3_cert_verify_mac(SSL *s, EVP_MD_CTX *in, 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);
@@ -399,7 +413,7 @@
 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_write(SSL *s, 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);
@@ -411,6 +425,28 @@
 int ssl23_read_bytes(SSL *s, int n);
 int ssl23_write_bytes(SSL *s);
 
+int tls1_new(SSL *s);
+void tls1_free(SSL *s);
+void tls1_clear(SSL *s);
+long tls1_ctrl(SSL *s,int cmd, long larg, char *parg);
+SSL_METHOD *tlsv1_base_method(void );
+
+
+int ssl_init_wbio_buffer(SSL *s, int push);
+
+int tls1_change_cipher_state(SSL *s, int which);
+int tls1_setup_key_block(SSL *s);
+int tls1_enc(SSL *s, int snd);
+int tls1_final_finish_mac(SSL *s, EVP_MD_CTX *in1_ctx, EVP_MD_CTX *in2_ctx,
+	unsigned char *str, int slen, unsigned char *p);
+int tls1_cert_verify_mac(SSL *s, EVP_MD_CTX *in, unsigned char *p);
+int tls1_mac(SSL *ssl, unsigned char *md, int snd);
+int tls1_generate_master_secret(SSL *s, unsigned char *out,
+	unsigned char *p, int len);
+int tls1_alert_code(int code);
+int ssl3_alert_code(int code);
+
+
 #else
 
 SSL_METHOD *ssl_bad_method();
@@ -485,9 +521,9 @@
 int ssl3_num_ciphers();
 SSL_CIPHER *ssl3_get_cipher();
 int ssl3_renegotiate();
+int ssl3_renegotiate_check();
 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();
@@ -515,6 +551,8 @@
 int ssl23_read_bytes();
 int ssl23_write_bytes();
 
+int ssl_init_wbio_buffer();
+
 #endif
 
 #endif
diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c
index 3a7b8d3..140475e 100644
--- a/ssl/ssl_rsa.c
+++ b/ssl/ssl_rsa.c
@@ -1,5 +1,5 @@
 /* ssl/ssl_rsa.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -99,6 +99,7 @@
 	return(ssl_set_cert(c,x));
 	}
 
+#ifndef NO_STDIO
 int SSL_use_certificate_file(ssl, file, type)
 SSL *ssl;
 char *file;
@@ -109,11 +110,7 @@
 	int ret=0;
 	X509 *x=NULL;
 
-#ifdef WIN16
-	in=BIO_new(BIO_s_file_internal_w16());
-#else
-	in=BIO_new(BIO_s_file());
-#endif
+	in=BIO_new(BIO_s_file_internal());
 	if (in == NULL)
 		{
 		SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE,ERR_R_BUF_LIB);
@@ -122,7 +119,6 @@
 
 	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;
 		}
@@ -154,6 +150,7 @@
 	if (in != NULL) BIO_free(in);
 	return(ret);
 	}
+#endif
 
 int SSL_use_certificate_ASN1(ssl, len, d)
 SSL *ssl;
@@ -232,7 +229,16 @@
 
 	if (c->pkeys[i].x509 != NULL)
 		{
-		if (!X509_check_private_key(c->pkeys[i].x509,pkey))
+#ifndef NO_RSA
+		/* Don't check the public/private key, this is mostly
+		 * for smart cards. */
+		if ((pkey->type == EVP_PKEY_RSA) &&
+			(RSA_flags(pkey->pkey.rsa) &
+			 RSA_METHOD_FLAG_NO_CHECK))
+			 ok=1;
+		else
+#endif
+			if (!X509_check_private_key(c->pkeys[i].x509,pkey))
 			{
 			if ((i == SSL_PKEY_DH_RSA) || (i == SSL_PKEY_DH_DSA))
 				{
@@ -277,6 +283,7 @@
 	}
 
 #ifndef NO_RSA
+#ifndef NO_STDIO
 int SSL_use_RSAPrivateKey_file(ssl, file, type)
 SSL *ssl;
 char *file;
@@ -286,11 +293,7 @@
 	BIO *in;
 	RSA *rsa=NULL;
 
-#ifdef WIN16
-	in=BIO_new(BIO_s_file_internal_w16());
-#else
-	in=BIO_new(BIO_s_file());
-#endif
+	in=BIO_new(BIO_s_file_internal());
 	if (in == NULL)
 		{
 		SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE,ERR_R_BUF_LIB);
@@ -299,7 +302,6 @@
 
 	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;
 		}
@@ -330,6 +332,7 @@
 	if (in != NULL) BIO_free(in);
 	return(ret);
 	}
+#endif
 
 int SSL_use_RSAPrivateKey_ASN1(ssl,d,len)
 SSL *ssl;
@@ -383,6 +386,7 @@
 	return(ret);
 	}
 
+#ifndef NO_STDIO
 int SSL_use_PrivateKey_file(ssl, file, type)
 SSL *ssl;
 char *file;
@@ -392,11 +396,7 @@
 	BIO *in;
 	EVP_PKEY *pkey=NULL;
 
-#ifdef WIN16
-	in=BIO_new(BIO_s_file_internal_w16());
-#else
-	in=BIO_new(BIO_s_file());
-#endif
+	in=BIO_new(BIO_s_file_internal());
 	if (in == NULL)
 		{
 		SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE,ERR_R_BUF_LIB);
@@ -405,7 +405,6 @@
 
 	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;
 		}
@@ -431,6 +430,7 @@
 	if (in != NULL) BIO_free(in);
 	return(ret);
 	}
+#endif
 
 int SSL_use_PrivateKey_ASN1(type,ssl,d,len)
 int type;
@@ -491,14 +491,14 @@
 	pkey=X509_get_pubkey(x);
 	if (pkey == NULL)
 		{
-		SSLerr(SSL_F_SSL_SET_PKEY,SSL_R_X509_LIB);
+		SSLerr(SSL_F_SSL_SET_CERT,SSL_R_X509_LIB);
 		return(0);
 		}
 
 	i=ssl_cert_type(x,pkey);
 	if (i < 0)
 		{
-		SSLerr(SSL_F_SSL_SET_PKEY,SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+		SSLerr(SSL_F_SSL_SET_CERT,SSL_R_UNKNOWN_CERTIFICATE_TYPE);
 		return(0);
 		}
 
@@ -547,6 +547,7 @@
 	return(1);
 	}
 
+#ifndef NO_STDIO
 int SSL_CTX_use_certificate_file(ctx, file, type)
 SSL_CTX *ctx;
 char *file;
@@ -557,11 +558,7 @@
 	int ret=0;
 	X509 *x=NULL;
 
-#ifdef WIN16
-	in=BIO_new(BIO_s_file_internal_w16());
-#else
-	in=BIO_new(BIO_s_file());
-#endif
+	in=BIO_new(BIO_s_file_internal());
 	if (in == NULL)
 		{
 		SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,ERR_R_BUF_LIB);
@@ -570,7 +567,6 @@
 
 	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;
 		}
@@ -602,6 +598,7 @@
 	if (in != NULL) BIO_free(in);
 	return(ret);
 	}
+#endif
 
 int SSL_CTX_use_certificate_ASN1(ctx, len, d)
 SSL_CTX *ctx;
@@ -663,6 +660,7 @@
 	return(ret);
 	}
 
+#ifndef NO_STDIO
 int SSL_CTX_use_RSAPrivateKey_file(ctx, file, type)
 SSL_CTX *ctx;
 char *file;
@@ -672,11 +670,7 @@
 	BIO *in;
 	RSA *rsa=NULL;
 
-#ifdef WIN16
-	in=BIO_new(BIO_s_file_internal_w16());
-#else
-	in=BIO_new(BIO_s_file());
-#endif
+	in=BIO_new(BIO_s_file_internal());
 	if (in == NULL)
 		{
 		SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE,ERR_R_BUF_LIB);
@@ -685,7 +679,6 @@
 
 	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;
 		}
@@ -716,6 +709,7 @@
 	if (in != NULL) BIO_free(in);
 	return(ret);
 	}
+#endif
 
 int SSL_CTX_use_RSAPrivateKey_ASN1(ctx,d,len)
 SSL_CTX *ctx;
@@ -766,6 +760,7 @@
 	return(ssl_set_pkey(c,pkey));
 	}
 
+#ifndef NO_STDIO
 int SSL_CTX_use_PrivateKey_file(ctx, file, type)
 SSL_CTX *ctx;
 char *file;
@@ -775,11 +770,7 @@
 	BIO *in;
 	EVP_PKEY *pkey=NULL;
 
-#ifdef WIN16
-	in=BIO_new(BIO_s_file_internal_w16());
-#else
-	in=BIO_new(BIO_s_file());
-#endif
+	in=BIO_new(BIO_s_file_internal());
 	if (in == NULL)
 		{
 		SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE,ERR_R_BUF_LIB);
@@ -788,7 +779,6 @@
 
 	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;
 		}
@@ -814,6 +804,7 @@
 	if (in != NULL) BIO_free(in);
 	return(ret);
 	}
+#endif
 
 int SSL_CTX_use_PrivateKey_ASN1(type,ctx,d,len)
 int type;
diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c
index af65c65..8212600 100644
--- a/ssl/ssl_sess.c
+++ b/ssl/ssl_sess.c
@@ -1,5 +1,5 @@
 /* ssl/ssl_sess.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -61,6 +61,51 @@
 #include "rand.h"
 #include "ssl_locl.h"
 
+#ifndef NOPROTO
+static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s);
+static void SSL_SESSION_list_add(SSL_CTX *ctx,SSL_SESSION *s);
+#else
+static void SSL_SESSION_list_remove();
+static void SSL_SESSION_list_add();
+#endif
+
+static ssl_session_num=0;
+static STACK *ssl_session_meth=NULL;
+
+SSL_SESSION *SSL_get_session(ssl)
+SSL *ssl;
+	{
+	return(ssl->session);
+	}
+
+int SSL_SESSION_get_ex_new_index(argl,argp,new_func,dup_func,free_func)
+long argl;
+char *argp;
+int (*new_func)();
+int (*dup_func)();
+void (*free_func)();
+        {
+        ssl_session_num++;
+        return(CRYPTO_get_ex_new_index(ssl_session_num-1,
+		&ssl_session_meth,
+                argl,argp,new_func,dup_func,free_func));
+        }
+
+int SSL_SESSION_set_ex_data(s,idx,arg)
+SSL_SESSION *s;
+int idx;
+char *arg;
+	{
+	return(CRYPTO_set_ex_data(&s->ex_data,idx,arg));
+	}
+
+char *SSL_SESSION_get_ex_data(s,idx)
+SSL_SESSION *s;
+int idx;
+	{
+	return(CRYPTO_get_ex_data(&s->ex_data,idx));
+	}
+
 SSL_SESSION *SSL_SESSION_new()
 	{
 	SSL_SESSION *ss;
@@ -76,6 +121,9 @@
 	ss->references=1;
 	ss->timeout=60*5+4; /* 5 minute timeout by default */
 	ss->time=time(NULL);
+	ss->prev=NULL;
+	ss->next=NULL;
+	CRYPTO_new_ex_data(ssl_session_meth,(char *)ss,&ss->ex_data);
 	return(ss);
 	}
 
@@ -101,12 +149,17 @@
 		{
 		if (s->version == SSL2_CLIENT_VERSION)
 			{
-			ss->ssl_version=2;
+			ss->ssl_version=SSL2_VERSION;
 			ss->session_id_length=SSL2_SSL_SESSION_ID_LENGTH;
 			}
-		else if (s->version == SSL3_VERSION_MAJOR)
+		else if (s->version == SSL3_VERSION)
 			{
-			ss->ssl_version=3;
+			ss->ssl_version=SSL3_VERSION;
+			ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
+			}
+		else if (s->version == TLS1_VERSION)
+			{
+			ss->ssl_version=TLS1_VERSION;
 			ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
 			}
 		else
@@ -140,23 +193,26 @@
 	return(1);
 	}
 
-int ssl_get_prev_session(s, len, session)
+int ssl_get_prev_session(s,session_id,len)
 SSL *s;
+unsigned char *session_id;
 int len;
-unsigned char *session;
 	{
-	SSL_SESSION *ret,data;
+	SSL_SESSION *ret=NULL,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);;
+	memcpy(data.session_id,session_id,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 (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP))
+		{
+		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)
 		{
@@ -165,7 +221,7 @@
 		s->ctx->sess_miss++;
 		ret=NULL;
 		if ((s->ctx->get_session_cb != NULL) &&
-			((ret=s->ctx->get_session_cb(s,session,len,&copy))
+			((ret=s->ctx->get_session_cb(s,session_id,len,&copy))
 				!= NULL))
 			{
 			s->ctx->sess_cb_hit++;
@@ -188,7 +244,7 @@
 		p=buf;
 		l=ret->cipher_id;
 		l2n(l,p);
-		if (ret->ssl_version == 3)
+		if ((ret->ssl_version>>8) == SSL3_VERSION_MAJOR)
 			ret->cipher=ssl_get_cipher_by_char(s,&(buf[2]));
 		else 
 			ret->cipher=ssl_get_cipher_by_char(s,&(buf[1]));
@@ -227,6 +283,7 @@
 SSL_CTX *ctx;
 SSL_SESSION *c;
 	{
+	int ret=0;
 	SSL_SESSION *s;
 
 	/* conn_init(); */
@@ -234,7 +291,10 @@
 
 	CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
 	s=(SSL_SESSION *)lh_insert(ctx->sessions,(char *)c);
-	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
+	
+	/* Put on the end of the queue unless it is already in the cache */
+	if (s == NULL)
+		SSL_SESSION_list_add(ctx,c);
 
 	/* If the same session if is being 're-added', Free the old
 	 * one when the last person stops using it.
@@ -243,10 +303,27 @@
 	if (s != NULL)
 		{
 		SSL_SESSION_free(s);
-		return(0);
+		ret=0;
 		}
 	else
-		return(1);
+		{
+		ret=1;
+
+		if (SSL_CTX_sess_get_cache_size(ctx) > 0)
+			{
+			while (SSL_CTX_sess_number(ctx) >
+				SSL_CTX_sess_get_cache_size(ctx))
+				{
+				if (!SSL_CTX_remove_session(ctx,
+					ctx->session_cache_tail))
+					break;
+				else
+					ctx->sess_cache_full++;
+				}
+			}
+		}
+	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
+	return(ret);
 	}
 
 int SSL_CTX_remove_session(ctx,c)
@@ -256,11 +333,15 @@
 	SSL_SESSION *r;
 	int ret=0;
 
-	if ((c->session_id_length != 0) && (c != NULL))
+	if ((c != NULL) && (c->session_id_length != 0))
 		{
 		CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
 		r=(SSL_SESSION *)lh_delete(ctx->sessions,(char *)c);
-		if (r != NULL) ret=1;
+		if (r != NULL)
+			{
+			ret=1;
+			SSL_SESSION_list_remove(ctx,c);
+			}
 
 		CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
 
@@ -268,7 +349,7 @@
 			{
 			r->not_resumable=1;
 			if (ctx->remove_session_cb != NULL)
-				ctx->remove_session_cb(ctx,c);
+				ctx->remove_session_cb(ctx,r);
 			SSL_SESSION_free(r);
 			}
 		}
@@ -283,6 +364,9 @@
 	int i;
 
 	i=CRYPTO_add(&ss->references,-1,CRYPTO_LOCK_SSL_SESSION);
+#ifdef REF_PRINT
+	REF_PRINT("SSL_SESSION",ss);
+#endif
 	if (i > 0) return;
 #ifdef REF_CHECK
 	if (i < 0)
@@ -292,6 +376,8 @@
 		}
 #endif
 
+	CRYPTO_free_ex_data(ssl_session_meth,(char *)ss,&ss->ex_data);
+
 	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);
@@ -335,10 +421,18 @@
 		/* CRYPTO_w_unlock(CRYPTO_LOCK_SSL);*/
 		ret=1;
 		}
+	else
+		{
+		if (s->session != NULL)
+			{
+			SSL_SESSION_free(s->session);
+			s->session=NULL;
+			}
+		}
 	return(ret);
 	}
 
-long SSL_set_timeout(s,t)
+long SSL_SESSION_set_timeout(s,t)
 SSL_SESSION *s;
 long t;
 	{
@@ -347,21 +441,21 @@
 	return(1);
 	}
 
-long SSL_get_timeout(s)
+long SSL_SESSION_get_timeout(s)
 SSL_SESSION *s;
 	{
 	if (s == NULL) return(0);
 	return(s->timeout);
 	}
 
-long SSL_get_time(s)
+long SSL_SESSION_get_time(s)
 SSL_SESSION *s;
 	{
 	if (s == NULL) return(0);
 	return(s->time);
 	}
 
-long SSL_set_time(s,t)
+long SSL_SESSION_set_time(s,t)
 SSL_SESSION *s;
 long t;
 	{
@@ -383,7 +477,10 @@
 	{
 	if ((p->time == 0) || (p->time > (s->time+s->timeout))) /* timeout */
 		{
+		/* The reason we don't call SSL_CTX_remove_session() is to
+		 * save on locking overhead */
 		lh_delete(p->cache,(char *)s);
+		SSL_SESSION_list_remove(p->ctx,s);
 		s->not_resumable=1;
 		if (p->ctx->remove_session_cb != NULL)
 			p->ctx->remove_session_cb(p->ctx,s);
@@ -423,3 +520,63 @@
 	else
 		return(0);
 	}
+
+/* locked by SSL_CTX in the calling function */
+static void SSL_SESSION_list_remove(ctx,s)
+SSL_CTX *ctx;
+SSL_SESSION *s;
+	{
+	if ((s->next == NULL) || (s->prev == NULL)) return;
+
+	if (s->next == (SSL_SESSION *)&(ctx->session_cache_tail))
+		{ /* last element in list */
+		if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head))
+			{ /* only one element in list */
+			ctx->session_cache_head=NULL;
+			ctx->session_cache_tail=NULL;
+			}
+		else
+			{
+			ctx->session_cache_tail=s->prev;
+			s->prev->next=(SSL_SESSION *)&(ctx->session_cache_tail);
+			}
+		}
+	else
+		{
+		if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head))
+			{ /* first element in list */
+			ctx->session_cache_head=s->next;
+			s->next->prev=(SSL_SESSION *)&(ctx->session_cache_head);
+			}
+		else
+			{ /* middle of list */
+			s->next->prev=s->prev;
+			s->prev->next=s->next;
+			}
+		}
+	s->prev=s->next=NULL;
+	}
+
+static void SSL_SESSION_list_add(ctx,s)
+SSL_CTX *ctx;
+SSL_SESSION *s;
+	{
+	if ((s->next != NULL) && (s->prev != NULL))
+		SSL_SESSION_list_remove(ctx,s);
+
+	if (ctx->session_cache_head == NULL)
+		{
+		ctx->session_cache_head=s;
+		ctx->session_cache_tail=s;
+		s->prev=(SSL_SESSION *)&(ctx->session_cache_head);
+		s->next=(SSL_SESSION *)&(ctx->session_cache_tail);
+		}
+	else
+		{
+		s->next=ctx->session_cache_head;
+		s->next->prev=s;
+		s->prev=(SSL_SESSION *)&(ctx->session_cache_head);
+		ctx->session_cache_head=s;
+		}
+	}
+
diff --git a/ssl/ssl_stat.c b/ssl/ssl_stat.c
index 328ccc9..a1daf25 100644
--- a/ssl/ssl_stat.c
+++ b/ssl/ssl_stat.c
@@ -1,5 +1,5 @@
 /* ssl/ssl_stat.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -207,6 +207,7 @@
 		{
 	case SSL_ST_READ_HEADER: str="read header"; break;
 	case SSL_ST_READ_BODY: str="read body"; break;
+	case SSL_ST_READ_DONE: str="read done"; break;
 	default: str="unknown"; break;
 		}
 	return(str);
diff --git a/ssl/ssl_task.c b/ssl/ssl_task.c
index c27ce91..ab72166 100644
--- a/ssl/ssl_task.c
+++ b/ssl/ssl_task.c
@@ -1,5 +1,5 @@
 /* ssl/ssl_task.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
diff --git a/ssl/ssl_txt.c b/ssl/ssl_txt.c
index b9cb9ef..ce60e1a 100644
--- a/ssl/ssl_txt.c
+++ b/ssl/ssl_txt.c
@@ -1,5 +1,5 @@
 /* ssl/ssl_txt.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -60,7 +60,7 @@
 #include "buffer.h"
 #include "ssl_locl.h"
 
-#ifndef WIN16
+#ifndef NO_FP_API
 int SSL_SESSION_print_fp(fp, x)
 FILE *fp;
 SSL_SESSION *x;
@@ -68,7 +68,7 @@
         BIO *b;
         int ret;
 
-        if ((b=BIO_new(BIO_s_file())) == NULL)
+        if ((b=BIO_new(BIO_s_file_internal())) == NULL)
 		{
 		SSLerr(SSL_F_SSL_SESSION_PRINT_FP,ERR_R_BUF_LIB);
                 return(0);
@@ -85,11 +85,30 @@
 SSL_SESSION *x;
 	{
 	int i;
-	char str[128];
+	char str[128],*s;
 
 	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 (x->ssl_version == SSL2_VERSION)
+		s="SSLv2";
+	else if (x->ssl_version == SSL3_VERSION)
+		s="SSLv3";
+	else if (x->ssl_version == TLS1_VERSION)
+		s="TLSv1";
+	else
+		s="unknown";
+	sprintf(str,"    Protocol  : %s\n",s);
+	if (BIO_puts(bp,str) <= 0) goto err;
+
+	if (x->cipher == NULL)
+		{
+		if (((x->cipher_id) & 0xff000000) == 0x02000000)
+			sprintf(str,"    Cipher    : %06lX\n",x->cipher_id&0xffffff);
+		else
+			sprintf(str,"    Cipher    : %04lX\n",x->cipher_id&0xffff);
+		}
+	else
+		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++)
diff --git a/ssl/ssltest.c b/ssl/ssltest.c
index b8d657f..f9dca4e 100644
--- a/ssl/ssltest.c
+++ b/ssl/ssltest.c
@@ -1,5 +1,5 @@
 /* ssl/ssltest.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -60,18 +60,13 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
-#ifdef WIN16
-#define APPS_WIN16
-#endif
+#include "e_os.h"
 #include "bio.h"
 #include "crypto.h"
-#include "../e_os.h"
 #include "x509.h"
 #include "ssl.h"
 #include "err.h"
-
-#ifdef WIN16
-#define APPS_WIN16
+#ifdef WINDOWS
 #include "../crypto/bio/bss_file.c"
 #endif
 
@@ -80,24 +75,31 @@
 
 #ifndef NOPROTO
 int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx);
+static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int export);
+#ifndef NO_DSA
 static DH *get_dh512(void);
+#endif
 #else
 int MS_CALLBACK verify_callback();
+static RSA MS_CALLBACK *tmp_rsa_cb();
+#ifndef NO_DSA
 static DH *get_dh512();
 #endif
+#endif
 
 BIO *bio_err=NULL;
 BIO *bio_stdout=NULL;
 
 static char *cipher=NULL;
 int verbose=0;
+int debug=0;
 #ifdef FIONBIO
 static int s_nbio=0;
 #endif
 
 
 #ifndef  NOPROTO
-int doit(SSL_CTX *s_ctx,SSL_CTX *c_ctx);
+int doit(SSL *s_ssl,SSL *c_ssl,long bytes);
 #else
 int doit();
 #endif
@@ -109,14 +111,25 @@
 	fprintf(stderr," -server_auth  - check server certificate\n");
 	fprintf(stderr," -client_auth  - do client authentication\n");
 	fprintf(stderr," -v            - more output\n");
+	fprintf(stderr," -d            - debug output\n");
+	fprintf(stderr," -reuse        - use session-id reuse\n");
+	fprintf(stderr," -num <val>    - number of connections to perform\n");
+	fprintf(stderr," -bytes <val>  - number of bytes to swap between client/server\n");
 #ifndef NO_SSL2
 	fprintf(stderr," -ssl2         - use SSLv2\n");
 #endif
 #ifndef NO_SSL3
 	fprintf(stderr," -ssl3         - use SSLv3\n");
 #endif
+#ifndef NO_TLS1
+	fprintf(stderr," -tls1         - use TLSv1\n");
+#endif
 	fprintf(stderr," -CApath arg   - PEM format directory of CA's\n");
 	fprintf(stderr," -CAfile arg   - PEM format file of CA's\n");
+	fprintf(stderr," -cert arg     - Certificate file\n");
+	fprintf(stderr," -s_cert arg   - Just the server certificate file\n");
+	fprintf(stderr," -c_cert arg   - Just the client certificate file\n");
+	fprintf(stderr," -cipher arg   - The cipher list\n");
 	}
 
 int main(argc, argv)
@@ -125,15 +138,21 @@
 	{
 	char *CApath=NULL,*CAfile=NULL;
 	int badop=0;
-	int ssl2=0,ssl3=0,ret=1;
+	int tls1=0,ssl2=0,ssl3=0,ret=1;
 	int client_auth=0;
-	int server_auth=0;
+	int server_auth=0,i;
 	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;
+	SSL *c_ssl,*s_ssl;
+	int number=1,reuse=0;
+	long bytes=1L;
+	SSL_CIPHER *ciph;
+#ifndef NO_DH
 	DH *dh;
+#endif
 
 	bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
 	bio_stdout=BIO_new_fp(stdout,BIO_NOCLOSE);
@@ -151,10 +170,31 @@
 			client_auth=1;
 		else if	(strcmp(*argv,"-v") == 0)
 			verbose=1;
+		else if	(strcmp(*argv,"-d") == 0)
+			debug=1;
+		else if	(strcmp(*argv,"-reuse") == 0)
+			reuse=1;
 		else if	(strcmp(*argv,"-ssl2") == 0)
 			ssl2=1;
+		else if	(strcmp(*argv,"-tls1") == 0)
+			tls1=1;
 		else if	(strcmp(*argv,"-ssl3") == 0)
 			ssl3=1;
+		else if	(strncmp(*argv,"-num",4) == 0)
+			{
+			if (--argc < 1) goto bad;
+			number= atoi(*(++argv));
+			if (number == 0) number=1;
+			}
+		else if	(strcmp(*argv,"-bytes") == 0)
+			{
+			if (--argc < 1) goto bad;
+			bytes= atol(*(++argv));
+			if (bytes == 0L) bytes=1L;
+			i=strlen(argv[0]);
+			if (argv[0][i-1] == 'k') bytes*=1024L;
+			if (argv[0][i-1] == 'm') bytes*=1024L*1024L;
+			}
 		else if	(strcmp(*argv,"-cert") == 0)
 			{
 			if (--argc < 1) goto bad;
@@ -210,6 +250,9 @@
 	if (ssl2)
 		meth=SSLv2_method();
 	else 
+	if (tls1)
+		meth=TLSv1_method();
+	else
 	if (ssl3)
 		meth=SSLv3_method();
 	else
@@ -239,7 +282,11 @@
 #ifndef NO_DH
 	dh=get_dh512();
 	SSL_CTX_set_tmp_dh(s_ctx,dh);
-        DH_free(dh);
+	DH_free(dh);
+#endif
+
+#ifndef NO_RSA
+	SSL_CTX_set_tmp_rsa_callback(s_ctx,tmp_rsa_cb);
 #endif
 
 	if (!SSL_CTX_use_certificate_file(s_ctx,server_cert,SSL_FILETYPE_PEM))
@@ -266,9 +313,9 @@
 		(!SSL_CTX_load_verify_locations(c_ctx,CAfile,CApath)) ||
 		(!SSL_CTX_set_default_verify_paths(c_ctx)))
 		{
-		fprintf(stderr,"SSL_load_verify_locations\n");
+		/* fprintf(stderr,"SSL_load_verify_locations\n"); */
 		ERR_print_errors(bio_err);
-		goto end;
+		/* goto end; */
 		}
 
 	if (client_auth)
@@ -285,7 +332,29 @@
 			verify_callback);
 		}
 
-	ret=doit(s_ctx,c_ctx);
+	c_ssl=SSL_new(c_ctx);
+	s_ssl=SSL_new(s_ctx);
+
+	for (i=0; i<number; i++)
+		{
+		if (!reuse) SSL_set_session(c_ssl,NULL);
+		ret=doit(s_ssl,c_ssl,bytes);
+		}
+
+	if (!verbose)
+		{
+		ciph=SSL_get_current_cipher(c_ssl);
+		fprintf(stdout,"Protocol %s, cipher %s, %s\n",
+			SSL_get_version(c_ssl),
+			SSL_CIPHER_get_version(ciph),
+			SSL_CIPHER_get_name(ciph));
+		}
+	if ((number > 1) || (bytes > 1L))
+		printf("%d handshakes of %ld bytes done\n",number,bytes);
+
+	SSL_free(s_ssl);
+	SSL_free(c_ssl);
+
 end:
 	if (s_ctx != NULL) SSL_CTX_free(s_ctx);
 	if (c_ctx != NULL) SSL_CTX_free(c_ctx);
@@ -303,33 +372,26 @@
 #define C_DONE	1
 #define S_DONE	2
 
-int doit(s_ctx,c_ctx)
-SSL_CTX *s_ctx,*c_ctx;
+int doit(s_ssl,c_ssl,count)
+SSL *s_ssl,*c_ssl;
+long count;
 	{
-	static char cbuf[200],sbuf[200];
+	MS_STATIC char cbuf[1024*8],sbuf[1024*8];
+	long cw_num=count,cr_num=count;
+	long sw_num=count,sr_num=count;
 	int ret=1;
-	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 i,j;
 	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))
@@ -348,11 +410,11 @@
 
 	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);
+	BIO_set_ssl(c_bio,c_ssl,BIO_NOCLOSE);
 
 	SSL_set_accept_state(s_ssl);
 	SSL_set_bio(s_ssl,c_to_s,s_to_c);
-	BIO_set_ssl(s_bio,s_ssl,BIO_CLOSE);
+	BIO_set_ssl(s_bio,s_ssl,BIO_NOCLOSE);
 
 	c_r=0; s_r=1;
 	c_w=1; s_w=0;
@@ -372,26 +434,26 @@
 		i=(int)BIO_pending(c_bio);
 		if ((i && c_r) || c_w) do_client=1;
 
-		if (do_server && verbose)
+		if (do_server && debug)
 			{
 			if (SSL_in_init(s_ssl))
 				printf("server waiting in SSL_accept - %s\n",
 					SSL_state_string_long(s_ssl));
-			else if (s_write)
+/*			else if (s_write)
 				printf("server:SSL_write()\n");
-			else 
-				printf("server:SSL_read()\n");
+			else
+				printf("server:SSL_read()\n"); */
 			}
 
-		if (do_client && verbose)
+		if (do_client && debug)
 			{
 			if (SSL_in_init(c_ssl))
 				printf("client waiting in SSL_connect - %s\n",
 					SSL_state_string_long(c_ssl));
-			else if (c_write)
+/*			else if (c_write)
 				printf("client:SSL_write()\n");
 			else
-				printf("client:SSL_read()\n");
+				printf("client:SSL_read()\n"); */
 			}
 
 		if (!do_client && !do_server)
@@ -404,7 +466,9 @@
 			{
 			if (c_write)
 				{
-				i=BIO_write(c_bio,"hello from client\n",18);
+				j=(cw_num > (long)sizeof(cbuf))
+					?sizeof(cbuf):(int)cw_num;
+				i=BIO_write(c_bio,cbuf,j);
 				if (i < 0)
 					{
 					c_r=0;
@@ -430,13 +494,17 @@
 					}
 				else
 					{
+					if (debug)
+						printf("client wrote %d\n",i);
 					/* ok */
+					s_r=1;
 					c_write=0;
+					cw_num-=i;
 					}
 				}
 			else
 				{
-				i=BIO_read(c_bio,cbuf,100);
+				i=BIO_read(c_bio,cbuf,sizeof(cbuf));
 				if (i < 0)
 					{
 					c_r=0;
@@ -462,10 +530,20 @@
 					}
 				else
 					{
-					done|=C_DONE;
-					fprintf(stdout,"CLIENT:from server:");
-					fwrite(cbuf,1,i,stdout);
-					fflush(stdout);
+					if (debug)
+						printf("client read %d\n",i);
+					cr_num-=i;
+					if (sw_num > 0)
+						{
+						s_write=1;
+						s_w=1;
+						}
+					if (cr_num <= 0)
+						{
+						s_write=1;
+						s_w=1;
+						done=S_DONE|C_DONE;
+						}
 					}
 				}
 			}
@@ -474,7 +552,7 @@
 			{
 			if (!s_write)
 				{
-				i=BIO_read(s_bio,sbuf,100);
+				i=BIO_read(s_bio,sbuf,sizeof(cbuf));
 				if (i < 0)
 					{
 					s_r=0;
@@ -501,16 +579,27 @@
 					}
 				else
 					{
-					s_write=1;
-					s_w=1;
-					fprintf(stdout,"SERVER:from client:");
-					fwrite(sbuf,1,i,stdout);
-					fflush(stdout);
+					if (debug)
+						printf("server read %d\n",i);
+					sr_num-=i;
+					if (cw_num > 0)
+						{
+						c_write=1;
+						c_w=1;
+						}
+					if (sr_num <= 0)
+						{
+						s_write=1;
+						s_w=1;
+						c_write=0;
+						}
 					}
 				}
 			else
 				{
-				i=BIO_write(s_bio,"hello from server\n",18);
+				j=(sw_num > (long)sizeof(sbuf))?
+					sizeof(sbuf):(int)sw_num;
+				i=BIO_write(s_bio,sbuf,j);
 				if (i < 0)
 					{
 					s_r=0;
@@ -537,9 +626,13 @@
 					}
 				else
 					{
+					if (debug)
+						printf("server wrote %d\n",i);
+					sw_num-=i;
 					s_write=0;
-					s_r=1;
-					done|=S_DONE;
+					c_r=1;
+					if (sw_num <= 0)
+						done|=S_DONE;
 					}
 				}
 			}
@@ -548,8 +641,11 @@
 		}
 
 	ciph=SSL_get_current_cipher(c_ssl);
-	fprintf(stdout,"DONE, used %s, %s\n",SSL_CIPHER_get_version(ciph),
-		SSL_CIPHER_get_name(ciph));
+	if (verbose)
+		fprintf(stdout,"DONE, protocol %s, cipher %s, %s\n",
+			SSL_get_version(c_ssl),
+			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
@@ -572,8 +668,8 @@
 
 	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);
+	if (c_bio != NULL) BIO_free_all(c_bio);
+	if (s_bio != NULL) BIO_free_all(s_bio);
 	return(ret);
 	}
 
@@ -607,6 +703,7 @@
 	return(ok);
 	}
 
+#ifndef NO_DH
 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,
@@ -623,13 +720,32 @@
 	{
 	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);
 	}
+#endif
+
+static RSA MS_CALLBACK *tmp_rsa_cb(s,export)
+SSL *s;
+int export;
+	{
+	static RSA *rsa_tmp=NULL;
+
+	if (rsa_tmp == NULL)
+		{
+		BIO_printf(bio_err,"Generating temp (512 bit) RSA key...");
+		BIO_flush(bio_err);
+#ifndef NO_RSA
+		rsa_tmp=RSA_generate_key(512,RSA_F4,NULL,NULL);
+#endif
+		BIO_printf(bio_err,"\n");
+		BIO_flush(bio_err);
+		}
+	return(rsa_tmp);
+	}
+
 
diff --git a/ssl/t1_clnt.c b/ssl/t1_clnt.c
new file mode 100644
index 0000000..986d243
--- /dev/null
+++ b/ssl/t1_clnt.c
@@ -0,0 +1,90 @@
+/* ssl/t1_clnt.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include "buffer.h"
+#include "rand.h"
+#include "objects.h"
+#include "evp.h"
+#include "ssl_locl.h"
+
+static SSL_METHOD *tls1_get_client_method(ver)
+int ver;
+	{
+	if (ver == TLS1_VERSION)
+		return(TLSv1_client_method());
+	else
+		return(NULL);
+	}
+
+SSL_METHOD *TLSv1_client_method()
+	{
+	static int init=1;
+	static SSL_METHOD TLSv1_client_data;
+
+	if (init)
+		{
+		init=0;
+		memcpy((char *)&TLSv1_client_data,(char *)tlsv1_base_method(),
+			sizeof(SSL_METHOD));
+		TLSv1_client_data.ssl_connect=ssl3_connect;
+		TLSv1_client_data.get_ssl_method=tls1_get_client_method;
+		}
+	return(&TLSv1_client_data);
+	}
+
diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c
new file mode 100644
index 0000000..fbdd3bf
--- /dev/null
+++ b/ssl/t1_enc.c
@@ -0,0 +1,635 @@
+/* ssl/t1_enc.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include "evp.h"
+#include "hmac.h"
+#include "ssl_locl.h"
+
+static void tls1_P_hash(md,sec,sec_len,seed,seed_len,out,olen)
+EVP_MD *md;
+unsigned char *sec;
+int sec_len;
+unsigned char *seed;
+int seed_len;
+unsigned char *out;
+int olen;
+	{
+	int chunk,n;
+	unsigned int j;
+	HMAC_CTX ctx;
+	HMAC_CTX ctx_tmp;
+	unsigned char A1[HMAC_MAX_MD_CBLOCK];
+	unsigned int A1_len;
+	
+	chunk=EVP_MD_size(md);
+
+	HMAC_Init(&ctx,sec,sec_len,md);
+	HMAC_Update(&ctx,seed,seed_len);
+	HMAC_Final(&ctx,A1,&A1_len);
+
+	n=0;
+	for (;;)
+		{
+		HMAC_Init(&ctx,NULL,0,NULL); /* re-init */
+		HMAC_Update(&ctx,A1,A1_len);
+		memcpy(&ctx_tmp,&ctx,sizeof(ctx)); /* Copy for A2 */ /* not needed for last one */
+		HMAC_Update(&ctx,seed,seed_len);
+
+		if (olen > chunk)
+			{
+			HMAC_Final(&ctx,out,&j);
+			out+=j;
+			olen-=j;
+			HMAC_Final(&ctx_tmp,A1,&A1_len); /* calc the next A1 value */
+			}
+		else	/* last one */
+			{
+			HMAC_Final(&ctx,A1,&A1_len);
+			memcpy(out,A1,olen);
+			break;
+			}
+		}
+	HMAC_cleanup(&ctx);
+	HMAC_cleanup(&ctx_tmp);
+	memset(A1,0,sizeof(A1));
+	}
+
+static void tls1_PRF(md5,sha1,label,label_len,sec,slen,out1,out2,olen)
+EVP_MD *md5;
+EVP_MD *sha1;
+unsigned char *label;
+int label_len;
+unsigned char *sec;
+int slen;
+unsigned char *out1;
+unsigned char *out2;
+int olen;
+	{
+	int len,i;
+	unsigned char *S1,*S2;
+
+	len=slen/2;
+	S1=sec;
+	S2= &(sec[len]);
+	len+=(slen&1); /* add for odd, make longer */
+
+	
+	tls1_P_hash(md5 ,S1,len,label,label_len,out1,olen);
+	tls1_P_hash(sha1,S2,len,label,label_len,out2,olen);
+
+	for (i=0; i<olen; i++)
+		out1[i]^=out2[i];
+	}
+
+static void tls1_generate_key_block(s,km,tmp,num)
+SSL *s;
+unsigned char *km,*tmp;
+int num;
+	{
+	unsigned char *p;
+	unsigned char buf[SSL3_RANDOM_SIZE*2+
+		TLS_MD_MAX_CONST_SIZE];
+	p=buf;
+
+	memcpy(p,TLS_MD_KEY_EXPANSION_CONST,
+		TLS_MD_KEY_EXPANSION_CONST_SIZE);
+	p+=TLS_MD_KEY_EXPANSION_CONST_SIZE;
+	memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE);
+	p+=SSL3_RANDOM_SIZE;
+	memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE);
+	p+=SSL3_RANDOM_SIZE;
+
+	tls1_PRF(s->ctx->md5,s->ctx->sha1,buf,p-buf,
+		s->session->master_key,s->session->master_key_length,
+		km,tmp,num);
+	}
+
+int tls1_change_cipher_state(s,which)
+SSL *s;
+int which;
+	{
+	unsigned char *p,*key_block,*mac_secret;
+	unsigned char *exp_label,buf[TLS_MD_MAX_CONST_SIZE+
+		SSL3_RANDOM_SIZE*2];
+	unsigned char tmp1[EVP_MAX_KEY_LENGTH];
+	unsigned char tmp2[EVP_MAX_KEY_LENGTH];
+	unsigned char iv1[EVP_MAX_IV_LENGTH*2];
+	unsigned char iv2[EVP_MAX_IV_LENGTH*2];
+	unsigned char *ms,*key,*iv,*er1,*er2;
+	int client_write;
+	EVP_CIPHER_CTX *dd;
+	EVP_CIPHER *c;
+	SSL_COMPRESSION *comp;
+	EVP_MD *m;
+	int exp,n,i,j,k,exp_label_len;
+
+	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]);
+		}
+
+	EVP_CIPHER_CTX_init(dd);
+
+	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);
+	er1= &(s->s3->client_random[0]);
+	er2= &(s->s3->server_random[0]);
+	if (	(which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) ||
+		(which == SSL3_CHANGE_CIPHER_SERVER_READ))
+		{
+		ms=  &(p[ 0]); n=i+i;
+		key= &(p[ n]); n+=j+j;
+		iv=  &(p[ n]); n+=k+k;
+		exp_label=(unsigned char *)TLS_MD_CLIENT_WRITE_KEY_CONST;
+		exp_label_len=TLS_MD_CLIENT_WRITE_KEY_CONST_SIZE;
+		client_write=1;
+		}
+	else
+		{
+		n=i;
+		ms=  &(p[ n]); n+=i+j;
+		key= &(p[ n]); n+=j+k;
+		iv=  &(p[ n]); n+=k;
+		exp_label=(unsigned char *)TLS_MD_SERVER_WRITE_KEY_CONST;
+		exp_label_len=TLS_MD_SERVER_WRITE_KEY_CONST_SIZE;
+		client_write=0;
+		}
+
+	if (n > s->s3->tmp.key_block_length)
+		{
+		SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_INTERNAL_ERROR);
+		goto err2;
+		}
+
+	memcpy(mac_secret,ms,i);
+#ifdef TLS_DEBUG
+printf("which = %04X\nmac key=",which);
+{ int z; for (z=0; z<i; z++) printf("%02X%c",ms[z],((z+1)%16)?' ':'\n'); }
+#endif
+	if (exp)
+		{
+		/* In here I set both the read and write key/iv to the
+		 * same value since only the correct one will be used :-).
+		 */
+		p=buf;
+		memcpy(p,exp_label,exp_label_len);
+		p+=exp_label_len;
+		memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE);
+		p+=SSL3_RANDOM_SIZE;
+		memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE);
+		p+=SSL3_RANDOM_SIZE;
+		tls1_PRF(s->ctx->md5,s->ctx->sha1,buf,p-buf,key,j,
+			tmp1,tmp2,EVP_CIPHER_key_length(c));
+		key=tmp1;
+
+		if (k > 0)
+			{
+			p=buf;
+			memcpy(p,TLS_MD_IV_BLOCK_CONST,
+				TLS_MD_IV_BLOCK_CONST_SIZE);
+			p+=TLS_MD_IV_BLOCK_CONST_SIZE;
+			memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE);
+			p+=SSL3_RANDOM_SIZE;
+			memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE);
+			p+=SSL3_RANDOM_SIZE;
+			tls1_PRF(s->ctx->md5,s->ctx->sha1,
+				buf,p-buf,"",0,iv1,iv2,k*2);
+			if (client_write)
+				iv=iv1;
+			else
+				iv= &(iv1[k]);
+			}
+		}
+
+	s->session->key_arg_length=0;
+
+	EVP_CipherInit(dd,c,key,iv,(which & SSL3_CC_WRITE));
+#ifdef TLS_DEBUG
+printf("which = %04X\nkey=",which);
+{ int z; for (z=0; z<EVP_CIPHER_key_length(c); z++) printf("%02X%c",key[z],((z+1)%16)?' ':'\n'); }
+printf("\niv=");
+{ int z; for (z=0; z<k; z++) printf("%02X%c",iv[z],((z+1)%16)?' ':'\n'); }
+printf("\n");
+#endif
+
+	memset(tmp1,0,sizeof(tmp1));
+	memset(tmp2,0,sizeof(tmp1));
+	memset(iv1,0,sizeof(iv1));
+	memset(iv2,0,sizeof(iv2));
+	return(1);
+err:
+	SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,ERR_R_MALLOC_FAILURE);
+err2:
+	return(0);
+	}
+
+int tls1_setup_key_block(s)
+SSL *s;
+	{
+	unsigned char *p1,*p2;
+	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_TLS1_SETUP_KEY_BLOCK,SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
+		return(0);
+		}
+
+	s->s3->tmp.new_sym_enc=c;
+	s->s3->tmp.new_hash=hash;
+
+	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 ((p1=(unsigned char *)Malloc(num)) == NULL)
+		goto err;
+	if ((p2=(unsigned char *)Malloc(num)) == NULL)
+		goto err;
+
+	s->s3->tmp.key_block_length=num;
+	s->s3->tmp.key_block=p1;
+
+
+#ifdef TLS_DEBUG
+printf("client random\n");
+{ int z; for (z=0; z<SSL3_RANDOM_SIZE; z++) printf("%02X%c",s->s3->client_random[z],((z+1)%16)?' ':'\n'); }
+printf("server random\n");
+{ int z; for (z=0; z<SSL3_RANDOM_SIZE; z++) printf("%02X%c",s->s3->server_random[z],((z+1)%16)?' ':'\n'); }
+printf("pre-master\n");
+{ int z; for (z=0; z<s->session->master_key_length; z++) printf("%02X%c",s->session->master_key[z],((z+1)%16)?' ':'\n'); }
+#endif
+	tls1_generate_key_block(s,p1,p2,num);
+	memset(p2,0,num);
+	Free(p2);
+#ifdef TLS_DEBUG
+printf("\nkey block\n");
+{ int z; for (z=0; z<num; z++) printf("%02X%c",p1[z],((z+1)%16)?' ':'\n'); }
+#endif
+
+	return(1);
+err:
+	SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK,ERR_R_MALLOC_FAILURE);
+	return(0);
+	}
+
+int tls1_enc(s,send)
+SSL *s;
+int send;
+	{
+	SSL3_RECORD *rec;
+	EVP_CIPHER_CTX *ds;
+	unsigned long l;
+	int bs,i,ii,j,k,n=0;
+	EVP_CIPHER *enc;
+	SSL_COMPRESSION *comp;
+
+	if (send)
+		{
+		if (s->write_hash != NULL)
+			n=EVP_MD_size(s->write_hash);
+		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
+		{
+		if (s->read_hash != NULL)
+			n=EVP_MD_size(s->read_hash);
+		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);
+
+		if ((bs != 1) && send)
+			{
+			i=bs-((int)l%bs);
+
+			/* Add weird padding of upto 256 bytes */
+
+			/* we need to add 'i' padding bytes of value j */
+			j=i-1;
+			if (s->options & SSL_OP_TLS_BLOCK_PADDING_BUG)
+				{
+				if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG)
+					j++;
+				}
+			for (k=(int)l; k<(int)(l+i); k++)
+				rec->input[k]=j;
+			l+=i;
+			rec->length+=i;
+			}
+
+		EVP_Cipher(ds,rec->data,rec->input,l);
+
+		if ((bs != 1) && !send)
+			{
+			ii=i=rec->data[l-1];
+			i++;
+			if (s->options&SSL_OP_TLS_BLOCK_PADDING_BUG)
+				{
+				/* First packet is even in size, so check */
+				if ((memcmp(s->s3->read_sequence,
+					"\0\0\0\0\0\0\0\0",8) == 0) && !(ii & 1))
+					s->s3->flags|=TLS1_FLAGS_TLS_PADDING_BUG;
+				if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG)
+					i--;
+				}
+			if (i > (int)rec->length)
+				{
+				SSLerr(SSL_F_TLS1_ENC,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG);
+				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECRYPTION_FAILED);
+				return(0);
+				}
+			for (j=(int)(l-i); j<(int)l; j++)
+				{
+				if (rec->data[j] != ii)
+					{
+					SSLerr(SSL_F_TLS1_ENC,SSL_R_DECRYPTION_FAILED);
+					ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECRYPTION_FAILED);
+					return(0);
+					}
+				}
+			rec->length-=i;
+			}
+		}
+	return(1);
+	}
+
+int tls1_cert_verify_mac(s,in_ctx,out)
+SSL *s;
+EVP_MD_CTX *in_ctx;
+unsigned char *out;
+	{
+	unsigned int ret;
+	EVP_MD_CTX ctx;
+
+	memcpy(&ctx,in_ctx,sizeof(EVP_MD_CTX));
+	EVP_DigestFinal(&ctx,out,&ret);
+	return((int)ret);
+	}
+
+int tls1_final_finish_mac(s,in1_ctx,in2_ctx,str,slen,out)
+SSL *s;
+EVP_MD_CTX *in1_ctx,*in2_ctx;
+unsigned char *str;
+int slen;
+unsigned char *out;
+	{
+	unsigned int i;
+	EVP_MD_CTX ctx;
+	unsigned char buf[TLS_MD_MAX_CONST_SIZE+MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH];
+	unsigned char *q,buf2[12];
+
+	q=buf;
+	memcpy(q,str,slen);
+	q+=slen;
+
+	memcpy(&ctx,in1_ctx,sizeof(EVP_MD_CTX));
+	EVP_DigestFinal(&ctx,q,&i);
+	q+=i;
+	memcpy(&ctx,in2_ctx,sizeof(EVP_MD_CTX));
+	EVP_DigestFinal(&ctx,q,&i);
+	q+=i;
+
+	tls1_PRF(s->ctx->md5,s->ctx->sha1,buf,q-buf,
+		s->session->master_key,s->session->master_key_length,
+		out,buf2,12);
+	memset(&ctx,0,sizeof(EVP_MD_CTX));
+
+	return((int)12);
+	}
+
+int tls1_mac(ssl,md,send)
+SSL *ssl;
+unsigned char *md;
+int send;
+	{
+	SSL3_RECORD *rec;
+	unsigned char *mac_sec,*seq;
+	EVP_MD *hash;
+	unsigned int md_size;
+	int i;
+	HMAC_CTX hmac;
+	unsigned char buf[5]; 
+
+	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);
+
+	buf[0]=rec->type;
+	buf[1]=TLS1_VERSION_MAJOR;
+	buf[2]=TLS1_VERSION_MINOR;
+	buf[3]=rec->length>>8;
+	buf[4]=rec->length&0xff;
+
+	/* I should fix this up TLS TLS TLS TLS TLS XXXXXXXX */
+	HMAC_Init(&hmac,mac_sec,EVP_MD_size(hash),hash);
+	HMAC_Update(&hmac,seq,8);
+	HMAC_Update(&hmac,buf,5);
+	HMAC_Update(&hmac,rec->input,rec->length);
+	HMAC_Final(&hmac,md,&md_size);
+
+#ifdef TLS_DEBUG
+printf("sec=");
+{int z; for (z=0; z<md_size; z++) printf("%02X ",mac_sec[z]); printf("\n"); }
+printf("seq=");
+{int z; for (z=0; z<8; z++) printf("%02X ",seq[z]); printf("\n"); }
+printf("buf=");
+{int z; for (z=0; z<5; z++) printf("%02X ",buf[z]); printf("\n"); }
+printf("rec=");
+{int z; for (z=0; z<rec->length; z++) printf("%02X ",buf[z]); printf("\n"); }
+#endif
+
+	for (i=7; i>=0; i--)
+		if (++seq[i]) break; 
+
+#ifdef TLS_DEBUG
+{int z; for (z=0; z<md_size; z++) printf("%02X ",md[z]); printf("\n"); }
+#endif
+	return(md_size);
+	}
+
+int tls1_generate_master_secret(s,out,p,len)
+SSL *s;
+unsigned char *out;
+unsigned char *p;
+int len;
+	{
+	unsigned char buf[SSL3_RANDOM_SIZE*2+TLS_MD_MASTER_SECRET_CONST_SIZE];
+	unsigned char buff[SSL_MAX_MASTER_KEY_LENGTH];
+
+	/* Setup the stuff to munge */
+	memcpy(buf,TLS_MD_MASTER_SECRET_CONST,
+		TLS_MD_MASTER_SECRET_CONST_SIZE);
+	memcpy(&(buf[TLS_MD_MASTER_SECRET_CONST_SIZE]),
+		s->s3->client_random,SSL3_RANDOM_SIZE);
+	memcpy(&(buf[SSL3_RANDOM_SIZE+TLS_MD_MASTER_SECRET_CONST_SIZE]),
+		s->s3->server_random,SSL3_RANDOM_SIZE);
+	tls1_PRF(s->ctx->md5,s->ctx->sha1,
+		buf,TLS_MD_MASTER_SECRET_CONST_SIZE+SSL3_RANDOM_SIZE*2,p,len,
+		s->session->master_key,buff,SSL3_MASTER_SECRET_SIZE);
+	return(SSL3_MASTER_SECRET_SIZE);
+	}
+
+int tls1_alert_code(code)
+int code;
+	{
+	switch (code)
+		{
+	case SSL_AD_CLOSE_NOTIFY:	return(SSL3_AD_CLOSE_NOTIFY);
+	case SSL_AD_UNEXPECTED_MESSAGE:	return(SSL3_AD_UNEXPECTED_MESSAGE);
+	case SSL_AD_BAD_RECORD_MAC:	return(SSL3_AD_BAD_RECORD_MAC);
+	case SSL_AD_DECRYPTION_FAILED:	return(TLS1_AD_DECRYPTION_FAILED);
+	case SSL_AD_RECORD_OVERFLOW:	return(TLS1_AD_RECORD_OVERFLOW);
+	case SSL_AD_DECOMPRESSION_FAILURE:return(SSL3_AD_DECOMPRESSION_FAILURE);
+	case SSL_AD_HANDSHAKE_FAILURE:	return(SSL3_AD_HANDSHAKE_FAILURE);
+	case SSL_AD_NO_CERTIFICATE:	return(-1);
+	case SSL_AD_BAD_CERTIFICATE:	return(SSL3_AD_BAD_CERTIFICATE);
+	case SSL_AD_UNSUPPORTED_CERTIFICATE:return(SSL3_AD_UNSUPPORTED_CERTIFICATE);
+	case SSL_AD_CERTIFICATE_REVOKED:return(SSL3_AD_CERTIFICATE_REVOKED);
+	case SSL_AD_CERTIFICATE_EXPIRED:return(SSL3_AD_CERTIFICATE_EXPIRED);
+	case SSL_AD_CERTIFICATE_UNKNOWN:return(SSL3_AD_CERTIFICATE_UNKNOWN);
+	case SSL_AD_ILLEGAL_PARAMETER:	return(SSL3_AD_ILLEGAL_PARAMETER);
+	case SSL_AD_UNKNOWN_CA:		return(TLS1_AD_UNKNOWN_CA);
+	case SSL_AD_ACCESS_DENIED:	return(TLS1_AD_ACCESS_DENIED);
+	case SSL_AD_DECODE_ERROR:	return(TLS1_AD_DECODE_ERROR);
+	case SSL_AD_DECRYPT_ERROR:	return(TLS1_AD_DECRYPT_ERROR);
+	case SSL_AD_EXPORT_RESTRICION:	return(TLS1_AD_EXPORT_RESTRICION);
+	case SSL_AD_PROTOCOL_VERSION:	return(TLS1_AD_PROTOCOL_VERSION);
+	case SSL_AD_INSUFFICIENT_SECURITY:return(TLS1_AD_INSUFFICIENT_SECURITY);
+	case SSL_AD_INTERNAL_ERROR:	return(TLS1_AD_INTERNAL_ERROR);
+	case SSL_AD_USER_CANCLED:	return(TLS1_AD_USER_CANCLED);
+	case SSL_AD_NO_RENEGOTIATION:	return(TLS1_AD_NO_RENEGOTIATION);
+	default:			return(-1);
+		}
+	}
+
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
new file mode 100644
index 0000000..f9fbfa4
--- /dev/null
+++ b/ssl/t1_lib.c
@@ -0,0 +1,151 @@
+/* ssl/t1_lib.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include "objects.h"
+#include "ssl_locl.h"
+
+char *tls1_version_str="TLSv1 part of SSLeay 0.9.0b 29-Jun-1998";
+
+#ifndef NO_PROTO
+static long tls1_default_timeout(void);
+#else
+static long tls1_default_timeout();
+#endif
+
+static SSL3_ENC_METHOD TLSv1_enc_data={
+	tls1_enc,
+	tls1_mac,
+	tls1_setup_key_block,
+	tls1_generate_master_secret,
+	tls1_change_cipher_state,
+	tls1_final_finish_mac,
+	TLS1_FINISH_MAC_LENGTH,
+	tls1_cert_verify_mac,
+	TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE,
+	TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE,
+	tls1_alert_code,
+	};
+
+static SSL_METHOD TLSv1_data= {
+	TLS1_VERSION,
+	tls1_new,
+	tls1_clear,
+	tls1_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,
+	tls1_default_timeout,
+	&TLSv1_enc_data,
+	};
+
+static long tls1_default_timeout()
+	{
+	/* 2 hours, the 24 hours mentioned in the TLSv1 spec
+	 * is way too long for http, the cache would over fill */
+	return(60*60*2);
+	}
+
+SSL_METHOD *tlsv1_base_method()
+	{
+	return(&TLSv1_data);
+	}
+
+int tls1_new(s)
+SSL *s;
+	{
+	if (!ssl3_new(s)) return(0);
+	s->method->ssl_clear(s);
+	return(1);
+	}
+
+void tls1_free(s)
+SSL *s;
+	{
+	ssl3_free(s);
+	}
+
+void tls1_clear(s)
+SSL *s;
+	{
+	ssl3_clear(s);
+	s->version=TLS1_VERSION;
+	}
+
+#if 0
+long tls1_ctrl(s,cmd,larg,parg)
+SSL *s;
+int cmd;
+long larg;
+char *parg;
+	{
+	return(0);
+	}
+#endif
diff --git a/ssl/t1_meth.c b/ssl/t1_meth.c
new file mode 100644
index 0000000..512c207
--- /dev/null
+++ b/ssl/t1_meth.c
@@ -0,0 +1,88 @@
+/* ssl/t1_meth.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include "objects.h"
+#include "ssl_locl.h"
+
+static SSL_METHOD *tls1_get_method(ver)
+int ver;
+	{
+	if (ver == TLS1_VERSION)
+		return(TLSv1_method());
+	else
+		return(NULL);
+	}
+
+SSL_METHOD *TLSv1_method()
+	{
+	static int init=1;
+	static SSL_METHOD TLSv1_data;
+
+	if (init)
+		{
+		init=0;
+		memcpy((char *)&TLSv1_data,(char *)tlsv1_base_method(),
+			sizeof(SSL_METHOD));
+		TLSv1_data.ssl_connect=ssl3_connect;
+		TLSv1_data.ssl_accept=ssl3_accept;
+		TLSv1_data.get_ssl_method=tls1_get_method;
+		}
+	return(&TLSv1_data);
+	}
+
diff --git a/ssl/t1_srvr.c b/ssl/t1_srvr.c
new file mode 100644
index 0000000..8cf0add
--- /dev/null
+++ b/ssl/t1_srvr.c
@@ -0,0 +1,91 @@
+/* ssl/t1_srvr.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include "buffer.h"
+#include "rand.h"
+#include "objects.h"
+#include "evp.h"
+#include "x509.h"
+#include "ssl_locl.h"
+
+static SSL_METHOD *tls1_get_server_method(ver)
+int ver;
+	{
+	if (ver == TLS1_VERSION)
+		return(TLSv1_server_method());
+	else
+		return(NULL);
+	}
+
+SSL_METHOD *TLSv1_server_method()
+	{
+	static int init=1;
+	static SSL_METHOD TLSv1_server_data;
+
+	if (init)
+		{
+		init=0;
+		memcpy((char *)&TLSv1_server_data,(char *)tlsv1_base_method(),
+			sizeof(SSL_METHOD));
+		TLSv1_server_data.ssl_accept=ssl3_accept;
+		TLSv1_server_data.get_ssl_method=tls1_get_server_method;
+		}
+	return(&TLSv1_server_data);
+	}
+
diff --git a/ssl/tls1.h b/ssl/tls1.h
new file mode 100644
index 0000000..6097861
--- /dev/null
+++ b/ssl/tls1.h
@@ -0,0 +1,115 @@
+/* ssl/tls1.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_TLS1_H 
+#define HEADER_TLS1_H 
+
+#include "buffer.h"
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#define TLS1_VERSION			0x0301
+#define TLS1_VERSION_MAJOR		0x03
+#define TLS1_VERSION_MINOR		0x01
+
+#define TLS1_AD_DECRYPTION_FAILED	21
+#define TLS1_AD_RECORD_OVERFLOW		22
+#define TLS1_AD_UNKNOWN_CA		48	/* fatal */
+#define TLS1_AD_ACCESS_DENIED		49	/* fatal */
+#define TLS1_AD_DECODE_ERROR		50	/* fatal */
+#define TLS1_AD_DECRYPT_ERROR		51
+#define TLS1_AD_EXPORT_RESTRICION	60	/* fatal */
+#define TLS1_AD_PROTOCOL_VERSION	70	/* fatal */
+#define TLS1_AD_INSUFFICIENT_SECURITY	71	/* fatal */
+#define TLS1_AD_INTERNAL_ERROR		80	/* fatal */
+#define TLS1_AD_USER_CANCLED		90
+#define TLS1_AD_NO_RENEGOTIATION	100
+
+#define TLS_CT_RSA_SIGN			1
+#define TLS_CT_DSS_SIGN			2
+#define TLS_CT_RSA_FIXED_DH		3
+#define TLS_CT_DSS_FIXED_DH		4
+#define TLS_CT_NUMBER			4
+
+#define TLS1_FINISH_MAC_LENGTH		12
+
+#define TLS_MD_MAX_CONST_SIZE			20
+#define TLS_MD_CLIENT_FINISH_CONST		"client finished"
+#define TLS_MD_CLIENT_FINISH_CONST_SIZE		15
+#define TLS_MD_SERVER_FINISH_CONST		"server finished"
+#define TLS_MD_SERVER_FINISH_CONST_SIZE		15
+#define TLS_MD_SERVER_WRITE_KEY_CONST		"server write key"
+#define TLS_MD_SERVER_WRITE_KEY_CONST_SIZE	16
+#define TLS_MD_KEY_EXPANSION_CONST		"key expansion"
+#define TLS_MD_KEY_EXPANSION_CONST_SIZE		13
+#define TLS_MD_CLIENT_WRITE_KEY_CONST		"client write key"
+#define TLS_MD_CLIENT_WRITE_KEY_CONST_SIZE	16
+#define TLS_MD_SERVER_WRITE_KEY_CONST		"server write key"
+#define TLS_MD_SERVER_WRITE_KEY_CONST_SIZE	16
+#define TLS_MD_IV_BLOCK_CONST			"IV block"
+#define TLS_MD_IV_BLOCK_CONST_SIZE		8
+#define TLS_MD_MASTER_SECRET_CONST		"master secret"
+#define TLS_MD_MASTER_SECRET_CONST_SIZE		13
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
+