Import of old SSLeay release: SSLeay 0.9.1b (unreleased)
diff --git a/crypto/Makefile.ssl b/crypto/Makefile.ssl
index efdbba3..ab821e2 100644
--- a/crypto/Makefile.ssl
+++ b/crypto/Makefile.ssl
@@ -22,7 +22,7 @@
 PEX_LIBS=
 EX_LIBS=
  
-CFLAGS= $(INCLUDE) $(CFLAG) -DCFLAGS=" \"$(CC) $(CFLAG)\" "
+CFLAGS= $(INCLUDE) $(CFLAG) -DCFLAGS=" \"$(CC) $(CFLAG)\" " -DPLATFORM=" \"$(PLATFORM)\" "
 
 ERR=crypto
 ERRC=cpt_err
@@ -34,17 +34,17 @@
 	bn rsa dsa dh \
 	buffer bio stack lhash rand err objects \
 	evp pem x509 \
-	asn1 conf txt_db pkcs7
+	asn1 conf txt_db pkcs7 comp
 
 GENERAL=Makefile README
 
 LIB= $(TOP)/libcrypto.a
-LIBSRC=	cryptlib.c mem.c cversion.c ex_data.c $(ERRC).c
-LIBOBJ= cryptlib.o mem.o cversion.o ex_data.o $(ERRC).o
+LIBSRC=	cryptlib.c mem.c cversion.c ex_data.c tmdiff.c $(ERRC).c
+LIBOBJ= cryptlib.o mem.o cversion.o ex_data.o tmdiff.o $(ERRC).o
 
 SRC= $(LIBSRC)
 
-EXHEADER= crypto.h cryptall.h
+EXHEADER= crypto.h cryptall.h tmdiff.h
 HEADER=	cryptlib.h date.h $(EXHEADER)
 
 ALL=    $(GENERAL) $(SRC) $(HEADER)
@@ -61,7 +61,7 @@
 	@for i in $(SDIRS) ;\
 	do \
 	(cd $$i; echo "making all in $$i..."; \
-	$(MAKE) CC='$(CC)' INCLUDES='${INCLUDES}' CFLAG='${CFLAG}' INSTALLTOP='${INSTALLTOP}' PEX_LIBS='${PEX_LIBS}' EX_LIBS='${EX_LIBS}' BN_MULW='${BN_MULW}' DES_ENC='${DES_ENC}' SHA1_ASM_OBJ='${SHA1_ASM_OBJ}' MD5_ASM_OBJ='${MD5_ASM_OBJ}' RMD160_ASM_OBJ='${RMD160_ASM_OBJ}' BF_ENC='${BF_ENC}' CAST_ENC='${CAST_ENC}' RC4_ENC='${RC4_ENC}' RC5_ENC='${RC5_ENC}' AR='${AR}' all ); \
+	$(MAKE) CC='$(CC)' INCLUDES='${INCLUDES}' CFLAG='${CFLAG}' INSTALLTOP='${INSTALLTOP}' PEX_LIBS='${PEX_LIBS}' EX_LIBS='${EX_LIBS}' BN_ASM='${BN_ASM}' DES_ENC='${DES_ENC}' SHA1_ASM_OBJ='${SHA1_ASM_OBJ}' MD5_ASM_OBJ='${MD5_ASM_OBJ}' RMD160_ASM_OBJ='${RMD160_ASM_OBJ}' BF_ENC='${BF_ENC}' CAST_ENC='${CAST_ENC}' RC4_ENC='${RC4_ENC}' RC5_ENC='${RC5_ENC}' AR='${AR}' all ); \
 	done;
 
 files:
diff --git a/crypto/asn1/Makefile.ssl b/crypto/asn1/Makefile.ssl
index 30751bd..1e9951f 100644
--- a/crypto/asn1/Makefile.ssl
+++ b/crypto/asn1/Makefile.ssl
@@ -23,7 +23,7 @@
 
 LIB=$(TOP)/libcrypto.a
 LIBSRC=	a_object.c a_bitstr.c a_utctm.c a_int.c a_octet.c a_print.c \
-	a_type.c a_set.c a_dup.c a_d2i_fp.c a_i2d_fp.c \
+	a_type.c a_set.c a_dup.c a_d2i_fp.c a_i2d_fp.c a_bmp.c \
 	a_sign.c a_digest.c a_verify.c \
 	x_algor.c x_val.c x_pubkey.c x_sig.c x_req.c x_attrib.c \
 	x_name.c x_cinf.c x_x509.c x_crl.c x_info.c x_spki.c \
@@ -38,7 +38,7 @@
 	asn1_par.c asn1_lib.c $(ERRC).c a_meth.c a_bytes.c \
 	evp_asn1.c
 LIBOBJ= a_object.o a_bitstr.o a_utctm.o a_int.o a_octet.o a_print.o \
-	a_type.o a_set.o a_dup.o a_d2i_fp.o a_i2d_fp.o \
+	a_type.o a_set.o a_dup.o a_d2i_fp.o a_i2d_fp.o a_bmp.o \
 	a_sign.o a_digest.o a_verify.o \
 	x_algor.o x_val.o x_pubkey.o x_sig.o x_req.o x_attrib.o \
 	x_name.o x_cinf.o x_x509.o x_crl.o x_info.o x_spki.o \
diff --git a/crypto/asn1/a_bitstr.c b/crypto/asn1/a_bitstr.c
index 2c10120..275de43 100644
--- a/crypto/asn1/a_bitstr.c
+++ b/crypto/asn1/a_bitstr.c
@@ -68,27 +68,50 @@
 ASN1_BIT_STRING *a;
 unsigned char **pp;
 	{
-	int ret,j,r,bits;
+	int ret,j,r,bits,len;
 	unsigned char *p,*d;
 
 	if (a == NULL) return(0);
 
-	/* our bit strings are always a multiple of 8 :-) */
-	bits=0;
-	ret=1+a->length;
+	len=a->length;
+
+	if (len > 0)
+		{
+		if (a->flags & ASN1_STRING_FLAG_BITS_LEFT)
+			{
+			bits=(int)a->flags&0x07;
+			}
+		else
+			{
+			for ( ; len > 0; len--)
+				{
+				if (a->data[len-1]) break;
+				}
+			j=a->data[len-1];
+			if      (j & 0x01) bits=0;
+			else if (j & 0x02) bits=1;
+			else if (j & 0x04) bits=2;
+			else if (j & 0x08) bits=3;
+			else if (j & 0x10) bits=4;
+			else if (j & 0x20) bits=5;
+			else if (j & 0x40) bits=6;
+			else if (j & 0x80) bits=7;
+			else bits=0; /* should not happen */
+			}
+		}
+	else
+		bits=0;
+	ret=1+len;
 	r=ASN1_object_size(0,ret,V_ASN1_BIT_STRING);
 	if (pp == NULL) return(r);
 	p= *pp;
 
 	ASN1_put_object(&p,0,ret,V_ASN1_BIT_STRING,V_ASN1_UNIVERSAL);
-	if (bits == 0)
-		j=0;
-	else	j=8-bits;
-	*(p++)=(unsigned char)j;
+	*(p++)=(unsigned char)bits;
 	d=a->data;
-	memcpy(p,d,a->length);
-	p+=a->length;
-	if (a->length > 0) p[-1]&=(0xff<<j);
+	memcpy(p,d,len);
+	p+=len;
+	if (len > 0) p[-1]&=(0xff<<bits);
 	*pp=p;
 	return(r);
 	}
@@ -127,6 +150,12 @@
 	if (len < 1) { i=ASN1_R_STRING_TOO_SHORT; goto err; }
 
 	i= *(p++);
+	/* We do this to preserve the settings.  If we modify
+	 * the settings, via the _set_bit function, we will recalculate
+	 * on output */
+	ret->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear */
+	ret->flags|=(ASN1_STRING_FLAG_BITS_LEFT|(i&0x07)); /* set */
+
 	if (len-- > 1) /* using one because of the bits left byte */
 		{
 		s=(unsigned char *)Malloc((int)len);
@@ -170,6 +199,8 @@
 	v=1<<(7-(n&0x07));
 	iv= ~v;
 
+	a->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear, set on write */
+
 	if (a == NULL) return(0);
 	if ((a->length < (w+1)) || (a->data == NULL))
 		{
diff --git a/crypto/asn1/a_bitstr.orig.c b/crypto/asn1/a_bitstr.orig.c
new file mode 100644
index 0000000..871e057
--- /dev/null
+++ b/crypto/asn1/a_bitstr.orig.c
@@ -0,0 +1,236 @@
+/* crypto/asn1/a_bitstr.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 "cryptlib.h"
+#include "asn1.h"
+
+/* ASN1err(ASN1_F_ASN1_STRING_NEW,ASN1_R_STRING_TOO_SHORT);
+ * ASN1err(ASN1_F_D2I_ASN1_BIT_STRING,ASN1_R_EXPECTING_A_BIT_STRING);
+ */
+
+int i2d_ASN1_BIT_STRING(a,pp)
+ASN1_BIT_STRING *a;
+unsigned char **pp;
+	{
+	int ret,i,j,r,bits,len;
+	unsigned char *p,*d;
+
+	if (a == NULL) return(0);
+
+	len=a->length;
+
+	if ((len > 0)
+		{
+		if (a->flags & ASN1_FG_BITS_LEFT))
+			{
+			bits=a->flags&0x07;
+			}
+		else
+			{
+			for ( ; len > 0; len--)
+				{
+				if (a->data[len-1]) break;
+				}
+			j=a->data[len-1];
+			if      (j & 0x80) bits=1;
+			else if (j & 0x40) bits=2;
+			else if (j & 0x20) bits=3;
+			else if (j & 0x10) bits=4;
+			else if (j & 0x08) bits=5;
+			else if (j & 0x04) bits=6;
+			else if (j & 0x02) bits=7;
+			else if (j & 0x01) bits=8;
+			else bits=0;
+			}
+		}
+	else
+		bits=0;
+	ret=1+len;
+	r=ASN1_object_size(0,ret,V_ASN1_BIT_STRING);
+	if (pp == NULL) return(r);
+	p= *pp;
+
+	ASN1_put_object(&p,0,ret,V_ASN1_BIT_STRING,V_ASN1_UNIVERSAL);
+	if (bits == 0)
+		j=0;
+	else	j=8-bits;
+	*(p++)=(unsigned char)j;
+	d=a->data;
+	memcpy(p,d,len);
+	p+=len;
+	if (len > 0) p[-1]&=(0xff<<j);
+	*pp=p;
+	return(r);
+	}
+
+ASN1_BIT_STRING *d2i_ASN1_BIT_STRING(a, pp, length)
+ASN1_BIT_STRING **a;
+unsigned char **pp;
+long length;
+	{
+	ASN1_BIT_STRING *ret=NULL;
+	unsigned char *p,*s;
+	long len;
+	int inf,tag,xclass;
+	int i;
+
+	if ((a == NULL) || ((*a) == NULL))
+		{
+		if ((ret=ASN1_BIT_STRING_new()) == NULL) return(NULL);
+		}
+	else
+		ret=(*a);
+
+	p= *pp;
+	inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
+	if (inf & 0x80)
+		{
+		i=ASN1_R_BAD_OBJECT_HEADER;
+		goto err;
+		}
+
+	if (tag != V_ASN1_BIT_STRING)
+		{
+		i=ASN1_R_EXPECTING_A_BIT_STRING;
+		goto err;
+		}
+	if (len < 1) { i=ASN1_R_STRING_TOO_SHORT; goto err; }
+
+	i= *(p++);
+	ret->flag&= ~(ASN1_FG_BITS_LEFT|0x07); /* clear */
+	if (i > 0)
+		ret->flag|=(ASN1_FG_BITS_LEFT|(i&0x07)); /* set */
+
+	if (len-- > 1) /* using one because of the bits left byte */
+		{
+		s=(unsigned char *)Malloc((int)len);
+		if (s == NULL)
+			{
+			i=ERR_R_MALLOC_FAILURE;
+			goto err;
+			}
+		memcpy(s,p,(int)len);
+		s[len-1]&=(0xff<<i);
+		p+=len;
+		}
+	else
+		s=NULL;
+
+	ret->length=(int)len;
+	if (ret->data != NULL) Free((char *)ret->data);
+	ret->data=s;
+	ret->type=V_ASN1_BIT_STRING;
+	if (a != NULL) (*a)=ret;
+	*pp=p;
+	return(ret);
+err:
+	ASN1err(ASN1_F_D2I_ASN1_BIT_STRING,i);
+	if ((ret != NULL) && ((a == NULL) || (*a != ret)))
+		ASN1_BIT_STRING_free(ret);
+	return(NULL);
+	}
+
+/* These next 2 functions from Goetz Babin-Ebell <babinebell@trustcenter.de>
+ */
+int ASN1_BIT_STRING_set_bit(a,n,value)
+ASN1_BIT_STRING *a;
+int n;
+int value;
+	{
+	int w,v,iv;
+	unsigned char *c;
+
+	w=n/8;
+	v=1<<(7-(n&0x07));
+	iv= ~v;
+
+	a->flag&= ~(ASN1_FG_BITS_LEFT|0x07); /* clear, set on write */
+
+	if (a == NULL) return(0);
+	if ((a->length < (w+1)) || (a->data == NULL))
+		{
+		if (!value) return(1); /* Don't need to set */
+		if (a->data == NULL)
+			c=(unsigned char *)Malloc(w+1);
+		else
+			c=(unsigned char *)Realloc(a->data,w+1);
+		if (c == NULL) return(0);
+		a->data=c;
+		a->length=w+1;
+		c[w]=0;
+		}
+	a->data[w]=((a->data[w])&iv)|v;
+	while ((a->length > 0) && (a->data[a->length-1] == 0))
+		a->length--;
+	return(1);
+	}
+
+int ASN1_BIT_STRING_get_bit(a,n)
+ASN1_BIT_STRING *a;
+int n;
+	{
+	int w,v;
+
+	w=n/8;
+	v=1<<(7-(n&0x07));
+	if ((a == NULL) || (a->length < (w+1)) || (a->data == NULL))
+		return(0);
+	return((a->data[w]&v) != 0);
+	}
+
diff --git a/crypto/asn1/a_bmp.c b/crypto/asn1/a_bmp.c
index 774502b..76a6f1c 100644
--- a/crypto/asn1/a_bmp.c
+++ b/crypto/asn1/a_bmp.c
@@ -79,10 +79,10 @@
 	ASN1_BMPSTRING *ret=NULL;
 
 	ret=(ASN1_BMPSTRING *)d2i_ASN1_bytes((ASN1_STRING **)a,
-	pp,length,V_ASN1_BMPSTRING,V_ASN1_UNIVERSAL);
+		pp,length,V_ASN1_BMPSTRING,V_ASN1_UNIVERSAL);
 	if (ret == NULL)
 		{
-		ASN1err(ASN1_F_D2I_ASN1_BMPSTRING,ASN1_R_ERROR_STACK);
+		ASN1err(ASN1_F_D2I_ASN1_BMPSTRING,ERR_R_NESTED_ASN1_ERROR);
 		return(NULL);
 		}
 	return(ret);
diff --git a/crypto/asn1/a_bytes.c b/crypto/asn1/a_bytes.c
index 14168d6..6bfa983 100644
--- a/crypto/asn1/a_bytes.c
+++ b/crypto/asn1/a_bytes.c
@@ -60,9 +60,7 @@
 #include "cryptlib.h"
 #include "asn1_mac.h"
 
-/* ASN1err(ASN1_F_ASN1_TYPE_NEW,ASN1_R_ERROR_STACK);
- * ASN1err(ASN1_F_D2I_ASN1_TYPE_BYTES,ASN1_R_ERROR_STACK);
- * ASN1err(ASN1_F_D2I_ASN1_TYPE_BYTES,ASN1_R_WRONG_TYPE);
+/* ASN1err(ASN1_F_D2I_ASN1_TYPE_BYTES,ASN1_R_WRONG_TYPE);
  * ASN1err(ASN1_F_ASN1_COLLATE_PRIMATIVE,ASN1_R_WRONG_TAG);
  */
 
diff --git a/crypto/asn1/a_hdr.c b/crypto/asn1/a_hdr.c
index 4fb7a5f..e9de283 100644
--- a/crypto/asn1/a_hdr.c
+++ b/crypto/asn1/a_hdr.c
@@ -62,10 +62,10 @@
 #include "asn1.h"
 
 /*
- * ASN1err(ASN1_F_D2I_ASN1_HEADER,ASN1_R_LENGTH_MISMATCH);
- * ASN1err(ASN1_F_I2D_ASN1_HEADER,ASN1_R_BAD_GET_OBJECT);
- * ASN1err(ASN1_F_I2D_ASN1_HEADER,ASN1_R_BAD_GET_OBJECT);
- * ASN1err(ASN1_F_ASN1_HEADER_NEW,ASN1_R_BAD_GET_OBJECT);
+ * ASN1err(ASN1_F_D2I_ASN1_HEADER,ERR_R_ASN1_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_I2D_ASN1_HEADER,ERR_R_BAD_GET_ASN1_OBJECT_CALL);
+ * ASN1err(ASN1_F_I2D_ASN1_HEADER,ERR_R_BAD_GET_ASN1_OBJECT_CALL);
+ * ASN1err(ASN1_F_ASN1_HEADER_NEW,ERR_R_BAD_GET_ASN1_OBJECT_CALL);
  */
 
 int i2d_ASN1_HEADER(a,pp)
@@ -110,6 +110,7 @@
 ASN1_HEADER *ASN1_HEADER_new()
 	{
 	ASN1_HEADER *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,ASN1_HEADER);
 	M_ASN1_New(ret->header,ASN1_OCTET_STRING_new);
diff --git a/crypto/asn1/a_int.c b/crypto/asn1/a_int.c
index df79cf9..e847efe 100644
--- a/crypto/asn1/a_int.c
+++ b/crypto/asn1/a_int.c
@@ -279,7 +279,7 @@
 		ret=ai;
 	if (ret == NULL)
 		{
-		ASN1err(ASN1_F_BN_TO_ASN1_INTEGER,ASN1_R_ERROR_STACK);
+		ASN1err(ASN1_F_BN_TO_ASN1_INTEGER,ERR_R_NESTED_ASN1_ERROR);
 		goto err;
 		}
 	ret->type=V_ASN1_INTEGER;
diff --git a/crypto/asn1/a_object.c b/crypto/asn1/a_object.c
index 5a7eeef..a476960 100644
--- a/crypto/asn1/a_object.c
+++ b/crypto/asn1/a_object.c
@@ -382,8 +382,8 @@
 	o.data=data;
 	o.nid=nid;
 	o.length=len;
-	o.flags=ASN1_OBJECT_FLAG_DYNAMIC|
-		ASN1_OBJECT_FLAG_DYNAMIC_STRINGS|ASN1_OBJECT_FLAG_DYNAMIC_DATA;
+	o.flags=ASN1_OBJECT_FLAG_DYNAMIC|ASN1_OBJECT_FLAG_DYNAMIC_STRINGS|
+		ASN1_OBJECT_FLAG_DYNAMIC_DATA;
 	return(OBJ_dup(&o));
 	}
 
diff --git a/crypto/asn1/a_octet.c b/crypto/asn1/a_octet.c
index be3f172..5954c7b 100644
--- a/crypto/asn1/a_octet.c
+++ b/crypto/asn1/a_octet.c
@@ -82,7 +82,7 @@
 		pp,length,V_ASN1_OCTET_STRING,V_ASN1_UNIVERSAL);
 	if (ret == NULL)
 		{
-		ASN1err(ASN1_F_D2I_ASN1_OCTET_STRING,ASN1_R_ERROR_STACK);
+		ASN1err(ASN1_F_D2I_ASN1_OCTET_STRING,ERR_R_NESTED_ASN1_ERROR);
 		return(NULL);
 		}
 	return(ret);
diff --git a/crypto/asn1/a_set.c b/crypto/asn1/a_set.c
index 17c4994..7fd4807 100644
--- a/crypto/asn1/a_set.c
+++ b/crypto/asn1/a_set.c
@@ -89,11 +89,12 @@
 	return(r);
 	}
 
-STACK *d2i_ASN1_SET(a,pp,length,func,ex_tag,ex_class)
+STACK *d2i_ASN1_SET(a,pp,length,func,free_func,ex_tag,ex_class)
 STACK **a;
 unsigned char **pp;
 long length;
 char *(*func)();
+void (*free_func)();
 int ex_tag;
 int ex_class;
 	{
@@ -136,14 +137,25 @@
 		char *s;
 
 		if (M_ASN1_D2I_end_sequence()) break;
-		if ((s=func(NULL,&c.p,c.slen,c.max-c.p)) == NULL) goto err;
+		if ((s=func(NULL,&c.p,c.slen,c.max-c.p)) == NULL)
+			{
+			ASN1err(ASN1_F_D2I_ASN1_SET,ASN1_R_ERROR_PARSING_SET_ELEMENT);
+			asn1_add_error(*pp,(int)(c.q- *pp));
+			goto err;
+			}
 		if (!sk_push(ret,s)) goto err;
 		}
 	if (a != NULL) (*a)=ret;
 	*pp=c.p;
 	return(ret);
 err:
-	if ((ret != NULL) && ((a == NULL) || (*a != ret))) sk_free(ret);
+	if ((ret != NULL) && ((a == NULL) || (*a != ret)))
+		{
+		if (free_func != NULL)
+			sk_pop_free(ret,free_func);
+		else
+			sk_free(ret);
+		}
 	return(NULL);
 	}
 
diff --git a/crypto/asn1/a_sign.c b/crypto/asn1/a_sign.c
index 02188e6..c2ff978 100644
--- a/crypto/asn1/a_sign.c
+++ b/crypto/asn1/a_sign.c
@@ -136,7 +136,11 @@
 	signature->data=buf_out;
 	buf_out=NULL;
 	signature->length=outl;
-
+	/* In the interests of compatability, I'll make sure that
+	 * the bit string has a 'not-used bits' value of 0
+	 */
+	signature->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
+	signature->flags|=ASN1_STRING_FLAG_BITS_LEFT;
 err:
 	memset(&ctx,0,sizeof(ctx));
 	if (buf_in != NULL)
diff --git a/crypto/asn1/a_type.c b/crypto/asn1/a_type.c
index 7c00040..7ddf5f9 100644
--- a/crypto/asn1/a_type.c
+++ b/crypto/asn1/a_type.c
@@ -60,9 +60,7 @@
 #include "cryptlib.h"
 #include "asn1_mac.h"
 
-/* ASN1err(ASN1_F_ASN1_TYPE_NEW,ASN1_R_ERROR_STACK);
- * ASN1err(ASN1_F_D2I_ASN1_BYTES,ASN1_R_ERROR_STACK);
- * ASN1err(ASN1_F_D2I_ASN1_BYTES,ASN1_R_WRONG_TAG);
+/* ASN1err(ASN1_F_D2I_ASN1_BYTES,ASN1_R_WRONG_TAG);
  * ASN1err(ASN1_F_ASN1_COLLATE_PRIMATIVE,ASN1_R_WRONG_TAG);
  */
 
@@ -252,6 +250,7 @@
 ASN1_TYPE *ASN1_TYPE_new()
 	{
 	ASN1_TYPE *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,ASN1_TYPE);
 	ret->type= -1;
@@ -304,14 +303,20 @@
 		case V_ASN1_NEG_INTEGER:
 		case V_ASN1_BIT_STRING:
 		case V_ASN1_OCTET_STRING:
+		case V_ASN1_SEQUENCE:
+		case V_ASN1_SET:
+		case V_ASN1_NUMERICSTRING:
 		case V_ASN1_PRINTABLESTRING:
 		case V_ASN1_T61STRING:
+		case V_ASN1_VIDEOTEXSTRING:
 		case V_ASN1_IA5STRING:
-		case V_ASN1_UNIVERSALSTRING:
-		case V_ASN1_GENERALSTRING:
 		case V_ASN1_UTCTIME:
-		case V_ASN1_SET:
-		case V_ASN1_SEQUENCE:
+		case V_ASN1_GENERALIZEDTIME:
+		case V_ASN1_GRAPHICSTRING:
+		case V_ASN1_VISIBLESTRING:
+		case V_ASN1_GENERALSTRING:
+		case V_ASN1_UNIVERSALSTRING:
+		case V_ASN1_BMPSTRING:
 			ASN1_STRING_free((ASN1_STRING *)a->value.ptr);
 			break;
 		default:
diff --git a/crypto/asn1/a_utctm.c b/crypto/asn1/a_utctm.c
index 17a7abb..ddd1a40 100644
--- a/crypto/asn1/a_utctm.c
+++ b/crypto/asn1/a_utctm.c
@@ -85,7 +85,7 @@
 		V_ASN1_UTCTIME,V_ASN1_UNIVERSAL);
 	if (ret == NULL)
 		{
-		ASN1err(ASN1_F_D2I_ASN1_UTCTIME,ASN1_R_ERROR_STACK);
+		ASN1err(ASN1_F_D2I_ASN1_UTCTIME,ERR_R_NESTED_ASN1_ERROR);
 		return(NULL);
 		}
 	if (!ASN1_UTCTIME_check(ret))
@@ -180,7 +180,7 @@
 	{
 	char *p;
 	struct tm *ts;
-#if defined(THREADS)
+#if defined(THREADS) && !defined(WIN32)
 	struct tm data;
 #endif
 
@@ -189,7 +189,7 @@
 	if (s == NULL)
 		return(NULL);
 
-#if defined(THREADS)
+#if defined(THREADS) && !defined(WIN32)
 	ts=(struct tm *)gmtime_r(&t,&data);
 #else
 	ts=(struct tm *)gmtime(&t);
diff --git a/crypto/asn1/asn1.err b/crypto/asn1/asn1.err
index c8b7011..1f5af96 100644
--- a/crypto/asn1/asn1.err
+++ b/crypto/asn1/asn1.err
@@ -126,57 +126,53 @@
 
 /* Reason codes. */
 #define ASN1_R_BAD_CLASS				 100
-#define ASN1_R_BAD_GET_OBJECT				 101
-#define ASN1_R_BAD_OBJECT_HEADER			 102
-#define ASN1_R_BAD_PASSWORD_READ			 103
-#define ASN1_R_BAD_PKCS7_CONTENT			 104
-#define ASN1_R_BAD_PKCS7_TYPE				 105
-#define ASN1_R_BAD_TAG					 106
-#define ASN1_R_BAD_TYPE					 107
-#define ASN1_R_BN_LIB					 108
-#define ASN1_R_BOOLEAN_IS_WRONG_LENGTH			 109
-#define ASN1_R_BUFFER_TOO_SMALL				 110
-#define ASN1_R_DATA_IS_WRONG				 111
-#define ASN1_R_DECODING_ERROR				 112
-#define ASN1_R_ERROR_STACK				 113
-#define ASN1_R_EXPECTING_AN_INTEGER			 114
-#define ASN1_R_EXPECTING_AN_OBJECT			 115
-#define ASN1_R_EXPECTING_AN_OCTET_STRING		 116
-#define ASN1_R_EXPECTING_A_BIT_STRING			 117
-#define ASN1_R_EXPECTING_A_BOOLEAN			 118
-#define ASN1_R_EXPECTING_A_SEQUENCE			 119
-#define ASN1_R_EXPECTING_A_UTCTIME			 120
-#define ASN1_R_FIRST_NUM_TOO_LARGE			 121
-#define ASN1_R_HEADER_TOO_LONG				 122
-#define ASN1_R_INVALID_DIGIT				 123
-#define ASN1_R_INVALID_SEPARATOR			 124
-#define ASN1_R_INVALID_TIME_FORMAT			 125
-#define ASN1_R_IV_TOO_LARGE				 126
-#define ASN1_R_LENGTH_ERROR				 127
-#define ASN1_R_LENGTH_MISMATCH				 128
-#define ASN1_R_MISSING_EOS				 129
-#define ASN1_R_MISSING_SECOND_NUMBER			 130
-#define ASN1_R_NON_HEX_CHARACTERS			 131
-#define ASN1_R_NOT_ENOUGH_DATA				 132
-#define ASN1_R_ODD_NUMBER_OF_CHARS			 133
-#define ASN1_R_PARSING					 134
-#define ASN1_R_PRIVATE_KEY_HEADER_MISSING		 135
-#define ASN1_R_SECOND_NUMBER_TOO_LARGE			 136
-#define ASN1_R_SHORT_LINE				 137
-#define ASN1_R_STRING_TOO_SHORT				 138
-#define ASN1_R_TAG_VALUE_TOO_HIGH			 139
-#define ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 140
-#define ASN1_R_TOO_LONG					 141
-#define ASN1_R_UNABLE_TO_DECODE_RSA_KEY			 142
-#define ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY		 143
-#define ASN1_R_UNKNOWN_ATTRIBUTE_TYPE			 144
-#define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM		 145
-#define ASN1_R_UNKNOWN_OBJECT_TYPE			 146
-#define ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE			 147
-#define ASN1_R_UNSUPPORTED_CIPHER			 148
-#define ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM		 149
-#define ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE		 150
-#define ASN1_R_UTCTIME_TOO_LONG				 151
-#define ASN1_R_WRONG_PRINTABLE_TYPE			 152
-#define ASN1_R_WRONG_TAG				 153
-#define ASN1_R_WRONG_TYPE				 154
+#define ASN1_R_BAD_OBJECT_HEADER			 101
+#define ASN1_R_BAD_PASSWORD_READ			 102
+#define ASN1_R_BAD_PKCS7_CONTENT			 103
+#define ASN1_R_BAD_PKCS7_TYPE				 104
+#define ASN1_R_BAD_TAG					 105
+#define ASN1_R_BAD_TYPE					 106
+#define ASN1_R_BN_LIB					 107
+#define ASN1_R_BOOLEAN_IS_WRONG_LENGTH			 108
+#define ASN1_R_BUFFER_TOO_SMALL				 109
+#define ASN1_R_DATA_IS_WRONG				 110
+#define ASN1_R_DECODING_ERROR				 111
+#define ASN1_R_ERROR_PARSING_SET_ELEMENT		 112
+#define ASN1_R_EXPECTING_AN_INTEGER			 113
+#define ASN1_R_EXPECTING_AN_OBJECT			 114
+#define ASN1_R_EXPECTING_AN_OCTET_STRING		 115
+#define ASN1_R_EXPECTING_A_BIT_STRING			 116
+#define ASN1_R_EXPECTING_A_BOOLEAN			 117
+#define ASN1_R_EXPECTING_A_UTCTIME			 118
+#define ASN1_R_FIRST_NUM_TOO_LARGE			 119
+#define ASN1_R_HEADER_TOO_LONG				 120
+#define ASN1_R_INVALID_DIGIT				 121
+#define ASN1_R_INVALID_SEPARATOR			 122
+#define ASN1_R_INVALID_TIME_FORMAT			 123
+#define ASN1_R_IV_TOO_LARGE				 124
+#define ASN1_R_LENGTH_ERROR				 125
+#define ASN1_R_MISSING_SECOND_NUMBER			 126
+#define ASN1_R_NON_HEX_CHARACTERS			 127
+#define ASN1_R_NOT_ENOUGH_DATA				 128
+#define ASN1_R_ODD_NUMBER_OF_CHARS			 129
+#define ASN1_R_PARSING					 130
+#define ASN1_R_PRIVATE_KEY_HEADER_MISSING		 131
+#define ASN1_R_SECOND_NUMBER_TOO_LARGE			 132
+#define ASN1_R_SHORT_LINE				 133
+#define ASN1_R_STRING_TOO_SHORT				 134
+#define ASN1_R_TAG_VALUE_TOO_HIGH			 135
+#define ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 136
+#define ASN1_R_TOO_LONG					 137
+#define ASN1_R_UNABLE_TO_DECODE_RSA_KEY			 138
+#define ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY		 139
+#define ASN1_R_UNKNOWN_ATTRIBUTE_TYPE			 140
+#define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM		 141
+#define ASN1_R_UNKNOWN_OBJECT_TYPE			 142
+#define ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE			 143
+#define ASN1_R_UNSUPPORTED_CIPHER			 144
+#define ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM		 145
+#define ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE		 146
+#define ASN1_R_UTCTIME_TOO_LONG				 147
+#define ASN1_R_WRONG_PRINTABLE_TYPE			 148
+#define ASN1_R_WRONG_TAG				 149
+#define ASN1_R_WRONG_TYPE				 150
diff --git a/crypto/asn1/asn1.h b/crypto/asn1/asn1.h
index 9793db3..0aa1ca0 100644
--- a/crypto/asn1/asn1.h
+++ b/crypto/asn1/asn1.h
@@ -122,101 +122,6 @@
 #define B_ASN1_BMPSTRING	0x0800
 #define B_ASN1_UNKNOWN		0x1000
 
-#ifndef DEBUG
-
-#define ASN1_INTEGER		ASN1_STRING
-#define ASN1_BIT_STRING		ASN1_STRING
-#define ASN1_OCTET_STRING	ASN1_STRING
-#define ASN1_PRINTABLESTRING	ASN1_STRING
-#define ASN1_T61STRING		ASN1_STRING
-#define ASN1_IA5STRING		ASN1_STRING
-#define ASN1_UTCTIME		ASN1_STRING
-#define ASN1_GENERALIZEDTIME	ASN1_STRING
-#define ASN1_GENERALSTRING	ASN1_STRING
-#define ASN1_UNIVERSALSTRING	ASN1_STRING
-#define ASN1_BMPSTRING		ASN1_STRING
-
-#else
-
-typedef struct asn1_integer_st
-	{
-	int length;
-	int type;
-	unsigned char *data;
-	} ASN1_INTEGER;
-
-typedef struct asn1_bit_string_st
-	{
-	int length;
-	int type;
-	unsigned char *data;
-	} ASN1_BIT_STRING;
-
-typedef struct asn1_octet_string_st
-	{
-	int length;
-	int type;
-	unsigned char *data;
-	} ASN1_OCTET_STRING;
-
-typedef struct asn1_printablestring_st
-	{
-	int length;
-	int type;
-	unsigned char *data;
-	} ASN1_PRINTABLESTRING;
-
-typedef struct asn1_t61string_st
-	{
-	int length;
-	int type;
-	unsigned char *data;
-	} ASN1_T61STRING;
-
-typedef struct asn1_ia5string_st
-	{
-	int length;
-	int type;
-	unsigned char *data;
-	} ASN1_IA5STRING;
-
-typedef struct asn1_generalstring_st
-	{
-	int length;
-	int type;
-	unsigned char *data;
-	} ASN1_GENERALSTRING;
-
-typedef struct asn1_universalstring_st
-	{
-	int length;
-	int type;
-	unsigned char *data;
-	} ASN1_UNIVERSALSTRING;
-
-typedef struct asn1_bmpstring_st
-	{
-	int length;
-	int type;
-	unsigned char *data;
-	} ASN1_BMPSTRING;
-
-typedef struct asn1_utctime_st
-	{
-	int length;
-	int type;
-	unsigned char *data;
-	} ASN1_UTCTIME;
-
-typedef struct asn1_generalizedtime_st
-	{
-	int length;
-	int type;
-	unsigned char *data;
-	} ASN1_GENERALIZEDTIME;
-
-#endif
-
 typedef struct asn1_ctx_st
 	{
 	unsigned char *p;/* work char pointer */
@@ -229,6 +134,7 @@
 	unsigned char *max; /* largest value of p alowed */
 	unsigned char *q;/* temporary variable */
 	unsigned char **pp;/* variable */
+	int line;	/* used in error processing */
 	} ASN1_CTX;
 
 /* These are used internally in the ASN1_OBJECT to keep track of
@@ -246,14 +152,46 @@
 	int flags;	/* Should we free this one */
 	} ASN1_OBJECT;
 
+#define ASN1_STRING_FLAG_BITS_LEFT 0x08 /* Set if 0x07 has bits left value */
 /* This is the base type that holds just about everything :-) */
 typedef struct asn1_string_st
 	{
 	int length;
 	int type;
 	unsigned char *data;
+	/* The value of the following field depends on the type being
+	 * held.  It is mostly being used for BIT_STRING so if the
+	 * input data has a non-zero 'unused bits' value, it will be
+	 * handled correctly */
+	long flags;
 	} ASN1_STRING;
 
+#ifndef DEBUG
+#define ASN1_INTEGER		ASN1_STRING
+#define ASN1_BIT_STRING		ASN1_STRING
+#define ASN1_OCTET_STRING	ASN1_STRING
+#define ASN1_PRINTABLESTRING	ASN1_STRING
+#define ASN1_T61STRING		ASN1_STRING
+#define ASN1_IA5STRING		ASN1_STRING
+#define ASN1_UTCTIME		ASN1_STRING
+#define ASN1_GENERALIZEDTIME	ASN1_STRING
+#define ASN1_GENERALSTRING	ASN1_STRING
+#define ASN1_UNIVERSALSTRING	ASN1_STRING
+#define ASN1_BMPSTRING		ASN1_STRING
+#else
+typedef struct asn1_string_st ASN1_INTEGER;
+typedef struct asn1_string_st ASN1_BIT_STRING;
+typedef struct asn1_string_st ASN1_OCTET_STRING;
+typedef struct asn1_string_st ASN1_PRINTABLESTRING;
+typedef struct asn1_string_st ASN1_T61STRING;
+typedef struct asn1_string_st ASN1_IA5STRING;
+typedef struct asn1_string_st ASN1_GENERALSTRING;
+typedef struct asn1_string_st ASN1_UNIVERSALSTRING;
+typedef struct asn1_string_st ASN1_BMPSTRING;
+typedef struct asn1_string_st ASN1_UTCTIME;
+typedef struct asn1_string_st ASN1_GENERALIZEDTIME;
+#endif
+
 typedef struct asn1_type_st
 	{
 	int type;
@@ -472,6 +410,10 @@
 ASN1_OCTET_STRING *d2i_ASN1_OCTET_STRING(ASN1_OCTET_STRING **a,
 			unsigned char **pp,long length);
 
+int i2d_ASN1_BMPSTRING(ASN1_BMPSTRING *a, unsigned char **pp);
+ASN1_BMPSTRING *d2i_ASN1_BMPSTRING(ASN1_BMPSTRING **a, unsigned char **pp,
+	long length);
+
 int i2d_ASN1_PRINTABLE(ASN1_STRING *a,unsigned char **pp);
 ASN1_STRING *d2i_ASN1_PRINTABLE(ASN1_STRING **a,
 	unsigned char **pp, long l);
@@ -491,7 +433,8 @@
 int		i2d_ASN1_SET(STACK *a, unsigned char **pp,
 			int (*func)(), int ex_tag, int ex_class);
 STACK *		d2i_ASN1_SET(STACK **a, unsigned char **pp, long length,
-			char *(*func)(), int ex_tag, int ex_class);
+			char *(*func)(), void (*free_func)(),
+			int ex_tag, int ex_class);
 
 #ifdef HEADER_BIO_H
 int i2a_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *a);
@@ -666,6 +609,9 @@
 int ASN1_TYPE_set_int_octetstring();
 int ASN1_TYPE_get_int_octetstring();
 
+int i2d_ASN1_BMPSTRING();
+ASN1_BMPSTRING *d2i_ASN1_BMPSTRING();
+
 #endif
 
 /* BEGIN ERROR CODES */
@@ -797,60 +743,56 @@
 
 /* Reason codes. */
 #define ASN1_R_BAD_CLASS				 100
-#define ASN1_R_BAD_GET_OBJECT				 101
-#define ASN1_R_BAD_OBJECT_HEADER			 102
-#define ASN1_R_BAD_PASSWORD_READ			 103
-#define ASN1_R_BAD_PKCS7_CONTENT			 104
-#define ASN1_R_BAD_PKCS7_TYPE				 105
-#define ASN1_R_BAD_TAG					 106
-#define ASN1_R_BAD_TYPE					 107
-#define ASN1_R_BN_LIB					 108
-#define ASN1_R_BOOLEAN_IS_WRONG_LENGTH			 109
-#define ASN1_R_BUFFER_TOO_SMALL				 110
-#define ASN1_R_DATA_IS_WRONG				 111
-#define ASN1_R_DECODING_ERROR				 112
-#define ASN1_R_ERROR_STACK				 113
-#define ASN1_R_EXPECTING_AN_INTEGER			 114
-#define ASN1_R_EXPECTING_AN_OBJECT			 115
-#define ASN1_R_EXPECTING_AN_OCTET_STRING		 116
-#define ASN1_R_EXPECTING_A_BIT_STRING			 117
-#define ASN1_R_EXPECTING_A_BOOLEAN			 118
-#define ASN1_R_EXPECTING_A_SEQUENCE			 119
-#define ASN1_R_EXPECTING_A_UTCTIME			 120
-#define ASN1_R_FIRST_NUM_TOO_LARGE			 121
-#define ASN1_R_HEADER_TOO_LONG				 122
-#define ASN1_R_INVALID_DIGIT				 123
-#define ASN1_R_INVALID_SEPARATOR			 124
-#define ASN1_R_INVALID_TIME_FORMAT			 125
-#define ASN1_R_IV_TOO_LARGE				 126
-#define ASN1_R_LENGTH_ERROR				 127
-#define ASN1_R_LENGTH_MISMATCH				 128
-#define ASN1_R_MISSING_EOS				 129
-#define ASN1_R_MISSING_SECOND_NUMBER			 130
-#define ASN1_R_NON_HEX_CHARACTERS			 131
-#define ASN1_R_NOT_ENOUGH_DATA				 132
-#define ASN1_R_ODD_NUMBER_OF_CHARS			 133
-#define ASN1_R_PARSING					 134
-#define ASN1_R_PRIVATE_KEY_HEADER_MISSING		 135
-#define ASN1_R_SECOND_NUMBER_TOO_LARGE			 136
-#define ASN1_R_SHORT_LINE				 137
-#define ASN1_R_STRING_TOO_SHORT				 138
-#define ASN1_R_TAG_VALUE_TOO_HIGH			 139
-#define ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 140
-#define ASN1_R_TOO_LONG					 141
-#define ASN1_R_UNABLE_TO_DECODE_RSA_KEY			 142
-#define ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY		 143
-#define ASN1_R_UNKNOWN_ATTRIBUTE_TYPE			 144
-#define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM		 145
-#define ASN1_R_UNKNOWN_OBJECT_TYPE			 146
-#define ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE			 147
-#define ASN1_R_UNSUPPORTED_CIPHER			 148
-#define ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM		 149
-#define ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE		 150
-#define ASN1_R_UTCTIME_TOO_LONG				 151
-#define ASN1_R_WRONG_PRINTABLE_TYPE			 152
-#define ASN1_R_WRONG_TAG				 153
-#define ASN1_R_WRONG_TYPE				 154
+#define ASN1_R_BAD_OBJECT_HEADER			 101
+#define ASN1_R_BAD_PASSWORD_READ			 102
+#define ASN1_R_BAD_PKCS7_CONTENT			 103
+#define ASN1_R_BAD_PKCS7_TYPE				 104
+#define ASN1_R_BAD_TAG					 105
+#define ASN1_R_BAD_TYPE					 106
+#define ASN1_R_BN_LIB					 107
+#define ASN1_R_BOOLEAN_IS_WRONG_LENGTH			 108
+#define ASN1_R_BUFFER_TOO_SMALL				 109
+#define ASN1_R_DATA_IS_WRONG				 110
+#define ASN1_R_DECODING_ERROR				 111
+#define ASN1_R_ERROR_PARSING_SET_ELEMENT		 112
+#define ASN1_R_EXPECTING_AN_INTEGER			 113
+#define ASN1_R_EXPECTING_AN_OBJECT			 114
+#define ASN1_R_EXPECTING_AN_OCTET_STRING		 115
+#define ASN1_R_EXPECTING_A_BIT_STRING			 116
+#define ASN1_R_EXPECTING_A_BOOLEAN			 117
+#define ASN1_R_EXPECTING_A_UTCTIME			 118
+#define ASN1_R_FIRST_NUM_TOO_LARGE			 119
+#define ASN1_R_HEADER_TOO_LONG				 120
+#define ASN1_R_INVALID_DIGIT				 121
+#define ASN1_R_INVALID_SEPARATOR			 122
+#define ASN1_R_INVALID_TIME_FORMAT			 123
+#define ASN1_R_IV_TOO_LARGE				 124
+#define ASN1_R_LENGTH_ERROR				 125
+#define ASN1_R_MISSING_SECOND_NUMBER			 126
+#define ASN1_R_NON_HEX_CHARACTERS			 127
+#define ASN1_R_NOT_ENOUGH_DATA				 128
+#define ASN1_R_ODD_NUMBER_OF_CHARS			 129
+#define ASN1_R_PARSING					 130
+#define ASN1_R_PRIVATE_KEY_HEADER_MISSING		 131
+#define ASN1_R_SECOND_NUMBER_TOO_LARGE			 132
+#define ASN1_R_SHORT_LINE				 133
+#define ASN1_R_STRING_TOO_SHORT				 134
+#define ASN1_R_TAG_VALUE_TOO_HIGH			 135
+#define ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 136
+#define ASN1_R_TOO_LONG					 137
+#define ASN1_R_UNABLE_TO_DECODE_RSA_KEY			 138
+#define ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY		 139
+#define ASN1_R_UNKNOWN_ATTRIBUTE_TYPE			 140
+#define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM		 141
+#define ASN1_R_UNKNOWN_OBJECT_TYPE			 142
+#define ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE			 143
+#define ASN1_R_UNSUPPORTED_CIPHER			 144
+#define ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM		 145
+#define ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE		 146
+#define ASN1_R_UTCTIME_TOO_LONG				 147
+#define ASN1_R_WRONG_PRINTABLE_TYPE			 148
+#define ASN1_R_WRONG_TAG				 149
+#define ASN1_R_WRONG_TYPE				 150
  
 #ifdef  __cplusplus
 }
diff --git a/crypto/asn1/asn1_err.c b/crypto/asn1/asn1_err.c
index 03c2858..b7818f8 100644
--- a/crypto/asn1/asn1_err.c
+++ b/crypto/asn1/asn1_err.c
@@ -87,7 +87,7 @@
 {ERR_PACK(0,ASN1_F_ASN1_VERIFY,0),	"ASN1_VERIFY"},
 {ERR_PACK(0,ASN1_F_BN_TO_ASN1_INTEGER,0),	"BN_to_ASN1_INTEGER"},
 {ERR_PACK(0,ASN1_F_D2I_ASN1_BIT_STRING,0),	"d2i_ASN1_BIT_STRING"},
-{ERR_PACK(0,ASN1_F_D2I_ASN1_BMPSTRING,0),	"D2I_ASN1_BMPSTRING"},
+{ERR_PACK(0,ASN1_F_D2I_ASN1_BMPSTRING,0),	"d2i_ASN1_BMPSTRING"},
 {ERR_PACK(0,ASN1_F_D2I_ASN1_BOOLEAN,0),	"d2i_ASN1_BOOLEAN"},
 {ERR_PACK(0,ASN1_F_D2I_ASN1_BYTES,0),	"d2i_ASN1_bytes"},
 {ERR_PACK(0,ASN1_F_D2I_ASN1_HEADER,0),	"d2i_ASN1_HEADER"},
@@ -191,7 +191,6 @@
 static ERR_STRING_DATA ASN1_str_reasons[]=
 	{
 {ASN1_R_BAD_CLASS                        ,"bad class"},
-{ASN1_R_BAD_GET_OBJECT                   ,"bad get object"},
 {ASN1_R_BAD_OBJECT_HEADER                ,"bad object header"},
 {ASN1_R_BAD_PASSWORD_READ                ,"bad password read"},
 {ASN1_R_BAD_PKCS7_CONTENT                ,"bad pkcs7 content"},
@@ -203,13 +202,12 @@
 {ASN1_R_BUFFER_TOO_SMALL                 ,"buffer too small"},
 {ASN1_R_DATA_IS_WRONG                    ,"data is wrong"},
 {ASN1_R_DECODING_ERROR                   ,"decoding error"},
-{ASN1_R_ERROR_STACK                      ,"error stack"},
+{ASN1_R_ERROR_PARSING_SET_ELEMENT        ,"error parsing set element"},
 {ASN1_R_EXPECTING_AN_INTEGER             ,"expecting an integer"},
 {ASN1_R_EXPECTING_AN_OBJECT              ,"expecting an object"},
 {ASN1_R_EXPECTING_AN_OCTET_STRING        ,"expecting an octet string"},
 {ASN1_R_EXPECTING_A_BIT_STRING           ,"expecting a bit string"},
 {ASN1_R_EXPECTING_A_BOOLEAN              ,"expecting a boolean"},
-{ASN1_R_EXPECTING_A_SEQUENCE             ,"expecting a sequence"},
 {ASN1_R_EXPECTING_A_UTCTIME              ,"expecting a utctime"},
 {ASN1_R_FIRST_NUM_TOO_LARGE              ,"first num too large"},
 {ASN1_R_HEADER_TOO_LONG                  ,"header too long"},
@@ -218,8 +216,6 @@
 {ASN1_R_INVALID_TIME_FORMAT              ,"invalid time format"},
 {ASN1_R_IV_TOO_LARGE                     ,"iv too large"},
 {ASN1_R_LENGTH_ERROR                     ,"length error"},
-{ASN1_R_LENGTH_MISMATCH                  ,"length mismatch"},
-{ASN1_R_MISSING_EOS                      ,"missing eos"},
 {ASN1_R_MISSING_SECOND_NUMBER            ,"missing second number"},
 {ASN1_R_NON_HEX_CHARACTERS               ,"non hex characters"},
 {ASN1_R_NOT_ENOUGH_DATA                  ,"not enough data"},
@@ -254,8 +250,8 @@
 	{
 	static int init=1;
 
-	if (init);
-		{;
+	if (init)
+		{
 		init=0;
 #ifndef NO_ERR
 		ERR_load_strings(ERR_LIB_ASN1,ASN1_str_functs);
diff --git a/crypto/asn1/asn1_lib.c b/crypto/asn1/asn1_lib.c
index ff30b25..bc34cc4 100644
--- a/crypto/asn1/asn1_lib.c
+++ b/crypto/asn1/asn1_lib.c
@@ -69,7 +69,7 @@
 static void asn1_put_length();
 #endif
 
-char *ASN1_version="ASN1 part of SSLeay 0.9.0b 29-Jun-1998";
+char *ASN1_version="ASN1 part of SSLeay 0.9.1a 06-Jul-1998";
 
 int ASN1_check_infinite_end(p,len)
 unsigned char **p;
@@ -130,11 +130,13 @@
 	*pclass=xclass;
 	if (!asn1_get_length(&p,&inf,plength,(int)max)) goto err;
 
-#ifdef undef
-	fprintf(stderr,"p=%d + *plength=%d > omax=%d + *pp=%d  (%d > %d)\n", 
-		p,*plength,omax,*pp,(p+ *plength),omax+ *pp);
+#if 0
+	fprintf(stderr,"p=%d + *plength=%ld > omax=%ld + *pp=%d  (%d > %d)\n", 
+		(int)p,*plength,omax,(int)*pp,(int)(p+ *plength),
+		(int)(omax+ *pp));
 
 #endif
+#if 0
 	if ((p+ *plength) > (omax+ *pp))
 		{
 		ASN1err(ASN1_F_ASN1_GET_OBJECT,ASN1_R_TOO_LONG);
@@ -142,8 +144,9 @@
 		 * the values are set correctly */
 		ret|=0x80;
 		}
+#endif
 	*pp=p;
-	return(ret+inf);
+	return(ret|inf);
 err:
 	ASN1err(ASN1_F_ASN1_GET_OBJECT,ASN1_R_HEADER_TOO_LONG);
 	return(0x80);
@@ -284,14 +287,14 @@
 		{
 		if (!ASN1_check_infinite_end(&c->p,c->slen))
 			{
-			c->error=ASN1_R_MISSING_EOS;
+			c->error=ERR_R_MISSING_ASN1_EOS;
 			return(0);
 			}
 		}
 	if (	((c->slen != 0) && !(c->inf & 1)) ||
 		((c->slen < 0) && (c->inf & 1)))
 		{
-		c->error=ASN1_R_LENGTH_MISMATCH;
+		c->error=ERR_R_ASN1_LENGTH_MISMATCH;
 		return(0);
 		}
 	return(1);
@@ -308,18 +311,18 @@
 		*length);
 	if (c->inf & 0x80)
 		{
-		c->error=ASN1_R_BAD_GET_OBJECT;
+		c->error=ERR_R_BAD_GET_ASN1_OBJECT_CALL;
 		return(0);
 		}
 	if (c->tag != V_ASN1_SEQUENCE)
 		{
-		c->error=ASN1_R_EXPECTING_A_SEQUENCE;
+		c->error=ERR_R_EXPECTING_AN_ASN1_SEQUENCE;
 		return(0);
 		}
 	(*length)-=(c->p-q);
 	if (c->max && (*length < 0))
 		{
-		c->error=ASN1_R_LENGTH_MISMATCH;
+		c->error=ERR_R_ASN1_LENGTH_MISMATCH;
 		return(0);
 		}
 	if (c->inf == (1|V_ASN1_CONSTRUCTED))
@@ -402,6 +405,7 @@
 	ret->length=0;
 	ret->type=type;
 	ret->data=NULL;
+	ret->flags=0;
 	return(ret);
 	}
 
diff --git a/crypto/asn1/asn1_mac.h b/crypto/asn1/asn1_mac.h
index 4fba70e..4e61152 100644
--- a/crypto/asn1/asn1_mac.h
+++ b/crypto/asn1/asn1_mac.h
@@ -67,14 +67,23 @@
 #include "x509.h"
 #include "pkcs7.h"
 
+#ifndef ASN1_MAC_ERR_LIB
+#define ASN1_MAC_ERR_LIB	ERR_LIB_ASN1
+#endif 
+
+#define ASN1_MAC_H_err(f,r,line) \
+	ERR_PUT_error(ASN1_MAC_ERR_LIB,(f),(r),ERR_file_name,(line))
+
 #define M_ASN1_D2I_vars(a,type,func) \
 	ASN1_CTX c; \
 	type ret=NULL; \
 	\
 	c.pp=pp; \
-	c.error=ASN1_R_ERROR_STACK; \
+	c.q= *pp; \
+	c.error=ERR_R_NESTED_ASN1_ERROR; \
 	if ((a == NULL) || ((*a) == NULL)) \
-		{ if ((ret=(type)func()) == NULL) goto err; } \
+		{ if ((ret=(type)func()) == NULL) \
+			{ c.line=__LINE__; goto err; } } \
 	else	ret=(*a);
 
 #define M_ASN1_D2I_Init() \
@@ -82,7 +91,8 @@
 	c.max=(length == 0)?0:(c.p+length);
 
 #define M_ASN1_D2I_Finish_2(a) \
-	if (!asn1_Finish(&c)) goto err; \
+	if (!asn1_Finish(&c)) \
+		{ c.line=__LINE__; goto err; } \
 	*pp=c.p; \
 	if (a != NULL) (*a)=ret; \
 	return(ret);
@@ -90,21 +100,31 @@
 #define M_ASN1_D2I_Finish(a,func,e) \
 	M_ASN1_D2I_Finish_2(a); \
 err:\
-	ASN1err((e),c.error); \
+	ASN1_MAC_H_err((e),c.error,c.line); \
 	asn1_add_error(*pp,(int)(c.q- *pp)); \
 	if ((ret != NULL) && ((a == NULL) || (*a != ret))) func(ret); \
 	return(NULL)
 
 #define M_ASN1_D2I_start_sequence() \
-	if (!asn1_GetSequence(&c,&length)) goto err;
+	if (!asn1_GetSequence(&c,&length)) \
+		{ c.line=__LINE__; goto err; }
 
 #define M_ASN1_D2I_end_sequence() \
 	(((c.inf&1) == 0)?(c.slen <= 0): \
 		(c.eos=ASN1_check_infinite_end(&c.p,c.slen)))
 
+/* Don't use this with d2i_ASN1_BOOLEAN() */
 #define M_ASN1_D2I_get(b,func) \
 	c.q=c.p; \
-	if (func(&(b),&c.p,c.slen) == NULL) goto err; \
+	if (func(&(b),&c.p,c.slen) == NULL) \
+		{c.line=__LINE__; goto err; } \
+	c.slen-=(c.p-c.q);
+
+/* use this instead () */
+#define M_ASN1_D2I_get_int(b,func) \
+	c.q=c.p; \
+	if (func(&(b),&c.p,c.slen) < 0) \
+		{c.line=__LINE__; goto err; } \
 	c.slen-=(c.p-c.q);
 
 #define M_ASN1_D2I_get_opt(b,func,type) \
@@ -125,38 +145,56 @@
 		M_ASN1_next_prev=tmp; \
 		}
 
-#define M_ASN1_D2I_get_set(r,func) \
-		M_ASN1_D2I_get_imp_set(r,func,V_ASN1_SET,V_ASN1_UNIVERSAL);
+#define M_ASN1_D2I_get_set(r,func,free_func) \
+		M_ASN1_D2I_get_imp_set(r,func,free_func, \
+			V_ASN1_SET,V_ASN1_UNIVERSAL);
 
-#define M_ASN1_D2I_get_IMP_set_opt(b,func,tag) \
+#define M_ASN1_D2I_get_set_opt(r,func,free_func) \
+	if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \
+		V_ASN1_CONSTRUCTED|V_ASN1_SET)))\
+		{ M_ASN1_D2I_get_set(r,func,free_func); }
+
+#define M_ASN1_I2D_len_SET_opt(a,f) \
+	if ((a != NULL) && (sk_num(a) != 0)) \
+		M_ASN1_I2D_len_SET(a,f);
+
+#define M_ASN1_I2D_put_SET_opt(a,f) \
+	if ((a != NULL) && (sk_num(a) != 0)) \
+		M_ASN1_I2D_put_SET(a,f);
+
+#define M_ASN1_D2I_get_IMP_set_opt(b,func,free_func,tag) \
 	if ((c.slen != 0) && \
 		(M_ASN1_next == \
 		(V_ASN1_CONTEXT_SPECIFIC|V_ASN1_CONSTRUCTED|(tag))))\
 		{ \
-		M_ASN1_D2I_get_imp_set(b,func,tag,V_ASN1_CONTEXT_SPECIFIC); \
+		M_ASN1_D2I_get_imp_set(b,func,free_func,\
+			tag,V_ASN1_CONTEXT_SPECIFIC); \
 		}
 
-#define M_ASN1_D2I_get_seq(r,func) \
-		M_ASN1_D2I_get_imp_set(r,func,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL);
+#define M_ASN1_D2I_get_seq(r,func,free_func) \
+		M_ASN1_D2I_get_imp_set(r,func,free_func,\
+			V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL);
 
-#define M_ASN1_D2I_get_seq_opt(r,func) \
+#define M_ASN1_D2I_get_seq_opt(r,func,free_func) \
 	if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \
 		V_ASN1_CONSTRUCTED|V_ASN1_SEQUENCE)))\
-		{ M_ASN1_D2I_get_seq(r,func); }
+		{ M_ASN1_D2I_get_seq(r,func,free_func); }
 
-#define M_ASN1_D2I_get_IMP_set(r,func,x) \
-		M_ASN1_D2I_get_imp_set(r,func,x,V_ASN1_CONTEXT_SPECIFIC);
+#define M_ASN1_D2I_get_IMP_set(r,func,free_func,x) \
+		M_ASN1_D2I_get_imp_set(r,func,free_func,\
+			x,V_ASN1_CONTEXT_SPECIFIC);
 
-#define M_ASN1_D2I_get_imp_set(r,func,a,b) \
+#define M_ASN1_D2I_get_imp_set(r,func,free_func,a,b) \
 	c.q=c.p; \
-	if (d2i_ASN1_SET(&(r),&c.p,c.slen,(char *(*)())func,a,b) == NULL) \
-		goto err; \
+	if (d2i_ASN1_SET(&(r),&c.p,c.slen,(char *(*)())func,\
+		(void (*)())free_func,a,b) == NULL) \
+		{ c.line=__LINE__; goto err; } \
 	c.slen-=(c.p-c.q);
 
 #define M_ASN1_D2I_get_set_strings(r,func,a,b) \
 	c.q=c.p; \
 	if (d2i_ASN1_STRING_SET(&(r),&c.p,c.slen,a,b) == NULL) \
-		goto err; \
+		{ c.line=__LINE__; goto err; } \
 	c.slen-=(c.p-c.q);
 
 #define M_ASN1_D2I_get_EXP_opt(r,func,tag) \
@@ -169,13 +207,14 @@
 		c.q=c.p; \
 		Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \
 		if (Tinf & 0x80) \
-			{ c.error=ASN1_R_BAD_OBJECT_HEADER; goto err; } \
+			{ c.error=ERR_R_BAD_ASN1_OBJECT_HEADER; \
+			c.line=__LINE__; goto err; } \
 		if (func(&(r),&c.p,Tlen) == NULL) \
-			goto err; \
+			{ c.line=__LINE__; goto err; } \
 		c.slen-=(c.p-c.q); \
 		}
 
-#define M_ASN1_D2I_get_EXP_set_opt(r,func,tag,b) \
+#define M_ASN1_D2I_get_EXP_set_opt(r,func,free_func,tag,b) \
 	if ((c.slen != 0) && (M_ASN1_next == \
 		(V_ASN1_CONSTRUCTED|V_ASN1_CONTEXT_SPECIFIC|tag))) \
 		{ \
@@ -185,24 +224,27 @@
 		c.q=c.p; \
 		Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \
 		if (Tinf & 0x80) \
-			{ c.error=ASN1_R_BAD_OBJECT_HEADER; goto err; } \
+			{ c.error=ERR_R_BAD_ASN1_OBJECT_HEADER; \
+			c.line=__LINE__; goto err; } \
 		if (d2i_ASN1_SET(&(r),&c.p,Tlen,(char *(*)())func, \
+			(void (*)())free_func, \
 			b,V_ASN1_UNIVERSAL) == NULL) \
-			goto err; \
+			{ c.line=__LINE__; goto err; } \
 		c.slen-=(c.p-c.q); \
 		}
 
 /* New macros */
 #define M_ASN1_New_Malloc(ret,type) \
-	if ((ret=(type *)Malloc(sizeof(type))) == NULL) goto err2;
+	if ((ret=(type *)Malloc(sizeof(type))) == NULL) \
+		{ c.line=__LINE__; goto err2; }
 
 #define M_ASN1_New(arg,func) \
 	if (((arg)=func()) == NULL) return(NULL)
 
 #define M_ASN1_New_Error(a) \
-/*	err:	ASN1err((a),ASN1_R_ERROR_STACK); \
+/*	err:	ASN1_MAC_H_err((a),ERR_R_NESTED_ASN1_ERROR,c.line); \
 		return(NULL);*/ \
-	err2:	ASN1err((a),ERR_R_MALLOC_FAILURE); \
+	err2:	ASN1_MAC_H_err((a),ERR_R_MALLOC_FAILURE,c.line); \
 		return(NULL)
 
 
diff --git a/crypto/asn1/asn1_par.c b/crypto/asn1/asn1_par.c
index 3906227..af71b1a 100644
--- a/crypto/asn1/asn1_par.c
+++ b/crypto/asn1/asn1_par.c
@@ -266,7 +266,8 @@
 			if (	(tag == V_ASN1_PRINTABLESTRING) ||
 				(tag == V_ASN1_T61STRING) ||
 				(tag == V_ASN1_IA5STRING) ||
-				(tag == V_ASN1_UTCTIME))
+				(tag == V_ASN1_UTCTIME) ||
+				(tag == V_ASN1_GENERALIZEDTIME))
 				{
 				if (BIO_write(bp,":",1) <= 0) goto end;
 				if ((len > 0) &&
diff --git a/crypto/asn1/d2i_dhp.c b/crypto/asn1/d2i_dhp.c
index 616a308..f2236fc 100644
--- a/crypto/asn1/d2i_dhp.c
+++ b/crypto/asn1/d2i_dhp.c
@@ -64,7 +64,7 @@
 #include "asn1_mac.h"
 
 /*
- * ASN1err(ASN1_F_D2I_DHPARAMS,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_DHPARAMS,ERR_R_ASN1_LENGTH_MISMATCH);
  * ASN1err(ASN1_F_I2D_DHPARAMS,ASN1_R_UNKNOWN_ATTRIBUTE_TYPE);
  */
 
@@ -73,7 +73,7 @@
 unsigned char **pp;
 long length;
 	{
-	int i=ASN1_R_ERROR_STACK;
+	int i=ERR_R_NESTED_ASN1_ERROR;
 	ASN1_INTEGER *bs=NULL;
 	long v=0;
 	M_ASN1_D2I_vars(a,DH *,DH_new);
diff --git a/crypto/asn1/d2i_dsap.c b/crypto/asn1/d2i_dsap.c
index 2c8ac7b..fc2961b 100644
--- a/crypto/asn1/d2i_dsap.c
+++ b/crypto/asn1/d2i_dsap.c
@@ -64,7 +64,7 @@
 #include "asn1_mac.h"
 
 /*
- * ASN1err(ASN1_F_D2I_DSAPARAMS,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_DSAPARAMS,ERR_R_ASN1_LENGTH_MISMATCH);
  * ASN1err(ASN1_F_I2D_DSAPARAMS,ASN1_R_UNKNOWN_ATTRIBUTE_TYPE);
  */
 
@@ -73,7 +73,7 @@
 unsigned char **pp;
 long length;
 	{
-	int i=ASN1_R_ERROR_STACK;
+	int i=ERR_R_NESTED_ASN1_ERROR;
 	ASN1_INTEGER *bs=NULL;
 	M_ASN1_D2I_vars(a,DSA *,DSA_new);
 
diff --git a/crypto/asn1/d2i_pr.c b/crypto/asn1/d2i_pr.c
index b9eaa96..6774035 100644
--- a/crypto/asn1/d2i_pr.c
+++ b/crypto/asn1/d2i_pr.c
@@ -106,7 +106,7 @@
 	default:
 		ASN1err(ASN1_F_D2I_PRIVATEKEY,ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE);
 		goto err;
-		break;
+		/* break; */
 		}
 	if (a != NULL) (*a)=ret;
 	return(ret);
diff --git a/crypto/asn1/d2i_pu.c b/crypto/asn1/d2i_pu.c
index 5d6192f1e..eb572ac 100644
--- a/crypto/asn1/d2i_pu.c
+++ b/crypto/asn1/d2i_pu.c
@@ -106,7 +106,7 @@
 	default:
 		ASN1err(ASN1_F_D2I_PUBLICKEY,ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE);
 		goto err;
-		break;
+		/* break; */
 		}
 	if (a != NULL) (*a)=ret;
 	return(ret);
diff --git a/crypto/asn1/d2i_r_pr.c b/crypto/asn1/d2i_r_pr.c
index 0c53aa9..a276a1d 100644
--- a/crypto/asn1/d2i_r_pr.c
+++ b/crypto/asn1/d2i_r_pr.c
@@ -64,7 +64,7 @@
 #include "asn1_mac.h"
 
 /*
- * ASN1err(ASN1_F_D2I_RSAPRIVATEKEY,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_RSAPRIVATEKEY,ERR_R_ASN1_LENGTH_MISMATCH);
  * ASN1err(ASN1_F_I2D_RSAPRIVATEKEY,ASN1_R_UNKNOWN_ATTRIBUTE_TYPE);
  * ASN1err(ASN1_F_I2D_RSAPRIVATEKEY,ASN1_R_PARSING);
  */
diff --git a/crypto/asn1/d2i_r_pu.c b/crypto/asn1/d2i_r_pu.c
index 778b792..a4e2c22 100644
--- a/crypto/asn1/d2i_r_pu.c
+++ b/crypto/asn1/d2i_r_pu.c
@@ -64,7 +64,7 @@
 #include "asn1_mac.h"
 
 /*
- * ASN1err(ASN1_F_D2I_RSAPUBLICKEY,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_RSAPUBLICKEY,ERR_R_ASN1_LENGTH_MISMATCH);
  * ASN1err(ASN1_F_I2D_RSAPUBLICKEY,ASN1_R_UNKNOWN_ATTRIBUTE_TYPE);
  */
 
diff --git a/crypto/asn1/d2i_s_pr.c b/crypto/asn1/d2i_s_pr.c
index 32ff8ba..8499702 100644
--- a/crypto/asn1/d2i_s_pr.c
+++ b/crypto/asn1/d2i_s_pr.c
@@ -66,7 +66,7 @@
 #include "asn1_mac.h"
 
 /*
- * ASN1err(ASN1_F_D2I_DSAPRIVATEKEY,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_DSAPRIVATEKEY,ERR_R_ASN1_LENGTH_MISMATCH);
  * ASN1err(ASN1_F_I2D_DSAPRIVATEKEY,ASN1_R_UNKNOWN_ATTRIBUTE_TYPE);
  * ASN1err(ASN1_F_I2D_DSAPRIVATEKEY,ASN1_R_PARSING);
  */
diff --git a/crypto/asn1/d2i_s_pu.c b/crypto/asn1/d2i_s_pu.c
index 1002f41..ecf6407 100644
--- a/crypto/asn1/d2i_s_pu.c
+++ b/crypto/asn1/d2i_s_pu.c
@@ -66,7 +66,7 @@
 #include "asn1_mac.h"
 
 /*
- * ASN1err(ASN1_F_D2I_DSAPUBLICKEY,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_DSAPUBLICKEY,ERR_R_ASN1_LENGTH_MISMATCH);
  * ASN1err(ASN1_F_I2D_DSAPUBLICKEY,ASN1_R_UNKNOWN_ATTRIBUTE_TYPE);
  */
 
diff --git a/crypto/asn1/evp_asn1.c b/crypto/asn1/evp_asn1.c
index ebe34a3..4153d1b 100644
--- a/crypto/asn1/evp_asn1.c
+++ b/crypto/asn1/evp_asn1.c
@@ -135,7 +135,8 @@
 	return(1);
 	}
 
-/* we return the actual length... */
+/* we return the actual length..., num may be missing, in which
+ * case, set it to zero */
 int ASN1_TYPE_get_int_octetstring(a,num,data,max_len)
 ASN1_TYPE *a;
 long *num;
diff --git a/crypto/asn1/i2d_dhp.c b/crypto/asn1/i2d_dhp.c
index a454025..a1afa46 100644
--- a/crypto/asn1/i2d_dhp.c
+++ b/crypto/asn1/i2d_dhp.c
@@ -63,8 +63,8 @@
 #include "dh.h"
 
 /*
- * ASN1err(ASN1_F_D2I_DHPARAMS,ASN1_R_LENGTH_MISMATCH);
- * ASN1err(ASN1_F_X509_DHPARAMS_NEW,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_DHPARAMS,ERR_R_ASN1_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_X509_DHPARAMS_NEW,ERR_R_ASN1_LENGTH_MISMATCH);
  */
 
 int i2d_DHparams(a,pp)
diff --git a/crypto/asn1/i2d_dsap.c b/crypto/asn1/i2d_dsap.c
index 94ecff1..0b7d554 100644
--- a/crypto/asn1/i2d_dsap.c
+++ b/crypto/asn1/i2d_dsap.c
@@ -63,7 +63,7 @@
 #include "dsa.h"
 
 /*
- * ASN1err(ASN1_F_D2I_DSAPARAMS,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_DSAPARAMS,ERR_R_ASN1_LENGTH_MISMATCH);
  */
 
 int i2d_DSAparams(a,pp)
diff --git a/crypto/asn1/i2d_r_pr.c b/crypto/asn1/i2d_r_pr.c
index aadbb92..78312db 100644
--- a/crypto/asn1/i2d_r_pr.c
+++ b/crypto/asn1/i2d_r_pr.c
@@ -64,7 +64,7 @@
 #include "asn1_mac.h"
 
 /*
- * ASN1err(ASN1_F_D2I_RSAPRIVATEKEY,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_RSAPRIVATEKEY,ERR_R_ASN1_LENGTH_MISMATCH);
  * ASN1err(ASN1_F_I2D_RSAPRIVATEKEY,ASN1_R_UNKNOWN_ATTRIBUTE_TYPE);
  */
 
diff --git a/crypto/asn1/i2d_r_pu.c b/crypto/asn1/i2d_r_pu.c
index 3c54f67..4bcebaa 100644
--- a/crypto/asn1/i2d_r_pu.c
+++ b/crypto/asn1/i2d_r_pu.c
@@ -64,7 +64,7 @@
 #include "asn1_mac.h"
 
 /*
- * ASN1err(ASN1_F_D2I_RSAPUBLICKEY,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_RSAPUBLICKEY,ERR_R_ASN1_LENGTH_MISMATCH);
  * ASN1err(ASN1_F_I2D_RSAPUBLICKEY,ASN1_R_UNKNOWN_ATTRIBUTE_TYPE);
  */
 
diff --git a/crypto/asn1/n_pkey.c b/crypto/asn1/n_pkey.c
index 5110c91..9649847 100644
--- a/crypto/asn1/n_pkey.c
+++ b/crypto/asn1/n_pkey.c
@@ -75,7 +75,7 @@
 	} NETSCAPE_PKEY;
 
 /*
- * ASN1err(ASN1_F_D2I_NETSCAPE_RSA,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_NETSCAPE_RSA,ERR_R_ASN1_LENGTH_MISMATCH);
  * ASN1err(ASN1_F_D2I_NETSCAPE_RSA,ASN1_R_DECODING_ERROR);
  * ASN1err(ASN1_F_D2I_NETSCAPE_PKEY,ASN1_R_DECODING_ERROR);
  * ASN1err(ASN1_F_NETSCAPE_PKEY_NEW,ASN1_R_DECODING_ERROR);
@@ -249,7 +249,7 @@
 	ASN1_OCTET_STRING *os=NULL;
 	ASN1_CTX c;
 
-	c.error=ASN1_R_ERROR_STACK;
+	c.error=ERR_R_NESTED_ASN1_ERROR;
 	c.pp=pp;
 
 	M_ASN1_D2I_Init();
@@ -342,6 +342,7 @@
 static NETSCAPE_PKEY *NETSCAPE_PKEY_new()
 	{
 	NETSCAPE_PKEY *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,NETSCAPE_PKEY);
 	M_ASN1_New(ret->version,ASN1_INTEGER_new);
diff --git a/crypto/asn1/p7_dgst.c b/crypto/asn1/p7_dgst.c
index f71ed8e..bf7b8e2 100644
--- a/crypto/asn1/p7_dgst.c
+++ b/crypto/asn1/p7_dgst.c
@@ -62,8 +62,8 @@
 #include "x509.h"
 
 /*
- * ASN1err(ASN1_F_PKCS7_DIGEST_NEW,ASN1_R_MISSING_EOS);
- * ASN1err(ASN1_F_D2I_PKCS7_DIGEST,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_PKCS7_DIGEST_NEW,ERR_R_MISSING_ASN1_EOS);
+ * ASN1err(ASN1_F_D2I_PKCS7_DIGEST,ERR_R_ASN1_LENGTH_MISMATCH);
  */
 
 int i2d_PKCS7_DIGEST(a,pp)
@@ -107,6 +107,7 @@
 PKCS7_DIGEST *PKCS7_DIGEST_new()
 	{
 	PKCS7_DIGEST *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,PKCS7_DIGEST);
 	M_ASN1_New(ret->version,ASN1_INTEGER_new);
diff --git a/crypto/asn1/p7_enc.c b/crypto/asn1/p7_enc.c
index 874dd78..56e27fa 100644
--- a/crypto/asn1/p7_enc.c
+++ b/crypto/asn1/p7_enc.c
@@ -62,8 +62,8 @@
 #include "x509.h"
 
 /*
- * ASN1err(ASN1_F_PKCS7_ENCRYPT_NEW,ASN1_R_LENGTH_MISMATCH);
- * ASN1err(ASN1_F_D2I_PKCS7_ENCRYPT,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_PKCS7_ENCRYPT_NEW,ERR_R_ASN1_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_PKCS7_ENCRYPT,ERR_R_ASN1_LENGTH_MISMATCH);
  */
 
 int i2d_PKCS7_ENCRYPT(a,pp)
@@ -101,6 +101,7 @@
 PKCS7_ENCRYPT *PKCS7_ENCRYPT_new()
 	{
 	PKCS7_ENCRYPT *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,PKCS7_ENCRYPT);
 	M_ASN1_New(ret->version,ASN1_INTEGER_new);
diff --git a/crypto/asn1/p7_enc_c.c b/crypto/asn1/p7_enc_c.c
index 2860d3e..f98afb5 100644
--- a/crypto/asn1/p7_enc_c.c
+++ b/crypto/asn1/p7_enc_c.c
@@ -62,8 +62,8 @@
 #include "x509.h"
 
 /*
- * ASN1err(ASN1_F_PKCS7_ENC_CONTENT_NEW,ASN1_R_LENGTH_MISMATCH);
- * ASN1err(ASN1_F_D2I_PKCS7_ENC_CONTENT,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_PKCS7_ENC_CONTENT_NEW,ERR_R_ASN1_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_PKCS7_ENC_CONTENT,ERR_R_ASN1_LENGTH_MISMATCH);
  */
 
 int i2d_PKCS7_ENC_CONTENT(a,pp)
@@ -106,9 +106,11 @@
 PKCS7_ENC_CONTENT *PKCS7_ENC_CONTENT_new()
 	{
 	PKCS7_ENC_CONTENT *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,PKCS7_ENC_CONTENT);
-	M_ASN1_New(ret->content_type,ASN1_OBJECT_new);
+	/* M_ASN1_New(ret->content_type,ASN1_OBJECT_new); */
+	ret->content_type=OBJ_nid2obj(NID_pkcs7_encrypted);
 	M_ASN1_New(ret->algorithm,X509_ALGOR_new);
 	ret->enc_data=NULL;
 	return(ret);
diff --git a/crypto/asn1/p7_evp.c b/crypto/asn1/p7_evp.c
index 4db0a7f..7879a66 100644
--- a/crypto/asn1/p7_evp.c
+++ b/crypto/asn1/p7_evp.c
@@ -62,8 +62,8 @@
 #include "x509.h"
 
 /*
- * ASN1err(ASN1_F_PKCS7_ENVELOPE_NEW,ASN1_R_LENGTH_MISMATCH);
- * ASN1err(ASN1_F_D2I_PKCS7_ENVELOPE,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_PKCS7_ENVELOPE_NEW,ERR_R_ASN1_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_PKCS7_ENVELOPE,ERR_R_ASN1_LENGTH_MISMATCH);
  */
 
 int i2d_PKCS7_ENVELOPE(a,pp)
@@ -95,7 +95,8 @@
 	M_ASN1_D2I_Init();
 	M_ASN1_D2I_start_sequence();
 	M_ASN1_D2I_get(ret->version,d2i_ASN1_INTEGER);
-	M_ASN1_D2I_get_set(ret->recipientinfo,d2i_PKCS7_RECIP_INFO);
+	M_ASN1_D2I_get_set(ret->recipientinfo,d2i_PKCS7_RECIP_INFO,
+		PKCS7_RECIP_INFO_free);
 	M_ASN1_D2I_get(ret->enc_data,d2i_PKCS7_ENC_CONTENT);
 
 	M_ASN1_D2I_Finish(a,PKCS7_ENVELOPE_free,ASN1_F_D2I_PKCS7_ENVELOPE);
@@ -104,6 +105,7 @@
 PKCS7_ENVELOPE *PKCS7_ENVELOPE_new()
 	{
 	PKCS7_ENVELOPE *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,PKCS7_ENVELOPE);
 	M_ASN1_New(ret->version,ASN1_INTEGER_new);
diff --git a/crypto/asn1/p7_i_s.c b/crypto/asn1/p7_i_s.c
index 9b00c55..9bae647 100644
--- a/crypto/asn1/p7_i_s.c
+++ b/crypto/asn1/p7_i_s.c
@@ -62,8 +62,8 @@
 #include "x509.h"
 
 /*
- * ASN1err(ASN1_F_PKCS7_ISSUER_AND_SERIAL_NEW,ASN1_R_LENGTH_MISMATCH);
- * ASN1err(ASN1_F_D2I_PKCS7_ISSUER_AND_SERIAL,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_PKCS7_ISSUER_AND_SERIAL_NEW,ERR_R_ASN1_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_PKCS7_ISSUER_AND_SERIAL,ERR_R_ASN1_LENGTH_MISMATCH);
  */
 
 int i2d_PKCS7_ISSUER_AND_SERIAL(a,pp)
@@ -101,6 +101,7 @@
 PKCS7_ISSUER_AND_SERIAL *PKCS7_ISSUER_AND_SERIAL_new()
 	{
 	PKCS7_ISSUER_AND_SERIAL *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,PKCS7_ISSUER_AND_SERIAL);
 	M_ASN1_New(ret->issuer,X509_NAME_new);
diff --git a/crypto/asn1/p7_lib.c b/crypto/asn1/p7_lib.c
index 2134e09..06e1da4 100644
--- a/crypto/asn1/p7_lib.c
+++ b/crypto/asn1/p7_lib.c
@@ -179,6 +179,7 @@
 			V_ASN1_CONTEXT_SPECIFIC|0))
 			{
 			c.error=ASN1_R_BAD_PKCS7_CONTENT;
+			c.line=__LINE__;
 			goto err;
 			}
 
@@ -187,7 +188,7 @@
 		c.q=c.p;
 		Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,
 			(c.inf & 1)?(length+ *pp-c.q):c.slen);
-		if (Tinf & 0x80) goto err;
+		if (Tinf & 0x80) { c.line=__LINE__; goto err; }
 		c.slen-=(c.p-c.q);
 
 		switch (OBJ_obj2nid(ret->type))
@@ -215,14 +216,16 @@
 			break;
 		default:
 			c.error=ASN1_R_BAD_PKCS7_TYPE;
+			c.line=__LINE__;
 			goto err;
-			break;
+			/* break; */
 			}
 		if (Tinf == (1|V_ASN1_CONSTRUCTED))
 			{
 			if (!ASN1_check_infinite_end(&c.p,c.slen))
 				{
-				c.error=ASN1_R_MISSING_EOS;
+				c.error=ERR_R_MISSING_ASN1_EOS;
+				c.line=__LINE__;
 				goto err;
 				}
 			}
@@ -236,9 +239,10 @@
 PKCS7 *PKCS7_new()
 	{
 	PKCS7 *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,PKCS7);
-	ret->type=ASN1_OBJECT_new();
+	ret->type=OBJ_nid2obj(NID_undef);
 	ret->asn1=NULL;
 	ret->length=0;
 	ret->detached=0;
diff --git a/crypto/asn1/p7_recip.c b/crypto/asn1/p7_recip.c
index f02233f..2516d7b 100644
--- a/crypto/asn1/p7_recip.c
+++ b/crypto/asn1/p7_recip.c
@@ -62,8 +62,8 @@
 #include "x509.h"
 
 /*
- * ASN1err(ASN1_F_PKCS7_RECIP_INFO_NEW,ASN1_R_LENGTH_MISMATCH);
- * ASN1err(ASN1_F_D2I_PKCS7_RECIP_INFO,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_PKCS7_RECIP_INFO_NEW,ERR_R_ASN1_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_PKCS7_RECIP_INFO,ERR_R_ASN1_LENGTH_MISMATCH);
  */
 
 int i2d_PKCS7_RECIP_INFO(a,pp)
@@ -107,6 +107,7 @@
 PKCS7_RECIP_INFO *PKCS7_RECIP_INFO_new()
 	{
 	PKCS7_RECIP_INFO *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,PKCS7_RECIP_INFO);
 	M_ASN1_New(ret->version,ASN1_INTEGER_new);
diff --git a/crypto/asn1/p7_s_e.c b/crypto/asn1/p7_s_e.c
index d344211..0368bcb 100644
--- a/crypto/asn1/p7_s_e.c
+++ b/crypto/asn1/p7_s_e.c
@@ -62,8 +62,8 @@
 #include "x509.h"
 
 /*
- * ASN1err(ASN1_F_PKCS7_SIGN_ENVELOPE_NEW,ASN1_R_LENGTH_MISMATCH);
- * ASN1err(ASN1_F_D2I_PKCS7_SIGN_ENVELOPE,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_PKCS7_SIGN_ENVELOPE_NEW,ERR_R_ASN1_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_PKCS7_SIGN_ENVELOPE,ERR_R_ASN1_LENGTH_MISMATCH);
  */
 
 int i2d_PKCS7_SIGN_ENVELOPE(a,pp)
@@ -103,12 +103,14 @@
 	M_ASN1_D2I_Init();
 	M_ASN1_D2I_start_sequence();
 	M_ASN1_D2I_get(ret->version,d2i_ASN1_INTEGER);
-	M_ASN1_D2I_get_set(ret->recipientinfo,d2i_PKCS7_RECIP_INFO);
-	M_ASN1_D2I_get_set(ret->md_algs,d2i_X509_ALGOR);
+	M_ASN1_D2I_get_set(ret->recipientinfo,d2i_PKCS7_RECIP_INFO,
+		PKCS7_RECIP_INFO_free);
+	M_ASN1_D2I_get_set(ret->md_algs,d2i_X509_ALGOR,X509_ALGOR_free);
 	M_ASN1_D2I_get(ret->enc_data,d2i_PKCS7_ENC_CONTENT);
-	M_ASN1_D2I_get_IMP_set_opt(ret->cert,d2i_X509,0);
-	M_ASN1_D2I_get_IMP_set_opt(ret->crl,d2i_X509_CRL,1);
-	M_ASN1_D2I_get_set(ret->signer_info,d2i_PKCS7_SIGNER_INFO);
+	M_ASN1_D2I_get_IMP_set_opt(ret->cert,d2i_X509,X509_free,0);
+	M_ASN1_D2I_get_IMP_set_opt(ret->crl,d2i_X509_CRL,X509_CRL_free,1);
+	M_ASN1_D2I_get_set(ret->signer_info,d2i_PKCS7_SIGNER_INFO,
+		PKCS7_SIGNER_INFO_free);
 
 	M_ASN1_D2I_Finish(a,PKCS7_SIGN_ENVELOPE_free,
 		ASN1_F_D2I_PKCS7_SIGN_ENVELOPE);
@@ -117,6 +119,7 @@
 PKCS7_SIGN_ENVELOPE *PKCS7_SIGN_ENVELOPE_new()
 	{
 	PKCS7_SIGN_ENVELOPE *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,PKCS7_SIGN_ENVELOPE);
 	M_ASN1_New(ret->version,ASN1_INTEGER_new);
diff --git a/crypto/asn1/p7_signd.c b/crypto/asn1/p7_signd.c
index 40f9a44..830617c 100644
--- a/crypto/asn1/p7_signd.c
+++ b/crypto/asn1/p7_signd.c
@@ -62,8 +62,8 @@
 #include "x509.h"
 
 /*
- * ASN1err(ASN1_F_PKCS7_SIGNED_NEW,ASN1_R_LENGTH_MISMATCH);
- * ASN1err(ASN1_F_D2I_PKCS7_SIGNED,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_PKCS7_SIGNED_NEW,ERR_R_ASN1_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_PKCS7_SIGNED,ERR_R_ASN1_LENGTH_MISMATCH);
  */
 
 int i2d_PKCS7_SIGNED(a,pp)
@@ -101,11 +101,12 @@
 	M_ASN1_D2I_Init();
 	M_ASN1_D2I_start_sequence();
 	M_ASN1_D2I_get(ret->version,d2i_ASN1_INTEGER);
-	M_ASN1_D2I_get_set(ret->md_algs,d2i_X509_ALGOR);
+	M_ASN1_D2I_get_set(ret->md_algs,d2i_X509_ALGOR,X509_ALGOR_free);
 	M_ASN1_D2I_get(ret->contents,d2i_PKCS7);
-	M_ASN1_D2I_get_IMP_set_opt(ret->cert,d2i_X509,0);
-	M_ASN1_D2I_get_IMP_set_opt(ret->crl,d2i_X509_CRL,1);
-	M_ASN1_D2I_get_set(ret->signer_info,d2i_PKCS7_SIGNER_INFO);
+	M_ASN1_D2I_get_IMP_set_opt(ret->cert,d2i_X509,X509_free,0);
+	M_ASN1_D2I_get_IMP_set_opt(ret->crl,d2i_X509_CRL,X509_CRL_free,1);
+	M_ASN1_D2I_get_set(ret->signer_info,d2i_PKCS7_SIGNER_INFO,
+		PKCS7_SIGNER_INFO_free);
 
 	M_ASN1_D2I_Finish(a,PKCS7_SIGNED_free,ASN1_F_D2I_PKCS7_SIGNED);
 	}
@@ -113,6 +114,7 @@
 PKCS7_SIGNED *PKCS7_SIGNED_new()
 	{
 	PKCS7_SIGNED *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,PKCS7_SIGNED);
 	M_ASN1_New(ret->version,ASN1_INTEGER_new);
diff --git a/crypto/asn1/p7_signi.c b/crypto/asn1/p7_signi.c
index 0da9216..4bc415d 100644
--- a/crypto/asn1/p7_signi.c
+++ b/crypto/asn1/p7_signi.c
@@ -62,8 +62,8 @@
 #include "x509.h"
 
 /*
- * ASN1err(ASN1_F_PKCS7_SIGNER_INFO_NEW,ASN1_R_LENGTH_MISMATCH);
- * ASN1err(ASN1_F_D2I_PKCS7_SIGNER_INFO,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_PKCS7_SIGNER_INFO_NEW,ERR_R_ASN1_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_PKCS7_SIGNER_INFO,ERR_R_ASN1_LENGTH_MISMATCH);
  */
 
 int i2d_PKCS7_SIGNER_INFO(a,pp)
@@ -105,10 +105,12 @@
 	M_ASN1_D2I_get(ret->version,d2i_ASN1_INTEGER);
 	M_ASN1_D2I_get(ret->issuer_and_serial,d2i_PKCS7_ISSUER_AND_SERIAL);
 	M_ASN1_D2I_get(ret->digest_alg,d2i_X509_ALGOR);
-	M_ASN1_D2I_get_IMP_set_opt(ret->auth_attr,d2i_X509_ATTRIBUTE,0);
+	M_ASN1_D2I_get_IMP_set_opt(ret->auth_attr,d2i_X509_ATTRIBUTE,
+		X509_ATTRIBUTE_free,0);
 	M_ASN1_D2I_get(ret->digest_enc_alg,d2i_X509_ALGOR);
 	M_ASN1_D2I_get(ret->enc_digest,d2i_ASN1_OCTET_STRING);
-	M_ASN1_D2I_get_IMP_set_opt(ret->unauth_attr,d2i_X509_ATTRIBUTE,1);
+	M_ASN1_D2I_get_IMP_set_opt(ret->unauth_attr,d2i_X509_ATTRIBUTE,
+		X509_ATTRIBUTE_free,1);
 
 	M_ASN1_D2I_Finish(a,PKCS7_SIGNER_INFO_free,
 		ASN1_F_D2I_PKCS7_SIGNER_INFO);
@@ -117,6 +119,7 @@
 PKCS7_SIGNER_INFO *PKCS7_SIGNER_INFO_new()
 	{
 	PKCS7_SIGNER_INFO *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,PKCS7_SIGNER_INFO);
 	M_ASN1_New(ret->version,ASN1_INTEGER_new);
diff --git a/crypto/asn1/pkcs8.c b/crypto/asn1/pkcs8.c
index 03fdadd..d2bc9ce 100644
--- a/crypto/asn1/pkcs8.c
+++ b/crypto/asn1/pkcs8.c
@@ -62,8 +62,8 @@
 #include "objects.h"
 
 /*
- * ASN1err(ASN1_F_D2I_X509_KEY,ASN1_R_LENGTH_MISMATCH);
- * ASN1err(ASN1_F_X509_KEY_NEW,ASN1_R_BAD_GET_OBJECT);
+ * ASN1err(ASN1_F_D2I_X509_KEY,ERR_R_ASN1_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_X509_KEY_NEW,ERR_R_BAD_GET_ASN1_OBJECT_CALL);
  */
 
 int i2d_X509_KEY(a,pp)
diff --git a/crypto/asn1/t_x509.c b/crypto/asn1/t_x509.c
index b10fbbb..9a8c8bf 100644
--- a/crypto/asn1/t_x509.c
+++ b/crypto/asn1/t_x509.c
@@ -158,6 +158,11 @@
 		(i == NID_undef)?"UNKNOWN":OBJ_nid2ln(i)) <= 0) goto err;
 
 	pkey=X509_get_pubkey(x);
+	if (pkey == NULL)
+		{
+		BIO_printf(bp,"%12sUnable to load Public Key\n","");
+		}
+	else
 #ifndef NO_RSA
 	if (pkey->type == EVP_PKEY_RSA)
 		{
@@ -175,7 +180,7 @@
 		}
 	else
 #endif
-		BIO_printf(bp,"%12sDSA Public Key:\n","");
+		BIO_printf(bp,"%12sUnknown Public Key:\n","");
 
 	n=X509_get_ext_count(x);
 	if (n > 0)
diff --git a/crypto/asn1/x b/crypto/asn1/x
new file mode 100644
index 0000000..13acdab
--- /dev/null
+++ b/crypto/asn1/x
@@ -0,0 +1,353 @@
+/* crypto/asn1/x_crl.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 "cryptlib.h"
+#include "asn1_mac.h"
+#include "x509.h"
+
+/*
+ * ASN1err(ASN1_F_D2I_X509_CRL,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_X509_CRL_INFO,ASN1_R_EXPECTING_A_SEQUENCE);
+ * ASN1err(ASN1_F_D2I_X509_REVOKED,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_X509_CRL_NEW,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_X509_CRL_INFO_NEW,ASN1_R_EXPECTING_A_SEQUENCE);
+ * ASN1err(ASN1_F_X509_REVOKED_NEW,ASN1_R_LENGTH_MISMATCH);
+ */
+
+#ifndef NOPROTO
+static int X509_REVOKED_cmp(X509_REVOKED **a,X509_REVOKED **b);
+static int X509_REVOKED_seq_cmp(X509_REVOKED **a,X509_REVOKED **b);
+#else
+static int X509_REVOKED_cmp();
+static int X509_REVOKED_seq_cmp();
+#endif
+
+int i2d_X509_REVOKED(a,pp)
+X509_REVOKED *a;
+unsigned char **pp;
+	{
+	M_ASN1_I2D_vars(a);
+
+	M_ASN1_I2D_len(a->serialNumber,i2d_ASN1_INTEGER);
+	M_ASN1_I2D_len(a->revocationDate,i2d_ASN1_UTCTIME);
+	M_ASN1_I2D_len_SEQ_opt(a->extensions,i2d_X509_EXTENSION);
+
+	M_ASN1_I2D_seq_total();
+
+	M_ASN1_I2D_put(a->serialNumber,i2d_ASN1_INTEGER);
+	M_ASN1_I2D_put(a->revocationDate,i2d_ASN1_UTCTIME);
+	M_ASN1_I2D_put_SEQ_opt(a->extensions,i2d_X509_EXTENSION);
+
+	M_ASN1_I2D_finish();
+	}
+
+X509_REVOKED *d2i_X509_REVOKED(a,pp,length)
+X509_REVOKED **a;
+unsigned char **pp;
+long length;
+	{
+	M_ASN1_D2I_vars(a,X509_REVOKED *,X509_REVOKED_new);
+
+	M_ASN1_D2I_Init();
+	M_ASN1_D2I_start_sequence();
+	M_ASN1_D2I_get(ret->serialNumber,d2i_ASN1_INTEGER);
+	M_ASN1_D2I_get(ret->revocationDate,d2i_ASN1_UTCTIME);
+	M_ASN1_D2I_get_seq_opt(ret->extensions,d2i_X509_EXTENSION);
+	M_ASN1_D2I_Finish(a,X509_REVOKED_free,ASN1_F_D2I_X509_REVOKED);
+	}
+
+int i2d_X509_CRL_INFO(a,pp)
+X509_CRL_INFO *a;
+unsigned char **pp;
+	{
+	int v1=0;
+	long l=0;
+	M_ASN1_I2D_vars(a);
+
+	if (sk_num(a->revoked) != 0)
+		qsort((char *)a->revoked->data,sk_num(a->revoked),
+			sizeof(X509_REVOKED *),(int (*)(P_CC_CC))X509_REVOKED_seq_cmp);
+	if ((a->version != NULL) && ((l=ASN1_INTEGER_get(a->version)) != 0))
+		{
+		M_ASN1_I2D_len(a->version,i2d_ASN1_INTEGER);
+		}
+	M_ASN1_I2D_len(a->sig_alg,i2d_X509_ALGOR);
+	M_ASN1_I2D_len(a->issuer,i2d_X509_NAME);
+	M_ASN1_I2D_len(a->lastUpdate,i2d_ASN1_UTCTIME);
+	if (a->nextUpdate != NULL)
+		{ M_ASN1_I2D_len(a->nextUpdate,i2d_ASN1_UTCTIME); }
+	M_ASN1_I2D_len_SEQ_opt(a->revoked,i2d_X509_REVOKED);
+	M_ASN1_I2D_len_EXP_set_opt(a->extensions,i2d_X509_EXTENSION,0,
+		V_ASN1_SEQUENCE,v1);
+
+	M_ASN1_I2D_seq_total();
+
+	if ((a->version != NULL) && (l != 0))
+		{
+		M_ASN1_I2D_put(a->version,i2d_ASN1_INTEGER);
+		}
+	M_ASN1_I2D_put(a->sig_alg,i2d_X509_ALGOR);
+	M_ASN1_I2D_put(a->issuer,i2d_X509_NAME);
+	M_ASN1_I2D_put(a->lastUpdate,i2d_ASN1_UTCTIME);
+	if (a->nextUpdate != NULL)
+		{ M_ASN1_I2D_put(a->nextUpdate,i2d_ASN1_UTCTIME); }
+	M_ASN1_I2D_put_SEQ_opt(a->revoked,i2d_X509_REVOKED);
+	M_ASN1_I2D_put_EXP_set_opt(a->extensions,i2d_X509_EXTENSION,0,
+		V_ASN1_SEQUENCE,v1);
+
+	M_ASN1_I2D_finish();
+	}
+
+X509_CRL_INFO *d2i_X509_CRL_INFO(a,pp,length)
+X509_CRL_INFO **a;
+unsigned char **pp;
+long length;
+	{
+	int i,ver=0;
+	M_ASN1_D2I_vars(a,X509_CRL_INFO *,X509_CRL_INFO_new);
+
+
+	M_ASN1_D2I_Init();
+	M_ASN1_D2I_start_sequence();
+	M_ASN1_D2I_get_opt(ret->version,d2i_ASN1_INTEGER,V_ASN1_INTEGER);
+	if (ret->version != NULL)
+		ver=ret->version->data[0];
+	
+	if ((ver == 0) && (ret->version != NULL))
+		{
+		ASN1_INTEGER_free(ret->version);
+		ret->version=NULL;
+		}
+	M_ASN1_D2I_get(ret->sig_alg,d2i_X509_ALGOR);
+	M_ASN1_D2I_get(ret->issuer,d2i_X509_NAME);
+	M_ASN1_D2I_get(ret->lastUpdate,d2i_ASN1_UTCTIME);
+	M_ASN1_D2I_get_opt(ret->nextUpdate,d2i_ASN1_UTCTIME,V_ASN1_UTCTIME);
+	if (ret->revoked != NULL)
+		{
+		while (sk_num(ret->revoked))
+			X509_REVOKED_free((X509_REVOKED *)sk_pop(ret->revoked));
+		}
+	M_ASN1_D2I_get_seq_opt(ret->revoked,d2i_X509_REVOKED);
+
+	if (ret->revoked != NULL)
+		{
+		for (i=0; i<sk_num(ret->revoked); i++)
+			{
+			((X509_REVOKED *)sk_value(ret->revoked,i))->sequence=i;
+			}
+		}
+
+	if (ver >= 1)
+		{
+		if (ret->extensions != NULL)
+			{
+			while (sk_num(ret->extensions))
+				X509_EXTENSION_free((X509_EXTENSION *)
+				sk_pop(ret->extensions));
+			}
+			
+		M_ASN1_D2I_get_EXP_set_opt(ret->extensions,d2i_X509_EXTENSION,
+			0,V_ASN1_SEQUENCE);
+		}
+
+	M_ASN1_D2I_Finish(a,X509_CRL_INFO_free,ASN1_F_D2I_X509_CRL_INFO);
+	}
+
+int i2d_X509_CRL(a,pp)
+X509_CRL *a;
+unsigned char **pp;
+	{
+	M_ASN1_I2D_vars(a);
+
+	M_ASN1_I2D_len(a->crl,i2d_X509_CRL_INFO);
+	M_ASN1_I2D_len(a->sig_alg,i2d_X509_ALGOR);
+	M_ASN1_I2D_len(a->signature,i2d_ASN1_BIT_STRING);
+
+	M_ASN1_I2D_seq_total();
+
+	M_ASN1_I2D_put(a->crl,i2d_X509_CRL_INFO);
+	M_ASN1_I2D_put(a->sig_alg,i2d_X509_ALGOR);
+	M_ASN1_I2D_put(a->signature,i2d_ASN1_BIT_STRING);
+
+	M_ASN1_I2D_finish();
+	}
+
+X509_CRL *d2i_X509_CRL(a,pp,length)
+X509_CRL **a;
+unsigned char **pp;
+long length;
+	{
+	M_ASN1_D2I_vars(a,X509_CRL *,X509_CRL_new);
+
+	M_ASN1_D2I_Init();
+	M_ASN1_D2I_start_sequence();
+	M_ASN1_D2I_get(ret->crl,d2i_X509_CRL_INFO);
+	M_ASN1_D2I_get(ret->sig_alg,d2i_X509_ALGOR);
+	M_ASN1_D2I_get(ret->signature,d2i_ASN1_BIT_STRING);
+
+	M_ASN1_D2I_Finish(a,X509_CRL_free,ASN1_F_D2I_X509_CRL);
+	}
+
+
+X509_REVOKED *X509_REVOKED_new()
+	{
+	X509_REVOKED *ret=NULL;
+
+	M_ASN1_New_Malloc(ret,X509_REVOKED);
+	M_ASN1_New(ret->serialNumber,ASN1_INTEGER_new);
+	M_ASN1_New(ret->revocationDate,ASN1_UTCTIME_new);
+	ret->extensions=NULL;
+	return(ret);
+	M_ASN1_New_Error(ASN1_F_X509_REVOKED_NEW);
+	}
+
+X509_CRL_INFO *X509_CRL_INFO_new()
+	{
+	X509_CRL_INFO *ret=NULL;
+
+	M_ASN1_New_Malloc(ret,X509_CRL_INFO);
+	ret->version=NULL;
+	M_ASN1_New(ret->sig_alg,X509_ALGOR_new);
+	M_ASN1_New(ret->issuer,X509_NAME_new);
+	M_ASN1_New(ret->lastUpdate,ASN1_UTCTIME_new);
+	ret->nextUpdate=NULL;
+	M_ASN1_New(ret->revoked,sk_new_null);
+	M_ASN1_New(ret->extensions,sk_new_null);
+	ret->revoked->comp=(int (*)())X509_REVOKED_cmp;
+	return(ret);
+	M_ASN1_New_Error(ASN1_F_X509_CRL_INFO_NEW);
+	}
+
+X509_CRL *X509_CRL_new()
+	{
+	X509_CRL *ret=NULL;
+
+	M_ASN1_New_Malloc(ret,X509_CRL);
+	ret->references=1;
+	M_ASN1_New(ret->crl,X509_CRL_INFO_new);
+	M_ASN1_New(ret->sig_alg,X509_ALGOR_new);
+	M_ASN1_New(ret->signature,ASN1_BIT_STRING_new);
+	return(ret);
+	M_ASN1_New_Error(ASN1_F_X509_CRL_NEW);
+	}
+
+void X509_REVOKED_free(a)
+X509_REVOKED *a;
+	{
+	if (a == NULL) return;
+	ASN1_INTEGER_free(a->serialNumber);
+	ASN1_UTCTIME_free(a->revocationDate);
+	sk_pop_free(a->extensions,X509_EXTENSION_free);
+	Free((char *)a);
+	}
+
+void X509_CRL_INFO_free(a)
+X509_CRL_INFO *a;
+	{
+	if (a == NULL) return;
+	ASN1_INTEGER_free(a->version);
+	X509_ALGOR_free(a->sig_alg);
+	X509_NAME_free(a->issuer);
+	ASN1_UTCTIME_free(a->lastUpdate);
+	if (a->nextUpdate)
+		ASN1_UTCTIME_free(a->nextUpdate);
+	sk_pop_free(a->revoked,X509_REVOKED_free);
+	sk_pop_free(a->extensions,X509_EXTENSION_free);
+	Free((char *)a);
+	}
+
+void X509_CRL_free(a)
+X509_CRL *a;
+	{
+	int i;
+
+	if (a == NULL) return;
+
+	i=CRYPTO_add(&a->references,-1,CRYPTO_LOCK_X509_CRL);
+#ifdef REF_PRINT
+	REF_PRINT("X509_CRL",a);
+#endif
+	if (i > 0) return;
+#ifdef REF_CHECK
+	if (i < 0)
+		{
+		fprintf(stderr,"X509_CRL_free, bad reference count\n");
+		abort();
+		}
+#endif
+
+	X509_CRL_INFO_free(a->crl);
+	X509_ALGOR_free(a->sig_alg);
+	ASN1_BIT_STRING_free(a->signature);
+	Free((char *)a);
+	}
+
+static int X509_REVOKED_cmp(a,b)
+X509_REVOKED **a,**b;
+	{
+	return(ASN1_STRING_cmp(
+		(ASN1_STRING *)(*a)->serialNumber,
+		(ASN1_STRING *)(*b)->serialNumber));
+	}
+
+static int X509_REVOKED_seq_cmp(a,b)
+X509_REVOKED **a,**b;
+	{
+	return((*a)->sequence-(*b)->sequence);
+	}
diff --git a/crypto/asn1/x_algor.c b/crypto/asn1/x_algor.c
index 0ed2c87..01aa0cb 100644
--- a/crypto/asn1/x_algor.c
+++ b/crypto/asn1/x_algor.c
@@ -61,9 +61,9 @@
 #include "asn1_mac.h"
 
 /*
- * ASN1err(ASN1_F_D2I_X509_ALGOR,ASN1_R_LENGTH_MISMATCH);
- * ASN1err(ASN1_F_X509_ALGOR_NEW,ASN1_R_EXPECTING_A_SEQUENCE);
- * ASN1err(ASN1_F_D2I_X509_ALGOR,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_X509_ALGOR,ERR_R_ASN1_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_X509_ALGOR_NEW,ERR_R_EXPECTING_AN_ASN1_SEQUENCE);
+ * ASN1err(ASN1_F_D2I_X509_ALGOR,ERR_R_ASN1_LENGTH_MISMATCH);
  */
 
 int i2d_X509_ALGOR(a,pp)
@@ -107,9 +107,10 @@
 X509_ALGOR *X509_ALGOR_new()
 	{
 	X509_ALGOR *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,X509_ALGOR);
-	M_ASN1_New(ret->algorithm,ASN1_OBJECT_new);
+	ret->algorithm=OBJ_nid2obj(NID_undef);
 	ret->parameter=NULL;
 	return(ret);
 	M_ASN1_New_Error(ASN1_F_X509_ALGOR_NEW);
diff --git a/crypto/asn1/x_attrib.c b/crypto/asn1/x_attrib.c
index e52ced8..d9faf14 100644
--- a/crypto/asn1/x_attrib.c
+++ b/crypto/asn1/x_attrib.c
@@ -62,7 +62,7 @@
 #include "asn1_mac.h"
 
 /*
- * ASN1err(ASN1_F_D2I_X509_ATTRIBUTE,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_X509_ATTRIBUTE,ERR_R_ASN1_LENGTH_MISMATCH);
  * ASN1err(ASN1_F_X509_ATTRIBUTE_NEW,ASN1_R_UNKNOWN_ATTRIBUTE_TYPE);
  * ASN1err(ASN1_F_I2D_X509_ATTRIBUTE,ASN1_R_UNKNOWN_ATTRIBUTE_TYPE);
  */
@@ -115,7 +115,7 @@
 		(M_ASN1_next == (V_ASN1_CONSTRUCTED|V_ASN1_UNIVERSAL|V_ASN1_SET)))
 		{
 		ret->set=1;
-		M_ASN1_D2I_get_set(ret->value.set,d2i_ASN1_TYPE);
+		M_ASN1_D2I_get_set(ret->value.set,d2i_ASN1_TYPE,ASN1_TYPE_free);
 		}
 	else
 		{
@@ -126,12 +126,37 @@
 	M_ASN1_D2I_Finish(a,X509_ATTRIBUTE_free,ASN1_F_D2I_X509_ATTRIBUTE);
 	}
 
+X509_ATTRIBUTE *X509_ATTRIBUTE_create(nid,atrtype,value)
+int nid;
+int atrtype;
+char *value;
+	{
+	X509_ATTRIBUTE *ret=NULL;
+	ASN1_TYPE *val=NULL;
+
+	if ((ret=X509_ATTRIBUTE_new()) == NULL)
+		return(NULL);
+	ret->object=OBJ_nid2obj(nid);
+	ret->set=1;
+	if ((ret->value.set=sk_new_null()) == NULL) goto err;
+	if ((val=ASN1_TYPE_new()) == NULL) goto err;
+	if (!sk_push(ret->value.set,(char *)val)) goto err;
+
+	ASN1_TYPE_set(val,atrtype,value);
+	return(ret);
+err:
+	if (ret != NULL) X509_ATTRIBUTE_free(ret);
+	if (val != NULL) ASN1_TYPE_free(val);
+	return(NULL);
+	}
+
 X509_ATTRIBUTE *X509_ATTRIBUTE_new()
 	{
 	X509_ATTRIBUTE *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,X509_ATTRIBUTE);
-	M_ASN1_New(ret->object,ASN1_OBJECT_new);
+	ret->object=OBJ_nid2obj(NID_undef);
 	ret->set=0;
 	ret->value.ptr=NULL;
 	return(ret);
diff --git a/crypto/asn1/x_cinf.c b/crypto/asn1/x_cinf.c
index 4fc2cc9..27aad14 100644
--- a/crypto/asn1/x_cinf.c
+++ b/crypto/asn1/x_cinf.c
@@ -61,8 +61,8 @@
 #include "asn1_mac.h"
 
 /*
- * ASN1err(ASN1_F_D2I_X509_CINF,ASN1_R_LENGTH_MISMATCH);
- * ASN1err(ASN1_F_X509_CINF_NEW,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_X509_CINF,ERR_R_ASN1_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_X509_CINF_NEW,ERR_R_ASN1_LENGTH_MISMATCH);
  */
 
 int i2d_X509_CINF(a,pp)
@@ -140,7 +140,7 @@
 		if (ret->subjectUID != NULL)
 			{
 			ASN1_BIT_STRING_free(ret->subjectUID);
-			ret->issuerUID=NULL;
+			ret->subjectUID=NULL;
 			}
 		M_ASN1_D2I_get_IMP_opt(ret->issuerUID,d2i_ASN1_BIT_STRING,  1,
 			V_ASN1_BIT_STRING);
@@ -153,8 +153,8 @@
 			while (sk_num(ret->extensions))
 				X509_EXTENSION_free((X509_EXTENSION *)
 					sk_pop(ret->extensions));
-		M_ASN1_D2I_get_EXP_set_opt(ret->extensions,d2i_X509_EXTENSION,3,
-			V_ASN1_SEQUENCE);
+		M_ASN1_D2I_get_EXP_set_opt(ret->extensions,d2i_X509_EXTENSION,
+			X509_EXTENSION_free,3,V_ASN1_SEQUENCE);
 		}
 	M_ASN1_D2I_Finish(a,X509_CINF_free,ASN1_F_D2I_X509_CINF);
 	}
@@ -162,6 +162,7 @@
 X509_CINF *X509_CINF_new()
 	{
 	X509_CINF *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,X509_CINF);
 	ret->version=NULL;
diff --git a/crypto/asn1/x_crl.c b/crypto/asn1/x_crl.c
index 13acdab..fe7b5f1 100644
--- a/crypto/asn1/x_crl.c
+++ b/crypto/asn1/x_crl.c
@@ -62,12 +62,12 @@
 #include "x509.h"
 
 /*
- * ASN1err(ASN1_F_D2I_X509_CRL,ASN1_R_LENGTH_MISMATCH);
- * ASN1err(ASN1_F_D2I_X509_CRL_INFO,ASN1_R_EXPECTING_A_SEQUENCE);
- * ASN1err(ASN1_F_D2I_X509_REVOKED,ASN1_R_LENGTH_MISMATCH);
- * ASN1err(ASN1_F_X509_CRL_NEW,ASN1_R_LENGTH_MISMATCH);
- * ASN1err(ASN1_F_X509_CRL_INFO_NEW,ASN1_R_EXPECTING_A_SEQUENCE);
- * ASN1err(ASN1_F_X509_REVOKED_NEW,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_X509_CRL,ERR_R_ASN1_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_X509_CRL_INFO,ERR_R_EXPECTING_AN_ASN1_SEQUENCE);
+ * ASN1err(ASN1_F_D2I_X509_REVOKED,ERR_R_ASN1_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_X509_CRL_NEW,ERR_R_ASN1_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_X509_CRL_INFO_NEW,ERR_R_EXPECTING_AN_ASN1_SEQUENCE);
+ * ASN1err(ASN1_F_X509_REVOKED_NEW,ERR_R_ASN1_LENGTH_MISMATCH);
  */
 
 #ifndef NOPROTO
@@ -108,7 +108,8 @@
 	M_ASN1_D2I_start_sequence();
 	M_ASN1_D2I_get(ret->serialNumber,d2i_ASN1_INTEGER);
 	M_ASN1_D2I_get(ret->revocationDate,d2i_ASN1_UTCTIME);
-	M_ASN1_D2I_get_seq_opt(ret->extensions,d2i_X509_EXTENSION);
+	M_ASN1_D2I_get_seq_opt(ret->extensions,d2i_X509_EXTENSION,
+		X509_EXTENSION_free);
 	M_ASN1_D2I_Finish(a,X509_REVOKED_free,ASN1_F_D2I_X509_REVOKED);
 	}
 
@@ -183,7 +184,7 @@
 		while (sk_num(ret->revoked))
 			X509_REVOKED_free((X509_REVOKED *)sk_pop(ret->revoked));
 		}
-	M_ASN1_D2I_get_seq_opt(ret->revoked,d2i_X509_REVOKED);
+	M_ASN1_D2I_get_seq_opt(ret->revoked,d2i_X509_REVOKED,X509_REVOKED_free);
 
 	if (ret->revoked != NULL)
 		{
@@ -203,7 +204,7 @@
 			}
 			
 		M_ASN1_D2I_get_EXP_set_opt(ret->extensions,d2i_X509_EXTENSION,
-			0,V_ASN1_SEQUENCE);
+			X509_EXTENSION_free,0,V_ASN1_SEQUENCE);
 		}
 
 	M_ASN1_D2I_Finish(a,X509_CRL_INFO_free,ASN1_F_D2I_X509_CRL_INFO);
@@ -248,6 +249,7 @@
 X509_REVOKED *X509_REVOKED_new()
 	{
 	X509_REVOKED *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,X509_REVOKED);
 	M_ASN1_New(ret->serialNumber,ASN1_INTEGER_new);
@@ -260,6 +262,7 @@
 X509_CRL_INFO *X509_CRL_INFO_new()
 	{
 	X509_CRL_INFO *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,X509_CRL_INFO);
 	ret->version=NULL;
@@ -277,6 +280,7 @@
 X509_CRL *X509_CRL_new()
 	{
 	X509_CRL *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,X509_CRL);
 	ret->references=1;
diff --git a/crypto/asn1/x_exten.c b/crypto/asn1/x_exten.c
index 54ffe2f..f5e3ece 100644
--- a/crypto/asn1/x_exten.c
+++ b/crypto/asn1/x_exten.c
@@ -62,8 +62,8 @@
 #include "asn1_mac.h"
 
 /*
- * ASN1err(ASN1_F_D2I_X509_EXTENSION,ASN1_R_LENGTH_MISMATCH);
- * ASN1err(ASN1_F_X509_EXTENSION_NEW,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_X509_EXTENSION,ERR_R_ASN1_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_X509_EXTENSION_NEW,ERR_R_ASN1_LENGTH_MISMATCH);
  */
 
 int i2d_X509_EXTENSION(a,pp)
@@ -130,9 +130,10 @@
 X509_EXTENSION *X509_EXTENSION_new()
 	{
 	X509_EXTENSION *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,X509_EXTENSION);
-	M_ASN1_New(ret->object,ASN1_OBJECT_new);
+	ret->object=OBJ_nid2obj(NID_undef);
 	M_ASN1_New(ret->value,ASN1_OCTET_STRING_new);
 	ret->critical=0;
 	ret->netscape_hack=0;
diff --git a/crypto/asn1/x_name.c b/crypto/asn1/x_name.c
index 28b9c34..3b8bc51 100644
--- a/crypto/asn1/x_name.c
+++ b/crypto/asn1/x_name.c
@@ -62,9 +62,9 @@
 #include "asn1_mac.h"
 
 /*
- * ASN1err(ASN1_F_D2I_X509_NAME,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_X509_NAME,ERR_R_ASN1_LENGTH_MISMATCH);
  * ASN1err(ASN1_F_X509_NAME_NEW,ASN1_R_UNKNOWN_ATTRIBUTE_TYPE);
- * ASN1err(ASN1_F_D2I_X509_NAME_ENTRY,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_X509_NAME_ENTRY,ERR_R_ASN1_LENGTH_MISMATCH);
  * ASN1err(ASN1_F_X509_NAME_ENTRY_NEW,ASN1_R_UNKNOWN_ATTRIBUTE_TYPE);
  */
 
@@ -213,7 +213,8 @@
 	for (;;)
 		{
 		if (M_ASN1_D2I_end_sequence()) break;
-		M_ASN1_D2I_get_set(ret->entries,d2i_X509_NAME_ENTRY);
+		M_ASN1_D2I_get_set(ret->entries,d2i_X509_NAME_ENTRY,
+			X509_NAME_ENTRY_free);
 		for (; idx < sk_num(ret->entries); idx++)
 			{
 			((X509_NAME_ENTRY *)sk_value(ret->entries,idx))->set=
@@ -234,9 +235,11 @@
 X509_NAME *X509_NAME_new()
 	{
 	X509_NAME *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,X509_NAME);
-	if ((ret->entries=sk_new(NULL)) == NULL) goto err2;
+	if ((ret->entries=sk_new(NULL)) == NULL)
+		{ c.line=__LINE__; goto err2; }
 	M_ASN1_New(ret->bytes,BUF_MEM_new);
 	ret->modified=1;
 	return(ret);
@@ -246,6 +249,7 @@
 X509_NAME_ENTRY *X509_NAME_ENTRY_new()
 	{
 	X509_NAME_ENTRY *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,X509_NAME_ENTRY);
 /*	M_ASN1_New(ret->object,ASN1_OBJECT_new);*/
diff --git a/crypto/asn1/x_pkey.c b/crypto/asn1/x_pkey.c
index 1d4d926..3a359cc 100644
--- a/crypto/asn1/x_pkey.c
+++ b/crypto/asn1/x_pkey.c
@@ -91,6 +91,7 @@
 	if (ret->cipher.cipher == NULL)
 		{
 		c.error=ASN1_R_UNSUPPORTED_CIPHER;
+		c.line=__LINE__;
 		goto err;
 		}
 	if (ret->enc_algor->parameter->type == V_ASN1_OCTET_STRING) 
@@ -99,6 +100,7 @@
 		if (i > EVP_MAX_IV_LENGTH)
 			{
 			c.error=ASN1_R_IV_TOO_LARGE;
+			c.line=__LINE__;
 			goto err;
 			}
 		memcpy(ret->cipher.iv,
@@ -112,6 +114,7 @@
 X509_PKEY *X509_PKEY_new()
 	{
 	X509_PKEY *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,X509_PKEY);
 	ret->version=0;
diff --git a/crypto/asn1/x_pubkey.c b/crypto/asn1/x_pubkey.c
index a309cf7..b8e6d0e 100644
--- a/crypto/asn1/x_pubkey.c
+++ b/crypto/asn1/x_pubkey.c
@@ -61,8 +61,8 @@
 #include "asn1_mac.h"
 
 /*
- * ASN1err(ASN1_F_D2I_X509_PUBKEY,ASN1_R_LENGTH_MISMATCH);
- * ASN1err(ASN1_F_X509_PUBKEY_NEW,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_X509_PUBKEY,ERR_R_ASN1_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_X509_PUBKEY_NEW,ERR_R_ASN1_LENGTH_MISMATCH);
  */
 
 int i2d_X509_PUBKEY(a,pp)
@@ -104,6 +104,7 @@
 X509_PUBKEY *X509_PUBKEY_new()
 	{
 	X509_PUBKEY *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,X509_PUBKEY);
 	M_ASN1_New(ret->algor,X509_ALGOR_new);
diff --git a/crypto/asn1/x_req.c b/crypto/asn1/x_req.c
index ff0be13..a0df998 100644
--- a/crypto/asn1/x_req.c
+++ b/crypto/asn1/x_req.c
@@ -62,10 +62,10 @@
 #include "x509.h"
 
 /*
- * ASN1err(ASN1_F_D2I_X509_REQ,ASN1_R_LENGTH_MISMATCH);
- * ASN1err(ASN1_F_D2I_X509_REQ_INFO,ASN1_R_LENGTH_MISMATCH);
- * ASN1err(ASN1_F_X509_REQ_NEW,ASN1_R_LENGTH_MISMATCH);
- * ASN1err(ASN1_F_X509_REQ_INFO_NEW,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_X509_REQ,ERR_R_ASN1_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_X509_REQ_INFO,ERR_R_ASN1_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_X509_REQ_NEW,ERR_R_ASN1_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_X509_REQ_INFO_NEW,ERR_R_ASN1_LENGTH_MISMATCH);
  */
 
 int i2d_X509_REQ_INFO(a,pp)
@@ -141,7 +141,8 @@
 		ret->req_kludge=1;
 	else
 		{
-		M_ASN1_D2I_get_IMP_set(ret->attributes,d2i_X509_ATTRIBUTE,0);
+		M_ASN1_D2I_get_IMP_set(ret->attributes,d2i_X509_ATTRIBUTE,
+			X509_ATTRIBUTE_free,0);
 		}
 
 	M_ASN1_D2I_Finish(a,X509_REQ_INFO_free,ASN1_F_D2I_X509_REQ_INFO);
@@ -150,6 +151,7 @@
 X509_REQ_INFO *X509_REQ_INFO_new()
 	{
 	X509_REQ_INFO *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,X509_REQ_INFO);
 	M_ASN1_New(ret->version,ASN1_INTEGER_new);
@@ -208,6 +210,7 @@
 X509_REQ *X509_REQ_new()
 	{
 	X509_REQ *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,X509_REQ);
 	ret->references=1;
diff --git a/crypto/asn1/x_sig.c b/crypto/asn1/x_sig.c
index f0a2e4c..245a76b 100644
--- a/crypto/asn1/x_sig.c
+++ b/crypto/asn1/x_sig.c
@@ -61,8 +61,8 @@
 #include "asn1_mac.h"
 
 /*
- * ASN1err(ASN1_F_D2I_X509_SIG,ASN1_R_LENGTH_MISMATCH);
- * ASN1err(ASN1_F_X509_SIG_NEW,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_X509_SIG,ERR_R_ASN1_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_X509_SIG_NEW,ERR_R_ASN1_LENGTH_MISMATCH);
  */
 
 int i2d_X509_SIG(a,pp)
@@ -99,6 +99,7 @@
 X509_SIG *X509_SIG_new()
 	{
 	X509_SIG *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,X509_SIG);
 	M_ASN1_New(ret->algor,X509_ALGOR_new);
diff --git a/crypto/asn1/x_spki.c b/crypto/asn1/x_spki.c
index 4a80df4..5600d30 100644
--- a/crypto/asn1/x_spki.c
+++ b/crypto/asn1/x_spki.c
@@ -66,10 +66,10 @@
 #include "asn1_mac.h"
 
 /*
- * ASN1err(ASN1_F_D2I_NETSCAPE_SPKAC,ASN1_R_LENGTH_MISMATCH);
- * ASN1err(ASN1_F_NETSCAPE_SPKAC_NEW,ASN1_R_LENGTH_MISMATCH);
- * ASN1err(ASN1_F_D2I_NETSCAPE_SPKI,ASN1_R_LENGTH_MISMATCH);
- * ASN1err(ASN1_F_NETSCAPE_SPKI_NEW,ASN1_R_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_NETSCAPE_SPKAC,ERR_R_ASN1_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_NETSCAPE_SPKAC_NEW,ERR_R_ASN1_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_D2I_NETSCAPE_SPKI,ERR_R_ASN1_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_NETSCAPE_SPKI_NEW,ERR_R_ASN1_LENGTH_MISMATCH);
  */
 
 int i2d_NETSCAPE_SPKAC(a,pp)
@@ -106,6 +106,7 @@
 NETSCAPE_SPKAC *NETSCAPE_SPKAC_new()
 	{
 	NETSCAPE_SPKAC *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,NETSCAPE_SPKAC);
 	M_ASN1_New(ret->pubkey,X509_PUBKEY_new);
@@ -160,6 +161,7 @@
 NETSCAPE_SPKI *NETSCAPE_SPKI_new()
 	{
 	NETSCAPE_SPKI *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,NETSCAPE_SPKI);
 	M_ASN1_New(ret->spkac,NETSCAPE_SPKAC_new);
diff --git a/crypto/asn1/x_val.c b/crypto/asn1/x_val.c
index a9c390f..8d996e9 100644
--- a/crypto/asn1/x_val.c
+++ b/crypto/asn1/x_val.c
@@ -99,6 +99,7 @@
 X509_VAL *X509_VAL_new()
 	{
 	X509_VAL *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,X509_VAL);
 	M_ASN1_New(ret->notBefore,ASN1_UTCTIME_new);
diff --git a/crypto/asn1/x_x509.c b/crypto/asn1/x_x509.c
index bc466ce..e235abb 100644
--- a/crypto/asn1/x_x509.c
+++ b/crypto/asn1/x_x509.c
@@ -62,8 +62,8 @@
 #include "asn1_mac.h"
 
 /*
- * ASN1err(ASN1_F_D2I_X509,ASN1_R_LENGTH_MISMATCH);
- * ASN1err(ASN1_F_X509_NEW,ASN1_R_BAD_GET_OBJECT);
+ * ASN1err(ASN1_F_D2I_X509,ERR_R_ASN1_LENGTH_MISMATCH);
+ * ASN1err(ASN1_F_X509_NEW,ERR_R_BAD_GET_ASN1_OBJECT_CALL);
  */
 
 static ASN1_METHOD meth={
@@ -117,6 +117,7 @@
 X509 *X509_new()
 	{
 	X509 *ret=NULL;
+	ASN1_CTX c;
 
 	M_ASN1_New_Malloc(ret,X509);
 	ret->references=1;
@@ -149,9 +150,11 @@
 		}
 #endif
 
+	/* CRYPTO_free_ex_data(bio_meth,(char *)a,&a->ex_data); */
 	X509_CINF_free(a->cert_info);
 	X509_ALGOR_free(a->sig_alg);
 	ASN1_BIT_STRING_free(a->signature);
+
 	if (a->name != NULL) Free(a->name);
 	Free((char *)a);
 	}
diff --git a/crypto/bf/Makefile.ssl b/crypto/bf/Makefile.ssl
index 236671f..22aa4ca 100644
--- a/crypto/bf/Makefile.ssl
+++ b/crypto/bf/Makefile.ssl
@@ -61,7 +61,7 @@
 
 # bsdi
 asm/bx86bsdi.o: asm/bx86unix.cpp
-	$(CPP) -DBSDI asm/bx86unix.cpp | as -o asm/bx86bsdi.o
+	$(CPP) -DBSDI asm/bx86unix.cpp | sed 's/ :/:/' | as -o asm/bx86bsdi.o
 
 asm/bx86unix.cpp:
 	(cd asm; perl bf-586.pl cpp >bx86unix.cpp)
diff --git a/crypto/bf/bf_ecb.c b/crypto/bf/bf_ecb.c
index 6d16360..3b534ac 100644
--- a/crypto/bf/bf_ecb.c
+++ b/crypto/bf/bf_ecb.c
@@ -64,7 +64,7 @@
  * CAMBRIDGE SECURITY WORKSHOP, CAMBRIDGE, U.K., DECEMBER 9-11, 1993)
  */
 
-char *BF_version="BlowFish part of SSLeay 0.9.0b 29-Jun-1998";
+char *BF_version="BlowFish part of SSLeay 0.9.1a 06-Jul-1998";
 
 char *BF_options()
 	{
diff --git a/crypto/bf/bf_opts.c b/crypto/bf/bf_opts.c
index 5cfa60c..735d16b 100644
--- a/crypto/bf/bf_opts.c
+++ b/crypto/bf/bf_opts.c
@@ -92,7 +92,8 @@
 #include <sys/timeb.h>
 #endif
 
-#ifdef sun
+#if defined(sun) || defined(__ultrix)
+#define _POSIX_SOURCE
 #include <limits.h>
 #include <sys/param.h>
 #endif
diff --git a/crypto/bf/bfspeed.c b/crypto/bf/bfspeed.c
index 640d820..30db62b 100644
--- a/crypto/bf/bfspeed.c
+++ b/crypto/bf/bfspeed.c
@@ -92,7 +92,8 @@
 #include <sys/timeb.h>
 #endif
 
-#ifdef sun
+#if defined(sun) || defined(__ultrix)
+#define _POSIX_SOURCE
 #include <limits.h>
 #include <sys/param.h>
 #endif
diff --git a/crypto/bio/b_sock.c b/crypto/bio/b_sock.c
index a459095..2c36150 100644
--- a/crypto/bio/b_sock.c
+++ b/crypto/bio/b_sock.c
@@ -148,7 +148,7 @@
 
 int BIO_get_port(str,port_ptr)
 char *str;
-short *port_ptr;
+unsigned short *port_ptr;
 	{
 	int i;
 	struct servent *s;
@@ -223,13 +223,13 @@
 		{
 	case BIO_GHBN_CTRL_HITS:
 		return(BIO_ghbn_hits);
-		break;
+		/* break; */
 	case BIO_GHBN_CTRL_MISSES:
 		return(BIO_ghbn_miss);
-		break;
+		/* break; */
 	case BIO_GHBN_CTRL_CACHE_SIZE:
 		return(GHBN_NUM);
-		break;
+		/* break; */
 	case BIO_GHBN_CTRL_GET_ENTRY:
 		if ((iarg >= 0) && (iarg <GHBN_NUM) &&
 			(ghbn_cache[iarg].order > 0))
@@ -241,7 +241,7 @@
 			return(1);
 			}
 		return(0);
-		break;
+		/* break; */
 	case BIO_GHBN_CTRL_FLUSH:
 		for (i=0; i<GHBN_NUM; i++)
 			ghbn_cache[i].order=0;
@@ -258,46 +258,51 @@
 	struct hostent *ret;
 	int i,j;
 
-	ret=(struct hostent *)malloc(sizeof(struct hostent));
+	MemCheck_off();
+	ret=(struct hostent *)Malloc(sizeof(struct hostent));
 	if (ret == NULL) return(NULL);
 	memset(ret,0,sizeof(struct hostent));
 
 	for (i=0; a->h_aliases[i] != NULL; i++)
 		;
 	i++;
-	ret->h_aliases=(char **)malloc(sizeof(char *)*i);
+	ret->h_aliases=(char **)Malloc(sizeof(char *)*i);
 	memset(ret->h_aliases,0,sizeof(char *)*i);
 	if (ret == NULL) goto err;
 
 	for (i=0; a->h_addr_list[i] != NULL; i++)
 		;
 	i++;
-	ret->h_addr_list=(char **)malloc(sizeof(char *)*i);
+	ret->h_addr_list=(char **)Malloc(sizeof(char *)*i);
 	memset(ret->h_addr_list,0,sizeof(char *)*i);
 	if (ret->h_addr_list == NULL) goto err;
 
 	j=strlen(a->h_name)+1;
-	if ((ret->h_name=malloc(j)) == NULL) goto err;
-	memcpy((char *)ret->h_name,a->h_name,j);
+	if ((ret->h_name=Malloc(j)) == NULL) goto err;
+	memcpy((char *)ret->h_name,a->h_name,j+1);
 	for (i=0; a->h_aliases[i] != NULL; i++)
 		{
 		j=strlen(a->h_aliases[i])+1;
-		if ((ret->h_aliases[i]=malloc(j)) == NULL) goto err;
-		memcpy(ret->h_aliases[i],a->h_aliases[i],j);
+		if ((ret->h_aliases[i]=Malloc(j)) == NULL) goto err;
+		memcpy(ret->h_aliases[i],a->h_aliases[i],j+1);
 		}
 	ret->h_length=a->h_length;
 	ret->h_addrtype=a->h_addrtype;
 	for (i=0; a->h_addr_list[i] != NULL; i++)
 		{
-		if ((ret->h_addr_list[i]=malloc(a->h_length)) == NULL)
+		if ((ret->h_addr_list[i]=Malloc(a->h_length)) == NULL)
 			goto err;
 		memcpy(ret->h_addr_list[i],a->h_addr_list[i],a->h_length);
 		}
-	return(ret);
+	if (0)
+		{
 err:	
-	if (ret != NULL)
-		ghbn_free(ret);
-	return(NULL);
+		if (ret != NULL)
+			ghbn_free(ret);
+		ret=NULL;
+		}
+	MemCheck_on();
+	return(ret);
 	}
 
 static void ghbn_free(a)
@@ -308,17 +313,17 @@
 	if (a->h_aliases != NULL)
 		{
 		for (i=0; a->h_aliases[i] != NULL; i++)
-			free(a->h_aliases[i]);
-		free(a->h_aliases);
+			Free(a->h_aliases[i]);
+		Free(a->h_aliases);
 		}
 	if (a->h_addr_list != NULL)
 		{
 		for (i=0; a->h_addr_list[i] != NULL; i++)
-			free(a->h_addr_list[i]);
-		free(a->h_addr_list);
+			Free(a->h_addr_list[i]);
+		Free(a->h_addr_list);
 		}
-	if (a->h_name != NULL) free((char *)a->h_name);
-	free(a);
+	if (a->h_name != NULL) Free((char *)a->h_name);
+	Free(a);
 	}
 
 struct hostent *BIO_gethostbyname(name)
@@ -467,16 +472,18 @@
 	return(1);
 	}
 
-int BIO_get_accept_socket(host)
+int BIO_get_accept_socket(host,bind_mode)
 char *host;
+int bind_mode;
 	{
 	int ret=0;
-	struct sockaddr_in server;
-	int s= -1;
+	struct sockaddr_in server,client;
+	int s= -1,cs;
 	unsigned char ip[4];
 	short port;
 	char *str,*h,*p,*e;
 	unsigned long l;
+	int err_num;
 
 	if (!BIO_sock_init()) return(INVALID_SOCKET);
 
@@ -517,12 +524,13 @@
 		if (!BIO_get_host_ip(h,&(ip[0]))) return(INVALID_SOCKET);
 		l=(unsigned long)
 			((unsigned long)ip[0]<<24L)|
-			((unsigned long)ip[0]<<16L)|
-			((unsigned long)ip[0]<< 8L)|
-			((unsigned long)ip[0]);
+			((unsigned long)ip[1]<<16L)|
+			((unsigned long)ip[2]<< 8L)|
+			((unsigned long)ip[3]);
 		server.sin_addr.s_addr=htonl(l);
 		}
 
+again:
 	s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
 	if (s == INVALID_SOCKET)
 		{
@@ -531,9 +539,45 @@
 		BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_CREATE_SOCKET);
 		goto err;
 		}
+
+#ifdef SO_REUSEADDR
+	if (bind_mode == BIO_BIND_REUSEADDR)
+		{
+		int i=1;
+
+		ret=setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&i,sizeof(i));
+		bind_mode=BIO_BIND_NORMAL;
+		}
+#endif
 	if (bind(s,(struct sockaddr *)&server,sizeof(server)) == -1)
 		{
-		SYSerr(SYS_F_BIND,get_last_socket_error());
+#ifdef SO_REUSEADDR
+		err_num=get_last_socket_error();
+		if ((bind_mode == BIO_BIND_REUSEADDR_IF_UNUSED) &&
+			(err_num == EADDRINUSE))
+			{
+			memcpy((char *)&client,(char *)&server,sizeof(server));
+			if (strcmp(h,"*") == 0)
+				client.sin_addr.s_addr=htonl(0x7F000001);
+			cs=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
+			if (cs != INVALID_SOCKET)
+				{
+				int ii;
+				ii=connect(cs,(struct sockaddr *)&client,
+					sizeof(client));
+				closesocket(cs);
+				if (ii == INVALID_SOCKET)
+					{
+					bind_mode=BIO_BIND_REUSEADDR;
+					closesocket(s);
+					goto again;
+					}
+				/* else error */
+				}
+			/* else error */
+			}
+#endif
+		SYSerr(SYS_F_BIND,err_num);
 		ERR_add_error_data(3,"port='",host,"'");
 		BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_BIND_SOCKET);
 		goto err;
@@ -550,11 +594,7 @@
 	if (str != NULL) Free(str);
 	if ((ret == 0) && (s != INVALID_SOCKET))
 		{
-#ifdef WINDOWS
 		closesocket(s);
-#else
-		close(s);
-#endif
 		s= INVALID_SOCKET;
 		}
 	return(s);
@@ -626,3 +666,16 @@
 	}
 #endif
 
+int BIO_socket_nbio(s,mode)
+int s;
+int mode;
+	{
+	int ret= -1;
+	unsigned long l;
+
+	l=mode;
+#ifdef FIONBIO
+	ret=BIO_socket_ioctl(s,FIONBIO,&l);
+#endif
+	return(ret == 0);
+	}
diff --git a/crypto/bio/bio.err b/crypto/bio/bio.err
index 6e2f2b6..daef643 100644
--- a/crypto/bio/bio.err
+++ b/crypto/bio/bio.err
@@ -3,23 +3,25 @@
 /* Function codes. */
 #define BIO_F_ACPT_STATE				 100
 #define BIO_F_BIO_ACCEPT				 101
-#define BIO_F_BIO_CTRL					 102
-#define BIO_F_BIO_GETS					 103
-#define BIO_F_BIO_GET_ACCEPT_SOCKET			 104
-#define BIO_F_BIO_GET_HOST_IP				 105
-#define BIO_F_BIO_GET_PORT				 106
-#define BIO_F_BIO_NEW					 107
-#define BIO_F_BIO_NEW_FILE				 108
-#define BIO_F_BIO_PUTS					 109
-#define BIO_F_BIO_READ					 110
-#define BIO_F_BIO_SOCK_INIT				 111
-#define BIO_F_BIO_WRITE					 112
-#define BIO_F_BUFFER_CTRL				 113
-#define BIO_F_CONN_STATE				 114
-#define BIO_F_FILE_CTRL					 115
-#define BIO_F_MEM_WRITE					 116
-#define BIO_F_SSL_NEW					 117
-#define BIO_F_WSASTARTUP				 118
+#define BIO_F_BIO_BER_GET_HEADER			 102
+#define BIO_F_BIO_CTRL					 103
+#define BIO_F_BIO_GETS					 104
+#define BIO_F_BIO_GET_ACCEPT_SOCKET			 105
+#define BIO_F_BIO_GET_HOST_IP				 106
+#define BIO_F_BIO_GET_PORT				 107
+#define BIO_F_BIO_NEW					 108
+#define BIO_F_BIO_NEW_FILE				 109
+#define BIO_F_BIO_PUTS					 110
+#define BIO_F_BIO_READ					 111
+#define BIO_F_BIO_SOCK_INIT				 112
+#define BIO_F_BIO_WRITE					 113
+#define BIO_F_BUFFER_CTRL				 114
+#define BIO_F_CONN_STATE				 115
+#define BIO_F_FILE_CTRL					 116
+#define BIO_F_MEM_WRITE					 117
+#define BIO_F_SOCKS4A_STATE				 118
+#define BIO_F_SSL_NEW					 119
+#define BIO_F_WSASTARTUP				 120
 
 /* Reason codes. */
 #define BIO_R_ACCEPT_ERROR				 100
@@ -38,9 +40,14 @@
 #define BIO_R_NO_PORT_DEFINED				 113
 #define BIO_R_NO_PORT_SPECIFIED				 114
 #define BIO_R_NULL_PARAMETER				 115
-#define BIO_R_UNABLE_TO_BIND_SOCKET			 116
-#define BIO_R_UNABLE_TO_CREATE_SOCKET			 117
-#define BIO_R_UNABLE_TO_LISTEN_SOCKET			 118
-#define BIO_R_UNINITALISED				 119
-#define BIO_R_UNSUPPORTED_METHOD			 120
-#define BIO_R_WSASTARTUP				 121
+#define BIO_R_SOCKS_ID_AND_IDENT_DID_NOT_MATCH		 116
+#define BIO_R_SOCKS_REJECTED_CONNECTION			 117
+#define BIO_R_SOCKS_UNABLE_TO_TALK_TO_IDENT_SERVER	 118
+#define BIO_R_SOCKS_UNKNOWN_ERROR			 119
+#define BIO_R_TAG_MISMATCH				 120
+#define BIO_R_UNABLE_TO_BIND_SOCKET			 121
+#define BIO_R_UNABLE_TO_CREATE_SOCKET			 122
+#define BIO_R_UNABLE_TO_LISTEN_SOCKET			 123
+#define BIO_R_UNINITALISED				 124
+#define BIO_R_UNSUPPORTED_METHOD			 125
+#define BIO_R_WSASTARTUP				 126
diff --git a/crypto/bio/bio.h b/crypto/bio/bio.h
index 300b330..35db3df 100644
--- a/crypto/bio/bio.h
+++ b/crypto/bio/bio.h
@@ -84,6 +84,7 @@
 #define BIO_TYPE_PROXY_SERVER	(15|0x0200)		/* server proxy BIO */
 #define BIO_TYPE_NBIO_TEST	(16|0x0200)		/* server proxy BIO */
 #define BIO_TYPE_NULL_FILTER	(17|0x0200)
+#define BIO_TYPE_BER		(18|0x0200)		/* BER -> bin filter */
 
 #define BIO_TYPE_DESCRIPTOR	0x0100	/* socket, fd, connect or accept */
 #define BIO_TYPE_FILTER		0x0200
@@ -276,7 +277,7 @@
 #define BIO_CONN_S_OK			6
 #define BIO_CONN_S_BLOCKED_CONNECT	7
 #define BIO_CONN_S_NBIO			8
-#define BIO_CONN_get_param_hostname	BIO_ctrl
+/*#define BIO_CONN_get_param_hostname	BIO_ctrl */
 
 #define BIO_number_read(b)	((b)->num_read)
 #define BIO_number_written(b)	((b)->num_write)
@@ -309,6 +310,14 @@
 #define BIO_C_SET_SSL_RENEGOTIATE_BYTES		125
 #define BIO_C_GET_SSL_NUM_RENEGOTIATES		126
 #define BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT	127
+#define BIO_C_FILE_SEEK				128
+#define BIO_C_GET_CIPHER_CTX			129
+#define BIO_C_SET_BUF_MEM_EOF_RETURN		130/*return end of input value*/
+#define BIO_C_SET_BIND_MODE			131
+#define BIO_C_GET_BIND_MODE			132
+#define BIO_C_FILE_TELL				133
+#define BIO_C_GET_SOCKS				134
+#define BIO_C_SET_SOCKS				135
 
 #define BIO_set_app_data(s,arg)		BIO_set_ex_data(s,0,(char *)arg)
 #define BIO_get_app_data(s)		BIO_get_ex_data(s,0)
@@ -320,7 +329,7 @@
 int BIO_get_ex_new_index(long argl, char *argp, int (*new_func)(),
 	int (*dup_func)(), void (*free_func)());
 
-/* BIO_s_connect_socket() */
+/* BIO_s_connect() and BIO_s_socks4a_connect() */
 #define BIO_set_conn_hostname(b,name) BIO_ctrl(b,BIO_C_SET_CONNECT,0,(char *)name)
 #define BIO_set_conn_port(b,port) BIO_ctrl(b,BIO_C_SET_CONNECT,1,(char *)port)
 #define BIO_set_conn_ip(b,ip)	  BIO_ctrl(b,BIO_C_SET_CONNECT,2,(char *)ip)
@@ -328,7 +337,8 @@
 #define BIO_get_conn_hostname(b)  BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,0)
 #define BIO_get_conn_port(b)      BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,1)
 #define BIO_get_conn_ip(b,ip) BIO_ptr_ctrl(b,BIO_C_SET_CONNECT,2)
-#define BIO_get_conn_int port(b,port) BIO_int_ctrl(b,BIO_C_SET_CONNECT,3,port)
+#define BIO_get_conn_int_port(b,port) BIO_int_ctrl(b,BIO_C_SET_CONNECT,3,port)
+
 
 #define BIO_set_nbio(b,n)	BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL)
 
@@ -339,6 +349,12 @@
 #define BIO_set_nbio_accept(b,n) BIO_ctrl(b,BIO_C_SET_ACCEPT,1,(n)?"a":NULL)
 #define BIO_set_accept_bios(b,bio) BIO_ctrl(b,BIO_C_SET_ACCEPT,2,(char *)bio)
 
+#define BIO_BIND_NORMAL			0
+#define BIO_BIND_REUSEADDR_IF_UNUSED	1
+#define BIO_BIND_REUSEADDR		2
+#define BIO_set_bind_mode(b,mode) BIO_ctrl(b,BIO_C_SET_BIND_MODE,mode,NULL)
+#define BIO_get_bind_mode(b,mode) BIO_ctrl(b,BIO_C_GET_BIND_MODE,0,NULL)
+
 #define BIO_do_connect(b)	BIO_do_handshake(b)
 #define BIO_do_accept(b)	BIO_do_handshake(b)
 #define BIO_do_handshake(b)	BIO_ctrl(b,BIO_C_DO_STATE_MACHINE,0,NULL)
@@ -364,12 +380,17 @@
 #define BIO_set_fp(b,fp,c)	BIO_ctrl(b,BIO_C_SET_FILE_PTR,c,(char *)fp)
 #define BIO_get_fp(b,fpp)	BIO_ctrl(b,BIO_C_GET_FILE_PTR,0,(char *)fpp)
 
+#define BIO_seek(b,ofs)	(int)BIO_ctrl(b,BIO_C_FILE_SEEK,ofs,NULL)
+#define BIO_tell(b)	(int)BIO_ctrl(b,BIO_C_FILE_TELL,0,NULL)
+
 #define BIO_read_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \
 		BIO_CLOSE|BIO_FP_READ,name)
 #define BIO_write_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \
 		BIO_CLOSE|BIO_FP_WRITE,name)
 #define BIO_append_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \
 		BIO_CLOSE|BIO_FP_APPEND,name)
+#define BIO_rw_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \
+		BIO_CLOSE|BIO_FP_READ|BIO_FP_WRITE,name)
 
 /* WARNING WARNING, this ups the reference count on the read bio of the
  * SSL structure.  This is because the ssl read BIO is now pointed to by
@@ -388,8 +409,11 @@
 /* defined in evp.h */
 /* #define BIO_set_md(b,md)	BIO_ctrl(b,BIO_C_SET_MD,1,(char *)md) */
 
+#define BIO_get_mem_data(b,pp)	BIO_ctrl(b,BIO_CTRL_INFO,0,(char *)pp)
 #define BIO_set_mem_buf(b,bm,c)	BIO_ctrl(b,BIO_C_SET_BUF_MEM,c,(char *)bm)
 #define BIO_get_mem_ptr(b,pp)	BIO_ctrl(b,BIO_C_GET_BUF_MEM_PTR,0,(char *)pp)
+#define BIO_set_mem_eof_return(b,v) \
+				BIO_ctrl(b,BIO_C_SET_BUF_MEM_EOF_RETURN,v,NULL)
 
 /* For the BIO_f_buffer() type */
 #define BIO_get_buffer_num_lines(b)	BIO_ctrl(b,BIO_C_GET_BUFF_NUM_LINES,0,NULL)
@@ -486,8 +510,9 @@
 BIO_METHOD *BIO_s_fd(void);
 BIO_METHOD *BIO_s_null(void);
 BIO_METHOD *BIO_f_null(void);
-BIO_METHOD *BIO_f_nbio_test(void);
 BIO_METHOD *BIO_f_buffer(void);
+BIO_METHOD *BIO_f_nbio_test(void);
+/* BIO_METHOD *BIO_f_ber(void); */
 
 int BIO_sock_should_retry(int i);
 int BIO_sock_non_fatal_error(int error);
@@ -498,9 +523,10 @@
 struct hostent *BIO_gethostbyname(char *name);
 int BIO_sock_error(int sock);
 int BIO_socket_ioctl(int fd, long type, unsigned long *arg);
-int BIO_get_port(char *str, short *port_ptr);
+int BIO_socket_nbio(int fd,int mode);
+int BIO_get_port(char *str, unsigned short *port_ptr);
 int BIO_get_host_ip(char *str, unsigned char *ip);
-int BIO_get_accept_socket(char *host_port);
+int BIO_get_accept_socket(char *host_port,int mode);
 int BIO_accept(int sock,char **ip_port);
 int BIO_sock_init(void );
 void BIO_sock_cleanup(void);
@@ -552,6 +578,7 @@
 BIO_METHOD *BIO_f_null();
 BIO_METHOD *BIO_f_buffer();
 BIO_METHOD *BIO_f_nbio_test();
+/* BIO_METHOD *BIO_f_ber(); */
 
 int BIO_sock_should_retry();
 int BIO_sock_non_fatal_error();
@@ -562,6 +589,7 @@
 struct hostent *BIO_gethostbyname();
 int BIO_sock_error();
 int BIO_socket_ioctl();
+int BIO_socket_nbio();
 int BIO_get_port();
 int BIO_get_host_ip();
 int BIO_get_accept_socket();
@@ -579,7 +607,7 @@
 
 void BIO_copy_next_retry();
 
-int BIO_ghbn_ctrl();
+long BIO_ghbn_ctrl();
 
 #endif
 
@@ -639,23 +667,24 @@
 /* Function codes. */
 #define BIO_F_ACPT_STATE				 100
 #define BIO_F_BIO_ACCEPT				 101
-#define BIO_F_BIO_CTRL					 102
-#define BIO_F_BIO_GETS					 103
-#define BIO_F_BIO_GET_ACCEPT_SOCKET			 104
-#define BIO_F_BIO_GET_HOST_IP				 105
-#define BIO_F_BIO_GET_PORT				 106
-#define BIO_F_BIO_NEW					 107
-#define BIO_F_BIO_NEW_FILE				 108
-#define BIO_F_BIO_PUTS					 109
-#define BIO_F_BIO_READ					 110
-#define BIO_F_BIO_SOCK_INIT				 111
-#define BIO_F_BIO_WRITE					 112
-#define BIO_F_BUFFER_CTRL				 113
-#define BIO_F_CONN_STATE				 114
-#define BIO_F_FILE_CTRL					 115
-#define BIO_F_MEM_WRITE					 116
-#define BIO_F_SSL_NEW					 117
-#define BIO_F_WSASTARTUP				 118
+#define BIO_F_BIO_BER_GET_HEADER			 102
+#define BIO_F_BIO_CTRL					 103
+#define BIO_F_BIO_GETS					 104
+#define BIO_F_BIO_GET_ACCEPT_SOCKET			 105
+#define BIO_F_BIO_GET_HOST_IP				 106
+#define BIO_F_BIO_GET_PORT				 107
+#define BIO_F_BIO_NEW					 108
+#define BIO_F_BIO_NEW_FILE				 109
+#define BIO_F_BIO_PUTS					 110
+#define BIO_F_BIO_READ					 111
+#define BIO_F_BIO_SOCK_INIT				 112
+#define BIO_F_BIO_WRITE					 113
+#define BIO_F_BUFFER_CTRL				 114
+#define BIO_F_CONN_STATE				 115
+#define BIO_F_FILE_CTRL					 116
+#define BIO_F_MEM_WRITE					 117
+#define BIO_F_SSL_NEW					 119
+#define BIO_F_WSASTARTUP				 120
 
 /* Reason codes. */
 #define BIO_R_ACCEPT_ERROR				 100
@@ -674,12 +703,17 @@
 #define BIO_R_NO_PORT_DEFINED				 113
 #define BIO_R_NO_PORT_SPECIFIED				 114
 #define BIO_R_NULL_PARAMETER				 115
-#define BIO_R_UNABLE_TO_BIND_SOCKET			 116
-#define BIO_R_UNABLE_TO_CREATE_SOCKET			 117
-#define BIO_R_UNABLE_TO_LISTEN_SOCKET			 118
-#define BIO_R_UNINITALISED				 119
-#define BIO_R_UNSUPPORTED_METHOD			 120
-#define BIO_R_WSASTARTUP				 121
+#define BIO_R_SOCKS_ID_AND_IDENT_DID_NOT_MATCH		 116
+#define BIO_R_SOCKS_REJECTED_CONNECTION			 117
+#define BIO_R_SOCKS_UNABLE_TO_TALK_TO_IDENT_SERVER	 118
+#define BIO_R_SOCKS_UNKNOWN_ERROR			 119
+#define BIO_R_TAG_MISMATCH				 120
+#define BIO_R_UNABLE_TO_BIND_SOCKET			 121
+#define BIO_R_UNABLE_TO_CREATE_SOCKET			 122
+#define BIO_R_UNABLE_TO_LISTEN_SOCKET			 123
+#define BIO_R_UNINITALISED				 124
+#define BIO_R_UNSUPPORTED_METHOD			 125
+#define BIO_R_WSASTARTUP				 126
  
 #ifdef  __cplusplus
 }
diff --git a/crypto/bio/bio_err.c b/crypto/bio/bio_err.c
index 37e14ca..01aac6e 100644
--- a/crypto/bio/bio_err.c
+++ b/crypto/bio/bio_err.c
@@ -65,6 +65,7 @@
 	{
 {ERR_PACK(0,BIO_F_ACPT_STATE,0),	"ACPT_STATE"},
 {ERR_PACK(0,BIO_F_BIO_ACCEPT,0),	"BIO_accept"},
+{ERR_PACK(0,BIO_F_BIO_BER_GET_HEADER,0),	"BIO_BER_GET_HEADER"},
 {ERR_PACK(0,BIO_F_BIO_CTRL,0),	"BIO_ctrl"},
 {ERR_PACK(0,BIO_F_BIO_GETS,0),	"BIO_gets"},
 {ERR_PACK(0,BIO_F_BIO_GET_ACCEPT_SOCKET,0),	"BIO_get_accept_socket"},
@@ -80,6 +81,7 @@
 {ERR_PACK(0,BIO_F_CONN_STATE,0),	"CONN_STATE"},
 {ERR_PACK(0,BIO_F_FILE_CTRL,0),	"FILE_CTRL"},
 {ERR_PACK(0,BIO_F_MEM_WRITE,0),	"MEM_WRITE"},
+{ERR_PACK(0,BIO_F_SOCKS4A_STATE,0),	"SOCKS4A_STATE"},
 {ERR_PACK(0,BIO_F_SSL_NEW,0),	"SSL_NEW"},
 {ERR_PACK(0,BIO_F_WSASTARTUP,0),	"WSASTARTUP"},
 {0,NULL},
@@ -103,6 +105,11 @@
 {BIO_R_NO_PORT_DEFINED                   ,"no port defined"},
 {BIO_R_NO_PORT_SPECIFIED                 ,"no port specified"},
 {BIO_R_NULL_PARAMETER                    ,"null parameter"},
+{BIO_R_SOCKS_ID_AND_IDENT_DID_NOT_MATCH  ,"socks id and ident did not match"},
+{BIO_R_SOCKS_REJECTED_CONNECTION         ,"socks rejected connection"},
+{BIO_R_SOCKS_UNABLE_TO_TALK_TO_IDENT_SERVER,"socks unable to talk to ident server"},
+{BIO_R_SOCKS_UNKNOWN_ERROR               ,"socks unknown error"},
+{BIO_R_TAG_MISMATCH                      ,"tag mismatch"},
 {BIO_R_UNABLE_TO_BIND_SOCKET             ,"unable to bind socket"},
 {BIO_R_UNABLE_TO_CREATE_SOCKET           ,"unable to create socket"},
 {BIO_R_UNABLE_TO_LISTEN_SOCKET           ,"unable to listen socket"},
@@ -118,8 +125,8 @@
 	{
 	static int init=1;
 
-	if (init);
-		{;
+	if (init)
+		{
 		init=0;
 #ifndef NO_ERR
 		ERR_load_strings(ERR_LIB_BIO,BIO_str_functs);
diff --git a/crypto/bio/bio_lib.c b/crypto/bio/bio_lib.c
index 7a66b08..bee1f5d 100644
--- a/crypto/bio/bio_lib.c
+++ b/crypto/bio/bio_lib.c
@@ -167,6 +167,7 @@
 		}
 
 	i=b->method->bread(b,out,outl);
+
 	if (i > 0) b->num_read+=(unsigned long)i;
 
 	if (cb != NULL)
@@ -204,9 +205,16 @@
 		}
 
 	i=b->method->bwrite(b,in,inl);
+
 	if (i > 0) b->num_write+=(unsigned long)i;
 
-	if (cb != NULL)
+	/* This is evil and not thread safe.  If the BIO has been freed,
+	 * we must not call the callback.  The only way to be able to
+	 * determine this is the reference count which is now invalid since
+	 * the memory has been free()ed.
+	 */
+	if (b->references <= 0) abort();
+	if (cb != NULL) /* && (b->references >= 1)) */
 		i=(int)cb(b,BIO_CB_WRITE|BIO_CB_RETURN,in,inl,
 			0L,(long)i);
 	return(i);
diff --git a/crypto/bio/bss_acpt.c b/crypto/bio/bss_acpt.c
index e49902f..872807d 100644
--- a/crypto/bio/bss_acpt.c
+++ b/crypto/bio/bss_acpt.c
@@ -82,6 +82,10 @@
 
 	char *addr;
 	int nbio;
+	/* If 0, it means normal, if 1, do a connect on bind failure,
+	 * and if there is no-one listening, bind with SO_REUSEADDR.
+	 * If 2, always use SO_REUSEADDR. */
+	int bind_mode;
 	BIO *bio_chain;
 	} BIO_ACCEPT;
 
@@ -162,6 +166,7 @@
 
 	memset(ret,0,sizeof(BIO_ACCEPT));
 	ret->accept_sock=INVALID_SOCKET;
+	ret->bind_mode=BIO_BIND_NORMAL;
 	return(ret);
 	}
 
@@ -183,11 +188,7 @@
 	if (c->accept_sock != INVALID_SOCKET)
 		{
 		shutdown(c->accept_sock,2);
-# ifdef WINDOWS
 		closesocket(c->accept_sock);
-# else
-		close(c->accept_sock);
-# endif
 		c->accept_sock=INVALID_SOCKET;
 		bio->num=INVALID_SOCKET;
 		}
@@ -217,7 +218,6 @@
 BIO_ACCEPT *c;
 	{
 	BIO *bio=NULL,*dbio;
-	unsigned long l=1;
 	int s= -1;
 	int i;
 
@@ -230,31 +230,24 @@
 			BIOerr(BIO_F_ACPT_STATE,BIO_R_NO_ACCEPT_PORT_SPECIFIED);
 			return(-1);
 			}
-		s=BIO_get_accept_socket(c->param_addr);
+		s=BIO_get_accept_socket(c->param_addr,c->bind_mode);
 		if (s == INVALID_SOCKET)
 			return(-1);
 
-#ifdef FIONBIO
 		if (c->accept_nbio)
 			{
-			i=BIO_socket_ioctl(b->num,FIONBIO,&l);
-			if (i < 0)
+			if (!BIO_socket_nbio(s,1))
 				{
-#ifdef WINDOWS
 				closesocket(s);
-#else
-				close(s);
-# endif
 				BIOerr(BIO_F_ACPT_STATE,BIO_R_ERROR_SETTING_NBIO_ON_ACCEPT_SOCKET);
 				return(-1);
 				}
 			}
-#endif
 		c->accept_sock=s;
 		b->num=s;
 		c->state=ACPT_S_GET_ACCEPT_SOCKET;
 		return(1);
-		break;
+		/* break; */
 	case ACPT_S_GET_ACCEPT_SOCKET:
 		if (b->next_bio != NULL)
 			{
@@ -269,17 +262,14 @@
 		BIO_set_callback(bio,BIO_get_callback(b));
 		BIO_set_callback_arg(bio,BIO_get_callback_arg(b));
 
-#ifdef FIONBIO
 		if (c->nbio)
 			{
-			i=BIO_socket_ioctl(i,FIONBIO,&l);
-			if (i < 0)
+			if (!BIO_socket_nbio(i,1))
 				{
 				BIOerr(BIO_F_ACPT_STATE,BIO_R_ERROR_SETTING_NBIO_ON_ACCEPTED_SOCKET);
 				goto err;
 				}
 			}
-#endif
 
 		/* If the accept BIO has an bio_chain, we dup it and
 		 * put the new socket at the end. */
@@ -298,15 +288,9 @@
 		if (bio != NULL)
 			BIO_free(bio);
 		else if (s >= 0)
-			{
-#ifdef WINDOWS
 			closesocket(s);
-#else
-			close(s);
-# endif
-			}
 		return(0);
-		break;
+		/* break; */
 	case ACPT_S_OK:
 		if (b->next_bio == NULL)
 			{
@@ -314,10 +298,10 @@
 			goto again;
 			}
 		return(1);
-		break;
+		/* break; */
 	default:	
 		return(0);
-		break;
+		/* break; */
 		}
 
 	}
@@ -417,13 +401,21 @@
 	case BIO_C_SET_NBIO:
 		data->nbio=(int)num;
 		break;
+	case BIO_C_SET_FD:
+		b->init=1;
+		b->num= *((int *)ptr);
+		data->accept_sock=b->num;
+		data->state=ACPT_S_GET_ACCEPT_SOCKET;
+		b->shutdown=(int)num;
+		b->init=1;
+		break;
 	case BIO_C_GET_FD:
 		if (b->init)
 			{
 			ip=(int *)ptr;
 			if (ip != NULL)
 				*ip=data->accept_sock;
-			ret=b->num;
+			ret=data->accept_sock;
 			}
 		else
 			ret= -1;
@@ -454,6 +446,12 @@
 		break;
 	case BIO_CTRL_FLUSH:
 		break;
+	case BIO_C_SET_BIND_MODE:
+		data->bind_mode=(int)num;
+		break;
+	case BIO_C_GET_BIND_MODE:
+		ret=(long)data->bind_mode;
+		break;
 	case BIO_CTRL_DUP:
 		dbio=(BIO *)ptr;
 /*		if (data->param_port) EAY EAY
diff --git a/crypto/bio/bss_conn.c b/crypto/bio/bss_conn.c
index 6e547bf..3ec1388 100644
--- a/crypto/bio/bss_conn.c
+++ b/crypto/bio/bss_conn.c
@@ -81,13 +81,12 @@
 	int nbio;
 
 	unsigned char ip[4];
-	short port;
+	unsigned short port;
 
 	struct sockaddr_in them;
 
 	/* int socket; this will be kept in bio->num so that it is
 	 * compatable with the bss_sock bio */ 
-	int error;
 
 	/* called when the connection is initially made
 	 *  callback(BIO,state,ret);  The callback should return
@@ -187,7 +186,7 @@
 					}
 				}
 
-			if (p == NULL)
+			if (c->param_port == NULL)
 				{
 				BIOerr(BIO_F_CONN_STATE,BIO_R_NO_PORT_SPECIFIED);
 				ERR_add_error_data(2,"host=",c->param_hostname);
@@ -203,7 +202,12 @@
 			break;
 
 		case BIO_CONN_S_GET_PORT:
-			if (BIO_get_port(c->param_port,&c->port) <= 0)
+			if (c->param_port == NULL)
+				{
+				abort();
+				goto exit_loop;
+				}
+			else if (BIO_get_port(c->param_port,&c->port) <= 0)
 				goto exit_loop;
 			c->state=BIO_CONN_S_CREATE_SOCKET;
 			break;
@@ -235,12 +239,9 @@
 			break;
 
 		case BIO_CONN_S_NBIO:
-#ifdef FIONBIO
 			if (c->nbio)
 				{
-				l=1;
-				ret=BIO_socket_ioctl(b->num,FIONBIO,&l);
-				if (ret < 0)
+				if (!BIO_socket_nbio(b->num,1))
 					{
 					BIOerr(BIO_F_CONN_STATE,BIO_R_ERROR_SETTING_NBIO);
 					ERR_add_error_data(4,"host=",
@@ -249,7 +250,6 @@
 					goto exit_loop;
 					}
 				}
-#endif
 			c->state=BIO_CONN_S_CONNECT;
 
 #ifdef SO_KEEPALIVE
@@ -326,12 +326,10 @@
 			}
 		}
 
-	if (1)
-		{
+	/* Loop does not exit */
 exit_loop:
-		if (cb != NULL)
-			ret=cb((BIO *)b,c->state,ret);
-		}
+	if (cb != NULL)
+		ret=cb((BIO *)b,c->state,ret);
 end:
 	return(ret);
 	}
@@ -353,7 +351,6 @@
 	ret->ip[3]=0;
 	ret->port=0;
 	memset((char *)&ret->them,0,sizeof(ret->them));
-	ret->error=0;
 	return(ret);
 	}
 
@@ -395,11 +392,7 @@
 		/* Only do a shutdown if things were established */
 		if (c->state == BIO_CONN_S_OK)
 			shutdown(bio->num,2);
-# ifdef WINDOWS
 		closesocket(bio->num);
-# else
-		close(bio->num);
-# endif
 		bio->num=INVALID_SOCKET;
 		}
 	}
@@ -442,11 +435,7 @@
 	if (out != NULL)
 		{
 		clear_socket_error();
-#if defined(WINDOWS)
-		ret=recv(b->num,out,outl,0);
-#else
-		ret=read(b->num,out,outl);
-#endif
+		ret=readsocket(b->num,out,outl);
 		BIO_clear_retry_flags(b);
 		if (ret <= 0)
 			{
@@ -473,11 +462,7 @@
 		}
 
 	clear_socket_error();
-#if defined(WINDOWS)
-	ret=send(b->num,in,inl,0);
-#else
-	ret=write(b->num,in,inl);
-#endif
+	ret=writesocket(b->num,in,inl);
 	BIO_clear_retry_flags(b);
 	if (ret <= 0)
 		{
@@ -559,9 +544,26 @@
 				data->param_port=BUF_strdup(ptr);
 				}
 			else if (num == 2)
-				memcpy(data->ip,ptr,4);
+				{
+				char buf[16];
+
+				sprintf(buf,"%d.%d.%d.%d",
+					ptr[0],ptr[1],ptr[2],ptr[3]);
+				if (data->param_hostname != NULL)
+					Free(data->param_hostname);
+				data->param_hostname=BUF_strdup(buf);
+				memcpy(&(data->ip[0]),ptr,4);
+				}
 			else if (num == 3)
+				{
+				char buf[16];
+
+				sprintf(buf,"%d",*(int *)ptr);
+				if (data->param_port != NULL)
+					Free(data->param_port);
+				data->param_port=BUF_strdup(buf);
 				data->port= *(int *)ptr;
+				}
 			}
 		break;
 	case BIO_C_SET_NBIO:
diff --git a/crypto/bio/bss_file.c b/crypto/bio/bss_file.c
index 1484cf8..5068a7c 100644
--- a/crypto/bio/bss_file.c
+++ b/crypto/bio/bss_file.c
@@ -214,12 +214,14 @@
 
 	switch (cmd)
 		{
+	case BIO_C_FILE_SEEK:
 	case BIO_CTRL_RESET:
 		ret=(long)fseek(fp,num,0);
 		break;
 	case BIO_CTRL_EOF:
 		ret=(long)feof(fp);
 		break;
+	case BIO_C_FILE_TELL:
 	case BIO_CTRL_INFO:
 		ret=ftell(fp);
 		break;
diff --git a/crypto/bio/bss_mem.c b/crypto/bio/bss_mem.c
index 40c4e39..8a2efb9 100644
--- a/crypto/bio/bss_mem.c
+++ b/crypto/bio/bss_mem.c
@@ -92,6 +92,9 @@
 	mem_free,
 	};
 
+/* bio->num is used to hold the value to return on 'empty', if it is
+ * 0, should_retry is not set */
+
 BIO_METHOD *BIO_s_mem()
 	{
 	return(&mem_method);
@@ -106,7 +109,7 @@
 		return(0);
 	bi->shutdown=1;
 	bi->init=1;
-	bi->num=0;
+	bi->num= -1;
 	bi->ptr=(char *)b;
 	return(1);
 	}
@@ -151,8 +154,9 @@
 		}
 	else if (bm->length == 0)
 		{
-		BIO_set_retry_read(b);
-		ret= -1;
+		if (b->num != 0)
+			BIO_set_retry_read(b);
+		ret= b->num;
 		}
 	return(ret);
 	}
@@ -204,6 +208,9 @@
 	case BIO_CTRL_EOF:
 		ret=(long)(bm->length == 0);
 		break;
+	case BIO_C_SET_BUF_MEM_EOF_RETURN:
+		b->num=(int)num;
+		break;
 	case BIO_CTRL_INFO:
 		ret=(long)bm->length;
 		if (ptr != NULL)
diff --git a/crypto/bio/bss_sock.c b/crypto/bio/bss_sock.c
index d907a28..a664377 100644
--- a/crypto/bio/bss_sock.c
+++ b/crypto/bio/bss_sock.c
@@ -189,11 +189,7 @@
 			{
 #ifndef BIO_FD
 			shutdown(a->num,2);
-# ifdef WINDOWS
 			closesocket(a->num);
-# else
-			close(a->num);
-# endif
 #else			/* BIO_FD */
 			close(a->num);
 #endif
@@ -218,9 +214,9 @@
 
 	if (out != NULL)
 		{
-#if defined(WINDOWS) && !defined(BIO_FD)
+#ifndef BIO_FD
 		clear_socket_error();
-		ret=recv(b->num,out,outl,0);
+		ret=readsocket(b->num,out,outl);
 #else
 		clear_sys_error();
 		ret=read(b->num,out,outl);
@@ -250,9 +246,9 @@
 	{
 	int ret;
 	
-#if defined(WINDOWS) && !defined(BIO_FD)
+#ifndef BIO_FD
 	clear_socket_error();
-	ret=send(b->num,in,inl,0);
+	ret=writesocket(b->num,in,inl);
 #else
 	clear_sys_error();
 	ret=write(b->num,in,inl);
@@ -286,14 +282,21 @@
 	switch (cmd)
 		{
 	case BIO_CTRL_RESET:
+		num=0;
+	case BIO_C_FILE_SEEK:
 #ifdef BIO_FD
-		ret=(long)lseek(b->num,0,0);
+		ret=(long)lseek(b->num,num,0);
 #else
 		ret=0;
 #endif
 		break;
+	case BIO_C_FILE_TELL:
 	case BIO_CTRL_INFO:
+#ifdef BIO_FD
+		ret=(long)lseek(b->num,0,1);
+#else
 		ret=0;
+#endif
 		break;
 	case BIO_C_SET_FD:
 #ifndef BIO_FD
@@ -329,7 +332,6 @@
 	case BIO_CTRL_FLUSH:
 		ret=1;
 		break;
-		break;
 	default:
 		ret=0;
 		break;
@@ -377,7 +379,7 @@
 
 	if ((i == 0) || (i == -1))
 		{
-#if !defined(BIO_FD) && defined(WINDOWS)
+#ifndef BIO_FD
 		err=get_last_socket_error();
 #else
 		err=get_last_sys_error();
@@ -411,8 +413,10 @@
 	case WSAEWOULDBLOCK:
 # endif
 
-# if defined(WSAENOTCONN)
+# if 0 /* This appears to always be an error */
+#  if defined(WSAENOTCONN)
 	case WSAENOTCONN:
+#  endif
 # endif
 #endif
 
@@ -452,7 +456,7 @@
 	case EALREADY:
 #endif
 		return(1);
-		break;
+		/* break; */
 	default:
 		break;
 		}
diff --git a/crypto/bio/cd b/crypto/bio/cd
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/crypto/bio/cd
diff --git a/crypto/bio/fg b/crypto/bio/fg
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/crypto/bio/fg
diff --git a/crypto/bio/grep b/crypto/bio/grep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/crypto/bio/grep
diff --git a/crypto/bio/vi b/crypto/bio/vi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/crypto/bio/vi
diff --git a/crypto/bn/DSA b/crypto/bn/DSA
new file mode 100644
index 0000000..83f257c
--- /dev/null
+++ b/crypto/bn/DSA
@@ -0,0 +1,2 @@
+DSA wants 64*32 to use word mont mul, but
+RSA wants to use full.
diff --git a/crypto/bn/Makefile.ssl b/crypto/bn/Makefile.ssl
index 9809d26..0a365fc 100644
--- a/crypto/bn/Makefile.ssl
+++ b/crypto/bn/Makefile.ssl
@@ -13,9 +13,9 @@
 MAKEFILE=	Makefile.ssl
 AR=		ar r
 
-BN_MULW=	bn_mulw.o
+BN_ASM=		bn_asm.o
 # or use
-#BN_MULW=	bn86-elf.o
+#BN_ASM=	bn86-elf.o
 
 CFLAGS= $(INCLUDES) $(CFLAG)
 
@@ -26,16 +26,15 @@
 APPS=
 
 LIB=$(TOP)/libcrypto.a
-LIBSRC=	bn_add.c bn_div.c bn_exp.c bn_lib.c bn_mod.c bn_mul.c \
-	bn_print.c bn_rand.c bn_shift.c bn_sub.c bn_word.c bn_blind.c \
-	bn_gcd.c bn_prime.c $(ERRC).c bn_sqr.c bn_mulw.c bn_recp.c bn_mont.c \
-	bn_mpi.c
+LIBSRC=	bn_add.c bn_div.c bn_exp.c bn_lib.c bn_mul.c \
+	bn_print.c bn_rand.c bn_shift.c bn_word.c bn_blind.c \
+	bn_gcd.c bn_prime.c $(ERRC).c bn_sqr.c bn_asm.c bn_recp.c bn_mont.c \
+	bn_mpi.c bn_exp2.c
 
-LIBOBJ=	bn_add.o bn_div.o bn_exp.o bn_lib.o bn_mod.o bn_mul.o \
-	bn_print.o bn_rand.o bn_shift.o bn_sub.o bn_word.o bn_blind.o \
-	bn_gcd.o bn_prime.o $(ERRC).o bn_sqr.o $(BN_MULW) bn_recp.o bn_mont.o \
-	bn_mpi.o
-
+LIBOBJ=	bn_add.o bn_div.o bn_exp.o bn_lib.o bn_mul.o \
+	bn_print.o bn_rand.o bn_shift.o bn_word.o bn_blind.o \
+	bn_gcd.o bn_prime.o $(ERRC).o bn_sqr.o $(BN_ASM) bn_recp.o bn_mont.o \
+	bn_mpi.o bn_exp2.o
 
 SRC= $(LIBSRC)
 
@@ -65,23 +64,48 @@
 asm/bn86-elf.o: asm/bn86unix.cpp
 	$(CPP) -DELF asm/bn86unix.cpp | as -o asm/bn86-elf.o
 
+asm/co86-elf.o: asm/co86unix.cpp
+	$(CPP) -DELF asm/co86unix.cpp | as -o asm/co86-elf.o
+
 # solaris
 asm/bn86-sol.o: asm/bn86unix.cpp
 	$(CC) -E -DSOL asm/bn86unix.cpp | sed 's/^#.*//' > asm/bn86-sol.s
 	as -o asm/bn86-sol.o asm/bn86-sol.s
 	rm -f asm/bn86-sol.s
 
+asm/co86-sol.o: asm/co86unix.cpp
+	$(CC) -E -DSOL asm/co86unix.cpp | sed 's/^#.*//' > asm/co86-sol.s
+	as -o asm/co86-sol.o asm/co86-sol.s
+	rm -f asm/co86-sol.s
+
 # a.out
 asm/bn86-out.o: asm/bn86unix.cpp
 	$(CPP) -DOUT asm/bn86unix.cpp | as -o asm/bn86-out.o
 
+asm/co86-out.o: asm/co86unix.cpp
+	$(CPP) -DOUT asm/co86unix.cpp | as -o asm/co86-out.o
+
 # bsdi
 asm/bn86bsdi.o: asm/bn86unix.cpp
-	$(CPP) -DBSDI asm/bn86unix.cpp | as -o asm/bn86bsdi.o
+	$(CPP) -DBSDI asm/bn86unix.cpp | sed 's/ :/:/' | as -o asm/bn86bsdi.o
+
+asm/co86bsdi.o: asm/co86unix.cpp
+	$(CPP) -DBSDI asm/co86unix.cpp | sed 's/ :/:/' | as -o asm/co86bsdi.o
 
 asm/bn86unix.cpp:
 	(cd asm; perl bn-586.pl cpp >bn86unix.cpp )
 
+asm/co86unix.cpp:
+	(cd asm; perl co-586.pl cpp >co86unix.cpp )
+
+# MIPS 64 bit assember 
+asm/mips3.o: asm/mips3.s
+	/usr/bin/as -mips3 -O2 -o asm/mips3.o asm/mips3.s            
+
+# MIPS 32 bit assember
+asm/mips1.o: asm/mips1.s
+	/usr/bin/as -O2 -o asm/mips1.o asm/mips1.s
+
 files:
 	perl $(TOP)/util/files.pl Makefile.ssl >> $(TOP)/MINFO
 
@@ -123,7 +147,7 @@
 	mv -f Makefile.new $(MAKEFILE)
 
 clean:
-	/bin/rm -f *.o */*.o *.obj lib tags core .pure .nfs* *.old *.bak fluff bn_mulw.s
+	/bin/rm -f *.o */*.o *.obj lib tags core .pure .nfs* *.old *.bak fluff bn_asm.s
 
 errors:
 	perl $(TOP)/util/err-ins.pl $(ERR).err $(ERR).org # special case .org
diff --git a/crypto/bn/alpha.s b/crypto/bn/alpha.s
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/crypto/bn/alpha.s
diff --git a/crypto/bn/asm/a.out b/crypto/bn/asm/a.out
new file mode 100644
index 0000000..cc5094f
--- /dev/null
+++ b/crypto/bn/asm/a.out
Binary files differ
diff --git a/crypto/bn/asm/alpha.s b/crypto/bn/asm/alpha.s
index 1d17b1d..cf0b69c 100644
--- a/crypto/bn/asm/alpha.s
+++ b/crypto/bn/asm/alpha.s
@@ -2,7 +2,13 @@
  # The bn_div64 is actually gcc output but the other parts are hand done.
  # Thanks to tzeruch@ceddec.com for sending me the gcc output for
  # bn_div64.
-	.file	1 "bn_mulw.c"
+ # I've gone back and re-done most of routines.
+ # The key thing to remeber for the 164 CPU is that while a
+ # multiply operation takes 8 cycles, another one can only be issued
+ # after 4 cycles have elapsed.  I've done modification to help
+ # improve this.  Also, normally, a ld instruction will not be available
+ # for about 3 cycles.
+	.file	1 "bn_asm.c"
 	.set noat
 gcc2_compiled.:
 __gnu_compiled_c:
@@ -14,65 +20,91 @@
 bn_mul_add_words..ng:
 	.frame $30,0,$26,0
 	.prologue 0
-	subq $18,2,$25	# num=-2
-	bis $31,$31,$0
-	blt $25,$42
 	.align 5
-$142:
-	subq $18,2,$18	# num-=2
-	subq $25,2,$25	# num-=2
-
-	ldq $1,0($17)	# a[0]
-	ldq $2,8($17)	# a[1]
-
-	mulq $19,$1,$3	# a[0]*w low part	r3
- 	umulh $19,$1,$1 # a[0]*w high part	r1
-	mulq $19,$2,$4	# a[1]*w low part	r4
- 	umulh $19,$2,$2 # a[1]*w high part	r2
-
-	ldq $22,0($16)	# r[0]			r22
-	ldq $23,8($16)	# r[1]			r23
-
-	addq $3,$22,$3	# a0 low part + r[0]	
-	addq $4,$23,$4	# a1 low part + r[1]	
-	cmpult $3,$22,$5 # overflow?
-	cmpult $4,$23,$6 # overflow?
-	addq $5,$1,$1	# high part + overflow 
-	addq $6,$2,$2	# high part + overflow 
-
-	addq $3,$0,$3	# add c
-	cmpult $3,$0,$5 # overflow?
-	stq $3,0($16)
-	addq $5,$1,$0	# c=high part + overflow 
-
-	addq $4,$0,$4	# add c
-	cmpult $4,$0,$5 # overflow?
-	stq $4,8($16)
-	addq $5,$2,$0	# c=high part + overflow 
-
-	ble $18,$43
-
- 	addq $16,16,$16
- 	addq $17,16,$17
-	blt $25,$42
-
- 	br $31,$142
+	subq	$18,4,$18
+	bis	$31,$31,$0
+	blt	$18,$43		# if we are -1, -2, -3 or -4 goto tail code
+	ldq	$20,0($17)	# 1 1
+	ldq	$1,0($16)	# 1 1
+	.align 3
 $42:
-	ldq $1,0($17)	# a[0]
- 	umulh $19,$1,$3 # a[0]*w high part
-	mulq $19,$1,$1	# a[0]*w low part
-	ldq $2,0($16)	# r[0]
-	addq $1,$2,$1	# low part + r[0]
-	cmpult $1,$2,$4 # overflow?
-	addq $4,$3,$3	# high part + overflow 
-	addq $1,$0,$1	# add c
-	cmpult $1,$0,$4 # overflow?
-	addq $4,$3,$0	# c=high part + overflow 
-	stq $1,0($16)
+	mulq	$20,$19,$5	# 1 2 1	######
+	ldq	$21,8($17)	# 2 1
+	ldq	$2,8($16)	# 2 1
+	umulh	$20,$19,$20	# 1 2	######
+	ldq	$27,16($17)	# 3 1
+	ldq	$3,16($16)	# 3 1
+	mulq	$21,$19,$6	# 2 2 1	######
+	 ldq	$28,24($17)	# 4 1
+	addq	$1,$5,$1	# 1 2 2
+	 ldq	$4,24($16)	# 4 1
+	umulh	$21,$19,$21	# 2 2	######
+	 cmpult	$1,$5,$22	# 1 2 3 1
+	addq	$20,$22,$20	# 1 3 1
+	 addq	$1,$0,$1	# 1 2 3 1
+	mulq	$27,$19,$7	# 3 2 1	######
+	 cmpult	$1,$0,$0	# 1 2 3 2
+	addq	$2,$6,$2	# 2 2 2
+	 addq	$20,$0,$0	# 1 3 2 
+	cmpult	$2,$6,$23	# 2 2 3 1
+	 addq	$21,$23,$21	# 2 3 1
+	umulh	$27,$19,$27	# 3 2	######
+	 addq	$2,$0,$2	# 2 2 3 1
+	cmpult	$2,$0,$0	# 2 2 3 2
+	 subq	$18,4,$18
+	mulq	$28,$19,$8	# 4 2 1	######
+	 addq	$21,$0,$0	# 2 3 2 
+	addq	$3,$7,$3	# 3 2 2
+	 addq	$16,32,$16
+	cmpult	$3,$7,$24	# 3 2 3 1
+	 stq	$1,-32($16)	# 1 2 4
+	umulh	$28,$19,$28	# 4 2	######
+	 addq	$27,$24,$27	# 3 3 1
+	addq	$3,$0,$3	# 3 2 3 1
+	 stq	$2,-24($16)	# 2 2 4
+	cmpult	$3,$0,$0	# 3 2 3 2
+	 stq	$3,-16($16)	# 3 2 4
+	addq	$4,$8,$4	# 4 2 2
+	 addq	$27,$0,$0	# 3 3 2 
+	cmpult	$4,$8,$25	# 4 2 3 1
+	 addq	$17,32,$17
+	addq	$28,$25,$28	# 4 3 1
+	 addq	$4,$0,$4	# 4 2 3 1
+	cmpult	$4,$0,$0	# 4 2 3 2
+	 stq	$4,-8($16)	# 4 2 4
+	addq	$28,$0,$0	# 4 3 2 
+	 blt	$18,$43
+
+	ldq	$20,0($17)	# 1 1
+	ldq	$1,0($16)	# 1 1
+
+	br	$42
+
+	.align 4
+$45:
+	ldq	$20,0($17)	# 4 1
+	ldq	$1,0($16)	# 4 1
+	mulq	$20,$19,$5	# 4 2 1
+	subq	$18,1,$18
+	addq	$16,8,$16
+	addq	$17,8,$17
+	umulh	$20,$19,$20	# 4 2
+	addq	$1,$5,$1	# 4 2 2
+	cmpult	$1,$5,$22	# 4 2 3 1
+	addq	$20,$22,$20	# 4 3 1
+	addq	$1,$0,$1	# 4 2 3 1
+	cmpult	$1,$0,$0	# 4 2 3 2
+	addq	$20,$0,$0	# 4 3 2 
+	stq	$1,-8($16)	# 4 2 4
+	bgt	$18,$45
+	ret	$31,($26),1	# else exit
 
 	.align 4
 $43:
-	ret $31,($26),1
+	addq	$18,4,$18
+	bgt	$18,$45		# goto tail code
+	ret	$31,($26),1	# else exit
+
 	.end bn_mul_add_words
 	.align 3
 	.globl bn_mul_words
@@ -81,49 +113,75 @@
 bn_mul_words..ng:
 	.frame $30,0,$26,0
 	.prologue 0
-	subq $18,2,$25	# num=-2
-	bis $31,$31,$0
-	blt $25,$242
 	.align 5
-$342:
-	subq $18,2,$18	# num-=2
-	subq $25,2,$25	# num-=2
+	subq	$18,4,$18
+	bis	$31,$31,$0
+	blt	$18,$143	# if we are -1, -2, -3 or -4 goto tail code
+	ldq	$20,0($17)	# 1 1
+	.align 3
+$142:
 
-	ldq $1,0($17)	# a[0]
-	ldq $2,8($17)	# a[1]
+	mulq	$20,$19,$5	# 1 2 1	#####
+	 ldq	$21,8($17)	# 2 1
+	 ldq	$27,16($17)	# 3 1
+	umulh	$20,$19,$20	# 1 2	#####
+	 ldq	$28,24($17)	# 4 1
+	mulq	$21,$19,$6	# 2 2 1	#####
+	 addq	$5,$0,$5	# 1 2 3 1
+	subq	$18,4,$18
+	 cmpult	$5,$0,$0	# 1 2 3 2
+	umulh	$21,$19,$21	# 2 2	#####
+	 addq	$20,$0,$0	# 1 3 2 
+	addq	$17,32,$17
+	 addq	$6,$0,$6	# 2 2 3 1
+	mulq	$27,$19,$7	# 3 2 1	#####
+	 cmpult	$6,$0,$0	# 2 2 3 2
+	addq	$21,$0,$0	# 2 3 2 
+	 addq	$16,32,$16
+	umulh	$27,$19,$27	# 3 2	#####
+	 stq	$5,-32($16)	# 1 2 4
+	mulq	$28,$19,$8	# 4 2 1	#####
+	 addq	$7,$0,$7	# 3 2 3 1
+	stq	$6,-24($16)	# 2 2 4
+	 cmpult	$7,$0,$0	# 3 2 3 2
+	umulh	$28,$19,$28	# 4 2	#####
+	 addq	$27,$0,$0	# 3 3 2 
+	stq	$7,-16($16)	# 3 2 4
+	 addq	$8,$0,$8	# 4 2 3 1
+	cmpult	$8,$0,$0	# 4 2 3 2
 
-	mulq $19,$1,$3	# a[0]*w low part	r3
- 	umulh $19,$1,$1 # a[0]*w high part	r1
-	mulq $19,$2,$4	# a[1]*w low part	r4
- 	umulh $19,$2,$2 # a[1]*w high part	r2
+	addq	$28,$0,$0	# 4 3 2 
 
-	addq $3,$0,$3	# add c
-	cmpult $3,$0,$5 # overflow?
-	stq $3,0($16)
-	addq $5,$1,$0	# c=high part + overflow 
+	stq	$8,-8($16)	# 4 2 4
 
-	addq $4,$0,$4	# add c
-	cmpult $4,$0,$5 # overflow?
-	stq $4,8($16)
-	addq $5,$2,$0	# c=high part + overflow 
+	blt	$18,$143
 
-	ble $18,$243
+	ldq	$20,0($17)	# 1 1
 
- 	addq $16,16,$16
- 	addq $17,16,$17
-	blt $25,$242
+	br	$142
 
- 	br $31,$342
-$242:
-	ldq $1,0($17)	# a[0]
- 	umulh $19,$1,$3 # a[0]*w high part
-	mulq $19,$1,$1	# a[0]*w low part
-	addq $1,$0,$1	# add c
-	cmpult $1,$0,$4 # overflow?
-	addq $4,$3,$0	# c=high part + overflow 
-	stq $1,0($16)
-$243:
-	ret $31,($26),1
+	.align 4
+$145:
+	ldq	$20,0($17)	# 4 1
+	mulq	$20,$19,$5	# 4 2 1
+	subq	$18,1,$18
+	umulh	$20,$19,$20	# 4 2
+	addq	$5,$0,$5	# 4 2 3 1
+	 addq	$16,8,$16
+	cmpult	$5,$0,$0	# 4 2 3 2
+	 addq	$17,8,$17
+	addq	$20,$0,$0	# 4 3 2 
+	stq	$5,-8($16)	# 4 2 4
+
+	bgt	$18,$145
+	ret	$31,($26),1	# else exit
+
+	.align 4
+$143:
+	addq	$18,4,$18
+	bgt	$18,$145	# goto tail code
+	ret	$31,($26),1	# else exit
+
 	.end bn_mul_words
 	.align 3
 	.globl bn_sqr_words
@@ -132,44 +190,58 @@
 bn_sqr_words..ng:
 	.frame $30,0,$26,0
 	.prologue 0
-	
-	subq $18,2,$25	# num=-2
-	blt $25,$442
-	.align 5
+
+	subq	$18,4,$18
+	blt	$18,$543	# if we are -1, -2, -3 or -4 goto tail code
+	ldq	$20,0($17)	# 1 1
+	.align 3
 $542:
-	subq $18,2,$18	# num-=2
-	subq $25,2,$25	# num-=2
+	mulq	$20,$20,$5		######
+	 ldq	$21,8($17)	# 1 1
+	subq	$18,4
+ 	umulh	$20,$20,$1		######
+	ldq	$27,16($17)	# 1 1
+	mulq	$21,$21,$6		######
+	ldq	$28,24($17)	# 1 1
+	stq	$5,0($16)	# r[0]
+ 	umulh	$21,$21,$2		######
+	stq	$1,8($16)	# r[1]
+	mulq	$27,$27,$7		######
+	stq	$6,16($16)	# r[0]
+ 	umulh	$27,$27,$3		######
+	stq	$2,24($16)	# r[1]
+	mulq	$28,$28,$8		######
+	stq	$7,32($16)	# r[0]
+ 	umulh	$28,$28,$4		######
+	stq	$3,40($16)	# r[1]
 
-	ldq $1,0($17)	# a[0]
-	ldq $4,8($17)	# a[1]
+ 	addq	$16,64,$16
+ 	addq	$17,32,$17
+	stq	$8,-16($16)	# r[0]
+	stq	$4,-8($16)	# r[1]
 
-	mulq $1,$1,$2	# a[0]*w low part	r2
- 	umulh $1,$1,$3 # a[0]*w high part	r3
-	mulq $4,$4,$5	# a[1]*w low part	r5
- 	umulh $4,$4,$6 # a[1]*w high part	r6
-
-	stq $2,0($16)	# r[0]
-	stq $3,8($16)	# r[1]
-	stq $5,16($16)	# r[3]
-	stq $6,24($16)	# r[4]
-
-	ble $18,$443
-
- 	addq $16,32,$16
- 	addq $17,16,$17
-	blt $25,$442
- 	br $31,$542
+	blt	$18,$543
+	ldq	$20,0($17)	# 1 1
+ 	br 	$542
 
 $442:
-	ldq $1,0($17)   # a[0]
-	mulq $1,$1,$2   # a[0]*w low part       r2
-        umulh $1,$1,$3  # a[0]*w high part       r3
-	stq $2,0($16)   # r[0]
-        stq $3,8($16)   # r[1]
+	ldq	$20,0($17)   # a[0]
+	mulq	$20,$20,$5  # a[0]*w low part       r2
+	addq	$16,16,$16
+	addq	$17,8,$17
+	subq	$18,1,$18
+        umulh	$20,$20,$1  # a[0]*w high part       r3
+	stq	$5,-16($16)   # r[0]
+        stq	$1,-8($16)   # r[1]
+
+	bgt	$18,$442
+	ret	$31,($26),1	# else exit
 
 	.align 4
-$443:
-	ret $31,($26),1
+$543:
+	addq	$18,4,$18
+	bgt	$18,$442	# goto tail code
+	ret	$31,($26),1	# else exit
 	.end bn_sqr_words
 
 	.align 3
@@ -180,31 +252,74 @@
 	.frame $30,0,$26,0
 	.prologue 0
 
-	bis	$31,$31,$8	# carry = 0
-	ble	$19,$900
+	subq	$19,4,$19
+	bis	$31,$31,$0	# carry = 0
+	blt	$19,$900
+	ldq	$5,0($17)	# a[0]
+	ldq	$1,0($18)	# b[1]
+	.align 3
 $901:
-	ldq	$0,0($17)	# a[0]
-	ldq	$1,0($18)	# a[1]
+	addq	$1,$5,$1	# r=a+b;
+	 ldq	$6,8($17)	# a[1]
+	cmpult	$1,$5,$22	# did we overflow?
+	 ldq	$2,8($18)	# b[1]
+	addq	$1,$0,$1	# c+= overflow
+	 ldq	$7,16($17)	# a[2]
+	cmpult	$1,$0,$0	# overflow?
+	 ldq	$3,16($18)	# b[2]
+	addq	$0,$22,$0
+	 ldq	$8,24($17)	# a[3]
+	addq	$2,$6,$2	# r=a+b;
+	 ldq	$4,24($18)	# b[3]
+	cmpult	$2,$6,$23	# did we overflow?
+	 addq	$3,$7,$3	# r=a+b;
+	addq	$2,$0,$2	# c+= overflow
+	 cmpult	$3,$7,$24	# did we overflow?
+	cmpult	$2,$0,$0	# overflow?
+	 addq	$4,$8,$4	# r=a+b;
+	addq	$0,$23,$0
+	 cmpult	$4,$8,$25	# did we overflow?
+	addq	$3,$0,$3	# c+= overflow
+	 stq	$1,0($16)	# r[0]=c
+	cmpult	$3,$0,$0	# overflow?
+	 stq	$2,8($16)	# r[1]=c
+	addq	$0,$24,$0
+	 stq	$3,16($16)	# r[2]=c
+	addq	$4,$0,$4	# c+= overflow
+	 subq	$19,4,$19	# loop--
+	cmpult	$4,$0,$0	# overflow?
+	 addq	$17,32,$17	# a++
+	addq	$0,$25,$0
+	 stq	$4,24($16)	# r[3]=c
+	addq	$18,32,$18	# b++
+	 addq	$16,32,$16	# r++
 
-	addq	$0,$1,$3	# c=a+b;
-	 addq	$17,8,$17	# a++
-
-	cmpult	$3,$1,$7	# did we overflow?
-	 addq	$18,8,$18	# b++
-
-	addq	$8,$3,$3	# c+=carry
-
-	cmpult	$3,$8,$8	# did we overflow?
-	 stq	$3,($16)	# r[0]=c
-
-	addq	$7,$8,$8	# add into overflow
+	blt	$19,$900
+	 ldq	$5,0($17)	# a[0]
+	ldq	$1,0($18)	# b[1]
+	 br	$901
+	.align 4
+$945:
+	ldq	$5,0($17)	# a[0]
+	 ldq	$1,0($18)	# b[1]
+	addq	$1,$5,$1	# r=a+b;
 	 subq	$19,1,$19	# loop--
+	addq	$1,$0,$1	# c+= overflow
+	 addq	$17,8,$17	# a++
+	cmpult	$1,$5,$22	# did we overflow?
+	 cmpult	$1,$0,$0	# overflow?
+	addq	$18,8,$18	# b++
+	 stq	$1,0($16)	# r[0]=c
+	addq	$0,$22,$0
+	 addq	$16,8,$16	# r++
 
-	addq	$16,8,$16	# r++
-	 bgt	$19,$901
+	bgt	$19,$945
+	ret	$31,($26),1	# else exit
+
 $900:
-	bis	$8,$8,$0	# return carry
-	ret $31,($26),1
+	addq	$19,4,$19
+	bgt	$19,$945	# goto tail code
+	ret	$31,($26),1	# else exit
 	.end bn_add_words
 
  #
@@ -339,6 +454,1445 @@
 	addq $30,48,$30
 	ret $31,($26),1
 	.end bn_div64
-	.ident	"GCC: (GNU) 2.7.2.1"
 
+	.set noat
+	.text
+	.align 3
+	.globl bn_sub_words
+	.ent bn_sub_words
+bn_sub_words:
+bn_sub_words..ng:
+	.frame $30,0,$26,0
+	.prologue 0
 
+	subq	$19,	4,	$19
+	bis	$31,	$31,	$0
+	blt	$19,	$100
+	ldq	$1,	0($17)
+	ldq	$2,	0($18)
+$101:
+	ldq	$3,	8($17)
+	cmpult	$1,	$2,	$4
+	ldq	$5,	8($18)
+	subq	$1,	$2,	$1
+	ldq	$6,	16($17)
+	cmpult	$1,	$0,	$2
+	ldq	$7,	16($18)
+	subq	$1,	$0,	$23
+	ldq	$8,	24($17)
+	addq	$2,	$4,	$0
+	cmpult	$3,	$5,	$24
+	subq	$3,	$5,	$3
+	ldq	$22,	24($18)
+	cmpult	$3,	$0,	$5
+	subq	$3,	$0,	$25
+	addq	$5,	$24,	$0
+	cmpult	$6,	$7,	$27
+	subq	$6,	$7,	$6
+	stq	$23,	0($16)
+	cmpult	$6,	$0,	$7
+	subq	$6,	$0,	$28
+	addq	$7,	$27,	$0
+	cmpult	$8,	$22,	$21
+	subq	$8,	$22,	$8
+	stq	$25,	8($16)
+	cmpult	$8,	$0,	$22
+	subq	$8,	$0,	$20
+	addq	$22,	$21,	$0
+	stq	$28,	16($16)
+	subq	$19,	4,	$19
+	stq	$20,	24($16)
+	addq	$17,	32,	$17
+	addq	$18,	32,	$18
+	addq	$16,	32,	$16
+	blt	$19,	$100
+	ldq	$1,	0($17)
+	ldq	$2,	0($18)
+	br	$101
+$102:
+	ldq	$1,	0($17)
+	ldq	$2,	0($18)
+	cmpult	$1,	$2,	$27
+	subq	$1,	$2,	$1
+	cmpult	$1,	$0,	$2
+	subq	$1,	$0,	$1
+	stq	$1,	0($16)
+	addq	$2,	$27,	$0
+	addq	$17,	8,	$17
+	addq	$18,	8,	$18
+	addq	$16,	8,	$16
+	subq	$19,	1,	$19
+	bgt	$19,	$102
+	ret	$31,($26),1
+$100:
+	addq	$19,	4,	$19
+	bgt	$19,	$102
+$103:
+	ret	$31,($26),1
+	.end bn_sub_words
+	.text
+	.align 3
+	.globl bn_mul_comba4
+	.ent bn_mul_comba4
+bn_mul_comba4:
+bn_mul_comba4..ng:
+	.frame $30,0,$26,0
+	.prologue 0
+
+	ldq	$0,	0($17)
+	ldq	$1,	0($18)
+	ldq	$2,	8($17)
+	ldq	$3,	8($18)
+	ldq	$4,	16($17)
+	ldq	$5,	16($18)
+	ldq	$6,	24($17)
+	ldq	$7,	24($18)
+	bis	$31,	$31,	$23
+	mulq	$0,	$1,	$8
+	umulh	$0,	$1,	$22
+	stq	$8,	0($16)
+	bis	$31,	$31,	$8
+	mulq	$0,	$3,	$24
+	umulh	$0,	$3,	$25
+	addq	$22,	$24,	$22
+	cmpult	$22,	$24,	$27
+	addq	$27,	$25,	$25
+	addq	$23,	$25,	$23
+	cmpult	$23,	$25,	$28
+	addq	$8,	$28,	$8
+	mulq	$2,	$1,	$21
+	umulh	$2,	$1,	$20
+	addq	$22,	$21,	$22
+	cmpult	$22,	$21,	$19
+	addq	$19,	$20,	$20
+	addq	$23,	$20,	$23
+	cmpult	$23,	$20,	$17
+	addq	$8,	$17,	$8
+	stq	$22,	8($16)
+	bis	$31,	$31,	$22
+	mulq	$2,	$3,	$18
+	umulh	$2,	$3,	$24
+	addq	$23,	$18,	$23
+	cmpult	$23,	$18,	$27
+	addq	$27,	$24,	$24
+	addq	$8,	$24,	$8
+	cmpult	$8,	$24,	$25
+	addq	$22,	$25,	$22
+	mulq	$0,	$5,	$28
+	umulh	$0,	$5,	$21
+	addq	$23,	$28,	$23
+	cmpult	$23,	$28,	$19
+	addq	$19,	$21,	$21
+	addq	$8,	$21,	$8
+	cmpult	$8,	$21,	$20
+	addq	$22,	$20,	$22
+	mulq	$4,	$1,	$17
+	umulh	$4,	$1,	$18
+	addq	$23,	$17,	$23
+	cmpult	$23,	$17,	$27
+	addq	$27,	$18,	$18
+	addq	$8,	$18,	$8
+	cmpult	$8,	$18,	$24
+	addq	$22,	$24,	$22
+	stq	$23,	16($16)
+	bis	$31,	$31,	$23
+	mulq	$0,	$7,	$25
+	umulh	$0,	$7,	$28
+	addq	$8,	$25,	$8
+	cmpult	$8,	$25,	$19
+	addq	$19,	$28,	$28
+	addq	$22,	$28,	$22
+	cmpult	$22,	$28,	$21
+	addq	$23,	$21,	$23
+	mulq	$2,	$5,	$20
+	umulh	$2,	$5,	$17
+	addq	$8,	$20,	$8
+	cmpult	$8,	$20,	$27
+	addq	$27,	$17,	$17
+	addq	$22,	$17,	$22
+	cmpult	$22,	$17,	$18
+	addq	$23,	$18,	$23
+	mulq	$4,	$3,	$24
+	umulh	$4,	$3,	$25
+	addq	$8,	$24,	$8
+	cmpult	$8,	$24,	$19
+	addq	$19,	$25,	$25
+	addq	$22,	$25,	$22
+	cmpult	$22,	$25,	$28
+	addq	$23,	$28,	$23
+	mulq	$6,	$1,	$21
+	umulh	$6,	$1,	$0
+	addq	$8,	$21,	$8
+	cmpult	$8,	$21,	$20
+	addq	$20,	$0,	$0
+	addq	$22,	$0,	$22
+	cmpult	$22,	$0,	$27
+	addq	$23,	$27,	$23
+	stq	$8,	24($16)
+	bis	$31,	$31,	$8
+	mulq	$2,	$7,	$17
+	umulh	$2,	$7,	$18
+	addq	$22,	$17,	$22
+	cmpult	$22,	$17,	$24
+	addq	$24,	$18,	$18
+	addq	$23,	$18,	$23
+	cmpult	$23,	$18,	$19
+	addq	$8,	$19,	$8
+	mulq	$4,	$5,	$25
+	umulh	$4,	$5,	$28
+	addq	$22,	$25,	$22
+	cmpult	$22,	$25,	$21
+	addq	$21,	$28,	$28
+	addq	$23,	$28,	$23
+	cmpult	$23,	$28,	$20
+	addq	$8,	$20,	$8
+	mulq	$6,	$3,	$0
+	umulh	$6,	$3,	$27
+	addq	$22,	$0,	$22
+	cmpult	$22,	$0,	$1
+	addq	$1,	$27,	$27
+	addq	$23,	$27,	$23
+	cmpult	$23,	$27,	$17
+	addq	$8,	$17,	$8
+	stq	$22,	32($16)
+	bis	$31,	$31,	$22
+	mulq	$4,	$7,	$24
+	umulh	$4,	$7,	$18
+	addq	$23,	$24,	$23
+	cmpult	$23,	$24,	$19
+	addq	$19,	$18,	$18
+	addq	$8,	$18,	$8
+	cmpult	$8,	$18,	$2
+	addq	$22,	$2,	$22
+	mulq	$6,	$5,	$25
+	umulh	$6,	$5,	$21
+	addq	$23,	$25,	$23
+	cmpult	$23,	$25,	$28
+	addq	$28,	$21,	$21
+	addq	$8,	$21,	$8
+	cmpult	$8,	$21,	$20
+	addq	$22,	$20,	$22
+	stq	$23,	40($16)
+	bis	$31,	$31,	$23
+	mulq	$6,	$7,	$0
+	umulh	$6,	$7,	$1
+	addq	$8,	$0,	$8
+	cmpult	$8,	$0,	$27
+	addq	$27,	$1,	$1
+	addq	$22,	$1,	$22
+	cmpult	$22,	$1,	$17
+	addq	$23,	$17,	$23
+	stq	$8,	48($16)
+	stq	$22,	56($16)
+	ret	$31,($26),1
+	.end bn_mul_comba4
+	.text
+	.align 3
+	.globl bn_mul_comba8
+	.ent bn_mul_comba8
+bn_mul_comba8:
+bn_mul_comba8..ng:
+	.frame $30,0,$26,0
+	.prologue 0
+
+	subq	$30,	16,	$30
+	ldq	$0,	0($17)
+	ldq	$1,	0($18)
+	stq	$9,	0($30)
+	stq	$10,	8($30)
+	ldq	$2,	8($17)
+	ldq	$3,	8($18)
+	ldq	$4,	16($17)
+	ldq	$5,	16($18)
+	ldq	$6,	24($17)
+	ldq	$7,	24($18)
+	ldq	$8,	8($17)
+	ldq	$22,	8($18)
+	ldq	$23,	8($17)
+	ldq	$24,	8($18)
+	ldq	$25,	8($17)
+	ldq	$27,	8($18)
+	ldq	$28,	8($17)
+	ldq	$21,	8($18)
+	bis	$31,	$31,	$9
+	mulq	$0,	$1,	$20
+	umulh	$0,	$1,	$19
+	stq	$20,	0($16)
+	bis	$31,	$31,	$20
+	mulq	$0,	$3,	$10
+	umulh	$0,	$3,	$17
+	addq	$19,	$10,	$19
+	cmpult	$19,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$10
+	addq	$20,	$10,	$20
+	mulq	$2,	$1,	$18
+	umulh	$2,	$1,	$17
+	addq	$19,	$18,	$19
+	cmpult	$19,	$18,	$10
+	addq	$10,	$17,	$17
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$18
+	addq	$20,	$18,	$20
+	stq	$19,	8($16)
+	bis	$31,	$31,	$19
+	mulq	$0,	$5,	$10
+	umulh	$0,	$5,	$17
+	addq	$9,	$10,	$9
+	cmpult	$9,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$20,	$17,	$20
+	cmpult	$20,	$17,	$10
+	addq	$19,	$10,	$19
+	mulq	$2,	$3,	$18
+	umulh	$2,	$3,	$17
+	addq	$9,	$18,	$9
+	cmpult	$9,	$18,	$10
+	addq	$10,	$17,	$17
+	addq	$20,	$17,	$20
+	cmpult	$20,	$17,	$18
+	addq	$19,	$18,	$19
+	mulq	$4,	$1,	$10
+	umulh	$4,	$1,	$17
+	addq	$9,	$10,	$9
+	cmpult	$9,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$20,	$17,	$20
+	cmpult	$20,	$17,	$10
+	addq	$19,	$10,	$19
+	stq	$9,	16($16)
+	bis	$31,	$31,	$9
+	mulq	$0,	$7,	$18
+	umulh	$0,	$7,	$17
+	addq	$20,	$18,	$20
+	cmpult	$20,	$18,	$10
+	addq	$10,	$17,	$17
+	addq	$19,	$17,	$19
+	cmpult	$19,	$17,	$18
+	addq	$9,	$18,	$9
+	mulq	$2,	$5,	$10
+	umulh	$2,	$5,	$17
+	addq	$20,	$10,	$20
+	cmpult	$20,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$19,	$17,	$19
+	cmpult	$19,	$17,	$10
+	addq	$9,	$10,	$9
+	mulq	$4,	$3,	$18
+	umulh	$4,	$3,	$17
+	addq	$20,	$18,	$20
+	cmpult	$20,	$18,	$10
+	addq	$10,	$17,	$17
+	addq	$19,	$17,	$19
+	cmpult	$19,	$17,	$18
+	addq	$9,	$18,	$9
+	mulq	$6,	$1,	$10
+	umulh	$6,	$1,	$17
+	addq	$20,	$10,	$20
+	cmpult	$20,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$19,	$17,	$19
+	cmpult	$19,	$17,	$10
+	addq	$9,	$10,	$9
+	stq	$20,	24($16)
+	bis	$31,	$31,	$20
+	mulq	$0,	$22,	$18
+	umulh	$0,	$22,	$17
+	addq	$19,	$18,	$19
+	cmpult	$19,	$18,	$10
+	addq	$10,	$17,	$17
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$18
+	addq	$20,	$18,	$20
+	mulq	$2,	$7,	$10
+	umulh	$2,	$7,	$17
+	addq	$19,	$10,	$19
+	cmpult	$19,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$10
+	addq	$20,	$10,	$20
+	mulq	$4,	$5,	$18
+	umulh	$4,	$5,	$17
+	addq	$19,	$18,	$19
+	cmpult	$19,	$18,	$10
+	addq	$10,	$17,	$17
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$18
+	addq	$20,	$18,	$20
+	mulq	$6,	$3,	$10
+	umulh	$6,	$3,	$17
+	addq	$19,	$10,	$19
+	cmpult	$19,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$10
+	addq	$20,	$10,	$20
+	mulq	$8,	$1,	$18
+	umulh	$8,	$1,	$17
+	addq	$19,	$18,	$19
+	cmpult	$19,	$18,	$10
+	addq	$10,	$17,	$17
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$18
+	addq	$20,	$18,	$20
+	stq	$19,	32($16)
+	bis	$31,	$31,	$19
+	mulq	$0,	$24,	$10
+	umulh	$0,	$24,	$17
+	addq	$9,	$10,	$9
+	cmpult	$9,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$20,	$17,	$20
+	cmpult	$20,	$17,	$10
+	addq	$19,	$10,	$19
+	mulq	$2,	$22,	$18
+	umulh	$2,	$22,	$17
+	addq	$9,	$18,	$9
+	cmpult	$9,	$18,	$10
+	addq	$10,	$17,	$17
+	addq	$20,	$17,	$20
+	cmpult	$20,	$17,	$18
+	addq	$19,	$18,	$19
+	mulq	$4,	$7,	$10
+	umulh	$4,	$7,	$17
+	addq	$9,	$10,	$9
+	cmpult	$9,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$20,	$17,	$20
+	cmpult	$20,	$17,	$10
+	addq	$19,	$10,	$19
+	mulq	$6,	$5,	$18
+	umulh	$6,	$5,	$17
+	addq	$9,	$18,	$9
+	cmpult	$9,	$18,	$10
+	addq	$10,	$17,	$17
+	addq	$20,	$17,	$20
+	cmpult	$20,	$17,	$18
+	addq	$19,	$18,	$19
+	mulq	$8,	$3,	$10
+	umulh	$8,	$3,	$17
+	addq	$9,	$10,	$9
+	cmpult	$9,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$20,	$17,	$20
+	cmpult	$20,	$17,	$10
+	addq	$19,	$10,	$19
+	mulq	$23,	$1,	$18
+	umulh	$23,	$1,	$17
+	addq	$9,	$18,	$9
+	cmpult	$9,	$18,	$10
+	addq	$10,	$17,	$17
+	addq	$20,	$17,	$20
+	cmpult	$20,	$17,	$18
+	addq	$19,	$18,	$19
+	stq	$9,	40($16)
+	bis	$31,	$31,	$9
+	mulq	$0,	$27,	$10
+	umulh	$0,	$27,	$17
+	addq	$20,	$10,	$20
+	cmpult	$20,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$19,	$17,	$19
+	cmpult	$19,	$17,	$10
+	addq	$9,	$10,	$9
+	mulq	$2,	$24,	$18
+	umulh	$2,	$24,	$17
+	addq	$20,	$18,	$20
+	cmpult	$20,	$18,	$10
+	addq	$10,	$17,	$17
+	addq	$19,	$17,	$19
+	cmpult	$19,	$17,	$18
+	addq	$9,	$18,	$9
+	mulq	$4,	$22,	$10
+	umulh	$4,	$22,	$17
+	addq	$20,	$10,	$20
+	cmpult	$20,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$19,	$17,	$19
+	cmpult	$19,	$17,	$10
+	addq	$9,	$10,	$9
+	mulq	$6,	$7,	$18
+	umulh	$6,	$7,	$17
+	addq	$20,	$18,	$20
+	cmpult	$20,	$18,	$10
+	addq	$10,	$17,	$17
+	addq	$19,	$17,	$19
+	cmpult	$19,	$17,	$18
+	addq	$9,	$18,	$9
+	mulq	$8,	$5,	$10
+	umulh	$8,	$5,	$17
+	addq	$20,	$10,	$20
+	cmpult	$20,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$19,	$17,	$19
+	cmpult	$19,	$17,	$10
+	addq	$9,	$10,	$9
+	mulq	$23,	$3,	$18
+	umulh	$23,	$3,	$17
+	addq	$20,	$18,	$20
+	cmpult	$20,	$18,	$10
+	addq	$10,	$17,	$17
+	addq	$19,	$17,	$19
+	cmpult	$19,	$17,	$18
+	addq	$9,	$18,	$9
+	mulq	$25,	$1,	$10
+	umulh	$25,	$1,	$17
+	addq	$20,	$10,	$20
+	cmpult	$20,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$19,	$17,	$19
+	cmpult	$19,	$17,	$10
+	addq	$9,	$10,	$9
+	stq	$20,	48($16)
+	bis	$31,	$31,	$20
+	mulq	$0,	$21,	$18
+	umulh	$0,	$21,	$17
+	addq	$19,	$18,	$19
+	cmpult	$19,	$18,	$10
+	addq	$10,	$17,	$17
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$18
+	addq	$20,	$18,	$20
+	mulq	$2,	$27,	$10
+	umulh	$2,	$27,	$17
+	addq	$19,	$10,	$19
+	cmpult	$19,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$0
+	addq	$20,	$0,	$20
+	mulq	$4,	$24,	$10
+	umulh	$4,	$24,	$18
+	addq	$19,	$10,	$19
+	cmpult	$19,	$10,	$17
+	addq	$17,	$18,	$18
+	addq	$9,	$18,	$9
+	cmpult	$9,	$18,	$0
+	addq	$20,	$0,	$20
+	mulq	$6,	$22,	$10
+	umulh	$6,	$22,	$17
+	addq	$19,	$10,	$19
+	cmpult	$19,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$0
+	addq	$20,	$0,	$20
+	mulq	$8,	$7,	$10
+	umulh	$8,	$7,	$18
+	addq	$19,	$10,	$19
+	cmpult	$19,	$10,	$17
+	addq	$17,	$18,	$18
+	addq	$9,	$18,	$9
+	cmpult	$9,	$18,	$0
+	addq	$20,	$0,	$20
+	mulq	$23,	$5,	$10
+	umulh	$23,	$5,	$17
+	addq	$19,	$10,	$19
+	cmpult	$19,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$0
+	addq	$20,	$0,	$20
+	mulq	$25,	$3,	$10
+	umulh	$25,	$3,	$18
+	addq	$19,	$10,	$19
+	cmpult	$19,	$10,	$17
+	addq	$17,	$18,	$18
+	addq	$9,	$18,	$9
+	cmpult	$9,	$18,	$0
+	addq	$20,	$0,	$20
+	mulq	$28,	$1,	$10
+	umulh	$28,	$1,	$17
+	addq	$19,	$10,	$19
+	cmpult	$19,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$0
+	addq	$20,	$0,	$20
+	stq	$19,	56($16)
+	bis	$31,	$31,	$19
+	mulq	$2,	$21,	$10
+	umulh	$2,	$21,	$18
+	addq	$9,	$10,	$9
+	cmpult	$9,	$10,	$17
+	addq	$17,	$18,	$18
+	addq	$20,	$18,	$20
+	cmpult	$20,	$18,	$0
+	addq	$19,	$0,	$19
+	mulq	$4,	$27,	$1
+	umulh	$4,	$27,	$10
+	addq	$9,	$1,	$9
+	cmpult	$9,	$1,	$17
+	addq	$17,	$10,	$10
+	addq	$20,	$10,	$20
+	cmpult	$20,	$10,	$18
+	addq	$19,	$18,	$19
+	mulq	$6,	$24,	$0
+	umulh	$6,	$24,	$2
+	addq	$9,	$0,	$9
+	cmpult	$9,	$0,	$1
+	addq	$1,	$2,	$2
+	addq	$20,	$2,	$20
+	cmpult	$20,	$2,	$17
+	addq	$19,	$17,	$19
+	mulq	$8,	$22,	$10
+	umulh	$8,	$22,	$18
+	addq	$9,	$10,	$9
+	cmpult	$9,	$10,	$0
+	addq	$0,	$18,	$18
+	addq	$20,	$18,	$20
+	cmpult	$20,	$18,	$1
+	addq	$19,	$1,	$19
+	mulq	$23,	$7,	$2
+	umulh	$23,	$7,	$17
+	addq	$9,	$2,	$9
+	cmpult	$9,	$2,	$10
+	addq	$10,	$17,	$17
+	addq	$20,	$17,	$20
+	cmpult	$20,	$17,	$0
+	addq	$19,	$0,	$19
+	mulq	$25,	$5,	$18
+	umulh	$25,	$5,	$1
+	addq	$9,	$18,	$9
+	cmpult	$9,	$18,	$2
+	addq	$2,	$1,	$1
+	addq	$20,	$1,	$20
+	cmpult	$20,	$1,	$10
+	addq	$19,	$10,	$19
+	mulq	$28,	$3,	$17
+	umulh	$28,	$3,	$0
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$18
+	addq	$18,	$0,	$0
+	addq	$20,	$0,	$20
+	cmpult	$20,	$0,	$2
+	addq	$19,	$2,	$19
+	stq	$9,	64($16)
+	bis	$31,	$31,	$9
+	mulq	$4,	$21,	$1
+	umulh	$4,	$21,	$10
+	addq	$20,	$1,	$20
+	cmpult	$20,	$1,	$17
+	addq	$17,	$10,	$10
+	addq	$19,	$10,	$19
+	cmpult	$19,	$10,	$18
+	addq	$9,	$18,	$9
+	mulq	$6,	$27,	$0
+	umulh	$6,	$27,	$2
+	addq	$20,	$0,	$20
+	cmpult	$20,	$0,	$3
+	addq	$3,	$2,	$2
+	addq	$19,	$2,	$19
+	cmpult	$19,	$2,	$1
+	addq	$9,	$1,	$9
+	mulq	$8,	$24,	$17
+	umulh	$8,	$24,	$10
+	addq	$20,	$17,	$20
+	cmpult	$20,	$17,	$18
+	addq	$18,	$10,	$10
+	addq	$19,	$10,	$19
+	cmpult	$19,	$10,	$4
+	addq	$9,	$4,	$9
+	mulq	$23,	$22,	$0
+	umulh	$23,	$22,	$3
+	addq	$20,	$0,	$20
+	cmpult	$20,	$0,	$2
+	addq	$2,	$3,	$3
+	addq	$19,	$3,	$19
+	cmpult	$19,	$3,	$1
+	addq	$9,	$1,	$9
+	mulq	$25,	$7,	$17
+	umulh	$25,	$7,	$18
+	addq	$20,	$17,	$20
+	cmpult	$20,	$17,	$10
+	addq	$10,	$18,	$18
+	addq	$19,	$18,	$19
+	cmpult	$19,	$18,	$4
+	addq	$9,	$4,	$9
+	mulq	$28,	$5,	$0
+	umulh	$28,	$5,	$2
+	addq	$20,	$0,	$20
+	cmpult	$20,	$0,	$3
+	addq	$3,	$2,	$2
+	addq	$19,	$2,	$19
+	cmpult	$19,	$2,	$1
+	addq	$9,	$1,	$9
+	stq	$20,	72($16)
+	bis	$31,	$31,	$20
+	mulq	$6,	$21,	$17
+	umulh	$6,	$21,	$10
+	addq	$19,	$17,	$19
+	cmpult	$19,	$17,	$18
+	addq	$18,	$10,	$10
+	addq	$9,	$10,	$9
+	cmpult	$9,	$10,	$4
+	addq	$20,	$4,	$20
+	mulq	$8,	$27,	$0
+	umulh	$8,	$27,	$3
+	addq	$19,	$0,	$19
+	cmpult	$19,	$0,	$2
+	addq	$2,	$3,	$3
+	addq	$9,	$3,	$9
+	cmpult	$9,	$3,	$1
+	addq	$20,	$1,	$20
+	mulq	$23,	$24,	$5
+	umulh	$23,	$24,	$17
+	addq	$19,	$5,	$19
+	cmpult	$19,	$5,	$18
+	addq	$18,	$17,	$17
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$10
+	addq	$20,	$10,	$20
+	mulq	$25,	$22,	$4
+	umulh	$25,	$22,	$6
+	addq	$19,	$4,	$19
+	cmpult	$19,	$4,	$0
+	addq	$0,	$6,	$6
+	addq	$9,	$6,	$9
+	cmpult	$9,	$6,	$2
+	addq	$20,	$2,	$20
+	mulq	$28,	$7,	$3
+	umulh	$28,	$7,	$1
+	addq	$19,	$3,	$19
+	cmpult	$19,	$3,	$5
+	addq	$5,	$1,	$1
+	addq	$9,	$1,	$9
+	cmpult	$9,	$1,	$18
+	addq	$20,	$18,	$20
+	stq	$19,	80($16)
+	bis	$31,	$31,	$19
+	mulq	$8,	$21,	$17
+	umulh	$8,	$21,	$10
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$4
+	addq	$4,	$10,	$10
+	addq	$20,	$10,	$20
+	cmpult	$20,	$10,	$0
+	addq	$19,	$0,	$19
+	mulq	$23,	$27,	$6
+	umulh	$23,	$27,	$2
+	addq	$9,	$6,	$9
+	cmpult	$9,	$6,	$3
+	addq	$3,	$2,	$2
+	addq	$20,	$2,	$20
+	cmpult	$20,	$2,	$5
+	addq	$19,	$5,	$19
+	mulq	$25,	$24,	$1
+	umulh	$25,	$24,	$18
+	addq	$9,	$1,	$9
+	cmpult	$9,	$1,	$7
+	addq	$7,	$18,	$18
+	addq	$20,	$18,	$20
+	cmpult	$20,	$18,	$17
+	addq	$19,	$17,	$19
+	mulq	$28,	$22,	$4
+	umulh	$28,	$22,	$10
+	addq	$9,	$4,	$9
+	cmpult	$9,	$4,	$0
+	addq	$0,	$10,	$10
+	addq	$20,	$10,	$20
+	cmpult	$20,	$10,	$8
+	addq	$19,	$8,	$19
+	stq	$9,	88($16)
+	bis	$31,	$31,	$9
+	mulq	$23,	$21,	$6
+	umulh	$23,	$21,	$3
+	addq	$20,	$6,	$20
+	cmpult	$20,	$6,	$2
+	addq	$2,	$3,	$3
+	addq	$19,	$3,	$19
+	cmpult	$19,	$3,	$5
+	addq	$9,	$5,	$9
+	mulq	$25,	$27,	$1
+	umulh	$25,	$27,	$7
+	addq	$20,	$1,	$20
+	cmpult	$20,	$1,	$18
+	addq	$18,	$7,	$7
+	addq	$19,	$7,	$19
+	cmpult	$19,	$7,	$17
+	addq	$9,	$17,	$9
+	mulq	$28,	$24,	$4
+	umulh	$28,	$24,	$0
+	addq	$20,	$4,	$20
+	cmpult	$20,	$4,	$10
+	addq	$10,	$0,	$0
+	addq	$19,	$0,	$19
+	cmpult	$19,	$0,	$8
+	addq	$9,	$8,	$9
+	stq	$20,	96($16)
+	bis	$31,	$31,	$20
+	mulq	$25,	$21,	$22
+	umulh	$25,	$21,	$6
+	addq	$19,	$22,	$19
+	cmpult	$19,	$22,	$2
+	addq	$2,	$6,	$6
+	addq	$9,	$6,	$9
+	cmpult	$9,	$6,	$3
+	addq	$20,	$3,	$20
+	mulq	$28,	$27,	$5
+	umulh	$28,	$27,	$23
+	addq	$19,	$5,	$19
+	cmpult	$19,	$5,	$1
+	addq	$1,	$23,	$23
+	addq	$9,	$23,	$9
+	cmpult	$9,	$23,	$18
+	addq	$20,	$18,	$20
+	stq	$19,	104($16)
+	bis	$31,	$31,	$19
+	mulq	$28,	$21,	$7
+	umulh	$28,	$21,	$17
+	addq	$9,	$7,	$9
+	cmpult	$9,	$7,	$4
+	addq	$4,	$17,	$17
+	addq	$20,	$17,	$20
+	cmpult	$20,	$17,	$10
+	addq	$19,	$10,	$19
+	stq	$9,	112($16)
+	stq	$20,	120($16)
+	ldq	$9,	0($30)
+	ldq	$10,	8($30)
+	addq	$30,	16,	$30
+	ret	$31,($26),1
+	.end bn_mul_comba8
+	.text
+	.align 3
+	.globl bn_sqr_comba4
+	.ent bn_sqr_comba4
+bn_sqr_comba4:
+bn_sqr_comba4..ng:
+	.frame $30,0,$26,0
+	.prologue 0
+
+	ldq	$0,	0($17)
+	ldq	$1,	8($17)
+	ldq	$2,	16($17)
+	ldq	$3,	24($17)
+	bis	$31,	$31,	$6
+	mulq	$0,	$0,	$4
+	umulh	$0,	$0,	$5
+	stq	$4,	0($16)
+	bis	$31,	$31,	$4
+	mulq	$0,	$1,	$7
+	umulh	$0,	$1,	$8
+	cmplt	$7,	$31,	$22
+	cmplt	$8,	$31,	$23
+	addq	$7,	$7,	$7
+	addq	$8,	$8,	$8
+	addq	$8,	$22,	$8
+	addq	$4,	$23,	$4
+	addq	$5,	$7,	$5
+	addq	$6,	$8,	$6
+	cmpult	$5,	$7,	$24
+	cmpult	$6,	$8,	$25
+	addq	$6,	$24,	$6
+	addq	$4,	$25,	$4
+	stq	$5,	8($16)
+	bis	$31,	$31,	$5
+	mulq	$1,	$1,	$27
+	umulh	$1,	$1,	$28
+	addq	$6,	$27,	$6
+	addq	$4,	$28,	$4
+	cmpult	$6,	$27,	$21
+	cmpult	$4,	$28,	$20
+	addq	$4,	$21,	$4
+	addq	$5,	$20,	$5
+	mulq	$2,	$0,	$19
+	umulh	$2,	$0,	$18
+	cmplt	$19,	$31,	$17
+	cmplt	$18,	$31,	$22
+	addq	$19,	$19,	$19
+	addq	$18,	$18,	$18
+	addq	$18,	$17,	$18
+	addq	$5,	$22,	$5
+	addq	$6,	$19,	$6
+	addq	$4,	$18,	$4
+	cmpult	$6,	$19,	$23
+	cmpult	$4,	$18,	$7
+	addq	$4,	$23,	$4
+	addq	$5,	$7,	$5
+	stq	$6,	16($16)
+	bis	$31,	$31,	$6
+	mulq	$3,	$0,	$8
+	umulh	$3,	$0,	$24
+	cmplt	$8,	$31,	$25
+	cmplt	$24,	$31,	$27
+	addq	$8,	$8,	$8
+	addq	$24,	$24,	$24
+	addq	$24,	$25,	$24
+	addq	$6,	$27,	$6
+	addq	$4,	$8,	$4
+	addq	$5,	$24,	$5
+	cmpult	$4,	$8,	$28
+	cmpult	$5,	$24,	$21
+	addq	$5,	$28,	$5
+	addq	$6,	$21,	$6
+	mulq	$2,	$1,	$20
+	umulh	$2,	$1,	$17
+	cmplt	$20,	$31,	$22
+	cmplt	$17,	$31,	$19
+	addq	$20,	$20,	$20
+	addq	$17,	$17,	$17
+	addq	$17,	$22,	$17
+	addq	$6,	$19,	$6
+	addq	$4,	$20,	$4
+	addq	$5,	$17,	$5
+	cmpult	$4,	$20,	$18
+	cmpult	$5,	$17,	$23
+	addq	$5,	$18,	$5
+	addq	$6,	$23,	$6
+	stq	$4,	24($16)
+	bis	$31,	$31,	$4
+	mulq	$2,	$2,	$7
+	umulh	$2,	$2,	$25
+	addq	$5,	$7,	$5
+	addq	$6,	$25,	$6
+	cmpult	$5,	$7,	$27
+	cmpult	$6,	$25,	$8
+	addq	$6,	$27,	$6
+	addq	$4,	$8,	$4
+	mulq	$3,	$1,	$24
+	umulh	$3,	$1,	$28
+	cmplt	$24,	$31,	$21
+	cmplt	$28,	$31,	$22
+	addq	$24,	$24,	$24
+	addq	$28,	$28,	$28
+	addq	$28,	$21,	$28
+	addq	$4,	$22,	$4
+	addq	$5,	$24,	$5
+	addq	$6,	$28,	$6
+	cmpult	$5,	$24,	$19
+	cmpult	$6,	$28,	$20
+	addq	$6,	$19,	$6
+	addq	$4,	$20,	$4
+	stq	$5,	32($16)
+	bis	$31,	$31,	$5
+	mulq	$3,	$2,	$17
+	umulh	$3,	$2,	$18
+	cmplt	$17,	$31,	$23
+	cmplt	$18,	$31,	$7
+	addq	$17,	$17,	$17
+	addq	$18,	$18,	$18
+	addq	$18,	$23,	$18
+	addq	$5,	$7,	$5
+	addq	$6,	$17,	$6
+	addq	$4,	$18,	$4
+	cmpult	$6,	$17,	$25
+	cmpult	$4,	$18,	$27
+	addq	$4,	$25,	$4
+	addq	$5,	$27,	$5
+	stq	$6,	40($16)
+	bis	$31,	$31,	$6
+	mulq	$3,	$3,	$8
+	umulh	$3,	$3,	$21
+	addq	$4,	$8,	$4
+	addq	$5,	$21,	$5
+	cmpult	$4,	$8,	$22
+	cmpult	$5,	$21,	$24
+	addq	$5,	$22,	$5
+	addq	$6,	$24,	$6
+	stq	$4,	48($16)
+	stq	$5,	56($16)
+	ret	$31,($26),1
+	.end bn_sqr_comba4
+	.text
+	.align 3
+	.globl bn_sqr_comba8
+	.ent bn_sqr_comba8
+bn_sqr_comba8:
+bn_sqr_comba8..ng:
+	.frame $30,0,$26,0
+	.prologue 0
+
+	ldq	$0,	0($17)
+	ldq	$1,	8($17)
+	ldq	$2,	16($17)
+	ldq	$3,	24($17)
+	ldq	$4,	32($17)
+	ldq	$5,	40($17)
+	ldq	$6,	48($17)
+	ldq	$7,	56($17)
+	bis	$31,	$31,	$23
+	mulq	$0,	$0,	$8
+	umulh	$0,	$0,	$22
+	stq	$8,	0($16)
+	bis	$31,	$31,	$8
+	mulq	$1,	$0,	$24
+	umulh	$1,	$0,	$25
+	cmplt	$24,	$31,	$27
+	cmplt	$25,	$31,	$28
+	addq	$24,	$24,	$24
+	addq	$25,	$25,	$25
+	addq	$25,	$27,	$25
+	addq	$8,	$28,	$8
+	addq	$22,	$24,	$22
+	addq	$23,	$25,	$23
+	cmpult	$22,	$24,	$21
+	cmpult	$23,	$25,	$20
+	addq	$23,	$21,	$23
+	addq	$8,	$20,	$8
+	stq	$22,	8($16)
+	bis	$31,	$31,	$22
+	mulq	$1,	$1,	$19
+	umulh	$1,	$1,	$18
+	addq	$23,	$19,	$23
+	addq	$8,	$18,	$8
+	cmpult	$23,	$19,	$17
+	cmpult	$8,	$18,	$27
+	addq	$8,	$17,	$8
+	addq	$22,	$27,	$22
+	mulq	$2,	$0,	$28
+	umulh	$2,	$0,	$24
+	cmplt	$28,	$31,	$25
+	cmplt	$24,	$31,	$21
+	addq	$28,	$28,	$28
+	addq	$24,	$24,	$24
+	addq	$24,	$25,	$24
+	addq	$22,	$21,	$22
+	addq	$23,	$28,	$23
+	addq	$8,	$24,	$8
+	cmpult	$23,	$28,	$20
+	cmpult	$8,	$24,	$19
+	addq	$8,	$20,	$8
+	addq	$22,	$19,	$22
+	stq	$23,	16($16)
+	bis	$31,	$31,	$23
+	mulq	$2,	$1,	$18
+	umulh	$2,	$1,	$17
+	cmplt	$18,	$31,	$27
+	cmplt	$17,	$31,	$25
+	addq	$18,	$18,	$18
+	addq	$17,	$17,	$17
+	addq	$17,	$27,	$17
+	addq	$23,	$25,	$23
+	addq	$8,	$18,	$8
+	addq	$22,	$17,	$22
+	cmpult	$8,	$18,	$21
+	cmpult	$22,	$17,	$28
+	addq	$22,	$21,	$22
+	addq	$23,	$28,	$23
+	mulq	$3,	$0,	$24
+	umulh	$3,	$0,	$20
+	cmplt	$24,	$31,	$19
+	cmplt	$20,	$31,	$27
+	addq	$24,	$24,	$24
+	addq	$20,	$20,	$20
+	addq	$20,	$19,	$20
+	addq	$23,	$27,	$23
+	addq	$8,	$24,	$8
+	addq	$22,	$20,	$22
+	cmpult	$8,	$24,	$25
+	cmpult	$22,	$20,	$18
+	addq	$22,	$25,	$22
+	addq	$23,	$18,	$23
+	stq	$8,	24($16)
+	bis	$31,	$31,	$8
+	mulq	$2,	$2,	$17
+	umulh	$2,	$2,	$21
+	addq	$22,	$17,	$22
+	addq	$23,	$21,	$23
+	cmpult	$22,	$17,	$28
+	cmpult	$23,	$21,	$19
+	addq	$23,	$28,	$23
+	addq	$8,	$19,	$8
+	mulq	$3,	$1,	$27
+	umulh	$3,	$1,	$24
+	cmplt	$27,	$31,	$20
+	cmplt	$24,	$31,	$25
+	addq	$27,	$27,	$27
+	addq	$24,	$24,	$24
+	addq	$24,	$20,	$24
+	addq	$8,	$25,	$8
+	addq	$22,	$27,	$22
+	addq	$23,	$24,	$23
+	cmpult	$22,	$27,	$18
+	cmpult	$23,	$24,	$17
+	addq	$23,	$18,	$23
+	addq	$8,	$17,	$8
+	mulq	$4,	$0,	$21
+	umulh	$4,	$0,	$28
+	cmplt	$21,	$31,	$19
+	cmplt	$28,	$31,	$20
+	addq	$21,	$21,	$21
+	addq	$28,	$28,	$28
+	addq	$28,	$19,	$28
+	addq	$8,	$20,	$8
+	addq	$22,	$21,	$22
+	addq	$23,	$28,	$23
+	cmpult	$22,	$21,	$25
+	cmpult	$23,	$28,	$27
+	addq	$23,	$25,	$23
+	addq	$8,	$27,	$8
+	stq	$22,	32($16)
+	bis	$31,	$31,	$22
+	mulq	$3,	$2,	$24
+	umulh	$3,	$2,	$18
+	cmplt	$24,	$31,	$17
+	cmplt	$18,	$31,	$19
+	addq	$24,	$24,	$24
+	addq	$18,	$18,	$18
+	addq	$18,	$17,	$18
+	addq	$22,	$19,	$22
+	addq	$23,	$24,	$23
+	addq	$8,	$18,	$8
+	cmpult	$23,	$24,	$20
+	cmpult	$8,	$18,	$21
+	addq	$8,	$20,	$8
+	addq	$22,	$21,	$22
+	mulq	$4,	$1,	$28
+	umulh	$4,	$1,	$25
+	cmplt	$28,	$31,	$27
+	cmplt	$25,	$31,	$17
+	addq	$28,	$28,	$28
+	addq	$25,	$25,	$25
+	addq	$25,	$27,	$25
+	addq	$22,	$17,	$22
+	addq	$23,	$28,	$23
+	addq	$8,	$25,	$8
+	cmpult	$23,	$28,	$19
+	cmpult	$8,	$25,	$24
+	addq	$8,	$19,	$8
+	addq	$22,	$24,	$22
+	mulq	$5,	$0,	$18
+	umulh	$5,	$0,	$20
+	cmplt	$18,	$31,	$21
+	cmplt	$20,	$31,	$27
+	addq	$18,	$18,	$18
+	addq	$20,	$20,	$20
+	addq	$20,	$21,	$20
+	addq	$22,	$27,	$22
+	addq	$23,	$18,	$23
+	addq	$8,	$20,	$8
+	cmpult	$23,	$18,	$17
+	cmpult	$8,	$20,	$28
+	addq	$8,	$17,	$8
+	addq	$22,	$28,	$22
+	stq	$23,	40($16)
+	bis	$31,	$31,	$23
+	mulq	$3,	$3,	$25
+	umulh	$3,	$3,	$19
+	addq	$8,	$25,	$8
+	addq	$22,	$19,	$22
+	cmpult	$8,	$25,	$24
+	cmpult	$22,	$19,	$21
+	addq	$22,	$24,	$22
+	addq	$23,	$21,	$23
+	mulq	$4,	$2,	$27
+	umulh	$4,	$2,	$18
+	cmplt	$27,	$31,	$20
+	cmplt	$18,	$31,	$17
+	addq	$27,	$27,	$27
+	addq	$18,	$18,	$18
+	addq	$18,	$20,	$18
+	addq	$23,	$17,	$23
+	addq	$8,	$27,	$8
+	addq	$22,	$18,	$22
+	cmpult	$8,	$27,	$28
+	cmpult	$22,	$18,	$25
+	addq	$22,	$28,	$22
+	addq	$23,	$25,	$23
+	mulq	$5,	$1,	$19
+	umulh	$5,	$1,	$24
+	cmplt	$19,	$31,	$21
+	cmplt	$24,	$31,	$20
+	addq	$19,	$19,	$19
+	addq	$24,	$24,	$24
+	addq	$24,	$21,	$24
+	addq	$23,	$20,	$23
+	addq	$8,	$19,	$8
+	addq	$22,	$24,	$22
+	cmpult	$8,	$19,	$17
+	cmpult	$22,	$24,	$27
+	addq	$22,	$17,	$22
+	addq	$23,	$27,	$23
+	mulq	$6,	$0,	$18
+	umulh	$6,	$0,	$28
+	cmplt	$18,	$31,	$25
+	cmplt	$28,	$31,	$21
+	addq	$18,	$18,	$18
+	addq	$28,	$28,	$28
+	addq	$28,	$25,	$28
+	addq	$23,	$21,	$23
+	addq	$8,	$18,	$8
+	addq	$22,	$28,	$22
+	cmpult	$8,	$18,	$20
+	cmpult	$22,	$28,	$19
+	addq	$22,	$20,	$22
+	addq	$23,	$19,	$23
+	stq	$8,	48($16)
+	bis	$31,	$31,	$8
+	mulq	$4,	$3,	$24
+	umulh	$4,	$3,	$17
+	cmplt	$24,	$31,	$27
+	cmplt	$17,	$31,	$25
+	addq	$24,	$24,	$24
+	addq	$17,	$17,	$17
+	addq	$17,	$27,	$17
+	addq	$8,	$25,	$8
+	addq	$22,	$24,	$22
+	addq	$23,	$17,	$23
+	cmpult	$22,	$24,	$21
+	cmpult	$23,	$17,	$18
+	addq	$23,	$21,	$23
+	addq	$8,	$18,	$8
+	mulq	$5,	$2,	$28
+	umulh	$5,	$2,	$20
+	cmplt	$28,	$31,	$19
+	cmplt	$20,	$31,	$27
+	addq	$28,	$28,	$28
+	addq	$20,	$20,	$20
+	addq	$20,	$19,	$20
+	addq	$8,	$27,	$8
+	addq	$22,	$28,	$22
+	addq	$23,	$20,	$23
+	cmpult	$22,	$28,	$25
+	cmpult	$23,	$20,	$24
+	addq	$23,	$25,	$23
+	addq	$8,	$24,	$8
+	mulq	$6,	$1,	$17
+	umulh	$6,	$1,	$21
+	cmplt	$17,	$31,	$18
+	cmplt	$21,	$31,	$19
+	addq	$17,	$17,	$17
+	addq	$21,	$21,	$21
+	addq	$21,	$18,	$21
+	addq	$8,	$19,	$8
+	addq	$22,	$17,	$22
+	addq	$23,	$21,	$23
+	cmpult	$22,	$17,	$27
+	cmpult	$23,	$21,	$28
+	addq	$23,	$27,	$23
+	addq	$8,	$28,	$8
+	mulq	$7,	$0,	$20
+	umulh	$7,	$0,	$25
+	cmplt	$20,	$31,	$24
+	cmplt	$25,	$31,	$18
+	addq	$20,	$20,	$20
+	addq	$25,	$25,	$25
+	addq	$25,	$24,	$25
+	addq	$8,	$18,	$8
+	addq	$22,	$20,	$22
+	addq	$23,	$25,	$23
+	cmpult	$22,	$20,	$19
+	cmpult	$23,	$25,	$17
+	addq	$23,	$19,	$23
+	addq	$8,	$17,	$8
+	stq	$22,	56($16)
+	bis	$31,	$31,	$22
+	mulq	$4,	$4,	$21
+	umulh	$4,	$4,	$27
+	addq	$23,	$21,	$23
+	addq	$8,	$27,	$8
+	cmpult	$23,	$21,	$28
+	cmpult	$8,	$27,	$24
+	addq	$8,	$28,	$8
+	addq	$22,	$24,	$22
+	mulq	$5,	$3,	$18
+	umulh	$5,	$3,	$20
+	cmplt	$18,	$31,	$25
+	cmplt	$20,	$31,	$19
+	addq	$18,	$18,	$18
+	addq	$20,	$20,	$20
+	addq	$20,	$25,	$20
+	addq	$22,	$19,	$22
+	addq	$23,	$18,	$23
+	addq	$8,	$20,	$8
+	cmpult	$23,	$18,	$17
+	cmpult	$8,	$20,	$21
+	addq	$8,	$17,	$8
+	addq	$22,	$21,	$22
+	mulq	$6,	$2,	$27
+	umulh	$6,	$2,	$28
+	cmplt	$27,	$31,	$24
+	cmplt	$28,	$31,	$25
+	addq	$27,	$27,	$27
+	addq	$28,	$28,	$28
+	addq	$28,	$24,	$28
+	addq	$22,	$25,	$22
+	addq	$23,	$27,	$23
+	addq	$8,	$28,	$8
+	cmpult	$23,	$27,	$19
+	cmpult	$8,	$28,	$18
+	addq	$8,	$19,	$8
+	addq	$22,	$18,	$22
+	mulq	$7,	$1,	$20
+	umulh	$7,	$1,	$17
+	cmplt	$20,	$31,	$21
+	cmplt	$17,	$31,	$24
+	addq	$20,	$20,	$20
+	addq	$17,	$17,	$17
+	addq	$17,	$21,	$17
+	addq	$22,	$24,	$22
+	addq	$23,	$20,	$23
+	addq	$8,	$17,	$8
+	cmpult	$23,	$20,	$25
+	cmpult	$8,	$17,	$27
+	addq	$8,	$25,	$8
+	addq	$22,	$27,	$22
+	stq	$23,	64($16)
+	bis	$31,	$31,	$23
+	mulq	$5,	$4,	$28
+	umulh	$5,	$4,	$19
+	cmplt	$28,	$31,	$18
+	cmplt	$19,	$31,	$21
+	addq	$28,	$28,	$28
+	addq	$19,	$19,	$19
+	addq	$19,	$18,	$19
+	addq	$23,	$21,	$23
+	addq	$8,	$28,	$8
+	addq	$22,	$19,	$22
+	cmpult	$8,	$28,	$24
+	cmpult	$22,	$19,	$20
+	addq	$22,	$24,	$22
+	addq	$23,	$20,	$23
+	mulq	$6,	$3,	$17
+	umulh	$6,	$3,	$25
+	cmplt	$17,	$31,	$27
+	cmplt	$25,	$31,	$18
+	addq	$17,	$17,	$17
+	addq	$25,	$25,	$25
+	addq	$25,	$27,	$25
+	addq	$23,	$18,	$23
+	addq	$8,	$17,	$8
+	addq	$22,	$25,	$22
+	cmpult	$8,	$17,	$21
+	cmpult	$22,	$25,	$28
+	addq	$22,	$21,	$22
+	addq	$23,	$28,	$23
+	mulq	$7,	$2,	$19
+	umulh	$7,	$2,	$24
+	cmplt	$19,	$31,	$20
+	cmplt	$24,	$31,	$27
+	addq	$19,	$19,	$19
+	addq	$24,	$24,	$24
+	addq	$24,	$20,	$24
+	addq	$23,	$27,	$23
+	addq	$8,	$19,	$8
+	addq	$22,	$24,	$22
+	cmpult	$8,	$19,	$18
+	cmpult	$22,	$24,	$17
+	addq	$22,	$18,	$22
+	addq	$23,	$17,	$23
+	stq	$8,	72($16)
+	bis	$31,	$31,	$8
+	mulq	$5,	$5,	$25
+	umulh	$5,	$5,	$21
+	addq	$22,	$25,	$22
+	addq	$23,	$21,	$23
+	cmpult	$22,	$25,	$28
+	cmpult	$23,	$21,	$20
+	addq	$23,	$28,	$23
+	addq	$8,	$20,	$8
+	mulq	$6,	$4,	$27
+	umulh	$6,	$4,	$19
+	cmplt	$27,	$31,	$24
+	cmplt	$19,	$31,	$18
+	addq	$27,	$27,	$27
+	addq	$19,	$19,	$19
+	addq	$19,	$24,	$19
+	addq	$8,	$18,	$8
+	addq	$22,	$27,	$22
+	addq	$23,	$19,	$23
+	cmpult	$22,	$27,	$17
+	cmpult	$23,	$19,	$25
+	addq	$23,	$17,	$23
+	addq	$8,	$25,	$8
+	mulq	$7,	$3,	$21
+	umulh	$7,	$3,	$28
+	cmplt	$21,	$31,	$20
+	cmplt	$28,	$31,	$24
+	addq	$21,	$21,	$21
+	addq	$28,	$28,	$28
+	addq	$28,	$20,	$28
+	addq	$8,	$24,	$8
+	addq	$22,	$21,	$22
+	addq	$23,	$28,	$23
+	cmpult	$22,	$21,	$18
+	cmpult	$23,	$28,	$27
+	addq	$23,	$18,	$23
+	addq	$8,	$27,	$8
+	stq	$22,	80($16)
+	bis	$31,	$31,	$22
+	mulq	$6,	$5,	$19
+	umulh	$6,	$5,	$17
+	cmplt	$19,	$31,	$25
+	cmplt	$17,	$31,	$20
+	addq	$19,	$19,	$19
+	addq	$17,	$17,	$17
+	addq	$17,	$25,	$17
+	addq	$22,	$20,	$22
+	addq	$23,	$19,	$23
+	addq	$8,	$17,	$8
+	cmpult	$23,	$19,	$24
+	cmpult	$8,	$17,	$21
+	addq	$8,	$24,	$8
+	addq	$22,	$21,	$22
+	mulq	$7,	$4,	$28
+	umulh	$7,	$4,	$18
+	cmplt	$28,	$31,	$27
+	cmplt	$18,	$31,	$25
+	addq	$28,	$28,	$28
+	addq	$18,	$18,	$18
+	addq	$18,	$27,	$18
+	addq	$22,	$25,	$22
+	addq	$23,	$28,	$23
+	addq	$8,	$18,	$8
+	cmpult	$23,	$28,	$20
+	cmpult	$8,	$18,	$19
+	addq	$8,	$20,	$8
+	addq	$22,	$19,	$22
+	stq	$23,	88($16)
+	bis	$31,	$31,	$23
+	mulq	$6,	$6,	$17
+	umulh	$6,	$6,	$24
+	addq	$8,	$17,	$8
+	addq	$22,	$24,	$22
+	cmpult	$8,	$17,	$21
+	cmpult	$22,	$24,	$27
+	addq	$22,	$21,	$22
+	addq	$23,	$27,	$23
+	mulq	$7,	$5,	$25
+	umulh	$7,	$5,	$28
+	cmplt	$25,	$31,	$18
+	cmplt	$28,	$31,	$20
+	addq	$25,	$25,	$25
+	addq	$28,	$28,	$28
+	addq	$28,	$18,	$28
+	addq	$23,	$20,	$23
+	addq	$8,	$25,	$8
+	addq	$22,	$28,	$22
+	cmpult	$8,	$25,	$19
+	cmpult	$22,	$28,	$17
+	addq	$22,	$19,	$22
+	addq	$23,	$17,	$23
+	stq	$8,	96($16)
+	bis	$31,	$31,	$8
+	mulq	$7,	$6,	$24
+	umulh	$7,	$6,	$21
+	cmplt	$24,	$31,	$27
+	cmplt	$21,	$31,	$18
+	addq	$24,	$24,	$24
+	addq	$21,	$21,	$21
+	addq	$21,	$27,	$21
+	addq	$8,	$18,	$8
+	addq	$22,	$24,	$22
+	addq	$23,	$21,	$23
+	cmpult	$22,	$24,	$20
+	cmpult	$23,	$21,	$25
+	addq	$23,	$20,	$23
+	addq	$8,	$25,	$8
+	stq	$22,	104($16)
+	bis	$31,	$31,	$22
+	mulq	$7,	$7,	$28
+	umulh	$7,	$7,	$19
+	addq	$23,	$28,	$23
+	addq	$8,	$19,	$8
+	cmpult	$23,	$28,	$17
+	cmpult	$8,	$19,	$27
+	addq	$8,	$17,	$8
+	addq	$22,	$27,	$22
+	stq	$23,	112($16)
+	stq	$8,	120($16)
+	ret	$31,($26),1
+	.end bn_sqr_comba8
diff --git a/crypto/bn/asm/alpha.s.works b/crypto/bn/asm/alpha.s.works
new file mode 100644
index 0000000..ee6c587
--- /dev/null
+++ b/crypto/bn/asm/alpha.s.works
@@ -0,0 +1,533 @@
+
+ # DEC Alpha assember
+ # The bn_div64 is actually gcc output but the other parts are hand done.
+ # Thanks to tzeruch@ceddec.com for sending me the gcc output for
+ # bn_div64.
+ # I've gone back and re-done most of routines.
+ # The key thing to remeber for the 164 CPU is that while a
+ # multiply operation takes 8 cycles, another one can only be issued
+ # after 4 cycles have elapsed.  I've done modification to help
+ # improve this.  Also, normally, a ld instruction will not be available
+ # for about 3 cycles.
+	.file	1 "bn_asm.c"
+	.set noat
+gcc2_compiled.:
+__gnu_compiled_c:
+	.text
+	.align 3
+	.globl bn_mul_add_words
+	.ent bn_mul_add_words
+bn_mul_add_words:
+bn_mul_add_words..ng:
+	.frame $30,0,$26,0
+	.prologue 0
+	.align 5
+	subq	$18,4,$18
+	bis	$31,$31,$0
+	blt	$18,$43		# if we are -1, -2, -3 or -4 goto tail code
+	ldq	$20,0($17)	# 1 1
+	ldq	$1,0($16)	# 1 1
+	.align 3
+$42:
+	mulq	$20,$19,$5	# 1 2 1	######
+	ldq	$21,8($17)	# 2 1
+	ldq	$2,8($16)	# 2 1
+	umulh	$20,$19,$20	# 1 2	######
+	ldq	$27,16($17)	# 3 1
+	ldq	$3,16($16)	# 3 1
+	mulq	$21,$19,$6	# 2 2 1	######
+	 ldq	$28,24($17)	# 4 1
+	addq	$1,$5,$1	# 1 2 2
+	 ldq	$4,24($16)	# 4 1
+	umulh	$21,$19,$21	# 2 2	######
+	 cmpult	$1,$5,$22	# 1 2 3 1
+	addq	$20,$22,$20	# 1 3 1
+	 addq	$1,$0,$1	# 1 2 3 1
+	mulq	$27,$19,$7	# 3 2 1	######
+	 cmpult	$1,$0,$0	# 1 2 3 2
+	addq	$2,$6,$2	# 2 2 2
+	 addq	$20,$0,$0	# 1 3 2 
+	cmpult	$2,$6,$23	# 2 2 3 1
+	 addq	$21,$23,$21	# 2 3 1
+	umulh	$27,$19,$27	# 3 2	######
+	 addq	$2,$0,$2	# 2 2 3 1
+	cmpult	$2,$0,$0	# 2 2 3 2
+	 subq	$18,4,$18
+	mulq	$28,$19,$8	# 4 2 1	######
+	 addq	$21,$0,$0	# 2 3 2 
+	addq	$3,$7,$3	# 3 2 2
+	 addq	$16,32,$16
+	cmpult	$3,$7,$24	# 3 2 3 1
+	 stq	$1,-32($16)	# 1 2 4
+	umulh	$28,$19,$28	# 4 2	######
+	 addq	$27,$24,$27	# 3 3 1
+	addq	$3,$0,$3	# 3 2 3 1
+	 stq	$2,-24($16)	# 2 2 4
+	cmpult	$3,$0,$0	# 3 2 3 2
+	 stq	$3,-16($16)	# 3 2 4
+	addq	$4,$8,$4	# 4 2 2
+	 addq	$27,$0,$0	# 3 3 2 
+	cmpult	$4,$8,$25	# 4 2 3 1
+	 addq	$17,32,$17
+	addq	$28,$25,$28	# 4 3 1
+	 addq	$4,$0,$4	# 4 2 3 1
+	cmpult	$4,$0,$0	# 4 2 3 2
+	 stq	$4,-8($16)	# 4 2 4
+	addq	$28,$0,$0	# 4 3 2 
+	 blt	$18,$43
+
+	ldq	$20,0($17)	# 1 1
+	ldq	$1,0($16)	# 1 1
+
+	br	$42
+
+	.align 4
+$45:
+	ldq	$20,0($17)	# 4 1
+	ldq	$1,0($16)	# 4 1
+	mulq	$20,$19,$5	# 4 2 1
+	subq	$18,1,$18
+	addq	$16,8,$16
+	addq	$17,8,$17
+	umulh	$20,$19,$20	# 4 2
+	addq	$1,$5,$1	# 4 2 2
+	cmpult	$1,$5,$22	# 4 2 3 1
+	addq	$20,$22,$20	# 4 3 1
+	addq	$1,$0,$1	# 4 2 3 1
+	cmpult	$1,$0,$0	# 4 2 3 2
+	addq	$20,$0,$0	# 4 3 2 
+	stq	$1,-8($16)	# 4 2 4
+	bgt	$18,$45
+	ret	$31,($26),1	# else exit
+
+	.align 4
+$43:
+	addq	$18,4,$18
+	bgt	$18,$45		# goto tail code
+	ret	$31,($26),1	# else exit
+
+	.end bn_mul_add_words
+	.align 3
+	.globl bn_mul_words
+	.ent bn_mul_words
+bn_mul_words:
+bn_mul_words..ng:
+	.frame $30,0,$26,0
+	.prologue 0
+	.align 5
+	subq	$18,4,$18
+	bis	$31,$31,$0
+	blt	$18,$143	# if we are -1, -2, -3 or -4 goto tail code
+	ldq	$20,0($17)	# 1 1
+	.align 3
+$142:
+
+	mulq	$20,$19,$5	# 1 2 1	#####
+	 ldq	$21,8($17)	# 2 1
+	 ldq	$27,16($17)	# 3 1
+	umulh	$20,$19,$20	# 1 2	#####
+	 ldq	$28,24($17)	# 4 1
+	mulq	$21,$19,$6	# 2 2 1	#####
+	 addq	$5,$0,$5	# 1 2 3 1
+	subq	$18,4,$18
+	 cmpult	$5,$0,$0	# 1 2 3 2
+	umulh	$21,$19,$21	# 2 2	#####
+	 addq	$20,$0,$0	# 1 3 2 
+	addq	$17,32,$17
+	 addq	$6,$0,$6	# 2 2 3 1
+	mulq	$27,$19,$7	# 3 2 1	#####
+	 cmpult	$6,$0,$0	# 2 2 3 2
+	addq	$21,$0,$0	# 2 3 2 
+	 addq	$16,32,$16
+	umulh	$27,$19,$27	# 3 2	#####
+	 stq	$5,-32($16)	# 1 2 4
+	mulq	$28,$19,$8	# 4 2 1	#####
+	 addq	$7,$0,$7	# 3 2 3 1
+	stq	$6,-24($16)	# 2 2 4
+	 cmpult	$7,$0,$0	# 3 2 3 2
+	umulh	$28,$19,$28	# 4 2	#####
+	 addq	$27,$0,$0	# 3 3 2 
+	stq	$7,-16($16)	# 3 2 4
+	 addq	$8,$0,$8	# 4 2 3 1
+	cmpult	$8,$0,$0	# 4 2 3 2
+
+	addq	$28,$0,$0	# 4 3 2 
+
+	stq	$8,-8($16)	# 4 2 4
+
+	blt	$18,$143
+
+	ldq	$20,0($17)	# 1 1
+
+	br	$142
+
+	.align 4
+$145:
+	ldq	$20,0($17)	# 4 1
+	mulq	$20,$19,$5	# 4 2 1
+	subq	$18,1,$18
+	umulh	$20,$19,$20	# 4 2
+	addq	$5,$0,$5	# 4 2 3 1
+	 addq	$16,8,$16
+	cmpult	$5,$0,$0	# 4 2 3 2
+	 addq	$17,8,$17
+	addq	$20,$0,$0	# 4 3 2 
+	stq	$5,-8($16)	# 4 2 4
+
+	bgt	$18,$145
+	ret	$31,($26),1	# else exit
+
+	.align 4
+$143:
+	addq	$18,4,$18
+	bgt	$18,$145	# goto tail code
+	ret	$31,($26),1	# else exit
+
+	.end bn_mul_words
+	.align 3
+	.globl bn_sqr_words
+	.ent bn_sqr_words
+bn_sqr_words:
+bn_sqr_words..ng:
+	.frame $30,0,$26,0
+	.prologue 0
+
+	subq	$18,4,$18
+	blt	$18,$543	# if we are -1, -2, -3 or -4 goto tail code
+	ldq	$20,0($17)	# 1 1
+	.align 3
+$542:
+	mulq	$20,$20,$5		######
+	 ldq	$21,8($17)	# 1 1
+	subq	$18,4
+ 	umulh	$20,$20,$1		######
+	ldq	$27,16($17)	# 1 1
+	mulq	$21,$21,$6		######
+	ldq	$28,24($17)	# 1 1
+	stq	$5,0($16)	# r[0]
+ 	umulh	$21,$21,$2		######
+	stq	$1,8($16)	# r[1]
+	mulq	$27,$27,$7		######
+	stq	$6,16($16)	# r[0]
+ 	umulh	$27,$27,$3		######
+	stq	$2,24($16)	# r[1]
+	mulq	$28,$28,$8		######
+	stq	$7,32($16)	# r[0]
+ 	umulh	$28,$28,$4		######
+	stq	$3,40($16)	# r[1]
+
+ 	addq	$16,64,$16
+ 	addq	$17,32,$17
+	stq	$8,-16($16)	# r[0]
+	stq	$4,-8($16)	# r[1]
+
+	blt	$18,$543
+	ldq	$20,0($17)	# 1 1
+ 	br 	$542
+
+$442:
+	ldq	$20,0($17)   # a[0]
+	mulq	$20,$20,$5  # a[0]*w low part       r2
+	addq	$16,16,$16
+	addq	$17,8,$17
+	subq	$18,1,$18
+        umulh	$20,$20,$1  # a[0]*w high part       r3
+	stq	$5,-16($16)   # r[0]
+        stq	$1,-8($16)   # r[1]
+
+	bgt	$18,$442
+	ret	$31,($26),1	# else exit
+
+	.align 4
+$543:
+	addq	$18,4,$18
+	bgt	$18,$442	# goto tail code
+	ret	$31,($26),1	# else exit
+	.end bn_sqr_words
+
+	.align 3
+	.globl bn_add_words
+	.ent bn_add_words
+bn_add_words:
+bn_add_words..ng:
+	.frame $30,0,$26,0
+	.prologue 0
+
+	subq	$19,4,$19
+	bis	$31,$31,$0	# carry = 0
+	blt	$19,$900
+	ldq	$5,0($17)	# a[0]
+	ldq	$1,0($18)	# b[1]
+	.align 3
+$901:
+	addq	$1,$5,$1	# r=a+b;
+	 ldq	$6,8($17)	# a[1]
+	cmpult	$1,$5,$22	# did we overflow?
+	 ldq	$2,8($18)	# b[1]
+	addq	$1,$0,$1	# c+= overflow
+	 ldq	$7,16($17)	# a[2]
+	cmpult	$1,$0,$0	# overflow?
+	 ldq	$3,16($18)	# b[2]
+	addq	$0,$22,$0
+	 ldq	$8,24($17)	# a[3]
+	addq	$2,$6,$2	# r=a+b;
+	 ldq	$4,24($18)	# b[3]
+	cmpult	$2,$6,$23	# did we overflow?
+	 addq	$3,$7,$3	# r=a+b;
+	addq	$2,$0,$2	# c+= overflow
+	 cmpult	$3,$7,$24	# did we overflow?
+	cmpult	$2,$0,$0	# overflow?
+	 addq	$4,$8,$4	# r=a+b;
+	addq	$0,$23,$0
+	 cmpult	$4,$8,$25	# did we overflow?
+	addq	$3,$0,$3	# c+= overflow
+	 stq	$1,0($16)	# r[0]=c
+	cmpult	$3,$0,$0	# overflow?
+	 stq	$2,8($16)	# r[1]=c
+	addq	$0,$24,$0
+	 stq	$3,16($16)	# r[2]=c
+	addq	$4,$0,$4	# c+= overflow
+	 subq	$19,4,$19	# loop--
+	cmpult	$4,$0,$0	# overflow?
+	 addq	$17,32,$17	# a++
+	addq	$0,$25,$0
+	 stq	$4,24($16)	# r[3]=c
+	addq	$18,32,$18	# b++
+	 addq	$16,32,$16	# r++
+
+	blt	$19,$900
+	 ldq	$5,0($17)	# a[0]
+	ldq	$1,0($18)	# b[1]
+	 br	$901
+	.align 4
+$945:
+	ldq	$5,0($17)	# a[0]
+	 ldq	$1,0($18)	# b[1]
+	addq	$1,$5,$1	# r=a+b;
+	 subq	$19,1,$19	# loop--
+	addq	$1,$0,$1	# c+= overflow
+	 addq	$17,8,$17	# a++
+	cmpult	$1,$5,$22	# did we overflow?
+	 cmpult	$1,$0,$0	# overflow?
+	addq	$18,8,$18	# b++
+	 stq	$1,0($16)	# r[0]=c
+	addq	$0,$22,$0
+	 addq	$16,8,$16	# r++
+
+	bgt	$19,$945
+	ret	$31,($26),1	# else exit
+
+$900:
+	addq	$19,4,$19
+	bgt	$19,$945	# goto tail code
+	ret	$31,($26),1	# else exit
+	.end bn_add_words
+
+ #
+ # What follows was taken directly from the C compiler with a few
+ # hacks to redo the lables.
+ #
+.text
+	.align 3
+	.globl bn_div64
+	.ent bn_div64
+bn_div64:
+	ldgp $29,0($27)
+bn_div64..ng:
+	lda $30,-48($30)
+	.frame $30,48,$26,0
+	stq $26,0($30)
+	stq $9,8($30)
+	stq $10,16($30)
+	stq $11,24($30)
+	stq $12,32($30)
+	stq $13,40($30)
+	.mask 0x4003e00,-48
+	.prologue 1
+	bis $16,$16,$9
+	bis $17,$17,$10
+	bis $18,$18,$11
+	bis $31,$31,$13
+	bis $31,2,$12
+	bne $11,$119
+	lda $0,-1
+	br $31,$136
+	.align 4
+$119:
+	bis $11,$11,$16
+	jsr $26,BN_num_bits_word
+	ldgp $29,0($26)
+	subq $0,64,$1
+	beq $1,$120
+	bis $31,1,$1
+	sll $1,$0,$1
+	cmpule $9,$1,$1
+	bne $1,$120
+ #	lda $16,_IO_stderr_
+ #	lda $17,$C32
+ #	bis $0,$0,$18
+ #	jsr $26,fprintf
+ #	ldgp $29,0($26)
+	jsr $26,abort
+	ldgp $29,0($26)
+	.align 4
+$120:
+	bis $31,64,$3
+	cmpult $9,$11,$2
+	subq $3,$0,$1
+	addl $1,$31,$0
+	subq $9,$11,$1
+	cmoveq $2,$1,$9
+	beq $0,$122
+	zapnot $0,15,$2
+	subq $3,$0,$1
+	sll $11,$2,$11
+	sll $9,$2,$3
+	srl $10,$1,$1
+	sll $10,$2,$10
+	bis $3,$1,$9
+$122:
+	srl $11,32,$5
+	zapnot $11,15,$6
+	lda $7,-1
+	.align 5
+$123:
+	srl $9,32,$1
+	subq $1,$5,$1
+	bne $1,$126
+	zapnot $7,15,$27
+	br $31,$127
+	.align 4
+$126:
+	bis $9,$9,$24
+	bis $5,$5,$25
+	divqu $24,$25,$27
+$127:
+	srl $10,32,$4
+	.align 5
+$128:
+	mulq $27,$5,$1
+	subq $9,$1,$3
+	zapnot $3,240,$1
+	bne $1,$129
+	mulq $6,$27,$2
+	sll $3,32,$1
+	addq $1,$4,$1
+	cmpule $2,$1,$2
+	bne $2,$129
+	subq $27,1,$27
+	br $31,$128
+	.align 4
+$129:
+	mulq $27,$6,$1
+	mulq $27,$5,$4
+	srl $1,32,$3
+	sll $1,32,$1
+	addq $4,$3,$4
+	cmpult $10,$1,$2
+	subq $10,$1,$10
+	addq $2,$4,$2
+	cmpult $9,$2,$1
+	bis $2,$2,$4
+	beq $1,$134
+	addq $9,$11,$9
+	subq $27,1,$27
+$134:
+	subl $12,1,$12
+	subq $9,$4,$9
+	beq $12,$124
+	sll $27,32,$13
+	sll $9,32,$2
+	srl $10,32,$1
+	sll $10,32,$10
+	bis $2,$1,$9
+	br $31,$123
+	.align 4
+$124:
+	bis $13,$27,$0
+$136:
+	ldq $26,0($30)
+	ldq $9,8($30)
+	ldq $10,16($30)
+	ldq $11,24($30)
+	ldq $12,32($30)
+	ldq $13,40($30)
+	addq $30,48,$30
+	ret $31,($26),1
+	.end bn_div64
+
+	.set noat
+	.text
+	.align 3
+	.globl bn_sub_words
+	.ent bn_sub_words
+bn_sub_words:
+bn_sub_words..ng:
+	.frame $30,0,$26,0
+	.prologue 0
+
+	subq	$19,	4,	$19
+	bis	$31,	$31,	$0
+	blt	$19,	$100
+	ldq	$1,	0($17)
+	ldq	$2,	0($18)
+$101:
+	ldq	$3,	8($17)
+	cmpult	$1,	$2,	$4
+	ldq	$5,	8($18)
+	subq	$1,	$2,	$1
+	ldq	$6,	16($17)
+	cmpult	$1,	$0,	$2
+	ldq	$7,	16($18)
+	subq	$1,	$0,	$23
+	ldq	$8,	24($17)
+	addq	$2,	$4,	$0
+	cmpult	$3,	$5,	$24
+	subq	$3,	$5,	$3
+	ldq	$22,	24($18)
+	cmpult	$3,	$0,	$5
+	subq	$3,	$0,	$25
+	addq	$5,	$24,	$0
+	cmpult	$6,	$7,	$27
+	subq	$6,	$7,	$6
+	stq	$23,	0($16)
+	cmpult	$6,	$0,	$7
+	subq	$6,	$0,	$28
+	addq	$7,	$27,	$0
+	cmpult	$8,	$22,	$21
+	subq	$8,	$22,	$8
+	stq	$25,	8($16)
+	cmpult	$8,	$0,	$22
+	subq	$8,	$0,	$20
+	addq	$22,	$21,	$0
+	stq	$28,	16($16)
+	subq	$19,	4,	$19
+	stq	$20,	24($16)
+	addq	$17,	32,	$17
+	addq	$18,	32,	$18
+	addq	$16,	32,	$16
+	blt	$19,	$100
+	ldq	$1,	0($17)
+	ldq	$2,	0($18)
+	br	$101
+$102:
+	ldq	$1,	0($17)
+	ldq	$2,	0($18)
+	cmpult	$1,	$2,	$27
+	subq	$1,	$2,	$1
+	cmpult	$1,	$0,	$2
+	subq	$1,	$0,	$1
+	stq	$1,	0($16)
+	addq	$2,	$27,	$0
+	addq	$17,	8,	$17
+	addq	$18,	8,	$18
+	addq	$16,	8,	$16
+	subq	$19,	1,	$19
+	bgt	$19,	$102
+	ret	$31,($26),1
+$100:
+	addq	$19,	4,	$19
+	bgt	$19,	$102
+$103:
+	ret	$31,($26),1
+	.end bn_sub_words
diff --git a/crypto/bn/asm/alpha.works/add.pl b/crypto/bn/asm/alpha.works/add.pl
new file mode 100644
index 0000000..4dc76e6
--- /dev/null
+++ b/crypto/bn/asm/alpha.works/add.pl
@@ -0,0 +1,119 @@
+#!/usr/local/bin/perl
+# alpha assember 
+
+sub bn_add_words
+	{
+	local($name)=@_;
+	local($cc,$a,$b,$r);
+
+	&init_pool(4);
+	($cc)=GR("r0");
+
+	$rp=&wparam(0);
+	$ap=&wparam(1);
+	$bp=&wparam(2);
+	$count=&wparam(3);
+
+	&function_begin($name,"");
+
+	&comment("");
+	&sub($count,4,$count);
+	&mov("zero",$cc);
+	&br(&label("finish"));
+	&blt($count,&label("finish"));
+
+	($a0,$b0)=&NR(2);
+	&ld($a0,&QWPw(0,$ap));
+	&ld($b0,&QWPw(0,$bp));
+
+##########################################################
+	&set_label("loop");
+
+	($a1)=&NR(1); &ld($a1,&QWPw(1,$ap));
+	($b1)=&NR(1); &ld($b1,&QWPw(1,$bp));
+	($a2)=&NR(1); &ld($a2,&QWPw(2,$ap));
+	($b2)=&NR(1); &ld($b2,&QWPw(2,$bp));
+	($a3)=&NR(1); &ld($a3,&QWPw(3,$ap));
+	($b3)=&NR(1); &ld($b3,&QWPw(3,$bp));
+
+	($o0,$t0)=&NR(2);
+	&add($a0,$b0,$o0); 
+	&cmpult($o0,$b0,$t0);
+	&add($o0,$cc,$o0);
+	&cmpult($o0,$cc,$cc);
+	&add($cc,$t0,$cc);	&FR($t0);
+
+	($t1,$o1)=&NR(2);
+
+	&add($a1,$b1,$o1);	&FR($a1);
+	&cmpult($o1,$b1,$t1);	&FR($b1);
+	&add($o1,$cc,$o1);
+	&cmpult($o1,$cc,$cc);
+	&add($cc,$t1,$cc);	&FR($t1);
+
+	($t2,$o2)=&NR(2);
+
+	&add($a2,$b2,$o2);	&FR($a2);
+	&cmpult($o2,$b2,$t2);	&FR($b2);
+	&add($o2,$cc,$o2);
+	&cmpult($o2,$cc,$cc);
+	&add($cc,$t2,$cc);	&FR($t2);
+
+	($t3,$o3)=&NR(2);
+
+	&add($a3,$b3,$o3);	&FR($a3);
+	&cmpult($o3,$b3,$t3);	&FR($b3);
+	&add($o3,$cc,$o3);
+	&cmpult($o3,$cc,$cc);
+	&add($cc,$t3,$cc);	&FR($t3);
+
+	&st($o0,&QWPw(0,$rp)); &FR($o0);
+	&st($o1,&QWPw(0,$rp)); &FR($o1);
+	&st($o2,&QWPw(0,$rp)); &FR($o2);
+	&st($o3,&QWPw(0,$rp)); &FR($o3);
+
+	&sub($count,4,$count);	# count-=4
+	&add($ap,4*$QWS,$ap);	# count+=4
+	&add($bp,4*$QWS,$bp);	# count+=4
+	&add($rp,4*$QWS,$rp);	# count+=4
+
+	&blt($count,&label("finish"));
+	&ld($a0,&QWPw(0,$ap));
+	 &ld($b0,&QWPw(0,$bp));
+	&br(&label("loop"));
+##################################################
+	# Do the last 0..3 words
+
+	($t0,$o0)=&NR(2);
+	&set_label("last_loop");
+
+	&ld($a0,&QWPw(0,$ap));	# get a
+	&ld($b0,&QWPw(0,$bp));	# get b
+
+	&add($a0,$b0,$o0); 
+	&cmpult($o0,$b0,$t0);	# will we borrow?
+	&add($o0,$cc,$o0);	# will we borrow?
+	&cmpult($o0,$cc,$cc);	# will we borrow?
+	&add($cc,$t0,$cc);	# add the borrows
+	&st($o0,&QWPw(0,$rp));	# save
+
+	&add($ap,$QWS,$ap);
+	&add($bp,$QWS,$bp);
+	&add($rp,$QWS,$rp);
+	&sub($count,1,$count);
+	&bgt($count,&label("last_loop"));
+	&function_end_A($name);
+
+######################################################
+	&set_label("finish");
+	&add($count,4,$count);
+	&bgt($count,&label("last_loop"));
+
+	&FR($o0,$t0,$a0,$b0);
+	&set_label("end");
+	&function_end($name);
+
+	&fin_pool;
+	}
+
+1;
diff --git a/crypto/bn/asm/alpha.works/div.pl b/crypto/bn/asm/alpha.works/div.pl
new file mode 100644
index 0000000..7ec1443
--- /dev/null
+++ b/crypto/bn/asm/alpha.works/div.pl
@@ -0,0 +1,144 @@
+#!/usr/local/bin/perl
+
+sub bn_div64
+	{
+	local($data)=<<'EOF';
+ #
+ # What follows was taken directly from the C compiler with a few
+ # hacks to redo the lables.
+ #
+.text
+        .set noreorder
+	.set volatile
+	.align 3
+	.globl bn_div64
+	.ent bn_div64
+bn_div64:
+	ldgp $29,0($27)
+bn_div64..ng:
+	lda $30,-48($30)
+	.frame $30,48,$26,0
+	stq $26,0($30)
+	stq $9,8($30)
+	stq $10,16($30)
+	stq $11,24($30)
+	stq $12,32($30)
+	stq $13,40($30)
+	.mask 0x4003e00,-48
+	.prologue 1
+	bis $16,$16,$9
+	bis $17,$17,$10
+	bis $18,$18,$11
+	bis $31,$31,$13
+	bis $31,2,$12
+	bne $11,$9119
+	lda $0,-1
+	br $31,$9136
+	.align 4
+$9119:
+	bis $11,$11,$16
+	jsr $26,BN_num_bits_word
+	ldgp $29,0($26)
+	subq $0,64,$1
+	beq $1,$9120
+	bis $31,1,$1
+	sll $1,$0,$1
+	cmpule $9,$1,$1
+	bne $1,$9120
+ #	lda $16,_IO_stderr_
+ #	lda $17,$C32
+ #	bis $0,$0,$18
+ #	jsr $26,fprintf
+ #	ldgp $29,0($26)
+	jsr $26,abort
+	ldgp $29,0($26)
+	.align 4
+$9120:
+	bis $31,64,$3
+	cmpult $9,$11,$2
+	subq $3,$0,$1
+	addl $1,$31,$0
+	subq $9,$11,$1
+	cmoveq $2,$1,$9
+	beq $0,$9122
+	zapnot $0,15,$2
+	subq $3,$0,$1
+	sll $11,$2,$11
+	sll $9,$2,$3
+	srl $10,$1,$1
+	sll $10,$2,$10
+	bis $3,$1,$9
+$9122:
+	srl $11,32,$5
+	zapnot $11,15,$6
+	lda $7,-1
+	.align 5
+$9123:
+	srl $9,32,$1
+	subq $1,$5,$1
+	bne $1,$9126
+	zapnot $7,15,$27
+	br $31,$9127
+	.align 4
+$9126:
+	bis $9,$9,$24
+	bis $5,$5,$25
+	divqu $24,$25,$27
+$9127:
+	srl $10,32,$4
+	.align 5
+$9128:
+	mulq $27,$5,$1
+	subq $9,$1,$3
+	zapnot $3,240,$1
+	bne $1,$9129
+	mulq $6,$27,$2
+	sll $3,32,$1
+	addq $1,$4,$1
+	cmpule $2,$1,$2
+	bne $2,$9129
+	subq $27,1,$27
+	br $31,$9128
+	.align 4
+$9129:
+	mulq $27,$6,$1
+	mulq $27,$5,$4
+	srl $1,32,$3
+	sll $1,32,$1
+	addq $4,$3,$4
+	cmpult $10,$1,$2
+	subq $10,$1,$10
+	addq $2,$4,$2
+	cmpult $9,$2,$1
+	bis $2,$2,$4
+	beq $1,$9134
+	addq $9,$11,$9
+	subq $27,1,$27
+$9134:
+	subl $12,1,$12
+	subq $9,$4,$9
+	beq $12,$9124
+	sll $27,32,$13
+	sll $9,32,$2
+	srl $10,32,$1
+	sll $10,32,$10
+	bis $2,$1,$9
+	br $31,$9123
+	.align 4
+$9124:
+	bis $13,$27,$0
+$9136:
+	ldq $26,0($30)
+	ldq $9,8($30)
+	ldq $10,16($30)
+	ldq $11,24($30)
+	ldq $12,32($30)
+	ldq $13,40($30)
+	addq $30,48,$30
+	ret $31,($26),1
+	.end bn_div64
+EOF
+	&asm_add($data);
+	}
+
+1;
diff --git a/crypto/bn/asm/alpha.works/mul.pl b/crypto/bn/asm/alpha.works/mul.pl
new file mode 100644
index 0000000..b182bae
--- /dev/null
+++ b/crypto/bn/asm/alpha.works/mul.pl
@@ -0,0 +1,116 @@
+#!/usr/local/bin/perl
+# alpha assember 
+
+sub bn_mul_words
+	{
+	local($name)=@_;
+	local($cc,$a,$b,$r,$couny);
+
+	&init_pool(4);
+	($cc)=GR("r0");
+
+	$rp=&wparam(0);
+	$ap=&wparam(1);
+	$count=&wparam(2);
+	$word=&wparam(3);
+
+	&function_begin($name,"");
+
+	&comment("");
+	&sub($count,4,$count);
+	&mov("zero",$cc);
+	&br(&label("finish"));
+	&blt($count,&label("finish"));
+
+	($a0,$r0)=&NR(2);
+	&ld($a0,&QWPw(0,$ap));
+	&ld($r0,&QWPw(0,$rp));
+
+$a=<<'EOF';
+##########################################################
+	&set_label("loop");
+
+	($a1)=&NR(1); &ld($a1,&QWPw(1,$ap));
+	($b1)=&NR(1); &ld($b1,&QWPw(1,$bp));
+	($a2)=&NR(1); &ld($a2,&QWPw(2,$ap));
+	($b2)=&NR(1); &ld($b2,&QWPw(2,$bp));
+	($a3)=&NR(1); &ld($a3,&QWPw(3,$ap));
+	($b3)=&NR(1); &ld($b3,&QWPw(3,$bp));
+
+	($o0,$t0)=&NR(2);
+	&add($a0,$b0,$o0); 
+	&cmpult($o0,$b0,$t0);
+	&add($o0,$cc,$o0);
+	&cmpult($o0,$cc,$cc);
+	&add($cc,$t0,$cc);	&FR($t0);
+
+	($t1,$o1)=&NR(2);
+
+	&add($a1,$b1,$o1);	&FR($a1);
+	&cmpult($o1,$b1,$t1);	&FR($b1);
+	&add($o1,$cc,$o1);
+	&cmpult($o1,$cc,$cc);
+	&add($cc,$t1,$cc);	&FR($t1);
+
+	($t2,$o2)=&NR(2);
+
+	&add($a2,$b2,$o2);	&FR($a2);
+	&cmpult($o2,$b2,$t2);	&FR($b2);
+	&add($o2,$cc,$o2);
+	&cmpult($o2,$cc,$cc);
+	&add($cc,$t2,$cc);	&FR($t2);
+
+	($t3,$o3)=&NR(2);
+
+	&add($a3,$b3,$o3);	&FR($a3);
+	&cmpult($o3,$b3,$t3);	&FR($b3);
+	&add($o3,$cc,$o3);
+	&cmpult($o3,$cc,$cc);
+	&add($cc,$t3,$cc);	&FR($t3);
+
+	&st($o0,&QWPw(0,$rp)); &FR($o0);
+	&st($o1,&QWPw(0,$rp)); &FR($o1);
+	&st($o2,&QWPw(0,$rp)); &FR($o2);
+	&st($o3,&QWPw(0,$rp)); &FR($o3);
+
+	&sub($count,4,$count);	# count-=4
+	&add($ap,4*$QWS,$ap);	# count+=4
+	&add($bp,4*$QWS,$bp);	# count+=4
+	&add($rp,4*$QWS,$rp);	# count+=4
+
+	&blt($count,&label("finish"));
+	&ld($a0,&QWPw(0,$ap));
+	 &ld($b0,&QWPw(0,$bp));
+	&br(&label("loop"));
+EOF
+##################################################
+	# Do the last 0..3 words
+
+	&set_label("last_loop");
+
+	&ld(($a0)=&NR(1),&QWPw(0,$ap));	# get a
+	&mul($a0,$word,($l0)=&NR(1));
+	 &add($ap,$QWS,$ap);
+	&muh($a0,$word,($h0)=&NR(1));	&FR($a0);
+	&add($l0,$cc,$l0);
+	 &add($rp,$QWS,$rp);
+	 &sub($count,1,$count);
+	&cmpult($l0,$cc,$cc);
+	&st($l0,&QWPw(-1,$rp));		&FR($l0);
+	&add($h0,$cc,$cc);		&FR($h0);
+
+	&bgt($count,&label("last_loop"));
+	&function_end_A($name);
+
+######################################################
+	&set_label("finish");
+	&add($count,4,$count);
+	&bgt($count,&label("last_loop"));
+
+	&set_label("end");
+	&function_end($name);
+
+	&fin_pool;
+	}
+
+1;
diff --git a/crypto/bn/asm/alpha.works/mul_add.pl b/crypto/bn/asm/alpha.works/mul_add.pl
new file mode 100644
index 0000000..e37f631
--- /dev/null
+++ b/crypto/bn/asm/alpha.works/mul_add.pl
@@ -0,0 +1,120 @@
+#!/usr/local/bin/perl
+# alpha assember 
+
+sub bn_mul_add_words
+	{
+	local($name)=@_;
+	local($cc,$a,$b,$r,$couny);
+
+	&init_pool(4);
+	($cc)=GR("r0");
+
+	$rp=&wparam(0);
+	$ap=&wparam(1);
+	$count=&wparam(2);
+	$word=&wparam(3);
+
+	&function_begin($name,"");
+
+	&comment("");
+	&sub($count,4,$count);
+	&mov("zero",$cc);
+	&br(&label("finish"));
+	&blt($count,&label("finish"));
+
+	($a0,$r0)=&NR(2);
+	&ld($a0,&QWPw(0,$ap));
+	&ld($r0,&QWPw(0,$rp));
+
+$a=<<'EOF';
+##########################################################
+	&set_label("loop");
+
+	($a1)=&NR(1); &ld($a1,&QWPw(1,$ap));
+	($b1)=&NR(1); &ld($b1,&QWPw(1,$bp));
+	($a2)=&NR(1); &ld($a2,&QWPw(2,$ap));
+	($b2)=&NR(1); &ld($b2,&QWPw(2,$bp));
+	($a3)=&NR(1); &ld($a3,&QWPw(3,$ap));
+	($b3)=&NR(1); &ld($b3,&QWPw(3,$bp));
+
+	($o0,$t0)=&NR(2);
+	&add($a0,$b0,$o0); 
+	&cmpult($o0,$b0,$t0);
+	&add($o0,$cc,$o0);
+	&cmpult($o0,$cc,$cc);
+	&add($cc,$t0,$cc);	&FR($t0);
+
+	($t1,$o1)=&NR(2);
+
+	&add($a1,$b1,$o1);	&FR($a1);
+	&cmpult($o1,$b1,$t1);	&FR($b1);
+	&add($o1,$cc,$o1);
+	&cmpult($o1,$cc,$cc);
+	&add($cc,$t1,$cc);	&FR($t1);
+
+	($t2,$o2)=&NR(2);
+
+	&add($a2,$b2,$o2);	&FR($a2);
+	&cmpult($o2,$b2,$t2);	&FR($b2);
+	&add($o2,$cc,$o2);
+	&cmpult($o2,$cc,$cc);
+	&add($cc,$t2,$cc);	&FR($t2);
+
+	($t3,$o3)=&NR(2);
+
+	&add($a3,$b3,$o3);	&FR($a3);
+	&cmpult($o3,$b3,$t3);	&FR($b3);
+	&add($o3,$cc,$o3);
+	&cmpult($o3,$cc,$cc);
+	&add($cc,$t3,$cc);	&FR($t3);
+
+	&st($o0,&QWPw(0,$rp)); &FR($o0);
+	&st($o1,&QWPw(0,$rp)); &FR($o1);
+	&st($o2,&QWPw(0,$rp)); &FR($o2);
+	&st($o3,&QWPw(0,$rp)); &FR($o3);
+
+	&sub($count,4,$count);	# count-=4
+	&add($ap,4*$QWS,$ap);	# count+=4
+	&add($bp,4*$QWS,$bp);	# count+=4
+	&add($rp,4*$QWS,$rp);	# count+=4
+
+	&blt($count,&label("finish"));
+	&ld($a0,&QWPw(0,$ap));
+	 &ld($b0,&QWPw(0,$bp));
+	&br(&label("loop"));
+EOF
+##################################################
+	# Do the last 0..3 words
+
+	&set_label("last_loop");
+
+	&ld(($a0)=&NR(1),&QWPw(0,$ap));	# get a
+	&ld(($r0)=&NR(1),&QWPw(0,$rp));	# get b
+	&mul($a0,$word,($l0)=&NR(1));
+	 &sub($count,1,$count);
+	 &add($ap,$QWS,$ap);
+	&muh($a0,$word,($h0)=&NR(1));	&FR($a0);
+	&add($r0,$l0,$r0);
+	 &add($rp,$QWS,$rp);
+	&cmpult($r0,$l0,($t0)=&NR(1));	&FR($l0);
+	 &add($r0,$cc,$r0);
+	&add($h0,$t0,$h0);		&FR($t0);
+	 &cmpult($r0,$cc,$cc);
+	&st($r0,&QWPw(-1,$rp));		&FR($r0);
+	 &add($h0,$cc,$cc);		&FR($h0);
+
+	&bgt($count,&label("last_loop"));
+	&function_end_A($name);
+
+######################################################
+	&set_label("finish");
+	&add($count,4,$count);
+	&bgt($count,&label("last_loop"));
+
+	&set_label("end");
+	&function_end($name);
+
+	&fin_pool;
+	}
+
+1;
diff --git a/crypto/bn/asm/alpha.works/mul_c4.pl b/crypto/bn/asm/alpha.works/mul_c4.pl
new file mode 100644
index 0000000..5efd201
--- /dev/null
+++ b/crypto/bn/asm/alpha.works/mul_c4.pl
@@ -0,0 +1,213 @@
+#!/usr/local/bin/perl
+# alpha assember 
+
+sub mul_add_c
+	{
+	local($a,$b,$c0,$c1,$c2)=@_;
+	local($l1,$h1,$t1,$t2);
+
+	&mul($a,$b,($l1)=&NR(1));
+	&muh($a,$b,($h1)=&NR(1));
+	&add($c0,$l1,$c0);
+	&cmpult($c0,$l1,($t1)=&NR(1));	&FR($l1);
+	&add($t1,$h1,$h1);		&FR($t1);
+	&add($c1,$h1,$c1);
+	&cmpult($c1,$h1,($t2)=&NR(1));	&FR($h1);
+	&add($c2,$t2,$c2);		&FR($t2);
+	}
+
+sub bn_mul_comba4
+	{
+	local($name)=@_;
+	local(@a,@b,$r,$c0,$c1,$c2);
+
+	$cnt=1;
+	&init_pool(3);
+
+	$rp=&wparam(0);
+	$ap=&wparam(1);
+	$bp=&wparam(2);
+
+	&function_begin($name,"");
+
+	&comment("");
+
+	&ld(($a[0])=&NR(1),&QWPw(0,$ap));
+	&ld(($b[0])=&NR(1),&QWPw(0,$bp));
+	&ld(($a[1])=&NR(1),&QWPw(1,$ap));
+	&ld(($b[1])=&NR(1),&QWPw(1,$bp));
+	&mul($a[0],$b[0],($r00)=&NR(1));
+	&ld(($a[2])=&NR(1),&QWPw(2,$ap));
+	&ld(($b[2])=&NR(1),&QWPw(2,$bp));
+	&muh($a[0],$b[0],($r01)=&NR(1));
+	&FR($ap); &ld(($a[3])=&NR(1),&QWPw(3,$ap));
+	&FR($bp); &ld(($b[3])=&NR(1),&QWPw(3,$bp));
+	&mul($a[0],$b[1],($r02)=&NR(1));
+
+	($R,$H1,$H2)=&NR(3);
+
+	&st($r00,&QWPw(0,$rp));	&FR($r00);
+
+	&mov("zero",$R);
+	&mul($a[1],$b[0],($r03)=&NR(1));
+
+	&mov("zero",$H1);
+	&mov("zero",$H0);
+	 &add($R,$r01,$R);
+	&muh($a[0],$b[1],($r04)=&NR(1));
+	 &cmpult($R,$r01,($t01)=&NR(1));	&FR($r01);
+	 &add($R,$r02,$R);
+	 &add($H1,$t01,$H1)			&FR($t01);
+	&muh($a[1],$b[0],($r05)=&NR(1));
+	 &cmpult($R,$r02,($t02)=&NR(1));	&FR($r02);
+	 &add($R,$r03,$R);
+	 &add($H2,$t02,$H2)			&FR($t02);
+	&mul($a[0],$b[2],($r06)=&NR(1));
+	 &cmpult($R,$r03,($t03)=&NR(1));	&FR($r03);
+	 &add($H1,$t03,$H1)			&FR($t03);
+	&st($R,&QWPw(1,$rp));
+	&add($H1,$H2,$R);
+
+	&mov("zero",$H1);
+	 &add($R,$r04,$R);
+	&mov("zero",$H2);
+	&mul($a[1],$b[1],($r07)=&NR(1));
+	 &cmpult($R,$r04,($t04)=&NR(1));	&FR($r04);
+	 &add($R,$r05,$R);
+	 &add($H1,$t04,$H1)			&FR($t04);
+	&mul($a[2],$b[0],($r08)=&NR(1));
+	 &cmpult($R,$r05,($t05)=&NR(1));	&FR($r05);
+	 &add($R,$r01,$R);
+	 &add($H2,$t05,$H2)			&FR($t05);
+	&muh($a[0],$b[2],($r09)=&NR(1));
+	 &cmpult($R,$r06,($t06)=&NR(1));	&FR($r06);
+	 &add($R,$r07,$R);
+	 &add($H1,$t06,$H1)			&FR($t06);
+	&muh($a[1],$b[1],($r10)=&NR(1));
+	 &cmpult($R,$r07,($t07)=&NR(1));	&FR($r07);
+	 &add($R,$r08,$R);
+	 &add($H2,$t07,$H2)			&FR($t07);
+	&muh($a[2],$b[0],($r11)=&NR(1));
+	 &cmpult($R,$r08,($t08)=&NR(1));	&FR($r08);
+	 &add($H1,$t08,$H1)			&FR($t08);
+	&st($R,&QWPw(2,$rp));
+	&add($H1,$H2,$R);
+
+	&mov("zero",$H1);
+	 &add($R,$r09,$R);
+	&mov("zero",$H2);
+	&mul($a[0],$b[3],($r12)=&NR(1));
+	 &cmpult($R,$r09,($t09)=&NR(1));	&FR($r09);
+	 &add($R,$r10,$R);
+	 &add($H1,$t09,$H1)			&FR($t09);
+	&mul($a[1],$b[2],($r13)=&NR(1));
+	 &cmpult($R,$r10,($t10)=&NR(1));	&FR($r10);
+	 &add($R,$r11,$R);
+	 &add($H1,$t10,$H1)			&FR($t10);
+	&mul($a[2],$b[1],($r14)=&NR(1));
+	 &cmpult($R,$r11,($t11)=&NR(1));	&FR($r11);
+	 &add($R,$r12,$R);
+	 &add($H1,$t11,$H1)			&FR($t11);
+	&mul($a[3],$b[0],($r15)=&NR(1));
+	 &cmpult($R,$r12,($t12)=&NR(1));	&FR($r12);
+	 &add($R,$r13,$R);
+	 &add($H1,$t12,$H1)			&FR($t12);
+	&muh($a[0],$b[3],($r16)=&NR(1));
+	 &cmpult($R,$r13,($t13)=&NR(1));	&FR($r13);
+	 &add($R,$r14,$R);
+	 &add($H1,$t13,$H1)			&FR($t13);
+	&muh($a[1],$b[2],($r17)=&NR(1));
+	 &cmpult($R,$r14,($t14)=&NR(1));	&FR($r14);
+	 &add($R,$r15,$R);
+	 &add($H1,$t14,$H1)			&FR($t14);
+	&muh($a[2],$b[1],($r18)=&NR(1));
+	 &cmpult($R,$r15,($t15)=&NR(1));	&FR($r15);
+	 &add($H1,$t15,$H1)			&FR($t15);
+	&st($R,&QWPw(3,$rp));
+	&add($H1,$H2,$R);
+
+	&mov("zero",$H1);
+	 &add($R,$r16,$R);
+	&mov("zero",$H2);
+	&muh($a[3],$b[0],($r19)=&NR(1));
+	 &cmpult($R,$r16,($t16)=&NR(1));	&FR($r16);
+	 &add($R,$r17,$R);
+	 &add($H1,$t16,$H1)			&FR($t16);
+	&mul($a[1],$b[3],($r20)=&NR(1));
+	 &cmpult($R,$r17,($t17)=&NR(1));	&FR($r17);
+	 &add($R,$r18,$R);
+	 &add($H1,$t17,$H1)			&FR($t17);
+	&mul($a[2],$b[2],($r21)=&NR(1));
+	 &cmpult($R,$r18,($t18)=&NR(1));	&FR($r18);
+	 &add($R,$r19,$R);
+	 &add($H1,$t18,$H1)			&FR($t18);
+	&mul($a[3],$b[1],($r22)=&NR(1));
+	 &cmpult($R,$r19,($t19)=&NR(1));	&FR($r19);
+	 &add($R,$r20,$R);
+	 &add($H1,$t19,$H1)			&FR($t19);
+	&muh($a[1],$b[3],($r23)=&NR(1));
+	 &cmpult($R,$r20,($t20)=&NR(1));	&FR($r20);
+	 &add($R,$r21,$R);
+	 &add($H1,$t20,$H1)			&FR($t20);
+	&muh($a[2],$b[2],($r24)=&NR(1));
+	 &cmpult($R,$r21,($t21)=&NR(1));	&FR($r21);
+	 &add($R,$r22,$R);
+	 &add($H1,$t21,$H1)			&FR($t21);
+	&muh($a[3],$b[1],($r25)=&NR(1));
+	 &cmpult($R,$r22,($t22)=&NR(1));	&FR($r22);
+	 &add($H1,$t22,$H1)			&FR($t22);
+	&st($R,&QWPw(4,$rp));
+	&add($H1,$H2,$R);
+
+	&mov("zero",$H1);
+	 &add($R,$r23,$R);
+	&mov("zero",$H2);
+	&mul($a[2],$b[3],($r26)=&NR(1));
+	 &cmpult($R,$r23,($t23)=&NR(1));	&FR($r23);
+	 &add($R,$r24,$R);
+	 &add($H1,$t23,$H1)			&FR($t23);
+	&mul($a[3],$b[2],($r27)=&NR(1));
+	 &cmpult($R,$r24,($t24)=&NR(1));	&FR($r24);
+	 &add($R,$r25,$R);
+	 &add($H1,$t24,$H1)			&FR($t24);
+	&muh($a[2],$b[3],($r28)=&NR(1));
+	 &cmpult($R,$r25,($t25)=&NR(1));	&FR($r25);
+	 &add($R,$r26,$R);
+	 &add($H1,$t25,$H1)			&FR($t25);
+	&muh($a[3],$b[2],($r29)=&NR(1));
+	 &cmpult($R,$r26,($t26)=&NR(1));	&FR($r26);
+	 &add($R,$r27,$R);
+	 &add($H1,$t26,$H1)			&FR($t26);
+	&mul($a[3],$b[3],($r30)=&NR(1));
+	 &cmpult($R,$r27,($t27)=&NR(1));	&FR($r27);
+	 &add($H1,$t27,$H1)			&FR($t27);
+	&st($R,&QWPw(5,$rp));
+	&add($H1,$H2,$R);
+
+	&mov("zero",$H1);
+	 &add($R,$r28,$R);
+	&mov("zero",$H2);
+	&muh($a[3],$b[3],($r31)=&NR(1));
+	 &cmpult($R,$r28,($t28)=&NR(1));	&FR($r28);
+	 &add($R,$r29,$R);
+	 &add($H1,$t28,$H1)			&FR($t28);
+	############
+	 &cmpult($R,$r29,($t29)=&NR(1));	&FR($r29);
+	 &add($R,$r30,$R);
+	 &add($H1,$t29,$H1)			&FR($t29);
+        ############
+	 &cmpult($R,$r30,($t30)=&NR(1));	&FR($r30);
+	 &add($H1,$t30,$H1)			&FR($t30);
+	&st($R,&QWPw(6,$rp));
+	&add($H1,$H2,$R);
+
+	 &add($R,$r31,$R);			&FR($r31);
+	&st($R,&QWPw(7,$rp));
+
+	&FR($R,$H1,$H2);
+	&function_end($name);
+
+	&fin_pool;
+	}
+
+1;
diff --git a/crypto/bn/asm/alpha.works/mul_c4.works.pl b/crypto/bn/asm/alpha.works/mul_c4.works.pl
new file mode 100644
index 0000000..79d86dd
--- /dev/null
+++ b/crypto/bn/asm/alpha.works/mul_c4.works.pl
@@ -0,0 +1,98 @@
+#!/usr/local/bin/perl
+# alpha assember 
+
+sub mul_add_c
+	{
+	local($a,$b,$c0,$c1,$c2)=@_;
+	local($l1,$h1,$t1,$t2);
+
+print STDERR "count=$cnt\n"; $cnt++;
+	&mul($a,$b,($l1)=&NR(1));
+	&muh($a,$b,($h1)=&NR(1));
+	&add($c0,$l1,$c0);
+	&cmpult($c0,$l1,($t1)=&NR(1));	&FR($l1);
+	&add($t1,$h1,$h1);		&FR($t1);
+	&add($c1,$h1,$c1);
+	&cmpult($c1,$h1,($t2)=&NR(1));	&FR($h1);
+	&add($c2,$t2,$c2);		&FR($t2);
+	}
+
+sub bn_mul_comba4
+	{
+	local($name)=@_;
+	local(@a,@b,$r,$c0,$c1,$c2);
+
+	$cnt=1;
+	&init_pool(3);
+
+	$rp=&wparam(0);
+	$ap=&wparam(1);
+	$bp=&wparam(2);
+
+	&function_begin($name,"");
+
+	&comment("");
+
+	&ld(($a[0])=&NR(1),&QWPw(0,$ap));
+	&ld(($b[0])=&NR(1),&QWPw(0,$bp));
+	&ld(($a[1])=&NR(1),&QWPw(1,$ap));
+	&ld(($b[1])=&NR(1),&QWPw(1,$bp));
+	&ld(($a[2])=&NR(1),&QWPw(2,$ap));
+	&ld(($b[2])=&NR(1),&QWPw(2,$bp));
+	&ld(($a[3])=&NR(1),&QWPw(3,$ap));	&FR($ap);
+	&ld(($b[3])=&NR(1),&QWPw(3,$bp));	&FR($bp);
+
+	($c0,$c1,$c2)=&NR(3);
+	&mov("zero",$c2);
+	&mul($a[0],$b[0],$c0);
+	&muh($a[0],$b[0],$c1);
+	&st($c0,&QWPw(0,$rp));			&FR($c0); ($c0)=&NR($c0);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[0],$b[1],$c0,$c1,$c2);
+	&mul_add_c($a[1],$b[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(1,$rp));			&FR($c0); ($c0)=&NR($c0);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[1],$b[1],$c0,$c1,$c2);
+	&mul_add_c($a[0],$b[2],$c0,$c1,$c2);
+	&mul_add_c($a[2],$b[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(2,$rp));			&FR($c0); ($c0)=&NR($c0);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[0],$b[3],$c0,$c1,$c2);	&FR($a[0]);
+	&mul_add_c($a[1],$b[2],$c0,$c1,$c2);
+	&mul_add_c($a[2],$b[1],$c0,$c1,$c2);
+	&mul_add_c($a[3],$b[0],$c0,$c1,$c2);	&FR($b[0]);
+	&st($c0,&QWPw(3,$rp));			&FR($c0); ($c0)=&NR($c0);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[1],$b[3],$c0,$c1,$c2);	&FR($a[1]);
+	&mul_add_c($a[2],$b[2],$c0,$c1,$c2);
+	&mul_add_c($a[3],$b[1],$c0,$c1,$c2);	&FR($b[1]);
+	&st($c0,&QWPw(4,$rp));			&FR($c0); ($c0)=&NR($c0);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[2],$b[3],$c0,$c1,$c2);	&FR($a[2]);
+	&mul_add_c($a[3],$b[2],$c0,$c1,$c2);	&FR($b[2]);
+	&st($c0,&QWPw(5,$rp));			&FR($c0); ($c0)=&NR($c0);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[3],$b[3],$c0,$c1,$c2);	&FR($a[3],$b[3]);
+	&st($c0,&QWPw(6,$rp));
+	&st($c1,&QWPw(7,$rp));
+
+	&FR($c0,$c1,$c2);
+
+	&function_end($name);
+
+	&fin_pool;
+	}
+
+1;
diff --git a/crypto/bn/asm/alpha.works/mul_c8.pl b/crypto/bn/asm/alpha.works/mul_c8.pl
new file mode 100644
index 0000000..525ca74
--- /dev/null
+++ b/crypto/bn/asm/alpha.works/mul_c8.pl
@@ -0,0 +1,177 @@
+#!/usr/local/bin/perl
+# alpha assember 
+
+sub bn_mul_comba8
+	{
+	local($name)=@_;
+	local(@a,@b,$r,$c0,$c1,$c2);
+
+	$cnt=1;
+	&init_pool(3);
+
+	$rp=&wparam(0);
+	$ap=&wparam(1);
+	$bp=&wparam(2);
+
+	&function_begin($name,"");
+
+	&comment("");
+
+	&stack_push(2);
+	&ld(($a[0])=&NR(1),&QWPw(0,$ap));
+	&ld(($b[0])=&NR(1),&QWPw(0,$bp));
+	&st($reg_s0,&swtmp(0)); &FR($reg_s0);
+	&st($reg_s1,&swtmp(1)); &FR($reg_s1);
+	&ld(($a[1])=&NR(1),&QWPw(1,$ap));
+	&ld(($b[1])=&NR(1),&QWPw(1,$bp));
+	&ld(($a[2])=&NR(1),&QWPw(2,$ap));
+	&ld(($b[2])=&NR(1),&QWPw(2,$bp));
+	&ld(($a[3])=&NR(1),&QWPw(3,$ap));
+	&ld(($b[3])=&NR(1),&QWPw(3,$bp));
+	&ld(($a[4])=&NR(1),&QWPw(1,$ap));
+	&ld(($b[4])=&NR(1),&QWPw(1,$bp));
+	&ld(($a[5])=&NR(1),&QWPw(1,$ap));
+	&ld(($b[5])=&NR(1),&QWPw(1,$bp));
+	&ld(($a[6])=&NR(1),&QWPw(1,$ap));
+	&ld(($b[6])=&NR(1),&QWPw(1,$bp));
+	&ld(($a[7])=&NR(1),&QWPw(1,$ap));	&FR($ap);
+	&ld(($b[7])=&NR(1),&QWPw(1,$bp));	&FR($bp);
+
+	($c0,$c1,$c2)=&NR(3);
+	&mov("zero",$c2);
+	&mul($a[0],$b[0],$c0);
+	&muh($a[0],$b[0],$c1);
+	&st($c0,&QWPw(0,$rp));			&FR($c0); ($c0)=&NR(1);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[0],$b[1],$c0,$c1,$c2);
+	&mul_add_c($a[1],$b[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(1,$rp));			&FR($c0); ($c0)=&NR(1);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[0],$b[2],$c0,$c1,$c2);
+	&mul_add_c($a[1],$b[1],$c0,$c1,$c2);
+	&mul_add_c($a[2],$b[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(2,$rp));			&FR($c0); ($c0)=&NR(1);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[0],$b[3],$c0,$c1,$c2);
+	&mul_add_c($a[1],$b[2],$c0,$c1,$c2);
+	&mul_add_c($a[2],$b[1],$c0,$c1,$c2);
+	&mul_add_c($a[3],$b[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(3,$rp));			&FR($c0); ($c0)=&NR(1);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[0],$b[4],$c0,$c1,$c2);
+	&mul_add_c($a[1],$b[3],$c0,$c1,$c2);
+	&mul_add_c($a[2],$b[2],$c0,$c1,$c2);
+	&mul_add_c($a[3],$b[1],$c0,$c1,$c2);
+	&mul_add_c($a[4],$b[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(4,$rp));			&FR($c0); ($c0)=&NR(1);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[0],$b[5],$c0,$c1,$c2);
+	&mul_add_c($a[1],$b[4],$c0,$c1,$c2);
+	&mul_add_c($a[2],$b[3],$c0,$c1,$c2);
+	&mul_add_c($a[3],$b[2],$c0,$c1,$c2);
+	&mul_add_c($a[4],$b[1],$c0,$c1,$c2);
+	&mul_add_c($a[5],$b[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(5,$rp));			&FR($c0); ($c0)=&NR(1);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[0],$b[6],$c0,$c1,$c2);
+	&mul_add_c($a[1],$b[5],$c0,$c1,$c2);
+	&mul_add_c($a[2],$b[4],$c0,$c1,$c2);
+	&mul_add_c($a[3],$b[3],$c0,$c1,$c2);
+	&mul_add_c($a[4],$b[2],$c0,$c1,$c2);
+	&mul_add_c($a[5],$b[1],$c0,$c1,$c2);
+	&mul_add_c($a[6],$b[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(6,$rp));			&FR($c0); ($c0)=&NR(1);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[0],$b[7],$c0,$c1,$c2);	&FR($a[0]);
+	&mul_add_c($a[1],$b[6],$c0,$c1,$c2);
+	&mul_add_c($a[2],$b[5],$c0,$c1,$c2);
+	&mul_add_c($a[3],$b[4],$c0,$c1,$c2);
+	&mul_add_c($a[4],$b[3],$c0,$c1,$c2);
+	&mul_add_c($a[5],$b[2],$c0,$c1,$c2);
+	&mul_add_c($a[6],$b[1],$c0,$c1,$c2);
+	&mul_add_c($a[7],$b[0],$c0,$c1,$c2);	&FR($b[0]);
+	&st($c0,&QWPw(7,$rp));			&FR($c0); ($c0)=&NR(1);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[1],$b[7],$c0,$c1,$c2);	&FR($a[1]);
+	&mul_add_c($a[2],$b[6],$c0,$c1,$c2);
+	&mul_add_c($a[3],$b[5],$c0,$c1,$c2);
+	&mul_add_c($a[4],$b[4],$c0,$c1,$c2);
+	&mul_add_c($a[5],$b[3],$c0,$c1,$c2);
+	&mul_add_c($a[6],$b[2],$c0,$c1,$c2);
+	&mul_add_c($a[7],$b[1],$c0,$c1,$c2);	&FR($b[1]);
+	&st($c0,&QWPw(8,$rp));			&FR($c0); ($c0)=&NR(1);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[2],$b[7],$c0,$c1,$c2);	&FR($a[2]);
+	&mul_add_c($a[3],$b[6],$c0,$c1,$c2);
+	&mul_add_c($a[4],$b[5],$c0,$c1,$c2);
+	&mul_add_c($a[5],$b[4],$c0,$c1,$c2);
+	&mul_add_c($a[6],$b[3],$c0,$c1,$c2);
+	&mul_add_c($a[7],$b[2],$c0,$c1,$c2);	&FR($b[2]);
+	&st($c0,&QWPw(9,$rp));			&FR($c0); ($c0)=&NR(1);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[3],$b[7],$c0,$c1,$c2);	&FR($a[3]);
+	&mul_add_c($a[4],$b[6],$c0,$c1,$c2);
+	&mul_add_c($a[5],$b[5],$c0,$c1,$c2);
+	&mul_add_c($a[6],$b[4],$c0,$c1,$c2);
+	&mul_add_c($a[7],$b[3],$c0,$c1,$c2);	&FR($b[3]);
+	&st($c0,&QWPw(10,$rp));			&FR($c0); ($c0)=&NR(1);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[4],$b[7],$c0,$c1,$c2);	&FR($a[4]);
+	&mul_add_c($a[5],$b[6],$c0,$c1,$c2);
+	&mul_add_c($a[6],$b[5],$c0,$c1,$c2);
+	&mul_add_c($a[7],$b[4],$c0,$c1,$c2);	&FR($b[4]);
+	&st($c0,&QWPw(11,$rp));			&FR($c0); ($c0)=&NR(1);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[5],$b[7],$c0,$c1,$c2);	&FR($a[5]);
+	&mul_add_c($a[6],$b[6],$c0,$c1,$c2);
+	&mul_add_c($a[7],$b[5],$c0,$c1,$c2);	&FR($b[5]);
+	&st($c0,&QWPw(12,$rp));			&FR($c0); ($c0)=&NR(1);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[6],$b[7],$c0,$c1,$c2);	&FR($a[6]);
+	&mul_add_c($a[7],$b[6],$c0,$c1,$c2);	&FR($b[6]);
+	&st($c0,&QWPw(13,$rp));			&FR($c0); ($c0)=&NR(1);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[7],$b[7],$c0,$c1,$c2);	&FR($a[7],$b[7]);
+	&st($c0,&QWPw(14,$rp));
+	&st($c1,&QWPw(15,$rp));
+
+	&FR($c0,$c1,$c2);
+
+	&ld($reg_s0,&swtmp(0));
+	&ld($reg_s1,&swtmp(1));
+	&stack_pop(2);
+
+	&function_end($name);
+
+	&fin_pool;
+	}
+
+1;
diff --git a/crypto/bn/asm/alpha.works/sqr.pl b/crypto/bn/asm/alpha.works/sqr.pl
new file mode 100644
index 0000000..a55b696
--- /dev/null
+++ b/crypto/bn/asm/alpha.works/sqr.pl
@@ -0,0 +1,113 @@
+#!/usr/local/bin/perl
+# alpha assember 
+
+sub bn_sqr_words
+	{
+	local($name)=@_;
+	local($cc,$a,$b,$r,$couny);
+
+	&init_pool(3);
+	($cc)=GR("r0");
+
+	$rp=&wparam(0);
+	$ap=&wparam(1);
+	$count=&wparam(2);
+
+	&function_begin($name,"");
+
+	&comment("");
+	&sub($count,4,$count);
+	&mov("zero",$cc);
+	&br(&label("finish"));
+	&blt($count,&label("finish"));
+
+	($a0,$r0)=&NR(2);
+	&ld($a0,&QWPw(0,$ap));
+	&ld($r0,&QWPw(0,$rp));
+
+$a=<<'EOF';
+##########################################################
+	&set_label("loop");
+
+	($a1)=&NR(1); &ld($a1,&QWPw(1,$ap));
+	($b1)=&NR(1); &ld($b1,&QWPw(1,$bp));
+	($a2)=&NR(1); &ld($a2,&QWPw(2,$ap));
+	($b2)=&NR(1); &ld($b2,&QWPw(2,$bp));
+	($a3)=&NR(1); &ld($a3,&QWPw(3,$ap));
+	($b3)=&NR(1); &ld($b3,&QWPw(3,$bp));
+
+	($o0,$t0)=&NR(2);
+	&add($a0,$b0,$o0); 
+	&cmpult($o0,$b0,$t0);
+	&add($o0,$cc,$o0);
+	&cmpult($o0,$cc,$cc);
+	&add($cc,$t0,$cc);	&FR($t0);
+
+	($t1,$o1)=&NR(2);
+
+	&add($a1,$b1,$o1);	&FR($a1);
+	&cmpult($o1,$b1,$t1);	&FR($b1);
+	&add($o1,$cc,$o1);
+	&cmpult($o1,$cc,$cc);
+	&add($cc,$t1,$cc);	&FR($t1);
+
+	($t2,$o2)=&NR(2);
+
+	&add($a2,$b2,$o2);	&FR($a2);
+	&cmpult($o2,$b2,$t2);	&FR($b2);
+	&add($o2,$cc,$o2);
+	&cmpult($o2,$cc,$cc);
+	&add($cc,$t2,$cc);	&FR($t2);
+
+	($t3,$o3)=&NR(2);
+
+	&add($a3,$b3,$o3);	&FR($a3);
+	&cmpult($o3,$b3,$t3);	&FR($b3);
+	&add($o3,$cc,$o3);
+	&cmpult($o3,$cc,$cc);
+	&add($cc,$t3,$cc);	&FR($t3);
+
+	&st($o0,&QWPw(0,$rp)); &FR($o0);
+	&st($o1,&QWPw(0,$rp)); &FR($o1);
+	&st($o2,&QWPw(0,$rp)); &FR($o2);
+	&st($o3,&QWPw(0,$rp)); &FR($o3);
+
+	&sub($count,4,$count);	# count-=4
+	&add($ap,4*$QWS,$ap);	# count+=4
+	&add($bp,4*$QWS,$bp);	# count+=4
+	&add($rp,4*$QWS,$rp);	# count+=4
+
+	&blt($count,&label("finish"));
+	&ld($a0,&QWPw(0,$ap));
+	 &ld($b0,&QWPw(0,$bp));
+	&br(&label("loop"));
+EOF
+##################################################
+	# Do the last 0..3 words
+
+	&set_label("last_loop");
+
+	&ld(($a0)=&NR(1),&QWPw(0,$ap));	# get a
+	&mul($a0,$a0,($l0)=&NR(1));
+	 &add($ap,$QWS,$ap);
+	 &add($rp,2*$QWS,$rp);
+	 &sub($count,1,$count);
+	&muh($a0,$a0,($h0)=&NR(1));	&FR($a0);
+	&st($l0,&QWPw(-2,$rp));		&FR($l0);
+	&st($h0,&QWPw(-1,$rp));		&FR($h0);
+
+	&bgt($count,&label("last_loop"));
+	&function_end_A($name);
+
+######################################################
+	&set_label("finish");
+	&add($count,4,$count);
+	&bgt($count,&label("last_loop"));
+
+	&set_label("end");
+	&function_end($name);
+
+	&fin_pool;
+	}
+
+1;
diff --git a/crypto/bn/asm/alpha.works/sqr_c4.pl b/crypto/bn/asm/alpha.works/sqr_c4.pl
new file mode 100644
index 0000000..bf33f5b
--- /dev/null
+++ b/crypto/bn/asm/alpha.works/sqr_c4.pl
@@ -0,0 +1,109 @@
+#!/usr/local/bin/perl
+# alpha assember 
+
+sub sqr_add_c
+	{
+	local($a,$c0,$c1,$c2)=@_;
+	local($l1,$h1,$t1,$t2);
+
+	&mul($a,$a,($l1)=&NR(1));
+	&muh($a,$a,($h1)=&NR(1));
+	&add($c0,$l1,$c0);
+	&add($c1,$h1,$c1);
+	&cmpult($c0,$l1,($t1)=&NR(1));	&FR($l1);
+	&cmpult($c1,$h1,($t2)=&NR(1));	&FR($h1);
+	&add($c1,$t1,$c1);		&FR($t1);
+	&add($c2,$t2,$c2);		&FR($t2);
+	}
+
+sub sqr_add_c2
+	{
+	local($a,$b,$c0,$c1,$c2)=@_;
+	local($l1,$h1,$t1,$t2);
+
+	&mul($a,$b,($l1)=&NR(1));
+	&muh($a,$b,($h1)=&NR(1));
+	&cmplt($l1,"zero",($lc1)=&NR(1));
+	&cmplt($h1,"zero",($hc1)=&NR(1));
+	&add($l1,$l1,$l1);
+	&add($h1,$h1,$h1);
+	&add($h1,$lc1,$h1);		&FR($lc1);
+	&add($c2,$hc1,$c2);		&FR($hc1);
+
+	&add($c0,$l1,$c0);
+	&add($c1,$h1,$c1);
+	&cmpult($c0,$l1,($lc1)=&NR(1));	&FR($l1);
+	&cmpult($c1,$h1,($hc1)=&NR(1));	&FR($h1);
+
+	&add($c1,$lc1,$c1);		&FR($lc1);
+	&add($c2,$hc1,$c2);		&FR($hc1);
+	}
+
+
+sub bn_sqr_comba4
+	{
+	local($name)=@_;
+	local(@a,@b,$r,$c0,$c1,$c2);
+
+	$cnt=1;
+	&init_pool(2);
+
+	$rp=&wparam(0);
+	$ap=&wparam(1);
+
+	&function_begin($name,"");
+
+	&comment("");
+
+	&ld(($a[0])=&NR(1),&QWPw(0,$ap));
+	&ld(($a[1])=&NR(1),&QWPw(1,$ap));
+	&ld(($a[2])=&NR(1),&QWPw(2,$ap));
+        &ld(($a[3])=&NR(1),&QWPw(3,$ap)); &FR($ap);
+
+	($c0,$c1,$c2)=&NR(3);
+
+	&mov("zero",$c2);
+	&mul($a[0],$a[0],$c0);
+	&muh($a[0],$a[0],$c1);
+	&st($c0,&QWPw(0,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c2($a[0],$a[1],$c0,$c1,$c2);
+	&st($c0,&QWPw(1,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c($a[1],$c0,$c1,$c2);
+	&sqr_add_c2($a[2],$a[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(2,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c2($a[3],$a[0],$c0,$c1,$c2);
+	&sqr_add_c2($a[2],$a[1],$c0,$c1,$c2);
+	&st($c0,&QWPw(3,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c($a[2],$c0,$c1,$c2);
+	&sqr_add_c2($a[3],$a[1],$c0,$c1,$c2);
+	&st($c0,&QWPw(4,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c2($a[3],$a[2],$c0,$c1,$c2);
+	&st($c0,&QWPw(5,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c($a[3],$c0,$c1,$c2);
+	&st($c0,&QWPw(6,$rp));
+	&st($c1,&QWPw(7,$rp));
+
+	&function_end($name);
+
+	&fin_pool;
+	}
+
+1;
diff --git a/crypto/bn/asm/alpha.works/sqr_c8.pl b/crypto/bn/asm/alpha.works/sqr_c8.pl
new file mode 100644
index 0000000..b4afe08
--- /dev/null
+++ b/crypto/bn/asm/alpha.works/sqr_c8.pl
@@ -0,0 +1,132 @@
+#!/usr/local/bin/perl
+# alpha assember 
+
+sub bn_sqr_comba8
+	{
+	local($name)=@_;
+	local(@a,@b,$r,$c0,$c1,$c2);
+
+	$cnt=1;
+	&init_pool(2);
+
+	$rp=&wparam(0);
+	$ap=&wparam(1);
+
+	&function_begin($name,"");
+
+	&comment("");
+
+	&ld(($a[0])=&NR(1),&QWPw(0,$ap));
+	&ld(($a[1])=&NR(1),&QWPw(1,$ap));
+	&ld(($a[2])=&NR(1),&QWPw(2,$ap));
+	&ld(($a[3])=&NR(1),&QWPw(3,$ap));
+	&ld(($a[4])=&NR(1),&QWPw(4,$ap));
+	&ld(($a[5])=&NR(1),&QWPw(5,$ap));
+	&ld(($a[6])=&NR(1),&QWPw(6,$ap));
+        &ld(($a[7])=&NR(1),&QWPw(7,$ap)); &FR($ap);
+
+	($c0,$c1,$c2)=&NR(3);
+
+	&mov("zero",$c2);
+	&mul($a[0],$a[0],$c0);
+	&muh($a[0],$a[0],$c1);
+	&st($c0,&QWPw(0,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c2($a[1],$a[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(1,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c($a[1],$c0,$c1,$c2);
+	&sqr_add_c2($a[2],$a[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(2,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c2($a[2],$a[1],$c0,$c1,$c2);
+	&sqr_add_c2($a[3],$a[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(3,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c($a[2],$c0,$c1,$c2);
+	&sqr_add_c2($a[3],$a[1],$c0,$c1,$c2);
+	&sqr_add_c2($a[4],$a[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(4,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c2($a[3],$a[2],$c0,$c1,$c2);
+	&sqr_add_c2($a[4],$a[1],$c0,$c1,$c2);
+	&sqr_add_c2($a[5],$a[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(5,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c($a[3],$c0,$c1,$c2);
+	&sqr_add_c2($a[4],$a[2],$c0,$c1,$c2);
+	&sqr_add_c2($a[5],$a[1],$c0,$c1,$c2);
+	&sqr_add_c2($a[6],$a[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(6,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c2($a[4],$a[3],$c0,$c1,$c2);
+	&sqr_add_c2($a[5],$a[2],$c0,$c1,$c2);
+	&sqr_add_c2($a[6],$a[1],$c0,$c1,$c2);
+	&sqr_add_c2($a[7],$a[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(7,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c($a[4],$c0,$c1,$c2);
+	&sqr_add_c2($a[5],$a[3],$c0,$c1,$c2);
+	&sqr_add_c2($a[6],$a[2],$c0,$c1,$c2);
+	&sqr_add_c2($a[7],$a[1],$c0,$c1,$c2);
+	&st($c0,&QWPw(8,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c2($a[5],$a[4],$c0,$c1,$c2);
+	&sqr_add_c2($a[6],$a[3],$c0,$c1,$c2);
+	&sqr_add_c2($a[7],$a[2],$c0,$c1,$c2);
+	&st($c0,&QWPw(9,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c($a[5],$c0,$c1,$c2);
+	&sqr_add_c2($a[6],$a[4],$c0,$c1,$c2);
+	&sqr_add_c2($a[7],$a[3],$c0,$c1,$c2);
+	&st($c0,&QWPw(10,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c2($a[6],$a[5],$c0,$c1,$c2);
+	&sqr_add_c2($a[7],$a[4],$c0,$c1,$c2);
+	&st($c0,&QWPw(11,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c($a[6],$c0,$c1,$c2);
+	&sqr_add_c2($a[7],$a[5],$c0,$c1,$c2);
+	&st($c0,&QWPw(12,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c2($a[7],$a[6],$c0,$c1,$c2);
+	&st($c0,&QWPw(13,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c($a[7],$c0,$c1,$c2);
+	&st($c0,&QWPw(14,$rp));
+	&st($c1,&QWPw(15,$rp));
+
+	&function_end($name);
+
+	&fin_pool;
+	}
+
+1;
diff --git a/crypto/bn/asm/alpha.works/sub.pl b/crypto/bn/asm/alpha.works/sub.pl
new file mode 100644
index 0000000..d998da5
--- /dev/null
+++ b/crypto/bn/asm/alpha.works/sub.pl
@@ -0,0 +1,108 @@
+#!/usr/local/bin/perl
+# alpha assember
+
+sub bn_sub_words
+	{
+	local($name)=@_;
+	local($cc,$a,$b,$r);
+
+	&init_pool(4);
+	($cc)=GR("r0");
+
+	$rp=&wparam(0);
+	$ap=&wparam(1);
+	$bp=&wparam(2);
+	$count=&wparam(3);
+
+	&function_begin($name,"");
+
+	&comment("");
+	&sub($count,4,$count);
+	&mov("zero",$cc);
+	&blt($count,&label("finish"));
+
+	($a0,$b0)=&NR(2);
+	&ld($a0,&QWPw(0,$ap));
+	&ld($b0,&QWPw(0,$bp));
+
+##########################################################
+	&set_label("loop");
+
+	($a1,$tmp,$b1,$a2,$b2,$a3,$b3,$o0)=&NR(8);
+	&ld($a1,&QWPw(1,$ap));
+	 &cmpult($a0,$b0,$tmp);	# will we borrow?
+	&ld($b1,&QWPw(1,$bp));
+	 &sub($a0,$b0,$a0);		# do the subtract
+	&ld($a2,&QWPw(2,$ap));
+	 &cmpult($a0,$cc,$b0);	# will we borrow?
+	&ld($b2,&QWPw(2,$bp));
+	 &sub($a0,$cc,$o0);	# will we borrow?
+	&ld($a3,&QWPw(3,$ap));
+	 &add($b0,$tmp,$cc); ($t1,$o1)=&NR(2); &FR($tmp);
+
+	&cmpult($a1,$b1,$t1);	# will we borrow?
+	 &sub($a1,$b1,$a1);	# do the subtract
+	&ld($b3,&QWPw(3,$bp));
+	 &cmpult($a1,$cc,$b1);	# will we borrow?
+	&sub($a1,$cc,$o1);	# will we borrow?
+	 &add($b1,$t1,$cc); ($tmp,$o2)=&NR(2); &FR($t1,$a1,$b1);
+	
+	&cmpult($a2,$b2,$tmp);	# will we borrow?
+	 &sub($a2,$b2,$a2);		# do the subtract
+	&st($o0,&QWPw(0,$rp));	&FR($o0); # save
+	 &cmpult($a2,$cc,$b2);	# will we borrow?
+	&sub($a2,$cc,$o2);	# will we borrow?
+	 &add($b2,$tmp,$cc); ($t3,$o3)=&NR(2); &FR($tmp,$a2,$b2);
+
+	&cmpult($a3,$b3,$t3);	# will we borrow?
+	 &sub($a3,$b3,$a3);	# do the subtract
+	&st($o1,&QWPw(1,$rp)); &FR($o1);
+	 &cmpult($a3,$cc,$b3);	# will we borrow?
+	&sub($a3,$cc,$o3);	# will we borrow?
+	 &add($b3,$t3,$cc); &FR($t3,$a3,$b3);
+
+	&st($o2,&QWPw(2,$rp));	&FR($o2);
+	 &sub($count,4,$count);	# count-=4
+	&st($o3,&QWPw(3,$rp));	&FR($o3);
+	 &add($ap,4*$QWS,$ap);	# count+=4
+	&add($bp,4*$QWS,$bp);	# count+=4
+	 &add($rp,4*$QWS,$rp);	# count+=4
+
+	&blt($count,&label("finish"));
+	&ld($a0,&QWPw(0,$ap));
+	 &ld($b0,&QWPw(0,$bp));
+	&br(&label("loop"));
+##################################################
+	# Do the last 0..3 words
+
+	&set_label("last_loop");
+
+	&ld($a0,&QWPw(0,$ap));	# get a
+	 &ld($b0,&QWPw(0,$bp));	# get b
+	&cmpult($a0,$b0,$tmp);	# will we borrow?
+	&sub($a0,$b0,$a0);	# do the subtract
+	&cmpult($a0,$cc,$b0);	# will we borrow?
+	&sub($a0,$cc,$a0);	# will we borrow?
+	&st($a0,&QWPw(0,$rp));	# save
+	&add($b0,$tmp,$cc);	# add the borrows
+
+	&add($ap,$QWS,$ap);
+	&add($bp,$QWS,$bp);
+	&add($rp,$QWS,$rp);
+	&sub($count,1,$count);
+	&bgt($count,&label("last_loop"));
+	&function_end_A($name);
+
+######################################################
+	&set_label("finish");
+	&add($count,4,$count);
+	&bgt($count,&label("last_loop"));
+
+	&FR($a0,$b0);
+	&set_label("end");
+	&function_end($name);
+
+	&fin_pool;
+	}
+
+1;
diff --git a/crypto/bn/asm/alpha/add.pl b/crypto/bn/asm/alpha/add.pl
new file mode 100644
index 0000000..13bf516
--- /dev/null
+++ b/crypto/bn/asm/alpha/add.pl
@@ -0,0 +1,118 @@
+#!/usr/local/bin/perl
+# alpha assember 
+
+sub bn_add_words
+	{
+	local($name)=@_;
+	local($cc,$a,$b,$r);
+
+	&init_pool(4);
+	($cc)=GR("r0");
+
+	$rp=&wparam(0);
+	$ap=&wparam(1);
+	$bp=&wparam(2);
+	$count=&wparam(3);
+
+	&function_begin($name,"");
+
+	&comment("");
+	&sub($count,4,$count);
+	 &mov("zero",$cc);
+	&blt($count,&label("finish"));
+
+	($a0,$b0)=&NR(2);
+
+##########################################################
+	&set_label("loop");
+
+	&ld(($a0)=&NR(1),&QWPw(0,$ap));
+	 &ld(($b0)=&NR(1),&QWPw(0,$bp));
+	&ld(($a1)=&NR(1),&QWPw(1,$ap));
+	 &ld(($b1)=&NR(1),&QWPw(1,$bp));
+
+	($o0,$t0)=&NR(2);
+	&add($a0,$b0,$o0); 
+	 &ld(($a2)=&NR(1),&QWPw(2,$ap));
+	&cmpult($o0,$b0,$t0);
+	 &add($o0,$cc,$o0);
+	&cmpult($o0,$cc,$cc);
+	 &ld(($b2)=&NR(1),&QWPw(2,$bp));
+	&add($cc,$t0,$cc);	&FR($t0);
+
+	($t1,$o1)=&NR(2);
+
+	 &add($a1,$b1,$o1);	&FR($a1);
+	&cmpult($o1,$b1,$t1);	&FR($b1);
+	 &add($o1,$cc,$o1);
+	&cmpult($o1,$cc,$cc);
+	 &ld(($a3)=&NR(1),&QWPw(3,$ap));
+	&add($cc,$t1,$cc);	&FR($t1);
+
+	($t2,$o2)=&NR(2);
+
+	 &add($a2,$b2,$o2);	&FR($a2);
+	&cmpult($o2,$b2,$t2);	&FR($b2);
+	 &add($o2,$cc,$o2);
+	&cmpult($o2,$cc,$cc);
+	 &ld(($b3)=&NR(1),&QWPw(3,$bp));
+	&st($o0,&QWPw(0,$rp)); &FR($o0);
+	 &add($cc,$t2,$cc);	&FR($t2);
+
+	($t3,$o3)=&NR(2);
+
+	&st($o1,&QWPw(0,$rp)); &FR($o1);
+	 &add($a3,$b3,$o3);	&FR($a3);
+	&cmpult($o3,$b3,$t3);	&FR($b3);
+	 &add($o3,$cc,$o3);
+	&st($o2,&QWPw(0,$rp)); &FR($o2);
+	 &cmpult($o3,$cc,$cc);
+	&st($o3,&QWPw(0,$rp)); &FR($o3);
+	 &add($cc,$t3,$cc);	&FR($t3);
+
+
+	&sub($count,4,$count);	# count-=4
+	 &add($ap,4*$QWS,$ap);	# count+=4
+	&add($bp,4*$QWS,$bp);	# count+=4
+	 &add($rp,4*$QWS,$rp);	# count+=4
+
+	###
+	 &bge($count,&label("loop"));
+	###
+	&br(&label("finish"));
+##################################################
+	# Do the last 0..3 words
+
+	($t0,$o0)=&NR(2);
+	&set_label("last_loop");
+
+	&ld($a0,&QWPw(0,$ap));	# get a
+	 &ld($b0,&QWPw(0,$bp));	# get b
+	&add($ap,$QWS,$ap);
+	 &add($bp,$QWS,$bp);
+	&add($a0,$b0,$o0); 
+	 &sub($count,1,$count);
+	&cmpult($o0,$b0,$t0);	# will we borrow?
+	 &add($o0,$cc,$o0);	# will we borrow?
+	&cmpult($o0,$cc,$cc);	# will we borrow?
+	 &add($rp,$QWS,$rp);
+	&st($o0,&QWPw(-1,$rp));	# save
+	 &add($cc,$t0,$cc);	# add the borrows
+
+	###
+	 &bgt($count,&label("last_loop"));
+	&function_end_A($name);
+
+######################################################
+	&set_label("finish");
+	&add($count,4,$count);
+	 &bgt($count,&label("last_loop"));
+
+	&FR($o0,$t0,$a0,$b0);
+	&set_label("end");
+	&function_end($name);
+
+	&fin_pool;
+	}
+
+1;
diff --git a/crypto/bn/asm/alpha/div.pl b/crypto/bn/asm/alpha/div.pl
new file mode 100644
index 0000000..e9e6808
--- /dev/null
+++ b/crypto/bn/asm/alpha/div.pl
@@ -0,0 +1,144 @@
+#!/usr/local/bin/perl
+
+sub bn_div_words
+	{
+	local($data)=<<'EOF';
+ #
+ # What follows was taken directly from the C compiler with a few
+ # hacks to redo the lables.
+ #
+.text
+        .set noreorder
+	.set volatile
+	.align 3
+	.globl bn_div_words
+	.ent bn_div_words
+bn_div_words
+	ldgp $29,0($27)
+bn_div_words.ng:
+	lda $30,-48($30)
+	.frame $30,48,$26,0
+	stq $26,0($30)
+	stq $9,8($30)
+	stq $10,16($30)
+	stq $11,24($30)
+	stq $12,32($30)
+	stq $13,40($30)
+	.mask 0x4003e00,-48
+	.prologue 1
+	bis $16,$16,$9
+	bis $17,$17,$10
+	bis $18,$18,$11
+	bis $31,$31,$13
+	bis $31,2,$12
+	bne $11,$9119
+	lda $0,-1
+	br $31,$9136
+	.align 4
+$9119:
+	bis $11,$11,$16
+	jsr $26,BN_num_bits_word
+	ldgp $29,0($26)
+	subq $0,64,$1
+	beq $1,$9120
+	bis $31,1,$1
+	sll $1,$0,$1
+	cmpule $9,$1,$1
+	bne $1,$9120
+ #	lda $16,_IO_stderr_
+ #	lda $17,$C32
+ #	bis $0,$0,$18
+ #	jsr $26,fprintf
+ #	ldgp $29,0($26)
+	jsr $26,abort
+	ldgp $29,0($26)
+	.align 4
+$9120:
+	bis $31,64,$3
+	cmpult $9,$11,$2
+	subq $3,$0,$1
+	addl $1,$31,$0
+	subq $9,$11,$1
+	cmoveq $2,$1,$9
+	beq $0,$9122
+	zapnot $0,15,$2
+	subq $3,$0,$1
+	sll $11,$2,$11
+	sll $9,$2,$3
+	srl $10,$1,$1
+	sll $10,$2,$10
+	bis $3,$1,$9
+$9122:
+	srl $11,32,$5
+	zapnot $11,15,$6
+	lda $7,-1
+	.align 5
+$9123:
+	srl $9,32,$1
+	subq $1,$5,$1
+	bne $1,$9126
+	zapnot $7,15,$27
+	br $31,$9127
+	.align 4
+$9126:
+	bis $9,$9,$24
+	bis $5,$5,$25
+	divqu $24,$25,$27
+$9127:
+	srl $10,32,$4
+	.align 5
+$9128:
+	mulq $27,$5,$1
+	subq $9,$1,$3
+	zapnot $3,240,$1
+	bne $1,$9129
+	mulq $6,$27,$2
+	sll $3,32,$1
+	addq $1,$4,$1
+	cmpule $2,$1,$2
+	bne $2,$9129
+	subq $27,1,$27
+	br $31,$9128
+	.align 4
+$9129:
+	mulq $27,$6,$1
+	mulq $27,$5,$4
+	srl $1,32,$3
+	sll $1,32,$1
+	addq $4,$3,$4
+	cmpult $10,$1,$2
+	subq $10,$1,$10
+	addq $2,$4,$2
+	cmpult $9,$2,$1
+	bis $2,$2,$4
+	beq $1,$9134
+	addq $9,$11,$9
+	subq $27,1,$27
+$9134:
+	subl $12,1,$12
+	subq $9,$4,$9
+	beq $12,$9124
+	sll $27,32,$13
+	sll $9,32,$2
+	srl $10,32,$1
+	sll $10,32,$10
+	bis $2,$1,$9
+	br $31,$9123
+	.align 4
+$9124:
+	bis $13,$27,$0
+$9136:
+	ldq $26,0($30)
+	ldq $9,8($30)
+	ldq $10,16($30)
+	ldq $11,24($30)
+	ldq $12,32($30)
+	ldq $13,40($30)
+	addq $30,48,$30
+	ret $31,($26),1
+	.end bn_div_words
+EOF
+	&asm_add($data);
+	}
+
+1;
diff --git a/crypto/bn/asm/alpha/mul.pl b/crypto/bn/asm/alpha/mul.pl
new file mode 100644
index 0000000..76c9265
--- /dev/null
+++ b/crypto/bn/asm/alpha/mul.pl
@@ -0,0 +1,104 @@
+#!/usr/local/bin/perl
+# alpha assember 
+
+sub bn_mul_words
+	{
+	local($name)=@_;
+	local($cc,$a,$b,$r,$couny);
+
+	&init_pool(4);
+	($cc)=GR("r0");
+
+	$rp=&wparam(0);
+	$ap=&wparam(1);
+	$count=&wparam(2);
+	$word=&wparam(3);
+
+	&function_begin($name,"");
+
+	&comment("");
+	&sub($count,4,$count);
+	 &mov("zero",$cc);
+	###
+	 &blt($count,&label("finish"));
+
+	($a0)=&NR(1); &ld($a0,&QWPw(0,$ap));
+
+	&set_label("loop");
+
+	($a1)=&NR(1); &ld($a1,&QWPw(1,$ap));
+	 ($a2)=&NR(1); &ld($a2,&QWPw(2,$ap));
+
+	&muh($a0,$word,($h0)=&NR(1));	&FR($a0);
+	 ($a3)=&NR(1); &ld($a3,&QWPw(3,$ap));
+	 						### wait 8
+	&mul($a0,$word,($l0)=&NR(1));	&FR($a0);
+	 						### wait 8
+	&muh($a1,$word,($h1)=&NR(1));	&FR($a1);
+	 &add($l0,$cc,$l0);				### wait 8
+	&mul($a1,$word,($l1)=&NR(1));	&FR($a1);
+	 &cmpult($l0,$cc,$cc);				### wait 8
+	&muh($a2,$word,($h2)=&NR(1));	&FR($a2);
+	 &add($h0,$cc,$cc);	&FR($h0); 		### wait 8
+	&mul($a2,$word,($l2)=&NR(1));	&FR($a2);
+	 &add($l1,$cc,$l1);				### wait 8
+	&st($l0,&QWPw(0,$rp));		&FR($l0);
+	 &cmpult($l1,$cc,$cc);				### wait 8
+	&muh($a3,$word,($h3)=&NR(1));	&FR($a3);
+	 &add($h1,$cc,$cc);		&FR($h1);
+	&mul($a3,$word,($l3)=&NR(1));	&FR($a3);
+	 &add($l2,$cc,$l2);
+	&st($l1,&QWPw(1,$rp));		&FR($l1);
+	 &cmpult($l2,$cc,$cc);
+	&add($h2,$cc,$cc);		&FR($h2);
+	 &sub($count,4,$count);	# count-=4
+	&st($l2,&QWPw(2,$rp));		&FR($l2);
+	 &add($l3,$cc,$l3);
+	&cmpult($l3,$cc,$cc);
+	 &add($bp,4*$QWS,$bp);	# count+=4
+	&add($h3,$cc,$cc);		&FR($h3);
+	 &add($ap,4*$QWS,$ap);	# count+=4
+	&st($l3,&QWPw(3,$rp));		&FR($l3);
+	 &add($rp,4*$QWS,$rp);	# count+=4
+	###
+	 &blt($count,&label("finish"));
+	 ($a0)=&NR(1); &ld($a0,&QWPw(0,$ap));
+	&br(&label("finish"));
+##################################################
+
+##################################################
+	# Do the last 0..3 words
+
+	&set_label("last_loop");
+
+	&ld(($a0)=&NR(1),&QWPw(0,$ap));	# get a
+	 ###
+	###
+	 ###
+	&muh($a0,$word,($h0)=&NR(1));
+	 ### Wait 8 for next mul issue
+	&mul($a0,$word,($l0)=&NR(1)); &FR($a0)
+	 &add($ap,$QWS,$ap);
+	### Loose 12 until result is available
+	&add($rp,$QWS,$rp);
+	 &sub($count,1,$count);
+	&add($l0,$cc,$l0);
+	 ###
+	&st($l0,&QWPw(-1,$rp));		&FR($l0);
+	 &cmpult($l0,$cc,$cc);
+	&add($h0,$cc,$cc);		&FR($h0);
+	 &bgt($count,&label("last_loop"));
+	&function_end_A($name);
+
+######################################################
+	&set_label("finish");
+	&add($count,4,$count);
+	&bgt($count,&label("last_loop"));
+
+	&set_label("end");
+	&function_end($name);
+
+	&fin_pool;
+	}
+
+1;
diff --git a/crypto/bn/asm/alpha/mul_add.pl b/crypto/bn/asm/alpha/mul_add.pl
new file mode 100644
index 0000000..0d6df69
--- /dev/null
+++ b/crypto/bn/asm/alpha/mul_add.pl
@@ -0,0 +1,123 @@
+#!/usr/local/bin/perl
+# alpha assember 
+
+sub bn_mul_add_words
+	{
+	local($name)=@_;
+	local($cc,$a,$b,$r,$couny);
+
+	&init_pool(4);
+	($cc)=GR("r0");
+
+	$rp=&wparam(0);
+	$ap=&wparam(1);
+	$count=&wparam(2);
+	$word=&wparam(3);
+
+	&function_begin($name,"");
+
+	&comment("");
+	&sub($count,4,$count);
+	 &mov("zero",$cc);
+	###
+	 &blt($count,&label("finish"));
+
+	&ld(($a0)=&NR(1),&QWPw(0,$ap));
+
+$a=<<'EOF';
+##########################################################
+	&set_label("loop");
+
+	&ld(($r0)=&NR(1),&QWPw(0,$rp));
+	 &ld(($a1)=&NR(1),&QWPw(1,$ap));
+	&muh($a0,$word,($h0)=&NR(1));
+	 &ld(($r1)=&NR(1),&QWPw(1,$rp));
+	&ld(($a2)=&NR(1),&QWPw(2,$ap));
+	 ###
+	&mul($a0,$word,($l0)=&NR(1));	&FR($a0);
+	 &ld(($r2)=&NR(1),&QWPw(2,$rp));
+	&muh($a1,$word,($h1)=&NR(1));
+	 &ld(($a3)=&NR(1),&QWPw(3,$ap));
+	&mul($a1,$word,($l1)=&NR(1));	&FR($a1);
+	 &ld(($r3)=&NR(1),&QWPw(3,$rp));
+	&add($r0,$l0,$r0);
+	 &add($r1,$l1,$r1);
+	&cmpult($r0,$l0,($t0)=&NR(1));	&FR($l0);
+	 &cmpult($r1,$l1,($t1)=&NR(1));	&FR($l1);
+	&muh($a2,$word,($h2)=&NR(1));
+	 &add($r0,$cc,$r0);
+	&add($h0,$t0,$h0);		&FR($t0);
+	 &cmpult($r0,$cc,$cc);
+	&add($h1,$t1,$h1);		&FR($t1);
+	 &add($h0,$cc,$cc);		&FR($h0);
+	&mul($a2,$word,($l2)=&NR(1));	&FR($a2);
+	 &add($r1,$cc,$r1);
+	&cmpult($r1,$cc,$cc);
+	 &add($r2,$l2,$r2);
+	&add($h1,$cc,$cc);		&FR($h1);
+	 &cmpult($r2,$l2,($t2)=&NR(1));	&FR($l2);
+	&muh($a3,$word,($h3)=&NR(1));
+	 &add($r2,$cc,$r2);
+	&st($r0,&QWPw(0,$rp)); &FR($r0);
+	 &add($h2,$t2,$h2);		&FR($t2);
+	&st($r1,&QWPw(1,$rp)); &FR($r1);
+	 &cmpult($r2,$cc,$cc);
+	&mul($a3,$word,($l3)=&NR(1));	&FR($a3);
+	 &add($h2,$cc,$cc);		&FR($h2);
+	&st($r2,&QWPw(2,$rp)); &FR($r2);
+	 &sub($count,4,$count);	# count-=4
+	 &add($rp,4*$QWS,$rp);	# count+=4
+	&add($r3,$l3,$r3);
+	 &add($ap,4*$QWS,$ap);	# count+=4
+	&cmpult($r3,$l3,($t3)=&NR(1));	&FR($l3);
+	 &add($r3,$cc,$r3);
+	&add($h3,$t3,$h3);		&FR($t3);
+	 &cmpult($r3,$cc,$cc);
+	&st($r3,&QWPw(-1,$rp)); &FR($r3);
+	 &add($h3,$cc,$cc);		&FR($h3);
+
+	###
+	 &blt($count,&label("finish"));
+	&ld(($a0)=&NR(1),&QWPw(0,$ap));
+	 &br(&label("loop"));
+EOF
+##################################################
+	# Do the last 0..3 words
+
+	&set_label("last_loop");
+
+	&ld(($a0)=&NR(1),&QWPw(0,$ap));	# get a
+	 &ld(($r0)=&NR(1),&QWPw(0,$rp));	# get b
+	###
+	 ###
+	&muh($a0,$word,($h0)=&NR(1));	&FR($a0);
+	 ### wait 8
+	&mul($a0,$word,($l0)=&NR(1));	&FR($a0);
+	 &add($rp,$QWS,$rp);
+	&add($ap,$QWS,$ap);
+	 &sub($count,1,$count);
+	### wait 3 until l0 is available
+	&add($r0,$l0,$r0);
+	 ###
+	&cmpult($r0,$l0,($t0)=&NR(1));	&FR($l0);
+	 &add($r0,$cc,$r0);
+	&add($h0,$t0,$h0);		&FR($t0);
+	 &cmpult($r0,$cc,$cc);
+	&add($h0,$cc,$cc);		&FR($h0);
+
+	&st($r0,&QWPw(-1,$rp));		&FR($r0);
+	 &bgt($count,&label("last_loop"));
+	&function_end_A($name);
+
+######################################################
+	&set_label("finish");
+	&add($count,4,$count);
+	 &bgt($count,&label("last_loop"));
+
+	&set_label("end");
+	&function_end($name);
+
+	&fin_pool;
+	}
+
+1;
diff --git a/crypto/bn/asm/alpha/mul_c4.pl b/crypto/bn/asm/alpha/mul_c4.pl
new file mode 100644
index 0000000..9cc876d
--- /dev/null
+++ b/crypto/bn/asm/alpha/mul_c4.pl
@@ -0,0 +1,215 @@
+#!/usr/local/bin/perl
+# alpha assember 
+
+# upto
+
+sub mul_add_c
+	{
+	local($a,$b,$c0,$c1,$c2)=@_;
+	local($l1,$h1,$t1,$t2);
+
+	&mul($a,$b,($l1)=&NR(1));
+	&muh($a,$b,($h1)=&NR(1));
+	&add($c0,$l1,$c0);
+	&cmpult($c0,$l1,($t1)=&NR(1));	&FR($l1);
+	&add($t1,$h1,$h1);		&FR($t1);
+	&add($c1,$h1,$c1);
+	&cmpult($c1,$h1,($t2)=&NR(1));	&FR($h1);
+	&add($c2,$t2,$c2);		&FR($t2);
+	}
+
+sub bn_mul_comba4
+	{
+	local($name)=@_;
+	local(@a,@b,$r,$c0,$c1,$c2);
+
+	$cnt=1;
+	&init_pool(3);
+
+	$rp=&wparam(0);
+	$ap=&wparam(1);
+	$bp=&wparam(2);
+
+	&function_begin($name,"");
+
+	&comment("");
+
+	&ld(($a[0])=&NR(1),&QWPw(0,$ap));
+	&ld(($b[0])=&NR(1),&QWPw(0,$bp));
+	&ld(($a[1])=&NR(1),&QWPw(1,$ap));
+	&ld(($b[1])=&NR(1),&QWPw(1,$bp));
+	&mul($a[0],$b[0],($r00)=&NR(1));
+	&ld(($a[2])=&NR(1),&QWPw(2,$ap));
+	&ld(($b[2])=&NR(1),&QWPw(2,$bp));
+	&muh($a[0],$b[0],($r01)=&NR(1));
+	&FR($ap); &ld(($a[3])=&NR(1),&QWPw(3,$ap));
+	&FR($bp); &ld(($b[3])=&NR(1),&QWPw(3,$bp));
+	&mul($a[0],$b[1],($r02)=&NR(1));
+
+	($R,$H1,$H2)=&NR(3);
+
+	&st($r00,&QWPw(0,$rp));	&FR($r00);
+
+	&mov("zero",$R);
+	&mul($a[1],$b[0],($r03)=&NR(1));
+
+	&mov("zero",$H1);
+	&mov("zero",$H0);
+	 &add($R,$r01,$R);
+	&muh($a[0],$b[1],($r04)=&NR(1));
+	 &cmpult($R,$r01,($t01)=&NR(1));	&FR($r01);
+	 &add($R,$r02,$R);
+	 &add($H1,$t01,$H1)			&FR($t01);
+	&muh($a[1],$b[0],($r05)=&NR(1));
+	 &cmpult($R,$r02,($t02)=&NR(1));	&FR($r02);
+	 &add($R,$r03,$R);
+	 &add($H2,$t02,$H2)			&FR($t02);
+	&mul($a[0],$b[2],($r06)=&NR(1));
+	 &cmpult($R,$r03,($t03)=&NR(1));	&FR($r03);
+	 &add($H1,$t03,$H1)			&FR($t03);
+	&st($R,&QWPw(1,$rp));
+	&add($H1,$H2,$R);
+
+	&mov("zero",$H1);
+	 &add($R,$r04,$R);
+	&mov("zero",$H2);
+	&mul($a[1],$b[1],($r07)=&NR(1));
+	 &cmpult($R,$r04,($t04)=&NR(1));	&FR($r04);
+	 &add($R,$r05,$R);
+	 &add($H1,$t04,$H1)			&FR($t04);
+	&mul($a[2],$b[0],($r08)=&NR(1));
+	 &cmpult($R,$r05,($t05)=&NR(1));	&FR($r05);
+	 &add($R,$r01,$R);
+	 &add($H2,$t05,$H2)			&FR($t05);
+	&muh($a[0],$b[2],($r09)=&NR(1));
+	 &cmpult($R,$r06,($t06)=&NR(1));	&FR($r06);
+	 &add($R,$r07,$R);
+	 &add($H1,$t06,$H1)			&FR($t06);
+	&muh($a[1],$b[1],($r10)=&NR(1));
+	 &cmpult($R,$r07,($t07)=&NR(1));	&FR($r07);
+	 &add($R,$r08,$R);
+	 &add($H2,$t07,$H2)			&FR($t07);
+	&muh($a[2],$b[0],($r11)=&NR(1));
+	 &cmpult($R,$r08,($t08)=&NR(1));	&FR($r08);
+	 &add($H1,$t08,$H1)			&FR($t08);
+	&st($R,&QWPw(2,$rp));
+	&add($H1,$H2,$R);
+
+	&mov("zero",$H1);
+	 &add($R,$r09,$R);
+	&mov("zero",$H2);
+	&mul($a[0],$b[3],($r12)=&NR(1));
+	 &cmpult($R,$r09,($t09)=&NR(1));	&FR($r09);
+	 &add($R,$r10,$R);
+	 &add($H1,$t09,$H1)			&FR($t09);
+	&mul($a[1],$b[2],($r13)=&NR(1));
+	 &cmpult($R,$r10,($t10)=&NR(1));	&FR($r10);
+	 &add($R,$r11,$R);
+	 &add($H1,$t10,$H1)			&FR($t10);
+	&mul($a[2],$b[1],($r14)=&NR(1));
+	 &cmpult($R,$r11,($t11)=&NR(1));	&FR($r11);
+	 &add($R,$r12,$R);
+	 &add($H1,$t11,$H1)			&FR($t11);
+	&mul($a[3],$b[0],($r15)=&NR(1));
+	 &cmpult($R,$r12,($t12)=&NR(1));	&FR($r12);
+	 &add($R,$r13,$R);
+	 &add($H1,$t12,$H1)			&FR($t12);
+	&muh($a[0],$b[3],($r16)=&NR(1));
+	 &cmpult($R,$r13,($t13)=&NR(1));	&FR($r13);
+	 &add($R,$r14,$R);
+	 &add($H1,$t13,$H1)			&FR($t13);
+	&muh($a[1],$b[2],($r17)=&NR(1));
+	 &cmpult($R,$r14,($t14)=&NR(1));	&FR($r14);
+	 &add($R,$r15,$R);
+	 &add($H1,$t14,$H1)			&FR($t14);
+	&muh($a[2],$b[1],($r18)=&NR(1));
+	 &cmpult($R,$r15,($t15)=&NR(1));	&FR($r15);
+	 &add($H1,$t15,$H1)			&FR($t15);
+	&st($R,&QWPw(3,$rp));
+	&add($H1,$H2,$R);
+
+	&mov("zero",$H1);
+	 &add($R,$r16,$R);
+	&mov("zero",$H2);
+	&muh($a[3],$b[0],($r19)=&NR(1));
+	 &cmpult($R,$r16,($t16)=&NR(1));	&FR($r16);
+	 &add($R,$r17,$R);
+	 &add($H1,$t16,$H1)			&FR($t16);
+	&mul($a[1],$b[3],($r20)=&NR(1));
+	 &cmpult($R,$r17,($t17)=&NR(1));	&FR($r17);
+	 &add($R,$r18,$R);
+	 &add($H1,$t17,$H1)			&FR($t17);
+	&mul($a[2],$b[2],($r21)=&NR(1));
+	 &cmpult($R,$r18,($t18)=&NR(1));	&FR($r18);
+	 &add($R,$r19,$R);
+	 &add($H1,$t18,$H1)			&FR($t18);
+	&mul($a[3],$b[1],($r22)=&NR(1));
+	 &cmpult($R,$r19,($t19)=&NR(1));	&FR($r19);
+	 &add($R,$r20,$R);
+	 &add($H1,$t19,$H1)			&FR($t19);
+	&muh($a[1],$b[3],($r23)=&NR(1));
+	 &cmpult($R,$r20,($t20)=&NR(1));	&FR($r20);
+	 &add($R,$r21,$R);
+	 &add($H1,$t20,$H1)			&FR($t20);
+	&muh($a[2],$b[2],($r24)=&NR(1));
+	 &cmpult($R,$r21,($t21)=&NR(1));	&FR($r21);
+	 &add($R,$r22,$R);
+	 &add($H1,$t21,$H1)			&FR($t21);
+	&muh($a[3],$b[1],($r25)=&NR(1));
+	 &cmpult($R,$r22,($t22)=&NR(1));	&FR($r22);
+	 &add($H1,$t22,$H1)			&FR($t22);
+	&st($R,&QWPw(4,$rp));
+	&add($H1,$H2,$R);
+
+	&mov("zero",$H1);
+	 &add($R,$r23,$R);
+	&mov("zero",$H2);
+	&mul($a[2],$b[3],($r26)=&NR(1));
+	 &cmpult($R,$r23,($t23)=&NR(1));	&FR($r23);
+	 &add($R,$r24,$R);
+	 &add($H1,$t23,$H1)			&FR($t23);
+	&mul($a[3],$b[2],($r27)=&NR(1));
+	 &cmpult($R,$r24,($t24)=&NR(1));	&FR($r24);
+	 &add($R,$r25,$R);
+	 &add($H1,$t24,$H1)			&FR($t24);
+	&muh($a[2],$b[3],($r28)=&NR(1));
+	 &cmpult($R,$r25,($t25)=&NR(1));	&FR($r25);
+	 &add($R,$r26,$R);
+	 &add($H1,$t25,$H1)			&FR($t25);
+	&muh($a[3],$b[2],($r29)=&NR(1));
+	 &cmpult($R,$r26,($t26)=&NR(1));	&FR($r26);
+	 &add($R,$r27,$R);
+	 &add($H1,$t26,$H1)			&FR($t26);
+	&mul($a[3],$b[3],($r30)=&NR(1));
+	 &cmpult($R,$r27,($t27)=&NR(1));	&FR($r27);
+	 &add($H1,$t27,$H1)			&FR($t27);
+	&st($R,&QWPw(5,$rp));
+	&add($H1,$H2,$R);
+
+	&mov("zero",$H1);
+	 &add($R,$r28,$R);
+	&mov("zero",$H2);
+	&muh($a[3],$b[3],($r31)=&NR(1));
+	 &cmpult($R,$r28,($t28)=&NR(1));	&FR($r28);
+	 &add($R,$r29,$R);
+	 &add($H1,$t28,$H1)			&FR($t28);
+	############
+	 &cmpult($R,$r29,($t29)=&NR(1));	&FR($r29);
+	 &add($R,$r30,$R);
+	 &add($H1,$t29,$H1)			&FR($t29);
+        ############
+	 &cmpult($R,$r30,($t30)=&NR(1));	&FR($r30);
+	 &add($H1,$t30,$H1)			&FR($t30);
+	&st($R,&QWPw(6,$rp));
+	&add($H1,$H2,$R);
+
+	 &add($R,$r31,$R);			&FR($r31);
+	&st($R,&QWPw(7,$rp));
+
+	&FR($R,$H1,$H2);
+	&function_end($name);
+
+	&fin_pool;
+	}
+
+1;
diff --git a/crypto/bn/asm/alpha/mul_c4.works.pl b/crypto/bn/asm/alpha/mul_c4.works.pl
new file mode 100644
index 0000000..79d86dd
--- /dev/null
+++ b/crypto/bn/asm/alpha/mul_c4.works.pl
@@ -0,0 +1,98 @@
+#!/usr/local/bin/perl
+# alpha assember 
+
+sub mul_add_c
+	{
+	local($a,$b,$c0,$c1,$c2)=@_;
+	local($l1,$h1,$t1,$t2);
+
+print STDERR "count=$cnt\n"; $cnt++;
+	&mul($a,$b,($l1)=&NR(1));
+	&muh($a,$b,($h1)=&NR(1));
+	&add($c0,$l1,$c0);
+	&cmpult($c0,$l1,($t1)=&NR(1));	&FR($l1);
+	&add($t1,$h1,$h1);		&FR($t1);
+	&add($c1,$h1,$c1);
+	&cmpult($c1,$h1,($t2)=&NR(1));	&FR($h1);
+	&add($c2,$t2,$c2);		&FR($t2);
+	}
+
+sub bn_mul_comba4
+	{
+	local($name)=@_;
+	local(@a,@b,$r,$c0,$c1,$c2);
+
+	$cnt=1;
+	&init_pool(3);
+
+	$rp=&wparam(0);
+	$ap=&wparam(1);
+	$bp=&wparam(2);
+
+	&function_begin($name,"");
+
+	&comment("");
+
+	&ld(($a[0])=&NR(1),&QWPw(0,$ap));
+	&ld(($b[0])=&NR(1),&QWPw(0,$bp));
+	&ld(($a[1])=&NR(1),&QWPw(1,$ap));
+	&ld(($b[1])=&NR(1),&QWPw(1,$bp));
+	&ld(($a[2])=&NR(1),&QWPw(2,$ap));
+	&ld(($b[2])=&NR(1),&QWPw(2,$bp));
+	&ld(($a[3])=&NR(1),&QWPw(3,$ap));	&FR($ap);
+	&ld(($b[3])=&NR(1),&QWPw(3,$bp));	&FR($bp);
+
+	($c0,$c1,$c2)=&NR(3);
+	&mov("zero",$c2);
+	&mul($a[0],$b[0],$c0);
+	&muh($a[0],$b[0],$c1);
+	&st($c0,&QWPw(0,$rp));			&FR($c0); ($c0)=&NR($c0);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[0],$b[1],$c0,$c1,$c2);
+	&mul_add_c($a[1],$b[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(1,$rp));			&FR($c0); ($c0)=&NR($c0);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[1],$b[1],$c0,$c1,$c2);
+	&mul_add_c($a[0],$b[2],$c0,$c1,$c2);
+	&mul_add_c($a[2],$b[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(2,$rp));			&FR($c0); ($c0)=&NR($c0);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[0],$b[3],$c0,$c1,$c2);	&FR($a[0]);
+	&mul_add_c($a[1],$b[2],$c0,$c1,$c2);
+	&mul_add_c($a[2],$b[1],$c0,$c1,$c2);
+	&mul_add_c($a[3],$b[0],$c0,$c1,$c2);	&FR($b[0]);
+	&st($c0,&QWPw(3,$rp));			&FR($c0); ($c0)=&NR($c0);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[1],$b[3],$c0,$c1,$c2);	&FR($a[1]);
+	&mul_add_c($a[2],$b[2],$c0,$c1,$c2);
+	&mul_add_c($a[3],$b[1],$c0,$c1,$c2);	&FR($b[1]);
+	&st($c0,&QWPw(4,$rp));			&FR($c0); ($c0)=&NR($c0);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[2],$b[3],$c0,$c1,$c2);	&FR($a[2]);
+	&mul_add_c($a[3],$b[2],$c0,$c1,$c2);	&FR($b[2]);
+	&st($c0,&QWPw(5,$rp));			&FR($c0); ($c0)=&NR($c0);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[3],$b[3],$c0,$c1,$c2);	&FR($a[3],$b[3]);
+	&st($c0,&QWPw(6,$rp));
+	&st($c1,&QWPw(7,$rp));
+
+	&FR($c0,$c1,$c2);
+
+	&function_end($name);
+
+	&fin_pool;
+	}
+
+1;
diff --git a/crypto/bn/asm/alpha/mul_c8.pl b/crypto/bn/asm/alpha/mul_c8.pl
new file mode 100644
index 0000000..525ca74
--- /dev/null
+++ b/crypto/bn/asm/alpha/mul_c8.pl
@@ -0,0 +1,177 @@
+#!/usr/local/bin/perl
+# alpha assember 
+
+sub bn_mul_comba8
+	{
+	local($name)=@_;
+	local(@a,@b,$r,$c0,$c1,$c2);
+
+	$cnt=1;
+	&init_pool(3);
+
+	$rp=&wparam(0);
+	$ap=&wparam(1);
+	$bp=&wparam(2);
+
+	&function_begin($name,"");
+
+	&comment("");
+
+	&stack_push(2);
+	&ld(($a[0])=&NR(1),&QWPw(0,$ap));
+	&ld(($b[0])=&NR(1),&QWPw(0,$bp));
+	&st($reg_s0,&swtmp(0)); &FR($reg_s0);
+	&st($reg_s1,&swtmp(1)); &FR($reg_s1);
+	&ld(($a[1])=&NR(1),&QWPw(1,$ap));
+	&ld(($b[1])=&NR(1),&QWPw(1,$bp));
+	&ld(($a[2])=&NR(1),&QWPw(2,$ap));
+	&ld(($b[2])=&NR(1),&QWPw(2,$bp));
+	&ld(($a[3])=&NR(1),&QWPw(3,$ap));
+	&ld(($b[3])=&NR(1),&QWPw(3,$bp));
+	&ld(($a[4])=&NR(1),&QWPw(1,$ap));
+	&ld(($b[4])=&NR(1),&QWPw(1,$bp));
+	&ld(($a[5])=&NR(1),&QWPw(1,$ap));
+	&ld(($b[5])=&NR(1),&QWPw(1,$bp));
+	&ld(($a[6])=&NR(1),&QWPw(1,$ap));
+	&ld(($b[6])=&NR(1),&QWPw(1,$bp));
+	&ld(($a[7])=&NR(1),&QWPw(1,$ap));	&FR($ap);
+	&ld(($b[7])=&NR(1),&QWPw(1,$bp));	&FR($bp);
+
+	($c0,$c1,$c2)=&NR(3);
+	&mov("zero",$c2);
+	&mul($a[0],$b[0],$c0);
+	&muh($a[0],$b[0],$c1);
+	&st($c0,&QWPw(0,$rp));			&FR($c0); ($c0)=&NR(1);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[0],$b[1],$c0,$c1,$c2);
+	&mul_add_c($a[1],$b[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(1,$rp));			&FR($c0); ($c0)=&NR(1);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[0],$b[2],$c0,$c1,$c2);
+	&mul_add_c($a[1],$b[1],$c0,$c1,$c2);
+	&mul_add_c($a[2],$b[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(2,$rp));			&FR($c0); ($c0)=&NR(1);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[0],$b[3],$c0,$c1,$c2);
+	&mul_add_c($a[1],$b[2],$c0,$c1,$c2);
+	&mul_add_c($a[2],$b[1],$c0,$c1,$c2);
+	&mul_add_c($a[3],$b[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(3,$rp));			&FR($c0); ($c0)=&NR(1);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[0],$b[4],$c0,$c1,$c2);
+	&mul_add_c($a[1],$b[3],$c0,$c1,$c2);
+	&mul_add_c($a[2],$b[2],$c0,$c1,$c2);
+	&mul_add_c($a[3],$b[1],$c0,$c1,$c2);
+	&mul_add_c($a[4],$b[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(4,$rp));			&FR($c0); ($c0)=&NR(1);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[0],$b[5],$c0,$c1,$c2);
+	&mul_add_c($a[1],$b[4],$c0,$c1,$c2);
+	&mul_add_c($a[2],$b[3],$c0,$c1,$c2);
+	&mul_add_c($a[3],$b[2],$c0,$c1,$c2);
+	&mul_add_c($a[4],$b[1],$c0,$c1,$c2);
+	&mul_add_c($a[5],$b[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(5,$rp));			&FR($c0); ($c0)=&NR(1);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[0],$b[6],$c0,$c1,$c2);
+	&mul_add_c($a[1],$b[5],$c0,$c1,$c2);
+	&mul_add_c($a[2],$b[4],$c0,$c1,$c2);
+	&mul_add_c($a[3],$b[3],$c0,$c1,$c2);
+	&mul_add_c($a[4],$b[2],$c0,$c1,$c2);
+	&mul_add_c($a[5],$b[1],$c0,$c1,$c2);
+	&mul_add_c($a[6],$b[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(6,$rp));			&FR($c0); ($c0)=&NR(1);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[0],$b[7],$c0,$c1,$c2);	&FR($a[0]);
+	&mul_add_c($a[1],$b[6],$c0,$c1,$c2);
+	&mul_add_c($a[2],$b[5],$c0,$c1,$c2);
+	&mul_add_c($a[3],$b[4],$c0,$c1,$c2);
+	&mul_add_c($a[4],$b[3],$c0,$c1,$c2);
+	&mul_add_c($a[5],$b[2],$c0,$c1,$c2);
+	&mul_add_c($a[6],$b[1],$c0,$c1,$c2);
+	&mul_add_c($a[7],$b[0],$c0,$c1,$c2);	&FR($b[0]);
+	&st($c0,&QWPw(7,$rp));			&FR($c0); ($c0)=&NR(1);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[1],$b[7],$c0,$c1,$c2);	&FR($a[1]);
+	&mul_add_c($a[2],$b[6],$c0,$c1,$c2);
+	&mul_add_c($a[3],$b[5],$c0,$c1,$c2);
+	&mul_add_c($a[4],$b[4],$c0,$c1,$c2);
+	&mul_add_c($a[5],$b[3],$c0,$c1,$c2);
+	&mul_add_c($a[6],$b[2],$c0,$c1,$c2);
+	&mul_add_c($a[7],$b[1],$c0,$c1,$c2);	&FR($b[1]);
+	&st($c0,&QWPw(8,$rp));			&FR($c0); ($c0)=&NR(1);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[2],$b[7],$c0,$c1,$c2);	&FR($a[2]);
+	&mul_add_c($a[3],$b[6],$c0,$c1,$c2);
+	&mul_add_c($a[4],$b[5],$c0,$c1,$c2);
+	&mul_add_c($a[5],$b[4],$c0,$c1,$c2);
+	&mul_add_c($a[6],$b[3],$c0,$c1,$c2);
+	&mul_add_c($a[7],$b[2],$c0,$c1,$c2);	&FR($b[2]);
+	&st($c0,&QWPw(9,$rp));			&FR($c0); ($c0)=&NR(1);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[3],$b[7],$c0,$c1,$c2);	&FR($a[3]);
+	&mul_add_c($a[4],$b[6],$c0,$c1,$c2);
+	&mul_add_c($a[5],$b[5],$c0,$c1,$c2);
+	&mul_add_c($a[6],$b[4],$c0,$c1,$c2);
+	&mul_add_c($a[7],$b[3],$c0,$c1,$c2);	&FR($b[3]);
+	&st($c0,&QWPw(10,$rp));			&FR($c0); ($c0)=&NR(1);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[4],$b[7],$c0,$c1,$c2);	&FR($a[4]);
+	&mul_add_c($a[5],$b[6],$c0,$c1,$c2);
+	&mul_add_c($a[6],$b[5],$c0,$c1,$c2);
+	&mul_add_c($a[7],$b[4],$c0,$c1,$c2);	&FR($b[4]);
+	&st($c0,&QWPw(11,$rp));			&FR($c0); ($c0)=&NR(1);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[5],$b[7],$c0,$c1,$c2);	&FR($a[5]);
+	&mul_add_c($a[6],$b[6],$c0,$c1,$c2);
+	&mul_add_c($a[7],$b[5],$c0,$c1,$c2);	&FR($b[5]);
+	&st($c0,&QWPw(12,$rp));			&FR($c0); ($c0)=&NR(1);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[6],$b[7],$c0,$c1,$c2);	&FR($a[6]);
+	&mul_add_c($a[7],$b[6],$c0,$c1,$c2);	&FR($b[6]);
+	&st($c0,&QWPw(13,$rp));			&FR($c0); ($c0)=&NR(1);
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&mul_add_c($a[7],$b[7],$c0,$c1,$c2);	&FR($a[7],$b[7]);
+	&st($c0,&QWPw(14,$rp));
+	&st($c1,&QWPw(15,$rp));
+
+	&FR($c0,$c1,$c2);
+
+	&ld($reg_s0,&swtmp(0));
+	&ld($reg_s1,&swtmp(1));
+	&stack_pop(2);
+
+	&function_end($name);
+
+	&fin_pool;
+	}
+
+1;
diff --git a/crypto/bn/asm/alpha/sqr.pl b/crypto/bn/asm/alpha/sqr.pl
new file mode 100644
index 0000000..a55b696
--- /dev/null
+++ b/crypto/bn/asm/alpha/sqr.pl
@@ -0,0 +1,113 @@
+#!/usr/local/bin/perl
+# alpha assember 
+
+sub bn_sqr_words
+	{
+	local($name)=@_;
+	local($cc,$a,$b,$r,$couny);
+
+	&init_pool(3);
+	($cc)=GR("r0");
+
+	$rp=&wparam(0);
+	$ap=&wparam(1);
+	$count=&wparam(2);
+
+	&function_begin($name,"");
+
+	&comment("");
+	&sub($count,4,$count);
+	&mov("zero",$cc);
+	&br(&label("finish"));
+	&blt($count,&label("finish"));
+
+	($a0,$r0)=&NR(2);
+	&ld($a0,&QWPw(0,$ap));
+	&ld($r0,&QWPw(0,$rp));
+
+$a=<<'EOF';
+##########################################################
+	&set_label("loop");
+
+	($a1)=&NR(1); &ld($a1,&QWPw(1,$ap));
+	($b1)=&NR(1); &ld($b1,&QWPw(1,$bp));
+	($a2)=&NR(1); &ld($a2,&QWPw(2,$ap));
+	($b2)=&NR(1); &ld($b2,&QWPw(2,$bp));
+	($a3)=&NR(1); &ld($a3,&QWPw(3,$ap));
+	($b3)=&NR(1); &ld($b3,&QWPw(3,$bp));
+
+	($o0,$t0)=&NR(2);
+	&add($a0,$b0,$o0); 
+	&cmpult($o0,$b0,$t0);
+	&add($o0,$cc,$o0);
+	&cmpult($o0,$cc,$cc);
+	&add($cc,$t0,$cc);	&FR($t0);
+
+	($t1,$o1)=&NR(2);
+
+	&add($a1,$b1,$o1);	&FR($a1);
+	&cmpult($o1,$b1,$t1);	&FR($b1);
+	&add($o1,$cc,$o1);
+	&cmpult($o1,$cc,$cc);
+	&add($cc,$t1,$cc);	&FR($t1);
+
+	($t2,$o2)=&NR(2);
+
+	&add($a2,$b2,$o2);	&FR($a2);
+	&cmpult($o2,$b2,$t2);	&FR($b2);
+	&add($o2,$cc,$o2);
+	&cmpult($o2,$cc,$cc);
+	&add($cc,$t2,$cc);	&FR($t2);
+
+	($t3,$o3)=&NR(2);
+
+	&add($a3,$b3,$o3);	&FR($a3);
+	&cmpult($o3,$b3,$t3);	&FR($b3);
+	&add($o3,$cc,$o3);
+	&cmpult($o3,$cc,$cc);
+	&add($cc,$t3,$cc);	&FR($t3);
+
+	&st($o0,&QWPw(0,$rp)); &FR($o0);
+	&st($o1,&QWPw(0,$rp)); &FR($o1);
+	&st($o2,&QWPw(0,$rp)); &FR($o2);
+	&st($o3,&QWPw(0,$rp)); &FR($o3);
+
+	&sub($count,4,$count);	# count-=4
+	&add($ap,4*$QWS,$ap);	# count+=4
+	&add($bp,4*$QWS,$bp);	# count+=4
+	&add($rp,4*$QWS,$rp);	# count+=4
+
+	&blt($count,&label("finish"));
+	&ld($a0,&QWPw(0,$ap));
+	 &ld($b0,&QWPw(0,$bp));
+	&br(&label("loop"));
+EOF
+##################################################
+	# Do the last 0..3 words
+
+	&set_label("last_loop");
+
+	&ld(($a0)=&NR(1),&QWPw(0,$ap));	# get a
+	&mul($a0,$a0,($l0)=&NR(1));
+	 &add($ap,$QWS,$ap);
+	 &add($rp,2*$QWS,$rp);
+	 &sub($count,1,$count);
+	&muh($a0,$a0,($h0)=&NR(1));	&FR($a0);
+	&st($l0,&QWPw(-2,$rp));		&FR($l0);
+	&st($h0,&QWPw(-1,$rp));		&FR($h0);
+
+	&bgt($count,&label("last_loop"));
+	&function_end_A($name);
+
+######################################################
+	&set_label("finish");
+	&add($count,4,$count);
+	&bgt($count,&label("last_loop"));
+
+	&set_label("end");
+	&function_end($name);
+
+	&fin_pool;
+	}
+
+1;
diff --git a/crypto/bn/asm/alpha/sqr_c4.pl b/crypto/bn/asm/alpha/sqr_c4.pl
new file mode 100644
index 0000000..bf33f5b
--- /dev/null
+++ b/crypto/bn/asm/alpha/sqr_c4.pl
@@ -0,0 +1,109 @@
+#!/usr/local/bin/perl
+# alpha assember 
+
+sub sqr_add_c
+	{
+	local($a,$c0,$c1,$c2)=@_;
+	local($l1,$h1,$t1,$t2);
+
+	&mul($a,$a,($l1)=&NR(1));
+	&muh($a,$a,($h1)=&NR(1));
+	&add($c0,$l1,$c0);
+	&add($c1,$h1,$c1);
+	&cmpult($c0,$l1,($t1)=&NR(1));	&FR($l1);
+	&cmpult($c1,$h1,($t2)=&NR(1));	&FR($h1);
+	&add($c1,$t1,$c1);		&FR($t1);
+	&add($c2,$t2,$c2);		&FR($t2);
+	}
+
+sub sqr_add_c2
+	{
+	local($a,$b,$c0,$c1,$c2)=@_;
+	local($l1,$h1,$t1,$t2);
+
+	&mul($a,$b,($l1)=&NR(1));
+	&muh($a,$b,($h1)=&NR(1));
+	&cmplt($l1,"zero",($lc1)=&NR(1));
+	&cmplt($h1,"zero",($hc1)=&NR(1));
+	&add($l1,$l1,$l1);
+	&add($h1,$h1,$h1);
+	&add($h1,$lc1,$h1);		&FR($lc1);
+	&add($c2,$hc1,$c2);		&FR($hc1);
+
+	&add($c0,$l1,$c0);
+	&add($c1,$h1,$c1);
+	&cmpult($c0,$l1,($lc1)=&NR(1));	&FR($l1);
+	&cmpult($c1,$h1,($hc1)=&NR(1));	&FR($h1);
+
+	&add($c1,$lc1,$c1);		&FR($lc1);
+	&add($c2,$hc1,$c2);		&FR($hc1);
+	}
+
+
+sub bn_sqr_comba4
+	{
+	local($name)=@_;
+	local(@a,@b,$r,$c0,$c1,$c2);
+
+	$cnt=1;
+	&init_pool(2);
+
+	$rp=&wparam(0);
+	$ap=&wparam(1);
+
+	&function_begin($name,"");
+
+	&comment("");
+
+	&ld(($a[0])=&NR(1),&QWPw(0,$ap));
+	&ld(($a[1])=&NR(1),&QWPw(1,$ap));
+	&ld(($a[2])=&NR(1),&QWPw(2,$ap));
+        &ld(($a[3])=&NR(1),&QWPw(3,$ap)); &FR($ap);
+
+	($c0,$c1,$c2)=&NR(3);
+
+	&mov("zero",$c2);
+	&mul($a[0],$a[0],$c0);
+	&muh($a[0],$a[0],$c1);
+	&st($c0,&QWPw(0,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c2($a[0],$a[1],$c0,$c1,$c2);
+	&st($c0,&QWPw(1,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c($a[1],$c0,$c1,$c2);
+	&sqr_add_c2($a[2],$a[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(2,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c2($a[3],$a[0],$c0,$c1,$c2);
+	&sqr_add_c2($a[2],$a[1],$c0,$c1,$c2);
+	&st($c0,&QWPw(3,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c($a[2],$c0,$c1,$c2);
+	&sqr_add_c2($a[3],$a[1],$c0,$c1,$c2);
+	&st($c0,&QWPw(4,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c2($a[3],$a[2],$c0,$c1,$c2);
+	&st($c0,&QWPw(5,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c($a[3],$c0,$c1,$c2);
+	&st($c0,&QWPw(6,$rp));
+	&st($c1,&QWPw(7,$rp));
+
+	&function_end($name);
+
+	&fin_pool;
+	}
+
+1;
diff --git a/crypto/bn/asm/alpha/sqr_c8.pl b/crypto/bn/asm/alpha/sqr_c8.pl
new file mode 100644
index 0000000..b4afe08
--- /dev/null
+++ b/crypto/bn/asm/alpha/sqr_c8.pl
@@ -0,0 +1,132 @@
+#!/usr/local/bin/perl
+# alpha assember 
+
+sub bn_sqr_comba8
+	{
+	local($name)=@_;
+	local(@a,@b,$r,$c0,$c1,$c2);
+
+	$cnt=1;
+	&init_pool(2);
+
+	$rp=&wparam(0);
+	$ap=&wparam(1);
+
+	&function_begin($name,"");
+
+	&comment("");
+
+	&ld(($a[0])=&NR(1),&QWPw(0,$ap));
+	&ld(($a[1])=&NR(1),&QWPw(1,$ap));
+	&ld(($a[2])=&NR(1),&QWPw(2,$ap));
+	&ld(($a[3])=&NR(1),&QWPw(3,$ap));
+	&ld(($a[4])=&NR(1),&QWPw(4,$ap));
+	&ld(($a[5])=&NR(1),&QWPw(5,$ap));
+	&ld(($a[6])=&NR(1),&QWPw(6,$ap));
+        &ld(($a[7])=&NR(1),&QWPw(7,$ap)); &FR($ap);
+
+	($c0,$c1,$c2)=&NR(3);
+
+	&mov("zero",$c2);
+	&mul($a[0],$a[0],$c0);
+	&muh($a[0],$a[0],$c1);
+	&st($c0,&QWPw(0,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c2($a[1],$a[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(1,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c($a[1],$c0,$c1,$c2);
+	&sqr_add_c2($a[2],$a[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(2,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c2($a[2],$a[1],$c0,$c1,$c2);
+	&sqr_add_c2($a[3],$a[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(3,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c($a[2],$c0,$c1,$c2);
+	&sqr_add_c2($a[3],$a[1],$c0,$c1,$c2);
+	&sqr_add_c2($a[4],$a[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(4,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c2($a[3],$a[2],$c0,$c1,$c2);
+	&sqr_add_c2($a[4],$a[1],$c0,$c1,$c2);
+	&sqr_add_c2($a[5],$a[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(5,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c($a[3],$c0,$c1,$c2);
+	&sqr_add_c2($a[4],$a[2],$c0,$c1,$c2);
+	&sqr_add_c2($a[5],$a[1],$c0,$c1,$c2);
+	&sqr_add_c2($a[6],$a[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(6,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c2($a[4],$a[3],$c0,$c1,$c2);
+	&sqr_add_c2($a[5],$a[2],$c0,$c1,$c2);
+	&sqr_add_c2($a[6],$a[1],$c0,$c1,$c2);
+	&sqr_add_c2($a[7],$a[0],$c0,$c1,$c2);
+	&st($c0,&QWPw(7,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c($a[4],$c0,$c1,$c2);
+	&sqr_add_c2($a[5],$a[3],$c0,$c1,$c2);
+	&sqr_add_c2($a[6],$a[2],$c0,$c1,$c2);
+	&sqr_add_c2($a[7],$a[1],$c0,$c1,$c2);
+	&st($c0,&QWPw(8,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c2($a[5],$a[4],$c0,$c1,$c2);
+	&sqr_add_c2($a[6],$a[3],$c0,$c1,$c2);
+	&sqr_add_c2($a[7],$a[2],$c0,$c1,$c2);
+	&st($c0,&QWPw(9,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c($a[5],$c0,$c1,$c2);
+	&sqr_add_c2($a[6],$a[4],$c0,$c1,$c2);
+	&sqr_add_c2($a[7],$a[3],$c0,$c1,$c2);
+	&st($c0,&QWPw(10,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c2($a[6],$a[5],$c0,$c1,$c2);
+	&sqr_add_c2($a[7],$a[4],$c0,$c1,$c2);
+	&st($c0,&QWPw(11,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c($a[6],$c0,$c1,$c2);
+	&sqr_add_c2($a[7],$a[5],$c0,$c1,$c2);
+	&st($c0,&QWPw(12,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c2($a[7],$a[6],$c0,$c1,$c2);
+	&st($c0,&QWPw(13,$rp));
+	($c0,$c1,$c2)=($c1,$c2,$c0);
+	&mov("zero",$c2);
+
+	&sqr_add_c($a[7],$c0,$c1,$c2);
+	&st($c0,&QWPw(14,$rp));
+	&st($c1,&QWPw(15,$rp));
+
+	&function_end($name);
+
+	&fin_pool;
+	}
+
+1;
diff --git a/crypto/bn/asm/alpha/sub.pl b/crypto/bn/asm/alpha/sub.pl
new file mode 100644
index 0000000..d998da5
--- /dev/null
+++ b/crypto/bn/asm/alpha/sub.pl
@@ -0,0 +1,108 @@
+#!/usr/local/bin/perl
+# alpha assember
+
+sub bn_sub_words
+	{
+	local($name)=@_;
+	local($cc,$a,$b,$r);
+
+	&init_pool(4);
+	($cc)=GR("r0");
+
+	$rp=&wparam(0);
+	$ap=&wparam(1);
+	$bp=&wparam(2);
+	$count=&wparam(3);
+
+	&function_begin($name,"");
+
+	&comment("");
+	&sub($count,4,$count);
+	&mov("zero",$cc);
+	&blt($count,&label("finish"));
+
+	($a0,$b0)=&NR(2);
+	&ld($a0,&QWPw(0,$ap));
+	&ld($b0,&QWPw(0,$bp));
+
+##########################################################
+	&set_label("loop");
+
+	($a1,$tmp,$b1,$a2,$b2,$a3,$b3,$o0)=&NR(8);
+	&ld($a1,&QWPw(1,$ap));
+	 &cmpult($a0,$b0,$tmp);	# will we borrow?
+	&ld($b1,&QWPw(1,$bp));
+	 &sub($a0,$b0,$a0);		# do the subtract
+	&ld($a2,&QWPw(2,$ap));
+	 &cmpult($a0,$cc,$b0);	# will we borrow?
+	&ld($b2,&QWPw(2,$bp));
+	 &sub($a0,$cc,$o0);	# will we borrow?
+	&ld($a3,&QWPw(3,$ap));
+	 &add($b0,$tmp,$cc); ($t1,$o1)=&NR(2); &FR($tmp);
+
+	&cmpult($a1,$b1,$t1);	# will we borrow?
+	 &sub($a1,$b1,$a1);	# do the subtract
+	&ld($b3,&QWPw(3,$bp));
+	 &cmpult($a1,$cc,$b1);	# will we borrow?
+	&sub($a1,$cc,$o1);	# will we borrow?
+	 &add($b1,$t1,$cc); ($tmp,$o2)=&NR(2); &FR($t1,$a1,$b1);
+	
+	&cmpult($a2,$b2,$tmp);	# will we borrow?
+	 &sub($a2,$b2,$a2);		# do the subtract
+	&st($o0,&QWPw(0,$rp));	&FR($o0); # save
+	 &cmpult($a2,$cc,$b2);	# will we borrow?
+	&sub($a2,$cc,$o2);	# will we borrow?
+	 &add($b2,$tmp,$cc); ($t3,$o3)=&NR(2); &FR($tmp,$a2,$b2);
+
+	&cmpult($a3,$b3,$t3);	# will we borrow?
+	 &sub($a3,$b3,$a3);	# do the subtract
+	&st($o1,&QWPw(1,$rp)); &FR($o1);
+	 &cmpult($a3,$cc,$b3);	# will we borrow?
+	&sub($a3,$cc,$o3);	# will we borrow?
+	 &add($b3,$t3,$cc); &FR($t3,$a3,$b3);
+
+	&st($o2,&QWPw(2,$rp));	&FR($o2);
+	 &sub($count,4,$count);	# count-=4
+	&st($o3,&QWPw(3,$rp));	&FR($o3);
+	 &add($ap,4*$QWS,$ap);	# count+=4
+	&add($bp,4*$QWS,$bp);	# count+=4
+	 &add($rp,4*$QWS,$rp);	# count+=4
+
+	&blt($count,&label("finish"));
+	&ld($a0,&QWPw(0,$ap));
+	 &ld($b0,&QWPw(0,$bp));
+	&br(&label("loop"));
+##################################################
+	# Do the last 0..3 words
+
+	&set_label("last_loop");
+
+	&ld($a0,&QWPw(0,$ap));	# get a
+	 &ld($b0,&QWPw(0,$bp));	# get b
+	&cmpult($a0,$b0,$tmp);	# will we borrow?
+	&sub($a0,$b0,$a0);	# do the subtract
+	&cmpult($a0,$cc,$b0);	# will we borrow?
+	&sub($a0,$cc,$a0);	# will we borrow?
+	&st($a0,&QWPw(0,$rp));	# save
+	&add($b0,$tmp,$cc);	# add the borrows
+
+	&add($ap,$QWS,$ap);
+	&add($bp,$QWS,$bp);
+	&add($rp,$QWS,$rp);
+	&sub($count,1,$count);
+	&bgt($count,&label("last_loop"));
+	&function_end_A($name);
+
+######################################################
+	&set_label("finish");
+	&add($count,4,$count);
+	&bgt($count,&label("last_loop"));
+
+	&FR($a0,$b0);
+	&set_label("end");
+	&function_end($name);
+
+	&fin_pool;
+	}
+
+1;
diff --git a/crypto/bn/asm/bn-586.pl b/crypto/bn/asm/bn-586.pl
index 128f0f2..7a03c67 100644
--- a/crypto/bn/asm/bn-586.pl
+++ b/crypto/bn/asm/bn-586.pl
@@ -1,7 +1,4 @@
 #!/usr/local/bin/perl
-#
-
-#!/usr/local/bin/perl
 
 push(@INC,"perlasm","../../perlasm");
 require "x86asm.pl";
@@ -11,8 +8,9 @@
 &bn_mul_add_words("bn_mul_add_words");
 &bn_mul_words("bn_mul_words");
 &bn_sqr_words("bn_sqr_words");
-&bn_div64("bn_div64");
+&bn_div_words("bn_div_words");
 &bn_add_words("bn_add_words");
+&bn_sub_words("bn_sub_words");
 
 &asm_finish();
 
@@ -228,7 +226,7 @@
 	&function_end($name);
 	}
 
-sub bn_div64
+sub bn_div_words
 	{
 	local($name)=@_;
 
@@ -307,7 +305,79 @@
 		}
 	&set_label("aw_end",0);
 
-	&mov("eax",$c);
+#	&mov("eax",$c);		# $c is "eax"
+
+	&function_end($name);
+	}
+
+sub bn_sub_words
+	{
+	local($name)=@_;
+
+	&function_begin($name,"");
+
+	&comment("");
+	$a="esi";
+	$b="edi";
+	$c="eax";
+	$r="ebx";
+	$tmp1="ecx";
+	$tmp2="edx";
+	$num="ebp";
+
+	&mov($r,&wparam(0));	# get r
+	 &mov($a,&wparam(1));	# get a
+	&mov($b,&wparam(2));	# get b
+	 &mov($num,&wparam(3));	# get num
+	&xor($c,$c);		# clear carry
+	 &and($num,0xfffffff8);	# num / 8
+
+	&jz(&label("aw_finish"));
+
+	&set_label("aw_loop",0);
+	for ($i=0; $i<8; $i++)
+		{
+		&comment("Round $i");
+
+		&mov($tmp1,&DWP($i*4,$a,"",0)); 	# *a
+		 &mov($tmp2,&DWP($i*4,$b,"",0)); 	# *b
+		&sub($tmp1,$c);
+		 &mov($c,0);
+		&adc($c,$c);
+		 &sub($tmp1,$tmp2);
+		&adc($c,0);
+		 &mov(&DWP($i*4,$r,"",0),$tmp1); 	# *r
+		}
+
+	&comment("");
+	&add($a,32);
+	 &add($b,32);
+	&add($r,32);
+	 &sub($num,8);
+	&jnz(&label("aw_loop"));
+
+	&set_label("aw_finish",0);
+	&mov($num,&wparam(3));	# get num
+	&and($num,7);
+	 &jz(&label("aw_end"));
+
+	for ($i=0; $i<7; $i++)
+		{
+		&comment("Tail Round $i");
+		&mov($tmp1,&DWP($i*4,$a,"",0));	# *a
+		 &mov($tmp2,&DWP($i*4,$b,"",0));# *b
+		&sub($tmp1,$c);
+		 &mov($c,0);
+		&adc($c,$c);
+		 &sub($tmp1,$tmp2);
+		&adc($c,0);
+		 &dec($num) if ($i != 6);
+		&mov(&DWP($i*4,$r,"",0),$tmp1);	# *a
+		 &jz(&label("aw_end")) if ($i != 6);
+		}
+	&set_label("aw_end",0);
+
+#	&mov("eax",$c);		# $c is "eax"
 
 	&function_end($name);
 	}
diff --git a/crypto/bn/asm/bn-alpha.pl b/crypto/bn/asm/bn-alpha.pl
new file mode 100644
index 0000000..302edf2
--- /dev/null
+++ b/crypto/bn/asm/bn-alpha.pl
@@ -0,0 +1,571 @@
+#!/usr/local/bin/perl
+# I have this in perl so I can use more usefull register names and then convert
+# them into alpha registers.
+#
+
+$d=&data();
+$d =~ s/CC/0/g;
+$d =~ s/R1/1/g;
+$d =~ s/R2/2/g;
+$d =~ s/R3/3/g;
+$d =~ s/R4/4/g;
+$d =~ s/L1/5/g;
+$d =~ s/L2/6/g;
+$d =~ s/L3/7/g;
+$d =~ s/L4/8/g;
+$d =~ s/O1/22/g;
+$d =~ s/O2/23/g;
+$d =~ s/O3/24/g;
+$d =~ s/O4/25/g;
+$d =~ s/A1/20/g;
+$d =~ s/A2/21/g;
+$d =~ s/A3/27/g;
+$d =~ s/A4/28/g;
+if (0){
+}
+
+print $d;
+
+sub data
+	{
+	local($data)=<<'EOF';
+
+ # DEC Alpha assember
+ # The bn_div_words is actually gcc output but the other parts are hand done.
+ # Thanks to tzeruch@ceddec.com for sending me the gcc output for
+ # bn_div_words.
+ # I've gone back and re-done most of routines.
+ # The key thing to remeber for the 164 CPU is that while a
+ # multiply operation takes 8 cycles, another one can only be issued
+ # after 4 cycles have elapsed.  I've done modification to help
+ # improve this.  Also, normally, a ld instruction will not be available
+ # for about 3 cycles.
+	.file	1 "bn_asm.c"
+	.set noat
+gcc2_compiled.:
+__gnu_compiled_c:
+	.text
+	.align 3
+	.globl bn_mul_add_words
+	.ent bn_mul_add_words
+bn_mul_add_words:
+bn_mul_add_words..ng:
+	.frame $30,0,$26,0
+	.prologue 0
+	.align 5
+	subq	$18,4,$18
+	bis	$31,$31,$CC
+	blt	$18,$43		# if we are -1, -2, -3 or -4 goto tail code
+	ldq	$A1,0($17)	# 1 1
+	ldq	$R1,0($16)	# 1 1
+	.align 3
+$42:
+	mulq	$A1,$19,$L1	# 1 2 1	######
+	ldq	$A2,8($17)	# 2 1
+	ldq	$R2,8($16)	# 2 1
+	umulh	$A1,$19,$A1	# 1 2	######
+	ldq	$A3,16($17)	# 3 1
+	ldq	$R3,16($16)	# 3 1
+	mulq	$A2,$19,$L2	# 2 2 1	######
+	 ldq	$A4,24($17)	# 4 1
+	addq	$R1,$L1,$R1	# 1 2 2
+	 ldq	$R4,24($16)	# 4 1
+	umulh	$A2,$19,$A2	# 2 2	######
+	 cmpult	$R1,$L1,$O1	# 1 2 3 1
+	addq	$A1,$O1,$A1	# 1 3 1
+	 addq	$R1,$CC,$R1	# 1 2 3 1
+	mulq	$A3,$19,$L3	# 3 2 1	######
+	 cmpult	$R1,$CC,$CC	# 1 2 3 2
+	addq	$R2,$L2,$R2	# 2 2 2
+	 addq	$A1,$CC,$CC	# 1 3 2 
+	cmpult	$R2,$L2,$O2	# 2 2 3 1
+	 addq	$A2,$O2,$A2	# 2 3 1
+	umulh	$A3,$19,$A3	# 3 2	######
+	 addq	$R2,$CC,$R2	# 2 2 3 1
+	cmpult	$R2,$CC,$CC	# 2 2 3 2
+	 subq	$18,4,$18
+	mulq	$A4,$19,$L4	# 4 2 1	######
+	 addq	$A2,$CC,$CC	# 2 3 2 
+	addq	$R3,$L3,$R3	# 3 2 2
+	 addq	$16,32,$16
+	cmpult	$R3,$L3,$O3	# 3 2 3 1
+	 stq	$R1,-32($16)	# 1 2 4
+	umulh	$A4,$19,$A4	# 4 2	######
+	 addq	$A3,$O3,$A3	# 3 3 1
+	addq	$R3,$CC,$R3	# 3 2 3 1
+	 stq	$R2,-24($16)	# 2 2 4
+	cmpult	$R3,$CC,$CC	# 3 2 3 2
+	 stq	$R3,-16($16)	# 3 2 4
+	addq	$R4,$L4,$R4	# 4 2 2
+	 addq	$A3,$CC,$CC	# 3 3 2 
+	cmpult	$R4,$L4,$O4	# 4 2 3 1
+	 addq	$17,32,$17
+	addq	$A4,$O4,$A4	# 4 3 1
+	 addq	$R4,$CC,$R4	# 4 2 3 1
+	cmpult	$R4,$CC,$CC	# 4 2 3 2
+	 stq	$R4,-8($16)	# 4 2 4
+	addq	$A4,$CC,$CC	# 4 3 2 
+	 blt	$18,$43
+
+	ldq	$A1,0($17)	# 1 1
+	ldq	$R1,0($16)	# 1 1
+
+	br	$42
+
+	.align 4
+$45:
+	ldq	$A1,0($17)	# 4 1
+	ldq	$R1,0($16)	# 4 1
+	mulq	$A1,$19,$L1	# 4 2 1
+	subq	$18,1,$18
+	addq	$16,8,$16
+	addq	$17,8,$17
+	umulh	$A1,$19,$A1	# 4 2
+	addq	$R1,$L1,$R1	# 4 2 2
+	cmpult	$R1,$L1,$O1	# 4 2 3 1
+	addq	$A1,$O1,$A1	# 4 3 1
+	addq	$R1,$CC,$R1	# 4 2 3 1
+	cmpult	$R1,$CC,$CC	# 4 2 3 2
+	addq	$A1,$CC,$CC	# 4 3 2 
+	stq	$R1,-8($16)	# 4 2 4
+	bgt	$18,$45
+	ret	$31,($26),1	# else exit
+
+	.align 4
+$43:
+	addq	$18,4,$18
+	bgt	$18,$45		# goto tail code
+	ret	$31,($26),1	# else exit
+
+	.end bn_mul_add_words
+	.align 3
+	.globl bn_mul_words
+	.ent bn_mul_words
+bn_mul_words:
+bn_mul_words..ng:
+	.frame $30,0,$26,0
+	.prologue 0
+	.align 5
+	subq	$18,4,$18
+	bis	$31,$31,$CC
+	blt	$18,$143	# if we are -1, -2, -3 or -4 goto tail code
+	ldq	$A1,0($17)	# 1 1
+	.align 3
+$142:
+
+	mulq	$A1,$19,$L1	# 1 2 1	#####
+	 ldq	$A2,8($17)	# 2 1
+	 ldq	$A3,16($17)	# 3 1
+	umulh	$A1,$19,$A1	# 1 2	#####
+	 ldq	$A4,24($17)	# 4 1
+	mulq	$A2,$19,$L2	# 2 2 1	#####
+	 addq	$L1,$CC,$L1	# 1 2 3 1
+	subq	$18,4,$18
+	 cmpult	$L1,$CC,$CC	# 1 2 3 2
+	umulh	$A2,$19,$A2	# 2 2	#####
+	 addq	$A1,$CC,$CC	# 1 3 2 
+	addq	$17,32,$17
+	 addq	$L2,$CC,$L2	# 2 2 3 1
+	mulq	$A3,$19,$L3	# 3 2 1	#####
+	 cmpult	$L2,$CC,$CC	# 2 2 3 2
+	addq	$A2,$CC,$CC	# 2 3 2 
+	 addq	$16,32,$16
+	umulh	$A3,$19,$A3	# 3 2	#####
+	 stq	$L1,-32($16)	# 1 2 4
+	mulq	$A4,$19,$L4	# 4 2 1	#####
+	 addq	$L3,$CC,$L3	# 3 2 3 1
+	stq	$L2,-24($16)	# 2 2 4
+	 cmpult	$L3,$CC,$CC	# 3 2 3 2
+	umulh	$A4,$19,$A4	# 4 2	#####
+	 addq	$A3,$CC,$CC	# 3 3 2 
+	stq	$L3,-16($16)	# 3 2 4
+	 addq	$L4,$CC,$L4	# 4 2 3 1
+	cmpult	$L4,$CC,$CC	# 4 2 3 2
+
+	addq	$A4,$CC,$CC	# 4 3 2 
+
+	stq	$L4,-8($16)	# 4 2 4
+
+	blt	$18,$143
+
+	ldq	$A1,0($17)	# 1 1
+
+	br	$142
+
+	.align 4
+$145:
+	ldq	$A1,0($17)	# 4 1
+	mulq	$A1,$19,$L1	# 4 2 1
+	subq	$18,1,$18
+	umulh	$A1,$19,$A1	# 4 2
+	addq	$L1,$CC,$L1	# 4 2 3 1
+	 addq	$16,8,$16
+	cmpult	$L1,$CC,$CC	# 4 2 3 2
+	 addq	$17,8,$17
+	addq	$A1,$CC,$CC	# 4 3 2 
+	stq	$L1,-8($16)	# 4 2 4
+
+	bgt	$18,$145
+	ret	$31,($26),1	# else exit
+
+	.align 4
+$143:
+	addq	$18,4,$18
+	bgt	$18,$145	# goto tail code
+	ret	$31,($26),1	# else exit
+
+	.end bn_mul_words
+	.align 3
+	.globl bn_sqr_words
+	.ent bn_sqr_words
+bn_sqr_words:
+bn_sqr_words..ng:
+	.frame $30,0,$26,0
+	.prologue 0
+
+	subq	$18,4,$18
+	blt	$18,$543	# if we are -1, -2, -3 or -4 goto tail code
+	ldq	$A1,0($17)	# 1 1
+	.align 3
+$542:
+	mulq	$A1,$A1,$L1		######
+	 ldq	$A2,8($17)	# 1 1
+	subq	$18,4
+ 	umulh	$A1,$A1,$R1		######
+	ldq	$A3,16($17)	# 1 1
+	mulq	$A2,$A2,$L2		######
+	ldq	$A4,24($17)	# 1 1
+	stq	$L1,0($16)	# r[0]
+ 	umulh	$A2,$A2,$R2		######
+	stq	$R1,8($16)	# r[1]
+	mulq	$A3,$A3,$L3		######
+	stq	$L2,16($16)	# r[0]
+ 	umulh	$A3,$A3,$R3		######
+	stq	$R2,24($16)	# r[1]
+	mulq	$A4,$A4,$L4		######
+	stq	$L3,32($16)	# r[0]
+ 	umulh	$A4,$A4,$R4		######
+	stq	$R3,40($16)	# r[1]
+
+ 	addq	$16,64,$16
+ 	addq	$17,32,$17
+	stq	$L4,-16($16)	# r[0]
+	stq	$R4,-8($16)	# r[1]
+
+	blt	$18,$543
+	ldq	$A1,0($17)	# 1 1
+ 	br 	$542
+
+$442:
+	ldq	$A1,0($17)   # a[0]
+	mulq	$A1,$A1,$L1  # a[0]*w low part       r2
+	addq	$16,16,$16
+	addq	$17,8,$17
+	subq	$18,1,$18
+        umulh	$A1,$A1,$R1  # a[0]*w high part       r3
+	stq	$L1,-16($16)   # r[0]
+        stq	$R1,-8($16)   # r[1]
+
+	bgt	$18,$442
+	ret	$31,($26),1	# else exit
+
+	.align 4
+$543:
+	addq	$18,4,$18
+	bgt	$18,$442	# goto tail code
+	ret	$31,($26),1	# else exit
+	.end bn_sqr_words
+
+	.align 3
+	.globl bn_add_words
+	.ent bn_add_words
+bn_add_words:
+bn_add_words..ng:
+	.frame $30,0,$26,0
+	.prologue 0
+
+	subq	$19,4,$19
+	bis	$31,$31,$CC	# carry = 0
+	blt	$19,$900
+	ldq	$L1,0($17)	# a[0]
+	ldq	$R1,0($18)	# b[1]
+	.align 3
+$901:
+	addq	$R1,$L1,$R1	# r=a+b;
+	 ldq	$L2,8($17)	# a[1]
+	cmpult	$R1,$L1,$O1	# did we overflow?
+	 ldq	$R2,8($18)	# b[1]
+	addq	$R1,$CC,$R1	# c+= overflow
+	 ldq	$L3,16($17)	# a[2]
+	cmpult	$R1,$CC,$CC	# overflow?
+	 ldq	$R3,16($18)	# b[2]
+	addq	$CC,$O1,$CC
+	 ldq	$L4,24($17)	# a[3]
+	addq	$R2,$L2,$R2	# r=a+b;
+	 ldq	$R4,24($18)	# b[3]
+	cmpult	$R2,$L2,$O2	# did we overflow?
+	 addq	$R3,$L3,$R3	# r=a+b;
+	addq	$R2,$CC,$R2	# c+= overflow
+	 cmpult	$R3,$L3,$O3	# did we overflow?
+	cmpult	$R2,$CC,$CC	# overflow?
+	 addq	$R4,$L4,$R4	# r=a+b;
+	addq	$CC,$O2,$CC
+	 cmpult	$R4,$L4,$O4	# did we overflow?
+	addq	$R3,$CC,$R3	# c+= overflow
+	 stq	$R1,0($16)	# r[0]=c
+	cmpult	$R3,$CC,$CC	# overflow?
+	 stq	$R2,8($16)	# r[1]=c
+	addq	$CC,$O3,$CC
+	 stq	$R3,16($16)	# r[2]=c
+	addq	$R4,$CC,$R4	# c+= overflow
+	 subq	$19,4,$19	# loop--
+	cmpult	$R4,$CC,$CC	# overflow?
+	 addq	$17,32,$17	# a++
+	addq	$CC,$O4,$CC
+	 stq	$R4,24($16)	# r[3]=c
+	addq	$18,32,$18	# b++
+	 addq	$16,32,$16	# r++
+
+	blt	$19,$900
+	 ldq	$L1,0($17)	# a[0]
+	ldq	$R1,0($18)	# b[1]
+	 br	$901
+	.align 4
+$945:
+	ldq	$L1,0($17)	# a[0]
+	 ldq	$R1,0($18)	# b[1]
+	addq	$R1,$L1,$R1	# r=a+b;
+	 subq	$19,1,$19	# loop--
+	addq	$R1,$CC,$R1	# c+= overflow
+	 addq	$17,8,$17	# a++
+	cmpult	$R1,$L1,$O1	# did we overflow?
+	 cmpult	$R1,$CC,$CC	# overflow?
+	addq	$18,8,$18	# b++
+	 stq	$R1,0($16)	# r[0]=c
+	addq	$CC,$O1,$CC
+	 addq	$16,8,$16	# r++
+
+	bgt	$19,$945
+	ret	$31,($26),1	# else exit
+
+$900:
+	addq	$19,4,$19
+	bgt	$19,$945	# goto tail code
+	ret	$31,($26),1	# else exit
+	.end bn_add_words
+
+	.align 3
+	.globl bn_sub_words
+	.ent bn_sub_words
+bn_sub_words:
+bn_sub_words..ng:
+	.frame $30,0,$26,0
+	.prologue 0
+
+	subq	$19,4,$19
+	bis	$31,$31,$CC	# carry = 0
+ br	$800
+	blt	$19,$800
+	ldq	$L1,0($17)	# a[0]
+	ldq	$R1,0($18)	# b[1]
+	.align 3
+$801:
+	addq	$R1,$L1,$R1	# r=a+b;
+	 ldq	$L2,8($17)	# a[1]
+	cmpult	$R1,$L1,$O1	# did we overflow?
+	 ldq	$R2,8($18)	# b[1]
+	addq	$R1,$CC,$R1	# c+= overflow
+	 ldq	$L3,16($17)	# a[2]
+	cmpult	$R1,$CC,$CC	# overflow?
+	 ldq	$R3,16($18)	# b[2]
+	addq	$CC,$O1,$CC
+	 ldq	$L4,24($17)	# a[3]
+	addq	$R2,$L2,$R2	# r=a+b;
+	 ldq	$R4,24($18)	# b[3]
+	cmpult	$R2,$L2,$O2	# did we overflow?
+	 addq	$R3,$L3,$R3	# r=a+b;
+	addq	$R2,$CC,$R2	# c+= overflow
+	 cmpult	$R3,$L3,$O3	# did we overflow?
+	cmpult	$R2,$CC,$CC	# overflow?
+	 addq	$R4,$L4,$R4	# r=a+b;
+	addq	$CC,$O2,$CC
+	 cmpult	$R4,$L4,$O4	# did we overflow?
+	addq	$R3,$CC,$R3	# c+= overflow
+	 stq	$R1,0($16)	# r[0]=c
+	cmpult	$R3,$CC,$CC	# overflow?
+	 stq	$R2,8($16)	# r[1]=c
+	addq	$CC,$O3,$CC
+	 stq	$R3,16($16)	# r[2]=c
+	addq	$R4,$CC,$R4	# c+= overflow
+	 subq	$19,4,$19	# loop--
+	cmpult	$R4,$CC,$CC	# overflow?
+	 addq	$17,32,$17	# a++
+	addq	$CC,$O4,$CC
+	 stq	$R4,24($16)	# r[3]=c
+	addq	$18,32,$18	# b++
+	 addq	$16,32,$16	# r++
+
+	blt	$19,$800
+	 ldq	$L1,0($17)	# a[0]
+	ldq	$R1,0($18)	# b[1]
+	 br	$801
+	.align 4
+$845:
+	ldq	$L1,0($17)	# a[0]
+	 ldq	$R1,0($18)	# b[1]
+	cmpult	$L1,$R1,$O1	# will we borrow?
+	 subq	$L1,$R1,$R1	# r=a-b;
+	subq	$19,1,$19	# loop--
+	 cmpult  $R1,$CC,$O2	# will we borrow?
+	subq	$R1,$CC,$R1	# c+= overflow
+	 addq	$17,8,$17	# a++
+	addq	$18,8,$18	# b++
+	 stq	$R1,0($16)	# r[0]=c
+	addq	$O2,$O1,$CC
+	 addq	$16,8,$16	# r++
+
+	bgt	$19,$845
+	ret	$31,($26),1	# else exit
+
+$800:
+	addq	$19,4,$19
+	bgt	$19,$845	# goto tail code
+	ret	$31,($26),1	# else exit
+	.end bn_sub_words
+
+ #
+ # What follows was taken directly from the C compiler with a few
+ # hacks to redo the lables.
+ #
+.text
+	.align 3
+	.globl bn_div_words
+	.ent bn_div_words
+bn_div_words:
+	ldgp $29,0($27)
+bn_div_words..ng:
+	lda $30,-48($30)
+	.frame $30,48,$26,0
+	stq $26,0($30)
+	stq $9,8($30)
+	stq $10,16($30)
+	stq $11,24($30)
+	stq $12,32($30)
+	stq $13,40($30)
+	.mask 0x4003e00,-48
+	.prologue 1
+	bis $16,$16,$9
+	bis $17,$17,$10
+	bis $18,$18,$11
+	bis $31,$31,$13
+	bis $31,2,$12
+	bne $11,$119
+	lda $0,-1
+	br $31,$136
+	.align 4
+$119:
+	bis $11,$11,$16
+	jsr $26,BN_num_bits_word
+	ldgp $29,0($26)
+	subq $0,64,$1
+	beq $1,$120
+	bis $31,1,$1
+	sll $1,$0,$1
+	cmpule $9,$1,$1
+	bne $1,$120
+ #	lda $16,_IO_stderr_
+ #	lda $17,$C32
+ #	bis $0,$0,$18
+ #	jsr $26,fprintf
+ #	ldgp $29,0($26)
+	jsr $26,abort
+	ldgp $29,0($26)
+	.align 4
+$120:
+	bis $31,64,$3
+	cmpult $9,$11,$2
+	subq $3,$0,$1
+	addl $1,$31,$0
+	subq $9,$11,$1
+	cmoveq $2,$1,$9
+	beq $0,$122
+	zapnot $0,15,$2
+	subq $3,$0,$1
+	sll $11,$2,$11
+	sll $9,$2,$3
+	srl $10,$1,$1
+	sll $10,$2,$10
+	bis $3,$1,$9
+$122:
+	srl $11,32,$5
+	zapnot $11,15,$6
+	lda $7,-1
+	.align 5
+$123:
+	srl $9,32,$1
+	subq $1,$5,$1
+	bne $1,$126
+	zapnot $7,15,$27
+	br $31,$127
+	.align 4
+$126:
+	bis $9,$9,$24
+	bis $5,$5,$25
+	divqu $24,$25,$27
+$127:
+	srl $10,32,$4
+	.align 5
+$128:
+	mulq $27,$5,$1
+	subq $9,$1,$3
+	zapnot $3,240,$1
+	bne $1,$129
+	mulq $6,$27,$2
+	sll $3,32,$1
+	addq $1,$4,$1
+	cmpule $2,$1,$2
+	bne $2,$129
+	subq $27,1,$27
+	br $31,$128
+	.align 4
+$129:
+	mulq $27,$6,$1
+	mulq $27,$5,$4
+	srl $1,32,$3
+	sll $1,32,$1
+	addq $4,$3,$4
+	cmpult $10,$1,$2
+	subq $10,$1,$10
+	addq $2,$4,$2
+	cmpult $9,$2,$1
+	bis $2,$2,$4
+	beq $1,$134
+	addq $9,$11,$9
+	subq $27,1,$27
+$134:
+	subl $12,1,$12
+	subq $9,$4,$9
+	beq $12,$124
+	sll $27,32,$13
+	sll $9,32,$2
+	srl $10,32,$1
+	sll $10,32,$10
+	bis $2,$1,$9
+	br $31,$123
+	.align 4
+$124:
+	bis $13,$27,$0
+$136:
+	ldq $26,0($30)
+	ldq $9,8($30)
+	ldq $10,16($30)
+	ldq $11,24($30)
+	ldq $12,32($30)
+	ldq $13,40($30)
+	addq $30,48,$30
+	ret $31,($26),1
+	.end bn_div_words
+EOF
+	return($data);
+	}
+
diff --git a/crypto/bn/asm/bn-win32.asm b/crypto/bn/asm/bn-win32.asm
index 017ea46..871bd88 100644
--- a/crypto/bn/asm/bn-win32.asm
+++ b/crypto/bn/asm/bn-win32.asm
@@ -485,9 +485,9 @@
 _bn_sqr_words ENDP
 _TEXT	ENDS
 _TEXT	SEGMENT
-PUBLIC	_bn_div64
+PUBLIC	_bn_div_words
 
-_bn_div64 PROC NEAR
+_bn_div_words PROC NEAR
 	push	ebp
 	push	ebx
 	push	esi
@@ -501,7 +501,7 @@
 	pop	ebx
 	pop	ebp
 	ret
-_bn_div64 ENDP
+_bn_div_words ENDP
 _TEXT	ENDS
 _TEXT	SEGMENT
 PUBLIC	_bn_add_words
@@ -678,7 +678,6 @@
 	adc	eax,		0
 	mov	DWORD PTR 24[ebx],ecx
 $L013aw_end:
-	mov	eax,		eax
 	pop	edi
 	pop	esi
 	pop	ebx
@@ -686,4 +685,1438 @@
 	ret
 _bn_add_words ENDP
 _TEXT	ENDS
+_TEXT	SEGMENT
+PUBLIC	_bn_sub_words
+
+_bn_sub_words PROC NEAR
+	push	ebp
+	push	ebx
+	push	esi
+	push	edi
+	; 
+	mov	ebx,		DWORD PTR 20[esp]
+	mov	esi,		DWORD PTR 24[esp]
+	mov	edi,		DWORD PTR 28[esp]
+	mov	ebp,		DWORD PTR 32[esp]
+	xor	eax,		eax
+	and	ebp,		4294967288
+	jz	$L014aw_finish
+L015aw_loop:
+	; Round 0
+	mov	ecx,		DWORD PTR [esi]
+	mov	edx,		DWORD PTR [edi]
+	sub	ecx,		eax
+	mov	eax,		0
+	adc	eax,		eax
+	sub	ecx,		edx
+	adc	eax,		0
+	mov	DWORD PTR [ebx],ecx
+	; Round 1
+	mov	ecx,		DWORD PTR 4[esi]
+	mov	edx,		DWORD PTR 4[edi]
+	sub	ecx,		eax
+	mov	eax,		0
+	adc	eax,		eax
+	sub	ecx,		edx
+	adc	eax,		0
+	mov	DWORD PTR 4[ebx],ecx
+	; Round 2
+	mov	ecx,		DWORD PTR 8[esi]
+	mov	edx,		DWORD PTR 8[edi]
+	sub	ecx,		eax
+	mov	eax,		0
+	adc	eax,		eax
+	sub	ecx,		edx
+	adc	eax,		0
+	mov	DWORD PTR 8[ebx],ecx
+	; Round 3
+	mov	ecx,		DWORD PTR 12[esi]
+	mov	edx,		DWORD PTR 12[edi]
+	sub	ecx,		eax
+	mov	eax,		0
+	adc	eax,		eax
+	sub	ecx,		edx
+	adc	eax,		0
+	mov	DWORD PTR 12[ebx],ecx
+	; Round 4
+	mov	ecx,		DWORD PTR 16[esi]
+	mov	edx,		DWORD PTR 16[edi]
+	sub	ecx,		eax
+	mov	eax,		0
+	adc	eax,		eax
+	sub	ecx,		edx
+	adc	eax,		0
+	mov	DWORD PTR 16[ebx],ecx
+	; Round 5
+	mov	ecx,		DWORD PTR 20[esi]
+	mov	edx,		DWORD PTR 20[edi]
+	sub	ecx,		eax
+	mov	eax,		0
+	adc	eax,		eax
+	sub	ecx,		edx
+	adc	eax,		0
+	mov	DWORD PTR 20[ebx],ecx
+	; Round 6
+	mov	ecx,		DWORD PTR 24[esi]
+	mov	edx,		DWORD PTR 24[edi]
+	sub	ecx,		eax
+	mov	eax,		0
+	adc	eax,		eax
+	sub	ecx,		edx
+	adc	eax,		0
+	mov	DWORD PTR 24[ebx],ecx
+	; Round 7
+	mov	ecx,		DWORD PTR 28[esi]
+	mov	edx,		DWORD PTR 28[edi]
+	sub	ecx,		eax
+	mov	eax,		0
+	adc	eax,		eax
+	sub	ecx,		edx
+	adc	eax,		0
+	mov	DWORD PTR 28[ebx],ecx
+	; 
+	add	esi,		32
+	add	edi,		32
+	add	ebx,		32
+	sub	ebp,		8
+	jnz	L015aw_loop
+$L014aw_finish:
+	mov	ebp,		DWORD PTR 32[esp]
+	and	ebp,		7
+	jz	$L016aw_end
+	; Tail Round 0
+	mov	ecx,		DWORD PTR [esi]
+	mov	edx,		DWORD PTR [edi]
+	sub	ecx,		eax
+	mov	eax,		0
+	adc	eax,		eax
+	sub	ecx,		edx
+	adc	eax,		0
+	dec	ebp
+	mov	DWORD PTR [ebx],ecx
+	jz	$L016aw_end
+	; Tail Round 1
+	mov	ecx,		DWORD PTR 4[esi]
+	mov	edx,		DWORD PTR 4[edi]
+	sub	ecx,		eax
+	mov	eax,		0
+	adc	eax,		eax
+	sub	ecx,		edx
+	adc	eax,		0
+	dec	ebp
+	mov	DWORD PTR 4[ebx],ecx
+	jz	$L016aw_end
+	; Tail Round 2
+	mov	ecx,		DWORD PTR 8[esi]
+	mov	edx,		DWORD PTR 8[edi]
+	sub	ecx,		eax
+	mov	eax,		0
+	adc	eax,		eax
+	sub	ecx,		edx
+	adc	eax,		0
+	dec	ebp
+	mov	DWORD PTR 8[ebx],ecx
+	jz	$L016aw_end
+	; Tail Round 3
+	mov	ecx,		DWORD PTR 12[esi]
+	mov	edx,		DWORD PTR 12[edi]
+	sub	ecx,		eax
+	mov	eax,		0
+	adc	eax,		eax
+	sub	ecx,		edx
+	adc	eax,		0
+	dec	ebp
+	mov	DWORD PTR 12[ebx],ecx
+	jz	$L016aw_end
+	; Tail Round 4
+	mov	ecx,		DWORD PTR 16[esi]
+	mov	edx,		DWORD PTR 16[edi]
+	sub	ecx,		eax
+	mov	eax,		0
+	adc	eax,		eax
+	sub	ecx,		edx
+	adc	eax,		0
+	dec	ebp
+	mov	DWORD PTR 16[ebx],ecx
+	jz	$L016aw_end
+	; Tail Round 5
+	mov	ecx,		DWORD PTR 20[esi]
+	mov	edx,		DWORD PTR 20[edi]
+	sub	ecx,		eax
+	mov	eax,		0
+	adc	eax,		eax
+	sub	ecx,		edx
+	adc	eax,		0
+	dec	ebp
+	mov	DWORD PTR 20[ebx],ecx
+	jz	$L016aw_end
+	; Tail Round 6
+	mov	ecx,		DWORD PTR 24[esi]
+	mov	edx,		DWORD PTR 24[edi]
+	sub	ecx,		eax
+	mov	eax,		0
+	adc	eax,		eax
+	sub	ecx,		edx
+	adc	eax,		0
+	mov	DWORD PTR 24[ebx],ecx
+$L016aw_end:
+	pop	edi
+	pop	esi
+	pop	ebx
+	pop	ebp
+	ret
+_bn_sub_words ENDP
+_TEXT	ENDS
+_TEXT	SEGMENT
+PUBLIC	_bn_mul_comba8
+
+_bn_mul_comba8 PROC NEAR
+	push	esi
+	mov	esi,		DWORD PTR 12[esp]
+	push	edi
+	mov	edi,		DWORD PTR 20[esp]
+	push	ebp
+	push	ebx
+	xor	ebx,		ebx
+	mov	eax,		DWORD PTR [esi]
+	xor	ecx,		ecx
+	mov	edx,		DWORD PTR [edi]
+	; ################## Calculate word 0
+	xor	ebp,		ebp
+	; mul a[0]*b[0]
+	mul	edx
+	add	ebx,		eax
+	mov	eax,		DWORD PTR 20[esp]
+	adc	ecx,		edx
+	mov	edx,		DWORD PTR [edi]
+	adc	ebp,		0
+	mov	DWORD PTR [eax],ebx
+	mov	eax,		DWORD PTR 4[esi]
+	; saved r[0]
+	; ################## Calculate word 1
+	xor	ebx,		ebx
+	; mul a[1]*b[0]
+	mul	edx
+	add	ecx,		eax
+	mov	eax,		DWORD PTR [esi]
+	adc	ebp,		edx
+	mov	edx,		DWORD PTR 4[edi]
+	adc	ebx,		0
+	; mul a[0]*b[1]
+	mul	edx
+	add	ecx,		eax
+	mov	eax,		DWORD PTR 20[esp]
+	adc	ebp,		edx
+	mov	edx,		DWORD PTR [edi]
+	adc	ebx,		0
+	mov	DWORD PTR 4[eax],ecx
+	mov	eax,		DWORD PTR 8[esi]
+	; saved r[1]
+	; ################## Calculate word 2
+	xor	ecx,		ecx
+	; mul a[2]*b[0]
+	mul	edx
+	add	ebp,		eax
+	mov	eax,		DWORD PTR 4[esi]
+	adc	ebx,		edx
+	mov	edx,		DWORD PTR 4[edi]
+	adc	ecx,		0
+	; mul a[1]*b[1]
+	mul	edx
+	add	ebp,		eax
+	mov	eax,		DWORD PTR [esi]
+	adc	ebx,		edx
+	mov	edx,		DWORD PTR 8[edi]
+	adc	ecx,		0
+	; mul a[0]*b[2]
+	mul	edx
+	add	ebp,		eax
+	mov	eax,		DWORD PTR 20[esp]
+	adc	ebx,		edx
+	mov	edx,		DWORD PTR [edi]
+	adc	ecx,		0
+	mov	DWORD PTR 8[eax],ebp
+	mov	eax,		DWORD PTR 12[esi]
+	; saved r[2]
+	; ################## Calculate word 3
+	xor	ebp,		ebp
+	; mul a[3]*b[0]
+	mul	edx
+	add	ebx,		eax
+	mov	eax,		DWORD PTR 8[esi]
+	adc	ecx,		edx
+	mov	edx,		DWORD PTR 4[edi]
+	adc	ebp,		0
+	; mul a[2]*b[1]
+	mul	edx
+	add	ebx,		eax
+	mov	eax,		DWORD PTR 4[esi]
+	adc	ecx,		edx
+	mov	edx,		DWORD PTR 8[edi]
+	adc	ebp,		0
+	; mul a[1]*b[2]
+	mul	edx
+	add	ebx,		eax
+	mov	eax,		DWORD PTR [esi]
+	adc	ecx,		edx
+	mov	edx,		DWORD PTR 12[edi]
+	adc	ebp,		0
+	; mul a[0]*b[3]
+	mul	edx
+	add	ebx,		eax
+	mov	eax,		DWORD PTR 20[esp]
+	adc	ecx,		edx
+	mov	edx,		DWORD PTR [edi]
+	adc	ebp,		0
+	mov	DWORD PTR 12[eax],ebx
+	mov	eax,		DWORD PTR 16[esi]
+	; saved r[3]
+	; ################## Calculate word 4
+	xor	ebx,		ebx
+	; mul a[4]*b[0]
+	mul	edx
+	add	ecx,		eax
+	mov	eax,		DWORD PTR 12[esi]
+	adc	ebp,		edx
+	mov	edx,		DWORD PTR 4[edi]
+	adc	ebx,		0
+	; mul a[3]*b[1]
+	mul	edx
+	add	ecx,		eax
+	mov	eax,		DWORD PTR 8[esi]
+	adc	ebp,		edx
+	mov	edx,		DWORD PTR 8[edi]
+	adc	ebx,		0
+	; mul a[2]*b[2]
+	mul	edx
+	add	ecx,		eax
+	mov	eax,		DWORD PTR 4[esi]
+	adc	ebp,		edx
+	mov	edx,		DWORD PTR 12[edi]
+	adc	ebx,		0
+	; mul a[1]*b[3]
+	mul	edx
+	add	ecx,		eax
+	mov	eax,		DWORD PTR [esi]
+	adc	ebp,		edx
+	mov	edx,		DWORD PTR 16[edi]
+	adc	ebx,		0
+	; mul a[0]*b[4]
+	mul	edx
+	add	ecx,		eax
+	mov	eax,		DWORD PTR 20[esp]
+	adc	ebp,		edx
+	mov	edx,		DWORD PTR [edi]
+	adc	ebx,		0
+	mov	DWORD PTR 16[eax],ecx
+	mov	eax,		DWORD PTR 20[esi]
+	; saved r[4]
+	; ################## Calculate word 5
+	xor	ecx,		ecx
+	; mul a[5]*b[0]
+	mul	edx
+	add	ebp,		eax
+	mov	eax,		DWORD PTR 16[esi]
+	adc	ebx,		edx
+	mov	edx,		DWORD PTR 4[edi]
+	adc	ecx,		0
+	; mul a[4]*b[1]
+	mul	edx
+	add	ebp,		eax
+	mov	eax,		DWORD PTR 12[esi]
+	adc	ebx,		edx
+	mov	edx,		DWORD PTR 8[edi]
+	adc	ecx,		0
+	; mul a[3]*b[2]
+	mul	edx
+	add	ebp,		eax
+	mov	eax,		DWORD PTR 8[esi]
+	adc	ebx,		edx
+	mov	edx,		DWORD PTR 12[edi]
+	adc	ecx,		0
+	; mul a[2]*b[3]
+	mul	edx
+	add	ebp,		eax
+	mov	eax,		DWORD PTR 4[esi]
+	adc	ebx,		edx
+	mov	edx,		DWORD PTR 16[edi]
+	adc	ecx,		0
+	; mul a[1]*b[4]
+	mul	edx
+	add	ebp,		eax
+	mov	eax,		DWORD PTR [esi]
+	adc	ebx,		edx
+	mov	edx,		DWORD PTR 20[edi]
+	adc	ecx,		0
+	; mul a[0]*b[5]
+	mul	edx
+	add	ebp,		eax
+	mov	eax,		DWORD PTR 20[esp]
+	adc	ebx,		edx
+	mov	edx,		DWORD PTR [edi]
+	adc	ecx,		0
+	mov	DWORD PTR 20[eax],ebp
+	mov	eax,		DWORD PTR 24[esi]
+	; saved r[5]
+	; ################## Calculate word 6
+	xor	ebp,		ebp
+	; mul a[6]*b[0]
+	mul	edx
+	add	ebx,		eax
+	mov	eax,		DWORD PTR 20[esi]
+	adc	ecx,		edx
+	mov	edx,		DWORD PTR 4[edi]
+	adc	ebp,		0
+	; mul a[5]*b[1]
+	mul	edx
+	add	ebx,		eax
+	mov	eax,		DWORD PTR 16[esi]
+	adc	ecx,		edx
+	mov	edx,		DWORD PTR 8[edi]
+	adc	ebp,		0
+	; mul a[4]*b[2]
+	mul	edx
+	add	ebx,		eax
+	mov	eax,		DWORD PTR 12[esi]
+	adc	ecx,		edx
+	mov	edx,		DWORD PTR 12[edi]
+	adc	ebp,		0
+	; mul a[3]*b[3]
+	mul	edx
+	add	ebx,		eax
+	mov	eax,		DWORD PTR 8[esi]
+	adc	ecx,		edx
+	mov	edx,		DWORD PTR 16[edi]
+	adc	ebp,		0
+	; mul a[2]*b[4]
+	mul	edx
+	add	ebx,		eax
+	mov	eax,		DWORD PTR 4[esi]
+	adc	ecx,		edx
+	mov	edx,		DWORD PTR 20[edi]
+	adc	ebp,		0
+	; mul a[1]*b[5]
+	mul	edx
+	add	ebx,		eax
+	mov	eax,		DWORD PTR [esi]
+	adc	ecx,		edx
+	mov	edx,		DWORD PTR 24[edi]
+	adc	ebp,		0
+	; mul a[0]*b[6]
+	mul	edx
+	add	ebx,		eax
+	mov	eax,		DWORD PTR 20[esp]
+	adc	ecx,		edx
+	mov	edx,		DWORD PTR [edi]
+	adc	ebp,		0
+	mov	DWORD PTR 24[eax],ebx
+	mov	eax,		DWORD PTR 28[esi]
+	; saved r[6]
+	; ################## Calculate word 7
+	xor	ebx,		ebx
+	; mul a[7]*b[0]
+	mul	edx
+	add	ecx,		eax
+	mov	eax,		DWORD PTR 24[esi]
+	adc	ebp,		edx
+	mov	edx,		DWORD PTR 4[edi]
+	adc	ebx,		0
+	; mul a[6]*b[1]
+	mul	edx
+	add	ecx,		eax
+	mov	eax,		DWORD PTR 20[esi]
+	adc	ebp,		edx
+	mov	edx,		DWORD PTR 8[edi]
+	adc	ebx,		0
+	; mul a[5]*b[2]
+	mul	edx
+	add	ecx,		eax
+	mov	eax,		DWORD PTR 16[esi]
+	adc	ebp,		edx
+	mov	edx,		DWORD PTR 12[edi]
+	adc	ebx,		0
+	; mul a[4]*b[3]
+	mul	edx
+	add	ecx,		eax
+	mov	eax,		DWORD PTR 12[esi]
+	adc	ebp,		edx
+	mov	edx,		DWORD PTR 16[edi]
+	adc	ebx,		0
+	; mul a[3]*b[4]
+	mul	edx
+	add	ecx,		eax
+	mov	eax,		DWORD PTR 8[esi]
+	adc	ebp,		edx
+	mov	edx,		DWORD PTR 20[edi]
+	adc	ebx,		0
+	; mul a[2]*b[5]
+	mul	edx
+	add	ecx,		eax
+	mov	eax,		DWORD PTR 4[esi]
+	adc	ebp,		edx
+	mov	edx,		DWORD PTR 24[edi]
+	adc	ebx,		0
+	; mul a[1]*b[6]
+	mul	edx
+	add	ecx,		eax
+	mov	eax,		DWORD PTR [esi]
+	adc	ebp,		edx
+	mov	edx,		DWORD PTR 28[edi]
+	adc	ebx,		0
+	; mul a[0]*b[7]
+	mul	edx
+	add	ecx,		eax
+	mov	eax,		DWORD PTR 20[esp]
+	adc	ebp,		edx
+	mov	edx,		DWORD PTR 4[edi]
+	adc	ebx,		0
+	mov	DWORD PTR 28[eax],ecx
+	mov	eax,		DWORD PTR 28[esi]
+	; saved r[7]
+	; ################## Calculate word 8
+	xor	ecx,		ecx
+	; mul a[7]*b[1]
+	mul	edx
+	add	ebp,		eax
+	mov	eax,		DWORD PTR 24[esi]
+	adc	ebx,		edx
+	mov	edx,		DWORD PTR 8[edi]
+	adc	ecx,		0
+	; mul a[6]*b[2]
+	mul	edx
+	add	ebp,		eax
+	mov	eax,		DWORD PTR 20[esi]
+	adc	ebx,		edx
+	mov	edx,		DWORD PTR 12[edi]
+	adc	ecx,		0
+	; mul a[5]*b[3]
+	mul	edx
+	add	ebp,		eax
+	mov	eax,		DWORD PTR 16[esi]
+	adc	ebx,		edx
+	mov	edx,		DWORD PTR 16[edi]
+	adc	ecx,		0
+	; mul a[4]*b[4]
+	mul	edx
+	add	ebp,		eax
+	mov	eax,		DWORD PTR 12[esi]
+	adc	ebx,		edx
+	mov	edx,		DWORD PTR 20[edi]
+	adc	ecx,		0
+	; mul a[3]*b[5]
+	mul	edx
+	add	ebp,		eax
+	mov	eax,		DWORD PTR 8[esi]
+	adc	ebx,		edx
+	mov	edx,		DWORD PTR 24[edi]
+	adc	ecx,		0
+	; mul a[2]*b[6]
+	mul	edx
+	add	ebp,		eax
+	mov	eax,		DWORD PTR 4[esi]
+	adc	ebx,		edx
+	mov	edx,		DWORD PTR 28[edi]
+	adc	ecx,		0
+	; mul a[1]*b[7]
+	mul	edx
+	add	ebp,		eax
+	mov	eax,		DWORD PTR 20[esp]
+	adc	ebx,		edx
+	mov	edx,		DWORD PTR 8[edi]
+	adc	ecx,		0
+	mov	DWORD PTR 32[eax],ebp
+	mov	eax,		DWORD PTR 28[esi]
+	; saved r[8]
+	; ################## Calculate word 9
+	xor	ebp,		ebp
+	; mul a[7]*b[2]
+	mul	edx
+	add	ebx,		eax
+	mov	eax,		DWORD PTR 24[esi]
+	adc	ecx,		edx
+	mov	edx,		DWORD PTR 12[edi]
+	adc	ebp,		0
+	; mul a[6]*b[3]
+	mul	edx
+	add	ebx,		eax
+	mov	eax,		DWORD PTR 20[esi]
+	adc	ecx,		edx
+	mov	edx,		DWORD PTR 16[edi]
+	adc	ebp,		0
+	; mul a[5]*b[4]
+	mul	edx
+	add	ebx,		eax
+	mov	eax,		DWORD PTR 16[esi]
+	adc	ecx,		edx
+	mov	edx,		DWORD PTR 20[edi]
+	adc	ebp,		0
+	; mul a[4]*b[5]
+	mul	edx
+	add	ebx,		eax
+	mov	eax,		DWORD PTR 12[esi]
+	adc	ecx,		edx
+	mov	edx,		DWORD PTR 24[edi]
+	adc	ebp,		0
+	; mul a[3]*b[6]
+	mul	edx
+	add	ebx,		eax
+	mov	eax,		DWORD PTR 8[esi]
+	adc	ecx,		edx
+	mov	edx,		DWORD PTR 28[edi]
+	adc	ebp,		0
+	; mul a[2]*b[7]
+	mul	edx
+	add	ebx,		eax
+	mov	eax,		DWORD PTR 20[esp]
+	adc	ecx,		edx
+	mov	edx,		DWORD PTR 12[edi]
+	adc	ebp,		0
+	mov	DWORD PTR 36[eax],ebx
+	mov	eax,		DWORD PTR 28[esi]
+	; saved r[9]
+	; ################## Calculate word 10
+	xor	ebx,		ebx
+	; mul a[7]*b[3]
+	mul	edx
+	add	ecx,		eax
+	mov	eax,		DWORD PTR 24[esi]
+	adc	ebp,		edx
+	mov	edx,		DWORD PTR 16[edi]
+	adc	ebx,		0
+	; mul a[6]*b[4]
+	mul	edx
+	add	ecx,		eax
+	mov	eax,		DWORD PTR 20[esi]
+	adc	ebp,		edx
+	mov	edx,		DWORD PTR 20[edi]
+	adc	ebx,		0
+	; mul a[5]*b[5]
+	mul	edx
+	add	ecx,		eax
+	mov	eax,		DWORD PTR 16[esi]
+	adc	ebp,		edx
+	mov	edx,		DWORD PTR 24[edi]
+	adc	ebx,		0
+	; mul a[4]*b[6]
+	mul	edx
+	add	ecx,		eax
+	mov	eax,		DWORD PTR 12[esi]
+	adc	ebp,		edx
+	mov	edx,		DWORD PTR 28[edi]
+	adc	ebx,		0
+	; mul a[3]*b[7]
+	mul	edx
+	add	ecx,		eax
+	mov	eax,		DWORD PTR 20[esp]
+	adc	ebp,		edx
+	mov	edx,		DWORD PTR 16[edi]
+	adc	ebx,		0
+	mov	DWORD PTR 40[eax],ecx
+	mov	eax,		DWORD PTR 28[esi]
+	; saved r[10]
+	; ################## Calculate word 11
+	xor	ecx,		ecx
+	; mul a[7]*b[4]
+	mul	edx
+	add	ebp,		eax
+	mov	eax,		DWORD PTR 24[esi]
+	adc	ebx,		edx
+	mov	edx,		DWORD PTR 20[edi]
+	adc	ecx,		0
+	; mul a[6]*b[5]
+	mul	edx
+	add	ebp,		eax
+	mov	eax,		DWORD PTR 20[esi]
+	adc	ebx,		edx
+	mov	edx,		DWORD PTR 24[edi]
+	adc	ecx,		0
+	; mul a[5]*b[6]
+	mul	edx
+	add	ebp,		eax
+	mov	eax,		DWORD PTR 16[esi]
+	adc	ebx,		edx
+	mov	edx,		DWORD PTR 28[edi]
+	adc	ecx,		0
+	; mul a[4]*b[7]
+	mul	edx
+	add	ebp,		eax
+	mov	eax,		DWORD PTR 20[esp]
+	adc	ebx,		edx
+	mov	edx,		DWORD PTR 20[edi]
+	adc	ecx,		0
+	mov	DWORD PTR 44[eax],ebp
+	mov	eax,		DWORD PTR 28[esi]
+	; saved r[11]
+	; ################## Calculate word 12
+	xor	ebp,		ebp
+	; mul a[7]*b[5]
+	mul	edx
+	add	ebx,		eax
+	mov	eax,		DWORD PTR 24[esi]
+	adc	ecx,		edx
+	mov	edx,		DWORD PTR 24[edi]
+	adc	ebp,		0
+	; mul a[6]*b[6]
+	mul	edx
+	add	ebx,		eax
+	mov	eax,		DWORD PTR 20[esi]
+	adc	ecx,		edx
+	mov	edx,		DWORD PTR 28[edi]
+	adc	ebp,		0
+	; mul a[5]*b[7]
+	mul	edx
+	add	ebx,		eax
+	mov	eax,		DWORD PTR 20[esp]
+	adc	ecx,		edx
+	mov	edx,		DWORD PTR 24[edi]
+	adc	ebp,		0
+	mov	DWORD PTR 48[eax],ebx
+	mov	eax,		DWORD PTR 28[esi]
+	; saved r[12]
+	; ################## Calculate word 13
+	xor	ebx,		ebx
+	; mul a[7]*b[6]
+	mul	edx
+	add	ecx,		eax
+	mov	eax,		DWORD PTR 24[esi]
+	adc	ebp,		edx
+	mov	edx,		DWORD PTR 28[edi]
+	adc	ebx,		0
+	; mul a[6]*b[7]
+	mul	edx
+	add	ecx,		eax
+	mov	eax,		DWORD PTR 20[esp]
+	adc	ebp,		edx
+	mov	edx,		DWORD PTR 28[edi]
+	adc	ebx,		0
+	mov	DWORD PTR 52[eax],ecx
+	mov	eax,		DWORD PTR 28[esi]
+	; saved r[13]
+	; ################## Calculate word 14
+	xor	ecx,		ecx
+	; mul a[7]*b[7]
+	mul	edx
+	add	ebp,		eax
+	mov	eax,		DWORD PTR 20[esp]
+	adc	ebx,		edx
+	adc	ecx,		0
+	mov	DWORD PTR 56[eax],ebp
+	; saved r[14]
+	; save r[15]
+	mov	DWORD PTR 60[eax],ebx
+	pop	ebx
+	pop	ebp
+	pop	edi
+	pop	esi
+	ret
+_bn_mul_comba8 ENDP
+_TEXT	ENDS
+_TEXT	SEGMENT
+PUBLIC	_bn_mul_comba4
+
+_bn_mul_comba4 PROC NEAR
+	push	esi
+	mov	esi,		DWORD PTR 12[esp]
+	push	edi
+	mov	edi,		DWORD PTR 20[esp]
+	push	ebp
+	push	ebx
+	xor	ebx,		ebx
+	mov	eax,		DWORD PTR [esi]
+	xor	ecx,		ecx
+	mov	edx,		DWORD PTR [edi]
+	; ################## Calculate word 0
+	xor	ebp,		ebp
+	; mul a[0]*b[0]
+	mul	edx
+	add	ebx,		eax
+	mov	eax,		DWORD PTR 20[esp]
+	adc	ecx,		edx
+	mov	edx,		DWORD PTR [edi]
+	adc	ebp,		0
+	mov	DWORD PTR [eax],ebx
+	mov	eax,		DWORD PTR 4[esi]
+	; saved r[0]
+	; ################## Calculate word 1
+	xor	ebx,		ebx
+	; mul a[1]*b[0]
+	mul	edx
+	add	ecx,		eax
+	mov	eax,		DWORD PTR [esi]
+	adc	ebp,		edx
+	mov	edx,		DWORD PTR 4[edi]
+	adc	ebx,		0
+	; mul a[0]*b[1]
+	mul	edx
+	add	ecx,		eax
+	mov	eax,		DWORD PTR 20[esp]
+	adc	ebp,		edx
+	mov	edx,		DWORD PTR [edi]
+	adc	ebx,		0
+	mov	DWORD PTR 4[eax],ecx
+	mov	eax,		DWORD PTR 8[esi]
+	; saved r[1]
+	; ################## Calculate word 2
+	xor	ecx,		ecx
+	; mul a[2]*b[0]
+	mul	edx
+	add	ebp,		eax
+	mov	eax,		DWORD PTR 4[esi]
+	adc	ebx,		edx
+	mov	edx,		DWORD PTR 4[edi]
+	adc	ecx,		0
+	; mul a[1]*b[1]
+	mul	edx
+	add	ebp,		eax
+	mov	eax,		DWORD PTR [esi]
+	adc	ebx,		edx
+	mov	edx,		DWORD PTR 8[edi]
+	adc	ecx,		0
+	; mul a[0]*b[2]
+	mul	edx
+	add	ebp,		eax
+	mov	eax,		DWORD PTR 20[esp]
+	adc	ebx,		edx
+	mov	edx,		DWORD PTR [edi]
+	adc	ecx,		0
+	mov	DWORD PTR 8[eax],ebp
+	mov	eax,		DWORD PTR 12[esi]
+	; saved r[2]
+	; ################## Calculate word 3
+	xor	ebp,		ebp
+	; mul a[3]*b[0]
+	mul	edx
+	add	ebx,		eax
+	mov	eax,		DWORD PTR 8[esi]
+	adc	ecx,		edx
+	mov	edx,		DWORD PTR 4[edi]
+	adc	ebp,		0
+	; mul a[2]*b[1]
+	mul	edx
+	add	ebx,		eax
+	mov	eax,		DWORD PTR 4[esi]
+	adc	ecx,		edx
+	mov	edx,		DWORD PTR 8[edi]
+	adc	ebp,		0
+	; mul a[1]*b[2]
+	mul	edx
+	add	ebx,		eax
+	mov	eax,		DWORD PTR [esi]
+	adc	ecx,		edx
+	mov	edx,		DWORD PTR 12[edi]
+	adc	ebp,		0
+	; mul a[0]*b[3]
+	mul	edx
+	add	ebx,		eax
+	mov	eax,		DWORD PTR 20[esp]
+	adc	ecx,		edx
+	mov	edx,		DWORD PTR 4[edi]
+	adc	ebp,		0
+	mov	DWORD PTR 12[eax],ebx
+	mov	eax,		DWORD PTR 12[esi]
+	; saved r[3]
+	; ################## Calculate word 4
+	xor	ebx,		ebx
+	; mul a[3]*b[1]
+	mul	edx
+	add	ecx,		eax
+	mov	eax,		DWORD PTR 8[esi]
+	adc	ebp,		edx
+	mov	edx,		DWORD PTR 8[edi]
+	adc	ebx,		0
+	; mul a[2]*b[2]
+	mul	edx
+	add	ecx,		eax
+	mov	eax,		DWORD PTR 4[esi]
+	adc	ebp,		edx
+	mov	edx,		DWORD PTR 12[edi]
+	adc	ebx,		0
+	; mul a[1]*b[3]
+	mul	edx
+	add	ecx,		eax
+	mov	eax,		DWORD PTR 20[esp]
+	adc	ebp,		edx
+	mov	edx,		DWORD PTR 8[edi]
+	adc	ebx,		0
+	mov	DWORD PTR 16[eax],ecx
+	mov	eax,		DWORD PTR 12[esi]
+	; saved r[4]
+	; ################## Calculate word 5
+	xor	ecx,		ecx
+	; mul a[3]*b[2]
+	mul	edx
+	add	ebp,		eax
+	mov	eax,		DWORD PTR 8[esi]
+	adc	ebx,		edx
+	mov	edx,		DWORD PTR 12[edi]
+	adc	ecx,		0
+	; mul a[2]*b[3]
+	mul	edx
+	add	ebp,		eax
+	mov	eax,		DWORD PTR 20[esp]
+	adc	ebx,		edx
+	mov	edx,		DWORD PTR 12[edi]
+	adc	ecx,		0
+	mov	DWORD PTR 20[eax],ebp
+	mov	eax,		DWORD PTR 12[esi]
+	; saved r[5]
+	; ################## Calculate word 6
+	xor	ebp,		ebp
+	; mul a[3]*b[3]
+	mul	edx
+	add	ebx,		eax
+	mov	eax,		DWORD PTR 20[esp]
+	adc	ecx,		edx
+	adc	ebp,		0
+	mov	DWORD PTR 24[eax],ebx
+	; saved r[6]
+	; save r[7]
+	mov	DWORD PTR 28[eax],ecx
+	pop	ebx
+	pop	ebp
+	pop	edi
+	pop	esi
+	ret
+_bn_mul_comba4 ENDP
+_TEXT	ENDS
+_TEXT	SEGMENT
+PUBLIC	_bn_sqr_comba8
+
+_bn_sqr_comba8 PROC NEAR
+	push	esi
+	push	edi
+	push	ebp
+	push	ebx
+	mov	edi,		DWORD PTR 20[esp]
+	mov	esi,		DWORD PTR 24[esp]
+	xor	ebx,		ebx
+	xor	ecx,		ecx
+	mov	eax,		DWORD PTR [esi]
+	; ############### Calculate word 0
+	xor	ebp,		ebp
+	; sqr a[0]*a[0]
+	mul	eax
+	add	ebx,		eax
+	adc	ecx,		edx
+	mov	edx,		DWORD PTR [esi]
+	adc	ebp,		0
+	mov	DWORD PTR [edi],ebx
+	mov	eax,		DWORD PTR 4[esi]
+	; saved r[0]
+	; ############### Calculate word 1
+	xor	ebx,		ebx
+	; sqr a[1]*a[0]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ebx,		0
+	add	ecx,		eax
+	adc	ebp,		edx
+	mov	eax,		DWORD PTR 8[esi]
+	adc	ebx,		0
+	mov	DWORD PTR 4[edi],ecx
+	mov	edx,		DWORD PTR [esi]
+	; saved r[1]
+	; ############### Calculate word 2
+	xor	ecx,		ecx
+	; sqr a[2]*a[0]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ecx,		0
+	add	ebp,		eax
+	adc	ebx,		edx
+	mov	eax,		DWORD PTR 4[esi]
+	adc	ecx,		0
+	; sqr a[1]*a[1]
+	mul	eax
+	add	ebp,		eax
+	adc	ebx,		edx
+	mov	edx,		DWORD PTR [esi]
+	adc	ecx,		0
+	mov	DWORD PTR 8[edi],ebp
+	mov	eax,		DWORD PTR 12[esi]
+	; saved r[2]
+	; ############### Calculate word 3
+	xor	ebp,		ebp
+	; sqr a[3]*a[0]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ebp,		0
+	add	ebx,		eax
+	adc	ecx,		edx
+	mov	eax,		DWORD PTR 8[esi]
+	adc	ebp,		0
+	mov	edx,		DWORD PTR 4[esi]
+	; sqr a[2]*a[1]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ebp,		0
+	add	ebx,		eax
+	adc	ecx,		edx
+	mov	eax,		DWORD PTR 16[esi]
+	adc	ebp,		0
+	mov	DWORD PTR 12[edi],ebx
+	mov	edx,		DWORD PTR [esi]
+	; saved r[3]
+	; ############### Calculate word 4
+	xor	ebx,		ebx
+	; sqr a[4]*a[0]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ebx,		0
+	add	ecx,		eax
+	adc	ebp,		edx
+	mov	eax,		DWORD PTR 12[esi]
+	adc	ebx,		0
+	mov	edx,		DWORD PTR 4[esi]
+	; sqr a[3]*a[1]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ebx,		0
+	add	ecx,		eax
+	adc	ebp,		edx
+	mov	eax,		DWORD PTR 8[esi]
+	adc	ebx,		0
+	; sqr a[2]*a[2]
+	mul	eax
+	add	ecx,		eax
+	adc	ebp,		edx
+	mov	edx,		DWORD PTR [esi]
+	adc	ebx,		0
+	mov	DWORD PTR 16[edi],ecx
+	mov	eax,		DWORD PTR 20[esi]
+	; saved r[4]
+	; ############### Calculate word 5
+	xor	ecx,		ecx
+	; sqr a[5]*a[0]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ecx,		0
+	add	ebp,		eax
+	adc	ebx,		edx
+	mov	eax,		DWORD PTR 16[esi]
+	adc	ecx,		0
+	mov	edx,		DWORD PTR 4[esi]
+	; sqr a[4]*a[1]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ecx,		0
+	add	ebp,		eax
+	adc	ebx,		edx
+	mov	eax,		DWORD PTR 12[esi]
+	adc	ecx,		0
+	mov	edx,		DWORD PTR 8[esi]
+	; sqr a[3]*a[2]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ecx,		0
+	add	ebp,		eax
+	adc	ebx,		edx
+	mov	eax,		DWORD PTR 24[esi]
+	adc	ecx,		0
+	mov	DWORD PTR 20[edi],ebp
+	mov	edx,		DWORD PTR [esi]
+	; saved r[5]
+	; ############### Calculate word 6
+	xor	ebp,		ebp
+	; sqr a[6]*a[0]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ebp,		0
+	add	ebx,		eax
+	adc	ecx,		edx
+	mov	eax,		DWORD PTR 20[esi]
+	adc	ebp,		0
+	mov	edx,		DWORD PTR 4[esi]
+	; sqr a[5]*a[1]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ebp,		0
+	add	ebx,		eax
+	adc	ecx,		edx
+	mov	eax,		DWORD PTR 16[esi]
+	adc	ebp,		0
+	mov	edx,		DWORD PTR 8[esi]
+	; sqr a[4]*a[2]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ebp,		0
+	add	ebx,		eax
+	adc	ecx,		edx
+	mov	eax,		DWORD PTR 12[esi]
+	adc	ebp,		0
+	; sqr a[3]*a[3]
+	mul	eax
+	add	ebx,		eax
+	adc	ecx,		edx
+	mov	edx,		DWORD PTR [esi]
+	adc	ebp,		0
+	mov	DWORD PTR 24[edi],ebx
+	mov	eax,		DWORD PTR 28[esi]
+	; saved r[6]
+	; ############### Calculate word 7
+	xor	ebx,		ebx
+	; sqr a[7]*a[0]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ebx,		0
+	add	ecx,		eax
+	adc	ebp,		edx
+	mov	eax,		DWORD PTR 24[esi]
+	adc	ebx,		0
+	mov	edx,		DWORD PTR 4[esi]
+	; sqr a[6]*a[1]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ebx,		0
+	add	ecx,		eax
+	adc	ebp,		edx
+	mov	eax,		DWORD PTR 20[esi]
+	adc	ebx,		0
+	mov	edx,		DWORD PTR 8[esi]
+	; sqr a[5]*a[2]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ebx,		0
+	add	ecx,		eax
+	adc	ebp,		edx
+	mov	eax,		DWORD PTR 16[esi]
+	adc	ebx,		0
+	mov	edx,		DWORD PTR 12[esi]
+	; sqr a[4]*a[3]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ebx,		0
+	add	ecx,		eax
+	adc	ebp,		edx
+	mov	eax,		DWORD PTR 28[esi]
+	adc	ebx,		0
+	mov	DWORD PTR 28[edi],ecx
+	mov	edx,		DWORD PTR 4[esi]
+	; saved r[7]
+	; ############### Calculate word 8
+	xor	ecx,		ecx
+	; sqr a[7]*a[1]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ecx,		0
+	add	ebp,		eax
+	adc	ebx,		edx
+	mov	eax,		DWORD PTR 24[esi]
+	adc	ecx,		0
+	mov	edx,		DWORD PTR 8[esi]
+	; sqr a[6]*a[2]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ecx,		0
+	add	ebp,		eax
+	adc	ebx,		edx
+	mov	eax,		DWORD PTR 20[esi]
+	adc	ecx,		0
+	mov	edx,		DWORD PTR 12[esi]
+	; sqr a[5]*a[3]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ecx,		0
+	add	ebp,		eax
+	adc	ebx,		edx
+	mov	eax,		DWORD PTR 16[esi]
+	adc	ecx,		0
+	; sqr a[4]*a[4]
+	mul	eax
+	add	ebp,		eax
+	adc	ebx,		edx
+	mov	edx,		DWORD PTR 8[esi]
+	adc	ecx,		0
+	mov	DWORD PTR 32[edi],ebp
+	mov	eax,		DWORD PTR 28[esi]
+	; saved r[8]
+	; ############### Calculate word 9
+	xor	ebp,		ebp
+	; sqr a[7]*a[2]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ebp,		0
+	add	ebx,		eax
+	adc	ecx,		edx
+	mov	eax,		DWORD PTR 24[esi]
+	adc	ebp,		0
+	mov	edx,		DWORD PTR 12[esi]
+	; sqr a[6]*a[3]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ebp,		0
+	add	ebx,		eax
+	adc	ecx,		edx
+	mov	eax,		DWORD PTR 20[esi]
+	adc	ebp,		0
+	mov	edx,		DWORD PTR 16[esi]
+	; sqr a[5]*a[4]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ebp,		0
+	add	ebx,		eax
+	adc	ecx,		edx
+	mov	eax,		DWORD PTR 28[esi]
+	adc	ebp,		0
+	mov	DWORD PTR 36[edi],ebx
+	mov	edx,		DWORD PTR 12[esi]
+	; saved r[9]
+	; ############### Calculate word 10
+	xor	ebx,		ebx
+	; sqr a[7]*a[3]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ebx,		0
+	add	ecx,		eax
+	adc	ebp,		edx
+	mov	eax,		DWORD PTR 24[esi]
+	adc	ebx,		0
+	mov	edx,		DWORD PTR 16[esi]
+	; sqr a[6]*a[4]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ebx,		0
+	add	ecx,		eax
+	adc	ebp,		edx
+	mov	eax,		DWORD PTR 20[esi]
+	adc	ebx,		0
+	; sqr a[5]*a[5]
+	mul	eax
+	add	ecx,		eax
+	adc	ebp,		edx
+	mov	edx,		DWORD PTR 16[esi]
+	adc	ebx,		0
+	mov	DWORD PTR 40[edi],ecx
+	mov	eax,		DWORD PTR 28[esi]
+	; saved r[10]
+	; ############### Calculate word 11
+	xor	ecx,		ecx
+	; sqr a[7]*a[4]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ecx,		0
+	add	ebp,		eax
+	adc	ebx,		edx
+	mov	eax,		DWORD PTR 24[esi]
+	adc	ecx,		0
+	mov	edx,		DWORD PTR 20[esi]
+	; sqr a[6]*a[5]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ecx,		0
+	add	ebp,		eax
+	adc	ebx,		edx
+	mov	eax,		DWORD PTR 28[esi]
+	adc	ecx,		0
+	mov	DWORD PTR 44[edi],ebp
+	mov	edx,		DWORD PTR 20[esi]
+	; saved r[11]
+	; ############### Calculate word 12
+	xor	ebp,		ebp
+	; sqr a[7]*a[5]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ebp,		0
+	add	ebx,		eax
+	adc	ecx,		edx
+	mov	eax,		DWORD PTR 24[esi]
+	adc	ebp,		0
+	; sqr a[6]*a[6]
+	mul	eax
+	add	ebx,		eax
+	adc	ecx,		edx
+	mov	edx,		DWORD PTR 24[esi]
+	adc	ebp,		0
+	mov	DWORD PTR 48[edi],ebx
+	mov	eax,		DWORD PTR 28[esi]
+	; saved r[12]
+	; ############### Calculate word 13
+	xor	ebx,		ebx
+	; sqr a[7]*a[6]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ebx,		0
+	add	ecx,		eax
+	adc	ebp,		edx
+	mov	eax,		DWORD PTR 28[esi]
+	adc	ebx,		0
+	mov	DWORD PTR 52[edi],ecx
+	; saved r[13]
+	; ############### Calculate word 14
+	xor	ecx,		ecx
+	; sqr a[7]*a[7]
+	mul	eax
+	add	ebp,		eax
+	adc	ebx,		edx
+	adc	ecx,		0
+	mov	DWORD PTR 56[edi],ebp
+	; saved r[14]
+	mov	DWORD PTR 60[edi],ebx
+	pop	ebx
+	pop	ebp
+	pop	edi
+	pop	esi
+	ret
+_bn_sqr_comba8 ENDP
+_TEXT	ENDS
+_TEXT	SEGMENT
+PUBLIC	_bn_sqr_comba4
+
+_bn_sqr_comba4 PROC NEAR
+	push	esi
+	push	edi
+	push	ebp
+	push	ebx
+	mov	edi,		DWORD PTR 20[esp]
+	mov	esi,		DWORD PTR 24[esp]
+	xor	ebx,		ebx
+	xor	ecx,		ecx
+	mov	eax,		DWORD PTR [esi]
+	; ############### Calculate word 0
+	xor	ebp,		ebp
+	; sqr a[0]*a[0]
+	mul	eax
+	add	ebx,		eax
+	adc	ecx,		edx
+	mov	edx,		DWORD PTR [esi]
+	adc	ebp,		0
+	mov	DWORD PTR [edi],ebx
+	mov	eax,		DWORD PTR 4[esi]
+	; saved r[0]
+	; ############### Calculate word 1
+	xor	ebx,		ebx
+	; sqr a[1]*a[0]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ebx,		0
+	add	ecx,		eax
+	adc	ebp,		edx
+	mov	eax,		DWORD PTR 8[esi]
+	adc	ebx,		0
+	mov	DWORD PTR 4[edi],ecx
+	mov	edx,		DWORD PTR [esi]
+	; saved r[1]
+	; ############### Calculate word 2
+	xor	ecx,		ecx
+	; sqr a[2]*a[0]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ecx,		0
+	add	ebp,		eax
+	adc	ebx,		edx
+	mov	eax,		DWORD PTR 4[esi]
+	adc	ecx,		0
+	; sqr a[1]*a[1]
+	mul	eax
+	add	ebp,		eax
+	adc	ebx,		edx
+	mov	edx,		DWORD PTR [esi]
+	adc	ecx,		0
+	mov	DWORD PTR 8[edi],ebp
+	mov	eax,		DWORD PTR 12[esi]
+	; saved r[2]
+	; ############### Calculate word 3
+	xor	ebp,		ebp
+	; sqr a[3]*a[0]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ebp,		0
+	add	ebx,		eax
+	adc	ecx,		edx
+	mov	eax,		DWORD PTR 8[esi]
+	adc	ebp,		0
+	mov	edx,		DWORD PTR 4[esi]
+	; sqr a[2]*a[1]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ebp,		0
+	add	ebx,		eax
+	adc	ecx,		edx
+	mov	eax,		DWORD PTR 12[esi]
+	adc	ebp,		0
+	mov	DWORD PTR 12[edi],ebx
+	mov	edx,		DWORD PTR 4[esi]
+	; saved r[3]
+	; ############### Calculate word 4
+	xor	ebx,		ebx
+	; sqr a[3]*a[1]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ebx,		0
+	add	ecx,		eax
+	adc	ebp,		edx
+	mov	eax,		DWORD PTR 8[esi]
+	adc	ebx,		0
+	; sqr a[2]*a[2]
+	mul	eax
+	add	ecx,		eax
+	adc	ebp,		edx
+	mov	edx,		DWORD PTR 8[esi]
+	adc	ebx,		0
+	mov	DWORD PTR 16[edi],ecx
+	mov	eax,		DWORD PTR 12[esi]
+	; saved r[4]
+	; ############### Calculate word 5
+	xor	ecx,		ecx
+	; sqr a[3]*a[2]
+	mul	edx
+	add	eax,		eax
+	adc	edx,		edx
+	adc	ecx,		0
+	add	ebp,		eax
+	adc	ebx,		edx
+	mov	eax,		DWORD PTR 12[esi]
+	adc	ecx,		0
+	mov	DWORD PTR 20[edi],ebp
+	; saved r[5]
+	; ############### Calculate word 6
+	xor	ebp,		ebp
+	; sqr a[3]*a[3]
+	mul	eax
+	add	ebx,		eax
+	adc	ecx,		edx
+	adc	ebp,		0
+	mov	DWORD PTR 24[edi],ebx
+	; saved r[6]
+	mov	DWORD PTR 28[edi],ecx
+	pop	ebx
+	pop	ebp
+	pop	edi
+	pop	esi
+	ret
+_bn_sqr_comba4 ENDP
+_TEXT	ENDS
 END
diff --git a/crypto/bn/asm/bn86unix.cpp b/crypto/bn/asm/bn86unix.cpp
index 6470220..639a3ac 100644
--- a/crypto/bn/asm/bn86unix.cpp
+++ b/crypto/bn/asm/bn86unix.cpp
@@ -12,8 +12,13 @@
 #define bn_mul_add_words _bn_mul_add_words
 #define bn_mul_words _bn_mul_words
 #define bn_sqr_words _bn_sqr_words
-#define bn_div64 _bn_div64
+#define bn_div_words _bn_div_words
 #define bn_add_words _bn_add_words
+#define bn_sub_words _bn_sub_words
+#define bn_mul_comba8 _bn_mul_comba8
+#define bn_mul_comba4 _bn_mul_comba4
+#define bn_sqr_comba8 _bn_sqr_comba8
+#define bn_sqr_comba4 _bn_sqr_comba4
 
 #endif
 
@@ -544,9 +549,9 @@
 .ident	"bn_sqr_words"
 .text
 	.align ALIGN
-.globl bn_div64
-	TYPE(bn_div64,@function)
-bn_div64:
+.globl bn_div_words
+	TYPE(bn_div_words,@function)
+bn_div_words:
 	pushl	%ebp
 	pushl	%ebx
 	pushl	%esi
@@ -561,9 +566,9 @@
 	popl	%ebx
 	popl	%ebp
 	ret
-.bn_div64_end:
-	SIZE(bn_div64,.bn_div64_end-bn_div64)
-.ident	"bn_div64"
+.bn_div_words_end:
+	SIZE(bn_div_words,.bn_div_words_end-bn_div_words)
+.ident	"bn_div_words"
 .text
 	.align ALIGN
 .globl bn_add_words
@@ -741,7 +746,6 @@
 	adcl	$0,		%eax
 	movl	%ecx,		24(%ebx)
 .L013aw_end:
-	movl	%eax,		%eax
 	popl	%edi
 	popl	%esi
 	popl	%ebx
@@ -750,3 +754,1448 @@
 .bn_add_words_end:
 	SIZE(bn_add_words,.bn_add_words_end-bn_add_words)
 .ident	"bn_add_words"
+.text
+	.align ALIGN
+.globl bn_sub_words
+	TYPE(bn_sub_words,@function)
+bn_sub_words:
+	pushl	%ebp
+	pushl	%ebx
+	pushl	%esi
+	pushl	%edi
+
+
+	movl	20(%esp),	%ebx
+	movl	24(%esp),	%esi
+	movl	28(%esp),	%edi
+	movl	32(%esp),	%ebp
+	xorl	%eax,		%eax
+	andl	$4294967288,	%ebp
+	jz	.L014aw_finish
+.L015aw_loop:
+	/* Round 0 */
+	movl	(%esi),		%ecx
+	movl	(%edi),		%edx
+	subl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	subl	%edx,		%ecx
+	adcl	$0,		%eax
+	movl	%ecx,		(%ebx)
+	/* Round 1 */
+	movl	4(%esi),	%ecx
+	movl	4(%edi),	%edx
+	subl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	subl	%edx,		%ecx
+	adcl	$0,		%eax
+	movl	%ecx,		4(%ebx)
+	/* Round 2 */
+	movl	8(%esi),	%ecx
+	movl	8(%edi),	%edx
+	subl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	subl	%edx,		%ecx
+	adcl	$0,		%eax
+	movl	%ecx,		8(%ebx)
+	/* Round 3 */
+	movl	12(%esi),	%ecx
+	movl	12(%edi),	%edx
+	subl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	subl	%edx,		%ecx
+	adcl	$0,		%eax
+	movl	%ecx,		12(%ebx)
+	/* Round 4 */
+	movl	16(%esi),	%ecx
+	movl	16(%edi),	%edx
+	subl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	subl	%edx,		%ecx
+	adcl	$0,		%eax
+	movl	%ecx,		16(%ebx)
+	/* Round 5 */
+	movl	20(%esi),	%ecx
+	movl	20(%edi),	%edx
+	subl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	subl	%edx,		%ecx
+	adcl	$0,		%eax
+	movl	%ecx,		20(%ebx)
+	/* Round 6 */
+	movl	24(%esi),	%ecx
+	movl	24(%edi),	%edx
+	subl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	subl	%edx,		%ecx
+	adcl	$0,		%eax
+	movl	%ecx,		24(%ebx)
+	/* Round 7 */
+	movl	28(%esi),	%ecx
+	movl	28(%edi),	%edx
+	subl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	subl	%edx,		%ecx
+	adcl	$0,		%eax
+	movl	%ecx,		28(%ebx)
+
+	addl	$32,		%esi
+	addl	$32,		%edi
+	addl	$32,		%ebx
+	subl	$8,		%ebp
+	jnz	.L015aw_loop
+.L014aw_finish:
+	movl	32(%esp),	%ebp
+	andl	$7,		%ebp
+	jz	.L016aw_end
+	/* Tail Round 0 */
+	movl	(%esi),		%ecx
+	movl	(%edi),		%edx
+	subl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	subl	%edx,		%ecx
+	adcl	$0,		%eax
+	decl	%ebp
+	movl	%ecx,		(%ebx)
+	jz	.L016aw_end
+	/* Tail Round 1 */
+	movl	4(%esi),	%ecx
+	movl	4(%edi),	%edx
+	subl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	subl	%edx,		%ecx
+	adcl	$0,		%eax
+	decl	%ebp
+	movl	%ecx,		4(%ebx)
+	jz	.L016aw_end
+	/* Tail Round 2 */
+	movl	8(%esi),	%ecx
+	movl	8(%edi),	%edx
+	subl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	subl	%edx,		%ecx
+	adcl	$0,		%eax
+	decl	%ebp
+	movl	%ecx,		8(%ebx)
+	jz	.L016aw_end
+	/* Tail Round 3 */
+	movl	12(%esi),	%ecx
+	movl	12(%edi),	%edx
+	subl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	subl	%edx,		%ecx
+	adcl	$0,		%eax
+	decl	%ebp
+	movl	%ecx,		12(%ebx)
+	jz	.L016aw_end
+	/* Tail Round 4 */
+	movl	16(%esi),	%ecx
+	movl	16(%edi),	%edx
+	subl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	subl	%edx,		%ecx
+	adcl	$0,		%eax
+	decl	%ebp
+	movl	%ecx,		16(%ebx)
+	jz	.L016aw_end
+	/* Tail Round 5 */
+	movl	20(%esi),	%ecx
+	movl	20(%edi),	%edx
+	subl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	subl	%edx,		%ecx
+	adcl	$0,		%eax
+	decl	%ebp
+	movl	%ecx,		20(%ebx)
+	jz	.L016aw_end
+	/* Tail Round 6 */
+	movl	24(%esi),	%ecx
+	movl	24(%edi),	%edx
+	subl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	subl	%edx,		%ecx
+	adcl	$0,		%eax
+	movl	%ecx,		24(%ebx)
+.L016aw_end:
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	popl	%ebp
+	ret
+.bn_sub_words_end:
+	SIZE(bn_sub_words,.bn_sub_words_end-bn_sub_words)
+.ident	"bn_sub_words"
+.text
+	.align ALIGN
+.globl bn_mul_comba8
+	TYPE(bn_mul_comba8,@function)
+bn_mul_comba8:
+	pushl	%esi
+	movl	12(%esp),	%esi
+	pushl	%edi
+	movl	20(%esp),	%edi
+	pushl	%ebp
+	pushl	%ebx
+	xorl	%ebx,		%ebx
+	movl	(%esi),		%eax
+	xorl	%ecx,		%ecx
+	movl	(%edi),		%edx
+	/* ################## Calculate word 0 */
+	xorl	%ebp,		%ebp
+	/* mul a[0]*b[0] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	movl	(%edi),		%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		(%eax)
+	movl	4(%esi),	%eax
+	/* saved r[0] */
+	/* ################## Calculate word 1 */
+	xorl	%ebx,		%ebx
+	/* mul a[1]*b[0] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	(%esi),		%eax
+	adcl	%edx,		%ebp
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[0]*b[1] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebp
+	movl	(%edi),		%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		4(%eax)
+	movl	8(%esi),	%eax
+	/* saved r[1] */
+	/* ################## Calculate word 2 */
+	xorl	%ecx,		%ecx
+	/* mul a[2]*b[0] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	4(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[1]*b[1] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	(%esi),		%eax
+	adcl	%edx,		%ebx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[0]*b[2] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebx
+	movl	(%edi),		%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		8(%eax)
+	movl	12(%esi),	%eax
+	/* saved r[2] */
+	/* ################## Calculate word 3 */
+	xorl	%ebp,		%ebp
+	/* mul a[3]*b[0] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[2]*b[1] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[1]*b[2] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	(%esi),		%eax
+	adcl	%edx,		%ecx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[0]*b[3] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	movl	(%edi),		%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		12(%eax)
+	movl	16(%esi),	%eax
+	/* saved r[3] */
+	/* ################## Calculate word 4 */
+	xorl	%ebx,		%ebx
+	/* mul a[4]*b[0] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	12(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[3]*b[1] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	8(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[2]*b[2] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[1]*b[3] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	(%esi),		%eax
+	adcl	%edx,		%ebp
+	movl	16(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[0]*b[4] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebp
+	movl	(%edi),		%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		16(%eax)
+	movl	20(%esi),	%eax
+	/* saved r[4] */
+	/* ################## Calculate word 5 */
+	xorl	%ecx,		%ecx
+	/* mul a[5]*b[0] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	16(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	4(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[4]*b[1] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	12(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[3]*b[2] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[2]*b[3] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	16(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[1]*b[4] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	(%esi),		%eax
+	adcl	%edx,		%ebx
+	movl	20(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[0]*b[5] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebx
+	movl	(%edi),		%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		20(%eax)
+	movl	24(%esi),	%eax
+	/* saved r[5] */
+	/* ################## Calculate word 6 */
+	xorl	%ebp,		%ebp
+	/* mul a[6]*b[0] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[5]*b[1] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	16(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[4]*b[2] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	12(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[3]*b[3] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	16(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[2]*b[4] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	20(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[1]*b[5] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	(%esi),		%eax
+	adcl	%edx,		%ecx
+	movl	24(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[0]*b[6] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	movl	(%edi),		%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		24(%eax)
+	movl	28(%esi),	%eax
+	/* saved r[6] */
+	/* ################## Calculate word 7 */
+	xorl	%ebx,		%ebx
+	/* mul a[7]*b[0] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	24(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[6]*b[1] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	8(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[5]*b[2] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	16(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[4]*b[3] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	12(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	16(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[3]*b[4] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	20(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[2]*b[5] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	24(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[1]*b[6] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	(%esi),		%eax
+	adcl	%edx,		%ebp
+	movl	28(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[0]*b[7] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebp
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		28(%eax)
+	movl	28(%esi),	%eax
+	/* saved r[7] */
+	/* ################## Calculate word 8 */
+	xorl	%ecx,		%ecx
+	/* mul a[7]*b[1] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	24(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[6]*b[2] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[5]*b[3] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	16(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	16(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[4]*b[4] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	12(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	20(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[3]*b[5] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	24(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[2]*b[6] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	28(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[1]*b[7] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		32(%eax)
+	movl	28(%esi),	%eax
+	/* saved r[8] */
+	/* ################## Calculate word 9 */
+	xorl	%ebp,		%ebp
+	/* mul a[7]*b[2] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	24(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[6]*b[3] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	16(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[5]*b[4] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	16(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	20(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[4]*b[5] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	12(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	24(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[3]*b[6] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	28(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[2]*b[7] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		36(%eax)
+	movl	28(%esi),	%eax
+	/* saved r[9] */
+	/* ################## Calculate word 10 */
+	xorl	%ebx,		%ebx
+	/* mul a[7]*b[3] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	24(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	16(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[6]*b[4] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	20(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[5]*b[5] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	16(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	24(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[4]*b[6] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	12(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	28(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[3]*b[7] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebp
+	movl	16(%edi),	%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		40(%eax)
+	movl	28(%esi),	%eax
+	/* saved r[10] */
+	/* ################## Calculate word 11 */
+	xorl	%ecx,		%ecx
+	/* mul a[7]*b[4] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	24(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	20(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[6]*b[5] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	24(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[5]*b[6] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	16(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	28(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[4]*b[7] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebx
+	movl	20(%edi),	%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		44(%eax)
+	movl	28(%esi),	%eax
+	/* saved r[11] */
+	/* ################## Calculate word 12 */
+	xorl	%ebp,		%ebp
+	/* mul a[7]*b[5] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	24(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	24(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[6]*b[6] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	28(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[5]*b[7] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	movl	24(%edi),	%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		48(%eax)
+	movl	28(%esi),	%eax
+	/* saved r[12] */
+	/* ################## Calculate word 13 */
+	xorl	%ebx,		%ebx
+	/* mul a[7]*b[6] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	24(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	28(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[6]*b[7] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebp
+	movl	28(%edi),	%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		52(%eax)
+	movl	28(%esi),	%eax
+	/* saved r[13] */
+	/* ################## Calculate word 14 */
+	xorl	%ecx,		%ecx
+	/* mul a[7]*b[7] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebx
+	adcl	$0,		%ecx
+	movl	%ebp,		56(%eax)
+	/* saved r[14] */
+	/* save r[15] */
+	movl	%ebx,		60(%eax)
+	popl	%ebx
+	popl	%ebp
+	popl	%edi
+	popl	%esi
+	ret
+.bn_mul_comba8_end:
+	SIZE(bn_mul_comba8,.bn_mul_comba8_end-bn_mul_comba8)
+.ident	"desasm.pl"
+.text
+	.align ALIGN
+.globl bn_mul_comba4
+	TYPE(bn_mul_comba4,@function)
+bn_mul_comba4:
+	pushl	%esi
+	movl	12(%esp),	%esi
+	pushl	%edi
+	movl	20(%esp),	%edi
+	pushl	%ebp
+	pushl	%ebx
+	xorl	%ebx,		%ebx
+	movl	(%esi),		%eax
+	xorl	%ecx,		%ecx
+	movl	(%edi),		%edx
+	/* ################## Calculate word 0 */
+	xorl	%ebp,		%ebp
+	/* mul a[0]*b[0] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	movl	(%edi),		%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		(%eax)
+	movl	4(%esi),	%eax
+	/* saved r[0] */
+	/* ################## Calculate word 1 */
+	xorl	%ebx,		%ebx
+	/* mul a[1]*b[0] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	(%esi),		%eax
+	adcl	%edx,		%ebp
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[0]*b[1] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebp
+	movl	(%edi),		%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		4(%eax)
+	movl	8(%esi),	%eax
+	/* saved r[1] */
+	/* ################## Calculate word 2 */
+	xorl	%ecx,		%ecx
+	/* mul a[2]*b[0] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	4(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[1]*b[1] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	(%esi),		%eax
+	adcl	%edx,		%ebx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[0]*b[2] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebx
+	movl	(%edi),		%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		8(%eax)
+	movl	12(%esi),	%eax
+	/* saved r[2] */
+	/* ################## Calculate word 3 */
+	xorl	%ebp,		%ebp
+	/* mul a[3]*b[0] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[2]*b[1] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[1]*b[2] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	(%esi),		%eax
+	adcl	%edx,		%ecx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[0]*b[3] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		12(%eax)
+	movl	12(%esi),	%eax
+	/* saved r[3] */
+	/* ################## Calculate word 4 */
+	xorl	%ebx,		%ebx
+	/* mul a[3]*b[1] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	8(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[2]*b[2] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[1]*b[3] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebp
+	movl	8(%edi),	%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		16(%eax)
+	movl	12(%esi),	%eax
+	/* saved r[4] */
+	/* ################## Calculate word 5 */
+	xorl	%ecx,		%ecx
+	/* mul a[3]*b[2] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[2]*b[3] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		20(%eax)
+	movl	12(%esi),	%eax
+	/* saved r[5] */
+	/* ################## Calculate word 6 */
+	xorl	%ebp,		%ebp
+	/* mul a[3]*b[3] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	adcl	$0,		%ebp
+	movl	%ebx,		24(%eax)
+	/* saved r[6] */
+	/* save r[7] */
+	movl	%ecx,		28(%eax)
+	popl	%ebx
+	popl	%ebp
+	popl	%edi
+	popl	%esi
+	ret
+.bn_mul_comba4_end:
+	SIZE(bn_mul_comba4,.bn_mul_comba4_end-bn_mul_comba4)
+.ident	"desasm.pl"
+.text
+	.align ALIGN
+.globl bn_sqr_comba8
+	TYPE(bn_sqr_comba8,@function)
+bn_sqr_comba8:
+	pushl	%esi
+	pushl	%edi
+	pushl	%ebp
+	pushl	%ebx
+	movl	20(%esp),	%edi
+	movl	24(%esp),	%esi
+	xorl	%ebx,		%ebx
+	xorl	%ecx,		%ecx
+	movl	(%esi),		%eax
+	/* ############### Calculate word 0 */
+	xorl	%ebp,		%ebp
+	/* sqr a[0]*a[0] */
+	mull	%eax
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	(%esi),		%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		(%edi)
+	movl	4(%esi),	%eax
+	/* saved r[0] */
+	/* ############### Calculate word 1 */
+	xorl	%ebx,		%ebx
+	/* sqr a[1]*a[0] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	8(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	%ecx,		4(%edi)
+	movl	(%esi),		%edx
+	/* saved r[1] */
+	/* ############### Calculate word 2 */
+	xorl	%ecx,		%ecx
+	/* sqr a[2]*a[0] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	4(%esi),	%eax
+	adcl	$0,		%ecx
+	/* sqr a[1]*a[1] */
+	mull	%eax
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	(%esi),		%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		8(%edi)
+	movl	12(%esi),	%eax
+	/* saved r[2] */
+	/* ############### Calculate word 3 */
+	xorl	%ebp,		%ebp
+	/* sqr a[3]*a[0] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	8(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	4(%esi),	%edx
+	/* sqr a[2]*a[1] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	16(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	%ebx,		12(%edi)
+	movl	(%esi),		%edx
+	/* saved r[3] */
+	/* ############### Calculate word 4 */
+	xorl	%ebx,		%ebx
+	/* sqr a[4]*a[0] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	12(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	4(%esi),	%edx
+	/* sqr a[3]*a[1] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	8(%esi),	%eax
+	adcl	$0,		%ebx
+	/* sqr a[2]*a[2] */
+	mull	%eax
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	(%esi),		%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		16(%edi)
+	movl	20(%esi),	%eax
+	/* saved r[4] */
+	/* ############### Calculate word 5 */
+	xorl	%ecx,		%ecx
+	/* sqr a[5]*a[0] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	16(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	4(%esi),	%edx
+	/* sqr a[4]*a[1] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	12(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	8(%esi),	%edx
+	/* sqr a[3]*a[2] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	24(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	%ebp,		20(%edi)
+	movl	(%esi),		%edx
+	/* saved r[5] */
+	/* ############### Calculate word 6 */
+	xorl	%ebp,		%ebp
+	/* sqr a[6]*a[0] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	20(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	4(%esi),	%edx
+	/* sqr a[5]*a[1] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	16(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	8(%esi),	%edx
+	/* sqr a[4]*a[2] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	12(%esi),	%eax
+	adcl	$0,		%ebp
+	/* sqr a[3]*a[3] */
+	mull	%eax
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	(%esi),		%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		24(%edi)
+	movl	28(%esi),	%eax
+	/* saved r[6] */
+	/* ############### Calculate word 7 */
+	xorl	%ebx,		%ebx
+	/* sqr a[7]*a[0] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	24(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	4(%esi),	%edx
+	/* sqr a[6]*a[1] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	20(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	8(%esi),	%edx
+	/* sqr a[5]*a[2] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	16(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	12(%esi),	%edx
+	/* sqr a[4]*a[3] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	28(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	%ecx,		28(%edi)
+	movl	4(%esi),	%edx
+	/* saved r[7] */
+	/* ############### Calculate word 8 */
+	xorl	%ecx,		%ecx
+	/* sqr a[7]*a[1] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	24(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	8(%esi),	%edx
+	/* sqr a[6]*a[2] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	20(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	12(%esi),	%edx
+	/* sqr a[5]*a[3] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	16(%esi),	%eax
+	adcl	$0,		%ecx
+	/* sqr a[4]*a[4] */
+	mull	%eax
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	8(%esi),	%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		32(%edi)
+	movl	28(%esi),	%eax
+	/* saved r[8] */
+	/* ############### Calculate word 9 */
+	xorl	%ebp,		%ebp
+	/* sqr a[7]*a[2] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	24(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	12(%esi),	%edx
+	/* sqr a[6]*a[3] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	20(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	16(%esi),	%edx
+	/* sqr a[5]*a[4] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	28(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	%ebx,		36(%edi)
+	movl	12(%esi),	%edx
+	/* saved r[9] */
+	/* ############### Calculate word 10 */
+	xorl	%ebx,		%ebx
+	/* sqr a[7]*a[3] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	24(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	16(%esi),	%edx
+	/* sqr a[6]*a[4] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	20(%esi),	%eax
+	adcl	$0,		%ebx
+	/* sqr a[5]*a[5] */
+	mull	%eax
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	16(%esi),	%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		40(%edi)
+	movl	28(%esi),	%eax
+	/* saved r[10] */
+	/* ############### Calculate word 11 */
+	xorl	%ecx,		%ecx
+	/* sqr a[7]*a[4] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	24(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	20(%esi),	%edx
+	/* sqr a[6]*a[5] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	28(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	%ebp,		44(%edi)
+	movl	20(%esi),	%edx
+	/* saved r[11] */
+	/* ############### Calculate word 12 */
+	xorl	%ebp,		%ebp
+	/* sqr a[7]*a[5] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	24(%esi),	%eax
+	adcl	$0,		%ebp
+	/* sqr a[6]*a[6] */
+	mull	%eax
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	24(%esi),	%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		48(%edi)
+	movl	28(%esi),	%eax
+	/* saved r[12] */
+	/* ############### Calculate word 13 */
+	xorl	%ebx,		%ebx
+	/* sqr a[7]*a[6] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	28(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	%ecx,		52(%edi)
+	/* saved r[13] */
+	/* ############### Calculate word 14 */
+	xorl	%ecx,		%ecx
+	/* sqr a[7]*a[7] */
+	mull	%eax
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	adcl	$0,		%ecx
+	movl	%ebp,		56(%edi)
+	/* saved r[14] */
+	movl	%ebx,		60(%edi)
+	popl	%ebx
+	popl	%ebp
+	popl	%edi
+	popl	%esi
+	ret
+.bn_sqr_comba8_end:
+	SIZE(bn_sqr_comba8,.bn_sqr_comba8_end-bn_sqr_comba8)
+.ident	"desasm.pl"
+.text
+	.align ALIGN
+.globl bn_sqr_comba4
+	TYPE(bn_sqr_comba4,@function)
+bn_sqr_comba4:
+	pushl	%esi
+	pushl	%edi
+	pushl	%ebp
+	pushl	%ebx
+	movl	20(%esp),	%edi
+	movl	24(%esp),	%esi
+	xorl	%ebx,		%ebx
+	xorl	%ecx,		%ecx
+	movl	(%esi),		%eax
+	/* ############### Calculate word 0 */
+	xorl	%ebp,		%ebp
+	/* sqr a[0]*a[0] */
+	mull	%eax
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	(%esi),		%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		(%edi)
+	movl	4(%esi),	%eax
+	/* saved r[0] */
+	/* ############### Calculate word 1 */
+	xorl	%ebx,		%ebx
+	/* sqr a[1]*a[0] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	8(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	%ecx,		4(%edi)
+	movl	(%esi),		%edx
+	/* saved r[1] */
+	/* ############### Calculate word 2 */
+	xorl	%ecx,		%ecx
+	/* sqr a[2]*a[0] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	4(%esi),	%eax
+	adcl	$0,		%ecx
+	/* sqr a[1]*a[1] */
+	mull	%eax
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	(%esi),		%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		8(%edi)
+	movl	12(%esi),	%eax
+	/* saved r[2] */
+	/* ############### Calculate word 3 */
+	xorl	%ebp,		%ebp
+	/* sqr a[3]*a[0] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	8(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	4(%esi),	%edx
+	/* sqr a[2]*a[1] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	12(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	%ebx,		12(%edi)
+	movl	4(%esi),	%edx
+	/* saved r[3] */
+	/* ############### Calculate word 4 */
+	xorl	%ebx,		%ebx
+	/* sqr a[3]*a[1] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	8(%esi),	%eax
+	adcl	$0,		%ebx
+	/* sqr a[2]*a[2] */
+	mull	%eax
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	8(%esi),	%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		16(%edi)
+	movl	12(%esi),	%eax
+	/* saved r[4] */
+	/* ############### Calculate word 5 */
+	xorl	%ecx,		%ecx
+	/* sqr a[3]*a[2] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	12(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	%ebp,		20(%edi)
+	/* saved r[5] */
+	/* ############### Calculate word 6 */
+	xorl	%ebp,		%ebp
+	/* sqr a[3]*a[3] */
+	mull	%eax
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	adcl	$0,		%ebp
+	movl	%ebx,		24(%edi)
+	/* saved r[6] */
+	movl	%ecx,		28(%edi)
+	popl	%ebx
+	popl	%ebp
+	popl	%edi
+	popl	%esi
+	ret
+.bn_sqr_comba4_end:
+	SIZE(bn_sqr_comba4,.bn_sqr_comba4_end-bn_sqr_comba4)
+.ident	"desasm.pl"
diff --git a/crypto/bn/asm/ca.pl b/crypto/bn/asm/ca.pl
new file mode 100644
index 0000000..181d1f0
--- /dev/null
+++ b/crypto/bn/asm/ca.pl
@@ -0,0 +1,33 @@
+#!/usr/local/bin/perl
+# I have this in perl so I can use more usefull register names and then convert
+# them into alpha registers.
+#
+
+push(@INC,"perlasm","../../perlasm");
+require "alpha.pl";
+require "alpha/mul_add.pl";
+require "alpha/mul.pl";
+require "alpha/sqr.pl";
+require "alpha/add.pl";
+require "alpha/sub.pl";
+require "alpha/mul_c8.pl";
+require "alpha/mul_c4.pl";
+require "alpha/sqr_c4.pl";
+require "alpha/sqr_c8.pl";
+require "alpha/div.pl";
+
+&asm_init($ARGV[0],"bn-586.pl");
+
+&bn_mul_words("bn_mul_words");
+&bn_sqr_words("bn_sqr_words");
+&bn_mul_add_words("bn_mul_add_words");
+&bn_add_words("bn_add_words");
+&bn_sub_words("bn_sub_words");
+&bn_div_words("bn_div_words");
+&bn_mul_comba8("bn_mul_comba8");
+&bn_mul_comba4("bn_mul_comba4");
+&bn_sqr_comba4("bn_sqr_comba4");
+&bn_sqr_comba8("bn_sqr_comba8");
+
+&asm_finish();
+
diff --git a/crypto/bn/asm/co-586.pl b/crypto/bn/asm/co-586.pl
new file mode 100644
index 0000000..0bcb5a6
--- /dev/null
+++ b/crypto/bn/asm/co-586.pl
@@ -0,0 +1,286 @@
+#!/usr/local/bin/perl
+
+push(@INC,"perlasm","../../perlasm");
+require "x86asm.pl";
+
+&asm_init($ARGV[0],"bn-586.pl");
+
+&bn_mul_comba("bn_mul_comba8",8);
+&bn_mul_comba("bn_mul_comba4",4);
+&bn_sqr_comba("bn_sqr_comba8",8);
+&bn_sqr_comba("bn_sqr_comba4",4);
+
+&asm_finish();
+
+sub mul_add_c
+	{
+	local($a,$ai,$b,$bi,$c0,$c1,$c2,$pos,$i,$na,$nb)=@_;
+
+	# pos == -1 if eax and edx are pre-loaded, 0 to load from next
+	# words, and 1 if load return value
+
+	&comment("mul a[$ai]*b[$bi]");
+
+	# "eax" and "edx" will always be pre-loaded.
+	# &mov("eax",&DWP($ai*4,$a,"",0)) ;
+	# &mov("edx",&DWP($bi*4,$b,"",0));
+
+	&mul("edx");
+	&add($c0,"eax");
+	 &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 0;	# laod next a
+	 &mov("eax",&wparam(0)) if $pos > 0;			# load r[]
+	 ###
+	&adc($c1,"edx");
+	 &mov("edx",&DWP(($nb)*4,$b,"",0)) if $pos == 0;	# laod next b
+	 &mov("edx",&DWP(($nb)*4,$b,"",0)) if $pos == 1;	# laod next b
+	 ###
+	&adc($c2,0);
+	 # is pos > 1, it means it is the last loop 
+	 &mov(&DWP($i*4,"eax","",0),$c0) if $pos > 0;		# save r[];
+	&mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 1;		# laod next a
+	}
+
+sub sqr_add_c
+	{
+	local($r,$a,$ai,$bi,$c0,$c1,$c2,$pos,$i,$na,$nb)=@_;
+
+	# pos == -1 if eax and edx are pre-loaded, 0 to load from next
+	# words, and 1 if load return value
+
+	&comment("sqr a[$ai]*a[$bi]");
+
+	# "eax" and "edx" will always be pre-loaded.
+	# &mov("eax",&DWP($ai*4,$a,"",0)) ;
+	# &mov("edx",&DWP($bi*4,$b,"",0));
+
+	if ($ai == $bi)
+		{ &mul("eax");}
+	else
+		{ &mul("edx");}
+	&add($c0,"eax");
+	 &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 0;	# load next a
+	 ###
+	&adc($c1,"edx");
+	 &mov("edx",&DWP(($nb)*4,$a,"",0)) if ($pos == 1) && ($na != $nb);
+	 ###
+	&adc($c2,0);
+	 # is pos > 1, it means it is the last loop 
+	 &mov(&DWP($i*4,$r,"",0),$c0) if $pos > 0;		# save r[];
+	&mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 1;		# load next b
+	}
+
+sub sqr_add_c2
+	{
+	local($r,$a,$ai,$bi,$c0,$c1,$c2,$pos,$i,$na,$nb)=@_;
+
+	# pos == -1 if eax and edx are pre-loaded, 0 to load from next
+	# words, and 1 if load return value
+
+	&comment("sqr a[$ai]*a[$bi]");
+
+	# "eax" and "edx" will always be pre-loaded.
+	# &mov("eax",&DWP($ai*4,$a,"",0)) ;
+	# &mov("edx",&DWP($bi*4,$a,"",0));
+
+	if ($ai == $bi)
+		{ &mul("eax");}
+	else
+		{ &mul("edx");}
+	&add("eax","eax");
+	 ###
+	&adc("edx","edx");
+	 ###
+	&adc($c2,0);
+	 &add($c0,"eax");
+	&adc($c1,"edx");
+	 &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 0;	# load next a
+	 &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 1;	# load next b
+	&adc($c2,0);
+	&mov(&DWP($i*4,$r,"",0),$c0) if $pos > 0;		# save r[];
+	 &mov("edx",&DWP(($nb)*4,$a,"",0)) if ($pos <= 1) && ($na != $nb);
+	 ###
+	}
+
+sub bn_mul_comba
+	{
+	local($name,$num)=@_;
+	local($a,$b,$c0,$c1,$c2);
+	local($i,$as,$ae,$bs,$be,$ai,$bi);
+	local($tot,$end);
+
+	&function_begin_B($name,"");
+
+	$c0="ebx";
+	$c1="ecx";
+	$c2="ebp";
+	$a="esi";
+	$b="edi";
+	
+	$as=0;
+	$ae=0;
+	$bs=0;
+	$be=0;
+	$tot=$num+$num-1;
+
+	&push("esi");
+	 &mov($a,&wparam(1));
+	&push("edi");
+	 &mov($b,&wparam(2));
+	&push("ebp");
+	 &push("ebx");
+
+	&xor($c0,$c0);
+	 &mov("eax",&DWP(0,$a,"",0));	# load the first word 
+	&xor($c1,$c1);
+	 &mov("edx",&DWP(0,$b,"",0));	# load the first second 
+
+	for ($i=0; $i<$tot; $i++)
+		{
+		$ai=$as;
+		$bi=$bs;
+		$end=$be+1;
+
+		&comment("################## Calculate word $i"); 
+
+		for ($j=$bs; $j<$end; $j++)
+			{
+			&xor($c2,$c2) if ($j == $bs);
+			if (($j+1) == $end)
+				{
+				$v=1;
+				$v=2 if (($i+1) == $tot);
+				}
+			else
+				{ $v=0; }
+			if (($j+1) != $end)
+				{
+				$na=($ai-1);
+				$nb=($bi+1);
+				}
+			else
+				{
+				$na=$as+($i < ($num-1));
+				$nb=$bs+($i >= ($num-1));
+				}
+#printf STDERR "[$ai,$bi] -> [$na,$nb]\n";
+			&mul_add_c($a,$ai,$b,$bi,$c0,$c1,$c2,$v,$i,$na,$nb);
+			if ($v)
+				{
+				&comment("saved r[$i]");
+				# &mov("eax",&wparam(0));
+				# &mov(&DWP($i*4,"eax","",0),$c0);
+				($c0,$c1,$c2)=($c1,$c2,$c0);
+				}
+			$ai--;
+			$bi++;
+			}
+		$as++ if ($i < ($num-1));
+		$ae++ if ($i >= ($num-1));
+
+		$bs++ if ($i >= ($num-1));
+		$be++ if ($i < ($num-1));
+		}
+	&comment("save r[$i]");
+	# &mov("eax",&wparam(0));
+	&mov(&DWP($i*4,"eax","",0),$c0);
+
+	&pop("ebx");
+	&pop("ebp");
+	&pop("edi");
+	&pop("esi");
+	&ret();
+	&function_end_B($name);
+	}
+
+sub bn_sqr_comba
+	{
+	local($name,$num)=@_;
+	local($r,$a,$c0,$c1,$c2)=@_;
+	local($i,$as,$ae,$bs,$be,$ai,$bi);
+	local($b,$tot,$end,$half);
+
+	&function_begin_B($name,"");
+
+	$c0="ebx";
+	$c1="ecx";
+	$c2="ebp";
+	$a="esi";
+	$r="edi";
+
+	&push("esi");
+	 &push("edi");
+	&push("ebp");
+	 &push("ebx");
+	&mov($r,&wparam(0));
+	 &mov($a,&wparam(1));
+	&xor($c0,$c0);
+	 &xor($c1,$c1);
+	&mov("eax",&DWP(0,$a,"",0)); # load the first word
+
+	$as=0;
+	$ae=0;
+	$bs=0;
+	$be=0;
+	$tot=$num+$num-1;
+
+	for ($i=0; $i<$tot; $i++)
+		{
+		$ai=$as;
+		$bi=$bs;
+		$end=$be+1;
+
+		&comment("############### Calculate word $i");
+		for ($j=$bs; $j<$end; $j++)
+			{
+			&xor($c2,$c2) if ($j == $bs);
+			if (($ai-1) < ($bi+1))
+				{
+				$v=1;
+				$v=2 if ($i+1) == $tot;
+				}
+			else
+				{ $v=0; }
+			if (!$v)
+				{
+				$na=$ai-1;
+				$nb=$bi+1;
+				}
+			else
+				{
+				$na=$as+($i < ($num-1));
+				$nb=$bs+($i >= ($num-1));
+				}
+			if ($ai == $bi)
+				{
+				&sqr_add_c($r,$a,$ai,$bi,
+					$c0,$c1,$c2,$v,$i,$na,$nb);
+				}
+			else
+				{
+				&sqr_add_c2($r,$a,$ai,$bi,
+					$c0,$c1,$c2,$v,$i,$na,$nb);
+				}
+			if ($v)
+				{
+				&comment("saved r[$i]");
+				#&mov(&DWP($i*4,$r,"",0),$c0);
+				($c0,$c1,$c2)=($c1,$c2,$c0);
+				last;
+				}
+			$ai--;
+			$bi++;
+			}
+		$as++ if ($i < ($num-1));
+		$ae++ if ($i >= ($num-1));
+
+		$bs++ if ($i >= ($num-1));
+		$be++ if ($i < ($num-1));
+		}
+	&mov(&DWP($i*4,$r,"",0),$c0);
+	&pop("ebx");
+	&pop("ebp");
+	&pop("edi");
+	&pop("esi");
+	&ret();
+	&function_end_B($name);
+	}
diff --git a/crypto/bn/asm/co-alpha.pl b/crypto/bn/asm/co-alpha.pl
new file mode 100644
index 0000000..23869a4
--- /dev/null
+++ b/crypto/bn/asm/co-alpha.pl
@@ -0,0 +1,116 @@
+#!/usr/local/bin/perl
+# I have this in perl so I can use more usefull register names and then convert
+# them into alpha registers.
+#
+
+push(@INC,"perlasm","../../perlasm");
+require "alpha.pl";
+
+&asm_init($ARGV[0],"bn-586.pl");
+
+print &bn_sub_words("bn_sub_words");
+
+&asm_finish();
+
+sub bn_sub_words
+	{
+	local($name)=@_;
+	local($cc,$a,$b,$r);
+
+	$cc="r0";
+	$a0="r1"; $b0="r5"; $r0="r9";  $tmp="r13";
+	$a1="r2"; $b1="r6"; $r1="r10"; $t1="r14";
+	$a2="r3"; $b2="r7"; $r2="r11";
+	$a3="r4"; $b3="r8"; $r3="r12"; $t3="r15";
+
+	$rp=&wparam(0);
+	$ap=&wparam(1);
+	$bp=&wparam(2);
+	$count=&wparam(3);
+
+	&function_begin($name,"");
+
+	&comment("");
+	&sub($count,4,$count);
+	&mov("zero",$cc);
+	&blt($count,&label("finish"));
+
+	&ld($a0,&QWPw(0,$ap));
+	&ld($b0,&QWPw(0,$bp));
+
+##########################################################
+	&set_label("loop");
+
+	&ld($a1,&QWPw(1,$ap));
+	 &cmpult($a0,$b0,$tmp);	# will we borrow?
+	&ld($b1,&QWPw(1,$bp));
+	 &sub($a0,$b0,$a0);		# do the subtract
+	&ld($a2,&QWPw(2,$ap));
+	 &cmpult($a0,$cc,$b0);	# will we borrow?
+	&ld($b2,&QWPw(2,$bp));
+	 &sub($a0,$cc,$a0);	# will we borrow?
+	&ld($a3,&QWPw(3,$ap));
+	 &add($b0,$tmp,$cc);	# add the borrows
+
+	&cmpult($a1,$b1,$t1);	# will we borrow?
+	 &sub($a1,$b1,$a1);	# do the subtract
+	&ld($b3,&QWPw(3,$bp));
+	 &cmpult($a1,$cc,$b1);	# will we borrow?
+	&sub($a1,$cc,$a1);	# will we borrow?
+	 &add($b1,$t1,$cc);	# add the borrows
+
+	&cmpult($a2,$b2,$tmp);	# will we borrow?
+	 &sub($a2,$b2,$a2);		# do the subtract
+	&st($a0,&QWPw(0,$rp));	# save
+	 &cmpult($a2,$cc,$b2);	# will we borrow?
+	&sub($a2,$cc,$a2);	# will we borrow?
+	 &add($b2,$tmp,$cc);	# add the borrows
+
+	&cmpult($a3,$b3,$t3);	# will we borrow?
+	 &sub($a3,$b3,$a3);		# do the subtract
+	&st($a1,&QWPw(1,$rp));	# save
+	 &cmpult($a3,$cc,$b3);	# will we borrow?
+	&sub($a3,$cc,$a3);	# will we borrow?
+	 &add($b3,$t3,$cc);	# add the borrows
+
+	&st($a2,&QWPw(2,$rp));	# save
+	 &sub($count,4,$count);	# count-=4
+	&st($a3,&QWPw(3,$rp));	# save
+	 &add($ap,4*$QWS,$ap);	# count+=4
+	&add($bp,4*$QWS,$bp);	# count+=4
+	 &add($rp,4*$QWS,$rp);	# count+=4
+
+	&blt($count,&label("finish"));
+	&ld($a0,&QWPw(0,$ap));
+	 &ld($b0,&QWPw(0,$bp));
+	&br(&label("loop"));
+##################################################
+	# Do the last 0..3 words
+
+	&set_label("last_loop");
+
+	&ld($a0,&QWPw(0,$ap));	# get a
+	 &ld($b0,&QWPw(0,$bp));	# get b
+	&cmpult($a0,$b0,$tmp);	# will we borrow?
+	&sub($a0,$b0,$a0);	# do the subtract
+	&cmpult($a0,$cc,$b0);	# will we borrow?
+	&sub($a0,$cc,$a0);	# will we borrow?
+	&st($a0,&QWPw(0,$rp));	# save
+	&add($b0,$tmp,$cc);	# add the borrows
+
+	&add($ap,$QWS,$ap);
+	&add($bp,$QWS,$bp);
+	&add($rp,$QWS,$rp);
+	&sub($count,1,$count);
+	&bgt($count,&label("last_loop"));
+	&function_end_A($name);
+
+######################################################
+	&set_label("finish");
+	&add($count,4,$count);
+	&bgt($count,&label("last_loop"));
+
+	&set_label("end");
+	&function_end($name);
+	}
+
diff --git a/crypto/bn/asm/co86unix.cpp b/crypto/bn/asm/co86unix.cpp
new file mode 100644
index 0000000..fa80b14
--- /dev/null
+++ b/crypto/bn/asm/co86unix.cpp
@@ -0,0 +1,1315 @@
+/* Run the C pre-processor over this file with one of the following defined
+ * ELF - elf object files,
+ * OUT - a.out object files,
+ * BSDI - BSDI style a.out object files
+ * SOL - Solaris style elf
+ */
+
+#define TYPE(a,b)       .type   a,b
+#define SIZE(a,b)       .size   a,b
+
+#if defined(OUT) || defined(BSDI)
+#define bn_mul_comba8 _bn_mul_comba8
+#define bn_mul_comba4 _bn_mul_comba4
+#define bn_sqr_comba8 _bn_sqr_comba8
+#define bn_sqr_comba4 _bn_sqr_comba4
+
+#endif
+
+#ifdef OUT
+#define OK	1
+#define ALIGN	4
+#endif
+
+#ifdef BSDI
+#define OK              1
+#define ALIGN           4
+#undef SIZE
+#undef TYPE
+#define SIZE(a,b)
+#define TYPE(a,b)
+#endif
+
+#if defined(ELF) || defined(SOL)
+#define OK              1
+#define ALIGN           16
+#endif
+
+#ifndef OK
+You need to define one of
+ELF - elf systems - linux-elf, NetBSD and DG-UX
+OUT - a.out systems - linux-a.out and FreeBSD
+SOL - solaris systems, which are elf with strange comment lines
+BSDI - a.out with a very primative version of as.
+#endif
+
+/* Let the Assembler begin :-) */
+	/* Don't even think of reading this code */
+	/* It was automatically generated by bn-586.pl */
+	/* Which is a perl program used to generate the x86 assember for */
+	/* any of elf, a.out, BSDI,Win32, or Solaris */
+	/* eric <eay@cryptsoft.com> */
+
+	.file	"bn-586.s"
+	.version	"01.01"
+gcc2_compiled.:
+.text
+	.align ALIGN
+.globl bn_mul_comba8
+	TYPE(bn_mul_comba8,@function)
+bn_mul_comba8:
+	pushl	%esi
+	movl	12(%esp),	%esi
+	pushl	%edi
+	movl	20(%esp),	%edi
+	pushl	%ebp
+	pushl	%ebx
+	xorl	%ebx,		%ebx
+	movl	(%esi),		%eax
+	xorl	%ecx,		%ecx
+	movl	(%edi),		%edx
+	/* ################## Calculate word 0 */
+	xorl	%ebp,		%ebp
+	/* mul a[0]*b[0] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	movl	(%edi),		%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		(%eax)
+	movl	4(%esi),	%eax
+	/* saved r[0] */
+	/* ################## Calculate word 1 */
+	xorl	%ebx,		%ebx
+	/* mul a[1]*b[0] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	(%esi),		%eax
+	adcl	%edx,		%ebp
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[0]*b[1] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebp
+	movl	(%edi),		%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		4(%eax)
+	movl	8(%esi),	%eax
+	/* saved r[1] */
+	/* ################## Calculate word 2 */
+	xorl	%ecx,		%ecx
+	/* mul a[2]*b[0] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	4(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[1]*b[1] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	(%esi),		%eax
+	adcl	%edx,		%ebx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[0]*b[2] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebx
+	movl	(%edi),		%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		8(%eax)
+	movl	12(%esi),	%eax
+	/* saved r[2] */
+	/* ################## Calculate word 3 */
+	xorl	%ebp,		%ebp
+	/* mul a[3]*b[0] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[2]*b[1] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[1]*b[2] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	(%esi),		%eax
+	adcl	%edx,		%ecx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[0]*b[3] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	movl	(%edi),		%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		12(%eax)
+	movl	16(%esi),	%eax
+	/* saved r[3] */
+	/* ################## Calculate word 4 */
+	xorl	%ebx,		%ebx
+	/* mul a[4]*b[0] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	12(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[3]*b[1] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	8(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[2]*b[2] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[1]*b[3] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	(%esi),		%eax
+	adcl	%edx,		%ebp
+	movl	16(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[0]*b[4] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebp
+	movl	(%edi),		%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		16(%eax)
+	movl	20(%esi),	%eax
+	/* saved r[4] */
+	/* ################## Calculate word 5 */
+	xorl	%ecx,		%ecx
+	/* mul a[5]*b[0] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	16(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	4(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[4]*b[1] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	12(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[3]*b[2] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[2]*b[3] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	16(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[1]*b[4] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	(%esi),		%eax
+	adcl	%edx,		%ebx
+	movl	20(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[0]*b[5] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebx
+	movl	(%edi),		%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		20(%eax)
+	movl	24(%esi),	%eax
+	/* saved r[5] */
+	/* ################## Calculate word 6 */
+	xorl	%ebp,		%ebp
+	/* mul a[6]*b[0] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[5]*b[1] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	16(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[4]*b[2] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	12(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[3]*b[3] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	16(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[2]*b[4] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	20(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[1]*b[5] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	(%esi),		%eax
+	adcl	%edx,		%ecx
+	movl	24(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[0]*b[6] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	movl	(%edi),		%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		24(%eax)
+	movl	28(%esi),	%eax
+	/* saved r[6] */
+	/* ################## Calculate word 7 */
+	xorl	%ebx,		%ebx
+	/* mul a[7]*b[0] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	24(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[6]*b[1] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	8(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[5]*b[2] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	16(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[4]*b[3] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	12(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	16(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[3]*b[4] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	20(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[2]*b[5] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	24(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[1]*b[6] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	(%esi),		%eax
+	adcl	%edx,		%ebp
+	movl	28(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[0]*b[7] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebp
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		28(%eax)
+	movl	28(%esi),	%eax
+	/* saved r[7] */
+	/* ################## Calculate word 8 */
+	xorl	%ecx,		%ecx
+	/* mul a[7]*b[1] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	24(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[6]*b[2] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[5]*b[3] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	16(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	16(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[4]*b[4] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	12(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	20(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[3]*b[5] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	24(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[2]*b[6] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	28(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[1]*b[7] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		32(%eax)
+	movl	28(%esi),	%eax
+	/* saved r[8] */
+	/* ################## Calculate word 9 */
+	xorl	%ebp,		%ebp
+	/* mul a[7]*b[2] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	24(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[6]*b[3] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	16(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[5]*b[4] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	16(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	20(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[4]*b[5] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	12(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	24(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[3]*b[6] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	28(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[2]*b[7] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		36(%eax)
+	movl	28(%esi),	%eax
+	/* saved r[9] */
+	/* ################## Calculate word 10 */
+	xorl	%ebx,		%ebx
+	/* mul a[7]*b[3] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	24(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	16(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[6]*b[4] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	20(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[5]*b[5] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	16(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	24(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[4]*b[6] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	12(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	28(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[3]*b[7] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebp
+	movl	16(%edi),	%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		40(%eax)
+	movl	28(%esi),	%eax
+	/* saved r[10] */
+	/* ################## Calculate word 11 */
+	xorl	%ecx,		%ecx
+	/* mul a[7]*b[4] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	24(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	20(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[6]*b[5] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	24(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[5]*b[6] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	16(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	28(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[4]*b[7] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebx
+	movl	20(%edi),	%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		44(%eax)
+	movl	28(%esi),	%eax
+	/* saved r[11] */
+	/* ################## Calculate word 12 */
+	xorl	%ebp,		%ebp
+	/* mul a[7]*b[5] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	24(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	24(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[6]*b[6] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	28(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[5]*b[7] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	movl	24(%edi),	%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		48(%eax)
+	movl	28(%esi),	%eax
+	/* saved r[12] */
+	/* ################## Calculate word 13 */
+	xorl	%ebx,		%ebx
+	/* mul a[7]*b[6] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	24(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	28(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[6]*b[7] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebp
+	movl	28(%edi),	%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		52(%eax)
+	movl	28(%esi),	%eax
+	/* saved r[13] */
+	/* ################## Calculate word 14 */
+	xorl	%ecx,		%ecx
+	/* mul a[7]*b[7] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebx
+	adcl	$0,		%ecx
+	movl	%ebp,		56(%eax)
+	/* saved r[14] */
+	/* save r[15] */
+	movl	%ebx,		60(%eax)
+	popl	%ebx
+	popl	%ebp
+	popl	%edi
+	popl	%esi
+	ret
+.bn_mul_comba8_end:
+	SIZE(bn_mul_comba8,.bn_mul_comba8_end-bn_mul_comba8)
+.ident	"desasm.pl"
+.text
+	.align ALIGN
+.globl bn_mul_comba4
+	TYPE(bn_mul_comba4,@function)
+bn_mul_comba4:
+	pushl	%esi
+	movl	12(%esp),	%esi
+	pushl	%edi
+	movl	20(%esp),	%edi
+	pushl	%ebp
+	pushl	%ebx
+	xorl	%ebx,		%ebx
+	movl	(%esi),		%eax
+	xorl	%ecx,		%ecx
+	movl	(%edi),		%edx
+	/* ################## Calculate word 0 */
+	xorl	%ebp,		%ebp
+	/* mul a[0]*b[0] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	movl	(%edi),		%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		(%eax)
+	movl	4(%esi),	%eax
+	/* saved r[0] */
+	/* ################## Calculate word 1 */
+	xorl	%ebx,		%ebx
+	/* mul a[1]*b[0] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	(%esi),		%eax
+	adcl	%edx,		%ebp
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[0]*b[1] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebp
+	movl	(%edi),		%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		4(%eax)
+	movl	8(%esi),	%eax
+	/* saved r[1] */
+	/* ################## Calculate word 2 */
+	xorl	%ecx,		%ecx
+	/* mul a[2]*b[0] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	4(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[1]*b[1] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	(%esi),		%eax
+	adcl	%edx,		%ebx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[0]*b[2] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebx
+	movl	(%edi),		%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		8(%eax)
+	movl	12(%esi),	%eax
+	/* saved r[2] */
+	/* ################## Calculate word 3 */
+	xorl	%ebp,		%ebp
+	/* mul a[3]*b[0] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[2]*b[1] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[1]*b[2] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	(%esi),		%eax
+	adcl	%edx,		%ecx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebp
+	/* mul a[0]*b[3] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		12(%eax)
+	movl	12(%esi),	%eax
+	/* saved r[3] */
+	/* ################## Calculate word 4 */
+	xorl	%ebx,		%ebx
+	/* mul a[3]*b[1] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	8(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[2]*b[2] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebx
+	/* mul a[1]*b[3] */
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebp
+	movl	8(%edi),	%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		16(%eax)
+	movl	12(%esi),	%eax
+	/* saved r[4] */
+	/* ################## Calculate word 5 */
+	xorl	%ecx,		%ecx
+	/* mul a[3]*b[2] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ecx
+	/* mul a[2]*b[3] */
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		20(%eax)
+	movl	12(%esi),	%eax
+	/* saved r[5] */
+	/* ################## Calculate word 6 */
+	xorl	%ebp,		%ebp
+	/* mul a[3]*b[3] */
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	adcl	$0,		%ebp
+	movl	%ebx,		24(%eax)
+	/* saved r[6] */
+	/* save r[7] */
+	movl	%ecx,		28(%eax)
+	popl	%ebx
+	popl	%ebp
+	popl	%edi
+	popl	%esi
+	ret
+.bn_mul_comba4_end:
+	SIZE(bn_mul_comba4,.bn_mul_comba4_end-bn_mul_comba4)
+.ident	"desasm.pl"
+.text
+	.align ALIGN
+.globl bn_sqr_comba8
+	TYPE(bn_sqr_comba8,@function)
+bn_sqr_comba8:
+	pushl	%esi
+	pushl	%edi
+	pushl	%ebp
+	pushl	%ebx
+	movl	20(%esp),	%edi
+	movl	24(%esp),	%esi
+	xorl	%ebx,		%ebx
+	xorl	%ecx,		%ecx
+	movl	(%esi),		%eax
+	/* ############### Calculate word 0 */
+	xorl	%ebp,		%ebp
+	/* sqr a[0]*a[0] */
+	mull	%eax
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	(%esi),		%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		(%edi)
+	movl	4(%esi),	%eax
+	/* saved r[0] */
+	/* ############### Calculate word 1 */
+	xorl	%ebx,		%ebx
+	/* sqr a[1]*a[0] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	8(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	%ecx,		4(%edi)
+	movl	(%esi),		%edx
+	/* saved r[1] */
+	/* ############### Calculate word 2 */
+	xorl	%ecx,		%ecx
+	/* sqr a[2]*a[0] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	4(%esi),	%eax
+	adcl	$0,		%ecx
+	/* sqr a[1]*a[1] */
+	mull	%eax
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	(%esi),		%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		8(%edi)
+	movl	12(%esi),	%eax
+	/* saved r[2] */
+	/* ############### Calculate word 3 */
+	xorl	%ebp,		%ebp
+	/* sqr a[3]*a[0] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	8(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	4(%esi),	%edx
+	/* sqr a[2]*a[1] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	16(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	%ebx,		12(%edi)
+	movl	(%esi),		%edx
+	/* saved r[3] */
+	/* ############### Calculate word 4 */
+	xorl	%ebx,		%ebx
+	/* sqr a[4]*a[0] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	12(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	4(%esi),	%edx
+	/* sqr a[3]*a[1] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	8(%esi),	%eax
+	adcl	$0,		%ebx
+	/* sqr a[2]*a[2] */
+	mull	%eax
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	(%esi),		%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		16(%edi)
+	movl	20(%esi),	%eax
+	/* saved r[4] */
+	/* ############### Calculate word 5 */
+	xorl	%ecx,		%ecx
+	/* sqr a[5]*a[0] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	16(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	4(%esi),	%edx
+	/* sqr a[4]*a[1] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	12(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	8(%esi),	%edx
+	/* sqr a[3]*a[2] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	24(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	%ebp,		20(%edi)
+	movl	(%esi),		%edx
+	/* saved r[5] */
+	/* ############### Calculate word 6 */
+	xorl	%ebp,		%ebp
+	/* sqr a[6]*a[0] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	20(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	4(%esi),	%edx
+	/* sqr a[5]*a[1] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	16(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	8(%esi),	%edx
+	/* sqr a[4]*a[2] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	12(%esi),	%eax
+	adcl	$0,		%ebp
+	/* sqr a[3]*a[3] */
+	mull	%eax
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	(%esi),		%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		24(%edi)
+	movl	28(%esi),	%eax
+	/* saved r[6] */
+	/* ############### Calculate word 7 */
+	xorl	%ebx,		%ebx
+	/* sqr a[7]*a[0] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	24(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	4(%esi),	%edx
+	/* sqr a[6]*a[1] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	20(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	8(%esi),	%edx
+	/* sqr a[5]*a[2] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	16(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	12(%esi),	%edx
+	/* sqr a[4]*a[3] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	28(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	%ecx,		28(%edi)
+	movl	4(%esi),	%edx
+	/* saved r[7] */
+	/* ############### Calculate word 8 */
+	xorl	%ecx,		%ecx
+	/* sqr a[7]*a[1] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	24(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	8(%esi),	%edx
+	/* sqr a[6]*a[2] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	20(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	12(%esi),	%edx
+	/* sqr a[5]*a[3] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	16(%esi),	%eax
+	adcl	$0,		%ecx
+	/* sqr a[4]*a[4] */
+	mull	%eax
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	8(%esi),	%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		32(%edi)
+	movl	28(%esi),	%eax
+	/* saved r[8] */
+	/* ############### Calculate word 9 */
+	xorl	%ebp,		%ebp
+	/* sqr a[7]*a[2] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	24(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	12(%esi),	%edx
+	/* sqr a[6]*a[3] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	20(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	16(%esi),	%edx
+	/* sqr a[5]*a[4] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	28(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	%ebx,		36(%edi)
+	movl	12(%esi),	%edx
+	/* saved r[9] */
+	/* ############### Calculate word 10 */
+	xorl	%ebx,		%ebx
+	/* sqr a[7]*a[3] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	24(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	16(%esi),	%edx
+	/* sqr a[6]*a[4] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	20(%esi),	%eax
+	adcl	$0,		%ebx
+	/* sqr a[5]*a[5] */
+	mull	%eax
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	16(%esi),	%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		40(%edi)
+	movl	28(%esi),	%eax
+	/* saved r[10] */
+	/* ############### Calculate word 11 */
+	xorl	%ecx,		%ecx
+	/* sqr a[7]*a[4] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	24(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	20(%esi),	%edx
+	/* sqr a[6]*a[5] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	28(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	%ebp,		44(%edi)
+	movl	20(%esi),	%edx
+	/* saved r[11] */
+	/* ############### Calculate word 12 */
+	xorl	%ebp,		%ebp
+	/* sqr a[7]*a[5] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	24(%esi),	%eax
+	adcl	$0,		%ebp
+	/* sqr a[6]*a[6] */
+	mull	%eax
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	24(%esi),	%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		48(%edi)
+	movl	28(%esi),	%eax
+	/* saved r[12] */
+	/* ############### Calculate word 13 */
+	xorl	%ebx,		%ebx
+	/* sqr a[7]*a[6] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	28(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	%ecx,		52(%edi)
+	/* saved r[13] */
+	/* ############### Calculate word 14 */
+	xorl	%ecx,		%ecx
+	/* sqr a[7]*a[7] */
+	mull	%eax
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	adcl	$0,		%ecx
+	movl	%ebp,		56(%edi)
+	/* saved r[14] */
+	movl	%ebx,		60(%edi)
+	popl	%ebx
+	popl	%ebp
+	popl	%edi
+	popl	%esi
+	ret
+.bn_sqr_comba8_end:
+	SIZE(bn_sqr_comba8,.bn_sqr_comba8_end-bn_sqr_comba8)
+.ident	"desasm.pl"
+.text
+	.align ALIGN
+.globl bn_sqr_comba4
+	TYPE(bn_sqr_comba4,@function)
+bn_sqr_comba4:
+	pushl	%esi
+	pushl	%edi
+	pushl	%ebp
+	pushl	%ebx
+	movl	20(%esp),	%edi
+	movl	24(%esp),	%esi
+	xorl	%ebx,		%ebx
+	xorl	%ecx,		%ecx
+	movl	(%esi),		%eax
+	/* ############### Calculate word 0 */
+	xorl	%ebp,		%ebp
+	/* sqr a[0]*a[0] */
+	mull	%eax
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	(%esi),		%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		(%edi)
+	movl	4(%esi),	%eax
+	/* saved r[0] */
+	/* ############### Calculate word 1 */
+	xorl	%ebx,		%ebx
+	/* sqr a[1]*a[0] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	8(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	%ecx,		4(%edi)
+	movl	(%esi),		%edx
+	/* saved r[1] */
+	/* ############### Calculate word 2 */
+	xorl	%ecx,		%ecx
+	/* sqr a[2]*a[0] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	4(%esi),	%eax
+	adcl	$0,		%ecx
+	/* sqr a[1]*a[1] */
+	mull	%eax
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	(%esi),		%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		8(%edi)
+	movl	12(%esi),	%eax
+	/* saved r[2] */
+	/* ############### Calculate word 3 */
+	xorl	%ebp,		%ebp
+	/* sqr a[3]*a[0] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	8(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	4(%esi),	%edx
+	/* sqr a[2]*a[1] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	12(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	%ebx,		12(%edi)
+	movl	4(%esi),	%edx
+	/* saved r[3] */
+	/* ############### Calculate word 4 */
+	xorl	%ebx,		%ebx
+	/* sqr a[3]*a[1] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	8(%esi),	%eax
+	adcl	$0,		%ebx
+	/* sqr a[2]*a[2] */
+	mull	%eax
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	8(%esi),	%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		16(%edi)
+	movl	12(%esi),	%eax
+	/* saved r[4] */
+	/* ############### Calculate word 5 */
+	xorl	%ecx,		%ecx
+	/* sqr a[3]*a[2] */
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	12(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	%ebp,		20(%edi)
+	/* saved r[5] */
+	/* ############### Calculate word 6 */
+	xorl	%ebp,		%ebp
+	/* sqr a[3]*a[3] */
+	mull	%eax
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	adcl	$0,		%ebp
+	movl	%ebx,		24(%edi)
+	/* saved r[6] */
+	movl	%ecx,		28(%edi)
+	popl	%ebx
+	popl	%ebp
+	popl	%edi
+	popl	%esi
+	ret
+.bn_sqr_comba4_end:
+	SIZE(bn_sqr_comba4,.bn_sqr_comba4_end-bn_sqr_comba4)
+.ident	"desasm.pl"
diff --git a/crypto/bn/asm/elf.s b/crypto/bn/asm/elf.s
new file mode 100644
index 0000000..97ad126
--- /dev/null
+++ b/crypto/bn/asm/elf.s
@@ -0,0 +1,1269 @@
+	# Don't even think of reading this code 
+	# It was automatically generated by bn-586.pl 
+	# Which is a perl program used to generate the x86 assember for 
+	# any of elf, a.out, BSDI,Win32, or Solaris 
+	# eric <eay@cryptsoft.com> 
+
+	.file	"bn-586.s"
+	.version	"01.01"
+gcc2_compiled.:
+.text
+	.align 16
+.globl bn_mul_comba8
+	.type	bn_mul_comba8,@function
+bn_mul_comba8:
+	pushl	%esi
+	movl	12(%esp),	%esi
+	pushl	%edi
+	movl	20(%esp),	%edi
+	pushl	%ebp
+	pushl	%ebx
+	xorl	%ebx,		%ebx
+	movl	(%esi),		%eax
+	xorl	%ecx,		%ecx
+	movl	(%edi),		%edx
+	# ################## Calculate word 0 
+	xorl	%ebp,		%ebp
+	# mul a[0]*b[0] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	movl	(%edi),		%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		(%eax)
+	movl	4(%esi),	%eax
+	# saved r[0] 
+	# ################## Calculate word 1 
+	xorl	%ebx,		%ebx
+	# mul a[1]*b[0] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	(%esi),		%eax
+	adcl	%edx,		%ebp
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[0]*b[1] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebp
+	movl	(%edi),		%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		4(%eax)
+	movl	8(%esi),	%eax
+	# saved r[1] 
+	# ################## Calculate word 2 
+	xorl	%ecx,		%ecx
+	# mul a[2]*b[0] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	4(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[1]*b[1] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	(%esi),		%eax
+	adcl	%edx,		%ebx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[0]*b[2] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebx
+	movl	(%edi),		%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		8(%eax)
+	movl	12(%esi),	%eax
+	# saved r[2] 
+	# ################## Calculate word 3 
+	xorl	%ebp,		%ebp
+	# mul a[3]*b[0] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[2]*b[1] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[1]*b[2] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	(%esi),		%eax
+	adcl	%edx,		%ecx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[0]*b[3] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	movl	(%edi),		%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		12(%eax)
+	movl	16(%esi),	%eax
+	# saved r[3] 
+	# ################## Calculate word 4 
+	xorl	%ebx,		%ebx
+	# mul a[4]*b[0] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	12(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[3]*b[1] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	8(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[2]*b[2] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[1]*b[3] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	(%esi),		%eax
+	adcl	%edx,		%ebp
+	movl	16(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[0]*b[4] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebp
+	movl	(%edi),		%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		16(%eax)
+	movl	20(%esi),	%eax
+	# saved r[4] 
+	# ################## Calculate word 5 
+	xorl	%ecx,		%ecx
+	# mul a[5]*b[0] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	16(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	4(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[4]*b[1] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	12(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[3]*b[2] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[2]*b[3] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	16(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[1]*b[4] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	(%esi),		%eax
+	adcl	%edx,		%ebx
+	movl	20(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[0]*b[5] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebx
+	movl	(%edi),		%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		20(%eax)
+	movl	24(%esi),	%eax
+	# saved r[5] 
+	# ################## Calculate word 6 
+	xorl	%ebp,		%ebp
+	# mul a[6]*b[0] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[5]*b[1] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	16(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[4]*b[2] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	12(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[3]*b[3] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	16(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[2]*b[4] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	20(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[1]*b[5] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	(%esi),		%eax
+	adcl	%edx,		%ecx
+	movl	24(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[0]*b[6] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	movl	(%edi),		%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		24(%eax)
+	movl	28(%esi),	%eax
+	# saved r[6] 
+	# ################## Calculate word 7 
+	xorl	%ebx,		%ebx
+	# mul a[7]*b[0] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	24(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[6]*b[1] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	8(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[5]*b[2] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	16(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[4]*b[3] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	12(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	16(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[3]*b[4] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	20(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[2]*b[5] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	24(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[1]*b[6] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	(%esi),		%eax
+	adcl	%edx,		%ebp
+	movl	28(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[0]*b[7] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebp
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		28(%eax)
+	movl	28(%esi),	%eax
+	# saved r[7] 
+	# ################## Calculate word 8 
+	xorl	%ecx,		%ecx
+	# mul a[7]*b[1] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	24(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[6]*b[2] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[5]*b[3] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	16(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	16(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[4]*b[4] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	12(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	20(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[3]*b[5] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	24(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[2]*b[6] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	28(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[1]*b[7] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		32(%eax)
+	movl	28(%esi),	%eax
+	# saved r[8] 
+	# ################## Calculate word 9 
+	xorl	%ebp,		%ebp
+	# mul a[7]*b[2] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	24(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[6]*b[3] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	16(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[5]*b[4] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	16(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	20(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[4]*b[5] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	12(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	24(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[3]*b[6] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	28(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[2]*b[7] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		36(%eax)
+	movl	28(%esi),	%eax
+	# saved r[9] 
+	# ################## Calculate word 10 
+	xorl	%ebx,		%ebx
+	# mul a[7]*b[3] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	24(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	16(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[6]*b[4] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	20(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[5]*b[5] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	16(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	24(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[4]*b[6] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	12(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	28(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[3]*b[7] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebp
+	movl	16(%edi),	%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		40(%eax)
+	movl	28(%esi),	%eax
+	# saved r[10] 
+	# ################## Calculate word 11 
+	xorl	%ecx,		%ecx
+	# mul a[7]*b[4] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	24(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	20(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[6]*b[5] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	24(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[5]*b[6] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	16(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	28(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[4]*b[7] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebx
+	movl	20(%edi),	%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		44(%eax)
+	movl	28(%esi),	%eax
+	# saved r[11] 
+	# ################## Calculate word 12 
+	xorl	%ebp,		%ebp
+	# mul a[7]*b[5] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	24(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	24(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[6]*b[6] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	28(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[5]*b[7] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	movl	24(%edi),	%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		48(%eax)
+	movl	28(%esi),	%eax
+	# saved r[12] 
+	# ################## Calculate word 13 
+	xorl	%ebx,		%ebx
+	# mul a[7]*b[6] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	24(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	28(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[6]*b[7] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebp
+	movl	28(%edi),	%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		52(%eax)
+	movl	28(%esi),	%eax
+	# saved r[13] 
+	# ################## Calculate word 14 
+	xorl	%ecx,		%ecx
+	# mul a[7]*b[7] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebx
+	adcl	$0,		%ecx
+	movl	%ebp,		56(%eax)
+	# saved r[14] 
+	# save r[15] 
+	movl	%ebx,		60(%eax)
+	popl	%ebx
+	popl	%ebp
+	popl	%edi
+	popl	%esi
+	ret
+.bn_mul_comba8_end:
+	.size	bn_mul_comba8,.bn_mul_comba8_end-bn_mul_comba8
+.ident	"desasm.pl"
+.text
+	.align 16
+.globl bn_mul_comba4
+	.type	bn_mul_comba4,@function
+bn_mul_comba4:
+	pushl	%esi
+	movl	12(%esp),	%esi
+	pushl	%edi
+	movl	20(%esp),	%edi
+	pushl	%ebp
+	pushl	%ebx
+	xorl	%ebx,		%ebx
+	movl	(%esi),		%eax
+	xorl	%ecx,		%ecx
+	movl	(%edi),		%edx
+	# ################## Calculate word 0 
+	xorl	%ebp,		%ebp
+	# mul a[0]*b[0] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	movl	(%edi),		%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		(%eax)
+	movl	4(%esi),	%eax
+	# saved r[0] 
+	# ################## Calculate word 1 
+	xorl	%ebx,		%ebx
+	# mul a[1]*b[0] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	(%esi),		%eax
+	adcl	%edx,		%ebp
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[0]*b[1] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebp
+	movl	(%edi),		%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		4(%eax)
+	movl	8(%esi),	%eax
+	# saved r[1] 
+	# ################## Calculate word 2 
+	xorl	%ecx,		%ecx
+	# mul a[2]*b[0] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	4(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[1]*b[1] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	(%esi),		%eax
+	adcl	%edx,		%ebx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[0]*b[2] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebx
+	movl	(%edi),		%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		8(%eax)
+	movl	12(%esi),	%eax
+	# saved r[2] 
+	# ################## Calculate word 3 
+	xorl	%ebp,		%ebp
+	# mul a[3]*b[0] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[2]*b[1] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[1]*b[2] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	(%esi),		%eax
+	adcl	%edx,		%ecx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[0]*b[3] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		12(%eax)
+	movl	12(%esi),	%eax
+	# saved r[3] 
+	# ################## Calculate word 4 
+	xorl	%ebx,		%ebx
+	# mul a[3]*b[1] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	8(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[2]*b[2] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[1]*b[3] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebp
+	movl	8(%edi),	%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		16(%eax)
+	movl	12(%esi),	%eax
+	# saved r[4] 
+	# ################## Calculate word 5 
+	xorl	%ecx,		%ecx
+	# mul a[3]*b[2] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[2]*b[3] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		20(%eax)
+	movl	12(%esi),	%eax
+	# saved r[5] 
+	# ################## Calculate word 6 
+	xorl	%ebp,		%ebp
+	# mul a[3]*b[3] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	adcl	$0,		%ebp
+	movl	%ebx,		24(%eax)
+	# saved r[6] 
+	# save r[7] 
+	movl	%ecx,		28(%eax)
+	popl	%ebx
+	popl	%ebp
+	popl	%edi
+	popl	%esi
+	ret
+.bn_mul_comba4_end:
+	.size	bn_mul_comba4,.bn_mul_comba4_end-bn_mul_comba4
+.ident	"desasm.pl"
+.text
+	.align 16
+.globl bn_sqr_comba8
+	.type	bn_sqr_comba8,@function
+bn_sqr_comba8:
+	pushl	%esi
+	pushl	%edi
+	pushl	%ebp
+	pushl	%ebx
+	movl	20(%esp),	%edi
+	movl	24(%esp),	%esi
+	xorl	%ebx,		%ebx
+	xorl	%ecx,		%ecx
+	movl	(%esi),		%eax
+	# ############### Calculate word 0 
+	xorl	%ebp,		%ebp
+	# sqr a[0]*a[0] 
+	mull	%eax
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	(%esi),		%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		(%edi)
+	movl	4(%esi),	%eax
+	# saved r[0] 
+	# ############### Calculate word 1 
+	xorl	%ebx,		%ebx
+	# sqr a[1]*a[0] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	8(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	%ecx,		4(%edi)
+	movl	(%esi),		%edx
+	# saved r[1] 
+	# ############### Calculate word 2 
+	xorl	%ecx,		%ecx
+	# sqr a[2]*a[0] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	4(%esi),	%eax
+	adcl	$0,		%ecx
+	# sqr a[1]*a[1] 
+	mull	%eax
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	(%esi),		%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		8(%edi)
+	movl	12(%esi),	%eax
+	# saved r[2] 
+	# ############### Calculate word 3 
+	xorl	%ebp,		%ebp
+	# sqr a[3]*a[0] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	8(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	4(%esi),	%edx
+	# sqr a[2]*a[1] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	16(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	%ebx,		12(%edi)
+	movl	(%esi),		%edx
+	# saved r[3] 
+	# ############### Calculate word 4 
+	xorl	%ebx,		%ebx
+	# sqr a[4]*a[0] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	12(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	4(%esi),	%edx
+	# sqr a[3]*a[1] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	8(%esi),	%eax
+	adcl	$0,		%ebx
+	# sqr a[2]*a[2] 
+	mull	%eax
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	(%esi),		%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		16(%edi)
+	movl	20(%esi),	%eax
+	# saved r[4] 
+	# ############### Calculate word 5 
+	xorl	%ecx,		%ecx
+	# sqr a[5]*a[0] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	16(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	4(%esi),	%edx
+	# sqr a[4]*a[1] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	12(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	8(%esi),	%edx
+	# sqr a[3]*a[2] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	24(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	%ebp,		20(%edi)
+	movl	(%esi),		%edx
+	# saved r[5] 
+	# ############### Calculate word 6 
+	xorl	%ebp,		%ebp
+	# sqr a[6]*a[0] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	20(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	4(%esi),	%edx
+	# sqr a[5]*a[1] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	16(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	8(%esi),	%edx
+	# sqr a[4]*a[2] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	12(%esi),	%eax
+	adcl	$0,		%ebp
+	# sqr a[3]*a[3] 
+	mull	%eax
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	(%esi),		%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		24(%edi)
+	movl	28(%esi),	%eax
+	# saved r[6] 
+	# ############### Calculate word 7 
+	xorl	%ebx,		%ebx
+	# sqr a[7]*a[0] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	24(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	4(%esi),	%edx
+	# sqr a[6]*a[1] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	20(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	8(%esi),	%edx
+	# sqr a[5]*a[2] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	16(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	12(%esi),	%edx
+	# sqr a[4]*a[3] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	28(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	%ecx,		28(%edi)
+	movl	4(%esi),	%edx
+	# saved r[7] 
+	# ############### Calculate word 8 
+	xorl	%ecx,		%ecx
+	# sqr a[7]*a[1] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	24(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	8(%esi),	%edx
+	# sqr a[6]*a[2] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	20(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	12(%esi),	%edx
+	# sqr a[5]*a[3] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	16(%esi),	%eax
+	adcl	$0,		%ecx
+	# sqr a[4]*a[4] 
+	mull	%eax
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	8(%esi),	%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		32(%edi)
+	movl	28(%esi),	%eax
+	# saved r[8] 
+	# ############### Calculate word 9 
+	xorl	%ebp,		%ebp
+	# sqr a[7]*a[2] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	24(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	12(%esi),	%edx
+	# sqr a[6]*a[3] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	20(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	16(%esi),	%edx
+	# sqr a[5]*a[4] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	28(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	%ebx,		36(%edi)
+	movl	12(%esi),	%edx
+	# saved r[9] 
+	# ############### Calculate word 10 
+	xorl	%ebx,		%ebx
+	# sqr a[7]*a[3] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	24(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	16(%esi),	%edx
+	# sqr a[6]*a[4] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	20(%esi),	%eax
+	adcl	$0,		%ebx
+	# sqr a[5]*a[5] 
+	mull	%eax
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	16(%esi),	%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		40(%edi)
+	movl	28(%esi),	%eax
+	# saved r[10] 
+	# ############### Calculate word 11 
+	xorl	%ecx,		%ecx
+	# sqr a[7]*a[4] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	24(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	20(%esi),	%edx
+	# sqr a[6]*a[5] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	28(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	%ebp,		44(%edi)
+	movl	20(%esi),	%edx
+	# saved r[11] 
+	# ############### Calculate word 12 
+	xorl	%ebp,		%ebp
+	# sqr a[7]*a[5] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	24(%esi),	%eax
+	adcl	$0,		%ebp
+	# sqr a[6]*a[6] 
+	mull	%eax
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	24(%esi),	%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		48(%edi)
+	movl	28(%esi),	%eax
+	# saved r[12] 
+	# ############### Calculate word 13 
+	xorl	%ebx,		%ebx
+	# sqr a[7]*a[6] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	28(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	%ecx,		52(%edi)
+	# saved r[13] 
+	# ############### Calculate word 14 
+	xorl	%ecx,		%ecx
+	# sqr a[7]*a[7] 
+	mull	%eax
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	adcl	$0,		%ecx
+	movl	%ebp,		56(%edi)
+	# saved r[14] 
+	movl	%ebx,		60(%edi)
+	popl	%ebx
+	popl	%ebp
+	popl	%edi
+	popl	%esi
+	ret
+.bn_sqr_comba8_end:
+	.size	bn_sqr_comba8,.bn_sqr_comba8_end-bn_sqr_comba8
+.ident	"desasm.pl"
+.text
+	.align 16
+.globl bn_sqr_comba4
+	.type	bn_sqr_comba4,@function
+bn_sqr_comba4:
+	pushl	%esi
+	pushl	%edi
+	pushl	%ebp
+	pushl	%ebx
+	movl	20(%esp),	%edi
+	movl	24(%esp),	%esi
+	xorl	%ebx,		%ebx
+	xorl	%ecx,		%ecx
+	movl	(%esi),		%eax
+	# ############### Calculate word 0 
+	xorl	%ebp,		%ebp
+	# sqr a[0]*a[0] 
+	mull	%eax
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	(%esi),		%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		(%edi)
+	movl	4(%esi),	%eax
+	# saved r[0] 
+	# ############### Calculate word 1 
+	xorl	%ebx,		%ebx
+	# sqr a[1]*a[0] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	8(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	%ecx,		4(%edi)
+	movl	(%esi),		%edx
+	# saved r[1] 
+	# ############### Calculate word 2 
+	xorl	%ecx,		%ecx
+	# sqr a[2]*a[0] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	4(%esi),	%eax
+	adcl	$0,		%ecx
+	# sqr a[1]*a[1] 
+	mull	%eax
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	(%esi),		%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		8(%edi)
+	movl	12(%esi),	%eax
+	# saved r[2] 
+	# ############### Calculate word 3 
+	xorl	%ebp,		%ebp
+	# sqr a[3]*a[0] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	8(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	4(%esi),	%edx
+	# sqr a[2]*a[1] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	12(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	%ebx,		12(%edi)
+	movl	4(%esi),	%edx
+	# saved r[3] 
+	# ############### Calculate word 4 
+	xorl	%ebx,		%ebx
+	# sqr a[3]*a[1] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	8(%esi),	%eax
+	adcl	$0,		%ebx
+	# sqr a[2]*a[2] 
+	mull	%eax
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	8(%esi),	%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		16(%edi)
+	movl	12(%esi),	%eax
+	# saved r[4] 
+	# ############### Calculate word 5 
+	xorl	%ecx,		%ecx
+	# sqr a[3]*a[2] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	12(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	%ebp,		20(%edi)
+	# saved r[5] 
+	# ############### Calculate word 6 
+	xorl	%ebp,		%ebp
+	# sqr a[3]*a[3] 
+	mull	%eax
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	adcl	$0,		%ebp
+	movl	%ebx,		24(%edi)
+	# saved r[6] 
+	movl	%ecx,		28(%edi)
+	popl	%ebx
+	popl	%ebp
+	popl	%edi
+	popl	%esi
+	ret
+.bn_sqr_comba4_end:
+	.size	bn_sqr_comba4,.bn_sqr_comba4_end-bn_sqr_comba4
+.ident	"desasm.pl"
diff --git a/crypto/bn/asm/f b/crypto/bn/asm/f
new file mode 100644
index 0000000..a23fa15
--- /dev/null
+++ b/crypto/bn/asm/f
@@ -0,0 +1,500 @@
+	.text
+	.align 3
+	.globl bn_sqr_comba8
+	.ent bn_sqr_comba8
+bn_sqr_comba8:
+bn_sqr_comba8..ng:
+	.frame $30,0,$26,0
+	.prologue 0
+
+	ldq	$0,	0($17)
+	ldq	$1,	8($17)
+	ldq	$2,	16($17)
+	ldq	$3,	24($17)
+	ldq	$4,	32($17)
+	ldq	$5,	40($17)
+	ldq	$6,	48($17)
+	ldq	$7,	56($17)
+	bis	$31,	$31,	$23
+	mulq	$0,	$0,	$8
+	umulh	$0,	$0,	$22
+	stq	$8,	0($16)
+	bis	$31,	$31,	$8
+	mulq	$1,	$0,	$24
+	umulh	$1,	$0,	$25
+	cmplt	$24,	$31,	$27
+	cmplt	$25,	$31,	$28
+	addq	$24,	$24,	$24
+	addq	$25,	$25,	$25
+	addq	$25,	$27,	$25
+	addq	$8,	$28,	$8
+	addq	$22,	$24,	$22
+	addq	$23,	$25,	$23
+	cmpult	$22,	$24,	$21
+	cmpult	$23,	$25,	$20
+	addq	$23,	$21,	$23
+	addq	$8,	$20,	$8
+	stq	$22,	8($16)
+	bis	$31,	$31,	$22
+	mulq	$1,	$1,	$19
+	umulh	$1,	$1,	$18
+	addq	$23,	$19,	$23
+	addq	$8,	$18,	$8
+	cmpult	$23,	$19,	$17
+	cmpult	$8,	$18,	$27
+	addq	$8,	$17,	$8
+	addq	$22,	$27,	$22
+	mulq	$2,	$0,	$28
+	umulh	$2,	$0,	$24
+	cmplt	$28,	$31,	$25
+	cmplt	$24,	$31,	$21
+	addq	$28,	$28,	$28
+	addq	$24,	$24,	$24
+	addq	$24,	$25,	$24
+	addq	$22,	$21,	$22
+	addq	$23,	$28,	$23
+	addq	$8,	$24,	$8
+	cmpult	$23,	$28,	$20
+	cmpult	$8,	$24,	$19
+	addq	$8,	$20,	$8
+	addq	$22,	$19,	$22
+	stq	$23,	16($16)
+	bis	$31,	$31,	$23
+	mulq	$2,	$1,	$18
+	umulh	$2,	$1,	$17
+	cmplt	$18,	$31,	$27
+	cmplt	$17,	$31,	$25
+	addq	$18,	$18,	$18
+	addq	$17,	$17,	$17
+	addq	$17,	$27,	$17
+	addq	$23,	$25,	$23
+	addq	$8,	$18,	$8
+	addq	$22,	$17,	$22
+	cmpult	$8,	$18,	$21
+	cmpult	$22,	$17,	$28
+	addq	$22,	$21,	$22
+	addq	$23,	$28,	$23
+	mulq	$3,	$0,	$24
+	umulh	$3,	$0,	$20
+	cmplt	$24,	$31,	$19
+	cmplt	$20,	$31,	$27
+	addq	$24,	$24,	$24
+	addq	$20,	$20,	$20
+	addq	$20,	$19,	$20
+	addq	$23,	$27,	$23
+	addq	$8,	$24,	$8
+	addq	$22,	$20,	$22
+	cmpult	$8,	$24,	$25
+	cmpult	$22,	$20,	$18
+	addq	$22,	$25,	$22
+	addq	$23,	$18,	$23
+	stq	$8,	24($16)
+	bis	$31,	$31,	$8
+	mulq	$2,	$2,	$17
+	umulh	$2,	$2,	$21
+	addq	$22,	$17,	$22
+	addq	$23,	$21,	$23
+	cmpult	$22,	$17,	$28
+	cmpult	$23,	$21,	$19
+	addq	$23,	$28,	$23
+	addq	$8,	$19,	$8
+	mulq	$3,	$1,	$27
+	umulh	$3,	$1,	$24
+	cmplt	$27,	$31,	$20
+	cmplt	$24,	$31,	$25
+	addq	$27,	$27,	$27
+	addq	$24,	$24,	$24
+	addq	$24,	$20,	$24
+	addq	$8,	$25,	$8
+	addq	$22,	$27,	$22
+	addq	$23,	$24,	$23
+	cmpult	$22,	$27,	$18
+	cmpult	$23,	$24,	$17
+	addq	$23,	$18,	$23
+	addq	$8,	$17,	$8
+	mulq	$4,	$0,	$21
+	umulh	$4,	$0,	$28
+	cmplt	$21,	$31,	$19
+	cmplt	$28,	$31,	$20
+	addq	$21,	$21,	$21
+	addq	$28,	$28,	$28
+	addq	$28,	$19,	$28
+	addq	$8,	$20,	$8
+	addq	$22,	$21,	$22
+	addq	$23,	$28,	$23
+	cmpult	$22,	$21,	$25
+	cmpult	$23,	$28,	$27
+	addq	$23,	$25,	$23
+	addq	$8,	$27,	$8
+	stq	$22,	32($16)
+	bis	$31,	$31,	$22
+	mulq	$3,	$2,	$24
+	umulh	$3,	$2,	$18
+	cmplt	$24,	$31,	$17
+	cmplt	$18,	$31,	$19
+	addq	$24,	$24,	$24
+	addq	$18,	$18,	$18
+	addq	$18,	$17,	$18
+	addq	$22,	$19,	$22
+	addq	$23,	$24,	$23
+	addq	$8,	$18,	$8
+	cmpult	$23,	$24,	$20
+	cmpult	$8,	$18,	$21
+	addq	$8,	$20,	$8
+	addq	$22,	$21,	$22
+	mulq	$4,	$1,	$28
+	umulh	$4,	$1,	$25
+	cmplt	$28,	$31,	$27
+	cmplt	$25,	$31,	$17
+	addq	$28,	$28,	$28
+	addq	$25,	$25,	$25
+	addq	$25,	$27,	$25
+	addq	$22,	$17,	$22
+	addq	$23,	$28,	$23
+	addq	$8,	$25,	$8
+	cmpult	$23,	$28,	$19
+	cmpult	$8,	$25,	$24
+	addq	$8,	$19,	$8
+	addq	$22,	$24,	$22
+	mulq	$5,	$0,	$18
+	umulh	$5,	$0,	$20
+	cmplt	$18,	$31,	$21
+	cmplt	$20,	$31,	$27
+	addq	$18,	$18,	$18
+	addq	$20,	$20,	$20
+	addq	$20,	$21,	$20
+	addq	$22,	$27,	$22
+	addq	$23,	$18,	$23
+	addq	$8,	$20,	$8
+	cmpult	$23,	$18,	$17
+	cmpult	$8,	$20,	$28
+	addq	$8,	$17,	$8
+	addq	$22,	$28,	$22
+	stq	$23,	40($16)
+	bis	$31,	$31,	$23
+	mulq	$3,	$3,	$25
+	umulh	$3,	$3,	$19
+	addq	$8,	$25,	$8
+	addq	$22,	$19,	$22
+	cmpult	$8,	$25,	$24
+	cmpult	$22,	$19,	$21
+	addq	$22,	$24,	$22
+	addq	$23,	$21,	$23
+	mulq	$4,	$2,	$27
+	umulh	$4,	$2,	$18
+	cmplt	$27,	$31,	$20
+	cmplt	$18,	$31,	$17
+	addq	$27,	$27,	$27
+	addq	$18,	$18,	$18
+	addq	$18,	$20,	$18
+	addq	$23,	$17,	$23
+	addq	$8,	$27,	$8
+	addq	$22,	$18,	$22
+	cmpult	$8,	$27,	$28
+	cmpult	$22,	$18,	$25
+	addq	$22,	$28,	$22
+	addq	$23,	$25,	$23
+	mulq	$5,	$1,	$19
+	umulh	$5,	$1,	$24
+	cmplt	$19,	$31,	$21
+	cmplt	$24,	$31,	$20
+	addq	$19,	$19,	$19
+	addq	$24,	$24,	$24
+	addq	$24,	$21,	$24
+	addq	$23,	$20,	$23
+	addq	$8,	$19,	$8
+	addq	$22,	$24,	$22
+	cmpult	$8,	$19,	$17
+	cmpult	$22,	$24,	$27
+	addq	$22,	$17,	$22
+	addq	$23,	$27,	$23
+	mulq	$6,	$0,	$18
+	umulh	$6,	$0,	$28
+	cmplt	$18,	$31,	$25
+	cmplt	$28,	$31,	$21
+	addq	$18,	$18,	$18
+	addq	$28,	$28,	$28
+	addq	$28,	$25,	$28
+	addq	$23,	$21,	$23
+	addq	$8,	$18,	$8
+	addq	$22,	$28,	$22
+	cmpult	$8,	$18,	$20
+	cmpult	$22,	$28,	$19
+	addq	$22,	$20,	$22
+	addq	$23,	$19,	$23
+	stq	$8,	48($16)
+	bis	$31,	$31,	$8
+	mulq	$4,	$3,	$24
+	umulh	$4,	$3,	$17
+	cmplt	$24,	$31,	$27
+	cmplt	$17,	$31,	$25
+	addq	$24,	$24,	$24
+	addq	$17,	$17,	$17
+	addq	$17,	$27,	$17
+	addq	$8,	$25,	$8
+	addq	$22,	$24,	$22
+	addq	$23,	$17,	$23
+	cmpult	$22,	$24,	$21
+	cmpult	$23,	$17,	$18
+	addq	$23,	$21,	$23
+	addq	$8,	$18,	$8
+	mulq	$5,	$2,	$28
+	umulh	$5,	$2,	$20
+	cmplt	$28,	$31,	$19
+	cmplt	$20,	$31,	$27
+	addq	$28,	$28,	$28
+	addq	$20,	$20,	$20
+	addq	$20,	$19,	$20
+	addq	$8,	$27,	$8
+	addq	$22,	$28,	$22
+	addq	$23,	$20,	$23
+	cmpult	$22,	$28,	$25
+	cmpult	$23,	$20,	$24
+	addq	$23,	$25,	$23
+	addq	$8,	$24,	$8
+	mulq	$6,	$1,	$17
+	umulh	$6,	$1,	$21
+	cmplt	$17,	$31,	$18
+	cmplt	$21,	$31,	$19
+	addq	$17,	$17,	$17
+	addq	$21,	$21,	$21
+	addq	$21,	$18,	$21
+	addq	$8,	$19,	$8
+	addq	$22,	$17,	$22
+	addq	$23,	$21,	$23
+	cmpult	$22,	$17,	$27
+	cmpult	$23,	$21,	$28
+	addq	$23,	$27,	$23
+	addq	$8,	$28,	$8
+	mulq	$7,	$0,	$20
+	umulh	$7,	$0,	$25
+	cmplt	$20,	$31,	$24
+	cmplt	$25,	$31,	$18
+	addq	$20,	$20,	$20
+	addq	$25,	$25,	$25
+	addq	$25,	$24,	$25
+	addq	$8,	$18,	$8
+	addq	$22,	$20,	$22
+	addq	$23,	$25,	$23
+	cmpult	$22,	$20,	$19
+	cmpult	$23,	$25,	$17
+	addq	$23,	$19,	$23
+	addq	$8,	$17,	$8
+	stq	$22,	56($16)
+	bis	$31,	$31,	$22
+	mulq	$4,	$4,	$21
+	umulh	$4,	$4,	$27
+	addq	$23,	$21,	$23
+	addq	$8,	$27,	$8
+	cmpult	$23,	$21,	$28
+	cmpult	$8,	$27,	$24
+	addq	$8,	$28,	$8
+	addq	$22,	$24,	$22
+	mulq	$5,	$3,	$18
+	umulh	$5,	$3,	$20
+	cmplt	$18,	$31,	$25
+	cmplt	$20,	$31,	$19
+	addq	$18,	$18,	$18
+	addq	$20,	$20,	$20
+	addq	$20,	$25,	$20
+	addq	$22,	$19,	$22
+	addq	$23,	$18,	$23
+	addq	$8,	$20,	$8
+	cmpult	$23,	$18,	$17
+	cmpult	$8,	$20,	$21
+	addq	$8,	$17,	$8
+	addq	$22,	$21,	$22
+	mulq	$6,	$2,	$27
+	umulh	$6,	$2,	$28
+	cmplt	$27,	$31,	$24
+	cmplt	$28,	$31,	$25
+	addq	$27,	$27,	$27
+	addq	$28,	$28,	$28
+	addq	$28,	$24,	$28
+	addq	$22,	$25,	$22
+	addq	$23,	$27,	$23
+	addq	$8,	$28,	$8
+	cmpult	$23,	$27,	$19
+	cmpult	$8,	$28,	$18
+	addq	$8,	$19,	$8
+	addq	$22,	$18,	$22
+	mulq	$7,	$1,	$20
+	umulh	$7,	$1,	$17
+	cmplt	$20,	$31,	$21
+	cmplt	$17,	$31,	$24
+	addq	$20,	$20,	$20
+	addq	$17,	$17,	$17
+	addq	$17,	$21,	$17
+	addq	$22,	$24,	$22
+	addq	$23,	$20,	$23
+	addq	$8,	$17,	$8
+	cmpult	$23,	$20,	$25
+	cmpult	$8,	$17,	$27
+	addq	$8,	$25,	$8
+	addq	$22,	$27,	$22
+	stq	$23,	64($16)
+	bis	$31,	$31,	$23
+	mulq	$5,	$4,	$28
+	umulh	$5,	$4,	$19
+	cmplt	$28,	$31,	$18
+	cmplt	$19,	$31,	$21
+	addq	$28,	$28,	$28
+	addq	$19,	$19,	$19
+	addq	$19,	$18,	$19
+	addq	$23,	$21,	$23
+	addq	$8,	$28,	$8
+	addq	$22,	$19,	$22
+	cmpult	$8,	$28,	$24
+	cmpult	$22,	$19,	$20
+	addq	$22,	$24,	$22
+	addq	$23,	$20,	$23
+	mulq	$6,	$3,	$17
+	umulh	$6,	$3,	$25
+	cmplt	$17,	$31,	$27
+	cmplt	$25,	$31,	$18
+	addq	$17,	$17,	$17
+	addq	$25,	$25,	$25
+	addq	$25,	$27,	$25
+	addq	$23,	$18,	$23
+	addq	$8,	$17,	$8
+	addq	$22,	$25,	$22
+	cmpult	$8,	$17,	$21
+	cmpult	$22,	$25,	$28
+	addq	$22,	$21,	$22
+	addq	$23,	$28,	$23
+	mulq	$7,	$2,	$19
+	umulh	$7,	$2,	$24
+	cmplt	$19,	$31,	$20
+	cmplt	$24,	$31,	$27
+	addq	$19,	$19,	$19
+	addq	$24,	$24,	$24
+	addq	$24,	$20,	$24
+	addq	$23,	$27,	$23
+	addq	$8,	$19,	$8
+	addq	$22,	$24,	$22
+	cmpult	$8,	$19,	$18
+	cmpult	$22,	$24,	$17
+	addq	$22,	$18,	$22
+	addq	$23,	$17,	$23
+	stq	$8,	72($16)
+	bis	$31,	$31,	$8
+	mulq	$5,	$5,	$25
+	umulh	$5,	$5,	$21
+	addq	$22,	$25,	$22
+	addq	$23,	$21,	$23
+	cmpult	$22,	$25,	$28
+	cmpult	$23,	$21,	$20
+	addq	$23,	$28,	$23
+	addq	$8,	$20,	$8
+	mulq	$6,	$4,	$27
+	umulh	$6,	$4,	$19
+	cmplt	$27,	$31,	$24
+	cmplt	$19,	$31,	$18
+	addq	$27,	$27,	$27
+	addq	$19,	$19,	$19
+	addq	$19,	$24,	$19
+	addq	$8,	$18,	$8
+	addq	$22,	$27,	$22
+	addq	$23,	$19,	$23
+	cmpult	$22,	$27,	$17
+	cmpult	$23,	$19,	$25
+	addq	$23,	$17,	$23
+	addq	$8,	$25,	$8
+	mulq	$7,	$3,	$21
+	umulh	$7,	$3,	$28
+	cmplt	$21,	$31,	$20
+	cmplt	$28,	$31,	$24
+	addq	$21,	$21,	$21
+	addq	$28,	$28,	$28
+	addq	$28,	$20,	$28
+	addq	$8,	$24,	$8
+	addq	$22,	$21,	$22
+	addq	$23,	$28,	$23
+	cmpult	$22,	$21,	$18
+	cmpult	$23,	$28,	$27
+	addq	$23,	$18,	$23
+	addq	$8,	$27,	$8
+	stq	$22,	80($16)
+	bis	$31,	$31,	$22
+	mulq	$6,	$5,	$19
+	umulh	$6,	$5,	$17
+	cmplt	$19,	$31,	$25
+	cmplt	$17,	$31,	$20
+	addq	$19,	$19,	$19
+	addq	$17,	$17,	$17
+	addq	$17,	$25,	$17
+	addq	$22,	$20,	$22
+	addq	$23,	$19,	$23
+	addq	$8,	$17,	$8
+	cmpult	$23,	$19,	$24
+	cmpult	$8,	$17,	$21
+	addq	$8,	$24,	$8
+	addq	$22,	$21,	$22
+	mulq	$7,	$4,	$28
+	umulh	$7,	$4,	$18
+	cmplt	$28,	$31,	$27
+	cmplt	$18,	$31,	$25
+	addq	$28,	$28,	$28
+	addq	$18,	$18,	$18
+	addq	$18,	$27,	$18
+	addq	$22,	$25,	$22
+	addq	$23,	$28,	$23
+	addq	$8,	$18,	$8
+	cmpult	$23,	$28,	$20
+	cmpult	$8,	$18,	$19
+	addq	$8,	$20,	$8
+	addq	$22,	$19,	$22
+	stq	$23,	88($16)
+	bis	$31,	$31,	$23
+	mulq	$6,	$6,	$17
+	umulh	$6,	$6,	$24
+	addq	$8,	$17,	$8
+	addq	$22,	$24,	$22
+	cmpult	$8,	$17,	$21
+	cmpult	$22,	$24,	$27
+	addq	$22,	$21,	$22
+	addq	$23,	$27,	$23
+	mulq	$7,	$5,	$25
+	umulh	$7,	$5,	$28
+	cmplt	$25,	$31,	$18
+	cmplt	$28,	$31,	$20
+	addq	$25,	$25,	$25
+	addq	$28,	$28,	$28
+	addq	$28,	$18,	$28
+	addq	$23,	$20,	$23
+	addq	$8,	$25,	$8
+	addq	$22,	$28,	$22
+	cmpult	$8,	$25,	$19
+	cmpult	$22,	$28,	$17
+	addq	$22,	$19,	$22
+	addq	$23,	$17,	$23
+	stq	$8,	96($16)
+	bis	$31,	$31,	$8
+	mulq	$7,	$6,	$24
+	umulh	$7,	$6,	$21
+	cmplt	$24,	$31,	$27
+	cmplt	$21,	$31,	$18
+	addq	$24,	$24,	$24
+	addq	$21,	$21,	$21
+	addq	$21,	$27,	$21
+	addq	$8,	$18,	$8
+	addq	$22,	$24,	$22
+	addq	$23,	$21,	$23
+	cmpult	$22,	$24,	$20
+	cmpult	$23,	$21,	$25
+	addq	$23,	$20,	$23
+	addq	$8,	$25,	$8
+	stq	$22,	104($16)
+	bis	$31,	$31,	$22
+	mulq	$7,	$7,	$28
+	umulh	$7,	$7,	$19
+	addq	$23,	$28,	$23
+	addq	$8,	$19,	$8
+	cmpult	$23,	$28,	$17
+	cmpult	$8,	$19,	$27
+	addq	$8,	$17,	$8
+	addq	$22,	$27,	$22
+	stq	$23,	112($16)
+	stq	$8,	120($16)
+	ret	$31,($26),1
+	.end bn_sqr_comba8
diff --git a/crypto/bn/asm/f.c b/crypto/bn/asm/f.c
new file mode 100644
index 0000000..bfdccae
--- /dev/null
+++ b/crypto/bn/asm/f.c
@@ -0,0 +1,8 @@
+int abc(a,b,c,d,e,f,g,h,i,j)
+unsigned long a,b,c,d,e,f,g,h,i,j;
+	{
+	gg(g);
+	if (g)
+		gg(h);
+	gg(i);
+	}
diff --git a/crypto/bn/asm/f.elf b/crypto/bn/asm/f.elf
new file mode 100644
index 0000000..39d07b7
--- /dev/null
+++ b/crypto/bn/asm/f.elf
@@ -0,0 +1,2149 @@
+	# Don't even think of reading this code 
+	# It was automatically generated by bn-586.pl 
+	# Which is a perl program used to generate the x86 assember for 
+	# any of elf, a.out, BSDI,Win32, or Solaris 
+	# eric <eay@cryptsoft.com> 
+
+	.file	"bn-586.s"
+	.version	"01.01"
+gcc2_compiled.:
+.text
+	.align 16
+.globl bn_mul_add_words
+	.type	bn_mul_add_words,@function
+bn_mul_add_words:
+	pushl	%ebp
+	pushl	%ebx
+	pushl	%esi
+	pushl	%edi
+
+
+	xorl	%esi,		%esi
+	movl	20(%esp),	%edi
+	movl	28(%esp),	%ecx
+	movl	24(%esp),	%ebx
+	andl	$4294967288,	%ecx
+	movl	32(%esp),	%ebp
+	pushl	%ecx
+	jz	.L000maw_finish
+.L001maw_loop:
+	movl	%ecx,		(%esp)
+	# Round 0 
+	movl	(%ebx),		%eax
+	mull	%ebp
+	addl	%esi,		%eax
+	movl	(%edi),		%esi
+	adcl	$0,		%edx
+	addl	%esi,		%eax
+	adcl	$0,		%edx
+	movl	%eax,		(%edi)
+	movl	%edx,		%esi
+	# Round 4 
+	movl	4(%ebx),	%eax
+	mull	%ebp
+	addl	%esi,		%eax
+	movl	4(%edi),	%esi
+	adcl	$0,		%edx
+	addl	%esi,		%eax
+	adcl	$0,		%edx
+	movl	%eax,		4(%edi)
+	movl	%edx,		%esi
+	# Round 8 
+	movl	8(%ebx),	%eax
+	mull	%ebp
+	addl	%esi,		%eax
+	movl	8(%edi),	%esi
+	adcl	$0,		%edx
+	addl	%esi,		%eax
+	adcl	$0,		%edx
+	movl	%eax,		8(%edi)
+	movl	%edx,		%esi
+	# Round 12 
+	movl	12(%ebx),	%eax
+	mull	%ebp
+	addl	%esi,		%eax
+	movl	12(%edi),	%esi
+	adcl	$0,		%edx
+	addl	%esi,		%eax
+	adcl	$0,		%edx
+	movl	%eax,		12(%edi)
+	movl	%edx,		%esi
+	# Round 16 
+	movl	16(%ebx),	%eax
+	mull	%ebp
+	addl	%esi,		%eax
+	movl	16(%edi),	%esi
+	adcl	$0,		%edx
+	addl	%esi,		%eax
+	adcl	$0,		%edx
+	movl	%eax,		16(%edi)
+	movl	%edx,		%esi
+	# Round 20 
+	movl	20(%ebx),	%eax
+	mull	%ebp
+	addl	%esi,		%eax
+	movl	20(%edi),	%esi
+	adcl	$0,		%edx
+	addl	%esi,		%eax
+	adcl	$0,		%edx
+	movl	%eax,		20(%edi)
+	movl	%edx,		%esi
+	# Round 24 
+	movl	24(%ebx),	%eax
+	mull	%ebp
+	addl	%esi,		%eax
+	movl	24(%edi),	%esi
+	adcl	$0,		%edx
+	addl	%esi,		%eax
+	adcl	$0,		%edx
+	movl	%eax,		24(%edi)
+	movl	%edx,		%esi
+	# Round 28 
+	movl	28(%ebx),	%eax
+	mull	%ebp
+	addl	%esi,		%eax
+	movl	28(%edi),	%esi
+	adcl	$0,		%edx
+	addl	%esi,		%eax
+	adcl	$0,		%edx
+	movl	%eax,		28(%edi)
+	movl	%edx,		%esi
+
+	movl	(%esp),		%ecx
+	addl	$32,		%ebx
+	addl	$32,		%edi
+	subl	$8,		%ecx
+	jnz	.L001maw_loop
+.L000maw_finish:
+	movl	32(%esp),	%ecx
+	andl	$7,		%ecx
+	jnz	.L002maw_finish2
+	jmp	.L003maw_end
+.align 16
+.L002maw_finish2:
+	# Tail Round 0 
+	movl	(%ebx),		%eax
+	mull	%ebp
+	addl	%esi,		%eax
+	movl	(%edi),		%esi
+	adcl	$0,		%edx
+	addl	%esi,		%eax
+	adcl	$0,		%edx
+	decl	%ecx
+	movl	%eax,		(%edi)
+	movl	%edx,		%esi
+	jz	.L003maw_end
+	# Tail Round 1 
+	movl	4(%ebx),	%eax
+	mull	%ebp
+	addl	%esi,		%eax
+	movl	4(%edi),	%esi
+	adcl	$0,		%edx
+	addl	%esi,		%eax
+	adcl	$0,		%edx
+	decl	%ecx
+	movl	%eax,		4(%edi)
+	movl	%edx,		%esi
+	jz	.L003maw_end
+	# Tail Round 2 
+	movl	8(%ebx),	%eax
+	mull	%ebp
+	addl	%esi,		%eax
+	movl	8(%edi),	%esi
+	adcl	$0,		%edx
+	addl	%esi,		%eax
+	adcl	$0,		%edx
+	decl	%ecx
+	movl	%eax,		8(%edi)
+	movl	%edx,		%esi
+	jz	.L003maw_end
+	# Tail Round 3 
+	movl	12(%ebx),	%eax
+	mull	%ebp
+	addl	%esi,		%eax
+	movl	12(%edi),	%esi
+	adcl	$0,		%edx
+	addl	%esi,		%eax
+	adcl	$0,		%edx
+	decl	%ecx
+	movl	%eax,		12(%edi)
+	movl	%edx,		%esi
+	jz	.L003maw_end
+	# Tail Round 4 
+	movl	16(%ebx),	%eax
+	mull	%ebp
+	addl	%esi,		%eax
+	movl	16(%edi),	%esi
+	adcl	$0,		%edx
+	addl	%esi,		%eax
+	adcl	$0,		%edx
+	decl	%ecx
+	movl	%eax,		16(%edi)
+	movl	%edx,		%esi
+	jz	.L003maw_end
+	# Tail Round 5 
+	movl	20(%ebx),	%eax
+	mull	%ebp
+	addl	%esi,		%eax
+	movl	20(%edi),	%esi
+	adcl	$0,		%edx
+	addl	%esi,		%eax
+	adcl	$0,		%edx
+	decl	%ecx
+	movl	%eax,		20(%edi)
+	movl	%edx,		%esi
+	jz	.L003maw_end
+	# Tail Round 6 
+	movl	24(%ebx),	%eax
+	mull	%ebp
+	addl	%esi,		%eax
+	movl	24(%edi),	%esi
+	adcl	$0,		%edx
+	addl	%esi,		%eax
+	adcl	$0,		%edx
+	movl	%eax,		24(%edi)
+	movl	%edx,		%esi
+.L003maw_end:
+	movl	%esi,		%eax
+	popl	%ecx
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	popl	%ebp
+	ret
+.bn_mul_add_words_end:
+	.size	bn_mul_add_words,.bn_mul_add_words_end-bn_mul_add_words
+.ident	"bn_mul_add_words"
+.text
+	.align 16
+.globl bn_mul_words
+	.type	bn_mul_words,@function
+bn_mul_words:
+	pushl	%ebp
+	pushl	%ebx
+	pushl	%esi
+	pushl	%edi
+
+
+	xorl	%esi,		%esi
+	movl	20(%esp),	%edi
+	movl	24(%esp),	%ebx
+	movl	28(%esp),	%ebp
+	movl	32(%esp),	%ecx
+	andl	$4294967288,	%ebp
+	jz	.L004mw_finish
+.L005mw_loop:
+	# Round 0 
+	movl	(%ebx),		%eax
+	mull	%ecx
+	addl	%esi,		%eax
+	adcl	$0,		%edx
+	movl	%eax,		(%edi)
+	movl	%edx,		%esi
+	# Round 4 
+	movl	4(%ebx),	%eax
+	mull	%ecx
+	addl	%esi,		%eax
+	adcl	$0,		%edx
+	movl	%eax,		4(%edi)
+	movl	%edx,		%esi
+	# Round 8 
+	movl	8(%ebx),	%eax
+	mull	%ecx
+	addl	%esi,		%eax
+	adcl	$0,		%edx
+	movl	%eax,		8(%edi)
+	movl	%edx,		%esi
+	# Round 12 
+	movl	12(%ebx),	%eax
+	mull	%ecx
+	addl	%esi,		%eax
+	adcl	$0,		%edx
+	movl	%eax,		12(%edi)
+	movl	%edx,		%esi
+	# Round 16 
+	movl	16(%ebx),	%eax
+	mull	%ecx
+	addl	%esi,		%eax
+	adcl	$0,		%edx
+	movl	%eax,		16(%edi)
+	movl	%edx,		%esi
+	# Round 20 
+	movl	20(%ebx),	%eax
+	mull	%ecx
+	addl	%esi,		%eax
+	adcl	$0,		%edx
+	movl	%eax,		20(%edi)
+	movl	%edx,		%esi
+	# Round 24 
+	movl	24(%ebx),	%eax
+	mull	%ecx
+	addl	%esi,		%eax
+	adcl	$0,		%edx
+	movl	%eax,		24(%edi)
+	movl	%edx,		%esi
+	# Round 28 
+	movl	28(%ebx),	%eax
+	mull	%ecx
+	addl	%esi,		%eax
+	adcl	$0,		%edx
+	movl	%eax,		28(%edi)
+	movl	%edx,		%esi
+
+	addl	$32,		%ebx
+	addl	$32,		%edi
+	subl	$8,		%ebp
+	jz	.L004mw_finish
+	jmp	.L005mw_loop
+.L004mw_finish:
+	movl	28(%esp),	%ebp
+	andl	$7,		%ebp
+	jnz	.L006mw_finish2
+	jmp	.L007mw_end
+.align 16
+.L006mw_finish2:
+	# Tail Round 0 
+	movl	(%ebx),		%eax
+	mull	%ecx
+	addl	%esi,		%eax
+	adcl	$0,		%edx
+	movl	%eax,		(%edi)
+	movl	%edx,		%esi
+	decl	%ebp
+	jz	.L007mw_end
+	# Tail Round 1 
+	movl	4(%ebx),	%eax
+	mull	%ecx
+	addl	%esi,		%eax
+	adcl	$0,		%edx
+	movl	%eax,		4(%edi)
+	movl	%edx,		%esi
+	decl	%ebp
+	jz	.L007mw_end
+	# Tail Round 2 
+	movl	8(%ebx),	%eax
+	mull	%ecx
+	addl	%esi,		%eax
+	adcl	$0,		%edx
+	movl	%eax,		8(%edi)
+	movl	%edx,		%esi
+	decl	%ebp
+	jz	.L007mw_end
+	# Tail Round 3 
+	movl	12(%ebx),	%eax
+	mull	%ecx
+	addl	%esi,		%eax
+	adcl	$0,		%edx
+	movl	%eax,		12(%edi)
+	movl	%edx,		%esi
+	decl	%ebp
+	jz	.L007mw_end
+	# Tail Round 4 
+	movl	16(%ebx),	%eax
+	mull	%ecx
+	addl	%esi,		%eax
+	adcl	$0,		%edx
+	movl	%eax,		16(%edi)
+	movl	%edx,		%esi
+	decl	%ebp
+	jz	.L007mw_end
+	# Tail Round 5 
+	movl	20(%ebx),	%eax
+	mull	%ecx
+	addl	%esi,		%eax
+	adcl	$0,		%edx
+	movl	%eax,		20(%edi)
+	movl	%edx,		%esi
+	decl	%ebp
+	jz	.L007mw_end
+	# Tail Round 6 
+	movl	24(%ebx),	%eax
+	mull	%ecx
+	addl	%esi,		%eax
+	adcl	$0,		%edx
+	movl	%eax,		24(%edi)
+	movl	%edx,		%esi
+.L007mw_end:
+	movl	%esi,		%eax
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	popl	%ebp
+	ret
+.bn_mul_words_end:
+	.size	bn_mul_words,.bn_mul_words_end-bn_mul_words
+.ident	"bn_mul_words"
+.text
+	.align 16
+.globl bn_sqr_words
+	.type	bn_sqr_words,@function
+bn_sqr_words:
+	pushl	%ebp
+	pushl	%ebx
+	pushl	%esi
+	pushl	%edi
+
+
+	movl	20(%esp),	%esi
+	movl	24(%esp),	%edi
+	movl	28(%esp),	%ebx
+	andl	$4294967288,	%ebx
+	jz	.L008sw_finish
+.L009sw_loop:
+	# Round 0 
+	movl	(%edi),		%eax
+	mull	%eax
+	movl	%eax,		(%esi)
+	movl	%edx,		4(%esi)
+	# Round 4 
+	movl	4(%edi),	%eax
+	mull	%eax
+	movl	%eax,		8(%esi)
+	movl	%edx,		12(%esi)
+	# Round 8 
+	movl	8(%edi),	%eax
+	mull	%eax
+	movl	%eax,		16(%esi)
+	movl	%edx,		20(%esi)
+	# Round 12 
+	movl	12(%edi),	%eax
+	mull	%eax
+	movl	%eax,		24(%esi)
+	movl	%edx,		28(%esi)
+	# Round 16 
+	movl	16(%edi),	%eax
+	mull	%eax
+	movl	%eax,		32(%esi)
+	movl	%edx,		36(%esi)
+	# Round 20 
+	movl	20(%edi),	%eax
+	mull	%eax
+	movl	%eax,		40(%esi)
+	movl	%edx,		44(%esi)
+	# Round 24 
+	movl	24(%edi),	%eax
+	mull	%eax
+	movl	%eax,		48(%esi)
+	movl	%edx,		52(%esi)
+	# Round 28 
+	movl	28(%edi),	%eax
+	mull	%eax
+	movl	%eax,		56(%esi)
+	movl	%edx,		60(%esi)
+
+	addl	$32,		%edi
+	addl	$64,		%esi
+	subl	$8,		%ebx
+	jnz	.L009sw_loop
+.L008sw_finish:
+	movl	28(%esp),	%ebx
+	andl	$7,		%ebx
+	jz	.L010sw_end
+	# Tail Round 0 
+	movl	(%edi),		%eax
+	mull	%eax
+	movl	%eax,		(%esi)
+	decl	%ebx
+	movl	%edx,		4(%esi)
+	jz	.L010sw_end
+	# Tail Round 1 
+	movl	4(%edi),	%eax
+	mull	%eax
+	movl	%eax,		8(%esi)
+	decl	%ebx
+	movl	%edx,		12(%esi)
+	jz	.L010sw_end
+	# Tail Round 2 
+	movl	8(%edi),	%eax
+	mull	%eax
+	movl	%eax,		16(%esi)
+	decl	%ebx
+	movl	%edx,		20(%esi)
+	jz	.L010sw_end
+	# Tail Round 3 
+	movl	12(%edi),	%eax
+	mull	%eax
+	movl	%eax,		24(%esi)
+	decl	%ebx
+	movl	%edx,		28(%esi)
+	jz	.L010sw_end
+	# Tail Round 4 
+	movl	16(%edi),	%eax
+	mull	%eax
+	movl	%eax,		32(%esi)
+	decl	%ebx
+	movl	%edx,		36(%esi)
+	jz	.L010sw_end
+	# Tail Round 5 
+	movl	20(%edi),	%eax
+	mull	%eax
+	movl	%eax,		40(%esi)
+	decl	%ebx
+	movl	%edx,		44(%esi)
+	jz	.L010sw_end
+	# Tail Round 6 
+	movl	24(%edi),	%eax
+	mull	%eax
+	movl	%eax,		48(%esi)
+	movl	%edx,		52(%esi)
+.L010sw_end:
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	popl	%ebp
+	ret
+.bn_sqr_words_end:
+	.size	bn_sqr_words,.bn_sqr_words_end-bn_sqr_words
+.ident	"bn_sqr_words"
+.text
+	.align 16
+.globl bn_div64
+	.type	bn_div64,@function
+bn_div64:
+	pushl	%ebp
+	pushl	%ebx
+	pushl	%esi
+	pushl	%edi
+
+	movl	20(%esp),	%edx
+	movl	24(%esp),	%eax
+	movl	28(%esp),	%ebx
+	divl	%ebx
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	popl	%ebp
+	ret
+.bn_div64_end:
+	.size	bn_div64,.bn_div64_end-bn_div64
+.ident	"bn_div64"
+.text
+	.align 16
+.globl bn_add_words
+	.type	bn_add_words,@function
+bn_add_words:
+	pushl	%ebp
+	pushl	%ebx
+	pushl	%esi
+	pushl	%edi
+
+
+	movl	20(%esp),	%ebx
+	movl	24(%esp),	%esi
+	movl	28(%esp),	%edi
+	movl	32(%esp),	%ebp
+	xorl	%eax,		%eax
+	andl	$4294967288,	%ebp
+	jz	.L011aw_finish
+.L012aw_loop:
+	# Round 0 
+	movl	(%esi),		%ecx
+	movl	(%edi),		%edx
+	addl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	addl	%edx,		%ecx
+	adcl	$0,		%eax
+	movl	%ecx,		(%ebx)
+	# Round 1 
+	movl	4(%esi),	%ecx
+	movl	4(%edi),	%edx
+	addl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	addl	%edx,		%ecx
+	adcl	$0,		%eax
+	movl	%ecx,		4(%ebx)
+	# Round 2 
+	movl	8(%esi),	%ecx
+	movl	8(%edi),	%edx
+	addl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	addl	%edx,		%ecx
+	adcl	$0,		%eax
+	movl	%ecx,		8(%ebx)
+	# Round 3 
+	movl	12(%esi),	%ecx
+	movl	12(%edi),	%edx
+	addl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	addl	%edx,		%ecx
+	adcl	$0,		%eax
+	movl	%ecx,		12(%ebx)
+	# Round 4 
+	movl	16(%esi),	%ecx
+	movl	16(%edi),	%edx
+	addl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	addl	%edx,		%ecx
+	adcl	$0,		%eax
+	movl	%ecx,		16(%ebx)
+	# Round 5 
+	movl	20(%esi),	%ecx
+	movl	20(%edi),	%edx
+	addl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	addl	%edx,		%ecx
+	adcl	$0,		%eax
+	movl	%ecx,		20(%ebx)
+	# Round 6 
+	movl	24(%esi),	%ecx
+	movl	24(%edi),	%edx
+	addl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	addl	%edx,		%ecx
+	adcl	$0,		%eax
+	movl	%ecx,		24(%ebx)
+	# Round 7 
+	movl	28(%esi),	%ecx
+	movl	28(%edi),	%edx
+	addl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	addl	%edx,		%ecx
+	adcl	$0,		%eax
+	movl	%ecx,		28(%ebx)
+
+	addl	$32,		%esi
+	addl	$32,		%edi
+	addl	$32,		%ebx
+	subl	$8,		%ebp
+	jnz	.L012aw_loop
+.L011aw_finish:
+	movl	32(%esp),	%ebp
+	andl	$7,		%ebp
+	jz	.L013aw_end
+	# Tail Round 0 
+	movl	(%esi),		%ecx
+	movl	(%edi),		%edx
+	addl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	addl	%edx,		%ecx
+	adcl	$0,		%eax
+	decl	%ebp
+	movl	%ecx,		(%ebx)
+	jz	.L013aw_end
+	# Tail Round 1 
+	movl	4(%esi),	%ecx
+	movl	4(%edi),	%edx
+	addl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	addl	%edx,		%ecx
+	adcl	$0,		%eax
+	decl	%ebp
+	movl	%ecx,		4(%ebx)
+	jz	.L013aw_end
+	# Tail Round 2 
+	movl	8(%esi),	%ecx
+	movl	8(%edi),	%edx
+	addl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	addl	%edx,		%ecx
+	adcl	$0,		%eax
+	decl	%ebp
+	movl	%ecx,		8(%ebx)
+	jz	.L013aw_end
+	# Tail Round 3 
+	movl	12(%esi),	%ecx
+	movl	12(%edi),	%edx
+	addl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	addl	%edx,		%ecx
+	adcl	$0,		%eax
+	decl	%ebp
+	movl	%ecx,		12(%ebx)
+	jz	.L013aw_end
+	# Tail Round 4 
+	movl	16(%esi),	%ecx
+	movl	16(%edi),	%edx
+	addl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	addl	%edx,		%ecx
+	adcl	$0,		%eax
+	decl	%ebp
+	movl	%ecx,		16(%ebx)
+	jz	.L013aw_end
+	# Tail Round 5 
+	movl	20(%esi),	%ecx
+	movl	20(%edi),	%edx
+	addl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	addl	%edx,		%ecx
+	adcl	$0,		%eax
+	decl	%ebp
+	movl	%ecx,		20(%ebx)
+	jz	.L013aw_end
+	# Tail Round 6 
+	movl	24(%esi),	%ecx
+	movl	24(%edi),	%edx
+	addl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	addl	%edx,		%ecx
+	adcl	$0,		%eax
+	movl	%ecx,		24(%ebx)
+.L013aw_end:
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	popl	%ebp
+	ret
+.bn_add_words_end:
+	.size	bn_add_words,.bn_add_words_end-bn_add_words
+.ident	"bn_add_words"
+.text
+	.align 16
+.globl bn_sub_words
+	.type	bn_sub_words,@function
+bn_sub_words:
+	pushl	%ebp
+	pushl	%ebx
+	pushl	%esi
+	pushl	%edi
+
+
+	movl	20(%esp),	%ebx
+	movl	24(%esp),	%esi
+	movl	28(%esp),	%edi
+	movl	32(%esp),	%ebp
+	xorl	%eax,		%eax
+	andl	$4294967288,	%ebp
+	jz	.L014aw_finish
+.L015aw_loop:
+	# Round 0 
+	movl	(%esi),		%ecx
+	movl	(%edi),		%edx
+	subl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	subl	%edx,		%ecx
+	adcl	$0,		%eax
+	movl	%ecx,		(%ebx)
+	# Round 1 
+	movl	4(%esi),	%ecx
+	movl	4(%edi),	%edx
+	subl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	subl	%edx,		%ecx
+	adcl	$0,		%eax
+	movl	%ecx,		4(%ebx)
+	# Round 2 
+	movl	8(%esi),	%ecx
+	movl	8(%edi),	%edx
+	subl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	subl	%edx,		%ecx
+	adcl	$0,		%eax
+	movl	%ecx,		8(%ebx)
+	# Round 3 
+	movl	12(%esi),	%ecx
+	movl	12(%edi),	%edx
+	subl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	subl	%edx,		%ecx
+	adcl	$0,		%eax
+	movl	%ecx,		12(%ebx)
+	# Round 4 
+	movl	16(%esi),	%ecx
+	movl	16(%edi),	%edx
+	subl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	subl	%edx,		%ecx
+	adcl	$0,		%eax
+	movl	%ecx,		16(%ebx)
+	# Round 5 
+	movl	20(%esi),	%ecx
+	movl	20(%edi),	%edx
+	subl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	subl	%edx,		%ecx
+	adcl	$0,		%eax
+	movl	%ecx,		20(%ebx)
+	# Round 6 
+	movl	24(%esi),	%ecx
+	movl	24(%edi),	%edx
+	subl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	subl	%edx,		%ecx
+	adcl	$0,		%eax
+	movl	%ecx,		24(%ebx)
+	# Round 7 
+	movl	28(%esi),	%ecx
+	movl	28(%edi),	%edx
+	subl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	subl	%edx,		%ecx
+	adcl	$0,		%eax
+	movl	%ecx,		28(%ebx)
+
+	addl	$32,		%esi
+	addl	$32,		%edi
+	addl	$32,		%ebx
+	subl	$8,		%ebp
+	jnz	.L015aw_loop
+.L014aw_finish:
+	movl	32(%esp),	%ebp
+	andl	$7,		%ebp
+	jz	.L016aw_end
+	# Tail Round 0 
+	movl	(%esi),		%ecx
+	movl	(%edi),		%edx
+	subl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	subl	%edx,		%ecx
+	adcl	$0,		%eax
+	decl	%ebp
+	movl	%ecx,		(%ebx)
+	jz	.L016aw_end
+	# Tail Round 1 
+	movl	4(%esi),	%ecx
+	movl	4(%edi),	%edx
+	subl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	subl	%edx,		%ecx
+	adcl	$0,		%eax
+	decl	%ebp
+	movl	%ecx,		4(%ebx)
+	jz	.L016aw_end
+	# Tail Round 2 
+	movl	8(%esi),	%ecx
+	movl	8(%edi),	%edx
+	subl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	subl	%edx,		%ecx
+	adcl	$0,		%eax
+	decl	%ebp
+	movl	%ecx,		8(%ebx)
+	jz	.L016aw_end
+	# Tail Round 3 
+	movl	12(%esi),	%ecx
+	movl	12(%edi),	%edx
+	subl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	subl	%edx,		%ecx
+	adcl	$0,		%eax
+	decl	%ebp
+	movl	%ecx,		12(%ebx)
+	jz	.L016aw_end
+	# Tail Round 4 
+	movl	16(%esi),	%ecx
+	movl	16(%edi),	%edx
+	subl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	subl	%edx,		%ecx
+	adcl	$0,		%eax
+	decl	%ebp
+	movl	%ecx,		16(%ebx)
+	jz	.L016aw_end
+	# Tail Round 5 
+	movl	20(%esi),	%ecx
+	movl	20(%edi),	%edx
+	subl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	subl	%edx,		%ecx
+	adcl	$0,		%eax
+	decl	%ebp
+	movl	%ecx,		20(%ebx)
+	jz	.L016aw_end
+	# Tail Round 6 
+	movl	24(%esi),	%ecx
+	movl	24(%edi),	%edx
+	subl	%eax,		%ecx
+	movl	$0,		%eax
+	adcl	%eax,		%eax
+	subl	%edx,		%ecx
+	adcl	$0,		%eax
+	movl	%ecx,		24(%ebx)
+.L016aw_end:
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	popl	%ebp
+	ret
+.bn_sub_words_end:
+	.size	bn_sub_words,.bn_sub_words_end-bn_sub_words
+.ident	"bn_sub_words"
+.text
+	.align 16
+.globl bn_mul_comba8
+	.type	bn_mul_comba8,@function
+bn_mul_comba8:
+	pushl	%esi
+	movl	12(%esp),	%esi
+	pushl	%edi
+	movl	20(%esp),	%edi
+	pushl	%ebp
+	pushl	%ebx
+	xorl	%ebx,		%ebx
+	movl	(%esi),		%eax
+	xorl	%ecx,		%ecx
+	movl	(%edi),		%edx
+	# ################## Calculate word 0 
+	xorl	%ebp,		%ebp
+	# mul a[0]*b[0] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	movl	(%edi),		%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		(%eax)
+	movl	4(%esi),	%eax
+	# saved r[0] 
+	# ################## Calculate word 1 
+	xorl	%ebx,		%ebx
+	# mul a[1]*b[0] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	(%esi),		%eax
+	adcl	%edx,		%ebp
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[0]*b[1] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebp
+	movl	(%edi),		%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		4(%eax)
+	movl	8(%esi),	%eax
+	# saved r[1] 
+	# ################## Calculate word 2 
+	xorl	%ecx,		%ecx
+	# mul a[2]*b[0] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	4(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[1]*b[1] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	(%esi),		%eax
+	adcl	%edx,		%ebx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[0]*b[2] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebx
+	movl	(%edi),		%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		8(%eax)
+	movl	12(%esi),	%eax
+	# saved r[2] 
+	# ################## Calculate word 3 
+	xorl	%ebp,		%ebp
+	# mul a[3]*b[0] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[2]*b[1] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[1]*b[2] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	(%esi),		%eax
+	adcl	%edx,		%ecx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[0]*b[3] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	movl	(%edi),		%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		12(%eax)
+	movl	16(%esi),	%eax
+	# saved r[3] 
+	# ################## Calculate word 4 
+	xorl	%ebx,		%ebx
+	# mul a[4]*b[0] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	12(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[3]*b[1] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	8(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[2]*b[2] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[1]*b[3] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	(%esi),		%eax
+	adcl	%edx,		%ebp
+	movl	16(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[0]*b[4] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebp
+	movl	(%edi),		%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		16(%eax)
+	movl	20(%esi),	%eax
+	# saved r[4] 
+	# ################## Calculate word 5 
+	xorl	%ecx,		%ecx
+	# mul a[5]*b[0] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	16(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	4(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[4]*b[1] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	12(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[3]*b[2] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[2]*b[3] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	16(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[1]*b[4] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	(%esi),		%eax
+	adcl	%edx,		%ebx
+	movl	20(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[0]*b[5] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebx
+	movl	(%edi),		%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		20(%eax)
+	movl	24(%esi),	%eax
+	# saved r[5] 
+	# ################## Calculate word 6 
+	xorl	%ebp,		%ebp
+	# mul a[6]*b[0] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[5]*b[1] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	16(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[4]*b[2] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	12(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[3]*b[3] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	16(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[2]*b[4] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	20(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[1]*b[5] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	(%esi),		%eax
+	adcl	%edx,		%ecx
+	movl	24(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[0]*b[6] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	movl	(%edi),		%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		24(%eax)
+	movl	28(%esi),	%eax
+	# saved r[6] 
+	# ################## Calculate word 7 
+	xorl	%ebx,		%ebx
+	# mul a[7]*b[0] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	24(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[6]*b[1] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	8(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[5]*b[2] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	16(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[4]*b[3] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	12(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	16(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[3]*b[4] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	20(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[2]*b[5] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	24(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[1]*b[6] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	(%esi),		%eax
+	adcl	%edx,		%ebp
+	movl	28(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[0]*b[7] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebp
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		28(%eax)
+	movl	28(%esi),	%eax
+	# saved r[7] 
+	# ################## Calculate word 8 
+	xorl	%ecx,		%ecx
+	# mul a[7]*b[1] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	24(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[6]*b[2] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[5]*b[3] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	16(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	16(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[4]*b[4] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	12(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	20(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[3]*b[5] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	24(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[2]*b[6] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	28(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[1]*b[7] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		32(%eax)
+	movl	28(%esi),	%eax
+	# saved r[8] 
+	# ################## Calculate word 9 
+	xorl	%ebp,		%ebp
+	# mul a[7]*b[2] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	24(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[6]*b[3] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	16(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[5]*b[4] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	16(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	20(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[4]*b[5] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	12(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	24(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[3]*b[6] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	28(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[2]*b[7] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		36(%eax)
+	movl	28(%esi),	%eax
+	# saved r[9] 
+	# ################## Calculate word 10 
+	xorl	%ebx,		%ebx
+	# mul a[7]*b[3] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	24(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	16(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[6]*b[4] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	20(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[5]*b[5] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	16(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	24(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[4]*b[6] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	12(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	28(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[3]*b[7] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebp
+	movl	16(%edi),	%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		40(%eax)
+	movl	28(%esi),	%eax
+	# saved r[10] 
+	# ################## Calculate word 11 
+	xorl	%ecx,		%ecx
+	# mul a[7]*b[4] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	24(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	20(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[6]*b[5] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	24(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[5]*b[6] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	16(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	28(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[4]*b[7] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebx
+	movl	20(%edi),	%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		44(%eax)
+	movl	28(%esi),	%eax
+	# saved r[11] 
+	# ################## Calculate word 12 
+	xorl	%ebp,		%ebp
+	# mul a[7]*b[5] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	24(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	24(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[6]*b[6] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	28(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[5]*b[7] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	movl	24(%edi),	%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		48(%eax)
+	movl	28(%esi),	%eax
+	# saved r[12] 
+	# ################## Calculate word 13 
+	xorl	%ebx,		%ebx
+	# mul a[7]*b[6] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	24(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	28(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[6]*b[7] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebp
+	movl	28(%edi),	%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		52(%eax)
+	movl	28(%esi),	%eax
+	# saved r[13] 
+	# ################## Calculate word 14 
+	xorl	%ecx,		%ecx
+	# mul a[7]*b[7] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebx
+	adcl	$0,		%ecx
+	movl	%ebp,		56(%eax)
+	# saved r[14] 
+	# save r[15] 
+	movl	%ebx,		60(%eax)
+	popl	%ebx
+	popl	%ebp
+	popl	%edi
+	popl	%esi
+	ret
+.bn_mul_comba8_end:
+	.size	bn_mul_comba8,.bn_mul_comba8_end-bn_mul_comba8
+.ident	"desasm.pl"
+.text
+	.align 16
+.globl bn_mul_comba4
+	.type	bn_mul_comba4,@function
+bn_mul_comba4:
+	pushl	%esi
+	movl	12(%esp),	%esi
+	pushl	%edi
+	movl	20(%esp),	%edi
+	pushl	%ebp
+	pushl	%ebx
+	xorl	%ebx,		%ebx
+	movl	(%esi),		%eax
+	xorl	%ecx,		%ecx
+	movl	(%edi),		%edx
+	# ################## Calculate word 0 
+	xorl	%ebp,		%ebp
+	# mul a[0]*b[0] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	movl	(%edi),		%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		(%eax)
+	movl	4(%esi),	%eax
+	# saved r[0] 
+	# ################## Calculate word 1 
+	xorl	%ebx,		%ebx
+	# mul a[1]*b[0] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	(%esi),		%eax
+	adcl	%edx,		%ebp
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[0]*b[1] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebp
+	movl	(%edi),		%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		4(%eax)
+	movl	8(%esi),	%eax
+	# saved r[1] 
+	# ################## Calculate word 2 
+	xorl	%ecx,		%ecx
+	# mul a[2]*b[0] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	4(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[1]*b[1] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	(%esi),		%eax
+	adcl	%edx,		%ebx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[0]*b[2] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebx
+	movl	(%edi),		%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		8(%eax)
+	movl	12(%esi),	%eax
+	# saved r[2] 
+	# ################## Calculate word 3 
+	xorl	%ebp,		%ebp
+	# mul a[3]*b[0] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[2]*b[1] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ecx
+	movl	8(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[1]*b[2] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	(%esi),		%eax
+	adcl	%edx,		%ecx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebp
+	# mul a[0]*b[3] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	movl	4(%edi),	%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		12(%eax)
+	movl	12(%esi),	%eax
+	# saved r[3] 
+	# ################## Calculate word 4 
+	xorl	%ebx,		%ebx
+	# mul a[3]*b[1] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	8(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[2]*b[2] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	4(%esi),	%eax
+	adcl	%edx,		%ebp
+	movl	12(%edi),	%edx
+	adcl	$0,		%ebx
+	# mul a[1]*b[3] 
+	mull	%edx
+	addl	%eax,		%ecx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebp
+	movl	8(%edi),	%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		16(%eax)
+	movl	12(%esi),	%eax
+	# saved r[4] 
+	# ################## Calculate word 5 
+	xorl	%ecx,		%ecx
+	# mul a[3]*b[2] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	8(%esi),	%eax
+	adcl	%edx,		%ebx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ecx
+	# mul a[2]*b[3] 
+	mull	%edx
+	addl	%eax,		%ebp
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ebx
+	movl	12(%edi),	%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		20(%eax)
+	movl	12(%esi),	%eax
+	# saved r[5] 
+	# ################## Calculate word 6 
+	xorl	%ebp,		%ebp
+	# mul a[3]*b[3] 
+	mull	%edx
+	addl	%eax,		%ebx
+	movl	20(%esp),	%eax
+	adcl	%edx,		%ecx
+	adcl	$0,		%ebp
+	movl	%ebx,		24(%eax)
+	# saved r[6] 
+	# save r[7] 
+	movl	%ecx,		28(%eax)
+	popl	%ebx
+	popl	%ebp
+	popl	%edi
+	popl	%esi
+	ret
+.bn_mul_comba4_end:
+	.size	bn_mul_comba4,.bn_mul_comba4_end-bn_mul_comba4
+.ident	"desasm.pl"
+.text
+	.align 16
+.globl bn_sqr_comba8
+	.type	bn_sqr_comba8,@function
+bn_sqr_comba8:
+	pushl	%esi
+	pushl	%edi
+	pushl	%ebp
+	pushl	%ebx
+	movl	20(%esp),	%edi
+	movl	24(%esp),	%esi
+	xorl	%ebx,		%ebx
+	xorl	%ecx,		%ecx
+	movl	(%esi),		%eax
+	# ############### Calculate word 0 
+	xorl	%ebp,		%ebp
+	# sqr a[0]*a[0] 
+	mull	%eax
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	(%esi),		%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		(%edi)
+	movl	4(%esi),	%eax
+	# saved r[0] 
+	# ############### Calculate word 1 
+	xorl	%ebx,		%ebx
+	# sqr a[1]*a[0] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	8(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	%ecx,		4(%edi)
+	movl	(%esi),		%edx
+	# saved r[1] 
+	# ############### Calculate word 2 
+	xorl	%ecx,		%ecx
+	# sqr a[2]*a[0] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	4(%esi),	%eax
+	adcl	$0,		%ecx
+	# sqr a[1]*a[1] 
+	mull	%eax
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	(%esi),		%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		8(%edi)
+	movl	12(%esi),	%eax
+	# saved r[2] 
+	# ############### Calculate word 3 
+	xorl	%ebp,		%ebp
+	# sqr a[3]*a[0] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	8(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	4(%esi),	%edx
+	# sqr a[2]*a[1] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	16(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	%ebx,		12(%edi)
+	movl	(%esi),		%edx
+	# saved r[3] 
+	# ############### Calculate word 4 
+	xorl	%ebx,		%ebx
+	# sqr a[4]*a[0] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	12(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	4(%esi),	%edx
+	# sqr a[3]*a[1] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	8(%esi),	%eax
+	adcl	$0,		%ebx
+	# sqr a[2]*a[2] 
+	mull	%eax
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	(%esi),		%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		16(%edi)
+	movl	20(%esi),	%eax
+	# saved r[4] 
+	# ############### Calculate word 5 
+	xorl	%ecx,		%ecx
+	# sqr a[5]*a[0] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	16(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	4(%esi),	%edx
+	# sqr a[4]*a[1] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	12(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	8(%esi),	%edx
+	# sqr a[3]*a[2] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	24(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	%ebp,		20(%edi)
+	movl	(%esi),		%edx
+	# saved r[5] 
+	# ############### Calculate word 6 
+	xorl	%ebp,		%ebp
+	# sqr a[6]*a[0] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	20(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	4(%esi),	%edx
+	# sqr a[5]*a[1] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	16(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	8(%esi),	%edx
+	# sqr a[4]*a[2] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	12(%esi),	%eax
+	adcl	$0,		%ebp
+	# sqr a[3]*a[3] 
+	mull	%eax
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	(%esi),		%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		24(%edi)
+	movl	28(%esi),	%eax
+	# saved r[6] 
+	# ############### Calculate word 7 
+	xorl	%ebx,		%ebx
+	# sqr a[7]*a[0] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	24(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	4(%esi),	%edx
+	# sqr a[6]*a[1] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	20(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	8(%esi),	%edx
+	# sqr a[5]*a[2] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	16(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	12(%esi),	%edx
+	# sqr a[4]*a[3] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	28(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	%ecx,		28(%edi)
+	movl	4(%esi),	%edx
+	# saved r[7] 
+	# ############### Calculate word 8 
+	xorl	%ecx,		%ecx
+	# sqr a[7]*a[1] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	24(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	8(%esi),	%edx
+	# sqr a[6]*a[2] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	20(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	12(%esi),	%edx
+	# sqr a[5]*a[3] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	16(%esi),	%eax
+	adcl	$0,		%ecx
+	# sqr a[4]*a[4] 
+	mull	%eax
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	8(%esi),	%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		32(%edi)
+	movl	28(%esi),	%eax
+	# saved r[8] 
+	# ############### Calculate word 9 
+	xorl	%ebp,		%ebp
+	# sqr a[7]*a[2] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	24(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	12(%esi),	%edx
+	# sqr a[6]*a[3] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	20(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	16(%esi),	%edx
+	# sqr a[5]*a[4] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	28(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	%ebx,		36(%edi)
+	movl	12(%esi),	%edx
+	# saved r[9] 
+	# ############### Calculate word 10 
+	xorl	%ebx,		%ebx
+	# sqr a[7]*a[3] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	24(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	16(%esi),	%edx
+	# sqr a[6]*a[4] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	20(%esi),	%eax
+	adcl	$0,		%ebx
+	# sqr a[5]*a[5] 
+	mull	%eax
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	16(%esi),	%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		40(%edi)
+	movl	28(%esi),	%eax
+	# saved r[10] 
+	# ############### Calculate word 11 
+	xorl	%ecx,		%ecx
+	# sqr a[7]*a[4] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	24(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	20(%esi),	%edx
+	# sqr a[6]*a[5] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	28(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	%ebp,		44(%edi)
+	movl	20(%esi),	%edx
+	# saved r[11] 
+	# ############### Calculate word 12 
+	xorl	%ebp,		%ebp
+	# sqr a[7]*a[5] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	24(%esi),	%eax
+	adcl	$0,		%ebp
+	# sqr a[6]*a[6] 
+	mull	%eax
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	24(%esi),	%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		48(%edi)
+	movl	28(%esi),	%eax
+	# saved r[12] 
+	# ############### Calculate word 13 
+	xorl	%ebx,		%ebx
+	# sqr a[7]*a[6] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	28(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	%ecx,		52(%edi)
+	# saved r[13] 
+	# ############### Calculate word 14 
+	xorl	%ecx,		%ecx
+	# sqr a[7]*a[7] 
+	mull	%eax
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	adcl	$0,		%ecx
+	movl	%ebp,		56(%edi)
+	# saved r[14] 
+	movl	%ebx,		60(%edi)
+	popl	%ebx
+	popl	%ebp
+	popl	%edi
+	popl	%esi
+	ret
+.bn_sqr_comba8_end:
+	.size	bn_sqr_comba8,.bn_sqr_comba8_end-bn_sqr_comba8
+.ident	"desasm.pl"
+.text
+	.align 16
+.globl bn_sqr_comba4
+	.type	bn_sqr_comba4,@function
+bn_sqr_comba4:
+	pushl	%esi
+	pushl	%edi
+	pushl	%ebp
+	pushl	%ebx
+	movl	20(%esp),	%edi
+	movl	24(%esp),	%esi
+	xorl	%ebx,		%ebx
+	xorl	%ecx,		%ecx
+	movl	(%esi),		%eax
+	# ############### Calculate word 0 
+	xorl	%ebp,		%ebp
+	# sqr a[0]*a[0] 
+	mull	%eax
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	(%esi),		%edx
+	adcl	$0,		%ebp
+	movl	%ebx,		(%edi)
+	movl	4(%esi),	%eax
+	# saved r[0] 
+	# ############### Calculate word 1 
+	xorl	%ebx,		%ebx
+	# sqr a[1]*a[0] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	8(%esi),	%eax
+	adcl	$0,		%ebx
+	movl	%ecx,		4(%edi)
+	movl	(%esi),		%edx
+	# saved r[1] 
+	# ############### Calculate word 2 
+	xorl	%ecx,		%ecx
+	# sqr a[2]*a[0] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	4(%esi),	%eax
+	adcl	$0,		%ecx
+	# sqr a[1]*a[1] 
+	mull	%eax
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	(%esi),		%edx
+	adcl	$0,		%ecx
+	movl	%ebp,		8(%edi)
+	movl	12(%esi),	%eax
+	# saved r[2] 
+	# ############### Calculate word 3 
+	xorl	%ebp,		%ebp
+	# sqr a[3]*a[0] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	8(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	4(%esi),	%edx
+	# sqr a[2]*a[1] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebp
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	movl	12(%esi),	%eax
+	adcl	$0,		%ebp
+	movl	%ebx,		12(%edi)
+	movl	4(%esi),	%edx
+	# saved r[3] 
+	# ############### Calculate word 4 
+	xorl	%ebx,		%ebx
+	# sqr a[3]*a[1] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ebx
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	8(%esi),	%eax
+	adcl	$0,		%ebx
+	# sqr a[2]*a[2] 
+	mull	%eax
+	addl	%eax,		%ecx
+	adcl	%edx,		%ebp
+	movl	8(%esi),	%edx
+	adcl	$0,		%ebx
+	movl	%ecx,		16(%edi)
+	movl	12(%esi),	%eax
+	# saved r[4] 
+	# ############### Calculate word 5 
+	xorl	%ecx,		%ecx
+	# sqr a[3]*a[2] 
+	mull	%edx
+	addl	%eax,		%eax
+	adcl	%edx,		%edx
+	adcl	$0,		%ecx
+	addl	%eax,		%ebp
+	adcl	%edx,		%ebx
+	movl	12(%esi),	%eax
+	adcl	$0,		%ecx
+	movl	%ebp,		20(%edi)
+	# saved r[5] 
+	# ############### Calculate word 6 
+	xorl	%ebp,		%ebp
+	# sqr a[3]*a[3] 
+	mull	%eax
+	addl	%eax,		%ebx
+	adcl	%edx,		%ecx
+	adcl	$0,		%ebp
+	movl	%ebx,		24(%edi)
+	# saved r[6] 
+	movl	%ecx,		28(%edi)
+	popl	%ebx
+	popl	%ebp
+	popl	%edi
+	popl	%esi
+	ret
+.bn_sqr_comba4_end:
+	.size	bn_sqr_comba4,.bn_sqr_comba4_end-bn_sqr_comba4
+.ident	"desasm.pl"
diff --git a/crypto/bn/asm/f.s b/crypto/bn/asm/f.s
new file mode 100644
index 0000000..2f8f63c
--- /dev/null
+++ b/crypto/bn/asm/f.s
@@ -0,0 +1,1773 @@
+	# Don't even think of reading this code 
+	# It was automatically generated by bn-586.pl 
+	# Which is a perl program used to generate the alpha assember. 
+	# eric <eay@cryptsoft.com> 
+
+ # DEC Alpha assember
+ # Generated from perl scripts contains in SSLeay
+	.file	1 "bn-586.s"
+	.set noat
+	.text
+	.align 3
+	.globl bn_mul_words
+	.ent bn_mul_words
+bn_mul_words:
+bn_mul_words..ng:
+	.frame $30,0,$26,0
+	.prologue 0
+
+	subq	$18,	4,	$18
+	bis	$31,	$31,	$0
+	br	$100
+	blt	$18,	$100
+	ldq	$1,	0($17)
+	ldq	$2,	0($16)
+$101:
+	ldq	$3,	0($17)
+	mulq	$3,	$19,	$4
+	addq	$17,	8,	$17
+	umulh	$3,	$19,	$5
+	addq	$4,	$0,	$4
+	addq	$16,	8,	$16
+	subq	$18,	1,	$18
+	cmpult	$4,	$0,	$0
+	stq	$4,	-8($16)
+	addq	$5,	$0,	$0
+	bgt	$18,	$101
+	ret	$31,($26),1
+$100:
+	addq	$18,	4,	$18
+	bgt	$18,	$101
+$102:
+	ret	$31,($26),1
+	.end bn_mul_words
+	.text
+	.align 3
+	.globl bn_sqr_words
+	.ent bn_sqr_words
+bn_sqr_words:
+bn_sqr_words..ng:
+	.frame $30,0,$26,0
+	.prologue 0
+
+	subq	$18,	4,	$18
+	bis	$31,	$31,	$0
+	br	$103
+	blt	$18,	$103
+	ldq	$1,	0($17)
+	ldq	$2,	0($16)
+$104:
+	ldq	$3,	0($17)
+	mulq	$3,	$3,	$4
+	addq	$17,	8,	$17
+	addq	$16,	16,	$16
+	subq	$18,	1,	$18
+	umulh	$3,	$3,	$5
+	stq	$4,	-16($16)
+	stq	$5,	-8($16)
+	bgt	$18,	$104
+	ret	$31,($26),1
+$103:
+	addq	$18,	4,	$18
+	bgt	$18,	$104
+$105:
+	ret	$31,($26),1
+	.end bn_sqr_words
+	.text
+	.align 3
+	.globl bn_mul_add_words
+	.ent bn_mul_add_words
+bn_mul_add_words:
+bn_mul_add_words..ng:
+	.frame $30,0,$26,0
+	.prologue 0
+
+	subq	$18,	4,	$18
+	bis	$31,	$31,	$0
+	br	$106
+	blt	$18,	$106
+	ldq	$1,	0($17)
+	ldq	$2,	0($16)
+$107:
+	ldq	$3,	0($17)
+	ldq	$4,	0($16)
+	mulq	$3,	$19,	$5
+	subq	$18,	1,	$18
+	addq	$17,	8,	$17
+	umulh	$3,	$19,	$6
+	addq	$4,	$5,	$4
+	addq	$16,	8,	$16
+	cmpult	$4,	$5,	$7
+	addq	$4,	$0,	$4
+	addq	$6,	$7,	$6
+	cmpult	$4,	$0,	$0
+	stq	$4,	-8($16)
+	addq	$6,	$0,	$0
+	bgt	$18,	$107
+	ret	$31,($26),1
+$106:
+	addq	$18,	4,	$18
+	bgt	$18,	$107
+$108:
+	ret	$31,($26),1
+	.end bn_mul_add_words
+	.text
+	.align 3
+	.globl bn_add_words
+	.ent bn_add_words
+bn_add_words:
+bn_add_words..ng:
+	.frame $30,0,$26,0
+	.prologue 0
+
+	subq	$19,	4,	$19
+	bis	$31,	$31,	$0
+	br	$109
+	blt	$19,	$109
+	ldq	$1,	0($17)
+	ldq	$2,	0($18)
+$110:
+	ldq	$3,	8($17)
+	ldq	$4,	8($18)
+	ldq	$5,	16($17)
+	ldq	$6,	16($18)
+	ldq	$7,	24($17)
+	ldq	$8,	24($18)
+	addq	$1,	$2,	$22
+	cmpult	$22,	$2,	$23
+	addq	$22,	$0,	$22
+	cmpult	$22,	$0,	$0
+	addq	$0,	$23,	$0
+	addq	$3,	$4,	$25
+	cmpult	$25,	$4,	$24
+	addq	$25,	$0,	$25
+	cmpult	$25,	$0,	$0
+	addq	$0,	$24,	$0
+	addq	$5,	$6,	$28
+	cmpult	$28,	$6,	$27
+	addq	$28,	$0,	$28
+	cmpult	$28,	$0,	$0
+	addq	$0,	$27,	$0
+	addq	$7,	$8,	$20
+	cmpult	$20,	$8,	$21
+	addq	$20,	$0,	$20
+	cmpult	$20,	$0,	$0
+	addq	$0,	$21,	$0
+	stq	$22,	0($16)
+	stq	$25,	0($16)
+	stq	$28,	0($16)
+	stq	$20,	0($16)
+	subq	$19,	4,	$19
+	addq	$17,	32,	$17
+	addq	$18,	32,	$18
+	addq	$16,	32,	$16
+	blt	$19,	$109
+	ldq	$1,	0($17)
+	ldq	$2,	0($18)
+	br	$110
+$111:
+	ldq	$1,	0($17)
+	ldq	$2,	0($18)
+	addq	$1,	$2,	$3
+	cmpult	$3,	$2,	$23
+	addq	$3,	$0,	$3
+	cmpult	$3,	$0,	$0
+	addq	$0,	$23,	$0
+	stq	$3,	0($16)
+	addq	$17,	8,	$17
+	addq	$18,	8,	$18
+	addq	$16,	8,	$16
+	subq	$19,	1,	$19
+	bgt	$19,	$111
+	ret	$31,($26),1
+$109:
+	addq	$19,	4,	$19
+	bgt	$19,	$111
+$112:
+	ret	$31,($26),1
+	.end bn_add_words
+	.text
+	.align 3
+	.globl bn_sub_words
+	.ent bn_sub_words
+bn_sub_words:
+bn_sub_words..ng:
+	.frame $30,0,$26,0
+	.prologue 0
+
+	subq	$19,	4,	$19
+	bis	$31,	$31,	$0
+	blt	$19,	$113
+	ldq	$1,	0($17)
+	ldq	$2,	0($18)
+$114:
+	ldq	$3,	8($17)
+	cmpult	$1,	$2,	$4
+	ldq	$5,	8($18)
+	subq	$1,	$2,	$1
+	ldq	$6,	16($17)
+	cmpult	$1,	$0,	$2
+	ldq	$7,	16($18)
+	subq	$1,	$0,	$23
+	ldq	$8,	24($17)
+	addq	$2,	$4,	$0
+	cmpult	$3,	$5,	$24
+	subq	$3,	$5,	$3
+	ldq	$22,	24($18)
+	cmpult	$3,	$0,	$5
+	subq	$3,	$0,	$25
+	addq	$5,	$24,	$0
+	cmpult	$6,	$7,	$27
+	subq	$6,	$7,	$6
+	stq	$23,	0($16)
+	cmpult	$6,	$0,	$7
+	subq	$6,	$0,	$28
+	addq	$7,	$27,	$0
+	cmpult	$8,	$22,	$21
+	subq	$8,	$22,	$8
+	stq	$25,	8($16)
+	cmpult	$8,	$0,	$22
+	subq	$8,	$0,	$20
+	addq	$22,	$21,	$0
+	stq	$28,	16($16)
+	subq	$19,	4,	$19
+	stq	$20,	24($16)
+	addq	$17,	32,	$17
+	addq	$18,	32,	$18
+	addq	$16,	32,	$16
+	blt	$19,	$113
+	ldq	$1,	0($17)
+	ldq	$2,	0($18)
+	br	$114
+$115:
+	ldq	$1,	0($17)
+	ldq	$2,	0($18)
+	cmpult	$1,	$2,	$27
+	subq	$1,	$2,	$1
+	cmpult	$1,	$0,	$2
+	subq	$1,	$0,	$1
+	stq	$1,	0($16)
+	addq	$2,	$27,	$0
+	addq	$17,	8,	$17
+	addq	$18,	8,	$18
+	addq	$16,	8,	$16
+	subq	$19,	1,	$19
+	bgt	$19,	$115
+	ret	$31,($26),1
+$113:
+	addq	$19,	4,	$19
+	bgt	$19,	$115
+$116:
+	ret	$31,($26),1
+	.end bn_sub_words
+ #
+ # What follows was taken directly from the C compiler with a few
+ # hacks to redo the lables.
+ #
+.text
+	.align 3
+	.globl bn_div64
+	.ent bn_div64
+bn_div64:
+	ldgp $29,0($27)
+bn_div64..ng:
+	lda $30,-48($30)
+	.frame $30,48,$26,0
+	stq $26,0($30)
+	stq $9,8($30)
+	stq $10,16($30)
+	stq $11,24($30)
+	stq $12,32($30)
+	stq $13,40($30)
+	.mask 0x4003e00,-48
+	.prologue 1
+	bis $16,$16,$9
+	bis $17,$17,$10
+	bis $18,$18,$11
+	bis $31,$31,$13
+	bis $31,2,$12
+	bne $11,$9119
+	lda $0,-1
+	br $31,$9136
+	.align 4
+$9119:
+	bis $11,$11,$16
+	jsr $26,BN_num_bits_word
+	ldgp $29,0($26)
+	subq $0,64,$1
+	beq $1,$9120
+	bis $31,1,$1
+	sll $1,$0,$1
+	cmpule $9,$1,$1
+	bne $1,$9120
+ #	lda $16,_IO_stderr_
+ #	lda $17,$C32
+ #	bis $0,$0,$18
+ #	jsr $26,fprintf
+ #	ldgp $29,0($26)
+	jsr $26,abort
+	ldgp $29,0($26)
+	.align 4
+$9120:
+	bis $31,64,$3
+	cmpult $9,$11,$2
+	subq $3,$0,$1
+	addl $1,$31,$0
+	subq $9,$11,$1
+	cmoveq $2,$1,$9
+	beq $0,$9122
+	zapnot $0,15,$2
+	subq $3,$0,$1
+	sll $11,$2,$11
+	sll $9,$2,$3
+	srl $10,$1,$1
+	sll $10,$2,$10
+	bis $3,$1,$9
+$9122:
+	srl $11,32,$5
+	zapnot $11,15,$6
+	lda $7,-1
+	.align 5
+$9123:
+	srl $9,32,$1
+	subq $1,$5,$1
+	bne $1,$9126
+	zapnot $7,15,$27
+	br $31,$9127
+	.align 4
+$9126:
+	bis $9,$9,$24
+	bis $5,$5,$25
+	divqu $24,$25,$27
+$9127:
+	srl $10,32,$4
+	.align 5
+$9128:
+	mulq $27,$5,$1
+	subq $9,$1,$3
+	zapnot $3,240,$1
+	bne $1,$9129
+	mulq $6,$27,$2
+	sll $3,32,$1
+	addq $1,$4,$1
+	cmpule $2,$1,$2
+	bne $2,$9129
+	subq $27,1,$27
+	br $31,$9128
+	.align 4
+$9129:
+	mulq $27,$6,$1
+	mulq $27,$5,$4
+	srl $1,32,$3
+	sll $1,32,$1
+	addq $4,$3,$4
+	cmpult $10,$1,$2
+	subq $10,$1,$10
+	addq $2,$4,$2
+	cmpult $9,$2,$1
+	bis $2,$2,$4
+	beq $1,$9134
+	addq $9,$11,$9
+	subq $27,1,$27
+$9134:
+	subl $12,1,$12
+	subq $9,$4,$9
+	beq $12,$9124
+	sll $27,32,$13
+	sll $9,32,$2
+	srl $10,32,$1
+	sll $10,32,$10
+	bis $2,$1,$9
+	br $31,$9123
+	.align 4
+$9124:
+	bis $13,$27,$0
+$9136:
+	ldq $26,0($30)
+	ldq $9,8($30)
+	ldq $10,16($30)
+	ldq $11,24($30)
+	ldq $12,32($30)
+	ldq $13,40($30)
+	addq $30,48,$30
+	ret $31,($26),1
+	.end bn_div64
+	.text
+	.align 3
+	.globl bn_mul_comba8
+	.ent bn_mul_comba8
+bn_mul_comba8:
+bn_mul_comba8..ng:
+	.frame $30,0,$26,0
+	.prologue 0
+
+	subq	$30,	16,	$30
+	ldq	$0,	0($17)
+	ldq	$1,	0($18)
+	stq	$9,	0($30)
+	stq	$10,	8($30)
+	ldq	$2,	8($17)
+	ldq	$3,	8($18)
+	ldq	$4,	16($17)
+	ldq	$5,	16($18)
+	ldq	$6,	24($17)
+	ldq	$7,	24($18)
+	ldq	$8,	8($17)
+	ldq	$22,	8($18)
+	ldq	$23,	8($17)
+	ldq	$24,	8($18)
+	ldq	$25,	8($17)
+	ldq	$27,	8($18)
+	ldq	$28,	8($17)
+	ldq	$21,	8($18)
+	bis	$31,	$31,	$9
+	mulq	$0,	$1,	$20
+	umulh	$0,	$1,	$19
+	stq	$20,	0($16)
+	bis	$31,	$31,	$10
+	mulq	$0,	$3,	$17
+	umulh	$0,	$3,	$18
+	addq	$19,	$17,	$19
+	cmpult	$19,	$17,	$20
+	addq	$20,	$18,	$18
+	addq	$9,	$18,	$9
+	cmpult	$9,	$18,	$17
+	addq	$10,	$17,	$10
+	mulq	$2,	$1,	$20
+	umulh	$2,	$1,	$18
+	addq	$19,	$20,	$19
+	cmpult	$19,	$20,	$17
+	addq	$17,	$18,	$18
+	addq	$9,	$18,	$9
+	cmpult	$9,	$18,	$20
+	addq	$10,	$20,	$10
+	stq	$19,	8($16)
+	bis	$31,	$31,	$17
+	mulq	$0,	$5,	$18
+	umulh	$0,	$5,	$20
+	addq	$9,	$18,	$9
+	cmpult	$9,	$18,	$19
+	addq	$19,	$20,	$20
+	addq	$10,	$20,	$10
+	cmpult	$10,	$20,	$18
+	addq	$17,	$18,	$17
+	mulq	$2,	$3,	$19
+	umulh	$2,	$3,	$20
+	addq	$9,	$19,	$9
+	cmpult	$9,	$19,	$18
+	addq	$18,	$20,	$20
+	addq	$10,	$20,	$10
+	cmpult	$10,	$20,	$19
+	addq	$17,	$19,	$17
+	mulq	$4,	$1,	$18
+	umulh	$4,	$1,	$20
+	addq	$9,	$18,	$9
+	cmpult	$9,	$18,	$19
+	addq	$19,	$20,	$20
+	addq	$10,	$20,	$10
+	cmpult	$10,	$20,	$18
+	addq	$17,	$18,	$17
+	stq	$9,	16($16)
+	bis	$31,	$31,	$19
+	mulq	$0,	$7,	$20
+	umulh	$0,	$7,	$18
+	addq	$10,	$20,	$10
+	cmpult	$10,	$20,	$9
+	addq	$9,	$18,	$18
+	addq	$17,	$18,	$17
+	cmpult	$17,	$18,	$20
+	addq	$19,	$20,	$19
+	mulq	$2,	$5,	$9
+	umulh	$2,	$5,	$18
+	addq	$10,	$9,	$10
+	cmpult	$10,	$9,	$20
+	addq	$20,	$18,	$18
+	addq	$17,	$18,	$17
+	cmpult	$17,	$18,	$9
+	addq	$19,	$9,	$19
+	mulq	$4,	$3,	$20
+	umulh	$4,	$3,	$18
+	addq	$10,	$20,	$10
+	cmpult	$10,	$20,	$9
+	addq	$9,	$18,	$18
+	addq	$17,	$18,	$17
+	cmpult	$17,	$18,	$20
+	addq	$19,	$20,	$19
+	mulq	$6,	$1,	$9
+	umulh	$6,	$1,	$18
+	addq	$10,	$9,	$10
+	cmpult	$10,	$9,	$20
+	addq	$20,	$18,	$18
+	addq	$17,	$18,	$17
+	cmpult	$17,	$18,	$9
+	addq	$19,	$9,	$19
+	stq	$10,	24($16)
+	bis	$31,	$31,	$20
+	mulq	$0,	$22,	$18
+	umulh	$0,	$22,	$9
+	addq	$17,	$18,	$17
+	cmpult	$17,	$18,	$10
+	addq	$10,	$9,	$9
+	addq	$19,	$9,	$19
+	cmpult	$19,	$9,	$18
+	addq	$20,	$18,	$20
+	mulq	$2,	$7,	$10
+	umulh	$2,	$7,	$9
+	addq	$17,	$10,	$17
+	cmpult	$17,	$10,	$18
+	addq	$18,	$9,	$9
+	addq	$19,	$9,	$19
+	cmpult	$19,	$9,	$10
+	addq	$20,	$10,	$20
+	mulq	$4,	$5,	$18
+	umulh	$4,	$5,	$9
+	addq	$17,	$18,	$17
+	cmpult	$17,	$18,	$10
+	addq	$10,	$9,	$9
+	addq	$19,	$9,	$19
+	cmpult	$19,	$9,	$18
+	addq	$20,	$18,	$20
+	mulq	$6,	$3,	$10
+	umulh	$6,	$3,	$9
+	addq	$17,	$10,	$17
+	cmpult	$17,	$10,	$18
+	addq	$18,	$9,	$9
+	addq	$19,	$9,	$19
+	cmpult	$19,	$9,	$10
+	addq	$20,	$10,	$20
+	mulq	$8,	$1,	$18
+	umulh	$8,	$1,	$9
+	addq	$17,	$18,	$17
+	cmpult	$17,	$18,	$10
+	addq	$10,	$9,	$9
+	addq	$19,	$9,	$19
+	cmpult	$19,	$9,	$18
+	addq	$20,	$18,	$20
+	stq	$17,	32($16)
+	bis	$31,	$31,	$10
+	mulq	$0,	$24,	$9
+	umulh	$0,	$24,	$18
+	addq	$19,	$9,	$19
+	cmpult	$19,	$9,	$17
+	addq	$17,	$18,	$18
+	addq	$20,	$18,	$20
+	cmpult	$20,	$18,	$9
+	addq	$10,	$9,	$10
+	mulq	$2,	$22,	$17
+	umulh	$2,	$22,	$18
+	addq	$19,	$17,	$19
+	cmpult	$19,	$17,	$9
+	addq	$9,	$18,	$18
+	addq	$20,	$18,	$20
+	cmpult	$20,	$18,	$17
+	addq	$10,	$17,	$10
+	mulq	$4,	$7,	$9
+	umulh	$4,	$7,	$18
+	addq	$19,	$9,	$19
+	cmpult	$19,	$9,	$17
+	addq	$17,	$18,	$18
+	addq	$20,	$18,	$20
+	cmpult	$20,	$18,	$9
+	addq	$10,	$9,	$10
+	mulq	$6,	$5,	$17
+	umulh	$6,	$5,	$18
+	addq	$19,	$17,	$19
+	cmpult	$19,	$17,	$9
+	addq	$9,	$18,	$18
+	addq	$20,	$18,	$20
+	cmpult	$20,	$18,	$17
+	addq	$10,	$17,	$10
+	mulq	$8,	$3,	$9
+	umulh	$8,	$3,	$18
+	addq	$19,	$9,	$19
+	cmpult	$19,	$9,	$17
+	addq	$17,	$18,	$18
+	addq	$20,	$18,	$20
+	cmpult	$20,	$18,	$9
+	addq	$10,	$9,	$10
+	mulq	$23,	$1,	$17
+	umulh	$23,	$1,	$18
+	addq	$19,	$17,	$19
+	cmpult	$19,	$17,	$9
+	addq	$9,	$18,	$18
+	addq	$20,	$18,	$20
+	cmpult	$20,	$18,	$17
+	addq	$10,	$17,	$10
+	stq	$19,	40($16)
+	bis	$31,	$31,	$9
+	mulq	$0,	$27,	$18
+	umulh	$0,	$27,	$17
+	addq	$20,	$18,	$20
+	cmpult	$20,	$18,	$19
+	addq	$19,	$17,	$17
+	addq	$10,	$17,	$10
+	cmpult	$10,	$17,	$18
+	addq	$9,	$18,	$9
+	mulq	$2,	$24,	$19
+	umulh	$2,	$24,	$17
+	addq	$20,	$19,	$20
+	cmpult	$20,	$19,	$18
+	addq	$18,	$17,	$17
+	addq	$10,	$17,	$10
+	cmpult	$10,	$17,	$19
+	addq	$9,	$19,	$9
+	mulq	$4,	$22,	$18
+	umulh	$4,	$22,	$17
+	addq	$20,	$18,	$20
+	cmpult	$20,	$18,	$19
+	addq	$19,	$17,	$17
+	addq	$10,	$17,	$10
+	cmpult	$10,	$17,	$18
+	addq	$9,	$18,	$9
+	mulq	$6,	$7,	$19
+	umulh	$6,	$7,	$17
+	addq	$20,	$19,	$20
+	cmpult	$20,	$19,	$18
+	addq	$18,	$17,	$17
+	addq	$10,	$17,	$10
+	cmpult	$10,	$17,	$19
+	addq	$9,	$19,	$9
+	mulq	$8,	$5,	$18
+	umulh	$8,	$5,	$17
+	addq	$20,	$18,	$20
+	cmpult	$20,	$18,	$19
+	addq	$19,	$17,	$17
+	addq	$10,	$17,	$10
+	cmpult	$10,	$17,	$18
+	addq	$9,	$18,	$9
+	mulq	$23,	$3,	$19
+	umulh	$23,	$3,	$17
+	addq	$20,	$19,	$20
+	cmpult	$20,	$19,	$18
+	addq	$18,	$17,	$17
+	addq	$10,	$17,	$10
+	cmpult	$10,	$17,	$19
+	addq	$9,	$19,	$9
+	mulq	$25,	$1,	$18
+	umulh	$25,	$1,	$17
+	addq	$20,	$18,	$20
+	cmpult	$20,	$18,	$19
+	addq	$19,	$17,	$17
+	addq	$10,	$17,	$10
+	cmpult	$10,	$17,	$18
+	addq	$9,	$18,	$9
+	stq	$20,	48($16)
+	bis	$31,	$31,	$19
+	mulq	$0,	$21,	$17
+	umulh	$0,	$21,	$18
+	addq	$10,	$17,	$10
+	cmpult	$10,	$17,	$20
+	addq	$20,	$18,	$18
+	addq	$9,	$18,	$9
+	cmpult	$9,	$18,	$17
+	addq	$19,	$17,	$19
+	mulq	$2,	$27,	$20
+	umulh	$2,	$27,	$18
+	addq	$10,	$20,	$10
+	cmpult	$10,	$20,	$17
+	addq	$17,	$18,	$18
+	addq	$9,	$18,	$9
+	cmpult	$9,	$18,	$0
+	addq	$19,	$0,	$19
+	mulq	$4,	$24,	$20
+	umulh	$4,	$24,	$17
+	addq	$10,	$20,	$10
+	cmpult	$10,	$20,	$18
+	addq	$18,	$17,	$17
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$0
+	addq	$19,	$0,	$19
+	mulq	$6,	$22,	$20
+	umulh	$6,	$22,	$18
+	addq	$10,	$20,	$10
+	cmpult	$10,	$20,	$17
+	addq	$17,	$18,	$18
+	addq	$9,	$18,	$9
+	cmpult	$9,	$18,	$0
+	addq	$19,	$0,	$19
+	mulq	$8,	$7,	$20
+	umulh	$8,	$7,	$17
+	addq	$10,	$20,	$10
+	cmpult	$10,	$20,	$18
+	addq	$18,	$17,	$17
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$0
+	addq	$19,	$0,	$19
+	mulq	$23,	$5,	$20
+	umulh	$23,	$5,	$18
+	addq	$10,	$20,	$10
+	cmpult	$10,	$20,	$17
+	addq	$17,	$18,	$18
+	addq	$9,	$18,	$9
+	cmpult	$9,	$18,	$0
+	addq	$19,	$0,	$19
+	mulq	$25,	$3,	$20
+	umulh	$25,	$3,	$17
+	addq	$10,	$20,	$10
+	cmpult	$10,	$20,	$18
+	addq	$18,	$17,	$17
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$0
+	addq	$19,	$0,	$19
+	mulq	$28,	$1,	$20
+	umulh	$28,	$1,	$18
+	addq	$10,	$20,	$10
+	cmpult	$10,	$20,	$17
+	addq	$17,	$18,	$18
+	addq	$9,	$18,	$9
+	cmpult	$9,	$18,	$0
+	addq	$19,	$0,	$19
+	stq	$10,	56($16)
+	bis	$31,	$31,	$20
+	mulq	$2,	$21,	$17
+	umulh	$2,	$21,	$18
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$0
+	addq	$0,	$18,	$18
+	addq	$19,	$18,	$19
+	cmpult	$19,	$18,	$1
+	addq	$20,	$1,	$20
+	mulq	$4,	$27,	$10
+	umulh	$4,	$27,	$17
+	addq	$9,	$10,	$9
+	cmpult	$9,	$10,	$0
+	addq	$0,	$17,	$17
+	addq	$19,	$17,	$19
+	cmpult	$19,	$17,	$18
+	addq	$20,	$18,	$20
+	mulq	$6,	$24,	$1
+	umulh	$6,	$24,	$2
+	addq	$9,	$1,	$9
+	cmpult	$9,	$1,	$10
+	addq	$10,	$2,	$2
+	addq	$19,	$2,	$19
+	cmpult	$19,	$2,	$0
+	addq	$20,	$0,	$20
+	mulq	$8,	$22,	$17
+	umulh	$8,	$22,	$18
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$1
+	addq	$1,	$18,	$18
+	addq	$19,	$18,	$19
+	cmpult	$19,	$18,	$10
+	addq	$20,	$10,	$20
+	mulq	$23,	$7,	$2
+	umulh	$23,	$7,	$0
+	addq	$9,	$2,	$9
+	cmpult	$9,	$2,	$17
+	addq	$17,	$0,	$0
+	addq	$19,	$0,	$19
+	cmpult	$19,	$0,	$1
+	addq	$20,	$1,	$20
+	mulq	$25,	$5,	$18
+	umulh	$25,	$5,	$10
+	addq	$9,	$18,	$9
+	cmpult	$9,	$18,	$2
+	addq	$2,	$10,	$10
+	addq	$19,	$10,	$19
+	cmpult	$19,	$10,	$17
+	addq	$20,	$17,	$20
+	mulq	$28,	$3,	$0
+	umulh	$28,	$3,	$1
+	addq	$9,	$0,	$9
+	cmpult	$9,	$0,	$18
+	addq	$18,	$1,	$1
+	addq	$19,	$1,	$19
+	cmpult	$19,	$1,	$2
+	addq	$20,	$2,	$20
+	stq	$9,	64($16)
+	bis	$31,	$31,	$10
+	mulq	$4,	$21,	$17
+	umulh	$4,	$21,	$0
+	addq	$19,	$17,	$19
+	cmpult	$19,	$17,	$18
+	addq	$18,	$0,	$0
+	addq	$20,	$0,	$20
+	cmpult	$20,	$0,	$1
+	addq	$10,	$1,	$10
+	mulq	$6,	$27,	$2
+	umulh	$6,	$27,	$3
+	addq	$19,	$2,	$19
+	cmpult	$19,	$2,	$9
+	addq	$9,	$3,	$3
+	addq	$20,	$3,	$20
+	cmpult	$20,	$3,	$17
+	addq	$10,	$17,	$10
+	mulq	$8,	$24,	$18
+	umulh	$8,	$24,	$0
+	addq	$19,	$18,	$19
+	cmpult	$19,	$18,	$1
+	addq	$1,	$0,	$0
+	addq	$20,	$0,	$20
+	cmpult	$20,	$0,	$4
+	addq	$10,	$4,	$10
+	mulq	$23,	$22,	$2
+	umulh	$23,	$22,	$9
+	addq	$19,	$2,	$19
+	cmpult	$19,	$2,	$3
+	addq	$3,	$9,	$9
+	addq	$20,	$9,	$20
+	cmpult	$20,	$9,	$17
+	addq	$10,	$17,	$10
+	mulq	$25,	$7,	$18
+	umulh	$25,	$7,	$1
+	addq	$19,	$18,	$19
+	cmpult	$19,	$18,	$0
+	addq	$0,	$1,	$1
+	addq	$20,	$1,	$20
+	cmpult	$20,	$1,	$4
+	addq	$10,	$4,	$10
+	mulq	$28,	$5,	$2
+	umulh	$28,	$5,	$3
+	addq	$19,	$2,	$19
+	cmpult	$19,	$2,	$9
+	addq	$9,	$3,	$3
+	addq	$20,	$3,	$20
+	cmpult	$20,	$3,	$17
+	addq	$10,	$17,	$10
+	stq	$19,	72($16)
+	bis	$31,	$31,	$18
+	mulq	$6,	$21,	$0
+	umulh	$6,	$21,	$1
+	addq	$20,	$0,	$20
+	cmpult	$20,	$0,	$4
+	addq	$4,	$1,	$1
+	addq	$10,	$1,	$10
+	cmpult	$10,	$1,	$2
+	addq	$18,	$2,	$18
+	mulq	$8,	$27,	$9
+	umulh	$8,	$27,	$3
+	addq	$20,	$9,	$20
+	cmpult	$20,	$9,	$17
+	addq	$17,	$3,	$3
+	addq	$10,	$3,	$10
+	cmpult	$10,	$3,	$5
+	addq	$18,	$5,	$18
+	mulq	$23,	$24,	$19
+	umulh	$23,	$24,	$0
+	addq	$20,	$19,	$20
+	cmpult	$20,	$19,	$4
+	addq	$4,	$0,	$0
+	addq	$10,	$0,	$10
+	cmpult	$10,	$0,	$1
+	addq	$18,	$1,	$18
+	mulq	$25,	$22,	$2
+	umulh	$25,	$22,	$6
+	addq	$20,	$2,	$20
+	cmpult	$20,	$2,	$9
+	addq	$9,	$6,	$6
+	addq	$10,	$6,	$10
+	cmpult	$10,	$6,	$17
+	addq	$18,	$17,	$18
+	mulq	$28,	$7,	$3
+	umulh	$28,	$7,	$5
+	addq	$20,	$3,	$20
+	cmpult	$20,	$3,	$19
+	addq	$19,	$5,	$5
+	addq	$10,	$5,	$10
+	cmpult	$10,	$5,	$4
+	addq	$18,	$4,	$18
+	stq	$20,	80($16)
+	bis	$31,	$31,	$0
+	mulq	$8,	$21,	$1
+	umulh	$8,	$21,	$2
+	addq	$10,	$1,	$10
+	cmpult	$10,	$1,	$9
+	addq	$9,	$2,	$2
+	addq	$18,	$2,	$18
+	cmpult	$18,	$2,	$6
+	addq	$0,	$6,	$0
+	mulq	$23,	$27,	$17
+	umulh	$23,	$27,	$3
+	addq	$10,	$17,	$10
+	cmpult	$10,	$17,	$19
+	addq	$19,	$3,	$3
+	addq	$18,	$3,	$18
+	cmpult	$18,	$3,	$5
+	addq	$0,	$5,	$0
+	mulq	$25,	$24,	$4
+	umulh	$25,	$24,	$7
+	addq	$10,	$4,	$10
+	cmpult	$10,	$4,	$20
+	addq	$20,	$7,	$7
+	addq	$18,	$7,	$18
+	cmpult	$18,	$7,	$1
+	addq	$0,	$1,	$0
+	mulq	$28,	$22,	$9
+	umulh	$28,	$22,	$2
+	addq	$10,	$9,	$10
+	cmpult	$10,	$9,	$6
+	addq	$6,	$2,	$2
+	addq	$18,	$2,	$18
+	cmpult	$18,	$2,	$8
+	addq	$0,	$8,	$0
+	stq	$10,	88($16)
+	bis	$31,	$31,	$17
+	mulq	$23,	$21,	$19
+	umulh	$23,	$21,	$3
+	addq	$18,	$19,	$18
+	cmpult	$18,	$19,	$5
+	addq	$5,	$3,	$3
+	addq	$0,	$3,	$0
+	cmpult	$0,	$3,	$4
+	addq	$17,	$4,	$17
+	mulq	$25,	$27,	$20
+	umulh	$25,	$27,	$7
+	addq	$18,	$20,	$18
+	cmpult	$18,	$20,	$1
+	addq	$1,	$7,	$7
+	addq	$0,	$7,	$0
+	cmpult	$0,	$7,	$9
+	addq	$17,	$9,	$17
+	mulq	$28,	$24,	$6
+	umulh	$28,	$24,	$2
+	addq	$18,	$6,	$18
+	cmpult	$18,	$6,	$8
+	addq	$8,	$2,	$2
+	addq	$0,	$2,	$0
+	cmpult	$0,	$2,	$22
+	addq	$17,	$22,	$17
+	stq	$18,	96($16)
+	bis	$31,	$31,	$10
+	mulq	$25,	$21,	$19
+	umulh	$25,	$21,	$5
+	addq	$0,	$19,	$0
+	cmpult	$0,	$19,	$3
+	addq	$3,	$5,	$5
+	addq	$17,	$5,	$17
+	cmpult	$17,	$5,	$4
+	addq	$10,	$4,	$10
+	mulq	$28,	$27,	$23
+	umulh	$28,	$27,	$20
+	addq	$0,	$23,	$0
+	cmpult	$0,	$23,	$1
+	addq	$1,	$20,	$20
+	addq	$17,	$20,	$17
+	cmpult	$17,	$20,	$7
+	addq	$10,	$7,	$10
+	stq	$0,	104($16)
+	bis	$31,	$31,	$9
+	mulq	$28,	$21,	$6
+	umulh	$28,	$21,	$8
+	addq	$17,	$6,	$17
+	cmpult	$17,	$6,	$2
+	addq	$2,	$8,	$8
+	addq	$10,	$8,	$10
+	cmpult	$10,	$8,	$22
+	addq	$9,	$22,	$9
+	stq	$17,	112($16)
+	stq	$10,	120($16)
+	ldq	$9,	0($30)
+	ldq	$10,	8($30)
+	addq	$30,	16,	$30
+	ret	$31,($26),1
+	.end bn_mul_comba8
+	.text
+	.align 3
+	.globl bn_mul_comba4
+	.ent bn_mul_comba4
+bn_mul_comba4:
+bn_mul_comba4..ng:
+	.frame $30,0,$26,0
+	.prologue 0
+
+	ldq	$0,	0($17)
+	ldq	$1,	0($18)
+	ldq	$2,	8($17)
+	ldq	$3,	8($18)
+	mulq	$0,	$1,	$4
+	ldq	$5,	16($17)
+	ldq	$6,	16($18)
+	umulh	$0,	$1,	$7
+	ldq	$8,	24($17)
+	ldq	$22,	24($18)
+	mulq	$0,	$3,	$23
+	stq	$4,	0($16)
+	bis	$31,	$31,	$24
+	mulq	$2,	$1,	$28
+	bis	$31,	$31,	$25
+	bis	$31,	$31,	
+	addq	$24,	$7,	$24
+	umulh	$0,	$3,	$21
+	cmpult	$24,	$7,	$20
+	addq	$24,	$23,	$24
+	addq	$25,	$20,	$25
+	umulh	$2,	$1,	$19
+	cmpult	$24,	$23,	$17
+	addq	$24,	$28,	$24
+	addq	$27,	$17,	$27
+	mulq	$0,	$6,	$18
+	cmpult	$24,	$28,	$4
+	addq	$25,	$4,	$25
+	stq	$24,	8($16)
+	addq	$25,	$27,	$24
+	bis	$31,	$31,	$25
+	addq	$24,	$21,	$24
+	bis	$31,	$31,	$27
+	mulq	$2,	$3,	$7
+	cmpult	$24,	$21,	$20
+	addq	$24,	$19,	$24
+	addq	$25,	$20,	$25
+	mulq	$5,	$1,	$23
+	cmpult	$24,	$19,	$17
+	addq	$24,	$7,	$24
+	addq	$27,	$17,	$27
+	umulh	$0,	$6,	$28
+	cmpult	$24,	$18,	$4
+	addq	$24,	$7,	$24
+	addq	$25,	$4,	$25
+	umulh	$2,	$3,	$21
+	cmpult	$24,	$7,	$20
+	addq	$24,	$23,	$24
+	addq	$27,	$20,	$27
+	umulh	$5,	$1,	$19
+	cmpult	$24,	$23,	$17
+	addq	$25,	$17,	$25
+	stq	$24,	16($16)
+	addq	$25,	$27,	$24
+	bis	$31,	$31,	$25
+	addq	$24,	$28,	$24
+	bis	$31,	$31,	$27
+	mulq	$0,	$22,	$18
+	cmpult	$24,	$28,	$4
+	addq	$24,	$21,	$24
+	addq	$25,	$4,	$25
+	mulq	$2,	$6,	$7
+	cmpult	$24,	$21,	$20
+	addq	$24,	$19,	$24
+	addq	$25,	$20,	$25
+	mulq	$5,	$3,	$23
+	cmpult	$24,	$19,	$17
+	addq	$24,	$18,	$24
+	addq	$25,	$17,	$25
+	mulq	$8,	$1,	$28
+	cmpult	$24,	$18,	$4
+	addq	$24,	$7,	$24
+	addq	$25,	$4,	$25
+	umulh	$0,	$22,	$21
+	cmpult	$24,	$7,	$20
+	addq	$24,	$23,	$24
+	addq	$25,	$20,	$25
+	umulh	$2,	$6,	$19
+	cmpult	$24,	$23,	$17
+	addq	$24,	$28,	$24
+	addq	$25,	$17,	$25
+	umulh	$5,	$3,	$18
+	cmpult	$24,	$28,	$4
+	addq	$25,	$4,	$25
+	stq	$24,	24($16)
+	addq	$25,	$27,	$24
+	bis	$31,	$31,	$25
+	addq	$24,	$21,	$24
+	bis	$31,	$31,	$27
+	umulh	$8,	$1,	$7
+	cmpult	$24,	$21,	$20
+	addq	$24,	$19,	$24
+	addq	$25,	$20,	$25
+	mulq	$2,	$22,	$23
+	cmpult	$24,	$19,	$17
+	addq	$24,	$18,	$24
+	addq	$25,	$17,	$25
+	mulq	$5,	$6,	$28
+	cmpult	$24,	$18,	$4
+	addq	$24,	$7,	$24
+	addq	$25,	$4,	$25
+	mulq	$8,	$3,	$21
+	cmpult	$24,	$7,	$20
+	addq	$24,	$23,	$24
+	addq	$25,	$20,	$25
+	umulh	$2,	$22,	$19
+	cmpult	$24,	$23,	$17
+	addq	$24,	$28,	$24
+	addq	$25,	$17,	$25
+	umulh	$5,	$6,	$18
+	cmpult	$24,	$28,	$4
+	addq	$24,	$21,	$24
+	addq	$25,	$4,	$25
+	umulh	$8,	$3,	$7
+	cmpult	$24,	$21,	$20
+	addq	$25,	$20,	$25
+	stq	$24,	32($16)
+	addq	$25,	$27,	$24
+	bis	$31,	$31,	$25
+	addq	$24,	$19,	$24
+	bis	$31,	$31,	$27
+	mulq	$5,	$22,	$23
+	cmpult	$24,	$19,	$17
+	addq	$24,	$18,	$24
+	addq	$25,	$17,	$25
+	mulq	$8,	$6,	$28
+	cmpult	$24,	$18,	$4
+	addq	$24,	$7,	$24
+	addq	$25,	$4,	$25
+	umulh	$5,	$22,	$21
+	cmpult	$24,	$7,	$20
+	addq	$24,	$23,	$24
+	addq	$25,	$20,	$25
+	umulh	$8,	$6,	$19
+	cmpult	$24,	$23,	$17
+	addq	$24,	$28,	$24
+	addq	$25,	$17,	$25
+	mulq	$8,	$22,	$18
+	cmpult	$24,	$28,	$4
+	addq	$25,	$4,	$25
+	stq	$24,	40($16)
+	addq	$25,	$27,	$24
+	bis	$31,	$31,	$25
+	addq	$24,	$21,	$24
+	bis	$31,	$31,	$27
+	umulh	$8,	$22,	$7
+	cmpult	$24,	$21,	$20
+	addq	$24,	$19,	$24
+	addq	$25,	$20,	$25
+	cmpult	$24,	$19,	$23
+	addq	$24,	$18,	$24
+	addq	$25,	$23,	$25
+	cmpult	$24,	$18,	$17
+	addq	$25,	$17,	$25
+	stq	$24,	48($16)
+	addq	$25,	$27,	$24
+	addq	$24,	$7,	$24
+	stq	$24,	56($16)
+	ret	$31,($26),1
+	.end bn_mul_comba4
+	.text
+	.align 3
+	.globl bn_sqr_comba4
+	.ent bn_sqr_comba4
+bn_sqr_comba4:
+bn_sqr_comba4..ng:
+	.frame $30,0,$26,0
+	.prologue 0
+
+	ldq	$0,	0($17)
+	ldq	$1,	8($17)
+	ldq	$2,	16($17)
+	ldq	$3,	24($17)
+	bis	$31,	$31,	$6
+	mulq	$0,	$0,	$4
+	umulh	$0,	$0,	$5
+	stq	$4,	0($16)
+	bis	$31,	$31,	$4
+	mulq	$0,	$1,	$7
+	umulh	$0,	$1,	$8
+	cmplt	$7,	$31,	$22
+	cmplt	$8,	$31,	$23
+	addq	$7,	$7,	$7
+	addq	$8,	$8,	$8
+	addq	$8,	$22,	$8
+	addq	$4,	$23,	$4
+	addq	$5,	$7,	$5
+	addq	$6,	$8,	$6
+	cmpult	$5,	$7,	$24
+	cmpult	$6,	$8,	$25
+	addq	$6,	$24,	$6
+	addq	$4,	$25,	$4
+	stq	$5,	8($16)
+	bis	$31,	$31,	$5
+	mulq	$1,	$1,	$27
+	umulh	$1,	$1,	$28
+	addq	$6,	$27,	$6
+	addq	$4,	$28,	$4
+	cmpult	$6,	$27,	$21
+	cmpult	$4,	$28,	$20
+	addq	$4,	$21,	$4
+	addq	$5,	$20,	$5
+	mulq	$2,	$0,	$19
+	umulh	$2,	$0,	$18
+	cmplt	$19,	$31,	$17
+	cmplt	$18,	$31,	$22
+	addq	$19,	$19,	$19
+	addq	$18,	$18,	$18
+	addq	$18,	$17,	$18
+	addq	$5,	$22,	$5
+	addq	$6,	$19,	$6
+	addq	$4,	$18,	$4
+	cmpult	$6,	$19,	$23
+	cmpult	$4,	$18,	$7
+	addq	$4,	$23,	$4
+	addq	$5,	$7,	$5
+	stq	$6,	16($16)
+	bis	$31,	$31,	$6
+	mulq	$3,	$0,	$8
+	umulh	$3,	$0,	$24
+	cmplt	$8,	$31,	$25
+	cmplt	$24,	$31,	$27
+	addq	$8,	$8,	$8
+	addq	$24,	$24,	$24
+	addq	$24,	$25,	$24
+	addq	$6,	$27,	$6
+	addq	$4,	$8,	$4
+	addq	$5,	$24,	$5
+	cmpult	$4,	$8,	$28
+	cmpult	$5,	$24,	$21
+	addq	$5,	$28,	$5
+	addq	$6,	$21,	$6
+	mulq	$2,	$1,	$20
+	umulh	$2,	$1,	$17
+	cmplt	$20,	$31,	$22
+	cmplt	$17,	$31,	$19
+	addq	$20,	$20,	$20
+	addq	$17,	$17,	$17
+	addq	$17,	$22,	$17
+	addq	$6,	$19,	$6
+	addq	$4,	$20,	$4
+	addq	$5,	$17,	$5
+	cmpult	$4,	$20,	$18
+	cmpult	$5,	$17,	$23
+	addq	$5,	$18,	$5
+	addq	$6,	$23,	$6
+	stq	$4,	24($16)
+	bis	$31,	$31,	$4
+	mulq	$2,	$2,	$7
+	umulh	$2,	$2,	$25
+	addq	$5,	$7,	$5
+	addq	$6,	$25,	$6
+	cmpult	$5,	$7,	$27
+	cmpult	$6,	$25,	$8
+	addq	$6,	$27,	$6
+	addq	$4,	$8,	$4
+	mulq	$3,	$1,	$24
+	umulh	$3,	$1,	$28
+	cmplt	$24,	$31,	$21
+	cmplt	$28,	$31,	$22
+	addq	$24,	$24,	$24
+	addq	$28,	$28,	$28
+	addq	$28,	$21,	$28
+	addq	$4,	$22,	$4
+	addq	$5,	$24,	$5
+	addq	$6,	$28,	$6
+	cmpult	$5,	$24,	$19
+	cmpult	$6,	$28,	$20
+	addq	$6,	$19,	$6
+	addq	$4,	$20,	$4
+	stq	$5,	32($16)
+	bis	$31,	$31,	$5
+	mulq	$3,	$2,	$17
+	umulh	$3,	$2,	$18
+	cmplt	$17,	$31,	$23
+	cmplt	$18,	$31,	$7
+	addq	$17,	$17,	$17
+	addq	$18,	$18,	$18
+	addq	$18,	$23,	$18
+	addq	$5,	$7,	$5
+	addq	$6,	$17,	$6
+	addq	$4,	$18,	$4
+	cmpult	$6,	$17,	$25
+	cmpult	$4,	$18,	$27
+	addq	$4,	$25,	$4
+	addq	$5,	$27,	$5
+	stq	$6,	40($16)
+	bis	$31,	$31,	$6
+	mulq	$3,	$3,	$8
+	umulh	$3,	$3,	$21
+	addq	$4,	$8,	$4
+	addq	$5,	$21,	$5
+	cmpult	$4,	$8,	$22
+	cmpult	$5,	$21,	$24
+	addq	$5,	$22,	$5
+	addq	$6,	$24,	$6
+	stq	$4,	48($16)
+	stq	$5,	56($16)
+	ret	$31,($26),1
+	.end bn_sqr_comba4
+	.text
+	.align 3
+	.globl bn_sqr_comba8
+	.ent bn_sqr_comba8
+bn_sqr_comba8:
+bn_sqr_comba8..ng:
+	.frame $30,0,$26,0
+	.prologue 0
+
+	ldq	$0,	0($17)
+	ldq	$1,	8($17)
+	ldq	$2,	16($17)
+	ldq	$3,	24($17)
+	ldq	$4,	32($17)
+	ldq	$5,	40($17)
+	ldq	$6,	48($17)
+	ldq	$7,	56($17)
+	bis	$31,	$31,	$23
+	mulq	$0,	$0,	$8
+	umulh	$0,	$0,	$22
+	stq	$8,	0($16)
+	bis	$31,	$31,	$8
+	mulq	$1,	$0,	$24
+	umulh	$1,	$0,	$25
+	cmplt	$24,	$31,	$27
+	cmplt	$25,	$31,	$28
+	addq	$24,	$24,	$24
+	addq	$25,	$25,	$25
+	addq	$25,	$27,	$25
+	addq	$8,	$28,	$8
+	addq	$22,	$24,	$22
+	addq	$23,	$25,	$23
+	cmpult	$22,	$24,	$21
+	cmpult	$23,	$25,	$20
+	addq	$23,	$21,	$23
+	addq	$8,	$20,	$8
+	stq	$22,	8($16)
+	bis	$31,	$31,	$22
+	mulq	$1,	$1,	$19
+	umulh	$1,	$1,	$18
+	addq	$23,	$19,	$23
+	addq	$8,	$18,	$8
+	cmpult	$23,	$19,	$17
+	cmpult	$8,	$18,	$27
+	addq	$8,	$17,	$8
+	addq	$22,	$27,	$22
+	mulq	$2,	$0,	$28
+	umulh	$2,	$0,	$24
+	cmplt	$28,	$31,	$25
+	cmplt	$24,	$31,	$21
+	addq	$28,	$28,	$28
+	addq	$24,	$24,	$24
+	addq	$24,	$25,	$24
+	addq	$22,	$21,	$22
+	addq	$23,	$28,	$23
+	addq	$8,	$24,	$8
+	cmpult	$23,	$28,	$20
+	cmpult	$8,	$24,	$19
+	addq	$8,	$20,	$8
+	addq	$22,	$19,	$22
+	stq	$23,	16($16)
+	bis	$31,	$31,	$23
+	mulq	$2,	$1,	$18
+	umulh	$2,	$1,	$17
+	cmplt	$18,	$31,	$27
+	cmplt	$17,	$31,	$25
+	addq	$18,	$18,	$18
+	addq	$17,	$17,	$17
+	addq	$17,	$27,	$17
+	addq	$23,	$25,	$23
+	addq	$8,	$18,	$8
+	addq	$22,	$17,	$22
+	cmpult	$8,	$18,	$21
+	cmpult	$22,	$17,	$28
+	addq	$22,	$21,	$22
+	addq	$23,	$28,	$23
+	mulq	$3,	$0,	$24
+	umulh	$3,	$0,	$20
+	cmplt	$24,	$31,	$19
+	cmplt	$20,	$31,	$27
+	addq	$24,	$24,	$24
+	addq	$20,	$20,	$20
+	addq	$20,	$19,	$20
+	addq	$23,	$27,	$23
+	addq	$8,	$24,	$8
+	addq	$22,	$20,	$22
+	cmpult	$8,	$24,	$25
+	cmpult	$22,	$20,	$18
+	addq	$22,	$25,	$22
+	addq	$23,	$18,	$23
+	stq	$8,	24($16)
+	bis	$31,	$31,	$8
+	mulq	$2,	$2,	$17
+	umulh	$2,	$2,	$21
+	addq	$22,	$17,	$22
+	addq	$23,	$21,	$23
+	cmpult	$22,	$17,	$28
+	cmpult	$23,	$21,	$19
+	addq	$23,	$28,	$23
+	addq	$8,	$19,	$8
+	mulq	$3,	$1,	$27
+	umulh	$3,	$1,	$24
+	cmplt	$27,	$31,	$20
+	cmplt	$24,	$31,	$25
+	addq	$27,	$27,	$27
+	addq	$24,	$24,	$24
+	addq	$24,	$20,	$24
+	addq	$8,	$25,	$8
+	addq	$22,	$27,	$22
+	addq	$23,	$24,	$23
+	cmpult	$22,	$27,	$18
+	cmpult	$23,	$24,	$17
+	addq	$23,	$18,	$23
+	addq	$8,	$17,	$8
+	mulq	$4,	$0,	$21
+	umulh	$4,	$0,	$28
+	cmplt	$21,	$31,	$19
+	cmplt	$28,	$31,	$20
+	addq	$21,	$21,	$21
+	addq	$28,	$28,	$28
+	addq	$28,	$19,	$28
+	addq	$8,	$20,	$8
+	addq	$22,	$21,	$22
+	addq	$23,	$28,	$23
+	cmpult	$22,	$21,	$25
+	cmpult	$23,	$28,	$27
+	addq	$23,	$25,	$23
+	addq	$8,	$27,	$8
+	stq	$22,	32($16)
+	bis	$31,	$31,	$22
+	mulq	$3,	$2,	$24
+	umulh	$3,	$2,	$18
+	cmplt	$24,	$31,	$17
+	cmplt	$18,	$31,	$19
+	addq	$24,	$24,	$24
+	addq	$18,	$18,	$18
+	addq	$18,	$17,	$18
+	addq	$22,	$19,	$22
+	addq	$23,	$24,	$23
+	addq	$8,	$18,	$8
+	cmpult	$23,	$24,	$20
+	cmpult	$8,	$18,	$21
+	addq	$8,	$20,	$8
+	addq	$22,	$21,	$22
+	mulq	$4,	$1,	$28
+	umulh	$4,	$1,	$25
+	cmplt	$28,	$31,	$27
+	cmplt	$25,	$31,	$17
+	addq	$28,	$28,	$28
+	addq	$25,	$25,	$25
+	addq	$25,	$27,	$25
+	addq	$22,	$17,	$22
+	addq	$23,	$28,	$23
+	addq	$8,	$25,	$8
+	cmpult	$23,	$28,	$19
+	cmpult	$8,	$25,	$24
+	addq	$8,	$19,	$8
+	addq	$22,	$24,	$22
+	mulq	$5,	$0,	$18
+	umulh	$5,	$0,	$20
+	cmplt	$18,	$31,	$21
+	cmplt	$20,	$31,	$27
+	addq	$18,	$18,	$18
+	addq	$20,	$20,	$20
+	addq	$20,	$21,	$20
+	addq	$22,	$27,	$22
+	addq	$23,	$18,	$23
+	addq	$8,	$20,	$8
+	cmpult	$23,	$18,	$17
+	cmpult	$8,	$20,	$28
+	addq	$8,	$17,	$8
+	addq	$22,	$28,	$22
+	stq	$23,	40($16)
+	bis	$31,	$31,	$23
+	mulq	$3,	$3,	$25
+	umulh	$3,	$3,	$19
+	addq	$8,	$25,	$8
+	addq	$22,	$19,	$22
+	cmpult	$8,	$25,	$24
+	cmpult	$22,	$19,	$21
+	addq	$22,	$24,	$22
+	addq	$23,	$21,	$23
+	mulq	$4,	$2,	$27
+	umulh	$4,	$2,	$18
+	cmplt	$27,	$31,	$20
+	cmplt	$18,	$31,	$17
+	addq	$27,	$27,	$27
+	addq	$18,	$18,	$18
+	addq	$18,	$20,	$18
+	addq	$23,	$17,	$23
+	addq	$8,	$27,	$8
+	addq	$22,	$18,	$22
+	cmpult	$8,	$27,	$28
+	cmpult	$22,	$18,	$25
+	addq	$22,	$28,	$22
+	addq	$23,	$25,	$23
+	mulq	$5,	$1,	$19
+	umulh	$5,	$1,	$24
+	cmplt	$19,	$31,	$21
+	cmplt	$24,	$31,	$20
+	addq	$19,	$19,	$19
+	addq	$24,	$24,	$24
+	addq	$24,	$21,	$24
+	addq	$23,	$20,	$23
+	addq	$8,	$19,	$8
+	addq	$22,	$24,	$22
+	cmpult	$8,	$19,	$17
+	cmpult	$22,	$24,	$27
+	addq	$22,	$17,	$22
+	addq	$23,	$27,	$23
+	mulq	$6,	$0,	$18
+	umulh	$6,	$0,	$28
+	cmplt	$18,	$31,	$25
+	cmplt	$28,	$31,	$21
+	addq	$18,	$18,	$18
+	addq	$28,	$28,	$28
+	addq	$28,	$25,	$28
+	addq	$23,	$21,	$23
+	addq	$8,	$18,	$8
+	addq	$22,	$28,	$22
+	cmpult	$8,	$18,	$20
+	cmpult	$22,	$28,	$19
+	addq	$22,	$20,	$22
+	addq	$23,	$19,	$23
+	stq	$8,	48($16)
+	bis	$31,	$31,	$8
+	mulq	$4,	$3,	$24
+	umulh	$4,	$3,	$17
+	cmplt	$24,	$31,	$27
+	cmplt	$17,	$31,	$25
+	addq	$24,	$24,	$24
+	addq	$17,	$17,	$17
+	addq	$17,	$27,	$17
+	addq	$8,	$25,	$8
+	addq	$22,	$24,	$22
+	addq	$23,	$17,	$23
+	cmpult	$22,	$24,	$21
+	cmpult	$23,	$17,	$18
+	addq	$23,	$21,	$23
+	addq	$8,	$18,	$8
+	mulq	$5,	$2,	$28
+	umulh	$5,	$2,	$20
+	cmplt	$28,	$31,	$19
+	cmplt	$20,	$31,	$27
+	addq	$28,	$28,	$28
+	addq	$20,	$20,	$20
+	addq	$20,	$19,	$20
+	addq	$8,	$27,	$8
+	addq	$22,	$28,	$22
+	addq	$23,	$20,	$23
+	cmpult	$22,	$28,	$25
+	cmpult	$23,	$20,	$24
+	addq	$23,	$25,	$23
+	addq	$8,	$24,	$8
+	mulq	$6,	$1,	$17
+	umulh	$6,	$1,	$21
+	cmplt	$17,	$31,	$18
+	cmplt	$21,	$31,	$19
+	addq	$17,	$17,	$17
+	addq	$21,	$21,	$21
+	addq	$21,	$18,	$21
+	addq	$8,	$19,	$8
+	addq	$22,	$17,	$22
+	addq	$23,	$21,	$23
+	cmpult	$22,	$17,	$27
+	cmpult	$23,	$21,	$28
+	addq	$23,	$27,	$23
+	addq	$8,	$28,	$8
+	mulq	$7,	$0,	$20
+	umulh	$7,	$0,	$25
+	cmplt	$20,	$31,	$24
+	cmplt	$25,	$31,	$18
+	addq	$20,	$20,	$20
+	addq	$25,	$25,	$25
+	addq	$25,	$24,	$25
+	addq	$8,	$18,	$8
+	addq	$22,	$20,	$22
+	addq	$23,	$25,	$23
+	cmpult	$22,	$20,	$19
+	cmpult	$23,	$25,	$17
+	addq	$23,	$19,	$23
+	addq	$8,	$17,	$8
+	stq	$22,	56($16)
+	bis	$31,	$31,	$22
+	mulq	$4,	$4,	$21
+	umulh	$4,	$4,	$27
+	addq	$23,	$21,	$23
+	addq	$8,	$27,	$8
+	cmpult	$23,	$21,	$28
+	cmpult	$8,	$27,	$24
+	addq	$8,	$28,	$8
+	addq	$22,	$24,	$22
+	mulq	$5,	$3,	$18
+	umulh	$5,	$3,	$20
+	cmplt	$18,	$31,	$25
+	cmplt	$20,	$31,	$19
+	addq	$18,	$18,	$18
+	addq	$20,	$20,	$20
+	addq	$20,	$25,	$20
+	addq	$22,	$19,	$22
+	addq	$23,	$18,	$23
+	addq	$8,	$20,	$8
+	cmpult	$23,	$18,	$17
+	cmpult	$8,	$20,	$21
+	addq	$8,	$17,	$8
+	addq	$22,	$21,	$22
+	mulq	$6,	$2,	$27
+	umulh	$6,	$2,	$28
+	cmplt	$27,	$31,	$24
+	cmplt	$28,	$31,	$25
+	addq	$27,	$27,	$27
+	addq	$28,	$28,	$28
+	addq	$28,	$24,	$28
+	addq	$22,	$25,	$22
+	addq	$23,	$27,	$23
+	addq	$8,	$28,	$8
+	cmpult	$23,	$27,	$19
+	cmpult	$8,	$28,	$18
+	addq	$8,	$19,	$8
+	addq	$22,	$18,	$22
+	mulq	$7,	$1,	$20
+	umulh	$7,	$1,	$17
+	cmplt	$20,	$31,	$21
+	cmplt	$17,	$31,	$24
+	addq	$20,	$20,	$20
+	addq	$17,	$17,	$17
+	addq	$17,	$21,	$17
+	addq	$22,	$24,	$22
+	addq	$23,	$20,	$23
+	addq	$8,	$17,	$8
+	cmpult	$23,	$20,	$25
+	cmpult	$8,	$17,	$27
+	addq	$8,	$25,	$8
+	addq	$22,	$27,	$22
+	stq	$23,	64($16)
+	bis	$31,	$31,	$23
+	mulq	$5,	$4,	$28
+	umulh	$5,	$4,	$19
+	cmplt	$28,	$31,	$18
+	cmplt	$19,	$31,	$21
+	addq	$28,	$28,	$28
+	addq	$19,	$19,	$19
+	addq	$19,	$18,	$19
+	addq	$23,	$21,	$23
+	addq	$8,	$28,	$8
+	addq	$22,	$19,	$22
+	cmpult	$8,	$28,	$24
+	cmpult	$22,	$19,	$20
+	addq	$22,	$24,	$22
+	addq	$23,	$20,	$23
+	mulq	$6,	$3,	$17
+	umulh	$6,	$3,	$25
+	cmplt	$17,	$31,	$27
+	cmplt	$25,	$31,	$18
+	addq	$17,	$17,	$17
+	addq	$25,	$25,	$25
+	addq	$25,	$27,	$25
+	addq	$23,	$18,	$23
+	addq	$8,	$17,	$8
+	addq	$22,	$25,	$22
+	cmpult	$8,	$17,	$21
+	cmpult	$22,	$25,	$28
+	addq	$22,	$21,	$22
+	addq	$23,	$28,	$23
+	mulq	$7,	$2,	$19
+	umulh	$7,	$2,	$24
+	cmplt	$19,	$31,	$20
+	cmplt	$24,	$31,	$27
+	addq	$19,	$19,	$19
+	addq	$24,	$24,	$24
+	addq	$24,	$20,	$24
+	addq	$23,	$27,	$23
+	addq	$8,	$19,	$8
+	addq	$22,	$24,	$22
+	cmpult	$8,	$19,	$18
+	cmpult	$22,	$24,	$17
+	addq	$22,	$18,	$22
+	addq	$23,	$17,	$23
+	stq	$8,	72($16)
+	bis	$31,	$31,	$8
+	mulq	$5,	$5,	$25
+	umulh	$5,	$5,	$21
+	addq	$22,	$25,	$22
+	addq	$23,	$21,	$23
+	cmpult	$22,	$25,	$28
+	cmpult	$23,	$21,	$20
+	addq	$23,	$28,	$23
+	addq	$8,	$20,	$8
+	mulq	$6,	$4,	$27
+	umulh	$6,	$4,	$19
+	cmplt	$27,	$31,	$24
+	cmplt	$19,	$31,	$18
+	addq	$27,	$27,	$27
+	addq	$19,	$19,	$19
+	addq	$19,	$24,	$19
+	addq	$8,	$18,	$8
+	addq	$22,	$27,	$22
+	addq	$23,	$19,	$23
+	cmpult	$22,	$27,	$17
+	cmpult	$23,	$19,	$25
+	addq	$23,	$17,	$23
+	addq	$8,	$25,	$8
+	mulq	$7,	$3,	$21
+	umulh	$7,	$3,	$28
+	cmplt	$21,	$31,	$20
+	cmplt	$28,	$31,	$24
+	addq	$21,	$21,	$21
+	addq	$28,	$28,	$28
+	addq	$28,	$20,	$28
+	addq	$8,	$24,	$8
+	addq	$22,	$21,	$22
+	addq	$23,	$28,	$23
+	cmpult	$22,	$21,	$18
+	cmpult	$23,	$28,	$27
+	addq	$23,	$18,	$23
+	addq	$8,	$27,	$8
+	stq	$22,	80($16)
+	bis	$31,	$31,	$22
+	mulq	$6,	$5,	$19
+	umulh	$6,	$5,	$17
+	cmplt	$19,	$31,	$25
+	cmplt	$17,	$31,	$20
+	addq	$19,	$19,	$19
+	addq	$17,	$17,	$17
+	addq	$17,	$25,	$17
+	addq	$22,	$20,	$22
+	addq	$23,	$19,	$23
+	addq	$8,	$17,	$8
+	cmpult	$23,	$19,	$24
+	cmpult	$8,	$17,	$21
+	addq	$8,	$24,	$8
+	addq	$22,	$21,	$22
+	mulq	$7,	$4,	$28
+	umulh	$7,	$4,	$18
+	cmplt	$28,	$31,	$27
+	cmplt	$18,	$31,	$25
+	addq	$28,	$28,	$28
+	addq	$18,	$18,	$18
+	addq	$18,	$27,	$18
+	addq	$22,	$25,	$22
+	addq	$23,	$28,	$23
+	addq	$8,	$18,	$8
+	cmpult	$23,	$28,	$20
+	cmpult	$8,	$18,	$19
+	addq	$8,	$20,	$8
+	addq	$22,	$19,	$22
+	stq	$23,	88($16)
+	bis	$31,	$31,	$23
+	mulq	$6,	$6,	$17
+	umulh	$6,	$6,	$24
+	addq	$8,	$17,	$8
+	addq	$22,	$24,	$22
+	cmpult	$8,	$17,	$21
+	cmpult	$22,	$24,	$27
+	addq	$22,	$21,	$22
+	addq	$23,	$27,	$23
+	mulq	$7,	$5,	$25
+	umulh	$7,	$5,	$28
+	cmplt	$25,	$31,	$18
+	cmplt	$28,	$31,	$20
+	addq	$25,	$25,	$25
+	addq	$28,	$28,	$28
+	addq	$28,	$18,	$28
+	addq	$23,	$20,	$23
+	addq	$8,	$25,	$8
+	addq	$22,	$28,	$22
+	cmpult	$8,	$25,	$19
+	cmpult	$22,	$28,	$17
+	addq	$22,	$19,	$22
+	addq	$23,	$17,	$23
+	stq	$8,	96($16)
+	bis	$31,	$31,	$8
+	mulq	$7,	$6,	$24
+	umulh	$7,	$6,	$21
+	cmplt	$24,	$31,	$27
+	cmplt	$21,	$31,	$18
+	addq	$24,	$24,	$24
+	addq	$21,	$21,	$21
+	addq	$21,	$27,	$21
+	addq	$8,	$18,	$8
+	addq	$22,	$24,	$22
+	addq	$23,	$21,	$23
+	cmpult	$22,	$24,	$20
+	cmpult	$23,	$21,	$25
+	addq	$23,	$20,	$23
+	addq	$8,	$25,	$8
+	stq	$22,	104($16)
+	bis	$31,	$31,	$22
+	mulq	$7,	$7,	$28
+	umulh	$7,	$7,	$19
+	addq	$23,	$28,	$23
+	addq	$8,	$19,	$8
+	cmpult	$23,	$28,	$17
+	cmpult	$8,	$19,	$27
+	addq	$8,	$17,	$8
+	addq	$22,	$27,	$22
+	stq	$23,	112($16)
+	stq	$8,	120($16)
+	ret	$31,($26),1
+	.end bn_sqr_comba8
diff --git a/crypto/bn/asm/ff b/crypto/bn/asm/ff
new file mode 100644
index 0000000..4af2168
--- /dev/null
+++ b/crypto/bn/asm/ff
@@ -0,0 +1,724 @@
+	.text
+	.align 3
+	.globl bn_mul_comba4
+	.ent bn_mul_comba4
+bn_mul_comba4:
+bn_mul_comba4..ng:
+	.frame $30,0,$26,0
+	.prologue 0
+
+	ldq	$0,	0($17)
+	ldq	$1,	0($18)
+	ldq	$2,	8($17)
+	ldq	$3,	8($18)
+	ldq	$4,	16($17)
+	ldq	$5,	16($18)
+	ldq	$6,	24($17)
+	ldq	$7,	24($18)
+	bis	$31,	$31,	$23
+	mulq	$0,	$1,	$8
+	umulh	$0,	$1,	$22
+	stq	$8,	0($16)
+	bis	$31,	$31,	$8
+	mulq	$0,	$3,	$24
+	umulh	$0,	$3,	$25
+	addq	$22,	$24,	$22
+	cmpult	$22,	$24,	$27
+	addq	$27,	$25,	$25
+	addq	$23,	$25,	$23
+	cmpult	$23,	$25,	$28
+	addq	$8,	$28,	$8
+	mulq	$2,	$1,	$21
+	umulh	$2,	$1,	$20
+	addq	$22,	$21,	$22
+	cmpult	$22,	$21,	$19
+	addq	$19,	$20,	$20
+	addq	$23,	$20,	$23
+	cmpult	$23,	$20,	$17
+	addq	$8,	$17,	$8
+	stq	$22,	8($16)
+	bis	$31,	$31,	$22
+	mulq	$2,	$3,	$18
+	umulh	$2,	$3,	$24
+	addq	$23,	$18,	$23
+	cmpult	$23,	$18,	$27
+	addq	$27,	$24,	$24
+	addq	$8,	$24,	$8
+	cmpult	$8,	$24,	$25
+	addq	$22,	$25,	$22
+	mulq	$0,	$5,	$28
+	umulh	$0,	$5,	$21
+	addq	$23,	$28,	$23
+	cmpult	$23,	$28,	$19
+	addq	$19,	$21,	$21
+	addq	$8,	$21,	$8
+	cmpult	$8,	$21,	$20
+	addq	$22,	$20,	$22
+	mulq	$4,	$1,	$17
+	umulh	$4,	$1,	$18
+	addq	$23,	$17,	$23
+	cmpult	$23,	$17,	$27
+	addq	$27,	$18,	$18
+	addq	$8,	$18,	$8
+	cmpult	$8,	$18,	$24
+	addq	$22,	$24,	$22
+	stq	$23,	16($16)
+	bis	$31,	$31,	$23
+	mulq	$0,	$7,	$25
+	umulh	$0,	$7,	$28
+	addq	$8,	$25,	$8
+	cmpult	$8,	$25,	$19
+	addq	$19,	$28,	$28
+	addq	$22,	$28,	$22
+	cmpult	$22,	$28,	$21
+	addq	$23,	$21,	$23
+	mulq	$2,	$5,	$20
+	umulh	$2,	$5,	$17
+	addq	$8,	$20,	$8
+	cmpult	$8,	$20,	$27
+	addq	$27,	$17,	$17
+	addq	$22,	$17,	$22
+	cmpult	$22,	$17,	$18
+	addq	$23,	$18,	$23
+	mulq	$4,	$3,	$24
+	umulh	$4,	$3,	$25
+	addq	$8,	$24,	$8
+	cmpult	$8,	$24,	$19
+	addq	$19,	$25,	$25
+	addq	$22,	$25,	$22
+	cmpult	$22,	$25,	$28
+	addq	$23,	$28,	$23
+	mulq	$6,	$1,	$21
+	umulh	$6,	$1,	$0
+	addq	$8,	$21,	$8
+	cmpult	$8,	$21,	$20
+	addq	$20,	$0,	$0
+	addq	$22,	$0,	$22
+	cmpult	$22,	$0,	$27
+	addq	$23,	$27,	$23
+	stq	$8,	24($16)
+	bis	$31,	$31,	$8
+	mulq	$2,	$7,	$17
+	umulh	$2,	$7,	$18
+	addq	$22,	$17,	$22
+	cmpult	$22,	$17,	$24
+	addq	$24,	$18,	$18
+	addq	$23,	$18,	$23
+	cmpult	$23,	$18,	$19
+	addq	$8,	$19,	$8
+	mulq	$4,	$5,	$25
+	umulh	$4,	$5,	$28
+	addq	$22,	$25,	$22
+	cmpult	$22,	$25,	$21
+	addq	$21,	$28,	$28
+	addq	$23,	$28,	$23
+	cmpult	$23,	$28,	$20
+	addq	$8,	$20,	$8
+	mulq	$6,	$3,	$0
+	umulh	$6,	$3,	$27
+	addq	$22,	$0,	$22
+	cmpult	$22,	$0,	$1
+	addq	$1,	$27,	$27
+	addq	$23,	$27,	$23
+	cmpult	$23,	$27,	$17
+	addq	$8,	$17,	$8
+	stq	$22,	32($16)
+	bis	$31,	$31,	$22
+	mulq	$4,	$7,	$24
+	umulh	$4,	$7,	$18
+	addq	$23,	$24,	$23
+	cmpult	$23,	$24,	$19
+	addq	$19,	$18,	$18
+	addq	$8,	$18,	$8
+	cmpult	$8,	$18,	$2
+	addq	$22,	$2,	$22
+	mulq	$6,	$5,	$25
+	umulh	$6,	$5,	$21
+	addq	$23,	$25,	$23
+	cmpult	$23,	$25,	$28
+	addq	$28,	$21,	$21
+	addq	$8,	$21,	$8
+	cmpult	$8,	$21,	$20
+	addq	$22,	$20,	$22
+	stq	$23,	40($16)
+	bis	$31,	$31,	$23
+	mulq	$6,	$7,	$0
+	umulh	$6,	$7,	$1
+	addq	$8,	$0,	$8
+	cmpult	$8,	$0,	$27
+	addq	$27,	$1,	$1
+	addq	$22,	$1,	$22
+	cmpult	$22,	$1,	$17
+	addq	$23,	$17,	$23
+	stq	$8,	48($16)
+	stq	$22,	56($16)
+	ret	$31,($26),1
+	.end bn_mul_comba4
+	.text
+	.align 3
+	.globl bn_mul_comba8
+	.ent bn_mul_comba8
+bn_mul_comba8:
+bn_mul_comba8..ng:
+	.frame $30,0,$26,0
+	.prologue 0
+
+	stq	$9,	8($30)
+	stq	$10,	16($30)
+	ldq	$0,	0($17)
+	ldq	$1,	0($18)
+	ldq	$2,	8($17)
+	ldq	$3,	8($18)
+	ldq	$4,	16($17)
+	ldq	$5,	16($18)
+	ldq	$6,	24($17)
+	ldq	$7,	24($18)
+	ldq	$8,	8($17)
+	ldq	$22,	8($18)
+	ldq	$23,	8($17)
+	ldq	$24,	8($18)
+	ldq	$25,	8($17)
+	ldq	$27,	8($18)
+	ldq	$28,	8($17)
+	ldq	$21,	8($18)
+	bis	$31,	$31,	$9
+	mulq	$0,	$1,	$20
+	umulh	$0,	$1,	$19
+	stq	$20,	0($16)
+	bis	$31,	$31,	$20
+	mulq	$0,	$3,	$10
+	umulh	$0,	$3,	$17
+	addq	$19,	$10,	$19
+	cmpult	$19,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$10
+	addq	$20,	$10,	$20
+	mulq	$2,	$1,	$18
+	umulh	$2,	$1,	$17
+	addq	$19,	$18,	$19
+	cmpult	$19,	$18,	$10
+	addq	$10,	$17,	$17
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$18
+	addq	$20,	$18,	$20
+	stq	$19,	8($16)
+	bis	$31,	$31,	$19
+	mulq	$0,	$5,	$10
+	umulh	$0,	$5,	$17
+	addq	$9,	$10,	$9
+	cmpult	$9,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$20,	$17,	$20
+	cmpult	$20,	$17,	$10
+	addq	$19,	$10,	$19
+	mulq	$2,	$3,	$18
+	umulh	$2,	$3,	$17
+	addq	$9,	$18,	$9
+	cmpult	$9,	$18,	$10
+	addq	$10,	$17,	$17
+	addq	$20,	$17,	$20
+	cmpult	$20,	$17,	$18
+	addq	$19,	$18,	$19
+	mulq	$4,	$1,	$10
+	umulh	$4,	$1,	$17
+	addq	$9,	$10,	$9
+	cmpult	$9,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$20,	$17,	$20
+	cmpult	$20,	$17,	$10
+	addq	$19,	$10,	$19
+	stq	$9,	16($16)
+	bis	$31,	$31,	$9
+	mulq	$0,	$7,	$18
+	umulh	$0,	$7,	$17
+	addq	$20,	$18,	$20
+	cmpult	$20,	$18,	$10
+	addq	$10,	$17,	$17
+	addq	$19,	$17,	$19
+	cmpult	$19,	$17,	$18
+	addq	$9,	$18,	$9
+	mulq	$2,	$5,	$10
+	umulh	$2,	$5,	$17
+	addq	$20,	$10,	$20
+	cmpult	$20,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$19,	$17,	$19
+	cmpult	$19,	$17,	$10
+	addq	$9,	$10,	$9
+	mulq	$4,	$3,	$18
+	umulh	$4,	$3,	$17
+	addq	$20,	$18,	$20
+	cmpult	$20,	$18,	$10
+	addq	$10,	$17,	$17
+	addq	$19,	$17,	$19
+	cmpult	$19,	$17,	$18
+	addq	$9,	$18,	$9
+	mulq	$6,	$1,	$10
+	umulh	$6,	$1,	$17
+	addq	$20,	$10,	$20
+	cmpult	$20,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$19,	$17,	$19
+	cmpult	$19,	$17,	$10
+	addq	$9,	$10,	$9
+	stq	$20,	24($16)
+	bis	$31,	$31,	$20
+	mulq	$0,	$22,	$18
+	umulh	$0,	$22,	$17
+	addq	$19,	$18,	$19
+	cmpult	$19,	$18,	$10
+	addq	$10,	$17,	$17
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$18
+	addq	$20,	$18,	$20
+	mulq	$2,	$7,	$10
+	umulh	$2,	$7,	$17
+	addq	$19,	$10,	$19
+	cmpult	$19,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$10
+	addq	$20,	$10,	$20
+	mulq	$4,	$5,	$18
+	umulh	$4,	$5,	$17
+	addq	$19,	$18,	$19
+	cmpult	$19,	$18,	$10
+	addq	$10,	$17,	$17
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$18
+	addq	$20,	$18,	$20
+	mulq	$6,	$3,	$10
+	umulh	$6,	$3,	$17
+	addq	$19,	$10,	$19
+	cmpult	$19,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$10
+	addq	$20,	$10,	$20
+	mulq	$8,	$1,	$18
+	umulh	$8,	$1,	$17
+	addq	$19,	$18,	$19
+	cmpult	$19,	$18,	$10
+	addq	$10,	$17,	$17
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$18
+	addq	$20,	$18,	$20
+	stq	$19,	32($16)
+	bis	$31,	$31,	$19
+	mulq	$0,	$24,	$10
+	umulh	$0,	$24,	$17
+	addq	$9,	$10,	$9
+	cmpult	$9,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$20,	$17,	$20
+	cmpult	$20,	$17,	$10
+	addq	$19,	$10,	$19
+	mulq	$2,	$22,	$18
+	umulh	$2,	$22,	$17
+	addq	$9,	$18,	$9
+	cmpult	$9,	$18,	$10
+	addq	$10,	$17,	$17
+	addq	$20,	$17,	$20
+	cmpult	$20,	$17,	$18
+	addq	$19,	$18,	$19
+	mulq	$4,	$7,	$10
+	umulh	$4,	$7,	$17
+	addq	$9,	$10,	$9
+	cmpult	$9,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$20,	$17,	$20
+	cmpult	$20,	$17,	$10
+	addq	$19,	$10,	$19
+	mulq	$6,	$5,	$18
+	umulh	$6,	$5,	$17
+	addq	$9,	$18,	$9
+	cmpult	$9,	$18,	$10
+	addq	$10,	$17,	$17
+	addq	$20,	$17,	$20
+	cmpult	$20,	$17,	$18
+	addq	$19,	$18,	$19
+	mulq	$8,	$3,	$10
+	umulh	$8,	$3,	$17
+	addq	$9,	$10,	$9
+	cmpult	$9,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$20,	$17,	$20
+	cmpult	$20,	$17,	$10
+	addq	$19,	$10,	$19
+	mulq	$23,	$1,	$18
+	umulh	$23,	$1,	$17
+	addq	$9,	$18,	$9
+	cmpult	$9,	$18,	$10
+	addq	$10,	$17,	$17
+	addq	$20,	$17,	$20
+	cmpult	$20,	$17,	$18
+	addq	$19,	$18,	$19
+	stq	$9,	40($16)
+	bis	$31,	$31,	$9
+	mulq	$0,	$27,	$10
+	umulh	$0,	$27,	$17
+	addq	$20,	$10,	$20
+	cmpult	$20,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$19,	$17,	$19
+	cmpult	$19,	$17,	$10
+	addq	$9,	$10,	$9
+	mulq	$2,	$24,	$18
+	umulh	$2,	$24,	$17
+	addq	$20,	$18,	$20
+	cmpult	$20,	$18,	$10
+	addq	$10,	$17,	$17
+	addq	$19,	$17,	$19
+	cmpult	$19,	$17,	$18
+	addq	$9,	$18,	$9
+	mulq	$4,	$22,	$10
+	umulh	$4,	$22,	$17
+	addq	$20,	$10,	$20
+	cmpult	$20,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$19,	$17,	$19
+	cmpult	$19,	$17,	$10
+	addq	$9,	$10,	$9
+	mulq	$6,	$7,	$18
+	umulh	$6,	$7,	$17
+	addq	$20,	$18,	$20
+	cmpult	$20,	$18,	$10
+	addq	$10,	$17,	$17
+	addq	$19,	$17,	$19
+	cmpult	$19,	$17,	$18
+	addq	$9,	$18,	$9
+	mulq	$8,	$5,	$10
+	umulh	$8,	$5,	$17
+	addq	$20,	$10,	$20
+	cmpult	$20,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$19,	$17,	$19
+	cmpult	$19,	$17,	$10
+	addq	$9,	$10,	$9
+	mulq	$23,	$3,	$18
+	umulh	$23,	$3,	$17
+	addq	$20,	$18,	$20
+	cmpult	$20,	$18,	$10
+	addq	$10,	$17,	$17
+	addq	$19,	$17,	$19
+	cmpult	$19,	$17,	$18
+	addq	$9,	$18,	$9
+	mulq	$25,	$1,	$10
+	umulh	$25,	$1,	$17
+	addq	$20,	$10,	$20
+	cmpult	$20,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$19,	$17,	$19
+	cmpult	$19,	$17,	$10
+	addq	$9,	$10,	$9
+	stq	$20,	48($16)
+	bis	$31,	$31,	$20
+	mulq	$0,	$21,	$18
+	umulh	$0,	$21,	$17
+	addq	$19,	$18,	$19
+	cmpult	$19,	$18,	$10
+	addq	$10,	$17,	$17
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$18
+	addq	$20,	$18,	$20
+	mulq	$2,	$27,	$10
+	umulh	$2,	$27,	$17
+	addq	$19,	$10,	$19
+	cmpult	$19,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$0
+	addq	$20,	$0,	$20
+	mulq	$4,	$24,	$10
+	umulh	$4,	$24,	$18
+	addq	$19,	$10,	$19
+	cmpult	$19,	$10,	$17
+	addq	$17,	$18,	$18
+	addq	$9,	$18,	$9
+	cmpult	$9,	$18,	$0
+	addq	$20,	$0,	$20
+	mulq	$6,	$22,	$10
+	umulh	$6,	$22,	$17
+	addq	$19,	$10,	$19
+	cmpult	$19,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$0
+	addq	$20,	$0,	$20
+	mulq	$8,	$7,	$10
+	umulh	$8,	$7,	$18
+	addq	$19,	$10,	$19
+	cmpult	$19,	$10,	$17
+	addq	$17,	$18,	$18
+	addq	$9,	$18,	$9
+	cmpult	$9,	$18,	$0
+	addq	$20,	$0,	$20
+	mulq	$23,	$5,	$10
+	umulh	$23,	$5,	$17
+	addq	$19,	$10,	$19
+	cmpult	$19,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$0
+	addq	$20,	$0,	$20
+	mulq	$25,	$3,	$10
+	umulh	$25,	$3,	$18
+	addq	$19,	$10,	$19
+	cmpult	$19,	$10,	$17
+	addq	$17,	$18,	$18
+	addq	$9,	$18,	$9
+	cmpult	$9,	$18,	$0
+	addq	$20,	$0,	$20
+	mulq	$28,	$1,	$10
+	umulh	$28,	$1,	$17
+	addq	$19,	$10,	$19
+	cmpult	$19,	$10,	$18
+	addq	$18,	$17,	$17
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$0
+	addq	$20,	$0,	$20
+	stq	$19,	56($16)
+	bis	$31,	$31,	$19
+	mulq	$2,	$21,	$10
+	umulh	$2,	$21,	$18
+	addq	$9,	$10,	$9
+	cmpult	$9,	$10,	$17
+	addq	$17,	$18,	$18
+	addq	$20,	$18,	$20
+	cmpult	$20,	$18,	$0
+	addq	$19,	$0,	$19
+	mulq	$4,	$27,	$1
+	umulh	$4,	$27,	$10
+	addq	$9,	$1,	$9
+	cmpult	$9,	$1,	$17
+	addq	$17,	$10,	$10
+	addq	$20,	$10,	$20
+	cmpult	$20,	$10,	$18
+	addq	$19,	$18,	$19
+	mulq	$6,	$24,	$0
+	umulh	$6,	$24,	$2
+	addq	$9,	$0,	$9
+	cmpult	$9,	$0,	$1
+	addq	$1,	$2,	$2
+	addq	$20,	$2,	$20
+	cmpult	$20,	$2,	$17
+	addq	$19,	$17,	$19
+	mulq	$8,	$22,	$10
+	umulh	$8,	$22,	$18
+	addq	$9,	$10,	$9
+	cmpult	$9,	$10,	$0
+	addq	$0,	$18,	$18
+	addq	$20,	$18,	$20
+	cmpult	$20,	$18,	$1
+	addq	$19,	$1,	$19
+	mulq	$23,	$7,	$2
+	umulh	$23,	$7,	$17
+	addq	$9,	$2,	$9
+	cmpult	$9,	$2,	$10
+	addq	$10,	$17,	$17
+	addq	$20,	$17,	$20
+	cmpult	$20,	$17,	$0
+	addq	$19,	$0,	$19
+	mulq	$25,	$5,	$18
+	umulh	$25,	$5,	$1
+	addq	$9,	$18,	$9
+	cmpult	$9,	$18,	$2
+	addq	$2,	$1,	$1
+	addq	$20,	$1,	$20
+	cmpult	$20,	$1,	$10
+	addq	$19,	$10,	$19
+	mulq	$28,	$3,	$17
+	umulh	$28,	$3,	$0
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$18
+	addq	$18,	$0,	$0
+	addq	$20,	$0,	$20
+	cmpult	$20,	$0,	$2
+	addq	$19,	$2,	$19
+	stq	$9,	64($16)
+	bis	$31,	$31,	$9
+	mulq	$4,	$21,	$1
+	umulh	$4,	$21,	$10
+	addq	$20,	$1,	$20
+	cmpult	$20,	$1,	$17
+	addq	$17,	$10,	$10
+	addq	$19,	$10,	$19
+	cmpult	$19,	$10,	$18
+	addq	$9,	$18,	$9
+	mulq	$6,	$27,	$0
+	umulh	$6,	$27,	$2
+	addq	$20,	$0,	$20
+	cmpult	$20,	$0,	$3
+	addq	$3,	$2,	$2
+	addq	$19,	$2,	$19
+	cmpult	$19,	$2,	$1
+	addq	$9,	$1,	$9
+	mulq	$8,	$24,	$17
+	umulh	$8,	$24,	$10
+	addq	$20,	$17,	$20
+	cmpult	$20,	$17,	$18
+	addq	$18,	$10,	$10
+	addq	$19,	$10,	$19
+	cmpult	$19,	$10,	$4
+	addq	$9,	$4,	$9
+	mulq	$23,	$22,	$0
+	umulh	$23,	$22,	$3
+	addq	$20,	$0,	$20
+	cmpult	$20,	$0,	$2
+	addq	$2,	$3,	$3
+	addq	$19,	$3,	$19
+	cmpult	$19,	$3,	$1
+	addq	$9,	$1,	$9
+	mulq	$25,	$7,	$17
+	umulh	$25,	$7,	$18
+	addq	$20,	$17,	$20
+	cmpult	$20,	$17,	$10
+	addq	$10,	$18,	$18
+	addq	$19,	$18,	$19
+	cmpult	$19,	$18,	$4
+	addq	$9,	$4,	$9
+	mulq	$28,	$5,	$0
+	umulh	$28,	$5,	$2
+	addq	$20,	$0,	$20
+	cmpult	$20,	$0,	$3
+	addq	$3,	$2,	$2
+	addq	$19,	$2,	$19
+	cmpult	$19,	$2,	$1
+	addq	$9,	$1,	$9
+	stq	$20,	72($16)
+	bis	$31,	$31,	$20
+	mulq	$6,	$21,	$17
+	umulh	$6,	$21,	$10
+	addq	$19,	$17,	$19
+	cmpult	$19,	$17,	$18
+	addq	$18,	$10,	$10
+	addq	$9,	$10,	$9
+	cmpult	$9,	$10,	$4
+	addq	$20,	$4,	$20
+	mulq	$8,	$27,	$0
+	umulh	$8,	$27,	$3
+	addq	$19,	$0,	$19
+	cmpult	$19,	$0,	$2
+	addq	$2,	$3,	$3
+	addq	$9,	$3,	$9
+	cmpult	$9,	$3,	$1
+	addq	$20,	$1,	$20
+	mulq	$23,	$24,	$5
+	umulh	$23,	$24,	$17
+	addq	$19,	$5,	$19
+	cmpult	$19,	$5,	$18
+	addq	$18,	$17,	$17
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$10
+	addq	$20,	$10,	$20
+	mulq	$25,	$22,	$4
+	umulh	$25,	$22,	$6
+	addq	$19,	$4,	$19
+	cmpult	$19,	$4,	$0
+	addq	$0,	$6,	$6
+	addq	$9,	$6,	$9
+	cmpult	$9,	$6,	$2
+	addq	$20,	$2,	$20
+	mulq	$28,	$7,	$3
+	umulh	$28,	$7,	$1
+	addq	$19,	$3,	$19
+	cmpult	$19,	$3,	$5
+	addq	$5,	$1,	$1
+	addq	$9,	$1,	$9
+	cmpult	$9,	$1,	$18
+	addq	$20,	$18,	$20
+	stq	$19,	80($16)
+	bis	$31,	$31,	$19
+	mulq	$8,	$21,	$17
+	umulh	$8,	$21,	$10
+	addq	$9,	$17,	$9
+	cmpult	$9,	$17,	$4
+	addq	$4,	$10,	$10
+	addq	$20,	$10,	$20
+	cmpult	$20,	$10,	$0
+	addq	$19,	$0,	$19
+	mulq	$23,	$27,	$6
+	umulh	$23,	$27,	$2
+	addq	$9,	$6,	$9
+	cmpult	$9,	$6,	$3
+	addq	$3,	$2,	$2
+	addq	$20,	$2,	$20
+	cmpult	$20,	$2,	$5
+	addq	$19,	$5,	$19
+	mulq	$25,	$24,	$1
+	umulh	$25,	$24,	$18
+	addq	$9,	$1,	$9
+	cmpult	$9,	$1,	$7
+	addq	$7,	$18,	$18
+	addq	$20,	$18,	$20
+	cmpult	$20,	$18,	$17
+	addq	$19,	$17,	$19
+	mulq	$28,	$22,	$4
+	umulh	$28,	$22,	$10
+	addq	$9,	$4,	$9
+	cmpult	$9,	$4,	$0
+	addq	$0,	$10,	$10
+	addq	$20,	$10,	$20
+	cmpult	$20,	$10,	$8
+	addq	$19,	$8,	$19
+	stq	$9,	88($16)
+	bis	$31,	$31,	$9
+	mulq	$23,	$21,	$6
+	umulh	$23,	$21,	$3
+	addq	$20,	$6,	$20
+	cmpult	$20,	$6,	$2
+	addq	$2,	$3,	$3
+	addq	$19,	$3,	$19
+	cmpult	$19,	$3,	$5
+	addq	$9,	$5,	$9
+	mulq	$25,	$27,	$1
+	umulh	$25,	$27,	$7
+	addq	$20,	$1,	$20
+	cmpult	$20,	$1,	$18
+	addq	$18,	$7,	$7
+	addq	$19,	$7,	$19
+	cmpult	$19,	$7,	$17
+	addq	$9,	$17,	$9
+	mulq	$28,	$24,	$4
+	umulh	$28,	$24,	$0
+	addq	$20,	$4,	$20
+	cmpult	$20,	$4,	$10
+	addq	$10,	$0,	$0
+	addq	$19,	$0,	$19
+	cmpult	$19,	$0,	$8
+	addq	$9,	$8,	$9
+	stq	$20,	96($16)
+	bis	$31,	$31,	$20
+	mulq	$25,	$21,	$22
+	umulh	$25,	$21,	$6
+	addq	$19,	$22,	$19
+	cmpult	$19,	$22,	$2
+	addq	$2,	$6,	$6
+	addq	$9,	$6,	$9
+	cmpult	$9,	$6,	$3
+	addq	$20,	$3,	$20
+	mulq	$28,	$27,	$5
+	umulh	$28,	$27,	$23
+	addq	$19,	$5,	$19
+	cmpult	$19,	$5,	$1
+	addq	$1,	$23,	$23
+	addq	$9,	$23,	$9
+	cmpult	$9,	$23,	$18
+	addq	$20,	$18,	$20
+	stq	$19,	104($16)
+	bis	$31,	$31,	$19
+	mulq	$28,	$21,	$7
+	umulh	$28,	$21,	$17
+	addq	$9,	$7,	$9
+	cmpult	$9,	$7,	$4
+	addq	$4,	$17,	$17
+	addq	$20,	$17,	$20
+	cmpult	$20,	$17,	$10
+	addq	$19,	$10,	$19
+	stq	$9,	112($16)
+	stq	$20,	120($16)
+	ldq	$9,	8($30)
+	ldq	$10,	16($30)
+	ret	$31,($26),1
+	.end bn_mul_comba8
diff --git a/crypto/bn/asm/mips1.s b/crypto/bn/asm/mips1.s
new file mode 100644
index 0000000..44fa125
--- /dev/null
+++ b/crypto/bn/asm/mips1.s
@@ -0,0 +1,539 @@
+/* This assember is for R2000/R3000 machines, or higher ones that do
+ * no want to do any 64 bit arithmatic.
+ * Make sure that the SSLeay bignum library is compiled with 
+ * THIRTY_TWO_BIT set.
+ * This must either be compiled with the system CC, or, if you use GNU gas,
+ * cc -E mips1.s|gas -o mips1.o
+ */
+	.set	reorder
+	.set	noat
+
+#define R1	$1
+#define CC	$2
+#define	R2	$3
+#define R3	$8
+#define R4	$9
+#define L1	$10
+#define L2 	$11
+#define L3	$12
+#define L4 	$13
+#define H1 	$14
+#define H2	$15
+#define H3	$24
+#define H4	$25
+
+#define P1	$4
+#define P2	$5
+#define P3	$6
+#define P4	$7
+
+	.align	2
+	.ent	bn_mul_add_words
+	.globl	bn_mul_add_words
+.text
+bn_mul_add_words:
+	.frame	$sp,0,$31
+	.mask	0x00000000,0
+	.fmask	0x00000000,0
+
+	#blt	P3,4,$lab34
+	
+	subu	R1,P3,4
+	move	CC,$0
+	bltz	R1,$lab34
+$lab2:	
+	lw	R1,0(P1)
+	 lw	L1,0(P2)
+	lw	R2,4(P1)
+	 lw	L2,4(P2)
+	lw	R3,8(P1)
+	 lw	L3,8(P2)
+	lw	R4,12(P1)
+	 lw	L4,12(P2)
+	multu	L1,P4
+	 addu	R1,R1,CC
+	mflo	L1
+	 sltu	CC,R1,CC
+	addu	R1,R1,L1
+	 mfhi	H1
+	sltu	L1,R1,L1
+	 sw	R1,0(P1)
+	addu	CC,CC,L1
+	 multu	L2,P4
+	addu	CC,H1,CC
+	mflo	L2
+	 addu	R2,R2,CC
+	sltu	CC,R2,CC
+	 mfhi	H2
+	addu	R2,R2,L2
+	 addu	P2,P2,16
+	sltu	L2,R2,L2
+	 sw	R2,4(P1)
+	addu	CC,CC,L2
+	 multu	L3,P4
+	addu	CC,H2,CC
+	mflo	L3
+	 addu	R3,R3,CC
+	sltu	CC,R3,CC
+	 mfhi	H3
+	addu	R3,R3,L3
+	 addu	P1,P1,16
+	sltu	L3,R3,L3
+	 sw	R3,-8(P1)
+	addu	CC,CC,L3
+	 multu	L4,P4
+	addu	CC,H3,CC
+	mflo	L4
+	 addu	R4,R4,CC
+	sltu	CC,R4,CC
+	 mfhi	H4
+	addu	R4,R4,L4
+	 subu	P3,P3,4
+	sltu	L4,R4,L4
+	addu	CC,CC,L4
+	addu	CC,H4,CC
+
+	subu	R1,P3,4
+	sw	R4,-4(P1)	# delay slot
+	bgez	R1,$lab2
+
+	bleu	P3,0,$lab3
+	.align	2
+$lab33: 
+	lw	L1,0(P2)
+	 lw	R1,0(P1)
+	multu	L1,P4
+	 addu	R1,R1,CC
+	sltu	CC,R1,CC
+	 addu	P1,P1,4
+	mflo	L1
+	 mfhi	H1
+	addu	R1,R1,L1
+	 addu	P2,P2,4
+	sltu	L1,R1,L1
+	 subu	P3,P3,1
+	addu	CC,CC,L1
+	 sw	R1,-4(P1)
+	addu	CC,H1,CC
+	 bgtz	P3,$lab33
+	j	$31
+	.align	2
+$lab3:
+	j	$31
+	.align	2
+$lab34:
+	bgt	P3,0,$lab33
+	j	$31
+	.end	bn_mul_add_words
+
+	.align	2
+	# Program Unit: bn_mul_words
+	.ent	bn_mul_words
+	.globl	bn_mul_words
+.text
+bn_mul_words:
+	.frame	$sp,0,$31
+	.mask	0x00000000,0
+	.fmask	0x00000000,0
+	
+	subu	P3,P3,4
+	move	CC,$0
+	bltz	P3,$lab45
+$lab44:	
+	lw	L1,0(P2)
+	 lw	L2,4(P2)
+	lw	L3,8(P2)
+	 lw	L4,12(P2)
+	multu	L1,P4
+	 subu	P3,P3,4
+	mflo	L1
+	 mfhi	H1
+	addu	L1,L1,CC
+	 multu	L2,P4
+	sltu	CC,L1,CC
+	 sw	L1,0(P1)
+	addu	CC,H1,CC
+	 mflo	L2
+	mfhi	H2
+	 addu	L2,L2,CC
+	multu	L3,P4
+	 sltu	CC,L2,CC
+	sw	L2,4(P1)
+	 addu	CC,H2,CC
+	mflo	L3
+	 mfhi	H3
+	addu	L3,L3,CC
+	 multu	L4,P4
+	sltu	CC,L3,CC
+	 sw	L3,8(P1)
+	addu	CC,H3,CC
+	 mflo	L4
+	mfhi	H4
+	 addu	L4,L4,CC
+	addu	P1,P1,16
+	 sltu	CC,L4,CC
+	addu	P2,P2,16
+	 addu	CC,H4,CC
+	sw	L4,-4(P1)
+
+	bgez	P3,$lab44
+	b	$lab45
+$lab46:
+	lw	L1,0(P2)
+	 addu	P1,P1,4
+	multu	L1,P4
+	 addu	P2,P2,4
+	mflo	L1
+	 mfhi	H1
+	addu	L1,L1,CC
+	 subu	P3,P3,1
+	sltu	CC,L1,CC
+	 sw	L1,-4(P1)
+	addu	CC,H1,CC
+	 bgtz	P3,$lab46
+	j	$31
+$lab45:
+	addu	P3,P3,4
+	bgtz	P3,$lab46
+	j	$31
+	.align	2
+	.end	bn_mul_words
+
+	# Program Unit: bn_sqr_words
+	.ent	bn_sqr_words
+	.globl	bn_sqr_words
+.text
+bn_sqr_words:
+	.frame	$sp,0,$31
+	.mask	0x00000000,0
+	.fmask	0x00000000,0
+	
+	subu	P3,P3,4
+	bltz	P3,$lab55
+$lab54:
+	lw	L1,0(P2)
+	 lw	L2,4(P2)
+	lw	L3,8(P2)
+	 lw	L4,12(P2)
+
+	multu	L1,L1
+	 subu	P3,P3,4
+	mflo	L1
+	 mfhi	H1
+	sw	L1,0(P1)
+	 sw	H1,4(P1)
+
+	multu	L2,L2
+	 addu	P1,P1,32
+	mflo	L2
+	 mfhi	H2
+	sw	L2,-24(P1)
+	 sw	H2,-20(P1)
+
+	multu	L3,L3
+	 addu	P2,P2,16
+	mflo	L3
+	 mfhi	H3
+	sw	L3,-16(P1)
+	 sw	H3,-12(P1)
+
+	multu	L4,L4
+
+	mflo	L4
+	 mfhi	H4
+	sw	L4,-8(P1)
+	 sw	H4,-4(P1)
+
+	bgtz	P3,$lab54
+	b	$lab55
+$lab56:	
+	lw	L1,0(P2)
+	addu	P1,P1,8
+	multu	L1,L1
+	addu	P2,P2,4
+	subu	P3,P3,1
+	mflo	L1
+	mfhi	H1
+	sw	L1,-8(P1)
+	sw	H1,-4(P1)
+
+	bgtz	P3,$lab56
+	j	$31
+$lab55:
+	addu	P3,P3,4
+	bgtz	P3,$lab56
+	j	$31
+	.align	2
+	.end	bn_sqr_words
+
+	# Program Unit: bn_add_words
+	.ent	bn_add_words
+	.globl	bn_add_words
+.text
+bn_add_words: 	 # 0x590
+	.frame	$sp,0,$31
+	.mask	0x00000000,0
+	.fmask	0x00000000,0
+	
+	subu	P4,P4,4
+	move	CC,$0
+	bltz	P4,$lab65
+$lab64:	
+	lw	L1,0(P2)
+	lw	R1,0(P3)
+	lw	L2,4(P2)
+	lw	R2,4(P3)
+
+	addu	L1,L1,CC
+	 lw	L3,8(P2)
+	sltu	CC,L1,CC
+	 addu	L1,L1,R1
+	sltu	R1,L1,R1
+	 lw	R3,8(P3)
+	addu	CC,CC,R1
+	 lw	L4,12(P2)
+
+	addu	L2,L2,CC
+	 lw	R4,12(P3)
+	sltu	CC,L2,CC
+	 addu	L2,L2,R2
+	sltu	R2,L2,R2
+	 sw	L1,0(P1)
+	addu	CC,CC,R2
+	 addu	P1,P1,16
+	addu	L3,L3,CC
+	 sw	L2,-12(P1)
+ 
+	sltu	CC,L3,CC
+	 addu	L3,L3,R3
+	sltu	R3,L3,R3
+	 addu	P2,P2,16
+	addu	CC,CC,R3
+
+	addu	L4,L4,CC
+	 addu	P3,P3,16
+	sltu	CC,L4,CC
+	 addu	L4,L4,R4
+	subu	P4,P4,4
+	 sltu	R4,L4,R4
+	sw	L3,-8(P1)
+	 addu	CC,CC,R4
+	sw	L4,-4(P1)
+
+	bgtz	P4,$lab64
+	b	$lab65
+$lab66:
+	lw	L1,0(P2)
+	 lw	R1,0(P3)
+	addu	L1,L1,CC
+	 addu	P1,P1,4
+	sltu	CC,L1,CC
+	 addu	P2,P2,4
+	addu	P3,P3,4
+	 addu	L1,L1,R1
+	subu	P4,P4,1
+	 sltu	R1,L1,R1
+	sw	L1,-4(P1)
+	 addu	CC,CC,R1
+
+	bgtz	P4,$lab66
+	j	$31
+$lab65:
+	addu	P4,P4,4
+	bgtz	P4,$lab66
+	j	$31
+	.end	bn_add_words
+
+	# Program Unit: bn_div64
+	.set	at
+	.set	reorder
+	.text	
+	.align	2
+	.globl	bn_div64
+ # 321		{
+	.ent	bn_div64 2
+bn_div64:
+	subu	$sp, 64
+	sw	$31, 56($sp)
+	sw	$16, 48($sp)
+	.mask	0x80010000, -56
+	.frame	$sp, 64, $31
+	move	$9, $4
+	move	$12, $5
+	move	$16, $6
+ # 322		BN_ULONG dh,dl,q,ret=0,th,tl,t;
+	move	$31, $0
+ # 323		int i,count=2;
+	li	$13, 2
+ # 324	
+ # 325		if (d == 0) return(BN_MASK2);
+	bne	$16, 0, $80
+	li	$2, -1
+	b	$93
+$80:
+ # 326	
+ # 327		i=BN_num_bits_word(d);
+	move	$4, $16
+	sw	$31, 16($sp)
+	sw	$9, 24($sp)
+	sw	$12, 32($sp)
+	sw	$13, 40($sp)
+	.livereg	0x800ff0e,0xfff
+	jal	BN_num_bits_word
+	li	$4, 32
+	lw	$31, 16($sp)
+	lw	$9, 24($sp)
+	lw	$12, 32($sp)
+	lw	$13, 40($sp)
+	move	$3, $2
+ # 328		if ((i != BN_BITS2) && (h > (BN_ULONG)1<<i))
+	beq	$2, $4, $81
+	li	$14, 1
+	sll	$15, $14, $2
+	bleu	$9, $15, $81
+ # 329			{
+ # 330	#if !defined(NO_STDIO) && !defined(WIN16)
+ # 331			fprintf(stderr,"Division would overflow (%d)\n",i);
+ # 332	#endif
+ # 333			abort();
+	sw	$3, 8($sp)
+	sw	$9, 24($sp)
+	sw	$12, 32($sp)
+	sw	$13, 40($sp)
+	sw	$31, 26($sp)
+	.livereg	0xff0e,0xfff
+	jal	abort
+	lw	$3, 8($sp)
+	li	$4, 32
+	lw	$9, 24($sp)
+	lw	$12, 32($sp)
+	lw	$13, 40($sp)
+	lw	$31, 26($sp)
+ # 334			}
+$81:
+ # 335		i=BN_BITS2-i;
+	subu	$3, $4, $3
+ # 336		if (h >= d) h-=d;
+	bltu	$9, $16, $82
+	subu	$9, $9, $16
+$82:
+ # 337	
+ # 338		if (i)
+	beq	$3, 0, $83
+ # 339			{
+ # 340			d<<=i;
+	sll	$16, $16, $3
+ # 341			h=(h<<i)|(l>>(BN_BITS2-i));
+	sll	$24, $9, $3
+	subu	$25, $4, $3
+	srl	$14, $12, $25
+	or	$9, $24, $14
+ # 342			l<<=i;
+	sll	$12, $12, $3
+ # 343			}
+$83:
+ # 344		dh=(d&BN_MASK2h)>>BN_BITS4;
+ # 345		dl=(d&BN_MASK2l);
+	and	$8, $16, -65536
+	srl	$8, $8, 16
+	and	$10, $16, 65535
+	li	$6, -65536
+$84:
+ # 346		for (;;)
+ # 347			{
+ # 348			if ((h>>BN_BITS4) == dh)
+	srl	$15, $9, 16
+	bne	$8, $15, $85
+ # 349				q=BN_MASK2l;
+	li	$5, 65535
+	b	$86
+$85:
+ # 350			else
+ # 351				q=h/dh;
+	divu	$5, $9, $8
+$86:
+ # 352	
+ # 353			for (;;)
+ # 354				{
+ # 355				t=(h-q*dh);
+	mul	$4, $5, $8
+	subu	$2, $9, $4
+	move	$3, $2
+ # 356				if ((t&BN_MASK2h) ||
+ # 357					((dl*q) <= (
+ # 358						(t<<BN_BITS4)+
+ # 359						((l&BN_MASK2h)>>BN_BITS4))))
+	and	$25, $2, $6
+	bne	$25, $0, $87
+	mul	$24, $10, $5
+	sll	$14, $3, 16
+	and	$15, $12, $6
+	srl	$25, $15, 16
+	addu	$15, $14, $25
+	bgtu	$24, $15, $88
+$87:
+ # 360					break;
+	mul	$3, $10, $5
+	b	$89
+$88:
+ # 361				q--;
+	addu	$5, $5, -1
+ # 362				}
+	b	$86
+$89:
+ # 363			th=q*dh;
+ # 364			tl=q*dl;
+ # 365			t=(tl>>BN_BITS4);
+ # 366			tl=(tl<<BN_BITS4)&BN_MASK2h;
+	sll	$14, $3, 16
+	and	$2, $14, $6
+	move	$11, $2
+ # 367			th+=t;
+	srl	$25, $3, 16
+	addu	$7, $4, $25
+ # 368	
+ # 369			if (l < tl) th++;
+	bgeu	$12, $2, $90
+	addu	$7, $7, 1
+$90:
+ # 370			l-=tl;
+	subu	$12, $12, $11
+ # 371			if (h < th)
+	bgeu	$9, $7, $91
+ # 372				{
+ # 373				h+=d;
+	addu	$9, $9, $16
+ # 374				q--;
+	addu	$5, $5, -1
+ # 375				}
+$91:
+ # 376			h-=th;
+	subu	$9, $9, $7
+ # 377	
+ # 378			if (--count == 0) break;
+	addu	$13, $13, -1
+	beq	$13, 0, $92
+ # 379	
+ # 380			ret=q<<BN_BITS4;
+	sll	$31, $5, 16
+ # 381			h=((h<<BN_BITS4)|(l>>BN_BITS4))&BN_MASK2;
+	sll	$24, $9, 16
+	srl	$15, $12, 16
+	or	$9, $24, $15
+ # 382			l=(l&BN_MASK2l)<<BN_BITS4;
+	and	$12, $12, 65535
+	sll	$12, $12, 16
+ # 383			}
+	b	$84
+$92:
+ # 384		ret|=q;
+	or	$31, $31, $5
+ # 385		return(ret);
+	move	$2, $31
+$93:
+	lw	$16, 48($sp)
+	lw	$31, 56($sp)
+	addu	$sp, 64
+	j	$31
+	.end	bn_div64
+
diff --git a/crypto/bn/asm/mips3.s b/crypto/bn/asm/mips3.s
new file mode 100644
index 0000000..e8fdd50
--- /dev/null
+++ b/crypto/bn/asm/mips3.s
@@ -0,0 +1,544 @@
+/* This assember is for R4000 and above machines.  It takes advantage
+ * of the 64 bit registers present on these CPUs.
+ * Make sure that the SSLeay bignum library is compiled with
+ * SIXTY_FOUR_BIT set and BN_LLONG undefined.
+ * This must either be compiled with the system CC, or, if you use GNU gas,
+ * cc -E mips3.s|gas -o mips3.o
+ */
+	.set	reorder
+	.set	noat
+
+#define R1	$1
+#define CC	$2
+#define	R2	$3
+#define R3	$8
+#define R4	$9
+#define L1	$10
+#define L2 	$11
+#define L3	$12
+#define L4 	$13
+#define H1 	$14
+#define H2	$15
+#define H3	$24
+#define H4	$25
+
+#define P1	$4
+#define P2	$5
+#define P3	$6
+#define P4	$7
+
+	.align	2
+	.ent	bn_mul_add_words
+	.globl	bn_mul_add_words
+.text
+bn_mul_add_words:
+	.frame	$sp,0,$31
+	.mask	0x00000000,0
+	.fmask	0x00000000,0
+
+	#blt	P3,4,$lab34
+	
+	subu	R1,P3,4
+	move	CC,$0
+	bltz	R1,$lab34
+$lab2:	
+	ld	R1,0(P1)
+	 ld	L1,0(P2)
+	ld	R2,8(P1)
+	 ld	L2,8(P2)
+	ld	R3,16(P1)
+	 ld	L3,16(P2)
+	ld	R4,24(P1)
+	 ld	L4,24(P2)
+	dmultu	L1,P4
+	 daddu	R1,R1,CC
+	mflo	L1
+	 sltu	CC,R1,CC
+	daddu	R1,R1,L1
+	 mfhi	H1
+	sltu	L1,R1,L1
+	 sd	R1,0(P1)
+	daddu	CC,CC,L1
+	 dmultu	L2,P4
+	daddu	CC,H1,CC
+	mflo	L2
+	 daddu	R2,R2,CC
+	sltu	CC,R2,CC
+	 mfhi	H2
+	daddu	R2,R2,L2
+	 daddu	P2,P2,32
+	sltu	L2,R2,L2
+	 sd	R2,8(P1)
+	daddu	CC,CC,L2
+	 dmultu	L3,P4
+	daddu	CC,H2,CC
+	mflo	L3
+	 daddu	R3,R3,CC
+	sltu	CC,R3,CC
+	 mfhi	H3
+	daddu	R3,R3,L3
+	 daddu	P1,P1,32
+	sltu	L3,R3,L3
+	 sd	R3,-16(P1)
+	daddu	CC,CC,L3
+	 dmultu	L4,P4
+	daddu	CC,H3,CC
+	mflo	L4
+	 daddu	R4,R4,CC
+	sltu	CC,R4,CC
+	 mfhi	H4
+	daddu	R4,R4,L4
+	 subu	P3,P3,4
+	sltu	L4,R4,L4
+	daddu	CC,CC,L4
+	daddu	CC,H4,CC
+
+	subu	R1,P3,4
+	sd	R4,-8(P1)	# delay slot
+	bgez	R1,$lab2
+
+	bleu	P3,0,$lab3
+	.align	2
+$lab33: 
+	ld	L1,0(P2)
+	 ld	R1,0(P1)
+	dmultu	L1,P4
+	 daddu	R1,R1,CC
+	sltu	CC,R1,CC
+	 daddu	P1,P1,8
+	mflo	L1
+	 mfhi	H1
+	daddu	R1,R1,L1
+	 daddu	P2,P2,8
+	sltu	L1,R1,L1
+	 subu	P3,P3,1
+	daddu	CC,CC,L1
+	 sd	R1,-8(P1)
+	daddu	CC,H1,CC
+	 bgtz	P3,$lab33
+	j	$31
+	.align	2
+$lab3:
+	j	$31
+	.align	2
+$lab34:
+	bgt	P3,0,$lab33
+	j	$31
+	.end	bn_mul_add_words
+
+	.align	2
+	# Program Unit: bn_mul_words
+	.ent	bn_mul_words
+	.globl	bn_mul_words
+.text
+bn_mul_words:
+	.frame	$sp,0,$31
+	.mask	0x00000000,0
+	.fmask	0x00000000,0
+	
+	subu	P3,P3,4
+	move	CC,$0
+	bltz	P3,$lab45
+$lab44:	
+	ld	L1,0(P2)
+	 ld	L2,8(P2)
+	ld	L3,16(P2)
+	 ld	L4,24(P2)
+	dmultu	L1,P4
+	 subu	P3,P3,4
+	mflo	L1
+	 mfhi	H1
+	daddu	L1,L1,CC
+	 dmultu	L2,P4
+	sltu	CC,L1,CC
+	 sd	L1,0(P1)
+	daddu	CC,H1,CC
+	 mflo	L2
+	mfhi	H2
+	 daddu	L2,L2,CC
+	dmultu	L3,P4
+	 sltu	CC,L2,CC
+	sd	L2,8(P1)
+	 daddu	CC,H2,CC
+	mflo	L3
+	 mfhi	H3
+	daddu	L3,L3,CC
+	 dmultu	L4,P4
+	sltu	CC,L3,CC
+	 sd	L3,16(P1)
+	daddu	CC,H3,CC
+	 mflo	L4
+	mfhi	H4
+	 daddu	L4,L4,CC
+	daddu	P1,P1,32
+	 sltu	CC,L4,CC
+	daddu	P2,P2,32
+	 daddu	CC,H4,CC
+	sd	L4,-8(P1)
+
+	bgez	P3,$lab44
+	b	$lab45
+$lab46:
+	ld	L1,0(P2)
+	 daddu	P1,P1,8
+	dmultu	L1,P4
+	 daddu	P2,P2,8
+	mflo	L1
+	 mfhi	H1
+	daddu	L1,L1,CC
+	 subu	P3,P3,1
+	sltu	CC,L1,CC
+	 sd	L1,-8(P1)
+	daddu	CC,H1,CC
+	 bgtz	P3,$lab46
+	j	$31
+$lab45:
+	addu	P3,P3,4
+	bgtz	P3,$lab46
+	j	$31
+	.align	2
+	.end	bn_mul_words
+
+	# Program Unit: bn_sqr_words
+	.ent	bn_sqr_words
+	.globl	bn_sqr_words
+.text
+bn_sqr_words:
+	.frame	$sp,0,$31
+	.mask	0x00000000,0
+	.fmask	0x00000000,0
+	
+	subu	P3,P3,4
+ b $lab55
+	bltz	P3,$lab55
+$lab54:
+	ld	L1,0(P2)
+	 ld	L2,8(P2)
+	ld	L3,16(P2)
+	 ld	L4,24(P2)
+
+	dmultu	L1,L1
+	 subu	P3,P3,4
+	mflo	L1
+	 mfhi	H1
+	sd	L1,0(P1)
+	 sd	H1,8(P1)
+
+	dmultu	L2,L2
+	 daddu	P1,P1,32
+	mflo	L2
+	 mfhi	H2
+	sd	L2,-48(P1)
+	 sd	H2,-40(P1)
+
+	dmultu	L3,L3
+	 daddu	P2,P2,32
+	mflo	L3
+	 mfhi	H3
+	sd	L3,-32(P1)
+	 sd	H3,-24(P1)
+
+	dmultu	L4,L4
+
+	mflo	L4
+	 mfhi	H4
+	sd	L4,-16(P1)
+	 sd	H4,-8(P1)
+
+	bgtz	P3,$lab54
+	b	$lab55
+$lab56:	
+	ld	L1,0(P2)
+	daddu	P1,P1,16
+	dmultu	L1,L1
+	daddu	P2,P2,8
+	subu	P3,P3,1
+	mflo	L1
+	mfhi	H1
+	sd	L1,-16(P1)
+	sd	H1,-8(P1)
+
+	bgtz	P3,$lab56
+	j	$31
+$lab55:
+	daddu	P3,P3,4
+	bgtz	P3,$lab56
+	j	$31
+	.align	2
+	.end	bn_sqr_words
+
+	# Program Unit: bn_add_words
+	.ent	bn_add_words
+	.globl	bn_add_words
+.text
+bn_add_words: 	 # 0x590
+	.frame	$sp,0,$31
+	.mask	0x00000000,0
+	.fmask	0x00000000,0
+	
+	subu	P4,P4,4
+	move	CC,$0
+	bltz	P4,$lab65
+$lab64:	
+	ld	L1,0(P2)
+	ld	R1,0(P3)
+	ld	L2,8(P2)
+	ld	R2,8(P3)
+
+	daddu	L1,L1,CC
+	 ld	L3,16(P2)
+	sltu	CC,L1,CC
+	 daddu	L1,L1,R1
+	sltu	R1,L1,R1
+	 ld	R3,16(P3)
+	daddu	CC,CC,R1
+	 ld	L4,24(P2)
+
+	daddu	L2,L2,CC
+	 ld	R4,24(P3)
+	sltu	CC,L2,CC
+	 daddu	L2,L2,R2
+	sltu	R2,L2,R2
+	 sd	L1,0(P1)
+	daddu	CC,CC,R2
+	 daddu	P1,P1,32
+	daddu	L3,L3,CC
+	 sd	L2,-24(P1)
+
+	sltu	CC,L3,CC
+	 daddu	L3,L3,R3
+	sltu	R3,L3,R3
+	 daddu	P2,P2,32
+	daddu	CC,CC,R3
+
+	daddu	L4,L4,CC
+	 daddu	P3,P3,32
+	sltu	CC,L4,CC
+	 daddu	L4,L4,R4
+	sltu	R4,L4,R4
+	 subu	P4,P4,4
+	sd	L3,-16(P1)
+	 daddu	CC,CC,R4
+	sd	L4,-8(P1)
+
+	bgtz	P4,$lab64
+	b	$lab65
+$lab66:
+	ld	L1,0(P2)
+	 ld	R1,0(P3)
+	daddu	L1,L1,CC
+	 daddu	P1,P1,8
+	sltu	CC,L1,CC
+	 daddu	P2,P2,8
+	daddu	P3,P3,8
+	 daddu	L1,L1,R1
+	subu	P4,P4,1
+	 sltu	R1,L1,R1
+	sd	L1,-8(P1)
+	 daddu	CC,CC,R1
+
+	bgtz	P4,$lab66
+	j	$31
+$lab65:
+	addu	P4,P4,4
+	bgtz	P4,$lab66
+	j	$31
+	.end	bn_add_words
+
+#if 1
+	# Program Unit: bn_div64
+	.set	at
+	.set	reorder
+	.text	
+	.align	2
+	.globl	bn_div64
+ # 321		{
+	.ent	bn_div64
+bn_div64:
+	dsubu	$sp, 64
+	sd	$31, 56($sp)
+	sd	$16, 48($sp)
+	.mask	0x80010000, -56
+	.frame	$sp, 64, $31
+	move	$9, $4
+	move	$12, $5
+	move	$16, $6
+ # 322		BN_ULONG dh,dl,q,ret=0,th,tl,t;
+	move	$31, $0
+ # 323		int i,count=2;
+	li	$13, 2
+ # 324	
+ # 325		if (d == 0) return(BN_MASK2);
+	bne	$16, 0, $80
+	dli	$2, -1
+	b	$93
+$80:
+ # 326	
+ # 327		i=BN_num_bits_word(d);
+	move	$4, $16
+	sd	$31, 16($sp)
+	sd	$9, 24($sp)
+	sd	$12, 32($sp)
+	sd	$13, 40($sp)
+	.livereg	0x800ff0e,0xfff
+	jal	BN_num_bits_word
+	dli	$4, 64
+	ld	$31, 16($sp)
+	ld	$9, 24($sp)
+	ld	$12, 32($sp)
+	ld	$13, 40($sp)
+	move	$3, $2
+ # 328		if ((i != BN_BITS2) && (h > (BN_ULONG)1<<i))
+	beq	$2, $4, $81
+	dli	$14, 1
+	dsll	$15, $14, $2
+	bleu	$9, $15, $81
+ # 329			{
+ # 330	#if !defined(NO_STDIO) && !defined(WIN16)
+ # 331			fprintf(stderr,"Division would overflow (%d)\n",i);
+ # 332	#endif
+ # 333			abort();
+	sd	$3, 8($sp)
+	sd	$31, 16($sp)
+	sd	$9, 24($sp)
+	sd	$12, 32($sp)
+	sd	$13, 40($sp)
+	.livereg	0xff0e,0xfff
+	jal	abort
+	dli	$4, 64
+	ld	$3, 8($sp)
+	ld	$31, 16($sp)
+	ld	$9, 24($sp)
+	ld	$12, 32($sp)
+	ld	$13, 40($sp)
+ # 334			}
+$81:
+ # 335		i=BN_BITS2-i;
+	dsubu	$3, $4, $3
+ # 336		if (h >= d) h-=d;
+	bltu	$9, $16, $82
+	dsubu	$9, $9, $16
+$82:
+ # 337	
+ # 338		if (i)
+	beq	$3, 0, $83
+ # 339			{
+ # 340			d<<=i;
+	dsll	$16, $16, $3
+ # 341			h=(h<<i)|(l>>(BN_BITS2-i));
+	dsll	$24, $9, $3
+	dsubu	$25, $4, $3
+	dsrl	$14, $12, $25
+	or	$9, $24, $14
+ # 342			l<<=i;
+	dsll	$12, $12, $3
+ # 343			}
+$83:
+ # 344		dh=(d&BN_MASK2h)>>BN_BITS4;
+ # 345		dl=(d&BN_MASK2l);
+	and	$8, $16,0xFFFFFFFF00000000
+	dsrl	$8, $8, 32
+	# dli	$10,0xFFFFFFFF # Is this needed?
+	# and	$10, $16, $10
+	dsll	$10, $16, 32
+	dsrl	$10, $10, 32
+	dli	$6,0xFFFFFFFF00000000
+$84:
+ # 346		for (;;)
+ # 347			{
+ # 348			if ((h>>BN_BITS4) == dh)
+	dsrl	$15, $9, 32
+	bne	$8, $15, $85
+ # 349				q=BN_MASK2l;
+	dli	$5, 0xFFFFFFFF
+	b	$86
+$85:
+ # 350			else
+ # 351				q=h/dh;
+	ddivu	$5, $9, $8
+$86:
+ # 352	
+ # 353			for (;;)
+ # 354				{
+ # 355				t=(h-q*dh);
+	dmul	$4, $5, $8
+	dsubu	$2, $9, $4
+	move	$3, $2
+ # 356				if ((t&BN_MASK2h) ||
+ # 357					((dl*q) <= (
+ # 358						(t<<BN_BITS4)+
+ # 359						((l&BN_MASK2h)>>BN_BITS4))))
+	and	$25, $2, $6
+	bne	$25, $0, $87
+	dmul	$24, $10, $5
+	dsll	$14, $3, 32
+	and	$15, $12, $6
+	dsrl	$25, $15, 32
+	daddu	$15, $14, $25
+	bgtu	$24, $15, $88
+$87:
+ # 360					break;
+	dmul	$3, $10, $5
+	b	$89
+$88:
+ # 361				q--;
+	daddu	$5, $5, -1
+ # 362				}
+	b	$86
+$89:
+ # 363			th=q*dh;
+ # 364			tl=q*dl;
+ # 365			t=(tl>>BN_BITS4);
+ # 366			tl=(tl<<BN_BITS4)&BN_MASK2h;
+	dsll	$14, $3, 32
+	and	$2, $14, $6
+	move	$11, $2
+ # 367			th+=t;
+	dsrl	$25, $3, 32
+	daddu	$7, $4, $25
+ # 368	
+ # 369			if (l < tl) th++;
+	bgeu	$12, $2, $90
+	daddu	$7, $7, 1
+$90:
+ # 370			l-=tl;
+	dsubu	$12, $12, $11
+ # 371			if (h < th)
+	bgeu	$9, $7, $91
+ # 372				{
+ # 373				h+=d;
+	daddu	$9, $9, $16
+ # 374				q--;
+	daddu	$5, $5, -1
+ # 375				}
+$91:
+ # 376			h-=th;
+	dsubu	$9, $9, $7
+ # 377	
+ # 378			if (--count == 0) break;
+	addu	$13, $13, -1
+	beq	$13, 0, $92
+ # 379	
+ # 380			ret=q<<BN_BITS4;
+	dsll	$31, $5, 32
+ # 381			h=((h<<BN_BITS4)|(l>>BN_BITS4))&BN_MASK2;
+	dsll	$24, $9, 32
+	dsrl	$15, $12, 32
+	or	$9, $24, $15
+ # 382			l=(l&BN_MASK2l)<<BN_BITS4;
+	and	$12, $12, 0xFFFFFFFF
+	dsll	$12, $12, 32
+ # 383			}
+	b	$84
+$92:
+ # 384		ret|=q;
+	or	$31, $31, $5
+ # 385		return(ret);
+	move	$2, $31
+$93:
+	ld	$16, 48($sp)
+	ld	$31, 56($sp)
+	daddu	$sp, 64
+	j	$31
+	.end	bn_div64
+#endif
diff --git a/crypto/bn/asm/x86.pl b/crypto/bn/asm/x86.pl
new file mode 100644
index 0000000..bf869fd
--- /dev/null
+++ b/crypto/bn/asm/x86.pl
@@ -0,0 +1,28 @@
+#!/usr/local/bin/perl
+
+push(@INC,"perlasm","../../perlasm");
+require "x86asm.pl";
+
+require("x86/mul_add.pl");
+require("x86/mul.pl");
+require("x86/sqr.pl");
+require("x86/div.pl");
+require("x86/add.pl");
+require("x86/sub.pl");
+require("x86/comba.pl");
+
+&asm_init($ARGV[0],"bn-586.pl");
+
+&bn_mul_add_words("bn_mul_add_words");
+&bn_mul_words("bn_mul_words");
+&bn_sqr_words("bn_sqr_words");
+&bn_div_words("bn_div_words");
+&bn_add_words("bn_add_words");
+&bn_sub_words("bn_sub_words");
+&bn_mul_comba("bn_mul_comba8",8);
+&bn_mul_comba("bn_mul_comba4",4);
+&bn_sqr_comba("bn_sqr_comba8",8);
+&bn_sqr_comba("bn_sqr_comba4",4);
+
+&asm_finish();
+
diff --git a/crypto/bn/asm/x86/add.pl b/crypto/bn/asm/x86/add.pl
new file mode 100644
index 0000000..0b5cf58
--- /dev/null
+++ b/crypto/bn/asm/x86/add.pl
@@ -0,0 +1,76 @@
+#!/usr/local/bin/perl
+# x86 assember
+
+sub bn_add_words
+	{
+	local($name)=@_;
+
+	&function_begin($name,"");
+
+	&comment("");
+	$a="esi";
+	$b="edi";
+	$c="eax";
+	$r="ebx";
+	$tmp1="ecx";
+	$tmp2="edx";
+	$num="ebp";
+
+	&mov($r,&wparam(0));	# get r
+	 &mov($a,&wparam(1));	# get a
+	&mov($b,&wparam(2));	# get b
+	 &mov($num,&wparam(3));	# get num
+	&xor($c,$c);		# clear carry
+	 &and($num,0xfffffff8);	# num / 8
+
+	&jz(&label("aw_finish"));
+
+	&set_label("aw_loop",0);
+	for ($i=0; $i<8; $i++)
+		{
+		&comment("Round $i");
+
+		&mov($tmp1,&DWP($i*4,$a,"",0)); 	# *a
+		 &mov($tmp2,&DWP($i*4,$b,"",0)); 	# *b
+		&add($tmp1,$c);
+		 &mov($c,0);
+		&adc($c,$c);
+		 &add($tmp1,$tmp2);
+		&adc($c,0);
+		 &mov(&DWP($i*4,$r,"",0),$tmp1); 	# *r
+		}
+
+	&comment("");
+	&add($a,32);
+	 &add($b,32);
+	&add($r,32);
+	 &sub($num,8);
+	&jnz(&label("aw_loop"));
+
+	&set_label("aw_finish",0);
+	&mov($num,&wparam(3));	# get num
+	&and($num,7);
+	 &jz(&label("aw_end"));
+
+	for ($i=0; $i<7; $i++)
+		{
+		&comment("Tail Round $i");
+		&mov($tmp1,&DWP($i*4,$a,"",0));	# *a
+		 &mov($tmp2,&DWP($i*4,$b,"",0));# *b
+		&add($tmp1,$c);
+		 &mov($c,0);
+		&adc($c,$c);
+		 &add($tmp1,$tmp2);
+		&adc($c,0);
+		 &dec($num) if ($i != 6);
+		&mov(&DWP($i*4,$r,"",0),$tmp1);	# *a
+		 &jz(&label("aw_end")) if ($i != 6);
+		}
+	&set_label("aw_end",0);
+
+#	&mov("eax",$c);		# $c is "eax"
+
+	&function_end($name);
+	}
+
+1;
diff --git a/crypto/bn/asm/x86/comba.pl b/crypto/bn/asm/x86/comba.pl
new file mode 100644
index 0000000..2291253
--- /dev/null
+++ b/crypto/bn/asm/x86/comba.pl
@@ -0,0 +1,277 @@
+#!/usr/local/bin/perl
+# x86 assember
+
+sub mul_add_c
+	{
+	local($a,$ai,$b,$bi,$c0,$c1,$c2,$pos,$i,$na,$nb)=@_;
+
+	# pos == -1 if eax and edx are pre-loaded, 0 to load from next
+	# words, and 1 if load return value
+
+	&comment("mul a[$ai]*b[$bi]");
+
+	# "eax" and "edx" will always be pre-loaded.
+	# &mov("eax",&DWP($ai*4,$a,"",0)) ;
+	# &mov("edx",&DWP($bi*4,$b,"",0));
+
+	&mul("edx");
+	&add($c0,"eax");
+	 &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 0;	# laod next a
+	 &mov("eax",&wparam(0)) if $pos > 0;			# load r[]
+	 ###
+	&adc($c1,"edx");
+	 &mov("edx",&DWP(($nb)*4,$b,"",0)) if $pos == 0;	# laod next b
+	 &mov("edx",&DWP(($nb)*4,$b,"",0)) if $pos == 1;	# laod next b
+	 ###
+	&adc($c2,0);
+	 # is pos > 1, it means it is the last loop 
+	 &mov(&DWP($i*4,"eax","",0),$c0) if $pos > 0;		# save r[];
+	&mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 1;		# laod next a
+	}
+
+sub sqr_add_c
+	{
+	local($r,$a,$ai,$bi,$c0,$c1,$c2,$pos,$i,$na,$nb)=@_;
+
+	# pos == -1 if eax and edx are pre-loaded, 0 to load from next
+	# words, and 1 if load return value
+
+	&comment("sqr a[$ai]*a[$bi]");
+
+	# "eax" and "edx" will always be pre-loaded.
+	# &mov("eax",&DWP($ai*4,$a,"",0)) ;
+	# &mov("edx",&DWP($bi*4,$b,"",0));
+
+	if ($ai == $bi)
+		{ &mul("eax");}
+	else
+		{ &mul("edx");}
+	&add($c0,"eax");
+	 &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 0;	# load next a
+	 ###
+	&adc($c1,"edx");
+	 &mov("edx",&DWP(($nb)*4,$a,"",0)) if ($pos == 1) && ($na != $nb);
+	 ###
+	&adc($c2,0);
+	 # is pos > 1, it means it is the last loop 
+	 &mov(&DWP($i*4,$r,"",0),$c0) if $pos > 0;		# save r[];
+	&mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 1;		# load next b
+	}
+
+sub sqr_add_c2
+	{
+	local($r,$a,$ai,$bi,$c0,$c1,$c2,$pos,$i,$na,$nb)=@_;
+
+	# pos == -1 if eax and edx are pre-loaded, 0 to load from next
+	# words, and 1 if load return value
+
+	&comment("sqr a[$ai]*a[$bi]");
+
+	# "eax" and "edx" will always be pre-loaded.
+	# &mov("eax",&DWP($ai*4,$a,"",0)) ;
+	# &mov("edx",&DWP($bi*4,$a,"",0));
+
+	if ($ai == $bi)
+		{ &mul("eax");}
+	else
+		{ &mul("edx");}
+	&add("eax","eax");
+	 ###
+	&adc("edx","edx");
+	 ###
+	&adc($c2,0);
+	 &add($c0,"eax");
+	&adc($c1,"edx");
+	 &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 0;	# load next a
+	 &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 1;	# load next b
+	&adc($c2,0);
+	&mov(&DWP($i*4,$r,"",0),$c0) if $pos > 0;		# save r[];
+	 &mov("edx",&DWP(($nb)*4,$a,"",0)) if ($pos <= 1) && ($na != $nb);
+	 ###
+	}
+
+sub bn_mul_comba
+	{
+	local($name,$num)=@_;
+	local($a,$b,$c0,$c1,$c2);
+	local($i,$as,$ae,$bs,$be,$ai,$bi);
+	local($tot,$end);
+
+	&function_begin_B($name,"");
+
+	$c0="ebx";
+	$c1="ecx";
+	$c2="ebp";
+	$a="esi";
+	$b="edi";
+	
+	$as=0;
+	$ae=0;
+	$bs=0;
+	$be=0;
+	$tot=$num+$num-1;
+
+	&push("esi");
+	 &mov($a,&wparam(1));
+	&push("edi");
+	 &mov($b,&wparam(2));
+	&push("ebp");
+	 &push("ebx");
+
+	&xor($c0,$c0);
+	 &mov("eax",&DWP(0,$a,"",0));	# load the first word 
+	&xor($c1,$c1);
+	 &mov("edx",&DWP(0,$b,"",0));	# load the first second 
+
+	for ($i=0; $i<$tot; $i++)
+		{
+		$ai=$as;
+		$bi=$bs;
+		$end=$be+1;
+
+		&comment("################## Calculate word $i"); 
+
+		for ($j=$bs; $j<$end; $j++)
+			{
+			&xor($c2,$c2) if ($j == $bs);
+			if (($j+1) == $end)
+				{
+				$v=1;
+				$v=2 if (($i+1) == $tot);
+				}
+			else
+				{ $v=0; }
+			if (($j+1) != $end)
+				{
+				$na=($ai-1);
+				$nb=($bi+1);
+				}
+			else
+				{
+				$na=$as+($i < ($num-1));
+				$nb=$bs+($i >= ($num-1));
+				}
+#printf STDERR "[$ai,$bi] -> [$na,$nb]\n";
+			&mul_add_c($a,$ai,$b,$bi,$c0,$c1,$c2,$v,$i,$na,$nb);
+			if ($v)
+				{
+				&comment("saved r[$i]");
+				# &mov("eax",&wparam(0));
+				# &mov(&DWP($i*4,"eax","",0),$c0);
+				($c0,$c1,$c2)=($c1,$c2,$c0);
+				}
+			$ai--;
+			$bi++;
+			}
+		$as++ if ($i < ($num-1));
+		$ae++ if ($i >= ($num-1));
+
+		$bs++ if ($i >= ($num-1));
+		$be++ if ($i < ($num-1));
+		}
+	&comment("save r[$i]");
+	# &mov("eax",&wparam(0));
+	&mov(&DWP($i*4,"eax","",0),$c0);
+
+	&pop("ebx");
+	&pop("ebp");
+	&pop("edi");
+	&pop("esi");
+	&ret();
+	&function_end_B($name);
+	}
+
+sub bn_sqr_comba
+	{
+	local($name,$num)=@_;
+	local($r,$a,$c0,$c1,$c2)=@_;
+	local($i,$as,$ae,$bs,$be,$ai,$bi);
+	local($b,$tot,$end,$half);
+
+	&function_begin_B($name,"");
+
+	$c0="ebx";
+	$c1="ecx";
+	$c2="ebp";
+	$a="esi";
+	$r="edi";
+
+	&push("esi");
+	 &push("edi");
+	&push("ebp");
+	 &push("ebx");
+	&mov($r,&wparam(0));
+	 &mov($a,&wparam(1));
+	&xor($c0,$c0);
+	 &xor($c1,$c1);
+	&mov("eax",&DWP(0,$a,"",0)); # load the first word
+
+	$as=0;
+	$ae=0;
+	$bs=0;
+	$be=0;
+	$tot=$num+$num-1;
+
+	for ($i=0; $i<$tot; $i++)
+		{
+		$ai=$as;
+		$bi=$bs;
+		$end=$be+1;
+
+		&comment("############### Calculate word $i");
+		for ($j=$bs; $j<$end; $j++)
+			{
+			&xor($c2,$c2) if ($j == $bs);
+			if (($ai-1) < ($bi+1))
+				{
+				$v=1;
+				$v=2 if ($i+1) == $tot;
+				}
+			else
+				{ $v=0; }
+			if (!$v)
+				{
+				$na=$ai-1;
+				$nb=$bi+1;
+				}
+			else
+				{
+				$na=$as+($i < ($num-1));
+				$nb=$bs+($i >= ($num-1));
+				}
+			if ($ai == $bi)
+				{
+				&sqr_add_c($r,$a,$ai,$bi,
+					$c0,$c1,$c2,$v,$i,$na,$nb);
+				}
+			else
+				{
+				&sqr_add_c2($r,$a,$ai,$bi,
+					$c0,$c1,$c2,$v,$i,$na,$nb);
+				}
+			if ($v)
+				{
+				&comment("saved r[$i]");
+				#&mov(&DWP($i*4,$r,"",0),$c0);
+				($c0,$c1,$c2)=($c1,$c2,$c0);
+				last;
+				}
+			$ai--;
+			$bi++;
+			}
+		$as++ if ($i < ($num-1));
+		$ae++ if ($i >= ($num-1));
+
+		$bs++ if ($i >= ($num-1));
+		$be++ if ($i < ($num-1));
+		}
+	&mov(&DWP($i*4,$r,"",0),$c0);
+	&pop("ebx");
+	&pop("ebp");
+	&pop("edi");
+	&pop("esi");
+	&ret();
+	&function_end_B($name);
+	}
+
+1;
diff --git a/crypto/bn/asm/x86/div.pl b/crypto/bn/asm/x86/div.pl
new file mode 100644
index 0000000..0e90152
--- /dev/null
+++ b/crypto/bn/asm/x86/div.pl
@@ -0,0 +1,15 @@
+#!/usr/local/bin/perl
+# x86 assember
+
+sub bn_div_words
+	{
+	local($name)=@_;
+
+	&function_begin($name,"");
+	&mov("edx",&wparam(0));	#
+	&mov("eax",&wparam(1));	#
+	&mov("ebx",&wparam(2));	#
+	&div("ebx");
+	&function_end($name);
+	}
+1;
diff --git a/crypto/bn/asm/x86/f b/crypto/bn/asm/x86/f
new file mode 100644
index 0000000..22e4112
--- /dev/null
+++ b/crypto/bn/asm/x86/f
@@ -0,0 +1,3 @@
+#!/usr/local/bin/perl
+# x86 assember
+
diff --git a/crypto/bn/asm/x86/mul.pl b/crypto/bn/asm/x86/mul.pl
new file mode 100644
index 0000000..674cb9b
--- /dev/null
+++ b/crypto/bn/asm/x86/mul.pl
@@ -0,0 +1,77 @@
+#!/usr/local/bin/perl
+# x86 assember
+
+sub bn_mul_words
+	{
+	local($name)=@_;
+
+	&function_begin($name,"");
+
+	&comment("");
+	$Low="eax";
+	$High="edx";
+	$a="ebx";
+	$w="ecx";
+	$r="edi";
+	$c="esi";
+	$num="ebp";
+
+	&xor($c,$c);		# clear carry
+	&mov($r,&wparam(0));	#
+	&mov($a,&wparam(1));	#
+	&mov($num,&wparam(2));	#
+	&mov($w,&wparam(3));	#
+
+	&and($num,0xfffffff8);	# num / 8
+	&jz(&label("mw_finish"));
+
+	&set_label("mw_loop",0);
+	for ($i=0; $i<32; $i+=4)
+		{
+		&comment("Round $i");
+
+		 &mov("eax",&DWP($i,$a,"",0)); 	# *a
+		&mul($w);			# *a * w
+		&add("eax",$c);			# L(t)+=c
+		 # XXX
+
+		&adc("edx",0);			# H(t)+=carry
+		 &mov(&DWP($i,$r,"",0),"eax");	# *r= L(t);
+
+		&mov($c,"edx");			# c=  H(t);
+		}
+
+	&comment("");
+	&add($a,32);
+	&add($r,32);
+	&sub($num,8);
+	&jz(&label("mw_finish"));
+	&jmp(&label("mw_loop"));
+
+	&set_label("mw_finish",0);
+	&mov($num,&wparam(2));	# get num
+	&and($num,7);
+	&jnz(&label("mw_finish2"));
+	&jmp(&label("mw_end"));
+
+	&set_label("mw_finish2",1);
+	for ($i=0; $i<7; $i++)
+		{
+		&comment("Tail Round $i");
+		 &mov("eax",&DWP($i*4,$a,"",0));# *a
+		&mul($w);			# *a * w
+		&add("eax",$c);			# L(t)+=c
+		 # XXX
+		&adc("edx",0);			# H(t)+=carry
+		 &mov(&DWP($i*4,$r,"",0),"eax");# *r= L(t);
+		&mov($c,"edx");			# c=  H(t);
+		 &dec($num) if ($i != 7-1);
+		&jz(&label("mw_end")) if ($i != 7-1);
+		}
+	&set_label("mw_end",0);
+	&mov("eax",$c);
+
+	&function_end($name);
+	}
+
+1;
diff --git a/crypto/bn/asm/x86/mul_add.pl b/crypto/bn/asm/x86/mul_add.pl
new file mode 100644
index 0000000..61830d3
--- /dev/null
+++ b/crypto/bn/asm/x86/mul_add.pl
@@ -0,0 +1,87 @@
+#!/usr/local/bin/perl
+# x86 assember
+
+sub bn_mul_add_words
+	{
+	local($name)=@_;
+
+	&function_begin($name,"");
+
+	&comment("");
+	$Low="eax";
+	$High="edx";
+	$a="ebx";
+	$w="ebp";
+	$r="edi";
+	$c="esi";
+
+	&xor($c,$c);		# clear carry
+	&mov($r,&wparam(0));	#
+
+	&mov("ecx",&wparam(2));	#
+	&mov($a,&wparam(1));	#
+
+	&and("ecx",0xfffffff8);	# num / 8
+	&mov($w,&wparam(3));	#
+
+	&push("ecx");		# Up the stack for a tmp variable
+
+	&jz(&label("maw_finish"));
+
+	&set_label("maw_loop",0);
+
+	&mov(&swtmp(0),"ecx");	#
+
+	for ($i=0; $i<32; $i+=4)
+		{
+		&comment("Round $i");
+
+		 &mov("eax",&DWP($i,$a,"",0)); 	# *a
+		&mul($w);			# *a * w
+		&add("eax",$c);		# L(t)+= *r
+		 &mov($c,&DWP($i,$r,"",0));	# L(t)+= *r
+		&adc("edx",0);			# H(t)+=carry
+		 &add("eax",$c);		# L(t)+=c
+		&adc("edx",0);			# H(t)+=carry
+		 &mov(&DWP($i,$r,"",0),"eax");	# *r= L(t);
+		&mov($c,"edx");			# c=  H(t);
+		}
+
+	&comment("");
+	&mov("ecx",&swtmp(0));	#
+	&add($a,32);
+	&add($r,32);
+	&sub("ecx",8);
+	&jnz(&label("maw_loop"));
+
+	&set_label("maw_finish",0);
+	&mov("ecx",&wparam(2));	# get num
+	&and("ecx",7);
+	&jnz(&label("maw_finish2"));	# helps branch prediction
+	&jmp(&label("maw_end"));
+
+	&set_label("maw_finish2",1);
+	for ($i=0; $i<7; $i++)
+		{
+		&comment("Tail Round $i");
+		 &mov("eax",&DWP($i*4,$a,"",0));# *a
+		&mul($w);			# *a * w
+		&add("eax",$c);			# L(t)+=c
+		 &mov($c,&DWP($i*4,$r,"",0));	# L(t)+= *r
+		&adc("edx",0);			# H(t)+=carry
+		 &add("eax",$c);
+		&adc("edx",0);			# H(t)+=carry
+		 &dec("ecx") if ($i != 7-1);
+		&mov(&DWP($i*4,$r,"",0),"eax");	# *r= L(t);
+		 &mov($c,"edx");			# c=  H(t);
+		&jz(&label("maw_end")) if ($i != 7-1);
+		}
+	&set_label("maw_end",0);
+	&mov("eax",$c);
+
+	&pop("ecx");	# clear variable from
+
+	&function_end($name);
+	}
+
+1;
diff --git a/crypto/bn/asm/x86/sqr.pl b/crypto/bn/asm/x86/sqr.pl
new file mode 100644
index 0000000..1f90993
--- /dev/null
+++ b/crypto/bn/asm/x86/sqr.pl
@@ -0,0 +1,60 @@
+#!/usr/local/bin/perl
+# x86 assember
+
+sub bn_sqr_words
+	{
+	local($name)=@_;
+
+	&function_begin($name,"");
+
+	&comment("");
+	$r="esi";
+	$a="edi";
+	$num="ebx";
+
+	&mov($r,&wparam(0));	#
+	&mov($a,&wparam(1));	#
+	&mov($num,&wparam(2));	#
+
+	&and($num,0xfffffff8);	# num / 8
+	&jz(&label("sw_finish"));
+
+	&set_label("sw_loop",0);
+	for ($i=0; $i<32; $i+=4)
+		{
+		&comment("Round $i");
+		&mov("eax",&DWP($i,$a,"",0)); 	# *a
+		 # XXX
+		&mul("eax");			# *a * *a
+		&mov(&DWP($i*2,$r,"",0),"eax");	#
+		 &mov(&DWP($i*2+4,$r,"",0),"edx");#
+		}
+
+	&comment("");
+	&add($a,32);
+	&add($r,64);
+	&sub($num,8);
+	&jnz(&label("sw_loop"));
+
+	&set_label("sw_finish",0);
+	&mov($num,&wparam(2));	# get num
+	&and($num,7);
+	&jz(&label("sw_end"));
+
+	for ($i=0; $i<7; $i++)
+		{
+		&comment("Tail Round $i");
+		&mov("eax",&DWP($i*4,$a,"",0));	# *a
+		 # XXX
+		&mul("eax");			# *a * *a
+		&mov(&DWP($i*8,$r,"",0),"eax");	#
+		 &dec($num) if ($i != 7-1);
+		&mov(&DWP($i*8+4,$r,"",0),"edx");
+		 &jz(&label("sw_end")) if ($i != 7-1);
+		}
+	&set_label("sw_end",0);
+
+	&function_end($name);
+	}
+
+1;
diff --git a/crypto/bn/asm/x86/sub.pl b/crypto/bn/asm/x86/sub.pl
new file mode 100644
index 0000000..837b0e1
--- /dev/null
+++ b/crypto/bn/asm/x86/sub.pl
@@ -0,0 +1,76 @@
+#!/usr/local/bin/perl
+# x86 assember
+
+sub bn_sub_words
+	{
+	local($name)=@_;
+
+	&function_begin($name,"");
+
+	&comment("");
+	$a="esi";
+	$b="edi";
+	$c="eax";
+	$r="ebx";
+	$tmp1="ecx";
+	$tmp2="edx";
+	$num="ebp";
+
+	&mov($r,&wparam(0));	# get r
+	 &mov($a,&wparam(1));	# get a
+	&mov($b,&wparam(2));	# get b
+	 &mov($num,&wparam(3));	# get num
+	&xor($c,$c);		# clear carry
+	 &and($num,0xfffffff8);	# num / 8
+
+	&jz(&label("aw_finish"));
+
+	&set_label("aw_loop",0);
+	for ($i=0; $i<8; $i++)
+		{
+		&comment("Round $i");
+
+		&mov($tmp1,&DWP($i*4,$a,"",0)); 	# *a
+		 &mov($tmp2,&DWP($i*4,$b,"",0)); 	# *b
+		&sub($tmp1,$c);
+		 &mov($c,0);
+		&adc($c,$c);
+		 &sub($tmp1,$tmp2);
+		&adc($c,0);
+		 &mov(&DWP($i*4,$r,"",0),$tmp1); 	# *r
+		}
+
+	&comment("");
+	&add($a,32);
+	 &add($b,32);
+	&add($r,32);
+	 &sub($num,8);
+	&jnz(&label("aw_loop"));
+
+	&set_label("aw_finish",0);
+	&mov($num,&wparam(3));	# get num
+	&and($num,7);
+	 &jz(&label("aw_end"));
+
+	for ($i=0; $i<7; $i++)
+		{
+		&comment("Tail Round $i");
+		&mov($tmp1,&DWP($i*4,$a,"",0));	# *a
+		 &mov($tmp2,&DWP($i*4,$b,"",0));# *b
+		&sub($tmp1,$c);
+		 &mov($c,0);
+		&adc($c,$c);
+		 &sub($tmp1,$tmp2);
+		&adc($c,0);
+		 &dec($num) if ($i != 6);
+		&mov(&DWP($i*4,$r,"",0),$tmp1);	# *a
+		 &jz(&label("aw_end")) if ($i != 6);
+		}
+	&set_label("aw_end",0);
+
+#	&mov("eax",$c);		# $c is "eax"
+
+	&function_end($name);
+	}
+
+1;
diff --git a/crypto/bn/asm/x86w16.asm b/crypto/bn/asm/x86w16.asm
index 74a933a..80a9ed6 100644
--- a/crypto/bn/asm/x86w16.asm
+++ b/crypto/bn/asm/x86w16.asm
@@ -6,11 +6,11 @@
 F_TEXT	ENDS
 _DATA	SEGMENT  WORD PUBLIC 'DATA'
 _DATA	ENDS
-CONST	SEGMENT  WORD PUBLIC 'CONST'
-CONST	ENDS
+_CONST	SEGMENT  WORD PUBLIC 'CONST'
+_CONST	ENDS
 _BSS	SEGMENT  WORD PUBLIC 'BSS'
 _BSS	ENDS
-DGROUP	GROUP	CONST, _BSS, _DATA
+DGROUP	GROUP	_CONST, _BSS, _DATA
 	ASSUME DS: DGROUP, SS: DGROUP
 F_TEXT      SEGMENT
 	ASSUME	CS: F_TEXT
diff --git a/crypto/bn/asm/x86w32.asm b/crypto/bn/asm/x86w32.asm
index fc6f917..957d71e 100644
--- a/crypto/bn/asm/x86w32.asm
+++ b/crypto/bn/asm/x86w32.asm
@@ -6,11 +6,11 @@
 F_TEXT	ENDS
 _DATA	SEGMENT  WORD USE16 PUBLIC 'DATA'
 _DATA	ENDS
-CONST	SEGMENT  WORD USE16 PUBLIC 'CONST'
-CONST	ENDS
+_CONST	SEGMENT  WORD USE16 PUBLIC 'CONST'
+_CONST	ENDS
 _BSS	SEGMENT  WORD USE16 PUBLIC 'BSS'
 _BSS	ENDS
-DGROUP	GROUP	CONST, _BSS, _DATA
+DGROUP	GROUP	_CONST, _BSS, _DATA
 	ASSUME DS: DGROUP, SS: DGROUP
 F_TEXT      SEGMENT
 	ASSUME	CS: F_TEXT
@@ -89,7 +89,7 @@
 	mov	bp,WORD PTR [bp+26]	; load num
 	and	bp,3
 	dec	bp
-	js	$L547
+	js	$L547m
 
 	mov	eax,ecx
 	mul	DWORD PTR es:[bx]	; w* *a
@@ -100,7 +100,7 @@
 	mov	DWORD PTR ds:[di],eax
 	mov	esi,edx
 	dec	bp
-	js	$L547			; Note that we are now testing for -1
+	js	$L547m			; Note that we are now testing for -1
 	;
 	mov	eax,ecx
 	mul	DWORD PTR es:[bx+4]	; w* *a
@@ -111,7 +111,7 @@
 	mov	DWORD PTR ds:[di+4],eax
 	mov	esi,edx
 	dec	bp
-	js	$L547
+	js	$L547m
 	;
 	mov	eax,ecx
 	mul	DWORD PTR es:[bx+8]	; w* *a
@@ -121,7 +121,7 @@
 	adc	edx,0
 	mov	DWORD PTR ds:[di+8],eax
 	mov	esi,edx
-$L547:
+$L547m:
 	mov	eax,esi
 	mov	edx,esi
 	shr	edx,16
@@ -315,37 +315,35 @@
 ;	ap = 22
 ;	rp = 18
 	xor	esi,esi			;c=0;
+	mov	bx,WORD PTR [bp+18]	; load low r
 	mov	si,WORD PTR [bp+22]	; load a
 	mov	es,WORD PTR [bp+24]	; load a
 	mov	di,WORD PTR [bp+26]	; load b
 	mov	ds,WORD PTR [bp+28]	; load b
 
 	mov	dx,WORD PTR [bp+30]	; load num
-	dec	dx
-	js	$L547
 	xor	ecx,ecx
+	dec	dx
+	js	$L547a
 
 $L5477:
-	xor	ebx,ebx
 	mov	eax,DWORD PTR es:[si]	; *a
 	add	eax,ecx
-	adc	ebx,0
+	mov	ecx,0
+	adc	ecx,0
 	add	si,4			; a++
 	add	eax,DWORD PTR ds:[di]	; + *b
-	mov	ecx,ebx
 	adc	ecx,0
-	add	di,4
-	mov	bx,WORD PTR [bp+18]
 	mov	ds,WORD PTR [bp+20]
+	add	di,4
 	mov	DWORD PTR ds:[bx],eax
-	add	bx,4
 	mov	ds,WORD PTR [bp+28]
-	mov	WORD PTR [bp+18],bx
+	add	bx,4
 	dec	dx
-	js	$L547			; Note that we are now testing for -1
+	js	$L547a			; Note that we are now testing for -1
 	jmp	$L5477
 	;
-$L547:
+$L547a:
 	mov	eax,ecx
 	mov	edx,ecx
 	shr	edx,16
diff --git a/crypto/bn/bn.err b/crypto/bn/bn.err
index 7ccc247..ba5c9bc 100644
--- a/crypto/bn/bn.err
+++ b/crypto/bn/bn.err
@@ -16,12 +16,15 @@
 #define BN_F_BN_MPI2BN					 112
 #define BN_F_BN_NEW					 113
 #define BN_F_BN_RAND					 114
+#define BN_F_BN_USUB					 115
 
 /* Reason codes. */
-#define BN_R_BAD_RECIPROCAL				 100
-#define BN_R_CALLED_WITH_EVEN_MODULUS			 101
-#define BN_R_DIV_BY_ZERO				 102
-#define BN_R_ENCODING_ERROR				 103
-#define BN_R_INVALID_LENGTH				 104
-#define BN_R_NOT_INITALISED				 105
-#define BN_R_NO_INVERSE					 106
+#define BN_R_ARG2_LT_ARG3				 100
+#define BN_R_BAD_RECIPROCAL				 101
+#define BN_R_CALLED_WITH_EVEN_MODULUS			 102
+#define BN_R_DIV_BY_ZERO				 103
+#define BN_R_ENCODING_ERROR				 104
+#define BN_R_EXPAND_ON_STATIC_BIGNUM_DATA		 105
+#define BN_R_INVALID_LENGTH				 106
+#define BN_R_NOT_INITALISED				 107
+#define BN_R_NO_INVERSE					 108
diff --git a/crypto/bn/bn.h b/crypto/bn/bn.h
index 66dde28..2c14a1d 100644
--- a/crypto/bn/bn.h
+++ b/crypto/bn/bn.h
@@ -77,6 +77,9 @@
 #define BN_LLONG /* This comment stops Configure mutilating things */
 #endif
 
+#define BN_MUL_COMBA
+#define BN_SQR_COMBA
+#undef BN_RECURSION
 #define RECP_MUL_MOD
 #define MONT_MUL_MOD
 
@@ -105,6 +108,7 @@
 #undef SIXTEEN_BIT
 #undef EIGHT_BIT
 
+
 /* assuming long is 64bit - this is the DEC Alpha
  * unsigned long long is only 64 bits :-(, don't define
  * BN_LLONG for the DEC Alpha */
@@ -116,17 +120,23 @@
 #define BN_BYTES	8
 #define BN_BITS2	64
 #define BN_BITS4	32
+#define BN_MASK		(0xffffffffffffffffffffffffffffffffLL)
 #define BN_MASK2	(0xffffffffffffffffL)
 #define BN_MASK2l	(0xffffffffL)
 #define BN_MASK2h	(0xffffffff00000000L)
 #define BN_MASK2h1	(0xffffffff80000000L)
 #define BN_TBIT		(0x8000000000000000L)
-#define BN_DEC_CONV	(10000000000000000000L)
+#define BN_DEC_CONV	(10000000000000000000UL)
 #define BN_DEC_FMT1	"%lu"
 #define BN_DEC_FMT2	"%019lu"
 #define BN_DEC_NUM	19
 #endif
 
+/* This is where the long long data type is 64 bits, but long is 32.
+ * For machines where there are 64bit registers, this is the mode to use.
+ * IRIX, on R4000 and above should use this mode, along with the relevent
+ * assember code :-).  Do NOT define BN_ULLONG.
+ */
 #ifdef SIXTY_FOUR_BIT
 #undef BN_LLONG
 /* #define BN_ULLONG	unsigned long long */
@@ -141,9 +151,9 @@
 #define BN_MASK2h	(0xffffffff00000000LL)
 #define BN_MASK2h1	(0xffffffff80000000LL)
 #define BN_TBIT		(0x8000000000000000LL)
-#define BN_DEC_CONV	(10000000000000000000L)
-#define BN_DEC_FMT1	"%lu"
-#define BN_DEC_FMT2	"%019lu"
+#define BN_DEC_CONV	(10000000000000000000LL)
+#define BN_DEC_FMT1	"%llu"
+#define BN_DEC_FMT2	"%019llu"
 #define BN_DEC_NUM	19
 #endif
 
@@ -159,6 +169,7 @@
 #define BN_BYTES	4
 #define BN_BITS2	32
 #define BN_BITS4	16
+#define BN_MASK		(0xffffffffffffffffLL)
 #define BN_MASK2	(0xffffffffL)
 #define BN_MASK2l	(0xffff)
 #define BN_MASK2h1	(0xffff8000L)
@@ -181,6 +192,7 @@
 #define BN_BYTES	2
 #define BN_BITS2	16
 #define BN_BITS4	8
+#define BN_MASK		(0xffffffff)
 #define BN_MASK2	(0xffff)
 #define BN_MASK2l	(0xff)
 #define BN_MASK2h1	(0xff80)
@@ -203,6 +215,7 @@
 #define BN_BYTES	1
 #define BN_BITS2	8
 #define BN_BITS4	4
+#define BN_MASK		(0xffff)
 #define BN_MASK2	(0xff)
 #define BN_MASK2l	(0xf)
 #define BN_MASK2h1	(0xf8)
@@ -220,6 +233,12 @@
 #undef BIGNUM
 #endif
 
+#define BN_FLG_MALLOCED		0x01
+#define BN_FLG_STATIC_DATA	0x02
+#define BN_FLG_FREE		0x8000	/* used for debuging */
+#define BN_set_flags(b,n)	((b)->flags|=(n))
+#define BN_get_flags(b,n)	((b)->flags&(n))
+
 typedef struct bignum_st
 	{
 	BN_ULONG *d;	/* Pointer to an array of 'BN_BITS2' bit chunks. */
@@ -227,6 +246,7 @@
 	/* The next are internal book keeping for bn_expand. */
 	int max;	/* Size of the d array. */
 	int neg;	/* one if the number is negative */
+	int flags;
 	} BIGNUM;
 
 /* Used for temp variables */
@@ -234,7 +254,8 @@
 typedef struct bignum_ctx
 	{
 	int tos;
-	BIGNUM *bn[BN_CTX_NUM+1];
+	BIGNUM bn[BN_CTX_NUM+1];
+	int flags;
 	} BN_CTX;
 
 typedef struct bn_blinding_st
@@ -248,51 +269,69 @@
 /* Used for montgomery multiplication */
 typedef struct bn_mont_ctx_st
         {
+	int use_word;	/* 0 for word form, 1 for long form */
         int ri;         /* number of bits in R */
-        BIGNUM *RR;     /* used to convert to montgomery form */
-        BIGNUM *N;      /* The modulus */
-        BIGNUM *Ni;     /* The inverse of N */
+        BIGNUM RR;     /* used to convert to montgomery form */
+        BIGNUM N;      /* The modulus */
+        BIGNUM Ni;     /* The inverse of N */
 	BN_ULONG n0;	/* word form of inverse, normally only one of
 			 * Ni or n0 is defined */
+	int flags;
         } BN_MONT_CTX;
 
+/* Used for reciprocal division/mod functions
+ * It cannot be shared between threads
+ */
+typedef struct bn_recp_ctx_st
+	{
+	BIGNUM N;	/* the divisor */
+	BIGNUM Nr;	/* the reciprocal */
+	int num_bits;
+	int shift;
+	int flags;
+	} BN_RECP_CTX;
+
 #define BN_to_montgomery(r,a,mont,ctx)	BN_mod_mul_montgomery(\
-	r,a,(mont)->RR,(mont),ctx)
+	r,a,&((mont)->RR),(mont),ctx)
 
 #define BN_prime_checks		(5)
 
 #define BN_num_bytes(a)	((BN_num_bits(a)+7)/8)
 #define BN_is_word(a,w)	(((a)->top == 1) && ((a)->d[0] == (BN_ULONG)(w)))
-#define BN_is_zero(a)	(((a)->top <= 1) && ((a)->d[0] == (BN_ULONG)0))
+#define BN_is_zero(a)	(((a)->top == 0) || BN_is_word(a,0))
 #define BN_is_one(a)	(BN_is_word((a),1))
-#define BN_is_odd(a)	((a)->d[0] & 1)
+#define BN_is_odd(a)	(((a)->top > 0) && ((a)->d[0] & 1))
 #define BN_one(a)	(BN_set_word((a),1))
 #define BN_zero(a)	(BN_set_word((a),0))
 
-#define BN_ascii2bn(a)	BN_hex2bn(a)
-#define BN_bn2ascii(a)	BN_bn2hex(a)
+/*#define BN_ascii2bn(a)	BN_hex2bn(a) */
+/*#define BN_bn2ascii(a)	BN_bn2hex(a) */
 
-#define bn_fix_top(a) \
-	{ \
-	BN_ULONG *fix_top_l; \
-	for (fix_top_l= &((a)->d[(a)->top-1]); (a)->top > 0; (a)->top--) \
-		if (*(fix_top_l--)) break; \
-	}
-
-#define bn_expand(n,b) ((((b)/BN_BITS2) <= (n)->max)?\
-	(n):bn_expand2((n),(b)/BN_BITS2))
+#define bn_expand(n,b) ((((((b+BN_BITS2-1))/BN_BITS2)) <= (n)->max)?\
+	(n):bn_expand2((n),(b)/BN_BITS2+1))
 #define bn_wexpand(n,b) (((b) <= (n)->max)?(n):bn_expand2((n),(b)))
 
+#define bn_fix_top(a) \
+        { \
+        BN_ULONG *ftl; \
+	if ((a)->top > 0) \
+		{ \
+		for (ftl= &((a)->d[(a)->top-1]); (a)->top > 0; (a)->top--) \
+		if (*(ftl--)) break; \
+		} \
+	}
 
 #ifndef NOPROTO
 BIGNUM *BN_value_one(void);
 char *	BN_options(void);
 BN_CTX *BN_CTX_new(void);
+void	BN_CTX_init(BN_CTX *c);
 void	BN_CTX_free(BN_CTX *c);
 int     BN_rand(BIGNUM *rnd, int bits, int top,int bottom);
 int	BN_num_bits(BIGNUM *a);
 int	BN_num_bits_word(BN_ULONG);
 BIGNUM *BN_new(void);
+void	BN_init(BIGNUM *);
 void	BN_clear_free(BIGNUM *a);
 BIGNUM *BN_copy(BIGNUM *a, BIGNUM *b);
 BIGNUM *BN_bin2bn(unsigned char *s,int len,BIGNUM *ret);
@@ -300,20 +339,20 @@
 BIGNUM *BN_mpi2bn(unsigned char *s,int len,BIGNUM *ret);
 int	BN_bn2mpi(BIGNUM *a, unsigned char *to);
 int	BN_sub(BIGNUM *r, BIGNUM *a, BIGNUM *b);
-void	bn_qsub(BIGNUM *r, BIGNUM *a, BIGNUM *b);
-void	bn_qadd(BIGNUM *r, BIGNUM *a, BIGNUM *b);
+int	BN_usub(BIGNUM *r, BIGNUM *a, BIGNUM *b);
+int	BN_uadd(BIGNUM *r, BIGNUM *a, BIGNUM *b);
 int	BN_add(BIGNUM *r, BIGNUM *a, BIGNUM *b);
 int	BN_mod(BIGNUM *rem, BIGNUM *m, BIGNUM *d, BN_CTX *ctx);
 int	BN_div(BIGNUM *dv, BIGNUM *rem, BIGNUM *m, BIGNUM *d, BN_CTX *ctx);
-int	BN_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b);
+int	BN_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b,BN_CTX *ctx);
 int	BN_sqr(BIGNUM *r, BIGNUM *a,BN_CTX *ctx);
-BN_ULONG BN_mod_word(BIGNUM *a, unsigned long w);
-BN_ULONG BN_div_word(BIGNUM *a, unsigned long w);
-int	BN_mul_word(BIGNUM *a, unsigned long w);
-int	BN_add_word(BIGNUM *a, unsigned long w);
-int	BN_sub_word(BIGNUM *a, unsigned long w);
-int	BN_set_word(BIGNUM *a, unsigned long w);
-unsigned long BN_get_word(BIGNUM *a);
+BN_ULONG BN_mod_word(BIGNUM *a, BN_ULONG w);
+BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w);
+int	BN_mul_word(BIGNUM *a, BN_ULONG w);
+int	BN_add_word(BIGNUM *a, BN_ULONG w);
+int	BN_sub_word(BIGNUM *a, BN_ULONG w);
+int	BN_set_word(BIGNUM *a, BN_ULONG w);
+BN_ULONG BN_get_word(BIGNUM *a);
 int	BN_cmp(BIGNUM *a, BIGNUM *b);
 void	BN_free(BIGNUM *a);
 int	BN_is_bit_set(BIGNUM *a, int n);
@@ -323,12 +362,11 @@
 int	BN_mod_exp(BIGNUM *r, BIGNUM *a, BIGNUM *p, BIGNUM *m,BN_CTX *ctx);
 int	BN_mod_exp_mont(BIGNUM *r, BIGNUM *a, BIGNUM *p, BIGNUM *m,BN_CTX *ctx,
 		BN_MONT_CTX *m_ctx);
-int	BN_mod_exp_recp(BIGNUM *r, BIGNUM *a, BIGNUM *p, BIGNUM *m,BN_CTX *ctx);
+int	BN_mod_exp2_mont(BIGNUM *r, BIGNUM *a1, BIGNUM *p1,BIGNUM *a2,
+		BIGNUM *p2,BIGNUM *m,BN_CTX *ctx,BN_MONT_CTX *m_ctx);
 int	BN_mod_exp_simple(BIGNUM *r, BIGNUM *a, BIGNUM *p,
 	BIGNUM *m,BN_CTX *ctx);
 int	BN_mask_bits(BIGNUM *a,int n);
-int	BN_mod_mul_reciprocal(BIGNUM *r, BIGNUM *x, BIGNUM *y, BIGNUM *m, 
-	BIGNUM *i, int nb, BN_CTX *ctx);
 int	BN_mod_mul(BIGNUM *ret, BIGNUM *a, BIGNUM *b, BIGNUM *m,
 	BN_CTX *ctx);
 #ifndef WIN16
@@ -339,7 +377,7 @@
 #else
 int	BN_print(char *fp, BIGNUM *a);
 #endif
-int	BN_reciprocal(BIGNUM *r, BIGNUM *m, BN_CTX *ctx);
+int	BN_reciprocal(BIGNUM *r, BIGNUM *m, int len, BN_CTX *ctx);
 int	BN_rshift(BIGNUM *r, BIGNUM *a, int n);
 int	BN_rshift1(BIGNUM *r, BIGNUM *a);
 void	BN_clear(BIGNUM *a);
@@ -353,8 +391,8 @@
 int 	BN_hex2bn(BIGNUM **a,char *str);
 int 	BN_dec2bn(BIGNUM **a,char *str);
 int	BN_gcd(BIGNUM *r,BIGNUM *in_a,BIGNUM *in_b,BN_CTX *ctx);
-BIGNUM *BN_mod_inverse(BIGNUM *a, BIGNUM *n,BN_CTX *ctx);
-BIGNUM *BN_generate_prime(int bits,int strong,BIGNUM *add,
+BIGNUM *BN_mod_inverse(BIGNUM *ret,BIGNUM *a, BIGNUM *n,BN_CTX *ctx);
+BIGNUM *BN_generate_prime(BIGNUM *ret,int bits,int strong,BIGNUM *add,
 		BIGNUM *rem,void (*callback)(int,int,char *),char *cb_arg);
 int	BN_is_prime(BIGNUM *p,int nchecks,void (*callback)(int,int,char *),
 		BN_CTX *ctx,char *cb_arg);
@@ -363,15 +401,18 @@
 BN_ULONG bn_mul_add_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w);
 BN_ULONG bn_mul_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w);
 void     bn_sqr_words(BN_ULONG *rp, BN_ULONG *ap, int num);
-BN_ULONG bn_div64(BN_ULONG h, BN_ULONG l, BN_ULONG d);
+BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d);
 BN_ULONG bn_add_words(BN_ULONG *rp, BN_ULONG *ap, BN_ULONG *bp,int num);
+BN_ULONG bn_sub_words(BN_ULONG *rp, BN_ULONG *ap, BN_ULONG *bp,int num);
 
 BN_MONT_CTX *BN_MONT_CTX_new(void );
+void BN_MONT_CTX_init(BN_MONT_CTX *ctx);
 int BN_mod_mul_montgomery(BIGNUM *r,BIGNUM *a,BIGNUM *b,BN_MONT_CTX *mont,
 	BN_CTX *ctx);
 int BN_from_montgomery(BIGNUM *r,BIGNUM *a,BN_MONT_CTX *mont,BN_CTX *ctx);
 void BN_MONT_CTX_free(BN_MONT_CTX *mont);
 int BN_MONT_CTX_set(BN_MONT_CTX *mont,BIGNUM *modulus,BN_CTX *ctx);
+BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to,BN_MONT_CTX *from);
 
 BN_BLINDING *BN_BLINDING_new(BIGNUM *A,BIGNUM *Ai,BIGNUM *mod);
 void BN_BLINDING_free(BN_BLINDING *b);
@@ -379,16 +420,45 @@
 int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *r, BN_CTX *ctx);
 int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx);
 
+void BN_set_params(int mul,int high,int low,int mont);
+int BN_get_params(int which); /* 0, mul, 1 high, 2 low, 3 mont */
+
+void bn_mul_normal(BN_ULONG *r,BN_ULONG *a,int na,BN_ULONG *b,int nb);
+void bn_mul_comba8(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b);
+void bn_mul_comba4(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b);
+void bn_sqr_normal(BN_ULONG *r, BN_ULONG *a, int n, BN_ULONG *tmp);
+void bn_sqr_comba8(BN_ULONG *r,BN_ULONG *a);
+void bn_sqr_comba4(BN_ULONG *r,BN_ULONG *a);
+int bn_cmp_words(BN_ULONG *a,BN_ULONG *b,int n);
+void bn_mul_recursive(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b,int n2,BN_ULONG *t);
+void bn_mul_part_recursive(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b,
+	int tn, int n,BN_ULONG *t);
+void bn_sqr_recursive(BN_ULONG *r,BN_ULONG *a, int n2, BN_ULONG *t);
+void bn_mul_low_normal(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b, int n);
+
+void	BN_RECP_CTX_init(BN_RECP_CTX *recp);
+BN_RECP_CTX *BN_RECP_CTX_new(void);
+void	BN_RECP_CTX_free(BN_RECP_CTX *recp);
+int	BN_RECP_CTX_set(BN_RECP_CTX *recp,BIGNUM *rdiv,BN_CTX *ctx);
+int	BN_mod_mul_reciprocal(BIGNUM *r, BIGNUM *x, BIGNUM *y,
+		BN_RECP_CTX *recp,BN_CTX *ctx);
+int	BN_mod_exp_recp(BIGNUM *r, BIGNUM *a, BIGNUM *p, BIGNUM *m,BN_CTX *ctx);
+int	BN_div_recp(BIGNUM *dv, BIGNUM *rem, BIGNUM *m,
+		BN_RECP_CTX *recp, BN_CTX *ctx);
+
+
 #else
 
 BIGNUM *BN_value_one();
 char *	BN_options();
 BN_CTX *BN_CTX_new();
+void	BN_CTX_init();
 void	BN_CTX_free();
 int     BN_rand();
 int	BN_num_bits();
 int	BN_num_bits_word();
 BIGNUM *BN_new();
+void	BN_init();
 void	BN_clear_free();
 BIGNUM *BN_copy();
 BIGNUM *BN_bin2bn();
@@ -396,8 +466,8 @@
 BIGNUM *BN_mpi2bn();
 int	BN_bn2mpi();
 int	BN_sub();
-void	bn_qsub();
-void	bn_qadd();
+int	BN_usub();
+int	BN_uadd();
 int	BN_add();
 int	BN_mod();
 int	BN_div();
@@ -449,12 +519,14 @@
 BN_ULONG bn_mul_add_words();
 BN_ULONG bn_mul_words();
 void     bn_sqr_words();
-BN_ULONG bn_div64();
+BN_ULONG bn_div_words();
 BN_ULONG bn_add_words();
+BN_ULONG bn_sub_words();
 
 int BN_mod_mul_montgomery();
 int BN_from_montgomery();
 BN_MONT_CTX *BN_MONT_CTX_new();
+void BN_MONT_CTX_init();
 void BN_MONT_CTX_free();
 int BN_MONT_CTX_set();
 
@@ -464,6 +536,26 @@
 int BN_BLINDING_convert();
 int BN_BLINDING_invert();
 
+void bn_mul_normal();
+void bn_mul_comba8();
+void bn_mul_comba4();
+void bn_sqr_normal();
+void bn_sqr_comba8();
+void bn_sqr_comba4();
+int bn_cmp_words();
+void bn_mul_recursive();
+void bn_mul_part_recursive();
+void bn_sqr_recursive();
+void bn_mul_low_normal();
+
+void	BN_RECP_CTX_init();
+BN_RECP_CTX *BN_RECP_CTX_new();
+void	BN_RECP_CTX_free();
+int	BN_RECP_CTX_set();
+int	BN_mod_mul_reciprocal();
+int	BN_mod_exp_recp();
+int	BN_div_recp();
+
 #endif
 
 /* BEGIN ERROR CODES */
@@ -485,15 +577,18 @@
 #define BN_F_BN_MPI2BN					 112
 #define BN_F_BN_NEW					 113
 #define BN_F_BN_RAND					 114
+#define BN_F_BN_USUB					 115
 
 /* Reason codes. */
-#define BN_R_BAD_RECIPROCAL				 100
-#define BN_R_CALLED_WITH_EVEN_MODULUS			 101
-#define BN_R_DIV_BY_ZERO				 102
-#define BN_R_ENCODING_ERROR				 103
-#define BN_R_INVALID_LENGTH				 104
-#define BN_R_NOT_INITALISED				 105
-#define BN_R_NO_INVERSE					 106
+#define BN_R_ARG2_LT_ARG3				 100
+#define BN_R_BAD_RECIPROCAL				 101
+#define BN_R_CALLED_WITH_EVEN_MODULUS			 102
+#define BN_R_DIV_BY_ZERO				 103
+#define BN_R_ENCODING_ERROR				 104
+#define BN_R_EXPAND_ON_STATIC_BIGNUM_DATA		 105
+#define BN_R_INVALID_LENGTH				 106
+#define BN_R_NOT_INITALISED				 107
+#define BN_R_NO_INVERSE					 108
  
 #ifdef  __cplusplus
 }
diff --git a/crypto/bn/bn.mul b/crypto/bn/bn.mul
new file mode 100644
index 0000000..9728870
--- /dev/null
+++ b/crypto/bn/bn.mul
@@ -0,0 +1,19 @@
+We need
+
+* bn_mul_comba8
+* bn_mul_comba4
+* bn_mul_normal
+* bn_mul_recursive
+
+* bn_sqr_comba8
+* bn_sqr_comba4
+bn_sqr_normal -> BN_sqr
+* bn_sqr_recursive
+
+* bn_mul_low_recursive
+* bn_mul_low_normal
+* bn_mul_high
+
+* bn_mul_part_recursive	# symetric but not power of 2
+
+bn_mul_asymetric_recursive # uneven, but do the chop up.
diff --git a/crypto/bn/bn.org b/crypto/bn/bn.org
index 66dde28..d8904d7 100644
--- a/crypto/bn/bn.org
+++ b/crypto/bn/bn.org
@@ -77,6 +77,9 @@
 #define BN_LLONG /* This comment stops Configure mutilating things */
 #endif
 
+#define BN_MUL_COMBA
+#define BN_SQR_COMBA
+#define BN_RECURSION
 #define RECP_MUL_MOD
 #define MONT_MUL_MOD
 
@@ -105,6 +108,7 @@
 #undef SIXTEEN_BIT
 #undef EIGHT_BIT
 
+
 /* assuming long is 64bit - this is the DEC Alpha
  * unsigned long long is only 64 bits :-(, don't define
  * BN_LLONG for the DEC Alpha */
@@ -116,17 +120,23 @@
 #define BN_BYTES	8
 #define BN_BITS2	64
 #define BN_BITS4	32
+#define BN_MASK		(0xffffffffffffffffffffffffffffffffLL)
 #define BN_MASK2	(0xffffffffffffffffL)
 #define BN_MASK2l	(0xffffffffL)
 #define BN_MASK2h	(0xffffffff00000000L)
 #define BN_MASK2h1	(0xffffffff80000000L)
 #define BN_TBIT		(0x8000000000000000L)
-#define BN_DEC_CONV	(10000000000000000000L)
+#define BN_DEC_CONV	(10000000000000000000UL)
 #define BN_DEC_FMT1	"%lu"
 #define BN_DEC_FMT2	"%019lu"
 #define BN_DEC_NUM	19
 #endif
 
+/* This is where the long long data type is 64 bits, but long is 32.
+ * For machines where there are 64bit registers, this is the mode to use.
+ * IRIX, on R4000 and above should use this mode, along with the relevent
+ * assember code :-).  Do NOT define BN_ULLONG.
+ */
 #ifdef SIXTY_FOUR_BIT
 #undef BN_LLONG
 /* #define BN_ULLONG	unsigned long long */
@@ -141,9 +151,9 @@
 #define BN_MASK2h	(0xffffffff00000000LL)
 #define BN_MASK2h1	(0xffffffff80000000LL)
 #define BN_TBIT		(0x8000000000000000LL)
-#define BN_DEC_CONV	(10000000000000000000L)
-#define BN_DEC_FMT1	"%lu"
-#define BN_DEC_FMT2	"%019lu"
+#define BN_DEC_CONV	(10000000000000000000LL)
+#define BN_DEC_FMT1	"%llu"
+#define BN_DEC_FMT2	"%019llu"
 #define BN_DEC_NUM	19
 #endif
 
@@ -159,6 +169,7 @@
 #define BN_BYTES	4
 #define BN_BITS2	32
 #define BN_BITS4	16
+#define BN_MASK		(0xffffffffffffffffLL)
 #define BN_MASK2	(0xffffffffL)
 #define BN_MASK2l	(0xffff)
 #define BN_MASK2h1	(0xffff8000L)
@@ -181,6 +192,7 @@
 #define BN_BYTES	2
 #define BN_BITS2	16
 #define BN_BITS4	8
+#define BN_MASK		(0xffffffff)
 #define BN_MASK2	(0xffff)
 #define BN_MASK2l	(0xff)
 #define BN_MASK2h1	(0xff80)
@@ -203,6 +215,7 @@
 #define BN_BYTES	1
 #define BN_BITS2	8
 #define BN_BITS4	4
+#define BN_MASK		(0xffff)
 #define BN_MASK2	(0xff)
 #define BN_MASK2l	(0xf)
 #define BN_MASK2h1	(0xf8)
@@ -220,6 +233,12 @@
 #undef BIGNUM
 #endif
 
+#define BN_FLG_MALLOCED		0x01
+#define BN_FLG_STATIC_DATA	0x02
+#define BN_FLG_FREE		0x8000	/* used for debuging */
+#define BN_set_flags(b,n)	((b)->flags|=(n))
+#define BN_get_flags(b,n)	((b)->flags&(n))
+
 typedef struct bignum_st
 	{
 	BN_ULONG *d;	/* Pointer to an array of 'BN_BITS2' bit chunks. */
@@ -227,6 +246,7 @@
 	/* The next are internal book keeping for bn_expand. */
 	int max;	/* Size of the d array. */
 	int neg;	/* one if the number is negative */
+	int flags;
 	} BIGNUM;
 
 /* Used for temp variables */
@@ -234,7 +254,8 @@
 typedef struct bignum_ctx
 	{
 	int tos;
-	BIGNUM *bn[BN_CTX_NUM+1];
+	BIGNUM bn[BN_CTX_NUM+1];
+	int flags;
 	} BN_CTX;
 
 typedef struct bn_blinding_st
@@ -248,51 +269,69 @@
 /* Used for montgomery multiplication */
 typedef struct bn_mont_ctx_st
         {
+	int use_word;	/* 0 for word form, 1 for long form */
         int ri;         /* number of bits in R */
-        BIGNUM *RR;     /* used to convert to montgomery form */
-        BIGNUM *N;      /* The modulus */
-        BIGNUM *Ni;     /* The inverse of N */
+        BIGNUM RR;     /* used to convert to montgomery form */
+        BIGNUM N;      /* The modulus */
+        BIGNUM Ni;     /* The inverse of N */
 	BN_ULONG n0;	/* word form of inverse, normally only one of
 			 * Ni or n0 is defined */
+	int flags;
         } BN_MONT_CTX;
 
+/* Used for reciprocal division/mod functions
+ * It cannot be shared between threads
+ */
+typedef struct bn_recp_ctx_st
+	{
+	BIGNUM N;	/* the divisor */
+	BIGNUM Nr;	/* the reciprocal */
+	int num_bits;
+	int shift;
+	int flags;
+	} BN_RECP_CTX;
+
 #define BN_to_montgomery(r,a,mont,ctx)	BN_mod_mul_montgomery(\
-	r,a,(mont)->RR,(mont),ctx)
+	r,a,&((mont)->RR),(mont),ctx)
 
 #define BN_prime_checks		(5)
 
 #define BN_num_bytes(a)	((BN_num_bits(a)+7)/8)
 #define BN_is_word(a,w)	(((a)->top == 1) && ((a)->d[0] == (BN_ULONG)(w)))
-#define BN_is_zero(a)	(((a)->top <= 1) && ((a)->d[0] == (BN_ULONG)0))
+#define BN_is_zero(a)	(((a)->top == 0) || BN_is_word(a,0))
 #define BN_is_one(a)	(BN_is_word((a),1))
-#define BN_is_odd(a)	((a)->d[0] & 1)
+#define BN_is_odd(a)	(((a)->top > 0) && ((a)->d[0] & 1))
 #define BN_one(a)	(BN_set_word((a),1))
 #define BN_zero(a)	(BN_set_word((a),0))
 
-#define BN_ascii2bn(a)	BN_hex2bn(a)
-#define BN_bn2ascii(a)	BN_bn2hex(a)
+/*#define BN_ascii2bn(a)	BN_hex2bn(a) */
+/*#define BN_bn2ascii(a)	BN_bn2hex(a) */
 
-#define bn_fix_top(a) \
-	{ \
-	BN_ULONG *fix_top_l; \
-	for (fix_top_l= &((a)->d[(a)->top-1]); (a)->top > 0; (a)->top--) \
-		if (*(fix_top_l--)) break; \
-	}
-
-#define bn_expand(n,b) ((((b)/BN_BITS2) <= (n)->max)?\
-	(n):bn_expand2((n),(b)/BN_BITS2))
+#define bn_expand(n,b) ((((((b+BN_BITS2-1))/BN_BITS2)) <= (n)->max)?\
+	(n):bn_expand2((n),(b)/BN_BITS2+1))
 #define bn_wexpand(n,b) (((b) <= (n)->max)?(n):bn_expand2((n),(b)))
 
+#define bn_fix_top(a) \
+        { \
+        BN_ULONG *ftl; \
+	if ((a)->top > 0) \
+		{ \
+		for (ftl= &((a)->d[(a)->top-1]); (a)->top > 0; (a)->top--) \
+		if (*(ftl--)) break; \
+		} \
+	}
 
 #ifndef NOPROTO
 BIGNUM *BN_value_one(void);
 char *	BN_options(void);
 BN_CTX *BN_CTX_new(void);
+void	BN_CTX_init(BN_CTX *c);
 void	BN_CTX_free(BN_CTX *c);
 int     BN_rand(BIGNUM *rnd, int bits, int top,int bottom);
 int	BN_num_bits(BIGNUM *a);
 int	BN_num_bits_word(BN_ULONG);
 BIGNUM *BN_new(void);
+void	BN_init(BIGNUM *);
 void	BN_clear_free(BIGNUM *a);
 BIGNUM *BN_copy(BIGNUM *a, BIGNUM *b);
 BIGNUM *BN_bin2bn(unsigned char *s,int len,BIGNUM *ret);
@@ -300,20 +339,20 @@
 BIGNUM *BN_mpi2bn(unsigned char *s,int len,BIGNUM *ret);
 int	BN_bn2mpi(BIGNUM *a, unsigned char *to);
 int	BN_sub(BIGNUM *r, BIGNUM *a, BIGNUM *b);
-void	bn_qsub(BIGNUM *r, BIGNUM *a, BIGNUM *b);
-void	bn_qadd(BIGNUM *r, BIGNUM *a, BIGNUM *b);
+int	BN_usub(BIGNUM *r, BIGNUM *a, BIGNUM *b);
+int	BN_uadd(BIGNUM *r, BIGNUM *a, BIGNUM *b);
 int	BN_add(BIGNUM *r, BIGNUM *a, BIGNUM *b);
 int	BN_mod(BIGNUM *rem, BIGNUM *m, BIGNUM *d, BN_CTX *ctx);
 int	BN_div(BIGNUM *dv, BIGNUM *rem, BIGNUM *m, BIGNUM *d, BN_CTX *ctx);
-int	BN_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b);
+int	BN_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b,BN_CTX *ctx);
 int	BN_sqr(BIGNUM *r, BIGNUM *a,BN_CTX *ctx);
-BN_ULONG BN_mod_word(BIGNUM *a, unsigned long w);
-BN_ULONG BN_div_word(BIGNUM *a, unsigned long w);
-int	BN_mul_word(BIGNUM *a, unsigned long w);
-int	BN_add_word(BIGNUM *a, unsigned long w);
-int	BN_sub_word(BIGNUM *a, unsigned long w);
-int	BN_set_word(BIGNUM *a, unsigned long w);
-unsigned long BN_get_word(BIGNUM *a);
+BN_ULONG BN_mod_word(BIGNUM *a, BN_ULONG w);
+BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w);
+int	BN_mul_word(BIGNUM *a, BN_ULONG w);
+int	BN_add_word(BIGNUM *a, BN_ULONG w);
+int	BN_sub_word(BIGNUM *a, BN_ULONG w);
+int	BN_set_word(BIGNUM *a, BN_ULONG w);
+BN_ULONG BN_get_word(BIGNUM *a);
 int	BN_cmp(BIGNUM *a, BIGNUM *b);
 void	BN_free(BIGNUM *a);
 int	BN_is_bit_set(BIGNUM *a, int n);
@@ -323,12 +362,11 @@
 int	BN_mod_exp(BIGNUM *r, BIGNUM *a, BIGNUM *p, BIGNUM *m,BN_CTX *ctx);
 int	BN_mod_exp_mont(BIGNUM *r, BIGNUM *a, BIGNUM *p, BIGNUM *m,BN_CTX *ctx,
 		BN_MONT_CTX *m_ctx);
-int	BN_mod_exp_recp(BIGNUM *r, BIGNUM *a, BIGNUM *p, BIGNUM *m,BN_CTX *ctx);
+int	BN_mod_exp2_mont(BIGNUM *r, BIGNUM *a1, BIGNUM *p1,BIGNUM *a2,
+		BIGNUM *p2,BIGNUM *m,BN_CTX *ctx,BN_MONT_CTX *m_ctx);
 int	BN_mod_exp_simple(BIGNUM *r, BIGNUM *a, BIGNUM *p,
 	BIGNUM *m,BN_CTX *ctx);
 int	BN_mask_bits(BIGNUM *a,int n);
-int	BN_mod_mul_reciprocal(BIGNUM *r, BIGNUM *x, BIGNUM *y, BIGNUM *m, 
-	BIGNUM *i, int nb, BN_CTX *ctx);
 int	BN_mod_mul(BIGNUM *ret, BIGNUM *a, BIGNUM *b, BIGNUM *m,
 	BN_CTX *ctx);
 #ifndef WIN16
@@ -339,7 +377,7 @@
 #else
 int	BN_print(char *fp, BIGNUM *a);
 #endif
-int	BN_reciprocal(BIGNUM *r, BIGNUM *m, BN_CTX *ctx);
+int	BN_reciprocal(BIGNUM *r, BIGNUM *m, int len, BN_CTX *ctx);
 int	BN_rshift(BIGNUM *r, BIGNUM *a, int n);
 int	BN_rshift1(BIGNUM *r, BIGNUM *a);
 void	BN_clear(BIGNUM *a);
@@ -353,8 +391,8 @@
 int 	BN_hex2bn(BIGNUM **a,char *str);
 int 	BN_dec2bn(BIGNUM **a,char *str);
 int	BN_gcd(BIGNUM *r,BIGNUM *in_a,BIGNUM *in_b,BN_CTX *ctx);
-BIGNUM *BN_mod_inverse(BIGNUM *a, BIGNUM *n,BN_CTX *ctx);
-BIGNUM *BN_generate_prime(int bits,int strong,BIGNUM *add,
+BIGNUM *BN_mod_inverse(BIGNUM *ret,BIGNUM *a, BIGNUM *n,BN_CTX *ctx);
+BIGNUM *BN_generate_prime(BIGNUM *ret,int bits,int strong,BIGNUM *add,
 		BIGNUM *rem,void (*callback)(int,int,char *),char *cb_arg);
 int	BN_is_prime(BIGNUM *p,int nchecks,void (*callback)(int,int,char *),
 		BN_CTX *ctx,char *cb_arg);
@@ -363,15 +401,18 @@
 BN_ULONG bn_mul_add_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w);
 BN_ULONG bn_mul_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w);
 void     bn_sqr_words(BN_ULONG *rp, BN_ULONG *ap, int num);
-BN_ULONG bn_div64(BN_ULONG h, BN_ULONG l, BN_ULONG d);
+BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d);
 BN_ULONG bn_add_words(BN_ULONG *rp, BN_ULONG *ap, BN_ULONG *bp,int num);
+BN_ULONG bn_sub_words(BN_ULONG *rp, BN_ULONG *ap, BN_ULONG *bp,int num);
 
 BN_MONT_CTX *BN_MONT_CTX_new(void );
+void BN_MONT_CTX_init(BN_MONT_CTX *ctx);
 int BN_mod_mul_montgomery(BIGNUM *r,BIGNUM *a,BIGNUM *b,BN_MONT_CTX *mont,
 	BN_CTX *ctx);
 int BN_from_montgomery(BIGNUM *r,BIGNUM *a,BN_MONT_CTX *mont,BN_CTX *ctx);
 void BN_MONT_CTX_free(BN_MONT_CTX *mont);
 int BN_MONT_CTX_set(BN_MONT_CTX *mont,BIGNUM *modulus,BN_CTX *ctx);
+BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to,BN_MONT_CTX *from);
 
 BN_BLINDING *BN_BLINDING_new(BIGNUM *A,BIGNUM *Ai,BIGNUM *mod);
 void BN_BLINDING_free(BN_BLINDING *b);
@@ -379,16 +420,45 @@
 int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *r, BN_CTX *ctx);
 int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx);
 
+void BN_set_params(int mul,int high,int low,int mont);
+int BN_get_params(int which); /* 0, mul, 1 high, 2 low, 3 mont */
+
+void bn_mul_normal(BN_ULONG *r,BN_ULONG *a,int na,BN_ULONG *b,int nb);
+void bn_mul_comba8(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b);
+void bn_mul_comba4(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b);
+void bn_sqr_normal(BN_ULONG *r, BN_ULONG *a, int n, BN_ULONG *tmp);
+void bn_sqr_comba8(BN_ULONG *r,BN_ULONG *a);
+void bn_sqr_comba4(BN_ULONG *r,BN_ULONG *a);
+int bn_cmp_words(BN_ULONG *a,BN_ULONG *b,int n);
+void bn_mul_recursive(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b,int n2,BN_ULONG *t);
+void bn_mul_part_recursive(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b,
+	int tn, int n,BN_ULONG *t);
+void bn_sqr_recursive(BN_ULONG *r,BN_ULONG *a, int n2, BN_ULONG *t);
+void bn_mul_low_normal(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b, int n);
+
+void	BN_RECP_CTX_init(BN_RECP_CTX *recp);
+BN_RECP_CTX *BN_RECP_CTX_new(void);
+void	BN_RECP_CTX_free(BN_RECP_CTX *recp);
+int	BN_RECP_CTX_set(BN_RECP_CTX *recp,BIGNUM *rdiv,BN_CTX *ctx);
+int	BN_mod_mul_reciprocal(BIGNUM *r, BIGNUM *x, BIGNUM *y,
+		BN_RECP_CTX *recp,BN_CTX *ctx);
+int	BN_mod_exp_recp(BIGNUM *r, BIGNUM *a, BIGNUM *p, BIGNUM *m,BN_CTX *ctx);
+int	BN_div_recp(BIGNUM *dv, BIGNUM *rem, BIGNUM *m,
+		BN_RECP_CTX *recp, BN_CTX *ctx);
+
+
 #else
 
 BIGNUM *BN_value_one();
 char *	BN_options();
 BN_CTX *BN_CTX_new();
+void	BN_CTX_init();
 void	BN_CTX_free();
 int     BN_rand();
 int	BN_num_bits();
 int	BN_num_bits_word();
 BIGNUM *BN_new();
+void	BN_init();
 void	BN_clear_free();
 BIGNUM *BN_copy();
 BIGNUM *BN_bin2bn();
@@ -396,8 +466,8 @@
 BIGNUM *BN_mpi2bn();
 int	BN_bn2mpi();
 int	BN_sub();
-void	bn_qsub();
-void	bn_qadd();
+int	BN_usub();
+int	BN_uadd();
 int	BN_add();
 int	BN_mod();
 int	BN_div();
@@ -449,12 +519,14 @@
 BN_ULONG bn_mul_add_words();
 BN_ULONG bn_mul_words();
 void     bn_sqr_words();
-BN_ULONG bn_div64();
+BN_ULONG bn_div_words();
 BN_ULONG bn_add_words();
+BN_ULONG bn_sub_words();
 
 int BN_mod_mul_montgomery();
 int BN_from_montgomery();
 BN_MONT_CTX *BN_MONT_CTX_new();
+void BN_MONT_CTX_init();
 void BN_MONT_CTX_free();
 int BN_MONT_CTX_set();
 
@@ -464,6 +536,26 @@
 int BN_BLINDING_convert();
 int BN_BLINDING_invert();
 
+void bn_mul_normal();
+void bn_mul_comba8();
+void bn_mul_comba4();
+void bn_sqr_normal();
+void bn_sqr_comba8();
+void bn_sqr_comba4();
+int bn_cmp_words();
+void bn_mul_recursive();
+void bn_mul_part_recursive();
+void bn_sqr_recursive();
+void bn_mul_low_normal();
+
+void	BN_RECP_CTX_init();
+BN_RECP_CTX *BN_RECP_CTX_new();
+void	BN_RECP_CTX_free();
+int	BN_RECP_CTX_set();
+int	BN_mod_mul_reciprocal();
+int	BN_mod_exp_recp();
+int	BN_div_recp();
+
 #endif
 
 /* BEGIN ERROR CODES */
@@ -485,15 +577,18 @@
 #define BN_F_BN_MPI2BN					 112
 #define BN_F_BN_NEW					 113
 #define BN_F_BN_RAND					 114
+#define BN_F_BN_USUB					 115
 
 /* Reason codes. */
-#define BN_R_BAD_RECIPROCAL				 100
-#define BN_R_CALLED_WITH_EVEN_MODULUS			 101
-#define BN_R_DIV_BY_ZERO				 102
-#define BN_R_ENCODING_ERROR				 103
-#define BN_R_INVALID_LENGTH				 104
-#define BN_R_NOT_INITALISED				 105
-#define BN_R_NO_INVERSE					 106
+#define BN_R_ARG2_LT_ARG3				 100
+#define BN_R_BAD_RECIPROCAL				 101
+#define BN_R_CALLED_WITH_EVEN_MODULUS			 102
+#define BN_R_DIV_BY_ZERO				 103
+#define BN_R_ENCODING_ERROR				 104
+#define BN_R_EXPAND_ON_STATIC_BIGNUM_DATA		 105
+#define BN_R_INVALID_LENGTH				 106
+#define BN_R_NOT_INITALISED				 107
+#define BN_R_NO_INVERSE					 108
  
 #ifdef  __cplusplus
 }
diff --git a/crypto/bn/bn_add.c b/crypto/bn/bn_add.c
index efb2e31..27b781a 100644
--- a/crypto/bn/bn_add.c
+++ b/crypto/bn/bn_add.c
@@ -66,9 +66,11 @@
 BIGNUM *a;
 BIGNUM *b;
 	{
-	int i;
 	BIGNUM *tmp;
 
+	bn_check_top(a);
+	bn_check_top(b);
+
 	/*  a +  b	a+b
 	 *  a + -b	a-b
 	 * -a +  b	b-a
@@ -84,14 +86,12 @@
 
 		if (BN_ucmp(a,b) < 0)
 			{
-			if (bn_wexpand(r,b->top) == NULL) return(0);
-			bn_qsub(r,b,a);
+			if (!BN_usub(r,b,a)) return(0);
 			r->neg=1;
 			}
 		else
 			{
-			if (bn_wexpand(r,a->top) == NULL) return(0);
-			bn_qsub(r,a,b);
+			if (!BN_usub(r,a,b)) return(0);
 			r->neg=0;
 			}
 		return(1);
@@ -102,23 +102,12 @@
 	else
 		r->neg=0;
 
-	i=(a->top > b->top);
-
-	if (i)
-		{
-		if (bn_wexpand(r,a->top+1) == NULL) return(0);
-		bn_qadd(r,a,b);
-		}
-	else
-		{
-		if (bn_wexpand(r,b->top+1) == NULL) return(0);
-		bn_qadd(r,b,a);
-		}
+	if (!BN_uadd(r,a,b)) return(0);
 	return(1);
 	}
 
 /* unsigned add of b to a, r must be large enough */
-void bn_qadd(r,a,b)
+int BN_uadd(r,a,b)
 BIGNUM *r;
 BIGNUM *a;
 BIGNUM *b;
@@ -126,11 +115,22 @@
 	register int i;
 	int max,min;
 	BN_ULONG *ap,*bp,*rp,carry,t1;
+	BIGNUM *tmp;
 
+	bn_check_top(a);
+	bn_check_top(b);
+
+	if (a->top < b->top)
+		{ tmp=a; a=b; b=tmp; }
 	max=a->top;
 	min=b->top;
+
+	if (bn_wexpand(r,max+1) == NULL)
+		return(0);
+
 	r->top=max;
 
+
 	ap=a->d;
 	bp=b->d;
 	rp=r->d;
@@ -160,8 +160,160 @@
 			r->top++;
 			}
 		}
-	for (; i<max; i++)
-		*(rp++)= *(ap++);
+	if (rp != ap)
+		{
+		for (; i<max; i++)
+			*(rp++)= *(ap++);
+		}
 	/* memcpy(rp,ap,sizeof(*ap)*(max-i));*/
+	return(1);
+	}
+
+/* unsigned subtraction of b from a, a must be larger than b. */
+int BN_usub(r, a, b)
+BIGNUM *r;
+BIGNUM *a;
+BIGNUM *b;
+	{
+	int max,min,ret=1;
+	register BN_ULONG t1,t2,*ap,*bp,*rp;
+	int i,carry;
+#if defined(IRIX_CC_BUG) && !defined(LINT)
+	int dummy;
+#endif
+
+	bn_check_top(a);
+	bn_check_top(b);
+
+	if (a->top < b->top) /* hmm... should not be happening */
+		{
+		BNerr(BN_F_BN_USUB,BN_R_ARG2_LT_ARG3);
+		return(0);
+		}
+
+	max=a->top;
+	min=b->top;
+	if (bn_wexpand(r,max) == NULL) return(0);
+
+	ap=a->d;
+	bp=b->d;
+	rp=r->d;
+
+#if 1
+	carry=0;
+	for (i=0; i<min; i++)
+		{
+		t1= *(ap++);
+		t2= *(bp++);
+		if (carry)
+			{
+			carry=(t1 <= t2);
+			t1=(t1-t2-1)&BN_MASK2;
+			}
+		else
+			{
+			carry=(t1 < t2);
+			t1=(t1-t2)&BN_MASK2;
+			}
+#if defined(IRIX_CC_BUG) && !defined(LINT)
+		dummy=t1;
+#endif
+		*(rp++)=t1&BN_MASK2;
+		}
+#else
+	carry=bn_sub_words(rp,ap,bp,min);
+	ap+=min;
+	bp+=min;
+	rp+=min;
+	i=min;
+#endif
+	if (carry) /* subtracted */
+		{
+		while (i < max)
+			{
+			i++;
+			t1= *(ap++);
+			t2=(t1-1)&BN_MASK2;
+			*(rp++)=t2;
+			if (t1 > t2) break;
+			}
+		}
+#if 0
+	memcpy(rp,ap,sizeof(*rp)*(max-i));
+#else
+	if (rp != ap)
+		{
+		for (;;)
+			{
+			if (i++ >= max) break;
+			rp[0]=ap[0];
+			if (i++ >= max) break;
+			rp[1]=ap[1];
+			if (i++ >= max) break;
+			rp[2]=ap[2];
+			if (i++ >= max) break;
+			rp[3]=ap[3];
+			rp+=4;
+			ap+=4;
+			}
+		}
+#endif
+
+	r->top=max;
+	bn_fix_top(r);
+	return(1);
+	}
+
+int BN_sub(r, a, b)
+BIGNUM *r;
+BIGNUM *a;
+BIGNUM *b;
+	{
+	int max;
+	int add=0,neg=0;
+	BIGNUM *tmp;
+
+	bn_check_top(a);
+	bn_check_top(b);
+
+	/*  a -  b	a-b
+	 *  a - -b	a+b
+	 * -a -  b	-(a+b)
+	 * -a - -b	b-a
+	 */
+	if (a->neg)
+		{
+		if (b->neg)
+			{ tmp=a; a=b; b=tmp; }
+		else
+			{ add=1; neg=1; }
+		}
+	else
+		{
+		if (b->neg) { add=1; neg=0; }
+		}
+
+	if (add)
+		{
+		if (!BN_uadd(r,a,b)) return(0);
+		r->neg=neg;
+		return(1);
+		}
+
+	/* We are actually doing a - b :-) */
+
+	max=(a->top > b->top)?a->top:b->top;
+	if (bn_wexpand(r,max) == NULL) return(0);
+	if (BN_ucmp(a,b) < 0)
+		{
+		if (!BN_usub(r,b,a)) return(0);
+		r->neg=1;
+		}
+	else
+		{
+		if (!BN_usub(r,a,b)) return(0);
+		r->neg=0;
+		}
+	return(1);
 	}
 
diff --git a/crypto/bn/bn_asm.c b/crypto/bn/bn_asm.c
new file mode 100644
index 0000000..c9eb0e9
--- /dev/null
+++ b/crypto/bn/bn_asm.c
@@ -0,0 +1,829 @@
+/* crypto/bn/bn_asm.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 "cryptlib.h"
+#include "bn_lcl.h"
+
+#ifdef BN_LLONG 
+
+BN_ULONG bn_mul_add_words(rp,ap,num,w)
+BN_ULONG *rp,*ap;
+int num;
+BN_ULONG w;
+	{
+	BN_ULONG c1=0;
+
+	bn_check_num(num);
+	if (num <= 0) return(c1);
+
+	for (;;)
+		{
+		mul_add(rp[0],ap[0],w,c1);
+		if (--num == 0) break;
+		mul_add(rp[1],ap[1],w,c1);
+		if (--num == 0) break;
+		mul_add(rp[2],ap[2],w,c1);
+		if (--num == 0) break;
+		mul_add(rp[3],ap[3],w,c1);
+		if (--num == 0) break;
+		ap+=4;
+		rp+=4;
+		}
+	
+	return(c1);
+	} 
+
+BN_ULONG bn_mul_words(rp,ap,num,w)
+BN_ULONG *rp,*ap;
+int num;
+BN_ULONG w;
+	{
+	BN_ULONG c1=0;
+
+	bn_check_num(num);
+	if (num <= 0) return(c1);
+
+	for (;;)
+		{
+		mul(rp[0],ap[0],w,c1);
+		if (--num == 0) break;
+		mul(rp[1],ap[1],w,c1);
+		if (--num == 0) break;
+		mul(rp[2],ap[2],w,c1);
+		if (--num == 0) break;
+		mul(rp[3],ap[3],w,c1);
+		if (--num == 0) break;
+		ap+=4;
+		rp+=4;
+		}
+	return(c1);
+	} 
+
+void bn_sqr_words(r,a,n)
+BN_ULONG *r,*a;
+int n;
+        {
+	bn_check_num(n);
+	if (n <= 0) return;
+	for (;;)
+		{
+		BN_ULLONG t;
+
+		t=(BN_ULLONG)(a[0])*(a[0]);
+		r[0]=Lw(t); r[1]=Hw(t);
+		if (--n == 0) break;
+
+		t=(BN_ULLONG)(a[1])*(a[1]);
+		r[2]=Lw(t); r[3]=Hw(t);
+		if (--n == 0) break;
+
+		t=(BN_ULLONG)(a[2])*(a[2]);
+		r[4]=Lw(t); r[5]=Hw(t);
+		if (--n == 0) break;
+
+		t=(BN_ULLONG)(a[3])*(a[3]);
+		r[6]=Lw(t); r[7]=Hw(t);
+		if (--n == 0) break;
+
+		a+=4;
+		r+=8;
+		}
+	}
+
+#else
+
+BN_ULONG bn_mul_add_words(rp,ap,num,w)
+BN_ULONG *rp,*ap;
+int num;
+BN_ULONG w;
+	{
+	BN_ULONG c=0;
+	BN_ULONG bl,bh;
+
+	bn_check_num(num);
+	if (num <= 0) return((BN_ULONG)0);
+
+	bl=LBITS(w);
+	bh=HBITS(w);
+
+	for (;;)
+		{
+		mul_add(rp[0],ap[0],bl,bh,c);
+		if (--num == 0) break;
+		mul_add(rp[1],ap[1],bl,bh,c);
+		if (--num == 0) break;
+		mul_add(rp[2],ap[2],bl,bh,c);
+		if (--num == 0) break;
+		mul_add(rp[3],ap[3],bl,bh,c);
+		if (--num == 0) break;
+		ap+=4;
+		rp+=4;
+		}
+	return(c);
+	} 
+
+BN_ULONG bn_mul_words(rp,ap,num,w)
+BN_ULONG *rp,*ap;
+int num;
+BN_ULONG w;
+	{
+	BN_ULONG carry=0;
+	BN_ULONG bl,bh;
+
+	bn_check_num(num);
+	if (num <= 0) return((BN_ULONG)0);
+
+	bl=LBITS(w);
+	bh=HBITS(w);
+
+	for (;;)
+		{
+		mul(rp[0],ap[0],bl,bh,carry);
+		if (--num == 0) break;
+		mul(rp[1],ap[1],bl,bh,carry);
+		if (--num == 0) break;
+		mul(rp[2],ap[2],bl,bh,carry);
+		if (--num == 0) break;
+		mul(rp[3],ap[3],bl,bh,carry);
+		if (--num == 0) break;
+		ap+=4;
+		rp+=4;
+		}
+	return(carry);
+	} 
+
+void bn_sqr_words(r,a,n)
+BN_ULONG *r,*a;
+int n;
+        {
+	bn_check_num(n);
+	if (n <= 0) return;
+	for (;;)
+		{
+		sqr64(r[0],r[1],a[0]);
+		if (--n == 0) break;
+
+		sqr64(r[2],r[3],a[1]);
+		if (--n == 0) break;
+
+		sqr64(r[4],r[5],a[2]);
+		if (--n == 0) break;
+
+		sqr64(r[6],r[7],a[3]);
+		if (--n == 0) break;
+
+		a+=4;
+		r+=8;
+		}
+	}
+
+#endif
+
+#if defined(BN_LLONG) && defined(BN_DIV2W)
+
+BN_ULONG bn_div_words(h,l,d)
+BN_ULONG h,l,d;
+	{
+	return((BN_ULONG)(((((BN_ULLONG)h)<<BN_BITS2)|l)/(BN_ULLONG)d));
+	}
+
+#else
+
+/* Divide h-l by d and return the result. */
+/* I need to test this some more :-( */
+BN_ULONG bn_div_words(h,l,d)
+BN_ULONG h,l,d;
+	{
+	BN_ULONG dh,dl,q,ret=0,th,tl,t;
+	int i,count=2;
+
+	if (d == 0) return(BN_MASK2);
+
+	i=BN_num_bits_word(d);
+	if ((i != BN_BITS2) && (h > (BN_ULONG)1<<i))
+		{
+#if !defined(NO_STDIO) && !defined(WIN16)
+		fprintf(stderr,"Division would overflow (%d)\n",i);
+#endif
+		abort();
+		}
+	i=BN_BITS2-i;
+	if (h >= d) h-=d;
+
+	if (i)
+		{
+		d<<=i;
+		h=(h<<i)|(l>>(BN_BITS2-i));
+		l<<=i;
+		}
+	dh=(d&BN_MASK2h)>>BN_BITS4;
+	dl=(d&BN_MASK2l);
+	for (;;)
+		{
+		if ((h>>BN_BITS4) == dh)
+			q=BN_MASK2l;
+		else
+			q=h/dh;
+
+		for (;;)
+			{
+			t=(h-q*dh);
+			if ((t&BN_MASK2h) ||
+				((dl*q) <= (
+					(t<<BN_BITS4)+
+					((l&BN_MASK2h)>>BN_BITS4))))
+				break;
+			q--;
+			}
+		th=q*dh;
+		tl=q*dl;
+		t=(tl>>BN_BITS4);
+		tl=(tl<<BN_BITS4)&BN_MASK2h;
+		th+=t;
+
+		if (l < tl) th++;
+		l-=tl;
+		if (h < th)
+			{
+			h+=d;
+			q--;
+			}
+		h-=th;
+
+		if (--count == 0) break;
+
+		ret=q<<BN_BITS4;
+		h=((h<<BN_BITS4)|(l>>BN_BITS4))&BN_MASK2;
+		l=(l&BN_MASK2l)<<BN_BITS4;
+		}
+	ret|=q;
+	return(ret);
+	}
+#endif
+
+#ifdef BN_LLONG
+BN_ULONG bn_add_words(r,a,b,n)
+BN_ULONG *r,*a,*b;
+int n;
+        {
+	BN_ULLONG ll=0;
+
+	bn_check_num(n);
+	if (n <= 0) return((BN_ULONG)0);
+
+	for (;;)
+		{
+		ll+=(BN_ULLONG)a[0]+b[0];
+		r[0]=(BN_ULONG)ll&BN_MASK2;
+		ll>>=BN_BITS2;
+		if (--n <= 0) break;
+
+		ll+=(BN_ULLONG)a[1]+b[1];
+		r[1]=(BN_ULONG)ll&BN_MASK2;
+		ll>>=BN_BITS2;
+		if (--n <= 0) break;
+
+		ll+=(BN_ULLONG)a[2]+b[2];
+		r[2]=(BN_ULONG)ll&BN_MASK2;
+		ll>>=BN_BITS2;
+		if (--n <= 0) break;
+
+		ll+=(BN_ULLONG)a[3]+b[3];
+		r[3]=(BN_ULONG)ll&BN_MASK2;
+		ll>>=BN_BITS2;
+		if (--n <= 0) break;
+
+		a+=4;
+		b+=4;
+		r+=4;
+		}
+	return((BN_ULONG)ll);
+	}
+#else
+BN_ULONG bn_add_words(r,a,b,n)
+BN_ULONG *r,*a,*b;
+int n;
+        {
+	BN_ULONG c,l,t;
+
+	bn_check_num(n);
+	if (n <= 0) return((BN_ULONG)0);
+
+	c=0;
+	for (;;)
+		{
+		t=a[0];
+		t=(t+c)&BN_MASK2;
+		c=(t < c);
+		l=(t+b[0])&BN_MASK2;
+		c+=(l < t);
+		r[0]=l;
+		if (--n <= 0) break;
+
+		t=a[1];
+		t=(t+c)&BN_MASK2;
+		c=(t < c);
+		l=(t+b[1])&BN_MASK2;
+		c+=(l < t);
+		r[1]=l;
+		if (--n <= 0) break;
+
+		t=a[2];
+		t=(t+c)&BN_MASK2;
+		c=(t < c);
+		l=(t+b[2])&BN_MASK2;
+		c+=(l < t);
+		r[2]=l;
+		if (--n <= 0) break;
+
+		t=a[3];
+		t=(t+c)&BN_MASK2;
+		c=(t < c);
+		l=(t+b[3])&BN_MASK2;
+		c+=(l < t);
+		r[3]=l;
+		if (--n <= 0) break;
+
+		a+=4;
+		b+=4;
+		r+=4;
+		}
+	return((BN_ULONG)c);
+	}
+#endif
+
+BN_ULONG bn_sub_words(r,a,b,n)
+BN_ULONG *r,*a,*b;
+int n;
+        {
+	BN_ULONG t1,t2;
+	int c=0;
+
+	bn_check_num(n);
+	if (n <= 0) return((BN_ULONG)0);
+
+	for (;;)
+		{
+		t1=a[0]; t2=b[0];
+		r[0]=(t1-t2-c)&BN_MASK2;
+		if (t1 != t2) c=(t1 < t2);
+		if (--n <= 0) break;
+
+		t1=a[1]; t2=b[1];
+		r[1]=(t1-t2-c)&BN_MASK2;
+		if (t1 != t2) c=(t1 < t2);
+		if (--n <= 0) break;
+
+		t1=a[2]; t2=b[2];
+		r[2]=(t1-t2-c)&BN_MASK2;
+		if (t1 != t2) c=(t1 < t2);
+		if (--n <= 0) break;
+
+		t1=a[3]; t2=b[3];
+		r[3]=(t1-t2-c)&BN_MASK2;
+		if (t1 != t2) c=(t1 < t2);
+		if (--n <= 0) break;
+
+		a+=4;
+		b+=4;
+		r+=4;
+		}
+	return(c);
+	}
+
+#ifdef BN_COMBA
+
+#undef bn_mul_comba8
+#undef bn_mul_comba4
+#undef bn_sqr_comba8
+#undef bn_sqr_comba4
+
+#ifdef BN_LLONG
+#define mul_add_c(a,b,c0,c1,c2) \
+	t=(BN_ULLONG)a*b; \
+	t1=(BN_ULONG)Lw(t); \
+	t2=(BN_ULONG)Hw(t); \
+	c0=(c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \
+	c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++;
+
+#define mul_add_c2(a,b,c0,c1,c2) \
+	t=(BN_ULLONG)a*b; \
+	tt=(t+t)&BN_MASK; \
+	if (tt < t) c2++; \
+	t1=(BN_ULONG)Lw(tt); \
+	t2=(BN_ULONG)Hw(tt); \
+	c0=(c0+t1)&BN_MASK2;  \
+	if ((c0 < t1) && (((++t2)&BN_MASK2) == 0)) c2++; \
+	c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++;
+
+#define sqr_add_c(a,i,c0,c1,c2) \
+	t=(BN_ULLONG)a[i]*a[i]; \
+	t1=(BN_ULONG)Lw(t); \
+	t2=(BN_ULONG)Hw(t); \
+	c0=(c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \
+	c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++;
+
+#define sqr_add_c2(a,i,j,c0,c1,c2) \
+	mul_add_c2((a)[i],(a)[j],c0,c1,c2)
+#else
+#define mul_add_c(a,b,c0,c1,c2) \
+	t1=LBITS(a); t2=HBITS(a); \
+	bl=LBITS(b); bh=HBITS(b); \
+	mul64(t1,t2,bl,bh); \
+	c0=(c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \
+	c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++;
+
+#define mul_add_c2(a,b,c0,c1,c2) \
+	t1=LBITS(a); t2=HBITS(a); \
+	bl=LBITS(b); bh=HBITS(b); \
+	mul64(t1,t2,bl,bh); \
+	if (t2 & BN_TBIT) c2++; \
+	t2=(t2+t2)&BN_MASK2; \
+	if (t1 & BN_TBIT) t2++; \
+	t1=(t1+t1)&BN_MASK2; \
+	c0=(c0+t1)&BN_MASK2;  \
+	if ((c0 < t1) && (((++t2)&BN_MASK2) == 0)) c2++; \
+	c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++;
+
+#define sqr_add_c(a,i,c0,c1,c2) \
+	sqr64(t1,t2,(a)[i]); \
+	c0=(c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \
+	c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++;
+
+#define sqr_add_c2(a,i,j,c0,c1,c2) \
+	mul_add_c2((a)[i],(a)[j],c0,c1,c2)
+#endif
+
+void bn_mul_comba8(r,a,b)
+BN_ULONG *r,*a,*b;
+	{
+#ifdef BN_LLONG
+	BN_ULLONG t;
+#else
+	BN_ULONG bl,bh;
+#endif
+	BN_ULONG t1,t2;
+	BN_ULONG c1,c2,c3;
+
+	c1=0;
+	c2=0;
+	c3=0;
+	mul_add_c(a[0],b[0],c1,c2,c3);
+	r[0]=c1;
+	c1=0;
+	mul_add_c(a[0],b[1],c2,c3,c1);
+	mul_add_c(a[1],b[0],c2,c3,c1);
+	r[1]=c2;
+	c2=0;
+	mul_add_c(a[2],b[0],c3,c1,c2);
+	mul_add_c(a[1],b[1],c3,c1,c2);
+	mul_add_c(a[0],b[2],c3,c1,c2);
+	r[2]=c3;
+	c3=0;
+	mul_add_c(a[0],b[3],c1,c2,c3);
+	mul_add_c(a[1],b[2],c1,c2,c3);
+	mul_add_c(a[2],b[1],c1,c2,c3);
+	mul_add_c(a[3],b[0],c1,c2,c3);
+	r[3]=c1;
+	c1=0;
+	mul_add_c(a[4],b[0],c2,c3,c1);
+	mul_add_c(a[3],b[1],c2,c3,c1);
+	mul_add_c(a[2],b[2],c2,c3,c1);
+	mul_add_c(a[1],b[3],c2,c3,c1);
+	mul_add_c(a[0],b[4],c2,c3,c1);
+	r[4]=c2;
+	c2=0;
+	mul_add_c(a[0],b[5],c3,c1,c2);
+	mul_add_c(a[1],b[4],c3,c1,c2);
+	mul_add_c(a[2],b[3],c3,c1,c2);
+	mul_add_c(a[3],b[2],c3,c1,c2);
+	mul_add_c(a[4],b[1],c3,c1,c2);
+	mul_add_c(a[5],b[0],c3,c1,c2);
+	r[5]=c3;
+	c3=0;
+	mul_add_c(a[6],b[0],c1,c2,c3);
+	mul_add_c(a[5],b[1],c1,c2,c3);
+	mul_add_c(a[4],b[2],c1,c2,c3);
+	mul_add_c(a[3],b[3],c1,c2,c3);
+	mul_add_c(a[2],b[4],c1,c2,c3);
+	mul_add_c(a[1],b[5],c1,c2,c3);
+	mul_add_c(a[0],b[6],c1,c2,c3);
+	r[6]=c1;
+	c1=0;
+	mul_add_c(a[0],b[7],c2,c3,c1);
+	mul_add_c(a[1],b[6],c2,c3,c1);
+	mul_add_c(a[2],b[5],c2,c3,c1);
+	mul_add_c(a[3],b[4],c2,c3,c1);
+	mul_add_c(a[4],b[3],c2,c3,c1);
+	mul_add_c(a[5],b[2],c2,c3,c1);
+	mul_add_c(a[6],b[1],c2,c3,c1);
+	mul_add_c(a[7],b[0],c2,c3,c1);
+	r[7]=c2;
+	c2=0;
+	mul_add_c(a[7],b[1],c3,c1,c2);
+	mul_add_c(a[6],b[2],c3,c1,c2);
+	mul_add_c(a[5],b[3],c3,c1,c2);
+	mul_add_c(a[4],b[4],c3,c1,c2);
+	mul_add_c(a[3],b[5],c3,c1,c2);
+	mul_add_c(a[2],b[6],c3,c1,c2);
+	mul_add_c(a[1],b[7],c3,c1,c2);
+	r[8]=c3;
+	c3=0;
+	mul_add_c(a[2],b[7],c1,c2,c3);
+	mul_add_c(a[3],b[6],c1,c2,c3);
+	mul_add_c(a[4],b[5],c1,c2,c3);
+	mul_add_c(a[5],b[4],c1,c2,c3);
+	mul_add_c(a[6],b[3],c1,c2,c3);
+	mul_add_c(a[7],b[2],c1,c2,c3);
+	r[9]=c1;
+	c1=0;
+	mul_add_c(a[7],b[3],c2,c3,c1);
+	mul_add_c(a[6],b[4],c2,c3,c1);
+	mul_add_c(a[5],b[5],c2,c3,c1);
+	mul_add_c(a[4],b[6],c2,c3,c1);
+	mul_add_c(a[3],b[7],c2,c3,c1);
+	r[10]=c2;
+	c2=0;
+	mul_add_c(a[4],b[7],c3,c1,c2);
+	mul_add_c(a[5],b[6],c3,c1,c2);
+	mul_add_c(a[6],b[5],c3,c1,c2);
+	mul_add_c(a[7],b[4],c3,c1,c2);
+	r[11]=c3;
+	c3=0;
+	mul_add_c(a[7],b[5],c1,c2,c3);
+	mul_add_c(a[6],b[6],c1,c2,c3);
+	mul_add_c(a[5],b[7],c1,c2,c3);
+	r[12]=c1;
+	c1=0;
+	mul_add_c(a[6],b[7],c2,c3,c1);
+	mul_add_c(a[7],b[6],c2,c3,c1);
+	r[13]=c2;
+	c2=0;
+	mul_add_c(a[7],b[7],c3,c1,c2);
+	r[14]=c3;
+	r[15]=c1;
+	}
+
+void bn_mul_comba4(r,a,b)
+BN_ULONG *r,*a,*b;
+	{
+#ifdef BN_LLONG
+	BN_ULLONG t;
+#else
+	BN_ULONG bl,bh;
+#endif
+	BN_ULONG t1,t2;
+	BN_ULONG c1,c2,c3;
+
+	c1=0;
+	c2=0;
+	c3=0;
+	mul_add_c(a[0],b[0],c1,c2,c3);
+	r[0]=c1;
+	c1=0;
+	mul_add_c(a[0],b[1],c2,c3,c1);
+	mul_add_c(a[1],b[0],c2,c3,c1);
+	r[1]=c2;
+	c2=0;
+	mul_add_c(a[2],b[0],c3,c1,c2);
+	mul_add_c(a[1],b[1],c3,c1,c2);
+	mul_add_c(a[0],b[2],c3,c1,c2);
+	r[2]=c3;
+	c3=0;
+	mul_add_c(a[0],b[3],c1,c2,c3);
+	mul_add_c(a[1],b[2],c1,c2,c3);
+	mul_add_c(a[2],b[1],c1,c2,c3);
+	mul_add_c(a[3],b[0],c1,c2,c3);
+	r[3]=c1;
+	c1=0;
+	mul_add_c(a[3],b[1],c2,c3,c1);
+	mul_add_c(a[2],b[2],c2,c3,c1);
+	mul_add_c(a[1],b[3],c2,c3,c1);
+	r[4]=c2;
+	c2=0;
+	mul_add_c(a[2],b[3],c3,c1,c2);
+	mul_add_c(a[3],b[2],c3,c1,c2);
+	r[5]=c3;
+	c3=0;
+	mul_add_c(a[3],b[3],c1,c2,c3);
+	r[6]=c1;
+	r[7]=c2;
+	}
+
+void bn_sqr_comba8(r,a)
+BN_ULONG *r,*a;
+	{
+#ifdef BN_LLONG
+	BN_ULLONG t,tt;
+#else
+	BN_ULONG bl,bh;
+#endif
+	BN_ULONG t1,t2;
+	BN_ULONG c1,c2,c3;
+
+	c1=0;
+	c2=0;
+	c3=0;
+	sqr_add_c(a,0,c1,c2,c3);
+	r[0]=c1;
+	c1=0;
+	sqr_add_c2(a,1,0,c2,c3,c1);
+	r[1]=c2;
+	c2=0;
+	sqr_add_c(a,1,c3,c1,c2);
+	sqr_add_c2(a,2,0,c3,c1,c2);
+	r[2]=c3;
+	c3=0;
+	sqr_add_c2(a,3,0,c1,c2,c3);
+	sqr_add_c2(a,2,1,c1,c2,c3);
+	r[3]=c1;
+	c1=0;
+	sqr_add_c(a,2,c2,c3,c1);
+	sqr_add_c2(a,3,1,c2,c3,c1);
+	sqr_add_c2(a,4,0,c2,c3,c1);
+	r[4]=c2;
+	c2=0;
+	sqr_add_c2(a,5,0,c3,c1,c2);
+	sqr_add_c2(a,4,1,c3,c1,c2);
+	sqr_add_c2(a,3,2,c3,c1,c2);
+	r[5]=c3;
+	c3=0;
+	sqr_add_c(a,3,c1,c2,c3);
+	sqr_add_c2(a,4,2,c1,c2,c3);
+	sqr_add_c2(a,5,1,c1,c2,c3);
+	sqr_add_c2(a,6,0,c1,c2,c3);
+	r[6]=c1;
+	c1=0;
+	sqr_add_c2(a,7,0,c2,c3,c1);
+	sqr_add_c2(a,6,1,c2,c3,c1);
+	sqr_add_c2(a,5,2,c2,c3,c1);
+	sqr_add_c2(a,4,3,c2,c3,c1);
+	r[7]=c2;
+	c2=0;
+	sqr_add_c(a,4,c3,c1,c2);
+	sqr_add_c2(a,5,3,c3,c1,c2);
+	sqr_add_c2(a,6,2,c3,c1,c2);
+	sqr_add_c2(a,7,1,c3,c1,c2);
+	r[8]=c3;
+	c3=0;
+	sqr_add_c2(a,7,2,c1,c2,c3);
+	sqr_add_c2(a,6,3,c1,c2,c3);
+	sqr_add_c2(a,5,4,c1,c2,c3);
+	r[9]=c1;
+	c1=0;
+	sqr_add_c(a,5,c2,c3,c1);
+	sqr_add_c2(a,6,4,c2,c3,c1);
+	sqr_add_c2(a,7,3,c2,c3,c1);
+	r[10]=c2;
+	c2=0;
+	sqr_add_c2(a,7,4,c3,c1,c2);
+	sqr_add_c2(a,6,5,c3,c1,c2);
+	r[11]=c3;
+	c3=0;
+	sqr_add_c(a,6,c1,c2,c3);
+	sqr_add_c2(a,7,5,c1,c2,c3);
+	r[12]=c1;
+	c1=0;
+	sqr_add_c2(a,7,6,c2,c3,c1);
+	r[13]=c2;
+	c2=0;
+	sqr_add_c(a,7,c3,c1,c2);
+	r[14]=c3;
+	r[15]=c1;
+	}
+
+void bn_sqr_comba4(r,a)
+BN_ULONG *r,*a;
+	{
+#ifdef BN_LLONG
+	BN_ULLONG t,tt;
+#else
+	BN_ULONG bl,bh;
+#endif
+	BN_ULONG t1,t2;
+	BN_ULONG c1,c2,c3;
+
+	c1=0;
+	c2=0;
+	c3=0;
+	sqr_add_c(a,0,c1,c2,c3);
+	r[0]=c1;
+	c1=0;
+	sqr_add_c2(a,1,0,c2,c3,c1);
+	r[1]=c2;
+	c2=0;
+	sqr_add_c(a,1,c3,c1,c2);
+	sqr_add_c2(a,2,0,c3,c1,c2);
+	r[2]=c3;
+	c3=0;
+	sqr_add_c2(a,3,0,c1,c2,c3);
+	sqr_add_c2(a,2,1,c1,c2,c3);
+	r[3]=c1;
+	c1=0;
+	sqr_add_c(a,2,c2,c3,c1);
+	sqr_add_c2(a,3,1,c2,c3,c1);
+	r[4]=c2;
+	c2=0;
+	sqr_add_c2(a,3,2,c3,c1,c2);
+	r[5]=c3;
+	c3=0;
+	sqr_add_c(a,3,c1,c2,c3);
+	r[6]=c1;
+	r[7]=c2;
+	}
+#else
+
+/* hmm... is it faster just to do a multiply? */
+void bn_sqr_comba4(r,a)
+BN_ULONG *r,*a;
+	{
+	BN_ULONG t[8];
+	bn_sqr_normal(r,a,4,t);
+	}
+
+void bn_sqr_comba8(r,a)
+BN_ULONG *r,*a;
+	{
+	BN_ULONG t[16];
+	bn_sqr_normal(r,a,8,t);
+	}
+
+void bn_mul_comba4(r,a,b)
+BN_ULONG *r,*a,*b;
+	{
+	r[4]=bn_mul_words(    &(r[0]),a,4,b[0]);
+	r[5]=bn_mul_add_words(&(r[1]),a,4,b[1]);
+	r[6]=bn_mul_add_words(&(r[2]),a,4,b[2]);
+	r[7]=bn_mul_add_words(&(r[3]),a,4,b[3]);
+	}
+
+void bn_mul_comba8(r,a,b)
+BN_ULONG *r,*a,*b;
+	{
+	r[ 8]=bn_mul_words(    &(r[0]),a,8,b[0]);
+	r[ 9]=bn_mul_add_words(&(r[1]),a,8,b[1]);
+	r[10]=bn_mul_add_words(&(r[2]),a,8,b[2]);
+	r[11]=bn_mul_add_words(&(r[3]),a,8,b[3]);
+	r[12]=bn_mul_add_words(&(r[4]),a,8,b[4]);
+	r[13]=bn_mul_add_words(&(r[5]),a,8,b[5]);
+	r[14]=bn_mul_add_words(&(r[6]),a,8,b[6]);
+	r[15]=bn_mul_add_words(&(r[7]),a,8,b[7]);
+	}
+
+#endif /* BN_COMBA */
diff --git a/crypto/bn/bn_blind.c b/crypto/bn/bn_blind.c
index a7b34f0..35be32b 100644
--- a/crypto/bn/bn_blind.c
+++ b/crypto/bn/bn_blind.c
@@ -67,8 +67,14 @@
 	{
 	BN_BLINDING *ret=NULL;
 
+	bn_check_top(Ai);
+	bn_check_top(mod);
+
 	if ((ret=(BN_BLINDING *)Malloc(sizeof(BN_BLINDING))) == NULL)
+		{
 		BNerr(BN_F_BN_BLINDING_NEW,ERR_R_MALLOC_FAILURE);
+		return(NULL);
+		}
 	memset(ret,0,sizeof(BN_BLINDING));
 	if ((ret->A=BN_new()) == NULL) goto err;
 	if ((ret->Ai=BN_new()) == NULL) goto err;
@@ -78,7 +84,7 @@
 	return(ret);
 err:
 	if (ret != NULL) BN_BLINDING_free(ret);
-	return(ret);
+	return(NULL);
 	}
 
 void BN_BLINDING_free(r)
@@ -114,6 +120,8 @@
 BN_BLINDING *b;
 BN_CTX *ctx;
 	{
+	bn_check_top(n);
+
 	if ((b->A == NULL) || (b->Ai == NULL))
 		{
 		BNerr(BN_F_BN_BLINDING_CONVERT,BN_R_NOT_INITALISED);
@@ -128,6 +136,8 @@
 BN_CTX *ctx;
 	{
 	int ret;
+
+	bn_check_top(n);
 	if ((b->A == NULL) || (b->Ai == NULL))
 		{
 		BNerr(BN_F_BN_BLINDING_INVERT,BN_R_NOT_INITALISED);
diff --git a/crypto/bn/bn_comba.c b/crypto/bn/bn_comba.c
new file mode 100644
index 0000000..30357cf
--- /dev/null
+++ b/crypto/bn/bn_comba.c
@@ -0,0 +1,349 @@
+/* crypto/bn/bn_comba.c */
+#include <stdio.h>
+#include "bn_lcl.h"
+/* Auto generated from crypto/bn/comba.pl
+ */
+
+#undef bn_mul_comba8
+#undef bn_mul_comba4
+#undef bn_sqr_comba8
+#undef bn_sqr_comba4
+
+#ifdef BN_LLONG
+#define mul_add_c(a,b,c0,c1,c2) \
+	t=(BN_ULLONG)a*b; \
+	t1=(BN_ULONG)Lw(t); \
+	t2=(BN_ULONG)Hw(t); \
+	c0=(c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \
+	c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++;
+
+#define mul_add_c2(a,b,c0,c1,c2) \
+	t=(BN_ULLONG)a*b; \
+	tt=(t+t)&BN_MASK; \
+	if (tt < t) c2++; \
+	t1=(BN_ULONG)Lw(tt); \
+	t2=(BN_ULONG)Hw(tt); \
+	c0=(c0+t1)&BN_MASK2;  \
+	if ((c0 < t1) && (((++t2)&BN_MASK2) == 0)) c2++; \
+	c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++;
+
+#define sqr_add_c(a,i,c0,c1,c2) \
+	t=(BN_ULLONG)a[i]*a[i]; \
+	t1=(BN_ULONG)Lw(t); \
+	t2=(BN_ULONG)Hw(t); \
+	c0=(c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \
+	c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++;
+
+#define sqr_add_c2(a,i,j,c0,c1,c2) \
+	mul_add_c2((a)[i],(a)[j],c0,c1,c2)
+#else
+#define mul_add_c(a,b,c0,c1,c2) \
+	t1=LBITS(a); t2=HBITS(a); \
+	bl=LBITS(b); bh=HBITS(b); \
+	mul64(t1,t2,bl,bh); \
+	c0=(c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \
+	c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++;
+
+#define mul_add_c2(a,b,c0,c1,c2) \
+	t1=LBITS(a); t2=HBITS(a); \
+	bl=LBITS(b); bh=HBITS(b); \
+	mul64(t1,t2,bl,bh); \
+	if (t2 & BN_TBIT) c2++; \
+	t2=(t2+t2)&BN_MASK2; \
+	if (t1 & BN_TBIT) t2++; \
+	t1=(t1+t1)&BN_MASK2; \
+	c0=(c0+t1)&BN_MASK2;  \
+	if ((c0 < t1) && (((++t2)&BN_MASK2) == 0)) c2++; \
+	c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++;
+
+#define sqr_add_c(a,i,c0,c1,c2) \
+	sqr64(t1,t2,(a)[i]); \
+	c0=(c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \
+	c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++;
+
+#define sqr_add_c2(a,i,j,c0,c1,c2) \
+	mul_add_c2((a)[i],(a)[j],c0,c1,c2)
+#endif
+
+void bn_mul_comba88(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b);
+void bn_mul_comba44(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b);
+void bn_sqr_comba88(BN_ULONG *r,BN_ULONG *a);
+void bn_sqr_comba44(BN_ULONG *r,BN_ULONG *a);
+
+void bn_mul_comba88(r,a,b)
+BN_ULONG *r,*a,*b;
+	{
+#ifdef BN_LLONG
+	BN_ULLONG t;
+#else
+	BN_ULONG bl,bh;
+#endif
+	BN_ULONG t1,t2;
+	BN_ULONG c1,c2,c3;
+
+	c1=0;
+	c2=0;
+	c3=0;
+	mul_add_c(a[0],b[0],c1,c2,c3);
+	r[0]=c1;
+	c1=0;
+	mul_add_c(a[0],b[1],c2,c3,c1);
+	mul_add_c(a[1],b[0],c2,c3,c1);
+	r[1]=c2;
+	c2=0;
+	mul_add_c(a[2],b[0],c3,c1,c2);
+	mul_add_c(a[1],b[1],c3,c1,c2);
+	mul_add_c(a[0],b[2],c3,c1,c2);
+	r[2]=c3;
+	c3=0;
+	mul_add_c(a[0],b[3],c1,c2,c3);
+	mul_add_c(a[1],b[2],c1,c2,c3);
+	mul_add_c(a[2],b[1],c1,c2,c3);
+	mul_add_c(a[3],b[0],c1,c2,c3);
+	r[3]=c1;
+	c1=0;
+	mul_add_c(a[4],b[0],c2,c3,c1);
+	mul_add_c(a[3],b[1],c2,c3,c1);
+	mul_add_c(a[2],b[2],c2,c3,c1);
+	mul_add_c(a[1],b[3],c2,c3,c1);
+	mul_add_c(a[0],b[4],c2,c3,c1);
+	r[4]=c2;
+	c2=0;
+	mul_add_c(a[0],b[5],c3,c1,c2);
+	mul_add_c(a[1],b[4],c3,c1,c2);
+	mul_add_c(a[2],b[3],c3,c1,c2);
+	mul_add_c(a[3],b[2],c3,c1,c2);
+	mul_add_c(a[4],b[1],c3,c1,c2);
+	mul_add_c(a[5],b[0],c3,c1,c2);
+	r[5]=c3;
+	c3=0;
+	mul_add_c(a[6],b[0],c1,c2,c3);
+	mul_add_c(a[5],b[1],c1,c2,c3);
+	mul_add_c(a[4],b[2],c1,c2,c3);
+	mul_add_c(a[3],b[3],c1,c2,c3);
+	mul_add_c(a[2],b[4],c1,c2,c3);
+	mul_add_c(a[1],b[5],c1,c2,c3);
+	mul_add_c(a[0],b[6],c1,c2,c3);
+	r[6]=c1;
+	c1=0;
+	mul_add_c(a[0],b[7],c2,c3,c1);
+	mul_add_c(a[1],b[6],c2,c3,c1);
+	mul_add_c(a[2],b[5],c2,c3,c1);
+	mul_add_c(a[3],b[4],c2,c3,c1);
+	mul_add_c(a[4],b[3],c2,c3,c1);
+	mul_add_c(a[5],b[2],c2,c3,c1);
+	mul_add_c(a[6],b[1],c2,c3,c1);
+	mul_add_c(a[7],b[0],c2,c3,c1);
+	r[7]=c2;
+	c2=0;
+	mul_add_c(a[7],b[1],c3,c1,c2);
+	mul_add_c(a[6],b[2],c3,c1,c2);
+	mul_add_c(a[5],b[3],c3,c1,c2);
+	mul_add_c(a[4],b[4],c3,c1,c2);
+	mul_add_c(a[3],b[5],c3,c1,c2);
+	mul_add_c(a[2],b[6],c3,c1,c2);
+	mul_add_c(a[1],b[7],c3,c1,c2);
+	r[8]=c3;
+	c3=0;
+	mul_add_c(a[2],b[7],c1,c2,c3);
+	mul_add_c(a[3],b[6],c1,c2,c3);
+	mul_add_c(a[4],b[5],c1,c2,c3);
+	mul_add_c(a[5],b[4],c1,c2,c3);
+	mul_add_c(a[6],b[3],c1,c2,c3);
+	mul_add_c(a[7],b[2],c1,c2,c3);
+	r[9]=c1;
+	c1=0;
+	mul_add_c(a[7],b[3],c2,c3,c1);
+	mul_add_c(a[6],b[4],c2,c3,c1);
+	mul_add_c(a[5],b[5],c2,c3,c1);
+	mul_add_c(a[4],b[6],c2,c3,c1);
+	mul_add_c(a[3],b[7],c2,c3,c1);
+	r[10]=c2;
+	c2=0;
+	mul_add_c(a[4],b[7],c3,c1,c2);
+	mul_add_c(a[5],b[6],c3,c1,c2);
+	mul_add_c(a[6],b[5],c3,c1,c2);
+	mul_add_c(a[7],b[4],c3,c1,c2);
+	r[11]=c3;
+	c3=0;
+	mul_add_c(a[7],b[5],c1,c2,c3);
+	mul_add_c(a[6],b[6],c1,c2,c3);
+	mul_add_c(a[5],b[7],c1,c2,c3);
+	r[12]=c1;
+	c1=0;
+	mul_add_c(a[6],b[7],c2,c3,c1);
+	mul_add_c(a[7],b[6],c2,c3,c1);
+	r[13]=c2;
+	c2=0;
+	mul_add_c(a[7],b[7],c3,c1,c2);
+	r[14]=c3;
+	r[15]=c1;
+	}
+
+void bn_mul_comba44(r,a,b)
+BN_ULONG *r,*a,*b;
+	{
+#ifdef BN_LLONG
+	BN_ULLONG t;
+#else
+	BN_ULONG bl,bh;
+#endif
+	BN_ULONG t1,t2;
+	BN_ULONG c1,c2,c3;
+
+	c1=0;
+	c2=0;
+	c3=0;
+	mul_add_c(a[0],b[0],c1,c2,c3);
+	r[0]=c1;
+	c1=0;
+	mul_add_c(a[0],b[1],c2,c3,c1);
+	mul_add_c(a[1],b[0],c2,c3,c1);
+	r[1]=c2;
+	c2=0;
+	mul_add_c(a[2],b[0],c3,c1,c2);
+	mul_add_c(a[1],b[1],c3,c1,c2);
+	mul_add_c(a[0],b[2],c3,c1,c2);
+	r[2]=c3;
+	c3=0;
+	mul_add_c(a[0],b[3],c1,c2,c3);
+	mul_add_c(a[1],b[2],c1,c2,c3);
+	mul_add_c(a[2],b[1],c1,c2,c3);
+	mul_add_c(a[3],b[0],c1,c2,c3);
+	r[3]=c1;
+	c1=0;
+	mul_add_c(a[3],b[1],c2,c3,c1);
+	mul_add_c(a[2],b[2],c2,c3,c1);
+	mul_add_c(a[1],b[3],c2,c3,c1);
+	r[4]=c2;
+	c2=0;
+	mul_add_c(a[2],b[3],c3,c1,c2);
+	mul_add_c(a[3],b[2],c3,c1,c2);
+	r[5]=c3;
+	c3=0;
+	mul_add_c(a[3],b[3],c1,c2,c3);
+	r[6]=c1;
+	r[7]=c2;
+	}
+
+void bn_sqr_comba88(r,a)
+BN_ULONG *r,*a;
+	{
+#ifdef BN_LLONG
+	BN_ULLONG t,tt;
+#else
+	BN_ULONG bl,bh;
+#endif
+	BN_ULONG t1,t2;
+	BN_ULONG c1,c2,c3;
+
+	c1=0;
+	c2=0;
+	c3=0;
+	sqr_add_c(a,0,c1,c2,c3);
+	r[0]=c1;
+	c1=0;
+	sqr_add_c2(a,1,0,c2,c3,c1);
+	r[1]=c2;
+	c2=0;
+	sqr_add_c(a,1,c3,c1,c2);
+	sqr_add_c2(a,2,0,c3,c1,c2);
+	r[2]=c3;
+	c3=0;
+	sqr_add_c2(a,3,0,c1,c2,c3);
+	sqr_add_c2(a,2,1,c1,c2,c3);
+	r[3]=c1;
+	c1=0;
+	sqr_add_c(a,2,c2,c3,c1);
+	sqr_add_c2(a,3,1,c2,c3,c1);
+	sqr_add_c2(a,4,0,c2,c3,c1);
+	r[4]=c2;
+	c2=0;
+	sqr_add_c2(a,5,0,c3,c1,c2);
+	sqr_add_c2(a,4,1,c3,c1,c2);
+	sqr_add_c2(a,3,2,c3,c1,c2);
+	r[5]=c3;
+	c3=0;
+	sqr_add_c(a,3,c1,c2,c3);
+	sqr_add_c2(a,4,2,c1,c2,c3);
+	sqr_add_c2(a,5,1,c1,c2,c3);
+	sqr_add_c2(a,6,0,c1,c2,c3);
+	r[6]=c1;
+	c1=0;
+	sqr_add_c2(a,7,0,c2,c3,c1);
+	sqr_add_c2(a,6,1,c2,c3,c1);
+	sqr_add_c2(a,5,2,c2,c3,c1);
+	sqr_add_c2(a,4,3,c2,c3,c1);
+	r[7]=c2;
+	c2=0;
+	sqr_add_c(a,4,c3,c1,c2);
+	sqr_add_c2(a,5,3,c3,c1,c2);
+	sqr_add_c2(a,6,2,c3,c1,c2);
+	sqr_add_c2(a,7,1,c3,c1,c2);
+	r[8]=c3;
+	c3=0;
+	sqr_add_c2(a,7,2,c1,c2,c3);
+	sqr_add_c2(a,6,3,c1,c2,c3);
+	sqr_add_c2(a,5,4,c1,c2,c3);
+	r[9]=c1;
+	c1=0;
+	sqr_add_c(a,5,c2,c3,c1);
+	sqr_add_c2(a,6,4,c2,c3,c1);
+	sqr_add_c2(a,7,3,c2,c3,c1);
+	r[10]=c2;
+	c2=0;
+	sqr_add_c2(a,7,4,c3,c1,c2);
+	sqr_add_c2(a,6,5,c3,c1,c2);
+	r[11]=c3;
+	c3=0;
+	sqr_add_c(a,6,c1,c2,c3);
+	sqr_add_c2(a,7,5,c1,c2,c3);
+	r[12]=c1;
+	c1=0;
+	sqr_add_c2(a,7,6,c2,c3,c1);
+	r[13]=c2;
+	c2=0;
+	sqr_add_c(a,7,c3,c1,c2);
+	r[14]=c3;
+	r[15]=c1;
+	}
+
+void bn_sqr_comba44(r,a)
+BN_ULONG *r,*a;
+	{
+#ifdef BN_LLONG
+	BN_ULLONG t,tt;
+#else
+	BN_ULONG bl,bh;
+#endif
+	BN_ULONG t1,t2;
+	BN_ULONG c1,c2,c3;
+
+	c1=0;
+	c2=0;
+	c3=0;
+	sqr_add_c(a,0,c1,c2,c3);
+	r[0]=c1;
+	c1=0;
+	sqr_add_c2(a,1,0,c2,c3,c1);
+	r[1]=c2;
+	c2=0;
+	sqr_add_c(a,1,c3,c1,c2);
+	sqr_add_c2(a,2,0,c3,c1,c2);
+	r[2]=c3;
+	c3=0;
+	sqr_add_c2(a,3,0,c1,c2,c3);
+	sqr_add_c2(a,2,1,c1,c2,c3);
+	r[3]=c1;
+	c1=0;
+	sqr_add_c(a,2,c2,c3,c1);
+	sqr_add_c2(a,3,1,c2,c3,c1);
+	r[4]=c2;
+	c2=0;
+	sqr_add_c2(a,3,2,c3,c1,c2);
+	r[5]=c3;
+	c3=0;
+	sqr_add_c(a,3,c1,c2,c3);
+	r[6]=c1;
+	r[7]=c2;
+	}
diff --git a/crypto/bn/bn_div.c b/crypto/bn/bn_div.c
index 2263bdc..c7bc04d 100644
--- a/crypto/bn/bn_div.c
+++ b/crypto/bn/bn_div.c
@@ -72,6 +72,8 @@
 	int i,nm,nd;
 	BIGNUM *D;
 
+	bn_check_top(m);
+	bn_check_top(d);
 	if (BN_is_zero(d))
 		{
 		BNerr(BN_F_BN_DIV,BN_R_DIV_BY_ZERO);
@@ -86,9 +88,9 @@
 		return(1);
 		}
 
-	D=ctx->bn[ctx->tos];
-	if (dv == NULL) dv=ctx->bn[ctx->tos+1];
-	if (rem == NULL) rem=ctx->bn[ctx->tos+2];
+	D= &(ctx->bn[ctx->tos]);
+	if (dv == NULL) dv= &(ctx->bn[ctx->tos+1]);
+	if (rem == NULL) rem= &(ctx->bn[ctx->tos+2]);
 
 	nd=BN_num_bits(d);
 	nm=BN_num_bits(m);
@@ -98,6 +100,7 @@
 	/* The next 2 are needed so we can do a dv->d[0]|=1 later
 	 * since BN_lshift1 will only work once there is a value :-) */
 	BN_zero(dv);
+	bn_wexpand(dv,1);
 	dv->top=1;
 
 	if (!BN_lshift(D,D,nm-nd)) return(0);
@@ -107,7 +110,7 @@
 		if (BN_ucmp(rem,D) >= 0)
 			{
 			dv->d[0]|=1;
-			bn_qsub(rem,rem,D);
+			if (!BN_usub(rem,rem,D)) return(0);
 			}
 /* CAN IMPROVE (and have now :=) */
 		if (!BN_rshift1(D,D)) return(0);
@@ -132,6 +135,9 @@
 	BN_ULONG d0,d1;
 	int num_n,div_n;
 
+	bn_check_top(num);
+	bn_check_top(divisor);
+
 	if (BN_is_zero(divisor))
 		{
 		BNerr(BN_F_BN_DIV,BN_R_DIV_BY_ZERO);
@@ -146,12 +152,12 @@
 		return(1);
 		}
 
-	tmp=ctx->bn[ctx->tos]; 
+	tmp= &(ctx->bn[ctx->tos]);
 	tmp->neg=0;
-	snum=ctx->bn[ctx->tos+1];
-	sdiv=ctx->bn[ctx->tos+2];
+	snum= &(ctx->bn[ctx->tos+1]);
+	sdiv= &(ctx->bn[ctx->tos+2]);
 	if (dv == NULL)
-		res=ctx->bn[ctx->tos+3];
+		res= &(ctx->bn[ctx->tos+3]);
 	else	res=dv;
 
 	/* First we normalise the numbers */
@@ -168,10 +174,10 @@
 	/* Lets setup a 'window' into snum
 	 * This is the part that corresponds to the current
 	 * 'area' being divided */
+	BN_init(&wnum);
 	wnum.d=	 &(snum->d[loop]);
 	wnum.top= div_n;
-	wnum.max= snum->max; /* a bit of a lie */
-	wnum.neg= 0;
+	wnum.max= snum->max+1; /* a bit of a lie */
 
 	/* Get the top 2 words of sdiv */
 	/* i=sdiv->top; */
@@ -183,8 +189,8 @@
 
 	/* Setup to 'res' */
 	res->neg= (num->neg^divisor->neg);
-	res->top=loop;
 	if (!bn_wexpand(res,(loop+1))) goto err;
+	res->top=loop;
 	resp= &(res->d[loop-1]);
 
 	/* space for temp */
@@ -192,7 +198,7 @@
 
 	if (BN_ucmp(&wnum,sdiv) >= 0)
 		{
-		bn_qsub(&wnum,&wnum,sdiv);
+		if (!BN_usub(&wnum,&wnum,sdiv)) goto err;
 		*resp=1;
 		res->d[res->top-1]=1;
 		}
@@ -211,7 +217,7 @@
 		if (n0 == d0)
 			q=BN_MASK2;
 		else
-			q=bn_div64(n0,n1,d0);
+			q=bn_div_words(n0,n1,d0);
 		{
 #ifdef BN_LLONG
 		BN_ULLONG t1,t2,rem;
@@ -284,3 +290,39 @@
 	}
 
 #endif
+
+/* rem != m */
+int BN_mod(rem, m, d,ctx)
+BIGNUM *rem;
+BIGNUM *m;
+BIGNUM *d;
+BN_CTX *ctx;
+	{
+#if 0 /* The old slow way */
+	int i,nm,nd;
+	BIGNUM *dv;
+
+	if (BN_ucmp(m,d) < 0)
+		return((BN_copy(rem,m) == NULL)?0:1);
+
+	dv= &(ctx->bn[ctx->tos]);
+
+	if (!BN_copy(rem,m)) return(0);
+
+	nm=BN_num_bits(rem);
+	nd=BN_num_bits(d);
+	if (!BN_lshift(dv,d,nm-nd)) return(0);
+	for (i=nm-nd; i>=0; i--)
+		{
+		if (BN_cmp(rem,dv) >= 0)
+			{
+			if (!BN_sub(rem,rem,dv)) return(0);
+			}
+		if (!BN_rshift1(dv,dv)) return(0);
+		}
+	return(1);
+#else
+	return(BN_div(NULL,rem,m,d,ctx));
+#endif
+	}
+
diff --git a/crypto/bn/bn_err.c b/crypto/bn/bn_err.c
index 029ae81..4c29c1a 100644
--- a/crypto/bn/bn_err.c
+++ b/crypto/bn/bn_err.c
@@ -78,15 +78,18 @@
 {ERR_PACK(0,BN_F_BN_MPI2BN,0),	"BN_mpi2bn"},
 {ERR_PACK(0,BN_F_BN_NEW,0),	"BN_new"},
 {ERR_PACK(0,BN_F_BN_RAND,0),	"BN_rand"},
+{ERR_PACK(0,BN_F_BN_USUB,0),	"BN_usub"},
 {0,NULL},
 	};
 
 static ERR_STRING_DATA BN_str_reasons[]=
 	{
+{BN_R_ARG2_LT_ARG3                       ,"arg2 lt arg3"},
 {BN_R_BAD_RECIPROCAL                     ,"bad reciprocal"},
 {BN_R_CALLED_WITH_EVEN_MODULUS           ,"called with even modulus"},
 {BN_R_DIV_BY_ZERO                        ,"div by zero"},
 {BN_R_ENCODING_ERROR                     ,"encoding error"},
+{BN_R_EXPAND_ON_STATIC_BIGNUM_DATA       ,"expand on static bignum data"},
 {BN_R_INVALID_LENGTH                     ,"invalid length"},
 {BN_R_NOT_INITALISED                     ,"not initalised"},
 {BN_R_NO_INVERSE                         ,"no inverse"},
@@ -99,8 +102,8 @@
 	{
 	static int init=1;
 
-	if (init);
-		{;
+	if (init)
+		{
 		init=0;
 #ifndef NO_ERR
 		ERR_load_strings(ERR_LIB_BN,BN_str_functs);
diff --git a/crypto/bn/bn_exp.c b/crypto/bn/bn_exp.c
index c056a50..44f47e7 100644
--- a/crypto/bn/bn_exp.c
+++ b/crypto/bn/bn_exp.c
@@ -60,6 +60,8 @@
 #include "cryptlib.h"
 #include "bn_lcl.h"
 
+#define TABLE_SIZE	16
+
 /* slow but works */
 int BN_mod_mul(ret, a, b, m, ctx)
 BIGNUM *ret;
@@ -71,11 +73,15 @@
 	BIGNUM *t;
 	int r=0;
 
-	t=ctx->bn[ctx->tos++];
+	bn_check_top(a);
+	bn_check_top(b);
+	bn_check_top(m);
+
+	t= &(ctx->bn[ctx->tos++]);
 	if (a == b)
 		{ if (!BN_sqr(t,a,ctx)) goto err; }
 	else
-		{ if (!BN_mul(t,a,b)) goto err; }
+		{ if (!BN_mul(t,a,b,ctx)) goto err; }
 	if (!BN_mod(ret,t,m,ctx)) goto err;
 	r=1;
 err:
@@ -92,8 +98,8 @@
 	int i,bits,ret=0;
 	BIGNUM *v,*tmp;
 
-	v=ctx->bn[ctx->tos++];
-	tmp=ctx->bn[ctx->tos++];
+	v= &(ctx->bn[ctx->tos++]);
+	tmp= &(ctx->bn[ctx->tos++]);
 
 	if (BN_copy(v,a) == NULL) goto err;
 	bits=BN_num_bits(p);
@@ -108,7 +114,7 @@
 		if (!BN_mod(v,tmp,m,ctx)) goto err;
 		if (BN_is_bit_set(p,i))
 			{
-			if (!BN_mul(tmp,r,v)) goto err;
+			if (!BN_mul(tmp,r,v,ctx)) goto err;
 			if (!BN_mod(r,tmp,m,ctx)) goto err;
 			}
 		}
@@ -128,8 +134,8 @@
 	int i,bits,ret=0;
 	BIGNUM *v,*tmp;
 
-	v=ctx->bn[ctx->tos++];
-	tmp=ctx->bn[ctx->tos++];
+	v= &(ctx->bn[ctx->tos++]);
+	tmp= &(ctx->bn[ctx->tos++]);
 
 	if (BN_copy(v,a) == NULL) goto err;
 	bits=BN_num_bits(p);
@@ -143,7 +149,7 @@
 		if (!BN_sqr(tmp,v,ctx)) goto err;
 		if (BN_is_bit_set(p,i))
 			{
-			if (!BN_mul(tmp,r,v)) goto err;
+			if (!BN_mul(tmp,r,v,ctx)) goto err;
 			}
 		}
 	ret=1;
@@ -161,6 +167,10 @@
 	{
 	int ret;
 
+	bn_check_top(a);
+	bn_check_top(p);
+	bn_check_top(m);
+
 #ifdef MONT_MUL_MOD
 	/* I have finally been able to take out this pre-condition of
 	 * the top bit being set.  It was caused by an error in BN_div
@@ -189,13 +199,13 @@
 BIGNUM *m;
 BN_CTX *ctx;
 	{
-	int nb,i,j,bits,ret=0,wstart,wend,window,wvalue;
-	int start=1;
-	BIGNUM *d,*aa;
-	BIGNUM *val[16];
+	int i,j,bits,ret=0,wstart,wend,window,wvalue;
+	int start=1,ts=0;
+	BIGNUM *aa;
+	BIGNUM val[TABLE_SIZE];
+	BN_RECP_CTX recp;
 
-	d=ctx->bn[ctx->tos++];
-	aa=ctx->bn[ctx->tos++];
+	aa= &(ctx->bn[ctx->tos++]);
 	bits=BN_num_bits(p);
 
 	if (bits == 0)
@@ -203,12 +213,14 @@
 		BN_one(r);
 		return(1);
 		}
-	nb=BN_reciprocal(d,m,ctx);
-	if (nb == -1) goto err;
+	BN_RECP_CTX_init(&recp);
+	if (BN_RECP_CTX_set(&recp,m,ctx) <= 0) goto err;
 
-	val[0]=BN_new();
-	if (!BN_mod(val[0],a,m,ctx)) goto err;		/* 1 */
-	if (!BN_mod_mul_reciprocal(aa,val[0],val[0],m,d,nb,ctx))
+	BN_init(&(val[0]));
+	ts=1;
+
+	if (!BN_mod(&(val[0]),a,m,ctx)) goto err;		/* 1 */
+	if (!BN_mod_mul_reciprocal(aa,&(val[0]),&(val[0]),&recp,ctx))
 		goto err;				/* 2 */
 
 	if (bits <= 17) /* This is probably 3 or 0x10001, so just do singles */
@@ -223,12 +235,11 @@
 	j=1<<(window-1);
 	for (i=1; i<j; i++)
 		{
-		val[i]=BN_new();
-		if (!BN_mod_mul_reciprocal(val[i],val[i-1],aa,m,d,nb,ctx))
+		BN_init(&val[i]);
+		if (!BN_mod_mul_reciprocal(&(val[i]),&(val[i-1]),aa,&recp,ctx))
 			goto err;
 		}
-	for (; i<16; i++)
-		val[i]=NULL;
+	ts=i;
 
 	start=1;	/* This is used to avoid multiplication etc
 			 * when there is only the value '1' in the
@@ -244,7 +255,7 @@
 		if (BN_is_bit_set(p,wstart) == 0)
 			{
 			if (!start)
-				if (!BN_mod_mul_reciprocal(r,r,r,m,d,nb,ctx))
+				if (!BN_mod_mul_reciprocal(r,r,r,&recp,ctx))
 				goto err;
 			if (wstart == 0) break;
 			wstart--;
@@ -274,12 +285,12 @@
 		if (!start)
 			for (i=0; i<j; i++)
 				{
-				if (!BN_mod_mul_reciprocal(r,r,r,m,d,nb,ctx))
+				if (!BN_mod_mul_reciprocal(r,r,r,&recp,ctx))
 					goto err;
 				}
 		
 		/* wvalue will be an odd number < 2^window */
-		if (!BN_mod_mul_reciprocal(r,r,val[wvalue>>1],m,d,nb,ctx))
+		if (!BN_mod_mul_reciprocal(r,r,&(val[wvalue>>1]),&recp,ctx))
 			goto err;
 
 		/* move the 'window' down further */
@@ -290,35 +301,40 @@
 		}
 	ret=1;
 err:
-	ctx->tos-=2;
-	for (i=0; i<16; i++)
-		if (val[i] != NULL) BN_clear_free(val[i]);
+	ctx->tos--;
+	for (i=0; i<ts; i++)
+		BN_clear_free(&(val[i]));
+	BN_RECP_CTX_free(&recp);
 	return(ret);
 	}
 /* #endif */
 
 /* #ifdef MONT_MUL_MOD */
-int BN_mod_exp_mont(r,a,p,m,ctx,in_mont)
-BIGNUM *r;
+int BN_mod_exp_mont(rr,a,p,m,ctx,in_mont)
+BIGNUM *rr;
 BIGNUM *a;
 BIGNUM *p;
 BIGNUM *m;
 BN_CTX *ctx;
 BN_MONT_CTX *in_mont;
 	{
-#define TABLE_SIZE	16
 	int i,j,bits,ret=0,wstart,wend,window,wvalue;
-	int start=1;
-	BIGNUM *d,*aa;
-	BIGNUM *val[TABLE_SIZE];
+	int start=1,ts=0;
+	BIGNUM *d,*aa,*r;
+	BIGNUM val[TABLE_SIZE];
 	BN_MONT_CTX *mont=NULL;
 
+	bn_check_top(a);
+	bn_check_top(p);
+	bn_check_top(m);
+
 	if (!(m->d[0] & 1))
 		{
 		BNerr(BN_F_BN_MOD_EXP_MONT,BN_R_CALLED_WITH_EVEN_MODULUS);
 		return(0);
 		}
-	d=ctx->bn[ctx->tos++];
+	d= &(ctx->bn[ctx->tos++]);
+	r= &(ctx->bn[ctx->tos++]);
 	bits=BN_num_bits(p);
 	if (bits == 0)
 		{
@@ -339,22 +355,23 @@
 		if (!BN_MONT_CTX_set(mont,m,ctx)) goto err;
 		}
 
-	val[0]=BN_new();
+	BN_init(&val[0]);
+	ts=1;
 	if (BN_ucmp(a,m) >= 0)
 		{
-		BN_mod(val[0],a,m,ctx);
-		aa=val[0];
+		BN_mod(&(val[0]),a,m,ctx);
+		aa= &(val[0]);
 		}
 	else
 		aa=a;
-	if (!BN_to_montgomery(val[0],aa,mont,ctx)) goto err; /* 1 */
-	if (!BN_mod_mul_montgomery(d,val[0],val[0],mont,ctx)) goto err; /* 2 */
+	if (!BN_to_montgomery(&(val[0]),aa,mont,ctx)) goto err; /* 1 */
+	if (!BN_mod_mul_montgomery(d,&(val[0]),&(val[0]),mont,ctx)) goto err; /* 2 */
 
 	if (bits <= 20) /* This is probably 3 or 0x10001, so just do singles */
 		window=1;
-	else if (bits > 250)
+	else if (bits >= 256)
 		window=5;	/* max size of window */
-	else if (bits >= 120)
+	else if (bits >= 128)
 		window=4;
 	else
 		window=3;
@@ -362,12 +379,11 @@
 	j=1<<(window-1);
 	for (i=1; i<j; i++)
 		{
-		val[i]=BN_new();
-		if (!BN_mod_mul_montgomery(val[i],val[i-1],d,mont,ctx))
+		BN_init(&(val[i]));
+		if (!BN_mod_mul_montgomery(&(val[i]),&(val[i-1]),d,mont,ctx))
 			goto err;
 		}
-	for (; i<TABLE_SIZE; i++)
-		val[i]=NULL;
+	ts=i;
 
 	start=1;	/* This is used to avoid multiplication etc
 			 * when there is only the value '1' in the
@@ -419,7 +435,7 @@
 				}
 		
 		/* wvalue will be an odd number < 2^window */
-		if (!BN_mod_mul_montgomery(r,r,val[wvalue>>1],mont,ctx))
+		if (!BN_mod_mul_montgomery(r,r,&(val[wvalue>>1]),mont,ctx))
 			goto err;
 
 		/* move the 'window' down further */
@@ -428,13 +444,13 @@
 		start=0;
 		if (wstart < 0) break;
 		}
-	BN_from_montgomery(r,r,mont,ctx);
+	BN_from_montgomery(rr,r,mont,ctx);
 	ret=1;
 err:
 	if ((in_mont == NULL) && (mont != NULL)) BN_MONT_CTX_free(mont);
-	ctx->tos--;
-	for (i=0; i<TABLE_SIZE; i++)
-		if (val[i] != NULL) BN_clear_free(val[i]);
+	ctx->tos-=2;
+	for (i=0; i<ts; i++)
+		BN_clear_free(&(val[i]));
 	return(ret);
 	}
 /* #endif */
@@ -447,12 +463,12 @@
 BIGNUM *m;
 BN_CTX *ctx;
 	{
-	int i,j,bits,ret=0,wstart,wend,window,wvalue;
+	int i,j,bits,ret=0,wstart,wend,window,wvalue,ts=0;
 	int start=1;
 	BIGNUM *d;
-	BIGNUM *val[16];
+	BIGNUM val[TABLE_SIZE];
 
-	d=ctx->bn[ctx->tos++];
+	d= &(ctx->bn[ctx->tos++]);
 	bits=BN_num_bits(p);
 
 	if (bits == 0)
@@ -461,9 +477,10 @@
 		return(1);
 		}
 
-	val[0]=BN_new();
-	if (!BN_mod(val[0],a,m,ctx)) goto err;		/* 1 */
-	if (!BN_mod_mul(d,val[0],val[0],m,ctx))
+	BN_init(&(val[0]));
+	ts=1;
+	if (!BN_mod(&(val[0]),a,m,ctx)) goto err;		/* 1 */
+	if (!BN_mod_mul(d,&(val[0]),&(val[0]),m,ctx))
 		goto err;				/* 2 */
 
 	if (bits <= 17) /* This is probably 3 or 0x10001, so just do singles */
@@ -478,12 +495,11 @@
 	j=1<<(window-1);
 	for (i=1; i<j; i++)
 		{
-		val[i]=BN_new();
-		if (!BN_mod_mul(val[i],val[i-1],d,m,ctx))
+		BN_init(&(val[i]));
+		if (!BN_mod_mul(&(val[i]),&(val[i-1]),d,m,ctx))
 			goto err;
 		}
-	for (; i<16; i++)
-		val[i]=NULL;
+	ts=i;
 
 	start=1;	/* This is used to avoid multiplication etc
 			 * when there is only the value '1' in the
@@ -534,7 +550,7 @@
 				}
 		
 		/* wvalue will be an odd number < 2^window */
-		if (!BN_mod_mul(r,r,val[wvalue>>1],m,ctx))
+		if (!BN_mod_mul(r,r,&(val[wvalue>>1]),m,ctx))
 			goto err;
 
 		/* move the 'window' down further */
@@ -546,8 +562,8 @@
 	ret=1;
 err:
 	ctx->tos--;
-	for (i=0; i<16; i++)
-		if (val[i] != NULL) BN_clear_free(val[i]);
+	for (i=0; i<ts; i++)
+		BN_clear_free(&(val[i]));
 	return(ret);
 	}
 
diff --git a/crypto/bn/bn_exp2.c b/crypto/bn/bn_exp2.c
new file mode 100644
index 0000000..eface73
--- /dev/null
+++ b/crypto/bn/bn_exp2.c
@@ -0,0 +1,202 @@
+#include <stdio.h>
+#include "cryptlib.h"
+#include "bn_lcl.h"
+
+/* I've done some timing with different table sizes.
+ * The main hassle is that even with bits set at 3, this requires
+ * 63 BIGNUMs to store the pre-calculated values.
+ *          512   1024 
+ * bits=1  75.4%  79.4%
+ * bits=2  61.2%  62.4%
+ * bits=3  61.3%  59.3%
+ * The lack of speed improvment is also a function of the pre-calculation
+ * which could be removed.
+ */
+#define EXP2_TABLE_BITS	2 /* 1  2  3  4  5  */
+#define EXP2_TABLE_SIZE	4 /* 2  4  8 16 32  */
+
+int BN_mod_exp2_mont(rr,a1,p1,a2,p2,m,ctx,in_mont)
+BIGNUM *rr;
+BIGNUM *a1;
+BIGNUM *p1;
+BIGNUM *a2;
+BIGNUM *p2;
+BIGNUM *m;
+BN_CTX *ctx;
+BN_MONT_CTX *in_mont;
+	{
+	int i,j,k,bits,bits1,bits2,ret=0,wstart,wend,window,xvalue,yvalue;
+	int start=1,ts=0,x,y;
+	BIGNUM *d,*aa1,*aa2,*r;
+	BIGNUM val[EXP2_TABLE_SIZE][EXP2_TABLE_SIZE];
+	BN_MONT_CTX *mont=NULL;
+
+	bn_check_top(a1);
+	bn_check_top(p1);
+	bn_check_top(a2);
+	bn_check_top(p2);
+	bn_check_top(m);
+
+	if (!(m->d[0] & 1))
+		{
+		BNerr(BN_F_BN_MOD_EXP_MONT,BN_R_CALLED_WITH_EVEN_MODULUS);
+		return(0);
+		}
+	d= &(ctx->bn[ctx->tos++]);
+	r= &(ctx->bn[ctx->tos++]);
+	bits1=BN_num_bits(p1);
+	bits2=BN_num_bits(p2);
+	if ((bits1 == 0) && (bits2 == 0))
+		{
+		BN_one(r);
+		return(1);
+		}
+	bits=(bits1 > bits2)?bits1:bits2;
+
+	/* If this is not done, things will break in the montgomery
+	 * part */
+
+	if (in_mont != NULL)
+		mont=in_mont;
+	else
+		{
+		if ((mont=BN_MONT_CTX_new()) == NULL) goto err;
+		if (!BN_MONT_CTX_set(mont,m,ctx)) goto err;
+		}
+
+	BN_init(&(val[0][0]));
+	BN_init(&(val[1][1]));
+	BN_init(&(val[0][1]));
+	BN_init(&(val[1][0]));
+	ts=1;
+	if (BN_ucmp(a1,m) >= 0)
+		{
+		BN_mod(&(val[1][0]),a1,m,ctx);
+		aa1= &(val[1][0]);
+		}
+	else
+		aa1=a1;
+	if (BN_ucmp(a2,m) >= 0)
+		{
+		BN_mod(&(val[0][1]),a2,m,ctx);
+		aa2= &(val[0][1]);
+		}
+	else
+		aa2=a2;
+	if (!BN_to_montgomery(&(val[1][0]),aa1,mont,ctx)) goto err;
+	if (!BN_to_montgomery(&(val[0][1]),aa2,mont,ctx)) goto err;
+	if (!BN_mod_mul_montgomery(&(val[1][1]),
+		&(val[1][0]),&(val[0][1]),mont,ctx))
+		goto err;
+
+#if 0
+	if (bits <= 20) /* This is probably 3 or 0x10001, so just do singles */
+		window=1;
+	else if (bits > 250)
+		window=5;	/* max size of window */
+	else if (bits >= 120)
+		window=4;
+	else
+		window=3;
+#else
+	window=EXP2_TABLE_BITS;
+#endif
+
+	k=1<<window;
+	for (x=0; x<k; x++)
+		{
+		if (x >= 2)
+			{
+			BN_init(&(val[x][0]));
+			BN_init(&(val[x][1]));
+			if (!BN_mod_mul_montgomery(&(val[x][0]),
+				&(val[1][0]),&(val[x-1][0]),mont,ctx)) goto err;
+			if (!BN_mod_mul_montgomery(&(val[x][1]),
+				&(val[1][0]),&(val[x-1][1]),mont,ctx)) goto err;
+			}
+		for (y=2; y<k; y++)
+			{
+			BN_init(&(val[x][y]));
+			if (!BN_mod_mul_montgomery(&(val[x][y]),
+				&(val[x][y-1]),&(val[0][1]),mont,ctx))
+				goto err;
+			}
+		}
+	ts=k;
+
+	start=1;	/* This is used to avoid multiplication etc
+			 * when there is only the value '1' in the
+			 * buffer. */
+	xvalue=0;	/* The 'x value' of the window */
+	yvalue=0;	/* The 'y value' of the window */
+	wstart=bits-1;	/* The top bit of the window */
+	wend=0;		/* The bottom bit of the window */
+
+        if (!BN_to_montgomery(r,BN_value_one(),mont,ctx)) goto err;
+	for (;;)
+		{
+		xvalue=BN_is_bit_set(p1,wstart);
+		yvalue=BN_is_bit_set(p2,wstart);
+		if (!(xvalue || yvalue))
+			{
+			if (!start)
+				{
+				if (!BN_mod_mul_montgomery(r,r,r,mont,ctx))
+					goto err;
+				}
+			wstart--;
+			if (wstart < 0) break;
+			continue;
+			}
+		/* We now have wstart on a 'set' bit, we now need to work out
+		 * how bit a window to do.  To do this we need to scan
+		 * forward until the last set bit before the end of the
+		 * window */
+		j=wstart;
+		/* xvalue=BN_is_bit_set(p1,wstart); already set */
+		/* yvalue=BN_is_bit_set(p1,wstart); already set */
+		wend=0;
+		for (i=1; i<window; i++)
+			{
+			if (wstart-i < 0) break;
+			xvalue+=xvalue;
+			xvalue|=BN_is_bit_set(p1,wstart-i);
+			yvalue+=yvalue;
+			yvalue|=BN_is_bit_set(p2,wstart-i);
+			}
+
+		/* i is the size of the current window */
+		/* add the 'bytes above' */
+		if (!start)
+			for (j=0; j<i; j++)
+				{
+				if (!BN_mod_mul_montgomery(r,r,r,mont,ctx))
+					goto err;
+				}
+		
+		/* wvalue will be an odd number < 2^window */
+		if (xvalue || yvalue)
+			{
+			if (!BN_mod_mul_montgomery(r,r,&(val[xvalue][yvalue]),
+				mont,ctx)) goto err;
+			}
+
+		/* move the 'window' down further */
+		wstart-=i;
+		start=0;
+		if (wstart < 0) break;
+		}
+	BN_from_montgomery(rr,r,mont,ctx);
+	ret=1;
+err:
+	if ((in_mont == NULL) && (mont != NULL)) BN_MONT_CTX_free(mont);
+	ctx->tos-=2;
+	for (i=0; i<ts; i++)
+		{
+		for (j=0; j<ts; j++)
+			{
+			BN_clear_free(&(val[i][j]));
+			}
+		}
+	return(ret);
+	}
diff --git a/crypto/bn/bn_gcd.c b/crypto/bn/bn_gcd.c
index 071bba3..c80cecd 100644
--- a/crypto/bn/bn_gcd.c
+++ b/crypto/bn/bn_gcd.c
@@ -73,8 +73,11 @@
 	BIGNUM *a,*b,*t;
 	int ret=0;
 
-	a=ctx->bn[ctx->tos];
-	b=ctx->bn[ctx->tos+1];
+	bn_check_top(in_a);
+	bn_check_top(in_b);
+
+	a= &(ctx->bn[ctx->tos]);
+	b= &(ctx->bn[ctx->tos+1]);
 
 	if (BN_copy(a,in_a) == NULL) goto err;
 	if (BN_copy(b,in_b) == NULL) goto err;
@@ -95,6 +98,9 @@
 	BIGNUM *t;
 	int shifts=0;
 
+	bn_check_top(a);
+	bn_check_top(b);
+
 	for (;;)
 		{
 		if (BN_is_zero(b))
@@ -142,23 +148,30 @@
 	}
 
 /* solves ax == 1 (mod n) */
-BIGNUM *BN_mod_inverse(a, n, ctx)
+BIGNUM *BN_mod_inverse(in, a, n, ctx)
+BIGNUM *in;
 BIGNUM *a;
 BIGNUM *n;
 BN_CTX *ctx;
 	{
 	BIGNUM *A,*B,*X,*Y,*M,*D,*R;
-	BIGNUM *ret=NULL,*T;
+	BIGNUM *T,*ret=NULL;
 	int sign;
 
-	A=ctx->bn[ctx->tos];
-	B=ctx->bn[ctx->tos+1];
-	X=ctx->bn[ctx->tos+2];
-	D=ctx->bn[ctx->tos+3];
-	M=ctx->bn[ctx->tos+4];
-	Y=ctx->bn[ctx->tos+5];
+	bn_check_top(a);
+	bn_check_top(n);
+
+	A= &(ctx->bn[ctx->tos]);
+	B= &(ctx->bn[ctx->tos+1]);
+	X= &(ctx->bn[ctx->tos+2]);
+	D= &(ctx->bn[ctx->tos+3]);
+	M= &(ctx->bn[ctx->tos+4]);
+	Y= &(ctx->bn[ctx->tos+5]);
 	ctx->tos+=6;
-	R=BN_new();
+	if (in == NULL)
+		R=BN_new();
+	else
+		R=in;
 	if (R == NULL) goto err;
 
 	BN_zero(X);
@@ -175,7 +188,7 @@
 		B=M;
 		/* T has a struct, M does not */
 
-		if (!BN_mul(T,D,X)) goto err;
+		if (!BN_mul(T,D,X,ctx)) goto err;
 		if (!BN_add(T,T,Y)) goto err;
 		M=Y;
 		Y=X;
@@ -196,7 +209,7 @@
 		}
 	ret=R;
 err:
-	if ((ret == NULL) && (R != NULL)) BN_free(R);
+	if ((ret == NULL) && (in == NULL)) BN_free(R);
 	ctx->tos-=6;
 	return(ret);
 	}
diff --git a/crypto/bn/bn_lcl.h b/crypto/bn/bn_lcl.h
index edfd788..70b0787 100644
--- a/crypto/bn/bn_lcl.h
+++ b/crypto/bn/bn_lcl.h
@@ -65,17 +65,68 @@
 extern "C" {
 #endif
 
+/* Pentium pro 16,16,16,32,64 */
+/* Alpha       16,16,16,16.64 */
+#define BN_MULL_SIZE_NORMAL			(16) // 32
+#define BN_MUL_RECURSIVE_SIZE_NORMAL		(16) // 32 /* less than */
+#define BN_SQR_RECURSIVE_SIZE_NORMAL		(16) // 32
+#define BN_MUL_LOW_RECURSIVE_SIZE_NORMAL	(32) // 32
+#define BN_MONT_CTX_SET_SIZE_WORD		(64) // 32
+
+#ifndef BN_MUL_COMBA
+#define bn_mul_comba8(r,a,b)	bn_mul_normal(r,a,8,b,8)
+#define bn_mul_comba4(r,a,b)	bn_mul_normal(r,a,4,b,4)
+/* This is probably faster than using the C code - I need to check */
+#define bn_sqr_comba8(r,a)	bn_mul_normal(r,a,8,a,8)
+#define bn_sqr_comba4(r,a)	bn_mul_normal(r,a,4,a,4)
+#endif
+
 /*************************************************************
  * Using the long long type
  */
 #define Lw(t)    (((BN_ULONG)(t))&BN_MASK2)
 #define Hw(t)    (((BN_ULONG)((t)>>BN_BITS2))&BN_MASK2)
 
-#define bn_fix_top(a) \
-        { \
-        BN_ULONG *fix_top_l; \
-        for (fix_top_l= &((a)->d[(a)->top-1]); (a)->top > 0; (a)->top--) \
-		if (*(fix_top_l--)) break; \
+/* These are used for internal error checking and are not normally used */
+#ifdef BN_DEBUG
+#define bn_check_top(a) \
+	{ if (((a)->top < 0) || ((a)->top > (a)->max)) \
+		{ char *nullp=NULL; *nullp='z'; } }
+#define bn_check_num(a) if ((a) < 0) { char *nullp=NULL; *nullp='z'; }
+#else
+#define bn_check_top(a)
+#define bn_check_num(a)
+#endif
+
+/* This macro is to add extra stuff for development checking */
+#ifdef BN_DEBUG
+#define	bn_set_max(r) ((r)->max=(r)->top,BN_set_flags((r),BN_FLG_STATIC_DATA))
+#else
+#define	bn_set_max(r)
+#endif
+
+/* These macros are used to 'take' a section of a bignum for read only use */
+#define bn_set_low(r,a,n) \
+	{ \
+	(r)->top=((a)->top > (n))?(n):(a)->top; \
+	(r)->d=(a)->d; \
+	(r)->neg=(a)->neg; \
+	(r)->flags|=BN_FLG_STATIC_DATA; \
+	bn_set_max(r); \
+	}
+
+#define bn_set_high(r,a,n) \
+	{ \
+	if ((a)->top > (n)) \
+		{ \
+		(r)->top=(a)->top-n; \
+		(r)->d= &((a)->d[n]); \
+		} \
+	else \
+		(r)->top=0; \
+	(r)->neg=(a)->neg; \
+	(r)->flags|=BN_FLG_STATIC_DATA; \
+	bn_set_max(r); \
 	}
 
 /* #define bn_expand(n,b) ((((b)/BN_BITS2) <= (n)->max)?(n):bn_expand2((n),(b))) */
@@ -175,6 +226,17 @@
 
 #endif
 
+extern int bn_limit_bits;
+extern int bn_limit_num;        /* (1<<bn_limit_bits) */
+/* Recursive 'low' limit */
+extern int bn_limit_bits_low;
+extern int bn_limit_num_low;    /* (1<<bn_limit_bits_low) */
+/* Do modified 'high' part calculation' */
+extern int bn_limit_bits_high;
+extern int bn_limit_num_high;   /* (1<<bn_limit_bits_high) */
+extern int bn_limit_bits_mont;
+extern int bn_limit_num_mont;   /* (1<<bn_limit_bits_mont) */
+
 #ifndef NOPROTO
 
 BIGNUM *bn_expand2(BIGNUM *b, int bits);
@@ -197,3 +259,8 @@
 #endif
 
 #endif
+
+void bn_mul_low_recursive(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b,int n2,BN_ULONG *t);
+void bn_mul_high(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b,BN_ULONG *l,int n2, BN_ULONG *t);
+
+
diff --git a/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c
index bfe7628..7ea216f 100644
--- a/crypto/bn/bn_lib.c
+++ b/crypto/bn/bn_lib.c
@@ -60,7 +60,68 @@
 #include "cryptlib.h"
 #include "bn_lcl.h"
 
-char *BN_version="Big Number part of SSLeay 0.9.0b 29-Jun-1998";
+char *BN_version="Big Number part of SSLeay 0.9.1a 06-Jul-1998";
+
+/* For a 32 bit machine
+ * 2 -   4 ==  128
+ * 3 -   8 ==  256
+ * 4 -  16 ==  512
+ * 5 -  32 == 1024
+ * 6 -  64 == 2048
+ * 7 - 128 == 4096
+ * 8 - 256 == 8192
+ */
+int bn_limit_bits=0;
+int bn_limit_num=8;        /* (1<<bn_limit_bits) */
+int bn_limit_bits_low=0;
+int bn_limit_num_low=8;    /* (1<<bn_limit_bits_low) */
+int bn_limit_bits_high=0;
+int bn_limit_num_high=8;   /* (1<<bn_limit_bits_high) */
+int bn_limit_bits_mont=0;
+int bn_limit_num_mont=8;   /* (1<<bn_limit_bits_mont) */
+
+void BN_set_params(mult,high,low,mont)
+int mult,high,low,mont;
+	{
+	if (mult >= 0)
+		{
+		if (mult > (sizeof(int)*8)-1)
+			mult=sizeof(int)*8-1;
+		bn_limit_bits=mult;
+		bn_limit_num=1<<mult;
+		}
+	if (high >= 0)
+		{
+		if (high > (sizeof(int)*8)-1)
+			high=sizeof(int)*8-1;
+		bn_limit_bits_high=high;
+		bn_limit_num_high=1<<high;
+		}
+	if (low >= 0)
+		{
+		if (low > (sizeof(int)*8)-1)
+			low=sizeof(int)*8-1;
+		bn_limit_bits_low=low;
+		bn_limit_num_low=1<<low;
+		}
+	if (mont >= 0)
+		{
+		if (mont > (sizeof(int)*8)-1)
+			mont=sizeof(int)*8-1;
+		bn_limit_bits_mont=mont;
+		bn_limit_num_mont=1<<mont;
+		}
+	}
+
+int BN_get_params(which)
+int which;
+	{
+	if      (which == 0) return(bn_limit_bits);
+	else if (which == 1) return(bn_limit_bits_high);
+	else if (which == 2) return(bn_limit_bits_low);
+	else if (which == 3) return(bn_limit_bits_mont);
+	else return(0);
+	}
 
 BIGNUM *BN_value_one()
 	{
@@ -111,24 +172,24 @@
 		8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
 		};
 
-#ifdef SIXTY_FOUR_BIT_LONG
+#if defined(SIXTY_FOUR_BIT_LONG)
 	if (l & 0xffffffff00000000L)
 		{
 		if (l & 0xffff000000000000L)
 			{
 			if (l & 0xff00000000000000L)
 				{
-				return(bits[l>>56]+56);
+				return(bits[(int)(l>>56)]+56);
 				}
-			else	return(bits[l>>48]+48);
+			else	return(bits[(int)(l>>48)]+48);
 			}
 		else
 			{
 			if (l & 0x0000ff0000000000L)
 				{
-				return(bits[l>>40]+40);
+				return(bits[(int)(l>>40)]+40);
 				}
-			else	return(bits[l>>32]+32);
+			else	return(bits[(int)(l>>32)]+32);
 			}
 		}
 	else
@@ -140,17 +201,17 @@
 			{
 			if (l & 0xff00000000000000LL)
 				{
-				return(bits[l>>56]+56);
+				return(bits[(int)(l>>56)]+56);
 				}
-			else	return(bits[l>>48]+48);
+			else	return(bits[(int)(l>>48)]+48);
 			}
 		else
 			{
 			if (l & 0x0000ff0000000000LL)
 				{
-				return(bits[l>>40]+40);
+				return(bits[(int)(l>>40)]+40);
 				}
-			else	return(bits[l>>32]+32);
+			else	return(bits[(int)(l>>32)]+32);
 			}
 		}
 	else
@@ -161,18 +222,18 @@
 		if (l & 0xffff0000L)
 			{
 			if (l & 0xff000000L)
-				return(bits[l>>24L]+24);
-			else	return(bits[l>>16L]+16);
+				return(bits[(int)(l>>24L)]+24);
+			else	return(bits[(int)(l>>16L)]+16);
 			}
 		else
 #endif
 			{
 #if defined(SIXTEEN_BIT) || defined(THIRTY_TWO_BIT) || defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG)
 			if (l & 0xff00L)
-				return(bits[l>>8]+8);
+				return(bits[(int)(l>>8)]+8);
 			else	
 #endif
-				return(bits[l   ]  );
+				return(bits[(int)(l   )]  );
 			}
 		}
 	}
@@ -183,6 +244,8 @@
 	BN_ULONG l;
 	int i;
 
+	bn_check_top(a);
+
 	if (a->top == 0) return(0);
 	l=a->d[a->top-1];
 	i=(a->top-1)*BN_BITS2;
@@ -199,74 +262,78 @@
 void BN_clear_free(a)
 BIGNUM *a;
 	{
+	int i;
+
 	if (a == NULL) return;
 	if (a->d != NULL)
 		{
 		memset(a->d,0,a->max*sizeof(a->d[0]));
-		Free(a->d);
+		if (!(BN_get_flags(a,BN_FLG_STATIC_DATA)))
+			Free(a->d);
 		}
+	i=BN_get_flags(a,BN_FLG_MALLOCED);
 	memset(a,0,sizeof(BIGNUM));
-	Free(a);
+	if (i)
+		Free(a);
 	}
 
 void BN_free(a)
 BIGNUM *a;
 	{
 	if (a == NULL) return;
-	if (a->d != NULL) Free(a->d);
-	Free(a);
+	if ((a->d != NULL) && !(BN_get_flags(a,BN_FLG_STATIC_DATA)))
+		Free(a->d);
+	a->flags|=BN_FLG_FREE; /* REMOVE? */
+	if (a->flags & BN_FLG_MALLOCED)
+		Free(a);
+	}
+
+void BN_init(a)
+BIGNUM *a;
+	{
+	memset(a,0,sizeof(BIGNUM));
 	}
 
 BIGNUM *BN_new()
 	{
 	BIGNUM *ret;
-	BN_ULONG *p;
 
-	ret=(BIGNUM *)Malloc(sizeof(BIGNUM));
-	if (ret == NULL) goto err;
+	if ((ret=(BIGNUM *)Malloc(sizeof(BIGNUM))) == NULL)
+		{
+		BNerr(BN_F_BN_NEW,ERR_R_MALLOC_FAILURE);
+		return(NULL);
+		}
+	ret->flags=BN_FLG_MALLOCED;
 	ret->top=0;
 	ret->neg=0;
-	ret->max=(BN_DEFAULT_BITS/BN_BITS2);
-	p=(BN_ULONG *)Malloc(sizeof(BN_ULONG)*(ret->max+1));
-	if (p == NULL) goto err;
-	ret->d=p;
-
-	memset(p,0,(ret->max+1)*sizeof(p[0]));
+	ret->max=0;
+	ret->d=NULL;
 	return(ret);
-err:
-	BNerr(BN_F_BN_NEW,ERR_R_MALLOC_FAILURE);
-	return(NULL);
 	}
 
+
 BN_CTX *BN_CTX_new()
 	{
 	BN_CTX *ret;
-	BIGNUM *n;
-	int i,j;
 
 	ret=(BN_CTX *)Malloc(sizeof(BN_CTX));
-	if (ret == NULL) goto err2;
-
-	for (i=0; i<BN_CTX_NUM; i++)
+	if (ret == NULL)
 		{
-		n=BN_new();
-		if (n == NULL) goto err;
-		ret->bn[i]=n;
+		BNerr(BN_F_BN_CTX_NEW,ERR_R_MALLOC_FAILURE);
+		return(NULL);
 		}
 
-	/* There is actually an extra one, this is for debugging my
-	 * stuff */
-	ret->bn[BN_CTX_NUM]=NULL;
-
-	ret->tos=0;
+	BN_CTX_init(ret);
+	ret->flags=BN_FLG_MALLOCED;
 	return(ret);
-err:
-	for (j=0; j<i; j++)
-		BN_free(ret->bn[j]);
-	Free(ret);
-err2:
-	BNerr(BN_F_BN_CTX_NEW,ERR_R_MALLOC_FAILURE);
-	return(NULL);
+	}
+
+void BN_CTX_init(ctx)
+BN_CTX *ctx;
+	{
+	memset(ctx,0,sizeof(BN_CTX));
+	ctx->tos=0;
+	ctx->flags=0;
 	}
 
 void BN_CTX_free(c)
@@ -275,26 +342,98 @@
 	int i;
 
 	for (i=0; i<BN_CTX_NUM; i++)
-		BN_clear_free(c->bn[i]);
-	Free(c);
+		BN_clear_free(&(c->bn[i]));
+	if (c->flags & BN_FLG_MALLOCED)
+		Free(c);
 	}
 
 BIGNUM *bn_expand2(b, words)
 BIGNUM *b;
 int words;
 	{
-	BN_ULONG *p;
+	BN_ULONG *A,*B,*a;
+	int i,j;
+
+	bn_check_top(b);
 
 	if (words > b->max)
 		{
-		p=(BN_ULONG *)Realloc(b->d,sizeof(BN_ULONG)*(words+1));
-		if (p == NULL)
+		bn_check_top(b);	
+		if (BN_get_flags(b,BN_FLG_STATIC_DATA))
+			{
+			BNerr(BN_F_BN_EXPAND2,BN_R_EXPAND_ON_STATIC_BIGNUM_DATA);
+			return(NULL);
+			}
+		a=A=(BN_ULONG *)Malloc(sizeof(BN_ULONG)*(words+1));
+		if (A == NULL)
 			{
 			BNerr(BN_F_BN_EXPAND2,ERR_R_MALLOC_FAILURE);
 			return(NULL);
 			}
-		b->d=p;
-		memset(&(p[b->max]),0,((words+1)-b->max)*sizeof(BN_ULONG));
+memset(A,0x5c,sizeof(BN_ULONG)*(words+1));
+#if 1
+		B=b->d;
+		if (B != NULL)
+			{
+			for (i=b->top&(~7); i>0; i-=8)
+				{
+				A[0]=B[0]; A[1]=B[1]; A[2]=B[2]; A[3]=B[3];
+				A[4]=B[4]; A[5]=B[5]; A[6]=B[6]; A[7]=B[7];
+				A+=8;
+				B+=8;
+				}
+			switch (b->top&7)
+				{
+			case 7:
+				A[6]=B[6];
+			case 6:
+				A[5]=B[5];
+			case 5:
+				A[4]=B[4];
+			case 4:
+				A[3]=B[3];
+			case 3:
+				A[2]=B[2];
+			case 2:
+				A[1]=B[1];
+			case 1:
+				A[0]=B[0];
+			case 0:
+				/* I need the 'case 0' entry for utrix cc.
+				 * If the optimiser is turned on, it does the
+				 * switch table by doing
+				 * a=top&7
+				 * a--;
+				 * goto jump_table[a];
+				 * If top is 0, this makes us jump to 0xffffffc 
+				 * which is rather bad :-(.
+				 * eric 23-Apr-1998
+				 */
+				;
+				}
+			B= &(b->d[b->top]);
+			j=b->max-8;
+			for (i=b->top; i<j; i+=8)
+				{
+				B[0]=0; B[1]=0; B[2]=0; B[3]=0;
+				B[4]=0; B[5]=0; B[6]=0; B[7]=0;
+				B+=8;
+				}
+			for (j+=8; i<j; i++)
+				{
+				B[0]=0;
+				B++;
+				}
+#else
+			memcpy(a->d,b->d,sizeof(b->d[0])*b->top);
+#endif
+		
+/*		memset(&(p[b->max]),0,((words+1)-b->max)*sizeof(BN_ULONG)); */
+/*	{ int i; for (i=b->max; i<words+1; i++) p[i]=i;} */
+			Free(b->d);
+			}
+
+		b->d=a;
 		b->max=words;
 		}
 	return(b);
@@ -305,6 +444,8 @@
 	{
 	BIGNUM *r;
 
+	bn_check_top(a);
+
 	r=BN_new();
 	if (r == NULL) return(NULL);
 	return((BIGNUM *)BN_copy(r,a));
@@ -317,6 +458,8 @@
 	int i;
 	BN_ULONG *A,*B;
 
+	bn_check_top(b);
+
 	if (a == b) return(a);
 	if (bn_wexpand(a,b->top) == NULL) return(NULL);
 
@@ -352,6 +495,18 @@
 		A[1]=B[1];
 	case 1:
 		A[0]=B[0];
+        case 0:
+		/* I need the 'case 0' entry for utrix cc.
+		 * If the optimiser is turned on, it does the
+		 * switch table by doing
+		 * a=top&7
+		 * a--;
+		 * goto jump_table[a];
+		 * If top is 0, this makes us jump to 0xffffffc which is
+		 * rather bad :-(.
+		 * eric 23-Apr-1998
+		 */
+		;
 		}
 #else
 	memcpy(a->d,b->d,sizeof(b->d[0])*b->top);
@@ -359,7 +514,7 @@
 
 /*	memset(&(a->d[b->top]),0,sizeof(a->d[0])*(a->max-b->top));*/
 	a->top=b->top;
-	if (a->top == 0)
+	if ((a->top == 0) && (a->d != NULL))
 		a->d[0]=0;
 	a->neg=b->neg;
 	return(a);
@@ -368,24 +523,21 @@
 void BN_clear(a)
 BIGNUM *a;
 	{
-	memset(a->d,0,a->max*sizeof(a->d[0]));
+	if (a->d != NULL)
+		memset(a->d,0,a->max*sizeof(a->d[0]));
 	a->top=0;
 	a->neg=0;
 	}
 
-unsigned long BN_get_word(a)
+BN_ULONG BN_get_word(a)
 BIGNUM *a;
 	{
 	int i,n;
-	unsigned long ret=0;
+	BN_ULONG ret=0;
 
 	n=BN_num_bytes(a);
-	if (n > sizeof(unsigned long))
-#ifdef SIXTY_FOUR_BIT_LONG
+	if (n > sizeof(BN_ULONG))
 		return(BN_MASK2);
-#else
-		return(0xFFFFFFFFL);
-#endif
 	for (i=a->top-1; i>=0; i--)
 		{
 #ifndef SIXTY_FOUR_BIT /* the data item > unsigned long */
@@ -399,12 +551,12 @@
 
 int BN_set_word(a,w)
 BIGNUM *a;
-unsigned long w;
+BN_ULONG w;
 	{
 	int i,n;
-	if (bn_expand(a,sizeof(unsigned long)*8) == NULL) return(0);
+	if (bn_expand(a,sizeof(BN_ULONG)*8) == NULL) return(0);
 
-	n=sizeof(unsigned long)/BN_BYTES;
+	n=sizeof(BN_ULONG)/BN_BYTES;
 	a->neg=0;
 	a->top=0;
 	a->d[0]=(BN_ULONG)w&BN_MASK2;
@@ -488,6 +640,9 @@
 	int i;
 	BN_ULONG t1,t2,*ap,*bp;
 
+	bn_check_top(a);
+	bn_check_top(b);
+
 	i=a->top-b->top;
 	if (i != 0) return(i);
 	ap=a->d;
@@ -519,6 +674,10 @@
 		else
 			return(0);
 		}
+
+	bn_check_top(a);
+	bn_check_top(b);
+
 	if (a->neg != b->neg)
 		{
 		if (a->neg)
@@ -545,13 +704,15 @@
 BIGNUM *a;
 int n;
 	{
-	int i,j;
+	int i,j,k;
 
 	i=n/BN_BITS2;
 	j=n%BN_BITS2;
 	if (a->top <= i)
 		{
-		if (bn_expand(a,n) == NULL) return(0);
+		if (bn_wexpand(a,i+1) == NULL) return(0);
+		for(k=a->top; k<i+1; k++)
+			a->d[k]=0;
 		a->top=i+1;
 		}
 
@@ -570,6 +731,7 @@
 	if (a->top <= i) return(0);
 
 	a->d[i]&=(~(1L<<j));
+	bn_fix_top(a);
 	return(1);
 	}
 
@@ -601,11 +763,27 @@
 		{
 		a->top=w+1;
 		a->d[w]&= ~(BN_MASK2<<b);
-		while ((w >= 0) && (a->d[w] == 0))
-			{
-			a->top--;
-			w--;
-			}
 		}
+	bn_fix_top(a);
 	return(1);
 	}
+
+int bn_cmp_words(a,b,n)
+BN_ULONG *a,*b;
+int n;
+	{
+	int i;
+	BN_ULONG aa,bb;
+
+	aa=a[n-1];
+	bb=b[n-1];
+	if (aa != bb) return((aa > bb)?1:-1);
+	for (i=n-2; i>=0; i--)
+		{
+		aa=a[i];
+		bb=b[i];
+		if (aa != bb) return((aa > bb)?1:-1);
+		}
+	return(0);
+	}
+
diff --git a/crypto/bn/bn_mont.c b/crypto/bn/bn_mont.c
index e435df6..e0aa3c7 100644
--- a/crypto/bn/bn_mont.c
+++ b/crypto/bn/bn_mont.c
@@ -60,161 +60,208 @@
 #include "cryptlib.h"
 #include "bn_lcl.h"
 
+#define MONT_WORD
+
 int BN_mod_mul_montgomery(r,a,b,mont,ctx)
 BIGNUM *r,*a,*b;
 BN_MONT_CTX *mont;
 BN_CTX *ctx;
 	{
-	BIGNUM *tmp;
+	BIGNUM *tmp,*tmp2;
 
-        tmp=ctx->bn[ctx->tos++];
+        tmp= &(ctx->bn[ctx->tos]);
+        tmp2= &(ctx->bn[ctx->tos]);
+	ctx->tos+=2;
+
+	bn_check_top(tmp);
+	bn_check_top(tmp2);
 
 	if (a == b)
 		{
+#if 0
+		bn_wexpand(tmp,a->top*2);
+		bn_wexpand(tmp2,a->top*4);
+		bn_sqr_recursive(tmp->d,a->d,a->top,tmp2->d);
+		tmp->top=a->top*2;
+		if (tmp->d[tmp->top-1] == 0)
+			tmp->top--;
+#else
 		if (!BN_sqr(tmp,a,ctx)) goto err;
+#endif
 		}
 	else
 		{
-		if (!BN_mul(tmp,a,b)) goto err;
+		if (!BN_mul(tmp,a,b,ctx)) goto err;
 		}
 	/* reduce from aRR to aR */
 	if (!BN_from_montgomery(r,tmp,mont,ctx)) goto err;
-	ctx->tos--;
+	ctx->tos-=2;
 	return(1);
 err:
 	return(0);
 	}
 
-#define MONT_WORD
-
-#ifdef MONT_WORD
 int BN_from_montgomery(ret,a,mont,ctx)
 BIGNUM *ret;
 BIGNUM *a;
 BN_MONT_CTX *mont;
 BN_CTX *ctx;
 	{
-	BIGNUM *n,*t1,*r;
-	BN_ULONG *ap,*np,*rp,n0,v;
-	int al,nl,max,i,x,ri;
-	int retn=0;
+#ifdef BN_RECURSION
+	if (mont->use_word)
+#endif
+		{
+		BIGNUM *n,*r;
+		BN_ULONG *ap,*np,*rp,n0,v,*nrp;
+		int al,nl,max,i,x,ri;
+		int retn=0;
 
-	t1=ctx->bn[ctx->tos];
-	r=ctx->bn[ctx->tos+1];
+		r= &(ctx->bn[ctx->tos]);
 
-	if (!BN_copy(r,a)) goto err;
-	n=mont->N;
+		if (!BN_copy(r,a)) goto err1;
+		n= &(mont->N);
 
-	ap=a->d;
-	/* mont->ri is the size of mont->N in bits/words */
-	al=ri=mont->ri/BN_BITS2;
+		ap=a->d;
+		/* mont->ri is the size of mont->N in bits/words */
+		al=ri=mont->ri/BN_BITS2;
 
-	nl=n->top;
-	if ((al == 0) || (nl == 0)) { r->top=0; return(1); }
+		nl=n->top;
+		if ((al == 0) || (nl == 0)) { r->top=0; return(1); }
 
-	max=(nl+al+1); /* allow for overflow (no?) XXX */
-	if (bn_wexpand(r,max) == NULL) goto err;
-	if (bn_wexpand(ret,max) == NULL) goto err;
+		max=(nl+al+1); /* allow for overflow (no?) XXX */
+		if (bn_wexpand(r,max) == NULL) goto err1;
+		if (bn_wexpand(ret,max) == NULL) goto err1;
 
-	r->neg=a->neg^n->neg;
-	np=n->d;
-	rp=r->d;
+		r->neg=a->neg^n->neg;
+		np=n->d;
+		rp=r->d;
+		nrp= &(r->d[nl]);
 
-	/* clear the top words of T */
+		/* clear the top words of T */
 #if 1
-	for (i=r->top; i<max; i++) /* memset? XXX */
-		r->d[i]=0;
+		for (i=r->top; i<max; i++) /* memset? XXX */
+			r->d[i]=0;
 #else
-	memset(&(r->d[r->top]),0,(max-r->top)*sizeof(BN_ULONG)); 
+		memset(&(r->d[r->top]),0,(max-r->top)*sizeof(BN_ULONG)); 
 #endif
 
-	r->top=max;
-	n0=mont->n0;
+		r->top=max;
+		n0=mont->n0;
 
-	for (i=0; i<nl; i++)
-		{
-#if 0
-		int x1,x2;
-
-		if (i+4 > nl)
+#ifdef BN_COUNT
+printf("word BN_from_montgomery %d * %d\n",nl,nl);
+#endif
+		for (i=0; i<nl; i++)
 			{
-			x2=nl;
-			x1=0;
+			v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2);
+			nrp++;
+			rp++;
+			if (((nrp[-1]+=v)&BN_MASK2) >= v)
+				continue;
+			else
+				{
+				if (((++nrp[0])&BN_MASK2) != 0) continue;
+				if (((++nrp[1])&BN_MASK2) != 0) continue;
+				for (x=2; (((++nrp[x])&BN_MASK2) == 0); x++) ;
+				}
 			}
+		bn_fix_top(r);
+
+		/* mont->ri will be a multiple of the word size */
+#if 0
+		BN_rshift(ret,r,mont->ri);
+#else
+		x=ri;
+		rp=ret->d;
+		ap= &(r->d[x]);
+		if (r->top < x)
+			al=0;
 		else
+			al=r->top-x;
+		ret->top=al;
+		al-=4;
+		for (i=0; i<al; i+=4)
 			{
-			x2=i+4;
-			x1=nl-x2;
+			BN_ULONG t1,t2,t3,t4;
+
+			t1=ap[i+0];
+			t2=ap[i+1];
+			t3=ap[i+2];
+			t4=ap[i+3];
+			rp[i+0]=t1;
+			rp[i+1]=t2;
+			rp[i+2]=t3;
+			rp[i+3]=t4;
 			}
-		v=bn_mul_add_words(&(rp[x1]),&(np[x1]),x2,(rp[x1]*n0)&BN_MASK2);
-#else
-		v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2);
+		al+=4;
+		for (; i<al; i++)
+			rp[i]=ap[i];
 #endif
 
-		if (((rp[nl]+=v)&BN_MASK2) < v)
+		if (BN_ucmp(ret, &(mont->N)) >= 0)
 			{
-			for (x=(nl+1); (((++rp[x])&BN_MASK2) == 0); x++)
-				;
+			BN_usub(ret,ret,&(mont->N)); /* XXX */
 			}
-		rp++;
+		retn=1;
+err1:
+		return(retn);
 		}
-	while (r->d[r->top-1] == 0)
-		r->top--;
-
-	/* mont->ri will be a multiple of the word size */
-#if 0
-	BN_rshift(ret,r,mont->ri);
-#else
-	ap=r->d;
-	rp=ret->d;
-	x=ri;
-	al=r->top-x;
-	for (i=0; i<al; i++)
+#ifdef BN_RECURSION
+	else /* bignum version */ 
 		{
-		rp[i]=ap[i+x];
-		}
-	ret->top=al;
+		BIGNUM *t1,*t2,*t3;
+		int j,i;
+
+#ifdef BN_COUNT
+printf("number BN_from_montgomery\n");
 #endif
 
-	if (BN_ucmp(ret,mont->N) >= 0)
-		{
-		bn_qsub(ret,ret,mont->N); /* XXX */
+		t1= &(ctx->bn[ctx->tos]);
+		t2= &(ctx->bn[ctx->tos+1]);
+		t3= &(ctx->bn[ctx->tos+2]);
+
+		i=mont->Ni.top;
+		bn_wexpand(ret,i); /* perhaps only i*2 */
+		bn_wexpand(t1,i*4); /* perhaps only i*2 */
+		bn_wexpand(t2,i*2); /* perhaps only i   */
+
+		bn_mul_low_recursive(t2->d,a->d,mont->Ni.d,i,t1->d);
+
+		BN_zero(t3);
+		BN_set_bit(t3,mont->N.top*BN_BITS2);
+		bn_sub_words(t3->d,t3->d,a->d,i);
+		bn_mul_high(ret->d,t2->d,mont->N.d,t3->d,i,t1->d);
+
+		/* hmm... if a is between i and 2*i, things are bad */
+		if (a->top > i)
+			{
+			j=bn_add_words(ret->d,ret->d,&(a->d[i]),i);
+			if (j) /* overflow */
+				bn_sub_words(ret->d,ret->d,mont->N.d,i);
+			}
+		ret->top=i;
+		bn_fix_top(ret);
+		if (a->d[0])
+			BN_add_word(ret,1); /* Always? */
+		else	/* Very very rare */
+			{
+			for (i=1; i<mont->N.top-1; i++)
+				{
+				if (a->d[i])
+					{
+					BN_add_word(ret,1); /* Always? */
+					break;
+					}
+				}
+			}
+
+		if (BN_ucmp(ret,&(mont->N)) >= 0)
+			BN_usub(ret,ret,&(mont->N));
+
+		return(1);
 		}
-	retn=1;
-err:
-	return(retn);
-	}
-#else
-int BN_from_montgomery(r,a,mont,ctx)
-BIGNUM *r;
-BIGNUM *a;
-BN_MONT_CTX *mont;
-BN_CTX *ctx;
-	{
-	BIGNUM *t1,*t2;
-
-	t1=ctx->bn[ctx->tos];
-	t2=ctx->bn[ctx->tos+1];
-
-	if (!BN_copy(t1,a)) goto err;
-	/* can cheat */
-	BN_mask_bits(t1,mont->ri);
-
-	if (!BN_mul(t2,t1,mont->Ni)) goto err;
-	BN_mask_bits(t2,mont->ri);
-
-	if (!BN_mul(t1,t2,mont->N)) goto err;
-	if (!BN_add(t2,a,t1)) goto err;
-	BN_rshift(r,t2,mont->ri);
-
-	if (BN_ucmp(r,mont->N) >= 0)
-		bn_qsub(r,r,mont->N);
-
-	return(1);
-err:
-	return(0);
-	}
 #endif
+	}
 
 BN_MONT_CTX *BN_MONT_CTX_new()
 	{
@@ -222,25 +269,31 @@
 
 	if ((ret=(BN_MONT_CTX *)Malloc(sizeof(BN_MONT_CTX))) == NULL)
 		return(NULL);
-	ret->ri=0;
-	ret->RR=BN_new();
-	ret->N=BN_new();
-	ret->Ni=NULL;
-	if ((ret->RR == NULL) || (ret->N == NULL))
-		{
-		BN_MONT_CTX_free(ret);
-		return(NULL);
-		}
+
+	BN_MONT_CTX_init(ret);
+	ret->flags=BN_FLG_MALLOCED;
 	return(ret);
 	}
 
+void BN_MONT_CTX_init(ctx)
+BN_MONT_CTX *ctx;
+	{
+	ctx->use_word=0;
+	ctx->ri=0;
+	BN_init(&(ctx->RR));
+	BN_init(&(ctx->N));
+	BN_init(&(ctx->Ni));
+	ctx->flags=0;
+	}
+
 void BN_MONT_CTX_free(mont)
 BN_MONT_CTX *mont;
 	{
-	if (mont->RR != NULL) BN_free(mont->RR);
-	if (mont->N != NULL) BN_free(mont->N);
-	if (mont->Ni != NULL) BN_free(mont->Ni);
-	Free(mont);
+	BN_free(&(mont->RR));
+	BN_free(&(mont->N));
+	BN_free(&(mont->Ni));
+	if (mont->flags & BN_FLG_MALLOCED)
+		Free(mont);
 	}
 
 int BN_MONT_CTX_set(mont,mod,ctx)
@@ -248,59 +301,109 @@
 BIGNUM *mod;
 BN_CTX *ctx;
 	{
-	BIGNUM *Ri=NULL,*R=NULL;
+	BIGNUM Ri,*R;
 
-	if (mont->RR == NULL) mont->RR=BN_new();
-	if (mont->N == NULL)  mont->N=BN_new();
+	BN_init(&Ri);
+	R= &(mont->RR);					/* grab RR as a temp */
+	BN_copy(&(mont->N),mod);			/* Set N */
 
-	R=mont->RR;					/* grab RR as a temp */
-	BN_copy(mont->N,mod);				/* Set N */
+#ifdef BN_RECURSION
+	if (mont->N.top < BN_MONT_CTX_SET_SIZE_WORD)
+#endif
+		{
+		BIGNUM tmod;
+		BN_ULONG buf[2];
 
-#ifdef MONT_WORD
-{
-	BIGNUM tmod;
-	BN_ULONG buf[2];
-	/* int z; */
+		mont->use_word=1;
 
-	mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2;
-	BN_lshift(R,BN_value_one(),BN_BITS2);		/* R */
-	/* I was bad, this modification of a passed variable was
-	 * breaking the multithreaded stuff :-(
-	 * z=mod->top;
-	 * mod->top=1; */
+		mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2;
+		BN_zero(R);
+		BN_set_bit(R,BN_BITS2);
+		/* I was bad, this modification of a passed variable was
+		 * breaking the multithreaded stuff :-(
+		 * z=mod->top;
+		 * mod->top=1; */
 
-	buf[0]=mod->d[0];
-	buf[1]=0;
-	tmod.d=buf;
-	tmod.top=1;
-	tmod.max=mod->max;
-	tmod.neg=mod->neg;
+		buf[0]=mod->d[0];
+		buf[1]=0;
+		tmod.d=buf;
+		tmod.top=1;
+		tmod.max=mod->max;
+		tmod.neg=mod->neg;
 
-	if ((Ri=BN_mod_inverse(R,&tmod,ctx)) == NULL) goto err; /* Ri */
-	BN_lshift(Ri,Ri,BN_BITS2);			/* R*Ri */
-	bn_qsub(Ri,Ri,BN_value_one());			/* R*Ri - 1 */
-	BN_div(Ri,NULL,Ri,&tmod,ctx);
-	mont->n0=Ri->d[0];
-	BN_free(Ri);
-	/* mod->top=z; */
-}
+		if ((BN_mod_inverse(&Ri,R,&tmod,ctx)) == NULL)
+			goto err;
+		BN_lshift(&Ri,&Ri,BN_BITS2);			/* R*Ri */
+		if (!BN_is_zero(&Ri))
+			{
+#if 1
+			BN_sub_word(&Ri,1);
 #else
-	mont->ri=BN_num_bits(mod);
-	BN_lshift(R,BN_value_one(),mont->ri);			/* R */
-	if ((Ri=BN_mod_inverse(R,mod,ctx)) == NULL) goto err;	/* Ri */
-	BN_lshift(Ri,Ri,mont->ri);				/* R*Ri */
-	bn_qsub(Ri,Ri,BN_value_one());				/* R*Ri - 1 */
-	BN_div(Ri,NULL,Ri,mod,ctx);
-	if (mont->Ni != NULL) BN_free(mont->Ni);
-	mont->Ni=Ri;					/* Ni=(R*Ri-1)/N */
+			BN_usub(&Ri,&Ri,BN_value_one());	/* R*Ri - 1 */
+#endif
+			}
+		else
+			{
+			/* This is not common..., 1 in BN_MASK2,
+			 * It happens when buf[0] was == 1.  So for 8 bit,
+			 * this is 1/256, 16bit, 1 in 2^16 etc.
+			 */
+			BN_set_word(&Ri,BN_MASK2);
+			}
+		BN_div(&Ri,NULL,&Ri,&tmod,ctx);
+		mont->n0=Ri.d[0];
+		BN_free(&Ri);
+		/* mod->top=z; */
+		}
+#ifdef BN_RECURSION
+	else
+		{
+		mont->use_word=0;
+		mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2;
+#if 1
+		BN_zero(R);
+		BN_set_bit(R,mont->ri);
+#else
+		BN_lshift(R,BN_value_one(),mont->ri);	/* R */
+#endif
+		if ((BN_mod_inverse(&Ri,R,mod,ctx)) == NULL)
+			goto err;
+		BN_lshift(&Ri,&Ri,mont->ri);		/* R*Ri */
+#if 1
+		BN_sub_word(&Ri,1);
+#else
+		BN_usub(&Ri,&Ri,BN_value_one());	/* R*Ri - 1 */
+#endif
+		BN_div(&(mont->Ni),NULL,&Ri,mod,ctx);
+		BN_free(&Ri);
+		}
 #endif
 
 	/* setup RR for conversions */
+#if 1
+	BN_zero(&(mont->RR));
+	BN_set_bit(&(mont->RR),mont->ri*2);
+#else
 	BN_lshift(mont->RR,BN_value_one(),mont->ri*2);
-	BN_mod(mont->RR,mont->RR,mont->N,ctx);
+#endif
+	BN_mod(&(mont->RR),&(mont->RR),&(mont->N),ctx);
 
 	return(1);
 err:
 	return(0);
 	}
 
+BN_MONT_CTX *BN_MONT_CTX_copy(to, from)
+BN_MONT_CTX *to, *from;
+	{
+	if (to == from) return(to);
+
+	BN_copy(&(to->RR),&(from->RR));
+	BN_copy(&(to->N),&(from->N));
+	BN_copy(&(to->Ni),&(from->Ni));
+	to->use_word=from->use_word;
+	to->ri=from->ri;
+	to->n0=from->n0;
+	return(to);
+	}
+
diff --git a/crypto/bn/bn_mpi.c b/crypto/bn/bn_mpi.c
index 53945c1..84b0317 100644
--- a/crypto/bn/bn_mpi.c
+++ b/crypto/bn/bn_mpi.c
@@ -103,7 +103,7 @@
 		BNerr(BN_F_BN_MPI2BN,BN_R_INVALID_LENGTH);
 		return(NULL);
 		}
-	len=(d[0]<<24)|(d[1]<<16)|(d[2]<<8)|d[3];
+	len=((long)d[0]<<24)|((long)d[1]<<16)|((int)d[2]<<8)|(int)d[3];
 	if ((len+4) != n)
 		{
 		BNerr(BN_F_BN_MPI2BN,BN_R_ENCODING_ERROR);
diff --git a/crypto/bn/bn_mul.c b/crypto/bn/bn_mul.c
index d0c04e1..fc7bf97 100644
--- a/crypto/bn/bn_mul.c
+++ b/crypto/bn/bn_mul.c
@@ -60,150 +60,703 @@
 #include "cryptlib.h"
 #include "bn_lcl.h"
 
-/* r must be different to a and b */
-/* int BN_mmul(r, a, b) */
-int BN_mul(r, a, b)
-BIGNUM *r;
-BIGNUM *a;
-BIGNUM *b;
+#ifdef BN_RECURSION
+/* r is 2*n2 words in size,
+ * a and b are both n2 words in size.
+ * n2 must be a power of 2.
+ * We multiply and return the result.
+ * t must be 2*n2 words in size
+ * We calulate
+ * a[0]*b[0]
+ * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0])
+ * a[1]*b[1]
+ */
+void bn_mul_recursive(r,a,b,n2,t)
+BN_ULONG *r,*a,*b;
+int n2;
+BN_ULONG *t;
 	{
-	int i;
-	int max,al,bl;
-	BN_ULONG *ap,*bp,*rp;
+	int n=n2/2,c1,c2;
+	unsigned int neg,zero;
+	BN_ULONG ln,lo,*p;
 
-	al=a->top;
-	bl=b->top;
-	if ((al == 0) || (bl == 0))
+#ifdef BN_COUNT
+printf(" bn_mul_recursive %d * %d\n",n2,n2);
+#endif
+#ifdef BN_MUL_COMBA
+/*	if (n2 == 4)
 		{
-		r->top=0;
-		return(1);
+		bn_mul_comba4(r,a,b);
+		return;
+		}
+	else */ if (n2 == 8)
+		{
+		bn_mul_comba8(r,a,b);
+		return; 
+		}
+#endif
+	if (n2 < BN_MUL_RECURSIVE_SIZE_NORMAL)
+		{
+		/* This should not happen */
+		bn_mul_normal(r,a,n2,b,n2);
+		return;
+		}
+	/* r=(a[0]-a[1])*(b[1]-b[0]) */
+	c1=bn_cmp_words(a,&(a[n]),n);
+	c2=bn_cmp_words(&(b[n]),b,n);
+	zero=neg=0;
+	switch (c1*3+c2)
+		{
+	case -4:
+		bn_sub_words(t,      &(a[n]),a,      n); /* - */
+		bn_sub_words(&(t[n]),b,      &(b[n]),n); /* - */
+		break;
+	case -3:
+		zero=1;
+		break;
+	case -2:
+		bn_sub_words(t,      &(a[n]),a,      n); /* - */
+		bn_sub_words(&(t[n]),&(b[n]),b,      n); /* + */
+		neg=1;
+		break;
+	case -1:
+	case 0:
+	case 1:
+		zero=1;
+		break;
+	case 2:
+		bn_sub_words(t,      a,      &(a[n]),n); /* + */
+		bn_sub_words(&(t[n]),b,      &(b[n]),n); /* - */
+		neg=1;
+		break;
+	case 3:
+		zero=1;
+		break;
+	case 4:
+		bn_sub_words(t,      a,      &(a[n]),n);
+		bn_sub_words(&(t[n]),&(b[n]),b,      n);
+		break;
 		}
 
-	max=(al+bl);
-	if (bn_wexpand(r,max) == NULL) return(0);
-	r->top=max;
-	r->neg=a->neg^b->neg;
-	ap=a->d;
-	bp=b->d;
-	rp=r->d;
-
-	rp[al]=bn_mul_words(rp,ap,al,*(bp++));
-	rp++;
-	for (i=1; i<bl; i++)
+#ifdef BN_MUL_COMBA
+	if (n == 4)
 		{
-		rp[al]=bn_mul_add_words(rp,ap,al,*(bp++));
-		rp++;
+		if (!zero)
+			bn_mul_comba4(&(t[n2]),t,&(t[n]));
+		else
+			memset(&(t[n2]),0,8*sizeof(BN_ULONG));
+		
+		bn_mul_comba4(r,a,b);
+		bn_mul_comba4(&(r[n2]),&(a[n]),&(b[n]));
 		}
-	if (r->d[max-1] == 0) r->top--;
-	return(1);
-	}
-
-#if 0
-#include "stack.h"
-
-int limit=16;
-
-typedef struct bn_pool_st
-	{
-	int used;
-	int tos;
-	STACK *sk; 
-	} BN_POOL;
-
-BIGNUM *BN_POOL_push(bp)
-BN_POOL *bp;
-	{
-	BIGNUM *ret;
-
-	if (bp->used >= bp->tos)
+	else if (n == 8)
 		{
-		ret=BN_new();
-		sk_push(bp->sk,(char *)ret);
-		bp->tos++;
-		bp->used++;
+		if (!zero)
+			bn_mul_comba8(&(t[n2]),t,&(t[n]));
+		else
+			memset(&(t[n2]),0,16*sizeof(BN_ULONG));
+		
+		bn_mul_comba8(r,a,b);
+		bn_mul_comba8(&(r[n2]),&(a[n]),&(b[n]));
+		}
+	else
+#endif
+		{
+		p= &(t[n2*2]);
+		if (!zero)
+			bn_mul_recursive(&(t[n2]),t,&(t[n]),n,p);
+		else
+			memset(&(t[n2]),0,n2*sizeof(BN_ULONG));
+		bn_mul_recursive(r,a,b,n,p);
+		bn_mul_recursive(&(r[n2]),&(a[n]),&(b[n]),n,p);
+		}
+
+	/* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign
+	 * r[10] holds (a[0]*b[0])
+	 * r[32] holds (b[1]*b[1])
+	 */
+
+	c1=bn_add_words(t,r,&(r[n2]),n2);
+
+	if (neg) /* if t[32] is negative */
+		{
+		c1-=bn_sub_words(&(t[n2]),t,&(t[n2]),n2);
 		}
 	else
 		{
-		ret=(BIGNUM *)sk_value(bp->sk,bp->used);
-		bp->used++;
+		/* Might have a carry */
+		c1+=bn_add_words(&(t[n2]),&(t[n2]),t,n2);
 		}
-	return(ret);
-	}
 
-void BN_POOL_pop(bp,num)
-BN_POOL *bp;
-int num;
-	{
-	bp->used-=num;
-	}
-
-int BN_mul(r,a,b)
-BIGNUM *r,*a,*b;
-	{
-	static BN_POOL bp;
-	static init=1;
-
-	if (init)
+	/* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1])
+	 * r[10] holds (a[0]*b[0])
+	 * r[32] holds (b[1]*b[1])
+	 * c1 holds the carry bits
+	 */
+	c1+=bn_add_words(&(r[n]),&(r[n]),&(t[n2]),n2);
+	if (c1)
 		{
-		bp.used=0;
-		bp.tos=0;
-		bp.sk=sk_new_null();
-		init=0;
+		p= &(r[n+n2]);
+		lo= *p;
+		ln=(lo+c1)&BN_MASK2;
+		*p=ln;
+
+		/* The overflow will stop before we over write
+		 * words we should not overwrite */
+		if (ln < (BN_ULONG)c1)
+			{
+			do	{
+				p++;
+				lo= *p;
+				ln=(lo+1)&BN_MASK2;
+				*p=ln;
+				} while (ln == 0);
+			}
 		}
-	return(BN_mm(r,a,b,&bp));
 	}
 
-/* r must be different to a and b */
-int BN_mm(m, A, B, bp)
-BIGNUM *m,*A,*B;
-BN_POOL *bp;
+/* n+tn is the word length
+ * t needs to be n*4 is size, as does r */
+void bn_mul_part_recursive(r,a,b,tn,n,t)
+BN_ULONG *r,*a,*b;
+int tn,n;
+BN_ULONG *t;
 	{
-	int i,num;
-	int an,bn;
-	BIGNUM *a,*b,*c,*d,*ac,*bd;
+	int i,j,n2=n*2;
+	unsigned int c1;
+	BN_ULONG ln,lo,*p;
 
-	an=A->top;
-	bn=B->top;
-	if ((an <= limit) || (bn <= limit))
+#ifdef BN_COUNT
+printf(" bn_mul_part_recursive %d * %d\n",tn+n,tn+n);
+#endif
+	if (n < 8)
 		{
-		return(BN_mmul(m,A,B));
+		i=tn+n;
+		bn_mul_normal(r,a,i,b,i);
+		return;
 		}
 
-	a=BN_POOL_push(bp);
-	b=BN_POOL_push(bp);
-	c=BN_POOL_push(bp);
-	d=BN_POOL_push(bp);
-	ac=BN_POOL_push(bp);
-	bd=BN_POOL_push(bp);
+	/* r=(a[0]-a[1])*(b[1]-b[0]) */
+	bn_sub_words(t,      a,      &(a[n]),n); /* + */
+	bn_sub_words(&(t[n]),b,      &(b[n]),n); /* - */
 
-	num=(an <= bn)?an:bn;
-	num=1<<(BN_num_bits_word(num-1)-1);
+/*	if (n == 4)
+		{
+		bn_mul_comba4(&(t[n2]),t,&(t[n]));
+		bn_mul_comba4(r,a,b);
+		bn_mul_normal(&(r[n2]),&(a[n]),tn,&(b[n]),tn);
+		memset(&(r[n2+tn*2]),0,sizeof(BN_ULONG)*(n2-tn*2));
+		}
+	else */ if (n == 8)
+		{
+		bn_mul_comba8(&(t[n2]),t,&(t[n]));
+		bn_mul_comba8(r,a,b);
+		bn_mul_normal(&(r[n2]),&(a[n]),tn,&(b[n]),tn);
+		memset(&(r[n2+tn*2]),0,sizeof(BN_ULONG)*(n2-tn*2));
+		}
+	else
+		{
+		p= &(t[n2*2]);
+		bn_mul_recursive(&(t[n2]),t,&(t[n]),n,p);
+		bn_mul_recursive(r,a,b,n,p);
+		i=n/2;
+		/* If there is only a bottom half to the number,
+		 * just do it */
+		j=tn-i;
+		if (j == 0)
+			{
+			bn_mul_recursive(&(r[n2]),&(a[n]),&(b[n]),i,p);
+			memset(&(r[n2+i*2]),0,sizeof(BN_ULONG)*(n2-i*2));
+			}
+		else if (j > 0) /* eg, n == 16, i == 8 and tn == 11 */
+				{
+				bn_mul_part_recursive(&(r[n2]),&(a[n]),&(b[n]),
+					j,i,p);
+				memset(&(r[n2+tn*2]),0,
+					sizeof(BN_ULONG)*(n2-tn*2));
+				}
+		else /* (j < 0) eg, n == 16, i == 8 and tn == 5 */
+			{
+			memset(&(r[n2]),0,sizeof(BN_ULONG)*n2);
+			if (tn < BN_MUL_RECURSIVE_SIZE_NORMAL)
+				{
+				bn_mul_normal(&(r[n2]),&(a[n]),tn,&(b[n]),tn);
+				}
+			else
+				{
+				for (;;)
+					{
+					i/=2;
+					if (i < tn)
+						{
+						bn_mul_part_recursive(&(r[n2]),
+							&(a[n]),&(b[n]),
+							tn-i,i,p);
+						break;
+						}
+					else if (i == tn)
+						{
+						bn_mul_recursive(&(r[n2]),
+							&(a[n]),&(b[n]),
+							i,p);
+						break;
+						}
+					}
+				}
+			}
+		}
 
-	/* Are going to now chop things into 'num' word chunks. */
-	num*=BN_BITS2;
+	/* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign
+	 * r[10] holds (a[0]*b[0])
+	 * r[32] holds (b[1]*b[1])
+	 */
 
-	BN_copy(a,A);
-	BN_mask_bits(a,num);
-	BN_rshift(b,A,num);
+	c1=bn_add_words(t,r,&(r[n2]),n2);
+	c1-=bn_sub_words(&(t[n2]),t,&(t[n2]),n2);
 
-	BN_copy(c,B);
-	BN_mask_bits(c,num);
-	BN_rshift(d,B,num);
+	/* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1])
+	 * r[10] holds (a[0]*b[0])
+	 * r[32] holds (b[1]*b[1])
+	 * c1 holds the carry bits
+	 */
+	c1+=bn_add_words(&(r[n]),&(r[n]),&(t[n2]),n2);
+	if (c1)
+		{
+		p= &(r[n+n2]);
+		lo= *p;
+		ln=(lo+c1)&BN_MASK2;
+		*p=ln;
 
-	BN_sub(ac ,b,a);
-	BN_sub(bd,c,d);
-	BN_mm(m,ac,bd,bp);
-	BN_mm(ac,a,c,bp);
-	BN_mm(bd,b,d,bp);
+		/* The overflow will stop before we over write
+		 * words we should not overwrite */
+		if (ln < c1)
+			{
+			do	{
+				p++;
+				lo= *p;
+				ln=(lo+1)&BN_MASK2;
+				*p=ln;
+				} while (ln == 0);
+			}
+		}
+	}
 
-	BN_add(m,m,ac);
-	BN_add(m,m,bd);
-	BN_lshift(m,m,num);
-	BN_lshift(bd,bd,num*2);
+/* a and b must be the same size, which is n2.
+ * r needs to be n2 words and t needs to be n2*2
+ */
+void bn_mul_low_recursive(r,a,b,n2,t)
+BN_ULONG *r,*a,*b;
+int n2;
+BN_ULONG *t;
+	{
+	int n=n2/2;
 
-	BN_add(m,m,ac);
-	BN_add(m,m,bd);
-	BN_POOL_pop(bp,6);
-	return(1);
+#ifdef BN_COUNT
+printf(" bn_mul_low_recursive %d * %d\n",n2,n2);
+#endif
+
+	bn_mul_recursive(r,a,b,n,&(t[0]));
+	if (n >= BN_MUL_LOW_RECURSIVE_SIZE_NORMAL)
+		{
+		bn_mul_low_recursive(&(t[0]),&(a[0]),&(b[n]),n,&(t[n2]));
+		bn_add_words(&(r[n]),&(r[n]),&(t[0]),n);
+		bn_mul_low_recursive(&(t[0]),&(a[n]),&(b[0]),n,&(t[n2]));
+		bn_add_words(&(r[n]),&(r[n]),&(t[0]),n);
+		}
+	else
+		{
+		bn_mul_low_normal(&(t[0]),&(a[0]),&(b[n]),n);
+		bn_mul_low_normal(&(t[n]),&(a[n]),&(b[0]),n);
+		bn_add_words(&(r[n]),&(r[n]),&(t[0]),n);
+		bn_add_words(&(r[n]),&(r[n]),&(t[n]),n);
+		}
+	}
+
+/* a and b must be the same size, which is n2.
+ * r needs to be n2 words and t needs to be n2*2
+ * l is the low words of the output.
+ * t needs to be n2*3
+ */
+void bn_mul_high(r,a,b,l,n2,t)
+BN_ULONG *r,*a,*b,*l;
+int n2;
+BN_ULONG *t;
+	{
+	int i,n;
+	int c1,c2;
+	int neg,oneg,zero;
+	BN_ULONG ll,lc,*lp,*mp;
+
+#ifdef BN_COUNT
+printf(" bn_mul_high %d * %d\n",n2,n2);
+#endif
+	n=(n2+1)/2;
+
+	/* Calculate (al-ah)*(bh-bl) */
+	neg=zero=0;
+	c1=bn_cmp_words(&(a[0]),&(a[n]),n);
+	c2=bn_cmp_words(&(b[n]),&(b[0]),n);
+	switch (c1*3+c2)
+		{
+	case -4:
+		bn_sub_words(&(r[0]),&(a[n]),&(a[0]),n);
+		bn_sub_words(&(r[n]),&(b[0]),&(b[n]),n);
+		break;
+	case -3:
+		zero=1;
+		break;
+	case -2:
+		bn_sub_words(&(r[0]),&(a[n]),&(a[0]),n);
+		bn_sub_words(&(r[n]),&(b[n]),&(b[0]),n);
+		neg=1;
+		break;
+	case -1:
+	case 0:
+	case 1:
+		zero=1;
+		break;
+	case 2:
+		bn_sub_words(&(r[0]),&(a[0]),&(a[n]),n);
+		bn_sub_words(&(r[n]),&(b[0]),&(b[n]),n);
+		neg=1;
+		break;
+	case 3:
+		zero=1;
+		break;
+	case 4:
+		bn_sub_words(&(r[0]),&(a[0]),&(a[n]),n);
+		bn_sub_words(&(r[n]),&(b[n]),&(b[0]),n);
+		break;
+		}
+		
+	oneg=neg;
+	/* t[10] = (a[0]-a[1])*(b[1]-b[0]) */
+	/* r[10] = (a[1]*b[1]) */
+#ifdef BN_MUL_COMBA
+	if (n == 8)
+		{
+		bn_mul_comba8(&(t[0]),&(r[0]),&(r[n]));
+		bn_mul_comba8(r,&(a[n]),&(b[n]));
+		}
+	else
+#endif
+		{
+		bn_mul_recursive(&(t[0]),&(r[0]),&(r[n]),n,&(t[n2]));
+		bn_mul_recursive(r,&(a[n]),&(b[n]),n,&(t[n2]));
+		}
+
+	/* s0 == low(al*bl)
+	 * s1 == low(ah*bh)+low((al-ah)*(bh-bl))+low(al*bl)+high(al*bl)
+	 * We know s0 and s1 so the only unknown is high(al*bl)
+	 * high(al*bl) == s1 - low(ah*bh+s0+(al-ah)*(bh-bl))
+	 * high(al*bl) == s1 - (r[0]+l[0]+t[0])
+	 */
+	if (l != NULL)
+		{
+		lp= &(t[n2+n]);
+		c1=bn_add_words(lp,&(r[0]),&(l[0]),n);
+		}
+	else
+		{
+		c1=0;
+		lp= &(r[0]);
+		}
+
+	if (neg)
+		neg=bn_sub_words(&(t[n2]),lp,&(t[0]),n);
+	else
+		{
+		bn_add_words(&(t[n2]),lp,&(t[0]),n);
+		neg=0;
+		}
+
+	if (l != NULL)
+		{
+		bn_sub_words(&(t[n2+n]),&(l[n]),&(t[n2]),n);
+		}
+	else
+		{
+		lp= &(t[n2+n]);
+		mp= &(t[n2]);
+		for (i=0; i<n; i++)
+			lp[i]=((~mp[i])+1)&BN_MASK2;
+		}
+
+	/* s[0] = low(al*bl)
+	 * t[3] = high(al*bl)
+	 * t[10] = (a[0]-a[1])*(b[1]-b[0]) neg is the sign
+	 * r[10] = (a[1]*b[1])
+	 */
+	/* R[10] = al*bl
+	 * R[21] = al*bl + ah*bh + (a[0]-a[1])*(b[1]-b[0])
+	 * R[32] = ah*bh
+	 */
+	/* R[1]=t[3]+l[0]+r[0](+-)t[0] (have carry/borrow)
+	 * R[2]=r[0]+t[3]+r[1](+-)t[1] (have carry/borrow)
+	 * R[3]=r[1]+(carry/borrow)
+	 */
+	if (l != NULL)
+		{
+		lp= &(t[n2]);
+		c1= bn_add_words(lp,&(t[n2+n]),&(l[0]),n);
+		}
+	else
+		{
+		lp= &(t[n2+n]);
+		c1=0;
+		}
+	c1+=bn_add_words(&(t[n2]),lp,  &(r[0]),n);
+	if (oneg)
+		c1-=bn_sub_words(&(t[n2]),&(t[n2]),&(t[0]),n);
+	else
+		c1+=bn_add_words(&(t[n2]),&(t[n2]),&(t[0]),n);
+
+	c2 =bn_add_words(&(r[0]),&(r[0]),&(t[n2+n]),n);
+	c2+=bn_add_words(&(r[0]),&(r[0]),&(r[n]),n);
+	if (oneg)
+		c2-=bn_sub_words(&(r[0]),&(r[0]),&(t[n]),n);
+	else
+		c2+=bn_add_words(&(r[0]),&(r[0]),&(t[n]),n);
+	
+	if (c1 != 0) /* Add starting at r[0], could be +ve or -ve */
+		{
+		i=0;
+		if (c1 > 0)
+			{
+			lc=c1;
+			do	{
+				ll=(r[i]+lc)&BN_MASK2;
+				r[i++]=ll;
+				lc=(lc > ll);
+				} while (lc);
+			}
+		else
+			{
+			lc= -c1;
+			do	{
+				ll=r[i];
+				r[i++]=(ll-lc)&BN_MASK2;
+				lc=(lc > ll);
+				} while (lc);
+			}
+		}
+	if (c2 != 0) /* Add starting at r[1] */
+		{
+		i=n;
+		if (c2 > 0)
+			{
+			lc=c2;
+			do	{
+				ll=(r[i]+lc)&BN_MASK2;
+				r[i++]=ll;
+				lc=(lc > ll);
+				} while (lc);
+			}
+		else
+			{
+			lc= -c2;
+			do	{
+				ll=r[i];
+				r[i++]=(ll-lc)&BN_MASK2;
+				lc=(lc > ll);
+				} while (lc);
+			}
+		}
 	}
 #endif
+
+int BN_mul(r,a,b,ctx)
+BIGNUM *r,*a,*b;
+BN_CTX *ctx;
+	{
+	int top,i,j,k,al,bl;
+	BIGNUM *t;
+
+	t=NULL;
+	i=j=k=0;
+
+#ifdef BN_COUNT
+printf("BN_mul %d * %d\n",a->top,b->top);
+#endif
+
+	bn_check_top(a);
+	bn_check_top(b);
+	bn_check_top(r);
+
+	al=a->top;
+	bl=b->top;
+	r->neg=a->neg^b->neg;
+
+	if ((al == 0) || (bl == 0))
+		{
+		BN_zero(r);
+		return(1);
+		}
+	top=al+bl;
+#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
+	if (al == bl)
+		{
+#  ifdef BN_MUL_COMBA
+/*		if (al == 4)
+			{
+			if (bn_wexpand(r,8) == NULL) return(0);
+			r->top=8;
+			bn_mul_comba4(r->d,a->d,b->d);
+			goto end;
+			}
+		else */ if (al == 8)
+			{
+			if (bn_wexpand(r,16) == NULL) return(0);
+			r->top=16;
+			bn_mul_comba8(r->d,a->d,b->d);
+			goto end;
+			}
+		else
+#  endif
+#ifdef BN_RECURSION
+		if (al < BN_MULL_SIZE_NORMAL)
+#endif
+			{
+			if (bn_wexpand(r,top) == NULL) return(0);
+			r->top=top;
+			bn_mul_normal(r->d,a->d,al,b->d,bl);
+			goto end;
+			}
+#  ifdef BN_RECURSION
+		goto symetric;
+#  endif
+		}
+#endif
+#ifdef BN_RECURSION
+	else if ((al < BN_MULL_SIZE_NORMAL) || (bl < BN_MULL_SIZE_NORMAL))
+		{
+		if (bn_wexpand(r,top) == NULL) return(0);
+		r->top=top;
+		bn_mul_normal(r->d,a->d,al,b->d,bl);
+		goto end;
+		}
+	else
+		{
+		i=(al-bl);
+		if ((i ==  1) && !BN_get_flags(b,BN_FLG_STATIC_DATA))
+			{
+			bn_wexpand(b,al);
+			b->d[bl]=0;
+			bl++;
+			goto symetric;
+			}
+		else if ((i ==  -1) && !BN_get_flags(a,BN_FLG_STATIC_DATA))
+			{
+			bn_wexpand(a,bl);
+			a->d[al]=0;
+			al++;
+			goto symetric;
+			}
+		}
+#endif
+
+	/* asymetric and >= 4 */ 
+	if (bn_wexpand(r,top) == NULL) return(0);
+	r->top=top;
+	bn_mul_normal(r->d,a->d,al,b->d,bl);
+
+#ifdef BN_RECURSION
+	if (0)
+		{
+symetric:
+		/* symetric and > 4 */
+		/* 16 or larger */
+		j=BN_num_bits_word((BN_ULONG)al);
+		j=1<<(j-1);
+		k=j+j;
+		t= &(ctx->bn[ctx->tos]);
+		if (al == j) /* exact multiple */
+			{
+			bn_wexpand(t,k*2);
+			bn_wexpand(r,k*2);
+			bn_mul_recursive(r->d,a->d,b->d,al,t->d);
+			}
+		else
+			{
+			bn_wexpand(a,k);
+			bn_wexpand(b,k);
+			bn_wexpand(t,k*4);
+			bn_wexpand(r,k*4);
+			for (i=a->top; i<k; i++)
+				a->d[i]=0;
+			for (i=b->top; i<k; i++)
+				b->d[i]=0;
+			bn_mul_part_recursive(r->d,a->d,b->d,al-j,j,t->d);
+			}
+		r->top=top;
+		}
+#endif
+end:
+	bn_fix_top(r);
+	return(1);
+	}
+
+void bn_mul_normal(r,a,na,b,nb)
+BN_ULONG *r,*a;
+int na;
+BN_ULONG *b;
+int nb;
+	{
+	BN_ULONG *rr;
+
+#ifdef BN_COUNT
+printf(" bn_mul_normal %d * %d\n",na,nb);
+#endif
+
+	if (na < nb)
+		{
+		int itmp;
+		BN_ULONG *ltmp;
+
+		itmp=na; na=nb; nb=itmp;
+		ltmp=a;   a=b;   b=ltmp;
+
+		}
+	rr= &(r[na]);
+	rr[0]=bn_mul_words(r,a,na,b[0]);
+
+	for (;;)
+		{
+		if (--nb <= 0) return;
+		rr[1]=bn_mul_add_words(&(r[1]),a,na,b[1]);
+		if (--nb <= 0) return;
+		rr[2]=bn_mul_add_words(&(r[2]),a,na,b[2]);
+		if (--nb <= 0) return;
+		rr[3]=bn_mul_add_words(&(r[3]),a,na,b[3]);
+		if (--nb <= 0) return;
+		rr[4]=bn_mul_add_words(&(r[4]),a,na,b[4]);
+		rr+=4;
+		r+=4;
+		b+=4;
+		}
+	}
+
+void bn_mul_low_normal(r,a,b,n)
+BN_ULONG *r,*a,*b;
+int n;
+	{
+#ifdef BN_COUNT
+printf(" bn_mul_low_normal %d * %d\n",n,n);
+#endif
+	bn_mul_words(r,a,n,b[0]);
+
+	for (;;)
+		{
+		if (--n <= 0) return;
+		bn_mul_add_words(&(r[1]),a,n,b[1]);
+		if (--n <= 0) return;
+		bn_mul_add_words(&(r[2]),a,n,b[2]);
+		if (--n <= 0) return;
+		bn_mul_add_words(&(r[3]),a,n,b[3]);
+		if (--n <= 0) return;
+		bn_mul_add_words(&(r[4]),a,n,b[4]);
+		r+=4;
+		b+=4;
+		}
+	}
+
diff --git a/crypto/bn/bn_opts.c b/crypto/bn/bn_opts.c
new file mode 100644
index 0000000..86a03e2
--- /dev/null
+++ b/crypto/bn/bn_opts.c
@@ -0,0 +1,342 @@
+/* crypto/bn/expspeed.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.]
+ */
+
+/* most of this code has been pilfered from my libdes speed.c program */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include "crypto.h"
+#include "tmdiff.h"
+#include "bn.h"
+#include "err.h"
+
+#define DEFAULT_SIZE	512
+#define DEFAULT_TIME	3
+
+int verbose=1;
+
+typedef struct parms_st
+	{
+	char *name;
+	void (*func)();
+	BIGNUM r;
+	BIGNUM a;
+	BIGNUM b;
+	BIGNUM c;
+	BIGNUM low;
+	BN_CTX *ctx;
+	BN_MONT_CTX *mont;
+	int w;
+	} PARMS;
+
+void do_mul_exp(int num,PARMS *p);
+void do_mul(int num,PARMS *p);
+void do_sqr(int num,PARMS *p);
+void do_mul_low(int num,PARMS *p);
+void do_mul_high(int num,PARMS *p);
+void do_from_montgomery(int num,PARMS *p);
+int time_it(int sec, PARMS *p);
+void do_it(int sec, PARMS *p);
+
+#define P_EXP	1
+#define P_MUL	2
+#define P_SQR	3
+#define P_MULL	4
+#define P_MULH	5
+#define P_MRED	6
+
+int main(argc,argv)
+int argc;
+char **argv;
+	{
+	PARMS p;
+	BN_MONT_CTX *mont;
+	int size=0,num;
+	char *name;
+	int type=P_EXP;
+
+	mont=BN_MONT_CTX_new();
+	p.mont=NULL;
+	p.ctx=BN_CTX_new();
+	BN_init(&p.r);
+	BN_init(&p.a);
+	BN_init(&p.b);
+	BN_init(&p.c);
+	BN_init(&p.low);
+	p.w=0;
+
+	for (;;)
+		{
+		if (argc > 1)
+			{
+			if (argv[1][0] == '-')
+				{
+				switch(argv[1][1])
+					{
+				case 'e': type=P_EXP; break;
+				case 'm': type=P_MUL; break;
+				case 's': type=P_SQR; break;
+				case 'l': type=P_MULL; break;
+				case 'h': type=P_MULH; break;
+				case 'r': type=P_MRED; break;
+				default:
+					fprintf(stderr,"options: -[emslhr]\n");
+					exit(1);
+					}
+				}
+			else
+				{
+				size=atoi(argv[1]);
+				}
+			argc--;
+			argv++;
+			}
+		else
+			break;
+		}
+	if (size == 0)
+		size=DEFAULT_SIZE;
+
+	printf("bit size:%5d\n",size);
+
+	BN_rand(&p.a,size,1,0);
+	BN_rand(&p.b,size,1,0);
+	BN_rand(&p.c,size,1,1);
+	BN_mod(&p.a,&p.a,&p.c,p.ctx);
+	BN_mod(&p.b,&p.b,&p.c,p.ctx);
+	p.w=(p.a.top+1)/2;
+
+	BN_mul(&p.low,&p.a,&p.b,p.ctx);
+	p.low.top=p.a.top;
+	
+	switch(type)
+		{
+	case P_EXP:
+		p.name="r=a^b%c";
+		p.func=do_mul_exp;
+		p.mont=mont;
+		break;
+	case P_MUL:
+		p.name="r=a*b";
+		p.func=do_mul;
+		break;
+	case P_SQR:
+		p.name="r=a*a";
+		p.func=do_sqr;
+		break;
+	case P_MULL:
+		p.name="r=low(a*b)";
+		p.func=do_mul_low;
+		break;
+	case P_MULH:
+		p.name="r=high(a*b)";
+		p.func=do_mul_high;
+		break;
+	case P_MRED:
+		p.name="r=montgomery_reduction(a)";
+		p.func=do_from_montgomery;
+		p.mont=mont;
+		break;
+	default:
+		fprintf(stderr,"options: -[emslhr]\n");
+		exit(1);
+		}
+
+	num=time_it(DEFAULT_TIME,&p);
+	do_it(num,&p);
+	}
+
+void do_it(num,p)
+int num;
+PARMS *p;
+	{
+	char *start,*end;
+	int i,j,number;
+	double d;
+
+	start=ms_time_new();
+	end=ms_time_new();
+
+	number=BN_num_bits_word((BN_ULONG)BN_num_bits(&(p->c)))-
+		BN_num_bits_word(BN_BITS2)+2;
+	for (i=number-1; i >=0; i--)
+		{
+		if (i == 1) continue;
+		BN_set_params(i,i,i,1);
+		if (p->mont != NULL)
+			BN_MONT_CTX_set(p->mont,&(p->c),p->ctx);
+
+		printf("Timing %5d (%2d bit) %2d %2d %2d %2d :",
+			(1<<i)*BN_BITS2,i,
+				BN_get_params(0),
+				BN_get_params(1),
+				BN_get_params(2),
+				BN_get_params(3));
+		fflush(stdout);
+
+		ms_time_get(start);
+		p->func(num,p);
+		ms_time_get(end);
+		d=ms_time_diff(start,end);
+		printf("%6.6f sec, or %d in %.4f seconds\n",
+			(double)d/num,num,d);
+		}
+	}
+
+int time_it(sec,p)
+int sec;
+PARMS *p;
+	{
+	char *start,*end;
+	int i,j;
+	double d;
+
+	if (p->mont != NULL)
+		BN_MONT_CTX_set(p->mont,&(p->c),p->ctx);
+
+	start=ms_time_new();
+	end=ms_time_new();
+
+	i=1;
+	for (;;)
+		{
+		if (verbose)
+			printf("timing %s for %d interations\n",p->name,i);
+
+		ms_time_get(start);
+		p->func(i,p);
+		ms_time_get(end);
+		d=ms_time_diff(start,end);
+
+		if 	(d < 0.01) i*=100;
+		else if (d < 0.1 ) i*=10;
+		else if (d > (double)sec) break;
+		else
+			{
+			i=(int)(1.0*i*sec/d);
+			break;
+			}
+		}
+	if (verbose)
+		printf("using %d interations\n",i);
+	return(i);
+	}
+
+void do_mul_exp(num,p)
+int num;
+PARMS *p;
+	{
+	int i;
+
+	for (i=0; i<num; i++)
+		BN_mod_exp_mont(&(p->r),&(p->a),&(p->b),&(p->c),
+			p->ctx,p->mont);
+	}
+
+void do_mul(num,p)
+int num;
+PARMS *p;
+	{
+	int i;
+
+	for (i=0; i<num; i++)
+		BN_mul(&(p->r),&(p->a),&(p->b),p->ctx);
+	}
+
+void do_sqr(num,p)
+int num;
+PARMS *p;
+	{
+	int i;
+
+	for (i=0; i<num; i++)
+			BN_sqr(&(p->r),&(p->a),p->ctx);
+	}
+
+void do_mul_low(num,p)
+int num;
+PARMS *p;
+	{
+	int i;
+	
+	for (i=0; i<num; i++)
+		BN_mul_low(&(p->r),&(p->a),&(p->b),p->w,p->ctx);
+	}
+
+void do_mul_high(num,p)
+int num;
+PARMS *p;
+	{
+	int i;
+
+	for (i=0; i<num; i++)
+		BN_mul_low(&(p->r),&(p->a),&(p->b),&(p->low),p->w,p->ctx);
+	}
+
+void do_from_montgomery(num,p)
+int num;
+PARMS *p;
+	{
+	int i;
+	
+	for (i=0; i<num; i++)
+		BN_from_montgomery(&(p->r),&(p->a),p->mont,p->ctx);
+	}
+
diff --git a/crypto/bn/bn_prime.c b/crypto/bn/bn_prime.c
index 0c85f70..c4fb58e 100644
--- a/crypto/bn/bn_prime.c
+++ b/crypto/bn/bn_prime.c
@@ -83,7 +83,8 @@
 static int probable_prime_dh_strong();
 #endif
 
-BIGNUM *BN_generate_prime(bits,strong,add,rem,callback,cb_arg)
+BIGNUM *BN_generate_prime(ret,bits,strong,add,rem,callback,cb_arg)
+BIGNUM *ret;
 int bits;
 int strong;
 BIGNUM *add;
@@ -92,16 +93,19 @@
 char *cb_arg;
 	{
 	BIGNUM *rnd=NULL;
-	BIGNUM *ret=NULL;
-	BIGNUM *t=NULL;
+	BIGNUM t;
 	int i,j,c1=0;
 	BN_CTX *ctx;
 
 	ctx=BN_CTX_new();
 	if (ctx == NULL) goto err;
-	if ((rnd=BN_new()) == NULL) goto err;
-	if (strong)
-		if ((t=BN_new()) == NULL) goto err;
+	if (ret == NULL)
+		{
+		if ((rnd=BN_new()) == NULL) goto err;
+		}
+	else
+		rnd=ret;
+	BN_init(&t);
 loop: 
 	/* make a random number and set the top and bottom bits */
 	if (add == NULL)
@@ -136,7 +140,7 @@
 		 * check that (p-1)/2 is prime.
 		 * Since a prime is odd, We just
 		 * need to divide by 2 */
-		if (!BN_rshift1(t,rnd)) goto err;
+		if (!BN_rshift1(&t,rnd)) goto err;
 
 		for (i=0; i<BN_prime_checks; i++)
 			{
@@ -144,7 +148,7 @@
 			if (j == -1) goto err;
 			if (j == 0) goto loop;
 
-			j=BN_is_prime(t,1,callback,ctx,cb_arg);
+			j=BN_is_prime(&t,1,callback,ctx,cb_arg);
 			if (j == -1) goto err;
 			if (j == 0) goto loop;
 
@@ -156,7 +160,7 @@
 	ret=rnd;
 err:
 	if ((ret == NULL) && (rnd != NULL)) BN_free(rnd);
-	if (t != NULL) BN_free(t);
+	BN_free(&t);
 	if (ctx != NULL) BN_CTX_free(ctx);
 	return(ret);
 	}
@@ -183,7 +187,7 @@
 	if ((ctx2=BN_CTX_new()) == NULL) goto err;
 	if ((mont=BN_MONT_CTX_new()) == NULL) goto err;
 
-	check=ctx->bn[ctx->tos++];
+	check= &(ctx->bn[ctx->tos++]);
 
 	/* Setup the montgomery structure */
 	if (!BN_MONT_CTX_set(mont,a,ctx2)) goto err;
@@ -224,14 +228,14 @@
 	BIGNUM *d,*dd,*tmp,*d1,*d2,*n1;
 	BIGNUM *mont_one,*mont_n1,*mont_a;
 
-	d1=ctx->bn[ctx->tos];
-	d2=ctx->bn[ctx->tos+1];
-	n1=ctx->bn[ctx->tos+2];
+	d1= &(ctx->bn[ctx->tos]);
+	d2= &(ctx->bn[ctx->tos+1]);
+	n1= &(ctx->bn[ctx->tos+2]);
 	ctx->tos+=3;
 
-	mont_one=ctx2->bn[ctx2->tos];
-	mont_n1=ctx2->bn[ctx2->tos+1];
-	mont_a=ctx2->bn[ctx2->tos+2];
+	mont_one= &(ctx2->bn[ctx2->tos]);
+	mont_n1= &(ctx2->bn[ctx2->tos+1]);
+	mont_a= &(ctx2->bn[ctx2->tos+2]);
 	ctx2->tos+=3;
 
 	d=d1;
@@ -287,8 +291,9 @@
 	{
 	int i;
 	MS_STATIC BN_ULONG mods[NUMPRIMES];
-	BN_ULONG delta;
+	BN_ULONG delta,d;
 
+again:
 	if (!BN_rand(rnd,bits,1,1)) return(0);
 	/* we now have a random number 'rand' to test. */
 	for (i=1; i<NUMPRIMES; i++)
@@ -300,9 +305,12 @@
 		 * that gcd(rnd-1,primes) == 1 (except for 2) */
 		if (((mods[i]+delta)%primes[i]) <= 1)
 			{
+			d=delta;
 			delta+=2;
 			/* perhaps need to check for overflow of
-			 * delta (but delta can be upto 2^32) */
+			 * delta (but delta can be upto 2^32)
+			 * 21-May-98 eay - added overflow check */
+			if (delta < d) goto again;
 			goto loop;
 			}
 		}
@@ -320,7 +328,7 @@
 	int i,ret=0;
 	BIGNUM *t1;
 
-	t1=ctx->bn[ctx->tos++];
+	t1= &(ctx->bn[ctx->tos++]);
 
 	if (!BN_rand(rnd,bits,0,1)) goto err;
 
@@ -361,9 +369,9 @@
 	BIGNUM *t1,*qadd=NULL,*q=NULL;
 
 	bits--;
-	t1=ctx->bn[ctx->tos++];
-	q=ctx->bn[ctx->tos++];
-	qadd=ctx->bn[ctx->tos++];
+	t1= &(ctx->bn[ctx->tos++]);
+	q= &(ctx->bn[ctx->tos++]);
+	qadd= &(ctx->bn[ctx->tos++]);
 
 	if (!BN_rshift1(qadd,padd)) goto err;
 		
@@ -413,11 +421,11 @@
 	BIGNUM *d,*dd,*tmp;
 	BIGNUM *d1,*d2,*x,*n1,*inv;
 
-	d1=ctx->bn[ctx->tos];
-	d2=ctx->bn[ctx->tos+1];
-	x=ctx->bn[ctx->tos+2];
-	n1=ctx->bn[ctx->tos+3];
-	inv=ctx->bn[ctx->tos+4];
+	d1= &(ctx->bn[ctx->tos]);
+	d2= &(ctx->bn[ctx->tos+1]);
+	x=  &(ctx->bn[ctx->tos+2]);
+	n1= &(ctx->bn[ctx->tos+3]);
+	inv=&(ctx->bn[ctx->tos+4]);
 	ctx->tos+=5;
 
 	d=d1;
diff --git a/crypto/bn/bn_recp.c b/crypto/bn/bn_recp.c
index 72cd69d..97ca857 100644
--- a/crypto/bn/bn_recp.c
+++ b/crypto/bn/bn_recp.c
@@ -60,66 +60,182 @@
 #include "cryptlib.h"
 #include "bn_lcl.h"
 
-int BN_mod_mul_reciprocal(r, x, y, m, i, nb, ctx)
+void BN_RECP_CTX_init(recp)
+BN_RECP_CTX *recp;
+	{
+	BN_init(&(recp->N));
+	BN_init(&(recp->Nr));
+	recp->num_bits=0;
+	recp->flags=0;
+	}
+
+BN_RECP_CTX *BN_RECP_CTX_new()
+	{
+	BN_RECP_CTX *ret;
+
+	if ((ret=(BN_RECP_CTX *)Malloc(sizeof(BN_RECP_CTX))) == NULL)
+		return(NULL);
+
+	BN_RECP_CTX_init(ret);
+	ret->flags=BN_FLG_MALLOCED;
+	return(ret);
+	}
+
+void BN_RECP_CTX_free(recp)
+BN_RECP_CTX *recp;
+	{
+	BN_free(&(recp->N));
+	BN_free(&(recp->Nr));
+	if (recp->flags & BN_FLG_MALLOCED)
+		Free(recp);
+	}
+
+int BN_RECP_CTX_set(recp,d,ctx)
+BN_RECP_CTX *recp;
+BIGNUM *d;
+BN_CTX *ctx;
+	{
+	BN_copy(&(recp->N),d);
+	BN_zero(&(recp->Nr));
+	recp->num_bits=BN_num_bits(d);
+	recp->shift=0;
+	return(1);
+	}
+
+int BN_mod_mul_reciprocal(r, x, y, recp, ctx)
 BIGNUM *r;
 BIGNUM *x;
 BIGNUM *y;
-BIGNUM *m;
-BIGNUM *i;
-int nb;
+BN_RECP_CTX *recp;
 BN_CTX *ctx;
 	{
-	int ret=0,j;
-	BIGNUM *a,*b,*c,*d;
+	int ret=0;
+	BIGNUM *a;
 
-	a=ctx->bn[ctx->tos++];
-	b=ctx->bn[ctx->tos++];
-	c=ctx->bn[ctx->tos++];
-	d=ctx->bn[ctx->tos++];
-
-	if (x == y)
-		{ if (!BN_sqr(a,x,ctx)) goto err; }
+	a= &(ctx->bn[ctx->tos++]);
+	if (y != NULL)
+		{
+		if (x == y)
+			{ if (!BN_sqr(a,x,ctx)) goto err; }
+		else
+			{ if (!BN_mul(a,x,y,ctx)) goto err; }
+		}
 	else
-		{ if (!BN_mul(a,x,y)) goto err; }
-	if (!BN_rshift(d,a,nb)) goto err;
-	if (!BN_mul(b,d,i)) goto err;
-	if (!BN_rshift(c,b,nb)) goto err;
-	if (!BN_mul(b,m,c)) goto err;
-	if (!BN_sub(r,a,b)) goto err;
+		a=x; /* Just do the mod */
+
+	BN_div_recp(NULL,r,a,recp,ctx);
+	ret=1;
+err:
+	ctx->tos--;
+	return(ret);
+	}
+
+int BN_div_recp(dv,rem,m,recp,ctx)
+BIGNUM *dv;
+BIGNUM *rem;
+BIGNUM *m;
+BN_RECP_CTX *recp;
+BN_CTX *ctx;
+	{
+	int i,j,tos,ret=0,ex;
+	BIGNUM *a,*b,*d,*r;
+
+	tos=ctx->tos;
+	a= &(ctx->bn[ctx->tos++]);
+	b= &(ctx->bn[ctx->tos++]);
+	if (dv != NULL)
+		d=dv;
+	else
+		d= &(ctx->bn[ctx->tos++]);
+	if (rem != NULL)
+		r=rem;
+	else
+		r= &(ctx->bn[ctx->tos++]);
+
+	if (BN_ucmp(m,&(recp->N)) < 0)
+		{
+		BN_zero(d);
+		BN_copy(r,m);
+		ctx->tos=tos;
+		return(1);
+		}
+
+	/* We want the remainder
+	 * Given input of ABCDEF / ab
+	 * we need multiply ABCDEF by 3 digests of the reciprocal of ab
+	 *
+	 */
+	i=BN_num_bits(m);
+
+	j=recp->num_bits*2;
+	if (j > i)
+		{
+		i=j;
+		ex=0;
+		}
+	else
+		{
+		ex=(i-j)/2;
+		}
+
+	j=i/2;
+
+	if (i != recp->shift)
+		recp->shift=BN_reciprocal(&(recp->Nr),&(recp->N),
+			i,ctx);
+
+	if (!BN_rshift(a,m,j-ex)) goto err;
+	if (!BN_mul(b,a,&(recp->Nr),ctx)) goto err;
+	if (!BN_rshift(d,b,j+ex)) goto err;
+	d->neg=0;
+	if (!BN_mul(b,&(recp->N),d,ctx)) goto err;
+	if (!BN_usub(r,m,b)) goto err;
+	r->neg=0;
+
 	j=0;
-	while (BN_cmp(r,m) >= 0)
+#if 1
+	while (BN_ucmp(r,&(recp->N)) >= 0)
 		{
 		if (j++ > 2)
 			{
 			BNerr(BN_F_BN_MOD_MUL_RECIPROCAL,BN_R_BAD_RECIPROCAL);
 			goto err;
 			}
-		if (!BN_sub(r,r,m)) goto err;
+		if (!BN_usub(r,r,&(recp->N))) goto err;
+		if (!BN_add_word(d,1)) goto err;
 		}
+#endif
 
+	r->neg=BN_is_zero(r)?0:m->neg;
+	d->neg=m->neg^recp->N.neg;
 	ret=1;
 err:
-	ctx->tos-=4;
+	ctx->tos=tos;
 	return(ret);
-	}
+	} 
 
-int BN_reciprocal(r, m,ctx)
+/* len is the expected size of the result
+ * We actually calculate with an extra word of precision, so
+ * we can do faster division if the remainder is not required.
+ */
+int BN_reciprocal(r,m,len,ctx)
 BIGNUM *r;
 BIGNUM *m;
+int len;
 BN_CTX *ctx;
 	{
-	int nm,ret= -1;
-	BIGNUM *t;
+	int ret= -1;
+	BIGNUM t;
 
-	t=ctx->bn[ctx->tos++];
+	BN_init(&t);
 
-	nm=BN_num_bits(m);
-	if (!BN_lshift(t,BN_value_one(),nm*2)) goto err;
+	BN_zero(&t);
+	if (!BN_set_bit(&t,len)) goto err;
 
-	if (!BN_div(r,NULL,t,m,ctx)) goto err;
-	ret=nm;
+	if (!BN_div(r,NULL,&t,m,ctx)) goto err;
+	ret=len;
 err:
-	ctx->tos--;
+	BN_free(&t);
 	return(ret);
 	}
 
diff --git a/crypto/bn/bn_sqr.c b/crypto/bn/bn_sqr.c
index a846461..19ec0dd 100644
--- a/crypto/bn/bn_sqr.c
+++ b/crypto/bn/bn_sqr.c
@@ -67,30 +67,84 @@
 BIGNUM *a;
 BN_CTX *ctx;
 	{
-	int i,j,max,al;
+	int max,al;
 	BIGNUM *tmp;
-	BN_ULONG *ap,*rp;
 
-	tmp=ctx->bn[ctx->tos];
+#ifdef BN_COUNT
+printf("BN_sqr %d * %d\n",a->top,a->top);
+#endif
+	bn_check_top(a);
+	tmp= &(ctx->bn[ctx->tos]);
 
 	al=a->top;
-	if (al == 0)
+	if (al <= 0)
 		{
 		r->top=0;
 		return(1);
 		}
 
-	max=(al*2);
-	if (bn_wexpand(r,1+max) == NULL) return(0);
-	if (bn_wexpand(tmp,1+max) == NULL) return(0);
+	max=(al+al);
+	if (bn_wexpand(r,max+1) == NULL) return(0);
 
 	r->neg=0;
+	if (al == 4)
+		{
+#ifndef BN_SQR_COMBA
+		BN_ULONG t[8];
+		bn_sqr_normal(r->d,a->d,4,t);
+#else
+		bn_sqr_comba4(r->d,a->d);
+#endif
+		}
+	else if (al == 8)
+		{
+#ifndef BN_SQR_COMBA
+		BN_ULONG t[16];
+		bn_sqr_normal(r->d,a->d,8,t);
+#else
+		bn_sqr_comba8(r->d,a->d);
+#endif
+		}
+	else 
+		{
+#if defined(BN_RECURSION)
+		if (al < BN_SQR_RECURSIVE_SIZE_NORMAL)
+			{
+			BN_ULONG t[BN_SQR_RECURSIVE_SIZE_NORMAL*2];
+			bn_sqr_normal(r->d,a->d,al,t);
+			}
+		else
+			{
+			if (bn_wexpand(tmp,2*max+1) == NULL) return(0);
+			bn_sqr_recursive(r->d,a->d,al,tmp->d);
+			}
+#else
+		if (bn_wexpand(tmp,max) == NULL) return(0);
+		bn_sqr_normal(r->d,a->d,al,tmp->d);
+#endif
+		}
 
-	ap=a->d;
-	rp=r->d;
+	r->top=max;
+	if ((max > 0) && (r->d[max-1] == 0)) r->top--;
+	return(1);
+	}
+
+/* tmp must have 2*n words */
+void bn_sqr_normal(r, a, n, tmp)
+BN_ULONG *r;
+BN_ULONG *a;
+int n;
+BN_ULONG *tmp;
+	{
+	int i,j,max;
+	BN_ULONG *ap,*rp;
+
+	max=n*2;
+	ap=a;
+	rp=r;
 	rp[0]=rp[max-1]=0;
 	rp++;
-	j=al;
+	j=n;
 
 	if (--j > 0)
 		{
@@ -99,7 +153,7 @@
 		rp+=2;
 		}
 
-	for (i=2; i<al; i++)
+	for (i=n-2; i>0; i--)
 		{
 		j--;
 		ap++;
@@ -107,16 +161,115 @@
 		rp+=2;
 		}
 
-	bn_add_words(r->d,r->d,r->d,max);
+	bn_add_words(r,r,r,max);
 
 	/* There will not be a carry */
 
-	bn_sqr_words(tmp->d,a->d,al);
+	bn_sqr_words(tmp,a,n);
 
-	bn_add_words(r->d,r->d,tmp->d,max);
-
-	r->top=max;
-	if (r->d[max-1] == 0) r->top--;
-	return(1);
+	bn_add_words(r,r,tmp,max);
 	}
 
+#ifdef BN_RECURSION
+/* r is 2*n words in size,
+ * a and b are both n words in size.
+ * n must be a power of 2.
+ * We multiply and return the result.
+ * t must be 2*n words in size
+ * We calulate
+ * a[0]*b[0]
+ * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0])
+ * a[1]*b[1]
+ */
+void bn_sqr_recursive(r,a,n2,t)
+BN_ULONG *r,*a;
+int n2;
+BN_ULONG *t;
+	{
+	int n=n2/2;
+	int zero,c1;
+	BN_ULONG ln,lo,*p;
+
+#ifdef BN_COUNT
+printf(" bn_sqr_recursive %d * %d\n",n2,n2);
+#endif
+	if (n2 == 4)
+		{
+#ifndef BN_SQR_COMBA
+		bn_sqr_normal(r,a,4,t);
+#else
+		bn_sqr_comba4(r,a);
+#endif
+		return;
+		}
+	else if (n2 == 8)
+		{
+#ifndef BN_SQR_COMBA
+		bn_sqr_normal(r,a,8,t);
+#else
+		bn_sqr_comba8(r,a);
+#endif
+		return;
+		}
+	if (n2 < BN_SQR_RECURSIVE_SIZE_NORMAL)
+		{
+		bn_sqr_normal(r,a,n2,t);
+		return;
+		}
+	/* r=(a[0]-a[1])*(a[1]-a[0]) */
+	c1=bn_cmp_words(a,&(a[n]),n);
+	zero=0;
+	if (c1 > 0)
+		bn_sub_words(t,a,&(a[n]),n);
+	else if (c1 < 0)
+		bn_sub_words(t,&(a[n]),a,n);
+	else
+		zero=1;
+
+	/* The result will always be negative unless it is zero */
+	p= &(t[n2*2]);
+
+	if (!zero)
+		bn_sqr_recursive(&(t[n2]),t,n,p);
+	else
+		memset(&(t[n2]),0,n*sizeof(BN_ULONG));
+	bn_sqr_recursive(r,a,n,p);
+	bn_sqr_recursive(&(r[n2]),&(a[n]),n,p);
+
+	/* t[32] holds (a[0]-a[1])*(a[1]-a[0]), it is negative or zero
+	 * r[10] holds (a[0]*b[0])
+	 * r[32] holds (b[1]*b[1])
+	 */
+
+	c1=bn_add_words(t,r,&(r[n2]),n2);
+
+	/* t[32] is negative */
+	c1-=bn_sub_words(&(t[n2]),t,&(t[n2]),n2);
+
+	/* t[32] holds (a[0]-a[1])*(a[1]-a[0])+(a[0]*a[0])+(a[1]*a[1])
+	 * r[10] holds (a[0]*a[0])
+	 * r[32] holds (a[1]*a[1])
+	 * c1 holds the carry bits
+	 */
+	c1+=bn_add_words(&(r[n]),&(r[n]),&(t[n2]),n2);
+	if (c1)
+		{
+		p= &(r[n+n2]);
+		lo= *p;
+		ln=(lo+c1)&BN_MASK2;
+		*p=ln;
+
+		/* The overflow will stop before we over write
+		 * words we should not overwrite */
+		if (ln < (BN_ULONG)c1)
+			{
+			do	{
+				p++;
+				lo= *p;
+				ln=(lo+1)&BN_MASK2;
+				*p=ln;
+				} while (ln == 0);
+			}
+		}
+	}
+#endif
diff --git a/crypto/bn/bn_word.c b/crypto/bn/bn_word.c
index 4b3d0f01..9c168e4 100644
--- a/crypto/bn/bn_word.c
+++ b/crypto/bn/bn_word.c
@@ -62,7 +62,7 @@
 
 BN_ULONG BN_mod_word(a, w)
 BIGNUM *a;
-unsigned long w;
+BN_ULONG w;
 	{
 #ifndef BN_LLONG
 	BN_ULONG ret=0;
@@ -75,8 +75,8 @@
 	for (i=a->top-1; i>=0; i--)
 		{
 #ifndef BN_LLONG
-		ret=((ret<<BN_BITS4)|((a->d[i]>>BN_BITS4)&BN_MASK2l))%(unsigned long)w;
-		ret=((ret<<BN_BITS4)|(a->d[i]&BN_MASK2l))%(unsigned long)w;
+		ret=((ret<<BN_BITS4)|((a->d[i]>>BN_BITS4)&BN_MASK2l))%w;
+		ret=((ret<<BN_BITS4)|(a->d[i]&BN_MASK2l))%w;
 #else
 		ret=(BN_ULLONG)(((ret<<(BN_ULLONG)BN_BITS2)|a->d[i])%
 			(BN_ULLONG)w);
@@ -87,7 +87,7 @@
 
 BN_ULONG BN_div_word(a, w)
 BIGNUM *a;
-unsigned long w;
+BN_ULONG w;
 	{
 	BN_ULONG ret;
 	int i;
@@ -100,18 +100,18 @@
 		BN_ULONG l,d;
 		
 		l=a->d[i];
-		d=bn_div64(ret,l,w);
+		d=bn_div_words(ret,l,w);
 		ret=(l-((d*w)&BN_MASK2))&BN_MASK2;
 		a->d[i]=d;
 		}
-	if (a->d[a->top-1] == 0)
+	if ((a->top > 0) && (a->d[a->top-1] == 0))
 		a->top--;
 	return(ret);
 	}
 
 int BN_add_word(a, w)
 BIGNUM *a;
-unsigned long w;
+BN_ULONG w;
 	{
 	BN_ULONG l;
 	int i;
@@ -144,7 +144,7 @@
 
 int BN_sub_word(a, w)
 BIGNUM *a;
-unsigned long w;
+BN_ULONG w;
 	{
 	int i;
 
@@ -185,7 +185,7 @@
 
 int BN_mul_word(a,w)
 BIGNUM *a;
-unsigned long w;
+BN_ULONG w;
 	{
 	BN_ULONG ll;
 
@@ -199,6 +199,6 @@
 			a->d[a->top++]=ll;
 			}
 		}
-	return(0);
+	return(1);
 	}
 
diff --git a/crypto/bn/bnspeed.c b/crypto/bn/bnspeed.c
index f7c2790..777212c 100644
--- a/crypto/bn/bnspeed.c
+++ b/crypto/bn/bnspeed.c
@@ -94,7 +94,8 @@
 #include <sys/timeb.h>
 #endif
 
-#ifdef sun
+#if defined(sun) || defined(__ultrix)
+#define _POSIX_SOURCE
 #include <limits.h>
 #include <sys/param.h>
 #endif
@@ -180,15 +181,14 @@
 char **argv;
 	{
 	BN_CTX *ctx;
-	BIGNUM *a,*b,*c,*r;
+	BIGNUM a,b,c;
 
 	ctx=BN_CTX_new();
-	a=BN_new();
-	b=BN_new();
-	c=BN_new();
-	r=BN_new();
+	BN_init(&a);
+	BN_init(&b);
+	BN_init(&c);
 
-	do_mul(a,b,c,ctx);
+	do_mul(&a,&b,&c,ctx);
 	}
 
 void do_mul(r,a,b,ctx)
@@ -211,7 +211,7 @@
 			BN_rand(b,sizes[j],1,0);
 			Time_F(START);
 			for (k=0; k<num; k++)
-				BN_mul(r,b,a);
+				BN_mul(r,b,a,ctx);
 			tm=Time_F(STOP);
 			printf("mul %4d x %4d -> %8.3fms\n",sizes[i],sizes[j],tm*1000.0/num);
 			}
diff --git a/crypto/bn/bntest.c b/crypto/bn/bntest.c
index 9ebd68b..ec48bad 100644
--- a/crypto/bn/bntest.c
+++ b/crypto/bn/bntest.c
@@ -71,19 +71,20 @@
 #endif
 
 #ifndef NOPROTO
-int test_add (BIO *bp);
-int test_sub (BIO *bp);
-int test_lshift1 (BIO *bp);
-int test_lshift (BIO *bp);
-int test_rshift1 (BIO *bp);
-int test_rshift (BIO *bp);
-int test_div (BIO *bp,BN_CTX *ctx);
-int test_mul (BIO *bp);
-int test_sqr (BIO *bp,BN_CTX *ctx);
-int test_mont (BIO *bp,BN_CTX *ctx);
-int test_mod (BIO *bp,BN_CTX *ctx);
-int test_mod_mul (BIO *bp,BN_CTX *ctx);
-int test_mod_exp (BIO *bp,BN_CTX *ctx);
+int test_add(BIO *bp);
+int test_sub(BIO *bp);
+int test_lshift1(BIO *bp);
+int test_lshift(BIO *bp);
+int test_rshift1(BIO *bp);
+int test_rshift(BIO *bp);
+int test_div(BIO *bp,BN_CTX *ctx);
+int test_div_recp(BIO *bp,BN_CTX *ctx);
+int test_mul(BIO *bp);
+int test_sqr(BIO *bp,BN_CTX *ctx);
+int test_mont(BIO *bp,BN_CTX *ctx);
+int test_mod(BIO *bp,BN_CTX *ctx);
+int test_mod_mul(BIO *bp,BN_CTX *ctx);
+int test_mod_exp(BIO *bp,BN_CTX *ctx);
 int rand_neg(void);
 #else
 int test_add ();
@@ -192,6 +193,10 @@
 	if (!test_div(out,ctx)) goto err;
 	fflush(stdout);
 
+	fprintf(stderr,"test BN_div_recp\n");
+	if (!test_div_recp(out,ctx)) goto err;
+	fflush(stdout);
+
 	fprintf(stderr,"test BN_mod\n");
 	if (!test_mod(out,ctx)) goto err;
 	fflush(stdout);
@@ -221,80 +226,80 @@
 int test_add(bp)
 BIO *bp;
 	{
-	BIGNUM *a,*b,*c;
+	BIGNUM a,b,c;
 	int i;
 	int j;
 
-	a=BN_new();
-	b=BN_new();
-	c=BN_new();
+	BN_init(&a);
+	BN_init(&b);
+	BN_init(&c);
 
-	BN_rand(a,512,0,0);
+	BN_rand(&a,512,0,0);
 	for (i=0; i<100; i++)
 		{
-		BN_rand(b,450+i,0,0);
-		a->neg=rand_neg();
-		b->neg=rand_neg();
+		BN_rand(&b,450+i,0,0);
+		a.neg=rand_neg();
+		b.neg=rand_neg();
 		if (bp == NULL)
 			for (j=0; j<10000; j++)
-				BN_add(c,a,b);
-		BN_add(c,a,b);
+				BN_add(&c,&a,&b);
+		BN_add(&c,&a,&b);
 		if (bp != NULL)
 			{
 			if (!results)
 				{
-				BN_print(bp,a);
+				BN_print(bp,&a);
 				BIO_puts(bp," + ");
-				BN_print(bp,b);
+				BN_print(bp,&b);
 				BIO_puts(bp," - ");
 				}
-			BN_print(bp,c);
+			BN_print(bp,&c);
 			BIO_puts(bp,"\n");
 			}
 		}
-	BN_free(a);
-	BN_free(b);
-	BN_free(c);
+	BN_free(&a);
+	BN_free(&b);
+	BN_free(&c);
 	return(1);
 	}
 
 int test_sub(bp)
 BIO *bp;
 	{
-	BIGNUM *a,*b,*c;
+	BIGNUM a,b,c;
 	int i;
 	int j;
 
-	a=BN_new();
-	b=BN_new();
-	c=BN_new();
+	BN_init(&a);
+	BN_init(&b);
+	BN_init(&c);
 
-	BN_rand(a,512,0,0);
+	BN_rand(&a,512,0,0);
 	for (i=0; i<100; i++)
 		{
-		BN_rand(b,400+i,0,0);
-		a->neg=rand_neg();
-		b->neg=rand_neg();
+		BN_rand(&b,400+i,0,0);
+		a.neg=rand_neg();
+		b.neg=rand_neg();
 		if (bp == NULL)
 			for (j=0; j<10000; j++)
-				BN_sub(c,a,b);
-		BN_sub(c,a,b);
+				BN_sub(&c,&a,&b);
+		BN_sub(&c,&a,&b);
 		if (bp != NULL)
 			{
 			if (!results)
 				{
-				BN_print(bp,a);
+				BN_print(bp,&a);
 				BIO_puts(bp," - ");
-				BN_print(bp,b);
+				BN_print(bp,&b);
 				BIO_puts(bp," - ");
 				}
-			BN_print(bp,c);
+			BN_print(bp,&c);
 			BIO_puts(bp,"\n");
 			}
 		}
-	BN_free(a);
-	BN_free(b);
-	BN_free(c);
+	BN_free(&a);
+	BN_free(&b);
+	BN_free(&c);
 	return(1);
 	}
 
@@ -302,92 +307,154 @@
 BIO *bp;
 BN_CTX *ctx;
 	{
-	BIGNUM *a,*b,*c,*d;
+	BIGNUM a,b,c,d;
 	int i;
 	int j;
 
-	a=BN_new();
-	b=BN_new();
-	c=BN_new();
-	d=BN_new();
+	BN_init(&a);
+	BN_init(&b);
+	BN_init(&c);
+	BN_init(&d);
 
-	BN_rand(a,400,0,0);
+	BN_rand(&a,400,0,0);
 	for (i=0; i<100; i++)
 		{
-		BN_rand(b,50+i,0,0);
-		a->neg=rand_neg();
-		b->neg=rand_neg();
+		BN_rand(&b,50+i,0,0);
+		a.neg=rand_neg();
+		b.neg=rand_neg();
 		if (bp == NULL)
 			for (j=0; j<100; j++)
-				BN_div(d,c,a,b,ctx);
-		BN_div(d,c,a,b,ctx);
+				BN_div(&d,&c,&a,&b,ctx);
+		BN_div(&d,&c,&a,&b,ctx);
 		if (bp != NULL)
 			{
 			if (!results)
 				{
-				BN_print(bp,a);
+				BN_print(bp,&a);
 				BIO_puts(bp," / ");
-				BN_print(bp,b);
+				BN_print(bp,&b);
 				BIO_puts(bp," - ");
 				}
-			BN_print(bp,d);
+			BN_print(bp,&d);
 			BIO_puts(bp,"\n");
 
 			if (!results)
 				{
-				BN_print(bp,a);
+				BN_print(bp,&a);
 				BIO_puts(bp," % ");
-				BN_print(bp,b);
+				BN_print(bp,&b);
 				BIO_puts(bp," - ");
 				}
-			BN_print(bp,c);
+			BN_print(bp,&c);
 			BIO_puts(bp,"\n");
 			}
 		}
-	BN_free(a);
-	BN_free(b);
-	BN_free(c);
-	BN_free(d);
+	BN_free(&a);
+	BN_free(&b);
+	BN_free(&c);
+	BN_free(&d);
+	return(1);
+	}
+
+int test_div_recp(bp,ctx)
+BIO *bp;
+BN_CTX *ctx;
+	{
+	BIGNUM a,b,c,d;
+	BN_RECP_CTX recp;
+	int i;
+	int j;
+
+	BN_RECP_CTX_init(&recp);
+	BN_init(&a);
+	BN_init(&b);
+	BN_init(&c);
+	BN_init(&d);
+
+	BN_rand(&a,400,0,0);
+	for (i=0; i<100; i++)
+		{
+		BN_rand(&b,50+i,0,0);
+		a.neg=rand_neg();
+		b.neg=rand_neg();
+		BN_RECP_CTX_set(&recp,&b,ctx);
+		if (bp == NULL)
+			for (j=0; j<100; j++)
+				BN_div_recp(&d,&c,&a,&recp,ctx);
+		BN_div_recp(&d,&c,&a,&recp,ctx);
+		if (bp != NULL)
+			{
+			if (!results)
+				{
+				BN_print(bp,&a);
+				BIO_puts(bp," / ");
+				BN_print(bp,&b);
+				BIO_puts(bp," - ");
+				}
+			BN_print(bp,&d);
+			BIO_puts(bp,"\n");
+
+			if (!results)
+				{
+				BN_print(bp,&a);
+				BIO_puts(bp," % ");
+				BN_print(bp,&b);
+				BIO_puts(bp," - ");
+				}
+			BN_print(bp,&c);
+			BIO_puts(bp,"\n");
+			}
+		}
+	BN_free(&a);
+	BN_free(&b);
+	BN_free(&c);
+	BN_free(&d);
+	BN_RECP_CTX_free(&recp);
 	return(1);
 	}
 
 int test_mul(bp)
 BIO *bp;
 	{
-	BIGNUM *a,*b,*c;
+	BIGNUM a,b,c;
 	int i;
 	int j;
+	BN_CTX ctx;
 
-	a=BN_new();
-	b=BN_new();
-	c=BN_new();
+	BN_CTX_init(&ctx);
+	BN_init(&a);
+	BN_init(&b);
+	BN_init(&c);
 
-	BN_rand(a,200,0,0);
+	BN_rand(&a,200,0,0);
 	for (i=0; i<100; i++)
 		{
-		BN_rand(b,250+i,0,0);
-		a->neg=rand_neg();
-		b->neg=rand_neg();
+		BN_rand(&b,250+i,0,0);
+		BN_rand(&b,200,0,0);
+		a.neg=rand_neg();
+		b.neg=rand_neg();
 		if (bp == NULL)
 			for (j=0; j<100; j++)
-				BN_mul(c,a,b);
-		BN_mul(c,a,b);
+				BN_mul(&c,&a,&b,&ctx);
+		BN_mul(&c,&a,&b,&ctx);
+/*bn_do(&c,&a,&b,ctx); */
 		if (bp != NULL)
 			{
 			if (!results)
 				{
-				BN_print(bp,a);
+				BN_print(bp,&a);
 				BIO_puts(bp," * ");
-				BN_print(bp,b);
+				BN_print(bp,&b);
 				BIO_puts(bp," - ");
 				}
-			BN_print(bp,c);
+			BN_print(bp,&c);
 			BIO_puts(bp,"\n");
 			}
 		}
-	BN_free(a);
-	BN_free(b);
-	BN_free(c);
+	BN_free(&a);
+	BN_free(&b);
+	BN_free(&c);
+	BN_CTX_free(&ctx);
 	return(1);
 	}
 
@@ -395,36 +462,36 @@
 BIO *bp;
 BN_CTX *ctx;
 	{
-	BIGNUM *a,*c;
+	BIGNUM a,c;
 	int i;
 	int j;
 
-	a=BN_new();
-	c=BN_new();
+	BN_init(&a);
+	BN_init(&c);
 
 	for (i=0; i<40; i++)
 		{
-		BN_rand(a,40+i*10,0,0);
-		a->neg=rand_neg();
+		BN_rand(&a,40+i*10,0,0);
+		a.neg=rand_neg();
 		if (bp == NULL)
 			for (j=0; j<100; j++)
-				BN_sqr(c,a,ctx);
-		BN_sqr(c,a,ctx);
+				BN_sqr(&c,&a,ctx);
+		BN_sqr(&c,&a,ctx);
 		if (bp != NULL)
 			{
 			if (!results)
 				{
-				BN_print(bp,a);
+				BN_print(bp,&a);
 				BIO_puts(bp," * ");
-				BN_print(bp,a);
+				BN_print(bp,&a);
 				BIO_puts(bp," - ");
 				}
-			BN_print(bp,c);
+			BN_print(bp,&c);
 			BIO_puts(bp,"\n");
 			}
 		}
-	BN_free(a);
-	BN_free(c);
+	BN_free(&a);
+	BN_free(&c);
 	return(1);
 	}
 
@@ -432,61 +499,61 @@
 BIO *bp;
 BN_CTX *ctx;
 	{
-	BIGNUM *a,*b,*c,*A,*B;
-	BIGNUM *n;
+	BIGNUM a,b,c,A,B;
+	BIGNUM n;
 	int i;
 	int j;
 	BN_MONT_CTX *mont;
 
-	a=BN_new();
-	b=BN_new();
-	c=BN_new();
-	A=BN_new();
-	B=BN_new();
-	n=BN_new();
+	BN_init(&a);
+	BN_init(&b);
+	BN_init(&c);
+	BN_init(&A);
+	BN_init(&B);
+	BN_init(&n);
 
 	mont=BN_MONT_CTX_new();
 
-	BN_rand(a,100,0,0); /**/
-	BN_rand(b,100,0,0); /**/
+	BN_rand(&a,100,0,0); /**/
+	BN_rand(&b,100,0,0); /**/
 	for (i=0; i<10; i++)
 		{
-		BN_rand(n,(100%BN_BITS2+1)*BN_BITS2*i*BN_BITS2,0,1); /**/
-		BN_MONT_CTX_set(mont,n,ctx);
+		BN_rand(&n,(100%BN_BITS2+1)*BN_BITS2*i*BN_BITS2,0,1); /**/
+		BN_MONT_CTX_set(mont,&n,ctx);
 
-		BN_to_montgomery(A,a,mont,ctx);
-		BN_to_montgomery(B,b,mont,ctx);
+		BN_to_montgomery(&A,&a,mont,ctx);
+		BN_to_montgomery(&B,&b,mont,ctx);
 
 		if (bp == NULL)
 			for (j=0; j<100; j++)
-				BN_mod_mul_montgomery(c,A,B,mont,ctx);/**/
-		BN_mod_mul_montgomery(c,A,B,mont,ctx);/**/
-		BN_from_montgomery(A,c,mont,ctx);/**/
+				BN_mod_mul_montgomery(&c,&A,&B,mont,ctx);/**/
+		BN_mod_mul_montgomery(&c,&A,&B,mont,ctx);/**/
+		BN_from_montgomery(&A,&c,mont,ctx);/**/
 		if (bp != NULL)
 			{
 			if (!results)
 				{
 #ifdef undef
 fprintf(stderr,"%d * %d %% %d\n",
-BN_num_bits(a),
-BN_num_bits(b),
+BN_num_bits(&a),
+BN_num_bits(&b),
 BN_num_bits(mont->N));
 #endif
-				BN_print(bp,a);
+				BN_print(bp,&a);
 				BIO_puts(bp," * ");
-				BN_print(bp,b);
+				BN_print(bp,&b);
 				BIO_puts(bp," % ");
-				BN_print(bp,mont->N);
+				BN_print(bp,&(mont->N));
 				BIO_puts(bp," - ");
 				}
-			BN_print(bp,A);
+			BN_print(bp,&A);
 			BIO_puts(bp,"\n");
 			}
 		}
 	BN_MONT_CTX_free(mont);
-	BN_free(a);
-	BN_free(b);
-	BN_free(c);
+	BN_free(&a);
+	BN_free(&b);
+	BN_free(&c);
 	return(1);
 	}
 
diff --git a/crypto/bn/comba.pl b/crypto/bn/comba.pl
new file mode 100644
index 0000000..211a8b4
--- /dev/null
+++ b/crypto/bn/comba.pl
@@ -0,0 +1,285 @@
+#!/usr/local/bin/perl
+
+$num=8;
+$num2=8/2;
+
+print <<"EOF";
+/* crypto/bn/bn_comba.c */
+#include <stdio.h>
+#include "bn_lcl.h"
+/* Auto generated from crypto/bn/comba.pl
+ */
+
+#undef bn_mul_comba8
+#undef bn_mul_comba4
+#undef bn_sqr_comba8
+#undef bn_sqr_comba4
+
+#ifdef BN_LLONG
+#define mul_add_c(a,b,c0,c1,c2) \\
+	t=(BN_ULLONG)a*b; \\
+	t1=(BN_ULONG)Lw(t); \\
+	t2=(BN_ULONG)Hw(t); \\
+	c0=(c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \\
+	c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++;
+
+#define mul_add_c2(a,b,c0,c1,c2) \\
+	t=(BN_ULLONG)a*b; \\
+	tt=(t+t)&BN_MASK; \\
+	if (tt < t) c2++; \\
+	t1=(BN_ULONG)Lw(tt); \\
+	t2=(BN_ULONG)Hw(tt); \\
+	c0=(c0+t1)&BN_MASK2;  \\
+	if ((c0 < t1) && (((++t2)&BN_MASK2) == 0)) c2++; \\
+	c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++;
+
+#define sqr_add_c(a,i,c0,c1,c2) \\
+	t=(BN_ULLONG)a[i]*a[i]; \\
+	t1=(BN_ULONG)Lw(t); \\
+	t2=(BN_ULONG)Hw(t); \\
+	c0=(c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \\
+	c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++;
+
+#define sqr_add_c2(a,i,j,c0,c1,c2) \\
+	mul_add_c2((a)[i],(a)[j],c0,c1,c2)
+#else
+#define mul_add_c(a,b,c0,c1,c2) \\
+	t1=LBITS(a); t2=HBITS(a); \\
+	bl=LBITS(b); bh=HBITS(b); \\
+	mul64(t1,t2,bl,bh); \\
+	c0=(c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \\
+	c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++;
+
+#define mul_add_c2(a,b,c0,c1,c2) \\
+	t1=LBITS(a); t2=HBITS(a); \\
+	bl=LBITS(b); bh=HBITS(b); \\
+	mul64(t1,t2,bl,bh); \\
+	if (t2 & BN_TBIT) c2++; \\
+	t2=(t2+t2)&BN_MASK2; \\
+	if (t1 & BN_TBIT) t2++; \\
+	t1=(t1+t1)&BN_MASK2; \\
+	c0=(c0+t1)&BN_MASK2;  \\
+	if ((c0 < t1) && (((++t2)&BN_MASK2) == 0)) c2++; \\
+	c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++;
+
+#define sqr_add_c(a,i,c0,c1,c2) \\
+	sqr64(t1,t2,(a)[i]); \\
+	c0=(c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \\
+	c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++;
+
+#define sqr_add_c2(a,i,j,c0,c1,c2) \\
+	mul_add_c2((a)[i],(a)[j],c0,c1,c2)
+#endif
+
+void bn_mul_comba${num}(r,a,b)
+BN_ULONG *r,*a,*b;
+	{
+#ifdef BN_LLONG
+	BN_ULLONG t;
+#else
+	BN_ULONG bl,bh;
+#endif
+	BN_ULONG t1,t2;
+	BN_ULONG c1,c2,c3;
+
+EOF
+$ret=&combas_mul("r","a","b",$num,"c1","c2","c3");
+printf <<"EOF";
+	}
+
+void bn_mul_comba${num2}(r,a,b)
+BN_ULONG *r,*a,*b;
+	{
+#ifdef BN_LLONG
+	BN_ULLONG t;
+#else
+	BN_ULONG bl,bh;
+#endif
+	BN_ULONG t1,t2;
+	BN_ULONG c1,c2,c3;
+
+EOF
+$ret=&combas_mul("r","a","b",$num2,"c1","c2","c3");
+printf <<"EOF";
+	}
+
+void bn_sqr_comba${num}(r,a)
+BN_ULONG *r,*a;
+	{
+#ifdef BN_LLONG
+	BN_ULLONG t,tt;
+#else
+	BN_ULONG bl,bh;
+#endif
+	BN_ULONG t1,t2;
+	BN_ULONG c1,c2,c3;
+
+EOF
+$ret=&combas_sqr("r","a",$num,"c1","c2","c3");
+printf <<"EOF";
+	}
+
+void bn_sqr_comba${num2}(r,a)
+BN_ULONG *r,*a;
+	{
+#ifdef BN_LLONG
+	BN_ULLONG t,tt;
+#else
+	BN_ULONG bl,bh;
+#endif
+	BN_ULONG t1,t2;
+	BN_ULONG c1,c2,c3;
+
+EOF
+$ret=&combas_sqr("r","a",$num2,"c1","c2","c3");
+printf <<"EOF";
+	}
+EOF
+
+sub bn_str
+	{
+	local($var,$val)=@_;
+	print "\t$var=$val;\n";
+	}
+
+sub bn_ary
+	{
+	local($var,$idx)=@_;
+	return("${var}[$idx]");
+	}
+
+sub bn_clr
+	{
+	local($var)=@_;
+
+	print "\t$var=0;\n";
+	}
+
+sub bn_mad
+	{
+	local($a,$b,$c0,$c1,$c2,$num)=@_;
+
+	if ($num == 2)
+		{ printf("\tmul_add_c2($a,$b,$c0,$c1,$c2);\n"); }
+	else
+		{ printf("\tmul_add_c($a,$b,$c0,$c1,$c2);\n"); }
+	}
+
+sub bn_sad
+	{
+	local($a,$i,$j,$c0,$c1,$c2,$num)=@_;
+
+	if ($num == 2)
+		{ printf("\tsqr_add_c2($a,$i,$j,$c0,$c1,$c2);\n"); }
+	else
+		{ printf("\tsqr_add_c($a,$i,$c0,$c1,$c2);\n"); }
+	}
+
+sub combas_mul
+	{
+	local($r,$a,$b,$num,$c0,$c1,$c2)=@_;
+	local($i,$as,$ae,$bs,$be,$ai,$bi);
+	local($tot,$end);
+
+	$as=0;
+	$ae=0;
+	$bs=0;
+	$be=0;
+	$tot=$num+$num-1;
+	&bn_clr($c0);
+	&bn_clr($c1);
+	for ($i=0; $i<$tot; $i++)
+		{
+		$ai=$as;
+		$bi=$bs;
+		$end=$be+1;
+		@numa=@numb=();
+
+#print "($as $ae) ($bs $be) $bs -> $end [$i $num]\n";
+		for ($j=$bs; $j<$end; $j++)
+			{
+			push(@numa,$ai);
+			push(@numb,$bi);
+			$ai--;
+			$bi++;
+			}
+
+		if ($i & 1)
+			{
+			@numa=reverse(@numa);
+			@numb=reverse(@numb);
+			}
+
+		&bn_clr($c2);
+		for ($j=0; $j<=$#numa; $j++)
+			{
+			&bn_mad(&bn_ary($a,$numa[$j]),
+				&bn_ary($b,$numb[$j]),$c0,$c1,$c2,1);
+			}
+		&bn_str(&bn_ary($r,$i),$c0);
+		($c0,$c1,$c2)=($c1,$c2,$c0);
+
+		$as++ if ($i < ($num-1));
+		$ae++ if ($i >= ($num-1));
+
+		$bs++ if ($i >= ($num-1));
+		$be++ if ($i < ($num-1));
+		}
+	&bn_str(&bn_ary($r,$i),$c0);
+	}
+
+sub combas_sqr
+	{
+	local($r,$a,$num,$c0,$c1,$c2)=@_;
+	local($i,$as,$ae,$bs,$be,$ai,$bi);
+	local($b,$tot,$end,$half);
+
+	$b=$a;
+	$as=0;
+	$ae=0;
+	$bs=0;
+	$be=0;
+	$tot=$num+$num-1;
+	&bn_clr($c0);
+	&bn_clr($c1);
+	for ($i=0; $i<$tot; $i++)
+		{
+		$ai=$as;
+		$bi=$bs;
+		$end=$be+1;
+		@numa=@numb=();
+
+#print "($as $ae) ($bs $be) $bs -> $end [$i $num]\n";
+		for ($j=$bs; $j<$end; $j++)
+			{
+			push(@numa,$ai);
+			push(@numb,$bi);
+			$ai--;
+			$bi++;
+			last if ($ai < $bi);
+			}
+		if (!($i & 1))
+			{
+			@numa=reverse(@numa);
+			@numb=reverse(@numb);
+			}
+
+		&bn_clr($c2);
+		for ($j=0; $j <= $#numa; $j++)
+			{
+			if ($numa[$j] == $numb[$j])
+				{&bn_sad($a,$numa[$j],$numb[$j],$c0,$c1,$c2,1);}
+			else
+				{&bn_sad($a,$numa[$j],$numb[$j],$c0,$c1,$c2,2);}
+			}
+		&bn_str(&bn_ary($r,$i),$c0);
+		($c0,$c1,$c2)=($c1,$c2,$c0);
+
+		$as++ if ($i < ($num-1));
+		$ae++ if ($i >= ($num-1));
+
+		$bs++ if ($i >= ($num-1));
+		$be++ if ($i < ($num-1));
+		}
+	&bn_str(&bn_ary($r,$i),$c0);
+	}
diff --git a/crypto/bn/d.c b/crypto/bn/d.c
new file mode 100644
index 0000000..f738b50
--- /dev/null
+++ b/crypto/bn/d.c
@@ -0,0 +1,72 @@
+#include <stdio.h>
+#include "bio.h"
+#include "bn_lcl.h"
+
+#define SIZE_A (100*4+4)
+#define SIZE_B (13*4)
+
+main(argc,argv)
+int argc;
+char *argv[];
+	{
+	BN_CTX ctx;
+	BN_RECP_CTX recp;
+	BIGNUM a,b,dd,d,r,rr,t,l;
+	int i;
+
+	MemCheck_start();
+	MemCheck_on();
+	BN_CTX_init(&ctx);
+	BN_RECP_CTX_init(&recp);
+
+	BN_init(&r);
+	BN_init(&rr);
+	BN_init(&d);
+	BN_init(&dd);
+	BN_init(&a);
+	BN_init(&b);
+
+	{
+	BN_rand(&a,SIZE_A,0,0);
+	BN_rand(&b,SIZE_B,0,0);
+
+	a.neg=1;
+	BN_RECP_CTX_set(&recp,&b,&ctx);
+
+	BN_print_fp(stdout,&a); printf(" a\n");
+	BN_print_fp(stdout,&b); printf(" b\n");
+
+	BN_print_fp(stdout,&recp.N); printf(" N\n");
+	BN_print_fp(stdout,&recp.Nr); printf(" Nr num_bits=%d\n",recp.num_bits);
+
+	BN_div_recp(&r,&d,&a,&recp,&ctx);
+
+for (i=0; i<300; i++)
+	BN_div(&rr,&dd,&a,&b,&ctx);
+
+	BN_print_fp(stdout,&r); printf(" div recp\n");
+	BN_print_fp(stdout,&rr); printf(" div\n");
+	BN_print_fp(stdout,&d); printf(" rem recp\n");
+	BN_print_fp(stdout,&dd); printf(" rem\n");
+	}
+	BN_CTX_free(&ctx);
+	BN_RECP_CTX_free(&recp);
+
+	BN_free(&r);
+	BN_free(&rr);
+	BN_free(&d);
+	BN_free(&dd);
+	BN_free(&a);
+	BN_free(&b);
+
+	{
+	BIO *out;
+
+	if ((out=BIO_new(BIO_s_file())) != NULL)
+		BIO_set_fp(out,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
+
+        CRYPTO_mem_leaks(out);
+	BIO_free(out);
+	}
+
+	}
diff --git a/crypto/bn/exp.c b/crypto/bn/exp.c
new file mode 100644
index 0000000..2427116
--- /dev/null
+++ b/crypto/bn/exp.c
@@ -0,0 +1,60 @@
+#include <stdio.h>
+#include "tmdiff.h"
+#include "bn_lcl.h"
+
+#define SIZE	256
+#define NUM	(8*8*8)
+#define MOD	(8*8*8*8*8)
+
+main(argc,argv)
+int argc;
+char *argv[];
+	{
+	BN_CTX ctx;
+	BIGNUM a,b,c,r,rr,t,l;
+	int j,i,size=SIZE,num=NUM,mod=MOD;
+	char *start,*end;
+	BN_MONT_CTX mont;
+	double d,md;
+
+	BN_MONT_CTX_init(&mont);
+	BN_CTX_init(&ctx);
+	BN_init(&a);
+	BN_init(&b);
+	BN_init(&c);
+	BN_init(&r);
+
+	start=ms_time_new();
+	end=ms_time_new();
+	while (size <= 1024*8)
+		{
+		BN_rand(&a,size,0,0);
+		BN_rand(&b,size,1,0);
+		BN_rand(&c,size,0,1);
+
+		BN_mod(&a,&a,&c,&ctx);
+
+		ms_time_get(start);
+		for (i=0; i<10; i++)
+			BN_MONT_CTX_set(&mont,&c,&ctx);
+		ms_time_get(end);
+		md=ms_time_diff(start,end);
+
+		ms_time_get(start);
+		for (i=0; i<num; i++)
+			{
+			//bn_mull(&r,&a,&b,&ctx);
+			//BN_sqr(&r,&a,&ctx);
+			BN_mod_exp_mont(&r,&a,&b,&c,&ctx,&mont);
+			}
+		ms_time_get(end);
+		d=ms_time_diff(start,end) *50/33 /**/;
+		printf("%5d bit:%6.2f %6d %6.4f %4d m_set(%5.4f)\n",size,
+			d,num,d/num,(int)((d/num)*mod),md/10.0);
+		num/=8;
+		mod/=8;
+		if (num <= 0) num=1;
+		size*=2;
+		}
+
+	}
diff --git a/crypto/bn/expspeed.c b/crypto/bn/expspeed.c
index 344f883..fe00373 100644
--- a/crypto/bn/expspeed.c
+++ b/crypto/bn/expspeed.c
@@ -94,7 +94,8 @@
 #include <sys/timeb.h>
 #endif
 
-#ifdef sun
+#if defined(sun) || defined(__ultrix)
+#define _POSIX_SOURCE
 #include <limits.h>
 #include <sys/param.h>
 #endif
diff --git a/crypto/bn/exptest.c b/crypto/bn/exptest.c
index 67dc95d..1ec61c2 100644
--- a/crypto/bn/exptest.c
+++ b/crypto/bn/exptest.c
@@ -79,6 +79,8 @@
 	unsigned char c;
 	BIGNUM *r_mont,*r_recp,*a,*b,*m;
 
+	ERR_load_BN_strings();
+
 	ctx=BN_CTX_new();
 	if (ctx == NULL) exit(1);
 	r_mont=BN_new();
@@ -114,11 +116,19 @@
 
 		ret=BN_mod_exp_mont(r_mont,a,b,m,ctx,NULL);
 		if (ret <= 0)
-			{ printf("BN_mod_exp_mont() problems\n"); exit(1); }
+			{
+			printf("BN_mod_exp_mont() problems\n");
+			ERR_print_errors(out);
+			exit(1);
+			}
 
 		ret=BN_mod_exp_recp(r_recp,a,b,m,ctx);
 		if (ret <= 0)
-			{ printf("BN_mod_exp_recp() problems\n"); exit(1); }
+			{
+			printf("BN_mod_exp_recp() problems\n");
+			ERR_print_errors(out);
+			exit(1);
+			}
 		
 		if (BN_cmp(r_mont,r_recp) != 0)
 			{
@@ -137,6 +147,7 @@
 			fflush(stdout);
 			}
 		}
+	CRYPTO_mem_leaks(out);
 	printf(" done\n");
 	exit(0);
 err:
diff --git a/crypto/bn/m.pl b/crypto/bn/m.pl
new file mode 100644
index 0000000..f69b036
--- /dev/null
+++ b/crypto/bn/m.pl
@@ -0,0 +1,32 @@
+#!/usr/local/bin/perl
+
+
+for ($i=0; $i<256; $i++)
+	{
+	for ($j=0; $j<256; $j++)
+		{
+		$a0=$i&0x0f;
+		$a1=($i>>4)&0x0f;
+		$b0=$j&0x0f;
+		$b1=($j>>4)&0x0f;
+
+		$a0b0=$a0*$b0;
+		$a1b1=$a1*$b1;
+
+		$a01=$a0-$a1;
+		$b10=$b1-$b0;
+		$a01b10=$a01*$b10;
+
+		if ($a01b10 < 0)
+			{
+			$neg=1;
+			$a01b10= -$a01b10;
+			}
+		$t=($a0b0>>4)+($a0b0&0x0f)+($a1b1&0x0f);
+		if ($neg)
+			{ $t-=($a01b10&0x0f); }
+		else	{ $t+=($a01b10&0x0f); }
+		printf("%02X %s%02X %02X\n",$a1b1,($neg)?"-":" ",$a01b10,$a0b0)
+			if ($t < 0)
+		}
+	}
diff --git a/crypto/bn/new b/crypto/bn/new
new file mode 100644
index 0000000..285d506
--- /dev/null
+++ b/crypto/bn/new
@@ -0,0 +1,23 @@
+void BN_RECP_CTX_init(BN_RECP_CTX *recp);
+BN_RECP_CTX *BN_RECP_CTX_new();
+void BN_RECP_CTX_free(BN_RECP_CTX *recp);
+int BN_RECP_CTX_set(BN_RECP_CTX *recp,BIGNUM *div,BN_CTX *ctx);
+
+int BN_mod_exp_recp(BIGNUM *r, BIGNUM *a, BIGNUM *p, BIGNUM *m,
+	BN_RECP_CTX *recp,BN_CTX *ctx);
+
+int BN_div_recp(BIGNUM *dv, BIGNUM *rem, BIGNUM *m, BIGNUM *d,
+	BN_RECP_CTX *recp, BN_CTX *ctx);
+int BN_mod_recp(BIGNUM *rem, BIGNUM *m, BIGNUM *d,
+	BN_RECP_CTX *recp, BN_CTX *ctx);
+int BN_mod_mul_recp(BIGNUM *ret,BIGNUM *a,BIGNUM *b,BIGNUM *m
+
+int BN_mod_exp_montgomery(BIGNUM *r, BIGNUM *a, BIGNUM *p,
+	BN_MONT_CTX *m_ctx,BN_CTX *ctx);
+int BN_mod_exp2_montgomery(BIGNUM *r, BIGNUM *a1, BIGNUM *p1,BIGNUM *a2,
+                BIGNUM *p2,BN_MONT_CTX *m_ctx,BN_CTX *ctx);
+
+
+bn_div64 -> bn_div_words
+
+
diff --git a/crypto/bn/old/b_sqr.c b/crypto/bn/old/b_sqr.c
new file mode 100644
index 0000000..e1a61b8
--- /dev/null
+++ b/crypto/bn/old/b_sqr.c
@@ -0,0 +1,205 @@
+/* crypto/bn/bn_mul.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 "cryptlib.h"
+#include "bn_lcl.h"
+
+static int bn_mm(BIGNUM *m,BIGNUM *A,BIGNUM *B, BIGNUM *sk,BN_CTX *ctx);
+
+/* r must be different to a and b */
+/* int BN_mmul(r, a, b) */
+int BN_mul(r, a, b)
+BIGNUM *r;
+BIGNUM *a;
+BIGNUM *b;
+	{
+	BN_ULONG *ap,*bp,*rp;
+	BIGNUM *sk;
+	int i,n,ret;
+	int max,al,bl;
+	BN_CTX ctx;
+
+	bn_check_top(a);
+	bn_check_top(b);
+
+	al=a->top;
+	bl=b->top;
+	if ((al == 0) || (bl == 0))
+		{
+		r->top=0;
+		return(1);
+		}
+#ifdef BN_MUL_DEBUG
+printf("BN_mul(%d,%d)\n",a->top,b->top);
+#endif
+
+	if (	(bn_limit_bits > 0) &&
+		(bl > bn_limit_num) && (al > bn_limit_num))
+		{
+		n=(BN_num_bits_word(al|bl)-bn_limit_bits);
+		n*=2;
+		sk=(BIGNUM *)Malloc(sizeof(BIGNUM)*n);
+		memset(sk,0,sizeof(BIGNUM)*n);
+		memset(&ctx,0,sizeof(ctx));
+
+		ret=bn_mm(r,a,b,&(sk[0]),&ctx);
+		for (i=0; i<n; i+=2)
+			{
+			BN_clear_free(&sk[i]);
+			BN_clear_free(&sk[i+1]);
+			}
+		Free(sk);
+		return(ret);
+		}
+
+	max=(al+bl);
+	if (bn_wexpand(r,max) == NULL) return(0);
+	r->top=max;
+	r->neg=a->neg^b->neg;
+	ap=a->d;
+	bp=b->d;
+	rp=r->d;
+
+	rp[al]=bn_mul_words(rp,ap,al,*(bp++));
+	rp++;
+	for (i=1; i<bl; i++)
+		{
+		rp[al]=bn_mul_add_words(rp,ap,al,*(bp++));
+		rp++;
+		}
+	if ((max > 0) && (r->d[max-1] == 0)) r->top--;
+	return(1);
+	}
+
+
+#define ahal	(sk[0])
+#define blbh	(sk[1])
+
+/* r must be different to a and b */
+int bn_mm(m, A, B, sk,ctx)
+BIGNUM *m,*A,*B;
+BIGNUM *sk;
+BN_CTX *ctx;
+	{
+	int n,num,sqr=0;
+	int an,bn;
+	BIGNUM ah,al,bh,bl;
+
+	an=A->top;
+	bn=B->top;
+#ifdef BN_MUL_DEBUG
+printf("bn_mm(%d,%d)\n",A->top,B->top);
+#endif
+
+	if (A == B) sqr=1;
+	num=(an>bn)?an:bn;
+	n=(num+1)/2;
+	/* Are going to now chop things into 'num' word chunks. */
+
+	BN_init(&ah);
+	BN_init(&al);
+	BN_init(&bh);
+	BN_init(&bl);
+
+	bn_set_low (&al,A,n);
+	bn_set_high(&ah,A,n);
+	bn_set_low (&bl,B,n);
+	bn_set_high(&bh,B,n);
+
+	BN_sub(&ahal,&ah,&al);
+	BN_sub(&blbh,&bl,&bh);
+
+	if (num <= (bn_limit_num+bn_limit_num))
+		{
+		BN_mul(m,&ahal,&blbh);
+		if (sqr)
+			{
+			BN_sqr(&ahal,&al,ctx);
+			BN_sqr(&blbh,&ah,ctx);
+			}
+		else
+			{
+			BN_mul(&ahal,&al,&bl);
+			BN_mul(&blbh,&ah,&bh);
+			}
+		}
+	else
+		{
+		bn_mm(m,&ahal,&blbh,&(sk[2]),ctx);
+		bn_mm(&ahal,&al,&bl,&(sk[2]),ctx);
+		bn_mm(&blbh,&ah,&bh,&(sk[2]),ctx);
+		}
+
+	BN_add(m,m,&ahal);
+	BN_add(m,m,&blbh);
+
+	BN_lshift(m,m,n*BN_BITS2);
+	BN_lshift(&blbh,&blbh,n*BN_BITS2*2);
+
+	BN_add(m,m,&ahal);
+	BN_add(m,m,&blbh);
+
+	m->neg=A->neg^B->neg;
+	return(1);
+	}
+#undef ahal	(sk[0])
+#undef blbh	(sk[1])
+
+#include "bn_low.c"
+#include "bn_high.c"
diff --git a/crypto/bn/old/bn_com.c b/crypto/bn/old/bn_com.c
new file mode 100644
index 0000000..7666b23
--- /dev/null
+++ b/crypto/bn/old/bn_com.c
@@ -0,0 +1,90 @@
+/* crypto/bn/bn_mulw.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 "cryptlib.h"
+#include "bn_lcl.h"
+
+#ifdef BN_LLONG 
+
+ab
+12
+   a2 b2
+a1 b1
+
+abc
+123
+      a3 b3 c3
+   a2 b2 c2
+a1 b1 c1
+
+abcd
+1234
+         a4 b4 c4 d4
+      a3 b3 c3 d3
+   a2 b2 c2 d2
+a1 b1 c1 d1
+
+abcde
+01234
+               a5 b5 c5 d5 e5
+            a4 b4 c4 d4 e4
+         a3 b3 c3 d3 e3
+      a2 b2 c2 d2 e2
+   a1 b1 c1 d1 e1
+a0 b0 c0 d0 e0
diff --git a/crypto/bn/old/bn_high.c b/crypto/bn/old/bn_high.c
new file mode 100644
index 0000000..90268fb
--- /dev/null
+++ b/crypto/bn/old/bn_high.c
@@ -0,0 +1,137 @@
+#include <stdio.h>
+#include "cryptlib.h"
+#include "bn_lcl.h"
+
+#undef BN_MUL_HIGH_DEBUG
+
+#ifdef BN_MUL_HIGH_DEBUG
+#define debug_BN_print(a,b,c) BN_print_fp(a,b); printf(c);
+#else
+#define debug_BN_print(a,b,c)
+#endif
+
+int BN_mul_high(BIGNUM *r,BIGNUM *a,BIGNUM *b,BIGNUM *low, int words);
+
+#undef t1
+#undef t2
+
+int BN_mul_high(r,a,b,low,words)
+BIGNUM *r,*a,*b,*low;
+int words;
+	{
+	int w2,borrow=0,full=0;
+	BIGNUM t1,t2,t3,h,ah,al,bh,bl,m,s0,s1;
+	BN_ULONG ul1,ul2;
+	
+	BN_mul(r,a,b);
+	BN_rshift(r,r,words*BN_BITS2);
+	return(1);
+
+	w2=(words+1)/2;
+
+#ifdef BN_MUL_HIGH_DEBUG
+fprintf(stdout,"words=%d w2=%d\n",words,w2);
+#endif
+debug_BN_print(stdout,a," a\n");
+debug_BN_print(stdout,b," b\n");
+debug_BN_print(stdout,low," low\n");
+	BN_init(&al); BN_init(&ah);
+	BN_init(&bl); BN_init(&bh);
+	BN_init(&t1); BN_init(&t2); BN_init(&t3);
+	BN_init(&s0); BN_init(&s1);
+	BN_init(&h); BN_init(&m);
+
+	bn_set_low (&al,a,w2);
+	bn_set_high(&ah,a,w2);
+	bn_set_low (&bl,b,w2);
+	bn_set_high(&bh,b,w2);
+
+	bn_set_low(&s0,low,w2);
+	bn_set_high(&s1,low,w2);
+
+debug_BN_print(stdout,&al," al\n");
+debug_BN_print(stdout,&ah," ah\n");
+debug_BN_print(stdout,&bl," bl\n");
+debug_BN_print(stdout,&bh," bh\n");
+debug_BN_print(stdout,&s0," s0\n");
+debug_BN_print(stdout,&s1," s1\n");
+
+	/* Calculate (al-ah)*(bh-bl) */
+	BN_sub(&t1,&al,&ah);
+	BN_sub(&t2,&bh,&bl);
+	BN_mul(&m,&t1,&t2);
+
+	/* Calculate ah*bh */
+	BN_mul(&h,&ah,&bh);
+
+	/* s0 == low(al*bl)
+	 * s1 == low(ah*bh)+low((al-ah)*(bh-bl))+low(al*bl)+high(al*bl)
+	 * We know s0 and s1 so the only unknown is high(al*bl)
+	 * high(al*bl) == s1 - low(ah*bh+(al-ah)*(bh-bl)+s0)
+	 */
+	BN_add(&m,&m,&h);
+	BN_add(&t2,&m,&s0);
+
+debug_BN_print(stdout,&t2," middle value\n");
+
+	/* Quick and dirty mask off of high words */
+	if (w2 < t2.top) t2.top=w2;
+#if 0
+	bn_set_low(&t3,&t2,w2);
+#endif
+
+debug_BN_print(stdout,&t2," low middle value\n");
+	BN_sub(&t1,&s1,&t2);
+
+	if (t1.neg)
+		{
+debug_BN_print(stdout,&t1," before\n");
+		BN_zero(&t2);
+		BN_set_bit(&t2,w2*BN_BITS2);
+		BN_add(&t1,&t2,&t1);
+		/* BN_mask_bits(&t1,w2*BN_BITS2); */
+		/* if (words < t1.top) t1.top=words; */
+debug_BN_print(stdout,&t1," after\n");
+		borrow=1;
+		}
+
+/* XXXXX SPEED THIS UP */
+	/* al*bl == high(al*bl)<<words+s0 */
+	BN_lshift(&t1,&t1,w2*BN_BITS2);
+	BN_add(&t1,&t1,&s0);
+	if (w2*2 < t1.top) t1.top=w2*2; /* This should not happen? */
+	
+	/* We now have
+	 * al*bl			- t1
+	 * (al-ah)*(bh-bl)+ah*bh	- m
+	 * ah*bh			- h
+	 */
+#if 0
+	BN_add(&m,&m,&t1);
+debug_BN_print(stdout,&t1," s10\n");
+debug_BN_print(stdout,&m," s21\n");
+debug_BN_print(stdout,&h," s32\n");
+	BN_lshift(&m,&m,w2*BN_BITS2);
+	BN_lshift(&h,&h,w2*2*BN_BITS2);
+	BN_add(r,&m,&t1);
+	BN_add(r,r,&h);
+	BN_rshift(r,r,w2*2*BN_BITS2);
+#else
+	BN_add(&m,&m,&t1); 		/* Do a cmp then +1 if needed? */
+	bn_set_high(&t3,&t1,w2);
+	BN_add(&m,&m,&t3);
+	bn_set_high(&t3,&m,w2);
+	BN_add(r,&h,&t3);
+#endif
+
+#ifdef BN_MUL_HIGH_DEBUG
+printf("carry=%d\n",borrow);
+#endif
+debug_BN_print(stdout,r," ret\n");
+	BN_free(&t1); BN_free(&t2);
+	BN_free(&m); BN_free(&h);
+	return(1);
+	}
+
+
+
diff --git a/crypto/bn/old/bn_ka.c b/crypto/bn/old/bn_ka.c
new file mode 100644
index 0000000..b49a52a
--- /dev/null
+++ b/crypto/bn/old/bn_ka.c
@@ -0,0 +1,578 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include "bn_lcl.h"
+
+/* r is 2*n2 words in size,
+ * a and b are both n2 words in size.
+ * n2 must be a power of 2.
+ * We multiply and return the result.
+ * t must be 2*n2 words in size
+ * We calulate
+ * a[0]*b[0]
+ * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0])
+ * a[1]*b[1]
+ */
+void bn_mul_recursive(r,a,b,n2,t)
+BN_ULONG *r,*a,*b;
+int n2;
+BN_ULONG *t;
+	{
+	int n=n2/2;
+	int neg,zero,c1,c2;
+	BN_ULONG ln,lo,*p;
+
+#ifdef BN_COUNT
+printf(" bn_mul_recursive %d * %d\n",n2,n2);
+#endif
+	if (n2 <= 8)
+		{
+		if (n2 == 8)
+			bn_mul_comba8(r,a,b);
+		else
+			bn_mul_normal(r,a,n2,b,n2);
+		return;
+		}
+
+	if (n2 < BN_MUL_RECURSIVE_SIZE_NORMAL)
+		{
+		/* This should not happen */
+		/*abort(); */
+		bn_mul_normal(r,a,n2,b,n2);
+		return;
+		}
+	/* r=(a[0]-a[1])*(b[1]-b[0]) */
+	c1=bn_cmp_words(a,&(a[n]),n);
+	c2=bn_cmp_words(&(b[n]),b,n);
+	zero=neg=0;
+	switch (c1*3+c2)
+		{
+	case -4:
+		bn_sub_words(t,      &(a[n]),a,      n); /* - */
+		bn_sub_words(&(t[n]),b,      &(b[n]),n); /* - */
+		break;
+	case -3:
+		zero=1;
+		break;
+	case -2:
+		bn_sub_words(t,      &(a[n]),a,      n); /* - */
+		bn_sub_words(&(t[n]),&(b[n]),b,      n); /* + */
+		neg=1;
+		break;
+	case -1:
+	case 0:
+	case 1:
+		zero=1;
+		break;
+	case 2:
+		bn_sub_words(t,      a,      &(a[n]),n); /* + */
+		bn_sub_words(&(t[n]),b,      &(b[n]),n); /* - */
+		neg=1;
+		break;
+	case 3:
+		zero=1;
+		break;
+	case 4:
+		bn_sub_words(t,      a,      &(a[n]),n);
+		bn_sub_words(&(t[n]),&(b[n]),b,      n);
+		break;
+		}
+
+	if (n == 8)
+		{
+		if (!zero)
+			bn_mul_comba8(&(t[n2]),t,&(t[n]));
+		else
+			memset(&(t[n2]),0,8*sizeof(BN_ULONG));
+		
+		bn_mul_comba8(r,a,b);
+		bn_mul_comba8(&(r[n2]),&(a[n]),&(b[n]));
+		}
+	else
+		{
+		p= &(t[n2*2]);
+		if (!zero)
+			bn_mul_recursive(&(t[n2]),t,&(t[n]),n,p);
+		else
+			memset(&(t[n2]),0,n*sizeof(BN_ULONG));
+		bn_mul_recursive(r,a,b,n,p);
+		bn_mul_recursive(&(r[n2]),&(a[n]),&(b[n]),n,p);
+		}
+
+	/* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign
+	 * r[10] holds (a[0]*b[0])
+	 * r[32] holds (b[1]*b[1])
+	 */
+
+	c1=bn_add_words(t,r,&(r[n2]),n2);
+
+	if (neg) /* if t[32] is negative */
+		{
+		c1-=bn_sub_words(&(t[n2]),t,&(t[n2]),n2);
+		}
+	else
+		{
+		/* Might have a carry */
+		c1+=bn_add_words(&(t[n2]),&(t[n2]),t,n2);
+		}
+
+	/* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1])
+	 * r[10] holds (a[0]*b[0])
+	 * r[32] holds (b[1]*b[1])
+	 * c1 holds the carry bits
+	 */
+	c1+=bn_add_words(&(r[n]),&(r[n]),&(t[n2]),n2);
+	if (c1)
+		{
+		p= &(r[n+n2]);
+		lo= *p;
+		ln=(lo+c1)&BN_MASK2;
+		*p=ln;
+
+		/* The overflow will stop before we over write
+		 * words we should not overwrite */
+		if (ln < c1)
+			{
+			do	{
+				p++;
+				lo= *p;
+				ln=(lo+1)&BN_MASK2;
+				*p=ln;
+				} while (ln == 0);
+			}
+		}
+	}
+
+/* n+tn is the word length
+ * t needs to be n*4 is size, as does r */
+void bn_mul_part_recursive(r,a,b,tn,n,t)
+BN_ULONG *r,*a,*b;
+int tn,n;
+BN_ULONG *t;
+	{
+	int n2=n*2,i,j;
+	int c1;
+	BN_ULONG ln,lo,*p;
+
+#ifdef BN_COUNT
+printf(" bn_mul_part_recursive %d * %d\n",tn+n,tn+n);
+#endif
+	if (n < 8)
+		{
+		i=tn+n;
+		bn_mul_normal(r,a,i,b,i);
+		return;
+		}
+
+	/* r=(a[0]-a[1])*(b[1]-b[0]) */
+	bn_sub_words(t,      a,      &(a[n]),n); /* + */
+	bn_sub_words(&(t[n]),b,      &(b[n]),n); /* - */
+
+	if (n == 8)
+		{
+		bn_mul_comba8(&(t[n2]),t,&(t[n]));
+		bn_mul_comba8(r,a,b);
+		bn_mul_normal(&(r[n2]),&(a[n]),tn,&(b[n]),tn);
+		memset(&(r[n2+tn*2]),0,sizeof(BN_ULONG)*(n2-tn*2));
+		}
+	else
+		{
+		p= &(t[n2*2]);
+		bn_mul_recursive(&(t[n2]),t,&(t[n]),n,p);
+		bn_mul_recursive(r,a,b,n,p);
+		i=n/2;
+		/* If there is only a bottom half to the number,
+		 * just do it */
+		j=tn-i;
+		if (j == 0)
+			{
+			bn_mul_recursive(&(r[n2]),&(a[n]),&(b[n]),i,p);
+			memset(&(r[n2+i*2]),0,sizeof(BN_ULONG)*(n2-i*2));
+			}
+		else if (j > 0) /* eg, n == 16, i == 8 and tn == 11 */
+				{
+				bn_mul_part_recursive(&(r[n2]),&(a[n]),&(b[n]),
+					j,i,p);
+				memset(&(r[n2+tn*2]),0,
+					sizeof(BN_ULONG)*(n2-tn*2));
+				}
+		else /* (j < 0) eg, n == 16, i == 8 and tn == 5 */
+			{
+			memset(&(r[n2]),0,sizeof(BN_ULONG)*(tn*2));
+			for (;;)
+				{
+				i/=2;
+				if (i < tn)
+					{
+					bn_mul_part_recursive(&(r[n2]),
+						&(a[n]),&(b[n]),
+						tn-i,i,p);
+					break;
+					}
+				else if (i == tn)
+					{
+					bn_mul_recursive(&(r[n2]),
+						&(a[n]),&(b[n]),
+						i,p);
+					break;
+					}
+				}
+			}
+		}
+
+	/* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign
+	 * r[10] holds (a[0]*b[0])
+	 * r[32] holds (b[1]*b[1])
+	 */
+
+	c1=bn_add_words(t,r,&(r[n2]),n2);
+	c1-=bn_sub_words(&(t[n2]),t,&(t[n2]),n2);
+
+	/* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1])
+	 * r[10] holds (a[0]*b[0])
+	 * r[32] holds (b[1]*b[1])
+	 * c1 holds the carry bits
+	 */
+	c1+=bn_add_words(&(r[n]),&(r[n]),&(t[n2]),n2);
+	if (c1)
+		{
+		p= &(r[n+n2]);
+		lo= *p;
+		ln=(lo+c1)&BN_MASK2;
+		*p=ln;
+
+		/* The overflow will stop before we over write
+		 * words we should not overwrite */
+		if (ln < c1)
+			{
+			do	{
+				p++;
+				lo= *p;
+				ln=(lo+1)&BN_MASK2;
+				*p=ln;
+				} while (ln == 0);
+			}
+		}
+	}
+
+/* r is 2*n words in size,
+ * a and b are both n words in size.
+ * n must be a power of 2.
+ * We multiply and return the result.
+ * t must be 2*n words in size
+ * We calulate
+ * a[0]*b[0]
+ * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0])
+ * a[1]*b[1]
+ */
+void bn_sqr_recursive(r,a,n2,t)
+BN_ULONG *r,*a;
+int n2;
+BN_ULONG *t;
+	{
+	int n=n2/2;
+	int zero,c1;
+	BN_ULONG ln,lo,*p;
+
+#ifdef BN_COUNT
+printf(" bn_sqr_recursive %d * %d\n",n2,n2);
+#endif
+	if (n2 == 4)
+		{
+		bn_sqr_comba4(r,a);
+		return;
+		}
+	else if (n2 == 8)
+		{
+		bn_sqr_comba8(r,a);
+		return;
+		}
+	if (n2 < BN_SQR_RECURSIVE_SIZE_NORMAL)
+		{
+		bn_sqr_normal(r,a,n2,t);
+		return;
+		abort();
+		}
+	/* r=(a[0]-a[1])*(a[1]-a[0]) */
+	c1=bn_cmp_words(a,&(a[n]),n);
+	zero=0;
+	if (c1 > 0)
+		bn_sub_words(t,a,&(a[n]),n);
+	else if (c1 < 0)
+		bn_sub_words(t,&(a[n]),a,n);
+	else
+		zero=1;
+
+	/* The result will always be negative unless it is zero */
+
+	if (n == 8)
+		{
+		if (!zero)
+			bn_sqr_comba8(&(t[n2]),t);
+		else
+			memset(&(t[n2]),0,8*sizeof(BN_ULONG));
+		
+		bn_sqr_comba8(r,a);
+		bn_sqr_comba8(&(r[n2]),&(a[n]));
+		}
+	else
+		{
+		p= &(t[n2*2]);
+		if (!zero)
+			bn_sqr_recursive(&(t[n2]),t,n,p);
+		else
+			memset(&(t[n2]),0,n*sizeof(BN_ULONG));
+		bn_sqr_recursive(r,a,n,p);
+		bn_sqr_recursive(&(r[n2]),&(a[n]),n,p);
+		}
+
+	/* t[32] holds (a[0]-a[1])*(a[1]-a[0]), it is negative or zero
+	 * r[10] holds (a[0]*b[0])
+	 * r[32] holds (b[1]*b[1])
+	 */
+
+	c1=bn_add_words(t,r,&(r[n2]),n2);
+
+	/* t[32] is negative */
+	c1-=bn_sub_words(&(t[n2]),t,&(t[n2]),n2);
+
+	/* t[32] holds (a[0]-a[1])*(a[1]-a[0])+(a[0]*a[0])+(a[1]*a[1])
+	 * r[10] holds (a[0]*a[0])
+	 * r[32] holds (a[1]*a[1])
+	 * c1 holds the carry bits
+	 */
+	c1+=bn_add_words(&(r[n]),&(r[n]),&(t[n2]),n2);
+	if (c1)
+		{
+		p= &(r[n+n2]);
+		lo= *p;
+		ln=(lo+c1)&BN_MASK2;
+		*p=ln;
+
+		/* The overflow will stop before we over write
+		 * words we should not overwrite */
+		if (ln < c1)
+			{
+			do	{
+				p++;
+				lo= *p;
+				ln=(lo+1)&BN_MASK2;
+				*p=ln;
+				} while (ln == 0);
+			}
+		}
+	}
+
+#if 1
+/* a and b must be the same size, which is n2.
+ * r needs to be n2 words and t needs to be n2*2
+ */
+void bn_mul_low_recursive(r,a,b,n2,t)
+BN_ULONG *r,*a,*b;
+int n2;
+BN_ULONG *t;
+	{
+	int n=n2/2;
+
+#ifdef BN_COUNT
+printf(" bn_mul_low_recursive %d * %d\n",n2,n2);
+#endif
+
+	bn_mul_recursive(r,a,b,n,&(t[0]));
+	if (n > BN_MUL_LOW_RECURSIVE_SIZE_NORMAL)
+		{
+		bn_mul_low_recursive(&(t[0]),&(a[0]),&(b[n]),n,&(t[n2]));
+		bn_add_words(&(r[n]),&(r[n]),&(t[0]),n);
+		bn_mul_low_recursive(&(t[0]),&(a[n]),&(b[0]),n,&(t[n2]));
+		bn_add_words(&(r[n]),&(r[n]),&(t[0]),n);
+		}
+	else
+		{
+		bn_mul_low_normal(&(t[0]),&(a[0]),&(b[n]),n);
+		bn_mul_low_normal(&(t[n]),&(a[n]),&(b[0]),n);
+		bn_add_words(&(r[n]),&(r[n]),&(t[0]),n);
+		bn_add_words(&(r[n]),&(r[n]),&(t[n]),n);
+		}
+	}
+
+/* a and b must be the same size, which is n2.
+ * r needs to be n2 words and t needs to be n2*2
+ * l is the low words of the output.
+ * t needs to be n2*3
+ */
+void bn_mul_high(r,a,b,l,n2,t)
+BN_ULONG *r,*a,*b,*l;
+int n2;
+BN_ULONG *t;
+	{
+	int j,i,n,c1,c2;
+	int neg,oneg,zero;
+	BN_ULONG ll,lc,*lp,*mp;
+
+#ifdef BN_COUNT
+printf(" bn_mul_high %d * %d\n",n2,n2);
+#endif
+	n=(n2+1)/2;
+
+	/* Calculate (al-ah)*(bh-bl) */
+	neg=zero=0;
+	c1=bn_cmp_words(&(a[0]),&(a[n]),n);
+	c2=bn_cmp_words(&(b[n]),&(b[0]),n);
+	switch (c1*3+c2)
+		{
+	case -4:
+		bn_sub_words(&(r[0]),&(a[n]),&(a[0]),n);
+		bn_sub_words(&(r[n]),&(b[0]),&(b[n]),n);
+		break;
+	case -3:
+		zero=1;
+		break;
+	case -2:
+		bn_sub_words(&(r[0]),&(a[n]),&(a[0]),n);
+		bn_sub_words(&(r[n]),&(b[n]),&(b[0]),n);
+		neg=1;
+		break;
+	case -1:
+	case 0:
+	case 1:
+		zero=1;
+		break;
+	case 2:
+		bn_sub_words(&(r[0]),&(a[0]),&(a[n]),n);
+		bn_sub_words(&(r[n]),&(b[0]),&(b[n]),n);
+		neg=1;
+		break;
+	case 3:
+		zero=1;
+		break;
+	case 4:
+		bn_sub_words(&(r[0]),&(a[0]),&(a[n]),n);
+		bn_sub_words(&(r[n]),&(b[n]),&(b[0]),n);
+		break;
+		}
+		
+	oneg=neg;
+	/* t[10] = (a[0]-a[1])*(b[1]-b[0]) */
+	bn_mul_recursive(&(t[0]),&(r[0]),&(r[n]),n,&(t[n2]));
+	/* r[10] = (a[1]*b[1]) */
+	bn_mul_recursive(r,&(a[n]),&(b[n]),n,&(t[n2]));
+
+	/* s0 == low(al*bl)
+	 * s1 == low(ah*bh)+low((al-ah)*(bh-bl))+low(al*bl)+high(al*bl)
+	 * We know s0 and s1 so the only unknown is high(al*bl)
+	 * high(al*bl) == s1 - low(ah*bh+s0+(al-ah)*(bh-bl))
+	 * high(al*bl) == s1 - (r[0]+l[0]+t[0])
+	 */
+	if (l != NULL)
+		{
+		lp= &(t[n2+n]);
+		c1=bn_add_words(lp,&(r[0]),&(l[0]),n);
+		}
+	else
+		{
+		c1=0;
+		lp= &(r[0]);
+		}
+
+	if (neg)
+		neg=bn_sub_words(&(t[n2]),lp,&(t[0]),n);
+	else
+		{
+		bn_add_words(&(t[n2]),lp,&(t[0]),n);
+		neg=0;
+		}
+
+	if (l != NULL)
+		{
+		bn_sub_words(&(t[n2+n]),&(l[n]),&(t[n2]),n);
+		}
+	else
+		{
+		lp= &(t[n2+n]);
+		mp= &(t[n2]);
+		for (i=0; i<n; i++)
+			lp[i]=((~mp[i])+1)&BN_MASK2;
+		}
+
+	/* s[0] = low(al*bl)
+	 * t[3] = high(al*bl)
+	 * t[10] = (a[0]-a[1])*(b[1]-b[0]) neg is the sign
+	 * r[10] = (a[1]*b[1])
+	 */
+	/* R[10] = al*bl
+	 * R[21] = al*bl + ah*bh + (a[0]-a[1])*(b[1]-b[0])
+	 * R[32] = ah*bh
+	 */
+	/* R[1]=t[3]+l[0]+r[0](+-)t[0] (have carry/borrow)
+	 * R[2]=r[0]+t[3]+r[1](+-)t[1] (have carry/borrow)
+	 * R[3]=r[1]+(carry/borrow)
+	 */
+	if (l != NULL)
+		{
+		lp= &(t[n2]);
+		c1= bn_add_words(lp,&(t[n2+n]),&(l[0]),n);
+		}
+	else
+		{
+		lp= &(t[n2+n]);
+		c1=0;
+		}
+	c1+=bn_add_words(&(t[n2]),lp,  &(r[0]),n);
+	if (oneg)
+		c1-=bn_sub_words(&(t[n2]),&(t[n2]),&(t[0]),n);
+	else
+		c1+=bn_add_words(&(t[n2]),&(t[n2]),&(t[0]),n);
+
+	c2 =bn_add_words(&(r[0]),&(r[0]),&(t[n2+n]),n);
+	c2+=bn_add_words(&(r[0]),&(r[0]),&(r[n]),n);
+	if (oneg)
+		c2-=bn_sub_words(&(r[0]),&(r[0]),&(t[n]),n);
+	else
+		c2+=bn_add_words(&(r[0]),&(r[0]),&(t[n]),n);
+	
+	if (c1 != 0) /* Add starting at r[0], could be +ve or -ve */
+		{
+		i=0;
+		if (c1 > 0)
+			{
+			lc=c1;
+			do	{
+				ll=(r[i]+lc)&BN_MASK2;
+				r[i++]=ll;
+				lc=(lc > ll);
+				} while (lc);
+			}
+		else
+			{
+			lc= -c1;
+			do	{
+				ll=r[i];
+				r[i++]=(ll-lc)&BN_MASK2;
+				lc=(lc > ll);
+				} while (lc);
+			}
+		}
+	if (c2 != 0) /* Add starting at r[1] */
+		{
+		i=n;
+		if (c2 > 0)
+			{
+			lc=c2;
+			do	{
+				ll=(r[i]+lc)&BN_MASK2;
+				r[i++]=ll;
+				lc=(lc > ll);
+				} while (lc);
+			}
+		else
+			{
+			lc= -c2;
+			do	{
+				ll=r[i];
+				r[i++]=(ll-lc)&BN_MASK2;
+				lc=(lc > ll);
+				} while (lc);
+			}
+		}
+	}
+#endif
diff --git a/crypto/bn/old/bn_low.c b/crypto/bn/old/bn_low.c
new file mode 100644
index 0000000..217c8c2
--- /dev/null
+++ b/crypto/bn/old/bn_low.c
@@ -0,0 +1,201 @@
+/* crypto/bn/bn_mul.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 "cryptlib.h"
+#include "bn_lcl.h"
+
+static int bn_mm_low(BIGNUM *m,BIGNUM *A,BIGNUM *B, int num,
+		BIGNUM *sk,BN_CTX *ctx);
+int BN_mul_low(BIGNUM *r, BIGNUM *a, BIGNUM *b,int words);
+
+/* r must be different to a and b */
+int BN_mul_low(r, a, b, num)
+BIGNUM *r;
+BIGNUM *a;
+BIGNUM *b;
+int num;
+	{
+	BN_ULONG *ap,*bp,*rp;
+	BIGNUM *sk;
+	int j,i,n,ret;
+	int max,al,bl;
+	BN_CTX ctx;
+
+	bn_check_top(a);
+	bn_check_top(b);
+
+#ifdef BN_MUL_DEBUG
+printf("BN_mul_low(%d,%d,%d)\n",a->top,b->top,num);
+#endif
+
+	al=a->top;
+	bl=b->top;
+	if ((al == 0) || (bl == 0))
+		{
+		r->top=0;
+		return(1);
+		}
+
+	if ((bn_limit_bits_low > 0) && (num > bn_limit_num_low))
+		{
+		n=BN_num_bits_word(num*2)-bn_limit_bits_low;
+		n*=2;
+		sk=(BIGNUM *)Malloc(sizeof(BIGNUM)*n);
+		memset(sk,0,sizeof(BIGNUM)*n);
+		memset(&ctx,0,sizeof(ctx));
+
+		ret=bn_mm_low(r,a,b,num,&(sk[0]),&ctx);
+		for (i=0; i<n; i+=2)
+			{
+			BN_clear_free(&sk[i]);
+			BN_clear_free(&sk[i+1]);
+			}
+		Free(sk);
+		return(ret);
+		}
+
+	max=(al+bl);
+	if (bn_wexpand(r,max) == NULL) return(0);
+	r->neg=a->neg^b->neg;
+	ap=a->d;
+	bp=b->d;
+	rp=r->d;
+	r->top=(max > num)?num:max;
+
+	rp[al]=bn_mul_words(rp,ap,al,*(bp++));
+	rp++;
+	j=bl;
+	for (i=1; i<j; i++)
+		{
+		if (al >= num--)
+			{
+			al--;
+			if (al <= 0) break;
+			}
+		rp[al]=bn_mul_add_words(rp,ap,al,*(bp++));
+		rp++;
+		}
+	
+	while ((r->top > 0) && (r->d[r->top-1] == 0))
+		r->top--;
+	return(1);
+	}
+
+
+#define t1	(sk[0])
+#define t2	(sk[1])
+
+/* r must be different to a and b */
+int bn_mm_low(m, A, B, num, sk,ctx)
+BIGNUM *m,*A,*B;
+int num;
+BIGNUM *sk;
+BN_CTX *ctx;
+	{
+	int n; /* ,sqr=0; */
+	int an,bn;
+	BIGNUM ah,al,bh,bl;
+
+	bn_wexpand(m,num+3);
+	an=A->top;
+	bn=B->top;
+
+#ifdef BN_MUL_DEBUG
+printf("bn_mm_low(%d,%d,%d)\n",A->top,B->top,num);
+#endif
+
+	n=(num+1)/2;
+
+	BN_init(&ah); BN_init(&al); BN_init(&bh); BN_init(&bl);
+
+	bn_set_low( &al,A,n);
+	bn_set_high(&ah,A,n);
+	bn_set_low( &bl,B,n);
+	bn_set_high(&bh,B,n);
+
+	if (num <= (bn_limit_num_low+bn_limit_num_low))
+		{
+		BN_mul(m,&al,&bl);
+		BN_mul_low(&t1,&al,&bh,n);
+		BN_mul_low(&t2,&ah,&bl,n);
+		}
+	else
+		{
+		bn_mm(m  ,&al,&bl,&(sk[2]),ctx);
+		bn_mm_low(&t1,&al,&bh,n,&(sk[2]),ctx);
+		bn_mm_low(&t2,&ah,&bl,n,&(sk[2]),ctx);
+		}
+
+	BN_add(&t1,&t1,&t2);
+
+	/* We will now do an evil hack instead of
+	 * BN_lshift(&t1,&t1,n*BN_BITS2);
+	 * BN_add(m,m,&t1);
+	 * BN_mask_bits(m,num*BN_BITS2);
+	 */
+	bn_set_high(&ah,m,n); ah.max=num+2;
+	BN_add(&ah,&ah,&t1);
+	m->top=num;
+
+	m->neg=A->neg^B->neg;
+	return(1);
+	}
+
+#undef t1	(sk[0])
+#undef t2	(sk[1])
diff --git a/crypto/bn/old/bn_m.c b/crypto/bn/old/bn_m.c
new file mode 100644
index 0000000..1cf51e8
--- /dev/null
+++ b/crypto/bn/old/bn_m.c
@@ -0,0 +1,142 @@
+/* crypto/bn/bn_m.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 "cryptlib.h"*/
+#include "bn_lcl.h"
+
+#define limit_bits 5			/* 2^5, or 32 words */
+#define limit_num (1<<limit_bits)
+
+int BN_m(r,a,b)
+BIGNUM *r,*a,*b;
+	{
+	BIGNUM *sk;
+	int i,n;
+
+	n=(BN_num_bits_word(a->top|b->top)-limit_bits);
+	n*=2;
+	sk=(BIGNUM *)malloc(sizeof(BIGNUM)*n);
+	for (i=0; i<n; i++)
+		BN_init(&(sk[i]));
+
+	return(BN_mm(r,a,b,&(sk[0])));
+	}
+
+#define ahal	(sk[0])
+#define blbh	(sk[1])
+
+/* r must be different to a and b */
+int BN_mm(m, A, B, sk)
+BIGNUM *m,*A,*B;
+BIGNUM *sk;
+	{
+	int i,num,anum,bnum;
+	int an,bn;
+	BIGNUM ah,al,bh,bl;
+
+	an=A->top;
+	bn=B->top;
+	if ((an <= limit_num) || (bn <= limit_num))
+		{
+		return(BN_mul(m,A,B));
+		}
+
+	anum=(an>bn)?an:bn;
+	num=(anum)/2;
+
+	/* Are going to now chop things into 'num' word chunks. */
+	bnum=num*BN_BITS2;
+
+	BN_init(&ahal);
+	BN_init(&blbh);
+	BN_init(&ah);
+	BN_init(&al);
+	BN_init(&bh);
+	BN_init(&bl);
+
+	al.top=num;
+	al.d=A->d;
+	ah.top=A->top-num;
+	ah.d= &(A->d[num]);
+
+	bl.top=num;
+	bl.d=B->d;
+	bh.top=B->top-num;
+	bh.d= &(B->d[num]);
+
+	BN_sub(&ahal,&ah,&al);
+	BN_sub(&blbh,&bl,&bh);
+
+	BN_mm(m,&ahal,&blbh,&(sk[2]));
+	BN_mm(&ahal,&al,&bl,&(sk[2]));
+	BN_mm(&blbh,&ah,&bh,&(sk[2]));
+
+	BN_add(m,m,&ahal);
+	BN_add(m,m,&blbh);
+
+	BN_lshift(m,m,bnum);
+	BN_add(m,m,&ahal);
+
+	BN_lshift(&blbh,&blbh,bnum*2);
+	BN_add(m,m,&blbh);
+
+	m->neg=A->neg^B->neg;
+	return(1);
+	}
+
diff --git a/crypto/bn/old/bn_mul.c.works b/crypto/bn/old/bn_mul.c.works
new file mode 100644
index 0000000..6d565d4
--- /dev/null
+++ b/crypto/bn/old/bn_mul.c.works
@@ -0,0 +1,219 @@
+/* crypto/bn/bn_mul.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 "cryptlib.h"
+#include "bn_lcl.h"
+
+int bn_mm(BIGNUM *m,BIGNUM *A,BIGNUM *B, BIGNUM *sk,BN_CTX *ctx);
+
+/* r must be different to a and b */
+int BN_mul(r, a, b)
+BIGNUM *r;
+BIGNUM *a;
+BIGNUM *b;
+	{
+	BN_ULONG *ap,*bp,*rp;
+	BIGNUM *sk;
+	int i,n,ret;
+	int max,al,bl;
+	BN_CTX ctx;
+
+	bn_check_top(a);
+	bn_check_top(b);
+
+	al=a->top;
+	bl=b->top;
+	if ((al == 0) || (bl == 0))
+		{
+		r->top=0;
+		return(1);
+		}
+#ifdef BN_MUL_DEBUG
+printf("BN_mul(%d,%d)\n",a->top,b->top);
+#endif
+
+#ifdef BN_RECURSION
+	if (	(bn_limit_bits > 0) &&
+		(bl > bn_limit_num) && (al > bn_limit_num))
+		{
+		n=(BN_num_bits_word(al|bl)-bn_limit_bits);
+		n*=2;
+		sk=(BIGNUM *)Malloc(sizeof(BIGNUM)*n);
+		memset(sk,0,sizeof(BIGNUM)*n);
+		memset(&ctx,0,sizeof(ctx));
+
+		ret=bn_mm(r,a,b,&(sk[0]),&ctx);
+		for (i=0; i<n; i+=2)
+			{
+			BN_clear_free(&sk[i]);
+			BN_clear_free(&sk[i+1]);
+			}
+		Free(sk);
+		return(ret);
+		}
+#endif
+
+	max=(al+bl);
+	if (bn_wexpand(r,max) == NULL) return(0);
+	r->top=max;
+	r->neg=a->neg^b->neg;
+	ap=a->d;
+	bp=b->d;
+	rp=r->d;
+
+#ifdef BN_RECURSION
+	if ((al == bl) && (al == 8))
+		{
+		bn_mul_comba8(rp,ap,bp);
+		}
+	else
+#endif
+		{
+		rp[al]=bn_mul_words(rp,ap,al,*(bp++));
+		rp++;
+		for (i=1; i<bl; i++)
+			{
+			rp[al]=bn_mul_add_words(rp,ap,al,*(bp++));
+			rp++;
+			}
+		}
+	if ((max > 0) && (r->d[max-1] == 0)) r->top--;
+	return(1);
+	}
+
+#ifdef BN_RECURSION
+
+#define ahal	(sk[0])
+#define blbh	(sk[1])
+
+/* r must be different to a and b */
+int bn_mm(m, A, B, sk,ctx)
+BIGNUM *m,*A,*B;
+BIGNUM *sk;
+BN_CTX *ctx;
+	{
+	int n,num,sqr=0;
+	int an,bn;
+	BIGNUM ah,al,bh,bl;
+
+	an=A->top;
+	bn=B->top;
+#ifdef BN_MUL_DEBUG
+printf("bn_mm(%d,%d)\n",A->top,B->top);
+#endif
+
+	if (A == B) sqr=1;
+	num=(an>bn)?an:bn;
+	n=(num+1)/2;
+	/* Are going to now chop things into 'num' word chunks. */
+
+	BN_init(&ah);
+	BN_init(&al);
+	BN_init(&bh);
+	BN_init(&bl);
+
+	bn_set_low (&al,A,n);
+	bn_set_high(&ah,A,n);
+	bn_set_low (&bl,B,n);
+	bn_set_high(&bh,B,n);
+
+	BN_sub(&ahal,&ah,&al);
+	BN_sub(&blbh,&bl,&bh);
+
+	if (num <= (bn_limit_num+bn_limit_num))
+		{
+		BN_mul(m,&ahal,&blbh);
+		if (sqr)
+			{
+			BN_sqr(&ahal,&al,ctx);
+			BN_sqr(&blbh,&ah,ctx);
+			}
+		else
+			{
+			BN_mul(&ahal,&al,&bl);
+			BN_mul(&blbh,&ah,&bh);
+			}
+		}
+	else
+		{
+		bn_mm(m,&ahal,&blbh,&(sk[2]),ctx);
+		bn_mm(&ahal,&al,&bl,&(sk[2]),ctx);
+		bn_mm(&blbh,&ah,&bh,&(sk[2]),ctx);
+		}
+
+	BN_add(m,m,&ahal);
+	BN_add(m,m,&blbh);
+
+	BN_lshift(m,m,n*BN_BITS2);
+	BN_lshift(&blbh,&blbh,n*BN_BITS2*2);
+
+	BN_add(m,m,&ahal);
+	BN_add(m,m,&blbh);
+
+	m->neg=A->neg^B->neg;
+	return(1);
+	}
+#undef ahal	(sk[0])
+#undef blbh	(sk[1])
+
+#include "bn_low.c"
+#include "bn_high.c"
+#include "f.c"
+
+#endif
diff --git a/crypto/bn/old/bn_wmul.c b/crypto/bn/old/bn_wmul.c
new file mode 100644
index 0000000..e3ce107
--- /dev/null
+++ b/crypto/bn/old/bn_wmul.c
@@ -0,0 +1,181 @@
+#include <stdio.h>
+#include "bn_lcl.h"
+
+#if 1
+
+int bn_mull(BIGNUM *r,BIGNUM *a,BIGNUM *b, BN_CTX *ctx);
+
+int bn_mull(r,a,b,ctx)
+BIGNUM *r,*a,*b;
+BN_CTX *ctx;
+	{
+	int top,i,j,k,al,bl;
+	BIGNUM *t;
+
+#ifdef BN_COUNT
+printf("bn_mull %d * %d\n",a->top,b->top);
+#endif
+
+	bn_check_top(a);
+	bn_check_top(b);
+	bn_check_top(r);
+
+	al=a->top;
+	bl=b->top;
+	r->neg=a->neg^b->neg;
+
+	top=al+bl;
+	if ((al < 4) || (bl < 4))
+		{
+		if (bn_wexpand(r,top) == NULL) return(0);
+		r->top=top;
+		bn_mul_normal(r->d,a->d,al,b->d,bl);
+		goto end;
+		}
+	else if (al == bl) /* A good start, they are the same size */
+		goto symetric;
+	else
+		{
+		i=(al-bl);
+		if ((i ==  1) && !BN_get_flags(b,BN_FLG_STATIC_DATA))
+			{
+			bn_wexpand(b,al);
+			b->d[bl]=0;
+			bl++;
+			goto symetric;
+			}
+		else if ((i ==  -1) && !BN_get_flags(a,BN_FLG_STATIC_DATA))
+			{
+			bn_wexpand(a,bl);
+			a->d[al]=0;
+			al++;
+			goto symetric;
+			}
+		}
+
+	/* asymetric and >= 4 */ 
+	if (bn_wexpand(r,top) == NULL) return(0);
+	r->top=top;
+	bn_mul_normal(r->d,a->d,al,b->d,bl);
+
+	if (0)
+		{
+		/* symetric and > 4 */
+symetric:
+		if (al == 4)
+			{
+			if (bn_wexpand(r,al*2) == NULL) return(0);
+			r->top=top;
+			bn_mul_comba4(r->d,a->d,b->d);
+			goto end;
+			}
+		if (al == 8)
+			{
+			if (bn_wexpand(r,al*2) == NULL) return(0);
+			r->top=top;
+			bn_mul_comba8(r->d,a->d,b->d);
+			goto end;
+			}
+		if (al <= BN_MULL_NORMAL_SIZE)
+			{
+			if (bn_wexpand(r,al*2) == NULL) return(0);
+			r->top=top;
+			bn_mul_normal(r->d,a->d,al,b->d,bl);
+			goto end;
+			}
+		/* 16 or larger */
+		j=BN_num_bits_word((BN_ULONG)al);
+		j=1<<(j-1);
+		k=j+j;
+		t= &(ctx->bn[ctx->tos]);
+		if (al == j) /* exact multiple */
+			{
+			bn_wexpand(t,k*2);
+			bn_wexpand(r,k*2);
+			bn_mul_recursive(r->d,a->d,b->d,al,t->d);
+			}
+		else
+			{
+			bn_wexpand(a,k);
+			bn_wexpand(b,k);
+			bn_wexpand(t,k*4);
+			bn_wexpand(r,k*4);
+			for (i=a->top; i<k; i++)
+				a->d[i]=0;
+			for (i=b->top; i<k; i++)
+				b->d[i]=0;
+			bn_mul_part_recursive(r->d,a->d,b->d,al-j,j,t->d);
+			}
+		r->top=top;
+		}
+end:
+	bn_fix_top(r);
+	return(1);
+	}
+#endif
+
+void bn_mul_normal(r,a,na,b,nb)
+BN_ULONG *r,*a;
+int na;
+BN_ULONG *b;
+int nb;
+	{
+	BN_ULONG *rr;
+
+#ifdef BN_COUNT
+printf(" bn_mul_normal %d * %d\n",na,nb);
+#endif
+
+	if (na < nb)
+		{
+		int itmp;
+		BN_ULONG *ltmp;
+
+		itmp=na; na=nb; nb=itmp;
+		ltmp=a;   a=b;   b=ltmp;
+
+		}
+	rr= &(r[na]);
+	rr[0]=bn_mul_words(r,a,na,b[0]);
+
+	for (;;)
+		{
+		if (--nb <= 0) return;
+		rr[1]=bn_mul_add_words(&(r[1]),a,na,b[1]);
+		if (--nb <= 0) return;
+		rr[2]=bn_mul_add_words(&(r[2]),a,na,b[2]);
+		if (--nb <= 0) return;
+		rr[3]=bn_mul_add_words(&(r[3]),a,na,b[3]);
+		if (--nb <= 0) return;
+		rr[4]=bn_mul_add_words(&(r[4]),a,na,b[4]);
+		rr+=4;
+		r+=4;
+		b+=4;
+		}
+	}
+
+#if 1
+void bn_mul_low_normal(r,a,b,n)
+BN_ULONG *r,*a,*b;
+int n;
+	{
+#ifdef BN_COUNT
+printf(" bn_mul_low_normal %d * %d\n",n,n);
+#endif
+	bn_mul_words(r,a,n,b[0]);
+
+	for (;;)
+		{
+		if (--n <= 0) return;
+		bn_mul_add_words(&(r[1]),a,n,b[1]);
+		if (--n <= 0) return;
+		bn_mul_add_words(&(r[2]),a,n,b[2]);
+		if (--n <= 0) return;
+		bn_mul_add_words(&(r[3]),a,n,b[3]);
+		if (--n <= 0) return;
+		bn_mul_add_words(&(r[4]),a,n,b[4]);
+		r+=4;
+		b+=4;
+		}
+	}
+#endif
diff --git a/crypto/bn/old/build b/crypto/bn/old/build
new file mode 100755
index 0000000..8cd99e5
--- /dev/null
+++ b/crypto/bn/old/build
@@ -0,0 +1,3 @@
+#!/bin/sh -x
+
+gcc -g -I../../include test.c -L../.. -lcrypto
diff --git a/crypto/bn/old/info b/crypto/bn/old/info
new file mode 100644
index 0000000..5ac99c3
--- /dev/null
+++ b/crypto/bn/old/info
@@ -0,0 +1,22 @@
+Given A1A0 * B1B0 == S3S2S1S0
+
+S0=     low(A0*B0)
+S1=     low( (A1-A0)*(B0-B1)) +low( A1*B1) +high(A0*B0)
+S2=     high((A1-A0)*(B0-B1)) +high(A1*B1) +low( A1*B1)
+S3=     high(A1*B1);
+
+Assume we know S1 and S0, and can calulate A1*B1 and high((A1-A0)*(B0-B1))
+
+k0=	S0 == low(A0*B0)
+k1=	S1
+k2=	low( A1*B1)
+k3=	high(A1*B1)
+k4=	high((A1-A0)*(B0-B1))
+
+k1=	low((A1-A0)*(B0-B1)) +k2 +high(A0*B0)
+S2=	k4 +k3 +k2
+S3=	k3
+
+S1-k2= low((A1-A0)*(B0-B1)) +high(A0*B0)
+
+We potentially have a carry or a borrow from S1
diff --git a/crypto/bn/old/test.works b/crypto/bn/old/test.works
new file mode 100644
index 0000000..127c7b4
--- /dev/null
+++ b/crypto/bn/old/test.works
@@ -0,0 +1,205 @@
+#include <stdio.h>
+#include "cryptlib.h"
+#include "bn_lcl.h"
+
+#define SIZE	128
+
+#define BN_MONT_CTX_set		bn_mcs
+#define BN_from_montgomery	bn_fm
+#define BN_mod_mul_montgomery	bn_mmm
+#undef BN_to_montgomery
+#define BN_to_montgomery(r,a,mont,ctx)	bn_mmm(\
+	r,a,(mont)->RR,(mont),ctx)
+
+main()
+	{
+	BIGNUM prime,a,b,r,A,B,R;
+	BN_MONT_CTX *mont;
+	BN_CTX *ctx;
+	int i;
+
+	ctx=BN_CTX_new();
+	BN_init(&prime);
+	BN_init(&a); BN_init(&b); BN_init(&r);
+	BN_init(&A); BN_init(&B); BN_init(&R);
+
+	BN_generate_prime(&prime,SIZE,0,NULL,NULL,NULL,NULL);
+	BN_rand(&A,SIZE,1,0);
+	BN_rand(&B,SIZE,1,0);
+	BN_mod(&A,&A,&prime,ctx);
+	BN_mod(&B,&B,&prime,ctx);
+
+	mont=BN_MONT_CTX_new();
+	BN_MONT_CTX_set(mont,&prime,ctx);
+
+	BN_to_montgomery(&a,&A,mont,ctx);
+	BN_to_montgomery(&b,&B,mont,ctx);
+
+	BN_mul(&r,&a,&b);
+	BN_print_fp(stdout,&r); printf("\n");
+	BN_from_montgomery(&r,&r,mont,ctx);
+	BN_print_fp(stdout,&r); printf("\n");
+	BN_from_montgomery(&r,&r,mont,ctx);
+	BN_print_fp(stdout,&r); printf("\n");
+
+	BN_mod_mul(&R,&A,&B,&prime,ctx);
+
+	BN_print_fp(stdout,&a); printf("\n");
+	BN_print_fp(stdout,&b); printf("\n");
+	BN_print_fp(stdout,&prime); printf("\n");
+	BN_print_fp(stdout,&r); printf("\n\n");
+
+	BN_print_fp(stdout,&A); printf("\n");
+	BN_print_fp(stdout,&B); printf("\n");
+	BN_print_fp(stdout,&prime); printf("\n");
+	BN_print_fp(stdout,&R); printf("\n\n");
+
+	BN_mul(&r,&a,&b);
+	BN_print_fp(stdout,&r); printf(" <- BA*DC\n");
+	BN_copy(&A,&r);
+	i=SIZE/2;
+	BN_mask_bits(&A,i*2);
+//	BN_print_fp(stdout,&A); printf(" <- low(BA*DC)\n");
+	bn_do_lower(&r,&a,&b,&A,i);
+//	BN_print_fp(stdout,&r); printf(" <- low(BA*DC)\n");
+	}
+
+int bn_mul_low(r,a,b,low,i)
+BIGNUM *r,*a,*b,*low;
+int i;
+	{
+	int w;
+	BIGNUM Kh,Km,t1,t2,h,ah,al,bh,bl,l,m,s0,s1;
+
+	BN_init(&Kh); BN_init(&Km); BN_init(&t1); BN_init(&t2); BN_init(&l);
+	BN_init(&ah); BN_init(&al); BN_init(&bh); BN_init(&bl); BN_init(&h);
+	BN_init(&m); BN_init(&s0); BN_init(&s1);
+
+	BN_copy(&al,a); BN_mask_bits(&al,i); BN_rshift(&ah,a,i);
+	BN_copy(&bl,b); BN_mask_bits(&bl,i); BN_rshift(&bh,b,i);
+
+
+	BN_sub(&t1,&al,&ah);
+	BN_sub(&t2,&bh,&bl);
+	BN_mul(&m,&t1,&t2);
+	BN_mul(&h,&ah,&bh);
+
+	BN_copy(&s0,low); BN_mask_bits(&s0,i);
+	BN_rshift(&s1,low,i);
+
+	BN_add(&t1,&h,&m);
+	BN_add(&t1,&t1,&s0);
+
+	BN_copy(&t2,&t1); BN_mask_bits(&t2,i);
+	BN_sub(&t1,&s1,&t2);
+	BN_lshift(&t1,&t1,i);
+	BN_add(&t1,&t1,&s0);
+	if (t1.neg)
+		{
+		BN_lshift(&t2,BN_value_one(),i*2);
+		BN_add(&t1,&t2,&t1);
+		BN_mask_bits(&t1,i*2);
+		}
+	
+	BN_free(&Kh); BN_free(&Km); BN_free(&t1); BN_free(&t2);
+	BN_free(&ah); BN_free(&al); BN_free(&bh); BN_free(&bl);
+	}
+
+int BN_mod_mul_montgomery(r,a,b,mont,ctx)
+BIGNUM *r,*a,*b;
+BN_MONT_CTX *mont;
+BN_CTX *ctx;
+	{
+	BIGNUM *tmp;
+
+        tmp= &(ctx->bn[ctx->tos++]);
+
+	if (a == b)
+		{
+		if (!BN_sqr(tmp,a,ctx)) goto err;
+		}
+	else
+		{
+		if (!BN_mul(tmp,a,b)) goto err;
+		}
+	/* reduce from aRR to aR */
+	if (!BN_from_montgomery(r,tmp,mont,ctx)) goto err;
+	ctx->tos--;
+	return(1);
+err:
+	return(0);
+	}
+
+int BN_from_montgomery(r,a,mont,ctx)
+BIGNUM *r;
+BIGNUM *a;
+BN_MONT_CTX *mont;
+BN_CTX *ctx;
+	{
+	BIGNUM z1;
+	BIGNUM *t1,*t2;
+	BN_ULONG *ap,*bp,*rp;
+	int j,i,bl,al;
+
+	BN_init(&z1);
+	t1= &(ctx->bn[ctx->tos]);
+	t2= &(ctx->bn[ctx->tos+1]);
+
+	if (!BN_copy(t1,a)) goto err;
+	/* can cheat */
+	BN_mask_bits(t1,mont->ri);
+	if (!BN_mul(t2,t1,mont->Ni)) goto err;
+	BN_mask_bits(t2,mont->ri);
+
+	if (!BN_mul(t1,t2,mont->N)) goto err;
+	if (!BN_add(t2,t1,a)) goto err;
+
+	/* At this point, t2 has the bottom ri bits set to zero.
+	 * This means that the bottom ri bits == the 1^ri minus the bottom
+	 * ri bits of a.
+	 * This means that only the bits above 'ri' in a need to be added,
+	 * and XXXXXXXXXXXXXXXXXXXXXXXX
+	 */
+BN_print_fp(stdout,t2); printf("\n");
+	BN_rshift(r,t2,mont->ri);
+
+	if (BN_ucmp(r,mont->N) >= 0)
+		bn_qsub(r,r,mont->N);
+
+	return(1);
+err:
+	return(0);
+	}
+
+int BN_MONT_CTX_set(mont,mod,ctx)
+BN_MONT_CTX *mont;
+BIGNUM *mod;
+BN_CTX *ctx;
+	{
+	BIGNUM *Ri=NULL,*R=NULL;
+
+	if (mont->RR == NULL) mont->RR=BN_new();
+	if (mont->N == NULL)  mont->N=BN_new();
+
+	R=mont->RR;					/* grab RR as a temp */
+	BN_copy(mont->N,mod);				/* Set N */
+
+	mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2;
+	BN_lshift(R,BN_value_one(),mont->ri);			/* R */
+	if ((Ri=BN_mod_inverse(NULL,R,mod,ctx)) == NULL) goto err;/* Ri */
+	BN_lshift(Ri,Ri,mont->ri);				/* R*Ri */
+	bn_qsub(Ri,Ri,BN_value_one());				/* R*Ri - 1 */
+	BN_div(Ri,NULL,Ri,mod,ctx);
+	if (mont->Ni != NULL) BN_free(mont->Ni);
+	mont->Ni=Ri;					/* Ni=(R*Ri-1)/N */
+
+	/* setup RR for conversions */
+	BN_lshift(mont->RR,BN_value_one(),mont->ri*2);
+	BN_mod(mont->RR,mont->RR,mont->N,ctx);
+
+	return(1);
+err:
+	return(0);
+	}
+
+
diff --git a/crypto/bn/test.c b/crypto/bn/test.c
new file mode 100644
index 0000000..e23f215
--- /dev/null
+++ b/crypto/bn/test.c
@@ -0,0 +1,252 @@
+#include <stdio.h>
+#include "cryptlib.h"
+#include "bn_lcl.h"
+
+#define SIZE	32
+
+#define BN_MONT_CTX_set		bn_mcs
+#define BN_from_montgomery	bn_fm
+#define BN_mod_mul_montgomery	bn_mmm
+#undef BN_to_montgomery
+#define BN_to_montgomery(r,a,mont,ctx)	bn_mmm(\
+	r,a,(mont)->RR,(mont),ctx)
+
+main()
+	{
+	BIGNUM prime,a,b,r,A,B,R;
+	BN_MONT_CTX *mont;
+	BN_CTX *ctx;
+	int i;
+
+	ctx=BN_CTX_new();
+	BN_init(&prime);
+	BN_init(&a); BN_init(&b); BN_init(&r);
+	BN_init(&A); BN_init(&B); BN_init(&R);
+
+	BN_generate_prime(&prime,SIZE,0,NULL,NULL,NULL,NULL);
+	BN_rand(&A,SIZE,1,0);
+	BN_rand(&B,SIZE,1,0);
+	BN_mod(&A,&A,&prime,ctx);
+	BN_mod(&B,&B,&prime,ctx);
+
+	i=A.top;
+	BN_mul(&R,&A,&B,ctx);
+	BN_mask_bits(&R,i*BN_BITS2);
+
+
+	BN_print_fp(stdout,&A); printf(" <- a\n");
+	BN_print_fp(stdout,&B); printf(" <- b\n");
+	BN_mul_high(&r,&A,&B,&R,i);
+	BN_print_fp(stdout,&r); printf(" <- high(BA*DC)\n");
+
+	BN_mask_bits(&A,i*32);
+	BN_mask_bits(&B,i*32);
+
+	BN_mul(&R,&A,&B);
+	BN_rshift(&R,&R,i*32);
+	BN_print_fp(stdout,&R); printf(" <- norm BA*DC\n");
+	BN_sub(&R,&R,&r);
+	BN_print_fp(stdout,&R); printf(" <- diff\n");
+	}
+
+#if 0
+int bn_mul_high(r,a,b,low,words)
+BIGNUM *r,*a,*b,*low;
+int words;
+	{
+	int i;
+	BIGNUM t1,t2,t3,h,ah,al,bh,bl,m,s0,s1;
+
+	BN_init(&al); BN_init(&ah);
+	BN_init(&bl); BN_init(&bh);
+	BN_init(&t1); BN_init(&t2); BN_init(&t3);
+	BN_init(&s0); BN_init(&s1);
+	BN_init(&h); BN_init(&m);
+
+	i=a->top;
+	if (i >= words)
+		{
+		al.top=words;
+		ah.top=a->top-words;
+		ah.d= &(a->d[ah.top]);
+		}
+	else
+		al.top=i;
+	al.d=a->d;
+
+	i=b->top;
+	if (i >= words)
+		{
+		bl.top=words;
+		bh.top=i-words;
+		bh.d= &(b->d[bh.top]);
+		}
+	else
+		bl.top=i;
+	bl.d=b->d;
+
+	i=low->top;
+	if (i >= words)
+		{
+		s0.top=words;
+		s1.top=i-words;
+		s1.d= &(low->d[s1.top]);
+		}
+	else
+		s0.top=i;
+	s0.d=low->d;
+
+al.max=al.top; ah.max=ah.top;
+bl.max=bl.top; bh.max=bh.top;
+s0.max=bl.top; s1.max=bh.top;
+
+	/* Calculate (al-ah)*(bh-bl) */
+	BN_sub(&t1,&al,&ah);
+	BN_sub(&t2,&bh,&bl);
+	BN_mul(&m,&t1,&t2);
+
+	/* Calculate ah*bh */
+	BN_mul(&h,&ah,&bh);
+
+	/* s0 == low(al*bl)
+	 * s1 == low(ah*bh)+low((al-ah)*(bh-bl))+low(al*bl)+high(al*bl)
+	 * We know s0 and s1 so the only unknown is high(al*bl)
+	 * high(al*bl) == s1 - low(ah*bh+(al-ah)*(bh-bl)+s0)
+	 */
+	BN_add(&m,&m,&h);
+	BN_add(&t2,&m,&s0);
+	/* Quick and dirty mask off of high words */
+	t3.d=t2.d;
+	t3.top=(t2.top > words)?words:t2.top;
+	t3.neg=t2.neg;
+t3.max=t3.top;
+// BN_print_fp(stdout,&s1); printf(" s1\n");
+// BN_print_fp(stdout,&t2); printf(" middle value\n");
+// BN_print_fp(stdout,&t3); printf(" low middle value\n");
+	BN_sub(&t1,&s1,&t3);
+
+	if (t1.neg)
+		{
+//printf("neg fixup\n"); //BN_print_fp(stdout,&t1); printf(" before\n");
+		BN_lshift(&t2,BN_value_one(),words*32);
+		BN_add(&t1,&t2,&t1);
+		BN_mask_bits(&t1,words*32);
+// BN_print_fp(stdout,&t1); printf(" after\n");
+		}
+	/* al*bl == high(al*bl)<<words+s0 */
+	BN_lshift(&t1,&t1,words*32);
+	BN_add(&t1,&t1,&s0);
+	
+	/* We now have
+	 * al*bl			- t1
+	 * (al-ah)*(bh-bl)+ah*bh	- m
+	 * ah*bh			- h
+	 */
+	BN_copy(r,&t1);
+	BN_mask_bits(r,words*32*2);
+
+	/*BN_lshift(&m,&m,words*/
+
+	BN_free(&t1); BN_free(&t2);
+	BN_free(&m); BN_free(&h);
+	}
+
+int BN_mod_mul_montgomery(r,a,b,mont,ctx)
+BIGNUM *r,*a,*b;
+BN_MONT_CTX *mont;
+BN_CTX *ctx;
+	{
+	BIGNUM *tmp;
+
+        tmp= &(ctx->bn[ctx->tos++]);
+
+	if (a == b)
+		{
+		if (!BN_sqr(tmp,a,ctx)) goto err;
+		}
+	else
+		{
+		if (!BN_mul(tmp,a,b)) goto err;
+		}
+	/* reduce from aRR to aR */
+	if (!BN_from_montgomery(r,tmp,mont,ctx)) goto err;
+	ctx->tos--;
+	return(1);
+err:
+	return(0);
+	}
+
+int BN_from_montgomery(r,a,mont,ctx)
+BIGNUM *r;
+BIGNUM *a;
+BN_MONT_CTX *mont;
+BN_CTX *ctx;
+	{
+	BIGNUM z1;
+	BIGNUM *t1,*t2;
+	BN_ULONG *ap,*bp,*rp;
+	int j,i,bl,al;
+
+	BN_init(&z1);
+	t1= &(ctx->bn[ctx->tos]);
+	t2= &(ctx->bn[ctx->tos+1]);
+
+	if (!BN_copy(t1,a)) goto err;
+	/* can cheat */
+	BN_mask_bits(t1,mont->ri);
+	if (!BN_mul(t2,t1,mont->Ni)) goto err;
+	BN_mask_bits(t2,mont->ri);
+
+	if (!BN_mul(t1,t2,mont->N)) goto err;
+	if (!BN_add(t2,t1,a)) goto err;
+
+	/* At this point, t2 has the bottom ri bits set to zero.
+	 * This means that the bottom ri bits == the 1^ri minus the bottom
+	 * ri bits of a.
+	 * This means that only the bits above 'ri' in a need to be added,
+	 * and XXXXXXXXXXXXXXXXXXXXXXXX
+	 */
+BN_print_fp(stdout,t2); printf("\n");
+	BN_rshift(r,t2,mont->ri);
+
+	if (BN_ucmp(r,mont->N) >= 0)
+		BN_usub(r,r,mont->N);
+
+	return(1);
+err:
+	return(0);
+	}
+
+int BN_MONT_CTX_set(mont,mod,ctx)
+BN_MONT_CTX *mont;
+BIGNUM *mod;
+BN_CTX *ctx;
+	{
+	BIGNUM *Ri=NULL,*R=NULL;
+
+	if (mont->RR == NULL) mont->RR=BN_new();
+	if (mont->N == NULL)  mont->N=BN_new();
+
+	R=mont->RR;					/* grab RR as a temp */
+	BN_copy(mont->N,mod);				/* Set N */
+
+	mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2;
+	BN_lshift(R,BN_value_one(),mont->ri);			/* R */
+	if ((Ri=BN_mod_inverse(NULL,R,mod,ctx)) == NULL) goto err;/* Ri */
+	BN_lshift(Ri,Ri,mont->ri);				/* R*Ri */
+	BN_usub(Ri,Ri,BN_value_one());				/* R*Ri - 1 */
+	BN_div(Ri,NULL,Ri,mod,ctx);
+	if (mont->Ni != NULL) BN_free(mont->Ni);
+	mont->Ni=Ri;					/* Ni=(R*Ri-1)/N */
+
+	/* setup RR for conversions */
+	BN_lshift(mont->RR,BN_value_one(),mont->ri*2);
+	BN_mod(mont->RR,mont->RR,mont->N,ctx);
+
+	return(1);
+err:
+	return(0);
+	}
+
+
+#endif
diff --git a/crypto/bn/todo b/crypto/bn/todo
new file mode 100644
index 0000000..e47e381
--- /dev/null
+++ b/crypto/bn/todo
@@ -0,0 +1,3 @@
+Cache RECP_CTX values
+make the result argument independant of the inputs.
+split up the _exp_ functions
diff --git a/crypto/buffer/buf_err.c b/crypto/buffer/buf_err.c
index ff98885..433cf3a 100644
--- a/crypto/buffer/buf_err.c
+++ b/crypto/buffer/buf_err.c
@@ -76,8 +76,8 @@
 	{
 	static int init=1;
 
-	if (init);
-		{;
+	if (init)
+		{
 		init=0;
 #ifndef NO_ERR
 		ERR_load_strings(ERR_LIB_BUF,BUF_str_functs);
diff --git a/crypto/cast/Makefile.ssl b/crypto/cast/Makefile.ssl
index 0143827..c59982e 100644
--- a/crypto/cast/Makefile.ssl
+++ b/crypto/cast/Makefile.ssl
@@ -64,7 +64,7 @@
 
 # bsdi
 asm/cx86bsdi.o: asm/cx86unix.cpp
-	$(CPP) -DBSDI asm/cx86unix.cpp | as -o asm/cx86bsdi.o
+	$(CPP) -DBSDI asm/cx86unix.cpp | sed 's/ :/:/' | as -o asm/cx86bsdi.o
 
 asm/cx86unix.cpp:
 	(cd asm; perl cast-586.pl cpp >cx86unix.cpp)
diff --git a/crypto/cast/c_ecb.c b/crypto/cast/c_ecb.c
index f0f2f4d..fe34bd1 100644
--- a/crypto/cast/c_ecb.c
+++ b/crypto/cast/c_ecb.c
@@ -59,7 +59,7 @@
 #include "cast.h"
 #include "cast_lcl.h"
 
-char *CAST_version="CAST part of SSLeay 0.9.0b 29-Jun-1998";
+char *CAST_version="CAST part of SSLeay 0.9.1a 06-Jul-1998";
 
 void CAST_ecb_encrypt(in, out, ks, encrypt)
 unsigned char *in;
diff --git a/crypto/cast/cast_spd.c b/crypto/cast/cast_spd.c
index ab75e65..885b1df 100644
--- a/crypto/cast/cast_spd.c
+++ b/crypto/cast/cast_spd.c
@@ -92,7 +92,8 @@
 #include <sys/timeb.h>
 #endif
 
-#ifdef sun
+#if defined(sun) || defined(__ultrix)
+#define _POSIX_SOURCE
 #include <limits.h>
 #include <sys/param.h>
 #endif
diff --git a/crypto/cast/castopts.c b/crypto/cast/castopts.c
index 68cf5a4..8635b46 100644
--- a/crypto/cast/castopts.c
+++ b/crypto/cast/castopts.c
@@ -92,7 +92,8 @@
 #include <sys/timeb.h>
 #endif
 
-#ifdef sun
+#if defined(sun) || defined(__ultrix)
+#define _POSIX_SOURCE
 #include <limits.h>
 #include <sys/param.h>
 #endif
diff --git a/crypto/comp/Makefile.ssl b/crypto/comp/Makefile.ssl
new file mode 100644
index 0000000..8673626
--- /dev/null
+++ b/crypto/comp/Makefile.ssl
@@ -0,0 +1,87 @@
+#
+# SSLeay/crypto/comp/Makefile
+#
+
+DIR=	comp
+TOP=	../..
+CC=	cc
+INCLUDES= -I.. -I../../include
+CFLAG=-g
+INSTALLTOP=/usr/local/ssl
+MAKE=		make -f Makefile.ssl
+MAKEDEPEND=	makedepend -f Makefile.ssl
+MAKEFILE=	Makefile.ssl
+AR=		ar r
+
+CFLAGS= $(INCLUDES) $(CFLAG)
+
+ERR=comp
+ERRC=comp_err
+GENERAL=Makefile
+TEST=
+APPS=
+
+LIB=$(TOP)/libcrypto.a
+LIBSRC= comp_lib.c \
+	c_rle.c c_zlib.c
+
+LIBOBJ=	comp_lib.o \
+	c_rle.o c_zlib.o
+
+SRC= $(LIBSRC)
+
+EXHEADER= comp.h
+HEADER=	$(EXHEADER)
+
+ALL=    $(GENERAL) $(SRC) $(HEADER)
+
+top:
+	(cd ../..; $(MAKE) DIRS=crypto SDIRS=$(DIR) sub_all)
+
+all:	lib
+
+lib:	$(LIBOBJ)
+	$(AR) $(LIB) $(LIBOBJ)
+	sh $(TOP)/util/ranlib.sh $(LIB)
+	@touch lib
+
+files:
+	perl $(TOP)/util/files.pl Makefile.ssl >> $(TOP)/MINFO
+
+links:
+	/bin/rm -f Makefile
+	$(TOP)/util/point.sh Makefile.ssl Makefile ;
+	$(TOP)/util/mklink.sh ../../include $(EXHEADER)
+	$(TOP)/util/mklink.sh ../../test $(TEST)
+	$(TOP)/util/mklink.sh ../../apps $(APPS)
+
+install:
+	@for i in $(EXHEADER) ; \
+	do  \
+	(cp $$i $(INSTALLTOP)/include/$$i; \
+	chmod 644 $(INSTALLTOP)/include/$$i ); \
+	done;
+
+tags:
+	ctags $(SRC)
+
+tests:
+
+lint:
+	lint -DLINT $(INCLUDES) $(SRC)>fluff
+
+depend:
+	$(MAKEDEPEND) $(INCLUDES) $(LIBSRC)
+
+dclean:
+	perl -pe 'if (/^# DO NOT DELETE THIS LINE/) {print; exit(0);}' $(MAKEFILE) >Makefile.new
+	mv -f Makefile.new $(MAKEFILE)
+
+clean:
+	/bin/rm -f *.o *.obj lib tags core .pure .nfs* *.old *.bak fluff
+
+errors:
+	perl $(TOP)/util/err-ins.pl $(ERR).err $(ERR).h
+	perl ../err/err_genc.pl -s $(ERR).h $(ERRC).c
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
diff --git a/crypto/comp/c_rle.c b/crypto/comp/c_rle.c
new file mode 100644
index 0000000..b8b9b3e
--- /dev/null
+++ b/crypto/comp/c_rle.c
@@ -0,0 +1,69 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "objects.h"
+#include "comp.h"
+
+static int rle_compress_block(COMP_CTX *ctx, unsigned char *out,
+	unsigned int olen, unsigned char *in, unsigned int ilen);
+static int rle_expand_block(COMP_CTX *ctx, unsigned char *out,
+	unsigned int olen, unsigned char *in, unsigned int ilen);
+
+static COMP_METHOD rle_method={
+	NID_rle_compression,
+	LN_rle_compression,
+	NULL,
+	NULL,
+	rle_compress_block,
+	rle_expand_block,
+	NULL,
+	};
+
+COMP_METHOD *COMP_rle()
+	{
+	return(&rle_method);
+	}
+
+static int rle_compress_block(ctx,out,olen,in,ilen)
+COMP_CTX *ctx;
+unsigned char *out;
+unsigned int olen;
+unsigned char *in;
+unsigned int ilen;
+	{
+	/* int i; */
+
+	if (olen < (ilen+1))
+		{
+		/* ZZZZZZZZZZZZZZZZZZZZZZ */
+		return(-1);
+		}
+
+	*(out++)=0;
+	memcpy(out,in,ilen);
+	return(ilen+1);
+	}
+
+static int rle_expand_block(ctx,out,olen,in,ilen)
+COMP_CTX *ctx;
+unsigned char *out;
+unsigned int olen;
+unsigned char *in;
+unsigned int ilen;
+	{
+	int i;
+
+	if (olen < (ilen-1))
+		{
+		/* ZZZZZZZZZZZZZZZZZZZZZZ */
+		return(-1);
+		}
+
+	i= *(in++);
+	if (i == 0)
+		{
+		memcpy(out,in,ilen-1);
+		}
+	return(ilen-1);
+	}
+
diff --git a/crypto/comp/c_zlib.c b/crypto/comp/c_zlib.c
new file mode 100644
index 0000000..35ab0c6
--- /dev/null
+++ b/crypto/comp/c_zlib.c
@@ -0,0 +1,144 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "objects.h"
+#include "comp.h"
+
+COMP_METHOD *COMP_zlib(void );
+
+#ifndef ZLIB
+
+static COMP_METHOD zlib_method={
+	NID_undef,
+	"(null)",
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	};
+
+#else
+
+#include <zlib.h>
+
+static int zlib_compress_block(COMP_CTX *ctx, unsigned char *out,
+	unsigned int olen, unsigned char *in, unsigned int ilen);
+static int zlib_expand_block(COMP_CTX *ctx, unsigned char *out,
+	unsigned int olen, unsigned char *in, unsigned int ilen);
+
+static int zz_uncompress(Bytef *dest, uLongf *destLen, const Bytef *source,
+	uLong sourceLen);
+
+static COMP_METHOD zlib_method={
+	NID_zlib_compression,
+	LN_zlib_compression,
+	NULL,
+	NULL,
+	zlib_compress_block,
+	zlib_expand_block,
+	NULL,
+	};
+
+static int zlib_compress_block(ctx,out,olen,in,ilen)
+COMP_CTX *ctx;
+unsigned char *out;
+unsigned int olen;
+unsigned char *in;
+unsigned int ilen;
+	{
+	unsigned long l;
+	int i;
+	int clear=1;
+
+	if (ilen > 128)
+		{
+		out[0]=1;
+		l=olen-1;
+		i=compress(&(out[1]),&l,in,(unsigned long)ilen);
+		if (i != Z_OK)
+			return(-1);
+		if (ilen > l)
+			{
+			clear=0;
+			l++;
+			}
+		}
+	if (clear)
+		{
+		out[0]=0;
+		memcpy(&(out[1]),in,ilen);
+		l=ilen+1;
+		}
+fprintf(stderr,"compress(%4d)->%4d %s\n",ilen,(int)l,(clear)?"clear":"zlib");
+	return((int)l);
+	}
+
+static int zlib_expand_block(ctx,out,olen,in,ilen)
+COMP_CTX *ctx;
+unsigned char *out;
+unsigned int olen;
+unsigned char *in;
+unsigned int ilen;
+	{
+	unsigned long l;
+	int i;
+
+	if (in[0])
+		{
+		l=olen;
+		i=zz_uncompress(out,&l,&(in[1]),(unsigned long)ilen-1);
+		if (i != Z_OK)
+			return(-1);
+		}
+	else
+		{
+		memcpy(out,&(in[1]),ilen-1);
+		l=ilen-1;
+		}
+        fprintf(stderr,"expand  (%4d)->%4d %s\n",ilen,(int)l,in[0]?"zlib":"clear");
+	return((int)l);
+	}
+
+static int zz_uncompress (dest, destLen, source, sourceLen)
+    Bytef *dest;
+    uLongf *destLen;
+    const Bytef *source;
+    uLong sourceLen;
+{
+    z_stream stream;
+    int err;
+
+    stream.next_in = (Bytef*)source;
+    stream.avail_in = (uInt)sourceLen;
+    /* Check for source > 64K on 16-bit machine: */
+    if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
+
+    stream.next_out = dest;
+    stream.avail_out = (uInt)*destLen;
+    if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+    stream.zalloc = (alloc_func)0;
+    stream.zfree = (free_func)0;
+
+    err = inflateInit(&stream);
+    if (err != Z_OK) return err;
+
+    err = inflate(&stream, Z_FINISH);
+    if (err != Z_STREAM_END) {
+        inflateEnd(&stream);
+        return err;
+    }
+    *destLen = stream.total_out;
+
+    err = inflateEnd(&stream);
+    return err;
+}
+
+#endif
+
+COMP_METHOD *COMP_zlib()
+	{
+	return(&zlib_method);
+	}
+
diff --git a/crypto/comp/comp.err b/crypto/comp/comp.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/crypto/comp/comp.err
diff --git a/crypto/comp/comp.h b/crypto/comp/comp.h
new file mode 100644
index 0000000..00af062
--- /dev/null
+++ b/crypto/comp/comp.h
@@ -0,0 +1,64 @@
+
+#ifndef HEADER_COMP_H
+#define HEADER_COMP_H
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#include "crypto.h"
+
+typedef struct comp_method_st
+	{
+	int type;		/* NID for compression library */
+	char *name;		/* A text string to identify the library */
+	int (*init)();
+	void (*finish)();
+	int (*compress)();
+	int (*expand)();
+	long (*ctrl)();
+	} COMP_METHOD;
+
+typedef struct comp_ctx_st
+	{
+	COMP_METHOD *meth;
+	unsigned long compress_in;
+	unsigned long compress_out;
+	unsigned long expand_in;
+	unsigned long expand_out;
+
+	CRYPTO_EX_DATA	ex_data;
+	} COMP_CTX;
+
+#ifndef NOPROTO
+
+COMP_CTX *COMP_CTX_new(COMP_METHOD *meth);
+void COMP_CTX_free(COMP_CTX *ctx);
+int COMP_compress_block(COMP_CTX *ctx, unsigned char *out, int olen,
+	unsigned char *in, int ilen);
+int COMP_expand_block(COMP_CTX *ctx, unsigned char *out, int olen,
+	unsigned char *in, int ilen);
+COMP_METHOD *COMP_rle(void );
+#ifdef ZLIB
+COMP_METHOD *COMP_zlib(void );
+#endif
+
+#else
+
+COMP_CTX *COMP_CTX_new();
+void COMP_CTX_free();
+int COMP_compress_block();
+int COMP_expand_block();
+COMP_METHOD *COMP_rle();
+#ifdef ZLIB
+COMP_METHOD *COMP_zlib();
+#endif
+
+#endif
+/* BEGIN ERROR CODES */
+ 
+#ifdef  __cplusplus
+}
+#endif
+#endif
+
diff --git a/crypto/comp/comp_err.c b/crypto/comp/comp_err.c
new file mode 100644
index 0000000..7b68fc1
--- /dev/null
+++ b/crypto/comp/comp_err.c
@@ -0,0 +1,77 @@
+/* lib//_err.c */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+#include <stdio.h>
+#include "err.h"
+#include "comp.h"
+
+/* BEGIN ERROR CODES */
+#ifndef NO_ERR
+#endif
+
+void ERR_load__strings()
+	{
+	static int init=1;
+
+	if (init)
+		{
+		init=0;
+#ifndef NO_ERR
+#endif
+
+		}
+	}
diff --git a/crypto/comp/comp_lib.c b/crypto/comp/comp_lib.c
new file mode 100644
index 0000000..8ce0695
--- /dev/null
+++ b/crypto/comp/comp_lib.c
@@ -0,0 +1,85 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "objects.h"
+#include "comp.h"
+
+COMP_CTX *COMP_CTX_new(meth)
+COMP_METHOD *meth;
+	{
+	COMP_CTX *ret;
+
+	if ((ret=(COMP_CTX *)Malloc(sizeof(COMP_CTX))) == NULL)
+		{
+		/* ZZZZZZZZZZZZZZZZ */
+		return(NULL);
+		}
+	memset(ret,0,sizeof(COMP_CTX));
+	ret->meth=meth;
+	if ((ret->meth->init != NULL) && !ret->meth->init(ret))
+		{
+		Free(ret);
+		ret=NULL;
+		}
+#if 0
+	else
+		CRYPTO_new_ex_data(rsa_meth,(char *)ret,&ret->ex_data);
+#endif
+	return(ret);
+	}
+
+void COMP_CTX_free(ctx)
+COMP_CTX *ctx;
+	{
+	/* CRYPTO_free_ex_data(rsa_meth,(char *)ctx,&ctx->ex_data); */
+
+	if (ctx->meth->finish != NULL)
+		ctx->meth->finish(ctx);
+
+	Free(ctx);
+	}
+
+int COMP_compress_block(ctx,out,olen,in,ilen)
+COMP_CTX *ctx;
+unsigned char *out;
+int olen;
+unsigned char *in;
+int ilen;
+	{
+	int ret;
+	if (ctx->meth->compress == NULL)
+		{
+		/* ZZZZZZZZZZZZZZZZZ */
+		return(-1);
+		}
+	ret=ctx->meth->compress(ctx,out,olen,in,ilen);
+	if (ret > 0)
+		{
+		ctx->compress_in+=ilen;
+		ctx->compress_out+=ret;
+		}
+	return(ret);
+	}
+
+int COMP_expand_block(ctx,out,olen,in,ilen)
+COMP_CTX *ctx;
+unsigned char *out;
+int olen;
+unsigned char *in;
+int ilen;
+	{
+	int ret;
+
+	if (ctx->meth->expand == NULL)
+		{
+		/* ZZZZZZZZZZZZZZZZZ */
+		return(-1);
+		}
+	ret=ctx->meth->expand(ctx,out,olen,in,ilen);
+	if (ret > 0)
+		{
+		ctx->expand_in+=ilen;
+		ctx->expand_out+=ret;
+		}
+	return(ret);
+	}
diff --git a/crypto/conf/conf.c b/crypto/conf/conf.c
index 9e84300..f5114ea 100644
--- a/crypto/conf/conf.c
+++ b/crypto/conf/conf.c
@@ -93,9 +93,9 @@
 static CONF_VALUE *get_section();
 #endif
 
-#define scan_esc(p)	((*(++p) == '\0')?(p):(++p))
+#define scan_esc(p)	((((p)[1] == '\0')?(p++):(p+=2)),p)
 
-char *CONF_version="CONF part of SSLeay 0.9.0b 29-Jun-1998";
+char *CONF_version="CONF part of SSLeay 0.9.1a 06-Jul-1998";
 
 LHASH *CONF_load(h,file,line)
 LHASH *h;
@@ -105,10 +105,12 @@
 	LHASH *ret=NULL;
 	FILE *in=NULL;
 #define BUFSIZE	512
+	char btmp[16];
 	int bufnum=0,i,ii;
 	BUF_MEM *buff=NULL;
 	char *s,*p,*end;
-	int again,n,eline=0;
+	int again,n;
+	long eline=0;
 	CONF_VALUE *v=NULL,*vv,*tv;
 	CONF_VALUE *sv=NULL;
 	char *section=NULL,*buf;
@@ -219,12 +221,21 @@
 		if (IS_EOF(*s)) continue; /* blank line */
 		if (*s == '[')
 			{
+			char *ss;
+
 			s++;
 			start=eat_ws(s);
-			end=eat_alpha_numeric(start);
+			ss=start;
+again:
+			end=eat_alpha_numeric(ss);
 			p=eat_ws(end);
 			if (*p != ']')
 				{
+				if (*p != '\0')
+					{
+					ss=p;
+					goto again;
+					}
 				CONFerr(CONF_F_CONF_LOAD,CONF_R_MISSING_CLOSE_SQUARE_BRACKET);
 				goto err;
 				}
@@ -328,6 +339,8 @@
 	if (buff != NULL) BUF_MEM_free(buff);
 	if (section != NULL) Free(section);
 	if (line != NULL) *line=eline;
+	sprintf(btmp,"%ld",eline);
+	ERR_add_error_data(2,"line ",btmp);
 	if (in != NULL) fclose(in);
 	if ((h != ret) && (ret != NULL)) CONF_free(ret);
 	if (v != NULL)
diff --git a/crypto/conf/conf_err.c b/crypto/conf/conf_err.c
index a8db8f2..c6929b9 100644
--- a/crypto/conf/conf_err.c
+++ b/crypto/conf/conf_err.c
@@ -84,8 +84,8 @@
 	{
 	static int init=1;
 
-	if (init);
-		{;
+	if (init)
+		{
 		init=0;
 #ifndef NO_ERR
 		ERR_load_strings(ERR_LIB_CONF,CONF_str_functs);
diff --git a/crypto/cpt_err.c b/crypto/cpt_err.c
index ea3c135..27652fc 100644
--- a/crypto/cpt_err.c
+++ b/crypto/cpt_err.c
@@ -75,8 +75,8 @@
 	{
 	static int init=1;
 
-	if (init);
-		{;
+	if (init)
+		{
 		init=0;
 #ifndef NO_ERR
 		ERR_load_strings(ERR_LIB_CRYPTO,CRYPTO_str_functs);
diff --git a/crypto/cryptlib.c b/crypto/cryptlib.c
index 9a7e80b..3614e3f 100644
--- a/crypto/cryptlib.c
+++ b/crypto/cryptlib.c
@@ -120,10 +120,11 @@
 	SSLeay_MSVC5_hack=(double)name[0]*(double)name[1];
 #endif
 
-	if (app_locks == NULL)
-		if ((app_locks=sk_new_null()) == NULL)
-			CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_LOCKID,ERR_R_MALLOC_FAILURE);
-			return(0);
+	if ((app_locks == NULL) && ((app_locks=sk_new_null()) == NULL))
+		{
+		CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_LOCKID,ERR_R_MALLOC_FAILURE);
+		return(0);
+		}
 	if ((str=BUF_strdup(name)) == NULL)
 		return(0);
 	i=sk_push(app_locks,str);
diff --git a/crypto/crypto.h b/crypto/crypto.h
index 0a38b5b..306bc02 100644
--- a/crypto/crypto.h
+++ b/crypto/crypto.h
@@ -67,12 +67,13 @@
 
 /* This is more to be used to check the correct DLL is being used
  * in the MS world. */
-#define SSLEAY_VERSION_NUMBER	0x0902	/* Version 0.5.1c would be 0513 */
+#define SSLEAY_VERSION_NUMBER	0x0911	/* Version 0.5.1c would be 0513 */
 
 #define SSLEAY_VERSION		0
 /* #define SSLEAY_OPTIONS	1 no longer supported */
 #define SSLEAY_CFLAGS		2
 #define SSLEAY_BUILT_ON		3
+#define SSLEAY_PLATFORM		4
 
 /* When changing the CRYPTO_LOCK_* list, be sure to maintin the text lock
  * names in cryptlib.c
@@ -105,6 +106,7 @@
 #define CRYPTO_READ		4
 #define CRYPTO_WRITE		8
 
+#ifndef NO_LOCKING
 #ifndef CRYPTO_w_lock
 #define CRYPTO_w_lock(type)	\
 	CRYPTO_lock(CRYPTO_LOCK|CRYPTO_WRITE,type,__FILE__,__LINE__)
@@ -116,14 +118,22 @@
 	CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_READ,type,__FILE__,__LINE__)
 #define CRYPTO_add(addr,amount,type)	\
 	CRYPTO_add_lock(addr,amount,type,__FILE__,__LINE__)
-
+#endif
+#else
+#define CRYPTO_w_lock(a)
+#define	CRYPTO_w_unlock(a)
+#define CRYPTO_r_lock(a)
+#define CRYPTO_r_unlock(a)
+#define CRYPTO_add(a,b,c)	((*(a))+=(b))
 #endif
 
 /* The following can be used to detect memory leaks in the SSLeay library.
  * It used, it turns on malloc checking */
 
-#define CRYPTO_MEM_CHECK_OFF	0x0
-#define CRYPTO_MEM_CHECK_ON	0x1
+#define CRYPTO_MEM_CHECK_OFF	0x0	/* an enume */
+#define CRYPTO_MEM_CHECK_ON	0x1	/* a bit */
+#define CRYPTO_MEM_CHECK_ENABLE	0x2	/* a bit */
+#define CRYPTO_MEM_CHECK_DISABLE 0x3	/* an enume */
 
 /*
 typedef struct crypto_mem_st
@@ -179,6 +189,10 @@
 	(void (*)())free)
 
 #ifdef CRYPTO_MDEBUG
+#define MemCheck_start() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON)
+#define MemCheck_stop()	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF)
+#define MemCheck_on()	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE)
+#define MemCheck_off()	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE)
 #define Malloc(num)	CRYPTO_dbg_malloc((int)num,__FILE__,__LINE__)
 #define Realloc(addr,num) \
 	CRYPTO_dbg_realloc((char *)addr,(int)num,__FILE__,__LINE__)
@@ -186,18 +200,28 @@
 	CRYPTO_dbg_remalloc((char **)addr,(int)num,__FILE__,__LINE__)
 #define FreeFunc	CRYPTO_dbg_free
 #define Free(addr)	CRYPTO_dbg_free((char *)(addr))
+#define Malloc_locked(num) CRYPTO_malloc_locked((int)num)
+#define Free_locked(addr) CRYPTO_free_locked((char *)(addr))
 #else
+#define MemCheck_start()
+#define MemCheck_stop()
+#define MemCheck_on()
+#define MemCheck_off()
 #define Remalloc	CRYPTO_remalloc
 #if defined(WIN32) || defined(MFUNC)
 #define Malloc		CRYPTO_malloc
 #define Realloc(a,n)	CRYPTO_realloc((char *)(a),(n))
 #define FreeFunc	CRYPTO_free
 #define Free(addr)	CRYPTO_free((char *)(addr))
+#define Malloc_locked	CRYPTO_malloc_locked
+#define Free_locked(addr) CRYPTO_free_locked((char *)(addr))
 #else
 #define Malloc		malloc
 #define Realloc		realloc
 #define FreeFunc	free
 #define Free(addr)	free((char *)(addr))
+#define Malloc_locked	malloc
+#define Free_locked(addr) free((char *)(addr))
 #endif /* WIN32 || MFUNC */
 #endif /* MDEBUG */
 
@@ -238,10 +262,14 @@
 
 void CRYPTO_set_mem_functions(char *(*m)(),char *(*r)(), void (*free_func)());
 void CRYPTO_get_mem_functions(char *(**m)(),char *(**r)(), void (**f)());
+void CRYPTO_set_locked_mem_functions(char *(*m)(), void (*free_func)());
+void CRYPTO_get_locked_mem_functions(char *(**m)(), void (**f)());
 
+char *CRYPTO_malloc_locked(int num);
+void CRYPTO_free_locked(char *);
 char *CRYPTO_malloc(int num);
-char *CRYPTO_realloc(char *addr,int num);
 void CRYPTO_free(char *);
+char *CRYPTO_realloc(char *addr,int num);
 char *CRYPTO_remalloc(char *addr,int num);
 
 char *CRYPTO_dbg_malloc(int num,char *file,int line);
diff --git a/crypto/cversion.c b/crypto/cversion.c
index 4e823be..03d716a 100644
--- a/crypto/cversion.c
+++ b/crypto/cversion.c
@@ -66,7 +66,7 @@
 int t;
 	{
 	if (t == SSLEAY_VERSION)
-		return("SSLeay 0.9.0b 29-Jun-1998");
+		return("SSLeay 0.9.1a 06-Jul-1998");
 	if (t == SSLEAY_BUILT_ON)
 		{
 #ifdef DATE
@@ -89,6 +89,17 @@
 		return("C flags not available");
 #endif
 		}
+	if (t == SSLEAY_PLATFORM)
+		{
+#ifdef PLATFORM
+		static char buf[sizeof(PLATFORM)+10];
+
+		sprintf(buf,"Platform:%s",PLATFORM);
+		return(buf);
+#else
+		return("Platform information not available");
+#endif
+		}
 	return("not available");
 	}
 
diff --git a/crypto/date.h b/crypto/date.h
index 1cbe8f6..ea0b79a 100644
--- a/crypto/date.h
+++ b/crypto/date.h
@@ -1 +1 @@
-#define DATE	"Fri Apr 10 01:11:55 EST 1998"
+#define DATE	"Wed Jul 22 12:21:22 EST 1998"
diff --git a/crypto/des/Makefile.ssl b/crypto/des/Makefile.ssl
index 78b5189..9ca1b87 100644
--- a/crypto/des/Makefile.ssl
+++ b/crypto/des/Makefile.ssl
@@ -83,10 +83,10 @@
 
 # bsdi
 asm/dx86bsdi.o: asm/dx86unix.cpp
-	$(CPP) -DBSDI asm/dx86unix.cpp | as -o asm/dx86bsdi.o
+	$(CPP) -DBSDI asm/dx86unix.cpp | sed 's/ :/:/' | as -o asm/dx86bsdi.o
 
 asm/yx86bsdi.o: asm/yx86unix.cpp
-	$(CPP) -DBSDI asm/yx86unix.cpp | as -o asm/yx86bsdi.o
+	$(CPP) -DBSDI asm/yx86unix.cpp | sed 's/ :/:/' | as -o asm/yx86bsdi.o
 
 asm/dx86unix.cpp:
 	(cd asm; perl des-586.pl cpp >dx86unix.cpp)
diff --git a/crypto/des/VERSION b/crypto/des/VERSION
index f62d8bd..c7d0154 100644
--- a/crypto/des/VERSION
+++ b/crypto/des/VERSION
@@ -1,3 +1,4 @@
+	Fixed the weak key values which were wrong :-(
 	Defining SIGACTION causes sigaction() to be used instead of signal().
 	SIGUSR1/SIGUSR2 are no longer mapped in the read tty stuff because it
 	can cause problems.  This should hopefully not affect normal
diff --git a/crypto/des/asm/f.cpp b/crypto/des/asm/f.cpp
new file mode 100644
index 0000000..4fa46f2
--- /dev/null
+++ b/crypto/des/asm/f.cpp
@@ -0,0 +1,6 @@
+#define abc	def
+#define dbc:	ghi:
+
+
+abc
+dbc:
diff --git a/crypto/des/des.h b/crypto/des/des.h
index a4cf5c8..4d7610c8 100644
--- a/crypto/des/des.h
+++ b/crypto/des/des.h
@@ -90,6 +90,7 @@
 		} ks;
 #undef _
 #define _	ks._
+	int weak_key;
 	} des_key_schedule[16];
 
 #define DES_KEY_SZ 	(sizeof(des_cblock))
@@ -140,6 +141,7 @@
 
 extern int des_check_key;	/* defaults to false */
 extern int des_rw_mode;		/* defaults to DES_PCBC_MODE */
+extern int des_set_weak_key_flag; /* set the weak key flag */
 
 /* The next line is used to disable full ANSI prototypes, if your
  * compiler has problems with the prototypes, make sure this line always
diff --git a/crypto/des/des.org b/crypto/des/des.org
index a4cf5c8..4d7610c8 100644
--- a/crypto/des/des.org
+++ b/crypto/des/des.org
@@ -90,6 +90,7 @@
 		} ks;
 #undef _
 #define _	ks._
+	int weak_key;
 	} des_key_schedule[16];
 
 #define DES_KEY_SZ 	(sizeof(des_cblock))
@@ -140,6 +141,7 @@
 
 extern int des_check_key;	/* defaults to false */
 extern int des_rw_mode;		/* defaults to DES_PCBC_MODE */
+extern int des_set_weak_key_flag; /* set the weak key flag */
 
 /* The next line is used to disable full ANSI prototypes, if your
  * compiler has problems with the prototypes, make sure this line always
diff --git a/crypto/des/des_locl.h b/crypto/des/des_locl.h
index e2e503c..67ef3e7 100644
--- a/crypto/des/des_locl.h
+++ b/crypto/des/des_locl.h
@@ -119,16 +119,16 @@
    there's no way to tell at compile time what it is you're running on */
  
 #if defined( sun )		/* Newer Sparc's */
-  #define DES_PTR
-  #define DES_RISC1
-  #define DES_UNROLL
+#  define DES_PTR
+#  define DES_RISC1
+#  define DES_UNROLL
 #elif defined( __ultrix )	/* Older MIPS */
-  #define DES_PTR
-  #define DES_RISC2
-  #define DES_UNROLL
+#  define DES_PTR
+#  define DES_RISC2
+#  define DES_UNROLL
 #elif defined( __osf1__ )	/* Alpha */
-  #define DES_PTR
-  #define DES_RISC2
+#  define DES_PTR
+#  define DES_RISC2
 #elif defined ( _AIX )		/* RS6000 */
   /* Unknown */
 #elif defined( __hpux )		/* HP-PA */
@@ -136,15 +136,15 @@
 #elif defined( __aux )		/* 68K */
   /* Unknown */
 #elif defined( __dgux )		/* 88K (but P6 in latest boxes) */
-  #define DES_UNROLL
+#  define DES_UNROLL
 #elif defined( __sgi )		/* Newer MIPS */
-  #define DES_PTR
-  #define DES_RISC2
-  #define DES_UNROLL
+#  define DES_PTR
+#  define DES_RISC2
+#  define DES_UNROLL
 #elif defined( i386 )		/* x86 boxes, should be gcc */
-  #define DES_PTR
-  #define DES_RISC1
-  #define DES_UNROLL
+#  define DES_PTR
+#  define DES_RISC1
+#  define DES_UNROLL
 #endif /* Systems-specific speed defines */
 #endif
 
diff --git a/crypto/des/des_locl.org b/crypto/des/des_locl.org
index e2e503c..67ef3e7 100644
--- a/crypto/des/des_locl.org
+++ b/crypto/des/des_locl.org
@@ -119,16 +119,16 @@
    there's no way to tell at compile time what it is you're running on */
  
 #if defined( sun )		/* Newer Sparc's */
-  #define DES_PTR
-  #define DES_RISC1
-  #define DES_UNROLL
+#  define DES_PTR
+#  define DES_RISC1
+#  define DES_UNROLL
 #elif defined( __ultrix )	/* Older MIPS */
-  #define DES_PTR
-  #define DES_RISC2
-  #define DES_UNROLL
+#  define DES_PTR
+#  define DES_RISC2
+#  define DES_UNROLL
 #elif defined( __osf1__ )	/* Alpha */
-  #define DES_PTR
-  #define DES_RISC2
+#  define DES_PTR
+#  define DES_RISC2
 #elif defined ( _AIX )		/* RS6000 */
   /* Unknown */
 #elif defined( __hpux )		/* HP-PA */
@@ -136,15 +136,15 @@
 #elif defined( __aux )		/* 68K */
   /* Unknown */
 #elif defined( __dgux )		/* 88K (but P6 in latest boxes) */
-  #define DES_UNROLL
+#  define DES_UNROLL
 #elif defined( __sgi )		/* Newer MIPS */
-  #define DES_PTR
-  #define DES_RISC2
-  #define DES_UNROLL
+#  define DES_PTR
+#  define DES_RISC2
+#  define DES_UNROLL
 #elif defined( i386 )		/* x86 boxes, should be gcc */
-  #define DES_PTR
-  #define DES_RISC1
-  #define DES_UNROLL
+#  define DES_PTR
+#  define DES_RISC1
+#  define DES_UNROLL
 #endif /* Systems-specific speed defines */
 #endif
 
diff --git a/crypto/des/des_opts.c b/crypto/des/des_opts.c
index fdf0fbf..29d9461 100644
--- a/crypto/des/des_opts.c
+++ b/crypto/des/des_opts.c
@@ -92,7 +92,8 @@
 #include <sys/timeb.h>
 #endif
 
-#ifdef sun
+#if defined(sun) || defined(__ultrix)
+#define _POSIX_SOURCE
 #include <limits.h>
 #include <sys/param.h>
 #endif
diff --git a/crypto/des/destest.c b/crypto/des/destest.c
index 620c13b..5700608 100644
--- a/crypto/des/destest.c
+++ b/crypto/des/destest.c
@@ -72,6 +72,10 @@
 #include <string.h>
 #include "des.h"
 
+#if defined(PERL5) || defined(__FreeBSD__)
+#define crypt(c,s) (des_crypt((c),(s)))
+#endif
+
 /* tisk tisk - the test keys don't all have odd parity :-( */
 /* test data */
 #define NUM_TESTS 34
@@ -660,17 +664,20 @@
 	printf("Doing quad_cksum\n");
 	cs=quad_cksum((C_Block *)cbc_data,(C_Block *)qret,
 		(long)strlen(cbc_data),2,(C_Block *)cbc_iv);
+
+	{ /* Big-endian fix */
+	static DES_LONG l=1;
+	static unsigned char *c=(unsigned char *)&l;
+	DES_LONG ll;
+
 	j=sizeof(lqret[0])-4;
 	for (i=0; i<4; i++)
 		{
 		lqret[i]=0;
 		memcpy(&(lqret[i]),&(qret[i][0]),4);
-		if (j > 0) lqret[i]=lqret[i]>>(j*8); /* For Cray */
+		if (!c[0] && (j > 0))
+			lqret[i]=lqret[i]>>(j*8); /* For Cray */
 		}
-	{ /* Big-endian fix */
-	static DES_LONG l=1;
-	static unsigned char *c=(unsigned char *)&l;
-	DES_LONG ll;
 
 	if (!c[0])
 		{
diff --git a/crypto/des/ecb_enc.c b/crypto/des/ecb_enc.c
index acf23fd..2f99ae5 100644
--- a/crypto/des/ecb_enc.c
+++ b/crypto/des/ecb_enc.c
@@ -60,7 +60,7 @@
 #include "spr.h"
 
 char *libdes_version="libdes v 3.24 - 20-Apr-1996 - eay";
-char *DES_version="DES part of SSLeay 0.9.0b 29-Jun-1998";
+char *DES_version="DES part of SSLeay 0.9.1a 06-Jul-1998";
 
 char *des_options()
 	{
diff --git a/crypto/des/fcrypt.c b/crypto/des/fcrypt.c
index 129beb2..645e66a 100644
--- a/crypto/des/fcrypt.c
+++ b/crypto/des/fcrypt.c
@@ -55,21 +55,21 @@
 void fcrypt_body(DES_LONG *out,des_key_schedule ks,
 	DES_LONG Eswap0, DES_LONG Eswap1);
 
-#if defined(PERL5) || defined(FreeBSD)
+#if defined(PERL5) || defined(__FreeBSD__)
 char *des_crypt(const char *buf,const char *salt);
 #else
 char *crypt(const char *buf,const char *salt);
 #endif
 #else
 void fcrypt_body();
-#ifdef PERL5
+#if defined(PERL5) || defined(__FreeBSD__)
 char *des_crypt();
 #else
 char *crypt();
 #endif
 #endif
 
-#if defined(PERL5) || defined(FreeBSD)
+#if defined(PERL5) || defined(__FreeBSD__)
 char *des_crypt(buf,salt)
 #else
 char *crypt(buf,salt)
diff --git a/crypto/des/set_key.c b/crypto/des/set_key.c
index c3bcd7e..fe966fd 100644
--- a/crypto/des/set_key.c
+++ b/crypto/des/set_key.c
@@ -111,8 +111,8 @@
 	/* weak keys */
 	{0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01},
 	{0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE},
-	{0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F},
-	{0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0},
+	{0x1F,0x1F,0x1F,0x1F,0x0E,0x0E,0x0E,0x0E},
+	{0xE0,0xE0,0xE0,0xE0,0xF1,0xF1,0xF1,0xF1},
 	/* semi-weak keys */
 	{0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE},
 	{0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01},
diff --git a/crypto/des/speed.c b/crypto/des/speed.c
index 5bbe8b0..bac078e 100644
--- a/crypto/des/speed.c
+++ b/crypto/des/speed.c
@@ -92,7 +92,8 @@
 #include <sys/timeb.h>
 #endif
 
-#ifdef sun
+#if defined(sun) || defined(__ultrix)
+#define _POSIX_SOURCE
 #include <limits.h>
 #include <sys/param.h>
 #endif
diff --git a/crypto/dh/dh.h b/crypto/dh/dh.h
index 4cc1df2..8d60ae5 100644
--- a/crypto/dh/dh.h
+++ b/crypto/dh/dh.h
@@ -67,6 +67,8 @@
 #define BIGNUM 		char
 #endif
 
+#define DH_FLAG_CACHE_MONT_P	0x01
+
 typedef struct dh_st
 	{
 	/* This first argument is used to pick up errors when
@@ -78,6 +80,9 @@
 	int length; /* optional */
 	BIGNUM *pub_key;	/* y */
 	BIGNUM *priv_key;	/* x */
+
+	int flags;
+	char *method_mont_p;
 	} DH;
 
 #define DH_GENERATOR_2		2
diff --git a/crypto/dh/dh_err.c b/crypto/dh/dh_err.c
index 9d5c06a..83ad45f 100644
--- a/crypto/dh/dh_err.c
+++ b/crypto/dh/dh_err.c
@@ -84,8 +84,8 @@
 	{
 	static int init=1;
 
-	if (init);
-		{;
+	if (init)
+		{
 		init=0;
 #ifndef NO_ERR
 		ERR_load_strings(ERR_LIB_DH,DH_str_functs);
diff --git a/crypto/dh/dh_gen.c b/crypto/dh/dh_gen.c
index 04c7046..466f2bf 100644
--- a/crypto/dh/dh_gen.c
+++ b/crypto/dh/dh_gen.c
@@ -97,8 +97,8 @@
 	ret=DH_new();
 	ctx=BN_CTX_new();
 	if (ctx == NULL) goto err;
-	t1=ctx->bn[0];
-	t2=ctx->bn[1];
+	t1= &(ctx->bn[0]);
+	t2= &(ctx->bn[1]);
 	ctx->tos=2;
 	
 	if (generator == DH_GENERATOR_2)
@@ -126,7 +126,7 @@
 	else
 		g=generator;
 	
-	p=BN_generate_prime(prime_len,1,t1,t2,callback,cb_arg);
+	p=BN_generate_prime(NULL,prime_len,1,t1,t2,callback,cb_arg);
 	if (p == NULL) goto err;
 	if (callback != NULL) callback(3,0,cb_arg);
 	ret->p=p;
diff --git a/crypto/dh/dh_key.c b/crypto/dh/dh_key.c
index 7576772..fa2c960 100644
--- a/crypto/dh/dh_key.c
+++ b/crypto/dh/dh_key.c
@@ -67,11 +67,11 @@
 	{
 	int ok=0;
 	unsigned int i;
-	BN_CTX *ctx=NULL;
+	BN_CTX ctx;
+	BN_MONT_CTX *mont;
 	BIGNUM *pub_key=NULL,*priv_key=NULL;
 
-	ctx=BN_CTX_new();
-	if (ctx == NULL) goto err;
+	BN_CTX_init(&ctx);
 
 	if (dh->priv_key == NULL)
 		{
@@ -96,7 +96,15 @@
 	else
 		pub_key=dh->pub_key;
 
-	if (!BN_mod_exp(pub_key,dh->g,priv_key,dh->p,ctx)) goto err;
+	if ((dh->method_mont_p == NULL) && (dh->flags & DH_FLAG_CACHE_MONT_P))
+		{
+		if ((dh->method_mont_p=(char *)BN_MONT_CTX_new()) != NULL)
+			if (!BN_MONT_CTX_set((BN_MONT_CTX *)dh->method_mont_p,
+				dh->p,&ctx)) goto err;
+		}
+	mont=(BN_MONT_CTX *)dh->method_mont_p;
+
+	if (!BN_mod_exp_mont(pub_key,dh->g,priv_key,dh->p,&ctx,mont)) goto err;
 		
 	dh->pub_key=pub_key;
 	dh->priv_key=priv_key;
@@ -107,7 +115,7 @@
 
 	if ((pub_key != NULL)  && (dh->pub_key == NULL))  BN_free(pub_key);
 	if ((priv_key != NULL) && (dh->priv_key == NULL)) BN_free(priv_key);
-	if (ctx != NULL) BN_CTX_free(ctx);
+	BN_CTX_free(&ctx);
 	return(ok);
 	}
 
@@ -116,20 +124,28 @@
 BIGNUM *pub_key;
 DH *dh;
 	{
-	BN_CTX *ctx;
+	BN_CTX ctx;
+	BN_MONT_CTX *mont;
 	BIGNUM *tmp;
 	int ret= -1;
 
-	ctx=BN_CTX_new();
-	if (ctx == NULL) goto err;
-	tmp=ctx->bn[ctx->tos++];
+	BN_CTX_init(&ctx);
+	tmp= &(ctx.bn[ctx.tos++]);
 	
 	if (dh->priv_key == NULL)
 		{
 		DHerr(DH_F_DH_COMPUTE_KEY,DH_R_NO_PRIVATE_VALUE);
 		goto err;
 		}
-	if (!BN_mod_exp(tmp,pub_key,dh->priv_key,dh->p,ctx))
+	if ((dh->method_mont_p == NULL) && (dh->flags & DH_FLAG_CACHE_MONT_P))
+		{
+		if ((dh->method_mont_p=(char *)BN_MONT_CTX_new()) != NULL)
+			if (!BN_MONT_CTX_set((BN_MONT_CTX *)dh->method_mont_p,
+				dh->p,&ctx)) goto err;
+		}
+
+	mont=(BN_MONT_CTX *)dh->method_mont_p;
+	if (!BN_mod_exp_mont(tmp,pub_key,dh->priv_key,dh->p,&ctx,mont))
 		{
 		DHerr(DH_F_DH_COMPUTE_KEY,ERR_R_BN_LIB);
 		goto err;
@@ -137,6 +153,6 @@
 
 	ret=BN_bn2bin(tmp,key);
 err:
-	if (ctx != NULL) BN_CTX_free(ctx);
+	BN_CTX_free(&ctx);
 	return(ret);
 	}
diff --git a/crypto/dh/dh_lib.c b/crypto/dh/dh_lib.c
index a300b38..1b4bb4e 100644
--- a/crypto/dh/dh_lib.c
+++ b/crypto/dh/dh_lib.c
@@ -61,7 +61,7 @@
 #include "bn.h"
 #include "dh.h"
 
-char *DH_version="Diffie-Hellman part of SSLeay 0.9.0b 29-Jun-1998";
+char *DH_version="Diffie-Hellman part of SSLeay 0.9.1a 06-Jul-1998";
 
 DH *DH_new()
 	{
@@ -80,6 +80,8 @@
 	ret->length=0;
 	ret->pub_key=NULL;
 	ret->priv_key=NULL;
+	ret->flags=DH_FLAG_CACHE_MONT_P;
+	ret->method_mont_p=NULL;
 	return(ret);
 	}
 
@@ -90,6 +92,8 @@
 	if (r->g != NULL) BN_clear_free(r->g);
 	if (r->pub_key != NULL) BN_clear_free(r->pub_key);
 	if (r->priv_key != NULL) BN_clear_free(r->priv_key);
+	if (r->method_mont_p != NULL)
+		BN_MONT_CTX_free((BN_MONT_CTX *)r->method_mont_p);
 	Free(r);
 	}
 
diff --git a/crypto/dh/dhtest.c b/crypto/dh/dhtest.c
index 488f10f..e8e1695 100644
--- a/crypto/dh/dhtest.c
+++ b/crypto/dh/dhtest.c
@@ -182,6 +182,7 @@
 	if (p == 2) c='*';
 	if (p == 3) c='\n';
 	BIO_write((BIO *)arg,&c,1);
+	BIO_flush((BIO *)arg);
 #ifdef LINT
 	p=n;
 #endif
diff --git a/crypto/dsa/dsa.h b/crypto/dsa/dsa.h
index 1ca87c1..a231c19 100644
--- a/crypto/dsa/dsa.h
+++ b/crypto/dsa/dsa.h
@@ -71,6 +71,8 @@
 
 #include "bn.h"
 
+#define DSA_FLAG_CACHE_MONT_P	0x01
+
 typedef struct dsa_st
 	{
 	/* This first variable is used to pick up errors where
@@ -88,6 +90,10 @@
 	BIGNUM *kinv;	/* Signing pre-calc */
 	BIGNUM *r;	/* Signing pre-calc */
 
+	int flags;
+	/* Normally used to cache montgomery values */
+	char *method_mont_p;
+
 	int references;
 	} DSA;
 
diff --git a/crypto/dsa/dsa_err.c b/crypto/dsa/dsa_err.c
index 318e9f3..4cb58a8 100644
--- a/crypto/dsa/dsa_err.c
+++ b/crypto/dsa/dsa_err.c
@@ -87,8 +87,8 @@
 	{
 	static int init=1;
 
-	if (init);
-		{;
+	if (init)
+		{
 		init=0;
 #ifndef NO_ERR
 		ERR_load_strings(ERR_LIB_DSA,DSA_str_functs);
diff --git a/crypto/dsa/dsa_gen.c b/crypto/dsa/dsa_gen.c
index d7d30bf..8202b80 100644
--- a/crypto/dsa/dsa_gen.c
+++ b/crypto/dsa/dsa_gen.c
@@ -88,6 +88,7 @@
 	unsigned char buf[SHA_DIGEST_LENGTH],buf2[SHA_DIGEST_LENGTH];
 	BIGNUM *r0,*W,*X,*c,*test;
 	BIGNUM *g=NULL,*q=NULL,*p=NULL;
+	BN_MONT_CTX *mont=NULL;
 	int k,n=0,i,b,m=0;
 	int counter=0;
 	BN_CTX *ctx=NULL,*ctx2=NULL;
@@ -100,20 +101,20 @@
 	if ((seed_in != NULL) && (seed_len == 20))
 		memcpy(seed,seed_in,seed_len);
 
-	ctx=BN_CTX_new();
-	if (ctx == NULL) goto err;
-	ctx2=BN_CTX_new();
-	if (ctx2 == NULL) goto err;
-	ret=DSA_new();
-	if (ret == NULL) goto err;
-	r0=ctx2->bn[0];
-	g=ctx2->bn[1];
-	W=ctx2->bn[2];
-	q=ctx2->bn[3];
-	X=ctx2->bn[4];
-	c=ctx2->bn[5];
-	p=ctx2->bn[6];
-	test=ctx2->bn[7];
+	if ((ctx=BN_CTX_new()) == NULL) goto err;
+	if ((ctx2=BN_CTX_new()) == NULL) goto err;
+	if ((ret=DSA_new()) == NULL) goto err;
+
+	if ((mont=BN_MONT_CTX_new()) == NULL) goto err;
+
+	r0= &(ctx2->bn[0]);
+	g= &(ctx2->bn[1]);
+	W= &(ctx2->bn[2]);
+	q= &(ctx2->bn[3]);
+	X= &(ctx2->bn[4]);
+	c= &(ctx2->bn[5]);
+	p= &(ctx2->bn[6]);
+	test= &(ctx2->bn[7]);
 
 	BN_lshift(test,BN_value_one(),bits-1);
 
@@ -220,10 +221,12 @@
         BN_div(r0,NULL,test,q,ctx);
 
 	BN_set_word(test,h);
+	BN_MONT_CTX_set(mont,p,ctx);
+
 	for (;;)
 		{
 		/* g=test^r0%p */
-		BN_mod_exp(g,test,r0,p,ctx);
+		BN_mod_exp_mont(g,test,r0,p,ctx,mont);
 		if (!BN_is_one(g)) break;
 		BN_add(test,test,BN_value_one());
 		h++;
@@ -246,8 +249,9 @@
 		if (counter_ret != NULL) *counter_ret=counter;
 		if (h_ret != NULL) *h_ret=h;
 		}
-	BN_CTX_free(ctx);
-	BN_CTX_free(ctx2);
+	if (ctx != NULL) BN_CTX_free(ctx);
+	if (ctx != NULL) BN_CTX_free(ctx2);
+	if (mont != NULL) BN_MONT_CTX_free(mont);
 	return(ok?ret:NULL);
 	}
 
@@ -258,20 +262,22 @@
 	{
 	int ok= -1,j,i,n;
 	BN_CTX *ctx=NULL,*ctx2=NULL;
-	BIGNUM *w_1,*b,*m,*z;
+	BIGNUM *w_1,*b,*m,*z,*tmp,*mont_1;
 	int a;
+	BN_MONT_CTX *mont=NULL;
 
 	if (!BN_is_bit_set(w,0)) return(0);
 
-	ctx=BN_CTX_new();
-	if (ctx == NULL) goto err;
-	ctx2=BN_CTX_new();
-	if (ctx2 == NULL) goto err;
+	if ((ctx=BN_CTX_new()) == NULL) goto err;
+	if ((ctx2=BN_CTX_new()) == NULL) goto err;
+	if ((mont=BN_MONT_CTX_new()) == NULL) goto err;
 
-	m=  ctx2->bn[2];
-	b=  ctx2->bn[3];
-	z=  ctx2->bn[4];
-	w_1=ctx2->bn[5];
+	m=   &(ctx2->bn[2]);
+	b=   &(ctx2->bn[3]);
+	z=   &(ctx2->bn[4]);
+	w_1= &(ctx2->bn[5]);
+	tmp= &(ctx2->bn[6]);
+	mont_1= &(ctx2->bn[7]);
 
 	/* step 1 */
 	n=50;
@@ -282,24 +288,30 @@
 		;
 	if (!BN_rshift(m,w_1,a)) goto err;
 
+	BN_MONT_CTX_set(mont,w,ctx);
+	BN_to_montgomery(mont_1,BN_value_one(),mont,ctx);
+	BN_to_montgomery(w_1,w_1,mont,ctx);
 	for (i=1; i < n; i++)
 		{
 		/* step 3 */
 		BN_rand(b,BN_num_bits(w)-2/*-1*/,0,0);
-		BN_set_word(b,0x10001L);
+		/* BN_set_word(b,0x10001L); */
 
 		/* step 4 */
 		j=0;
-		if (!BN_mod_exp(z,b,m,w,ctx)) goto err;
+		if (!BN_mod_exp_mont(z,b,m,w,ctx,mont)) goto err;
+
+		if (!BN_to_montgomery(z,z,mont,ctx)) goto err;
 
 		/* step 5 */
 		for (;;)
 			{
-			if (((j == 0) && BN_is_one(z)) || (BN_cmp(z,w_1) == 0))
+			if (((j == 0) && (BN_cmp(z,mont_1) == 0)) ||
+				(BN_cmp(z,w_1) == 0))
 				break;
 
 			/* step 6 */
-			if ((j > 0) && BN_is_one(z))
+			if ((j > 0) && (BN_cmp(z,mont_1) == 0))
 				{
 				ok=0;
 				goto err;
@@ -312,7 +324,7 @@
 				goto err;
 				}
 
-			if (!BN_mod_mul(z,z,z,w,ctx)) goto err;
+			if (!BN_mod_mul_montgomery(z,z,z,mont,ctx)) goto err;
 			if (callback != NULL) callback(1,j,cb_arg);
 			}
 		}
diff --git a/crypto/dsa/dsa_lib.c b/crypto/dsa/dsa_lib.c
index b647257..bfa9ca2 100644
--- a/crypto/dsa/dsa_lib.c
+++ b/crypto/dsa/dsa_lib.c
@@ -64,7 +64,7 @@
 #include "dsa.h"
 #include "asn1.h"
 
-char *DSA_version="\0DSA part of SSLeay 0.9.0b 29-Jun-1998";
+char *DSA_version="\0DSA part of SSLeay 0.9.1a 06-Jul-1998";
 
 DSA *DSA_new()
 	{
@@ -82,12 +82,14 @@
 	ret->p=NULL;
 	ret->q=NULL;
 	ret->g=NULL;
+	ret->flags=DSA_FLAG_CACHE_MONT_P;
 
 	ret->pub_key=NULL;
 	ret->priv_key=NULL;
 
 	ret->kinv=NULL;
 	ret->r=NULL;
+	ret->method_mont_p=NULL;
 
 	ret->references=1;
 	return(ret);
@@ -120,6 +122,8 @@
 	if (r->priv_key != NULL) BN_clear_free(r->priv_key);
 	if (r->kinv != NULL) BN_clear_free(r->kinv);
 	if (r->r != NULL) BN_clear_free(r->r);
+	if (r->method_mont_p != NULL)
+		BN_MONT_CTX_free((BN_MONT_CTX *)r->method_mont_p);
 	Free(r);
 	}
 
diff --git a/crypto/dsa/dsa_sign.c b/crypto/dsa/dsa_sign.c
index 6ca1c31..c4df4e5 100644
--- a/crypto/dsa/dsa_sign.c
+++ b/crypto/dsa/dsa_sign.c
@@ -77,8 +77,8 @@
 DSA *dsa;
 	{
 	BIGNUM *kinv=NULL,*r=NULL;
-	BIGNUM *m=NULL;
-	BIGNUM *xr=NULL,*s=NULL;
+	BIGNUM m;
+	BIGNUM xr,s;
 	BN_CTX *ctx=NULL;
 	unsigned char *p;
 	int i,len=0,ret=0,reason=ERR_R_BN_LIB;
@@ -86,6 +86,10 @@
 	MS_STATIC unsigned char rbuf[50]; /* assuming r is 20 bytes +extra */
 	MS_STATIC unsigned char sbuf[50]; /* assuming s is 20 bytes +extra */
 
+	BN_init(&m);
+	BN_init(&xr);
+	BN_init(&s);
+
 	i=BN_num_bytes(dsa->q); /* should be 20 */
 	if ((dlen > i) || (dlen > 50))
 		{
@@ -108,17 +112,14 @@
 		dsa->r=NULL;
 		}
 
-	m=BN_new();
-	xr=BN_new();
-	s=BN_new();
-	if (m == NULL || xr == NULL || s == NULL) goto err;
-
-	if (BN_bin2bn(dgst,dlen,m) == NULL) goto err;
+	if (BN_bin2bn(dgst,dlen,&m) == NULL) goto err;
 
 	/* Compute  s = inv(k) (m + xr) mod q */
-	if (!BN_mul(xr, dsa->priv_key, r)) goto err;	/* s = xr */
-	if (!BN_add(s, xr, m)) goto err;		/* s = m + xr */
-	if (!BN_mod_mul(s,s,kinv,dsa->q,ctx)) goto err;
+	if (!BN_mod_mul(&xr,dsa->priv_key,r,dsa->q,ctx)) goto err;/* s = xr */
+	if (!BN_add(&s, &xr, &m)) goto err;		/* s = m + xr */
+	if (BN_cmp(&s,dsa->q) > 0)
+		BN_sub(&s,&s,dsa->q);
+	if (!BN_mod_mul(&s,&s,kinv,dsa->q,ctx)) goto err;
 
 	/*
 	 * Now create a ASN.1 sequence of the integers R and S.
@@ -128,7 +129,7 @@
 	rbs.type = V_ASN1_INTEGER;
 	sbs.type = V_ASN1_INTEGER;
 	rbs.length=BN_bn2bin(r,rbs.data);
-	sbs.length=BN_bn2bin(s,sbs.data);
+	sbs.length=BN_bn2bin(&s,sbs.data);
 
 	len =i2d_ASN1_INTEGER(&rbs,NULL);
 	len+=i2d_ASN1_INTEGER(&sbs,NULL);
@@ -147,9 +148,9 @@
 	if (r != NULL) BN_clear_free(r);
 #endif
 	if (ctx != NULL) BN_CTX_free(ctx);
-	if (m != NULL) BN_clear_free(m);
-	if (xr != NULL) BN_clear_free(xr);
-	if (s != NULL) BN_clear_free(s);
+	BN_clear_free(&m);
+	BN_clear_free(&xr);
+	BN_clear_free(&s);
 	return(ret);
 	}
 
@@ -160,7 +161,7 @@
 BIGNUM **rp;
 	{
 	BN_CTX *ctx;
-	BIGNUM *k=NULL,*kinv=NULL,*r=NULL;
+	BIGNUM k,*kinv=NULL,*r=NULL;
 	int ret=0;
 
 	if (ctx_in == NULL)
@@ -170,29 +171,33 @@
 	else
 		ctx=ctx_in;
 
-	r=BN_new();
-	k=BN_new();
-	if ((r == NULL) || (k == NULL))
-		goto err;
+	BN_init(&k);
+	if ((r=BN_new()) == NULL) goto err;
 	kinv=NULL;
 
-	if (r == NULL) goto err;
-
 	/* Get random k */
 	for (;;)
 		{
-		if (!BN_rand(k, BN_num_bits(dsa->q), 1, 0)) goto err;
-		if (BN_cmp(k,dsa->q) >= 0)
-			BN_sub(k,k,dsa->q);
-		if (!BN_is_zero(k)) break;
+		if (!BN_rand(&k, BN_num_bits(dsa->q), 1, 0)) goto err;
+		if (BN_cmp(&k,dsa->q) >= 0)
+			BN_sub(&k,&k,dsa->q);
+		if (!BN_is_zero(&k)) break;
+		}
+
+	if ((dsa->method_mont_p == NULL) && (dsa->flags & DSA_FLAG_CACHE_MONT_P))
+		{
+		if ((dsa->method_mont_p=(char *)BN_MONT_CTX_new()) != NULL)
+			if (!BN_MONT_CTX_set((BN_MONT_CTX *)dsa->method_mont_p,
+				dsa->p,ctx)) goto err;
 		}
 
 	/* Compute r = (g^k mod p) mod q */
-	if (!BN_mod_exp(r,dsa->g,k,dsa->p,ctx)) goto err;
+	if (!BN_mod_exp_mont(r,dsa->g,&k,dsa->p,ctx,
+		(BN_MONT_CTX *)dsa->method_mont_p)) goto err;
 	if (!BN_mod(r,r,dsa->q,ctx)) goto err;
 
 	/* Compute  part of 's = inv(k) (m + xr) mod q' */
-	if ((kinv=BN_mod_inverse(k,dsa->q,ctx)) == NULL) goto err;
+	if ((kinv=BN_mod_inverse(NULL,&k,dsa->q,ctx)) == NULL) goto err;
 
 	if (*kinvp != NULL) BN_clear_free(*kinvp);
 	*kinvp=kinv;
@@ -208,8 +213,8 @@
 		if (r != NULL) BN_clear_free(r);
 		}
 	if (ctx_in == NULL) BN_CTX_free(ctx);
-	if (k != NULL) BN_clear_free(k);
 	if (kinv != NULL) BN_clear_free(kinv);
+	BN_clear_free(&k);
 	return(ret);
 	}
 
diff --git a/crypto/dsa/dsa_vrf.c b/crypto/dsa/dsa_vrf.c
index 0f86098..71cefbe 100644
--- a/crypto/dsa/dsa_vrf.c
+++ b/crypto/dsa/dsa_vrf.c
@@ -85,52 +85,76 @@
 	ASN1_CTX c;
 	unsigned char **pp= &sigbuf;
 	BN_CTX *ctx;
-	BIGNUM *r=NULL;
-	BIGNUM *t1=NULL,*t2=NULL;
-	BIGNUM *u1=NULL,*u2=NULL;
+	BIGNUM r,u1,u2,t1;
 	ASN1_INTEGER *bs=NULL;
+	BN_MONT_CTX *mont=NULL;
 	int ret = -1;
 
-	ctx=BN_CTX_new();
-	if (ctx == NULL) goto err;
+	if ((ctx=BN_CTX_new()) == NULL) goto err;
+	if ((mont=BN_MONT_CTX_new()) == NULL) goto err;
 
-	t1=BN_new();
-	t2=BN_new();
-	if (t1 == NULL || t2 == NULL) goto err;
+	BN_init(&u1);
+	BN_init(&u2);
+	BN_init(&r);
+	BN_init(&t1);
 
 	M_ASN1_D2I_Init();
 	M_ASN1_D2I_start_sequence();
         M_ASN1_D2I_get(bs,d2i_ASN1_INTEGER);
-        if ((r=BN_bin2bn(bs->data,bs->length,NULL)) == NULL) goto err_bn;
+        if ((BN_bin2bn(bs->data,bs->length,&r)) == NULL) goto err_bn;
         M_ASN1_D2I_get(bs,d2i_ASN1_INTEGER);
-        if ((u1=BN_bin2bn(bs->data,bs->length,NULL)) == NULL) goto err_bn;
+        if ((BN_bin2bn(bs->data,bs->length,&u1)) == NULL) goto err_bn;
 	if (!asn1_Finish(&c)) goto err;
 
 	/* Calculate W = inv(S) mod Q
 	 * save W in u2 */
-	if ((u2=BN_mod_inverse(u1,dsa->q,ctx)) == NULL) goto err_bn;
+	if ((BN_mod_inverse(&u2,&u1,dsa->q,ctx)) == NULL) goto err_bn;
 
 	/* save M in u1 */
-	if (BN_bin2bn(dgst,dgst_len,u1) == NULL) goto err_bn;
+	if (BN_bin2bn(dgst,dgst_len,&u1) == NULL) goto err_bn;
 
 	/* u1 = M * w mod q */
-	if (!BN_mod_mul(u1,u1,u2,dsa->q,ctx)) goto err_bn;
+	if (!BN_mod_mul(&u1,&u1,&u2,dsa->q,ctx)) goto err_bn;
 
 	/* u2 = r * w mod q */
-	if (!BN_mod_mul(u2,r,u2,dsa->q,ctx)) goto err_bn;
+	if (!BN_mod_mul(&u2,&r,&u2,dsa->q,ctx)) goto err_bn;
 
+	if ((dsa->method_mont_p == NULL) && (dsa->flags & DSA_FLAG_CACHE_MONT_P))
+		{
+		if ((dsa->method_mont_p=(char *)BN_MONT_CTX_new()) != NULL)
+			if (!BN_MONT_CTX_set((BN_MONT_CTX *)dsa->method_mont_p,
+				dsa->p,ctx)) goto err;
+		}
+	mont=(BN_MONT_CTX *)dsa->method_mont_p;
+
+#if 0
+	{
+	BIGNUM t2;
+
+	BN_init(&t2);
 	/* v = ( g^u1 * y^u2 mod p ) mod q */
 	/* let t1 = g ^ u1 mod p */
-	if (!BN_mod_exp(t1,dsa->g,u1,dsa->p,ctx)) goto err_bn;
+	if (!BN_mod_exp_mont(&t1,dsa->g,&u1,dsa->p,ctx,mont)) goto err_bn;
 	/* let t2 = y ^ u2 mod p */
-	if (!BN_mod_exp(t2,dsa->pub_key,u2,dsa->p,ctx)) goto err_bn;
+	if (!BN_mod_exp_mont(&t2,dsa->pub_key,&u2,dsa->p,ctx,mont)) goto err_bn;
 	/* let u1 = t1 * t2 mod p */
-	if (!BN_mod_mul(u1,t1,t2,dsa->p,ctx)) goto err_bn;
+	if (!BN_mod_mul(&u1,&t1,&t2,dsa->p,ctx)) goto err_bn;
+	BN_free(&t2);
+	}
 	/* let u1 = u1 mod q */
-	if (!BN_mod(u1,u1,dsa->q,ctx)) goto err_bn;
+	if (!BN_mod(&u1,&u1,dsa->q,ctx)) goto err_bn;
+#else
+	{
+	if (!BN_mod_exp2_mont(&t1,dsa->g,&u1,dsa->pub_key,&u2,dsa->p,ctx,mont))
+		goto err_bn;
+	/* BN_copy(&u1,&t1); */
+	/* let u1 = u1 mod q */
+	if (!BN_mod(&u1,&t1,dsa->q,ctx)) goto err_bn;
+	}
+#endif
 	/* V is now in u1.  If the signature is correct, it will be
 	 * equal to R. */
-	ret=(BN_ucmp(u1, r) == 0);
+	ret=(BN_ucmp(&u1, &r) == 0);
 	if (0)
 		{
 err: /* ASN1 error */
@@ -142,11 +166,10 @@
 		DSAerr(DSA_F_DSA_VERIFY,ERR_R_BN_LIB);
 		}
 	if (ctx != NULL) BN_CTX_free(ctx);
-	if (r != NULL) BN_free(r);
-	if (t1 != NULL) BN_free(t1);
-	if (t2 != NULL) BN_free(t2);
-	if (u1 != NULL) BN_free(u1);
-	if (u2 != NULL) BN_free(u2);
+	BN_free(&r);
+	BN_free(&u1);
+	BN_free(&u2);
+	BN_free(&t1);
 	if (bs != NULL) ASN1_BIT_STRING_free(bs);
 	return(ret);
 	}
diff --git a/crypto/dsa/f b/crypto/dsa/f
new file mode 100644
index 0000000..36865a7
--- /dev/null
+++ b/crypto/dsa/f
@@ -0,0 +1,6 @@
+	if ((dsa->method_mod_p == NULL) && (dsa->flags & DSA_FLAG_CACHE_MONT_P))
+		{
+		if ((dsa->method_mod_p=(char *)BN_MONT_CTX_new()) != NULL)
+			if (!BN_MONT_CTX_set((BN_MONT_CTX *)dsa->method_mod_p,
+				dsa->p,ctx)) goto err;
+		}
diff --git a/crypto/err/err.c b/crypto/err/err.c
index a651924..5cf6218 100644
--- a/crypto/err/err.c
+++ b/crypto/err/err.c
@@ -81,6 +81,7 @@
 static int err_cmp();
 static unsigned long pid_hash();
 static int pid_cmp();
+static unsigned long get_error_values();
 static void ERR_STATE_free();
 ERR_STATE *s;
 #endif
@@ -148,6 +149,14 @@
 {ERR_R_PKCS7_LIB			,"PKCS7 lib"},
 {ERR_R_MALLOC_FAILURE			,"Malloc failure"},
 {ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED	,"called a fuction you should not call"},
+{ERR_R_PASSED_NULL_PARAMETER		,"passed a null parameter"},
+{ERR_R_NESTED_ASN1_ERROR		,"nested asn1 error"},
+{ERR_R_BAD_ASN1_OBJECT_HEADER		,"bad asn1 object header"},
+{ERR_R_BAD_GET_ASN1_OBJECT_CALL		,"bad get asn1 object call"},
+{ERR_R_EXPECTING_AN_ASN1_SEQUENCE	,"expecting an asn1 sequence"},
+{ERR_R_ASN1_LENGTH_MISMATCH		,"asn1 length mismatch"},
+{ERR_R_MISSING_ASN1_EOS			,"missing asn1 eos"},
+
 {0,NULL},
 	};
 #endif
@@ -539,7 +548,9 @@
 		CRYPTO_w_lock(CRYPTO_LOCK_ERR);
 		if (thread_hash == NULL)
 			{
+			MemCheck_off();
 			thread_hash=lh_new(pid_hash,pid_cmp);
+			MemCheck_on();
 			CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
 			if (thread_hash == NULL) return(&fallback);
 			}
@@ -618,20 +629,24 @@
 	for (i=0; i<num; i++)
 		{
 		VAR_ARG(args,char *,a);
-		n+=strlen(a);
-		if (n > s)
+		/* ignore NULLs, thanks to Bob Beck <beck@obtuse.com> */
+		if (a != NULL)
 			{
-			s=n+20;
-			p=Realloc(str,s+1);
-			if (p == NULL)
+			n+=strlen(a);
+			if (n > s)
 				{
-				Free(str);
-				return;
+				s=n+20;
+				p=Realloc(str,s+1);
+				if (p == NULL)
+					{
+					Free(str);
+					return;
+					}
+				else
+					str=p;
 				}
-			else
-				str=p;
+			strcat(str,a);
 			}
-		strcat(str,a);
 		}
 	ERR_set_error_data(str,ERR_TXT_MALLOCED|ERR_TXT_STRING);
 
diff --git a/crypto/err/err.h b/crypto/err/err.h
index 75f931b..c81dedd 100644
--- a/crypto/err/err.h
+++ b/crypto/err/err.h
@@ -192,6 +192,12 @@
 #define	ERR_R_MALLOC_FAILURE			(1|ERR_R_FATAL)
 #define	ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED	(2|ERR_R_FATAL)
 #define	ERR_R_PASSED_NULL_PARAMETER		(3|ERR_R_FATAL)
+#define ERR_R_NESTED_ASN1_ERROR			(4)
+#define ERR_R_BAD_ASN1_OBJECT_HEADER		(5)
+#define ERR_R_BAD_GET_ASN1_OBJECT_CALL		(6)
+#define ERR_R_EXPECTING_AN_ASN1_SEQUENCE	(7)
+#define ERR_R_ASN1_LENGTH_MISMATCH		(8)
+#define ERR_R_MISSING_ASN1_EOS			(9)
 
 typedef struct ERR_string_data_st
 	{
diff --git a/crypto/err/err_genc.pl b/crypto/err/err_genc.pl
index d3251da..87c6da9 100644
--- a/crypto/err/err_genc.pl
+++ b/crypto/err/err_genc.pl
@@ -86,8 +86,8 @@
 	if (${type}_lib_error_code == 0)
 		${type}_lib_error_code=ERR_get_next_error_library();
 
-	if (init);
-		{;
+	if (init)
+		{
 		init=0;
 $str
 		}
@@ -113,8 +113,8 @@
 	{
 	static int init=1;
 
-	if (init);
-		{;
+	if (init)
+		{
 		init=0;
 $str
 		}
diff --git a/crypto/err/ssleay.ec b/crypto/err/ssleay.ec
index 10b5dbb..12cb343 100644
--- a/crypto/err/ssleay.ec
+++ b/crypto/err/ssleay.ec
@@ -20,6 +20,7 @@
 L SSL2		../ssl/ssl2.err
 L SSL3		../ssl/ssl3.err
 L SSL23		../ssl/ssl23.err
+L COMP		comp/comp.err
 
 F RSAREF_F_RSA_BN2BIN
 F RSAREF_F_RSA_PRIVATE_DECRYPT
@@ -30,6 +31,8 @@
 
 R SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE		1010
 R SSL_R_SSLV3_ALERT_BAD_RECORD_MAC		1020
+R SSL_R_TLSV1_ALERT_DECRYPTION_FAILED		1021
+R SSL_R_TLSV1_ALERT_RECORD_OVERFLOW		1022
 R SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE	1030
 R SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE		1040
 R SSL_R_SSLV3_ALERT_NO_CERTIFICATE		1041
@@ -39,6 +42,16 @@
 R SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED		1045
 R SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN		1046
 R SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER		1047
+R SSL_R_TLSV1_ALERT_UNKNOWN_CA			1048
+R SSL_R_TLSV1_ALERT_ACCESS_DENIED		1049
+R SSL_R_TLSV1_ALERT_DECODE_ERROR		1050
+R SSL_R_TLSV1_ALERT_DECRYPT_ERROR		1051
+R SSL_R_TLSV1_ALERT_EXPORT_RESTRICION		1060
+R SSL_R_TLSV1_ALERT_PROTOCOL_VERSION		1070
+R SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY	1071
+R SSL_R_TLSV1_ALERT_INTERNAL_ERROR		1080
+R SSL_R_TLSV1_ALERT_USER_CANCLED		1090
+R SSL_R_TLSV1_ALERT_NO_RENEGOTIATION		1100
 
 R RSAREF_R_CONTENT_ENCODING			0x0400
 R RSAREF_R_DATA					0x0401
diff --git a/crypto/evp/abc.c b/crypto/evp/abc.c
new file mode 100644
index 0000000..d6cc1e1
--- /dev/null
+++ b/crypto/evp/abc.c
@@ -0,0 +1,124 @@
+/* lib/evp/evp_err.c */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+#include <stdio.h>
+#include "err.h"
+#include "evp.h"
+
+/* BEGIN ERROR CODES */
+#ifndef NO_ERR
+static ERR_STRING_DATA EVP_str_functs[]=
+	{
+{ERR_PACK(0,EVP_F_D2I_PKEY,0),	"D2I_PKEY"},
+{ERR_PACK(0,EVP_F_EVP_DECRYPTFINAL,0),	"EVP_DecryptFinal"},
+{ERR_PACK(0,EVP_F_EVP_OPENINIT,0),	"EVP_OpenInit"},
+{ERR_PACK(0,EVP_F_EVP_PKEY_COPY_PARAMETERS,0),	"EVP_PKEY_copy_parameters"},
+{ERR_PACK(0,EVP_F_EVP_PKEY_DECRYPT,0),	"EVP_PKEY_decrypt"},
+{ERR_PACK(0,EVP_F_EVP_PKEY_ENCRYPT,0),	"EVP_PKEY_encrypt"},
+{ERR_PACK(0,EVP_F_EVP_PKEY_NEW,0),	"EVP_PKEY_new"},
+{ERR_PACK(0,EVP_F_EVP_SIGNFINAL,0),	"EVP_SignFinal"},
+{ERR_PACK(0,EVP_F_EVP_VERIFYFINAL,0),	"EVP_VerifyFinal"},
+{0,NULL},
+	};
+
+static ERR_STRING_DATA EVP_str_reasons[]=
+	{
+{EVP_R_BAD_DECRYPT                       ,"bad decrypt"},
+{EVP_R_DIFFERENT_KEY_TYPES               ,"different key types"},
+{EVP_R_IV_TOO_LARGE                      ,"iv too large"},
+{EVP_R_MISSING_PARMATERS                 ,"missing parmaters"},
+{EVP_R_NO_SIGN_FUNCTION_CONFIGURED       ,"no sign function configured"},
+{EVP_R_NO_VERIFY_FUNCTION_CONFIGURED     ,"no verify function configured"},
+{EVP_R_PUBLIC_KEY_NOT_RSA                ,"public key not rsa"},
+{EVP_R_UNSUPPORTED_CIPHER                ,"unsupported cipher"},
+{EVP_R_WRONG_FINAL_BLOCK_LENGTH          ,"wrong final block length"},
+{EVP_R_WRONG_PUBLIC_KEY_TYPE             ,"wrong public key type"},
+{0,NULL},
+	};
+
+#endif
+
+static int EVP_lib_error_code=0;
+
+void ERR_load_EVP_strings()
+	{
+	static int init=1;
+
+	if (EVP_lib_error_code == 0)
+		EVP_lib_error_code=ERR_get_next_error_library();
+
+	if (init);
+		{;
+		init=0;
+#ifndef NO_ERR
+		ERR_load_strings(EVP_lib_error_code,EVP_str_functs);
+		ERR_load_strings(EVP_lib_error_code,EVP_str_reasons);
+#endif
+
+		}
+	}
+
+void ERR_EVP_error(function,reason,file,line)
+int function;
+int reason;
+char *file;
+int line;
+	{
+	if (EVP_lib_error_code == 0)
+		EVP_lib_error_code=ERR_get_next_error_library();
+	ERR_PUT_error(EVP_lib_error_code,function,reason,file,line);
+	}
diff --git a/crypto/evp/abcs.c b/crypto/evp/abcs.c
new file mode 100644
index 0000000..2b0a0ab
--- /dev/null
+++ b/crypto/evp/abcs.c
@@ -0,0 +1,108 @@
+/* lib/evp/evp_err.c */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+#include <stdio.h>
+#include "err.h"
+#include "evp.h"
+
+/* BEGIN ERROR CODES */
+#ifndef NO_ERR
+static ERR_STRING_DATA EVP_str_functs[]=
+	{
+{ERR_PACK(0,EVP_F_D2I_PKEY,0),	"D2I_PKEY"},
+{ERR_PACK(0,EVP_F_EVP_DECRYPTFINAL,0),	"EVP_DecryptFinal"},
+{ERR_PACK(0,EVP_F_EVP_OPENINIT,0),	"EVP_OpenInit"},
+{ERR_PACK(0,EVP_F_EVP_PKEY_COPY_PARAMETERS,0),	"EVP_PKEY_copy_parameters"},
+{ERR_PACK(0,EVP_F_EVP_PKEY_DECRYPT,0),	"EVP_PKEY_decrypt"},
+{ERR_PACK(0,EVP_F_EVP_PKEY_ENCRYPT,0),	"EVP_PKEY_encrypt"},
+{ERR_PACK(0,EVP_F_EVP_PKEY_NEW,0),	"EVP_PKEY_new"},
+{ERR_PACK(0,EVP_F_EVP_SIGNFINAL,0),	"EVP_SignFinal"},
+{ERR_PACK(0,EVP_F_EVP_VERIFYFINAL,0),	"EVP_VerifyFinal"},
+{0,NULL},
+	};
+
+static ERR_STRING_DATA EVP_str_reasons[]=
+	{
+{EVP_R_BAD_DECRYPT                       ,"bad decrypt"},
+{EVP_R_DIFFERENT_KEY_TYPES               ,"different key types"},
+{EVP_R_IV_TOO_LARGE                      ,"iv too large"},
+{EVP_R_MISSING_PARMATERS                 ,"missing parmaters"},
+{EVP_R_NO_SIGN_FUNCTION_CONFIGURED       ,"no sign function configured"},
+{EVP_R_NO_VERIFY_FUNCTION_CONFIGURED     ,"no verify function configured"},
+{EVP_R_PUBLIC_KEY_NOT_RSA                ,"public key not rsa"},
+{EVP_R_UNSUPPORTED_CIPHER                ,"unsupported cipher"},
+{EVP_R_WRONG_FINAL_BLOCK_LENGTH          ,"wrong final block length"},
+{EVP_R_WRONG_PUBLIC_KEY_TYPE             ,"wrong public key type"},
+{0,NULL},
+	};
+
+#endif
+
+void ERR_load_EVP_strings()
+	{
+	static int init=1;
+
+	if (init);
+		{;
+		init=0;
+#ifndef NO_ERR
+		ERR_load_strings(ERR_LIB_EVP,EVP_str_functs);
+		ERR_load_strings(ERR_LIB_EVP,EVP_str_reasons);
+#endif
+
+		}
+	}
diff --git a/crypto/evp/bio_enc.c b/crypto/evp/bio_enc.c
index 6c30ddf..ad09b94 100644
--- a/crypto/evp/bio_enc.c
+++ b/crypto/evp/bio_enc.c
@@ -298,6 +298,7 @@
 	BIO_ENC_CTX *ctx,*dctx;
 	long ret=1;
 	int i;
+	EVP_CIPHER_CTX **c_ctx;
 
 	ctx=(BIO_ENC_CTX *)b->ptr;
 
@@ -364,7 +365,11 @@
 		ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
 		BIO_copy_next_retry(b);
 		break;
-
+	case BIO_C_GET_CIPHER_CTX:
+		c_ctx=(EVP_CIPHER_CTX **)ptr;
+		(*c_ctx)= &(ctx->cipher);
+		b->init=1;
+		break;
 	case BIO_CTRL_DUP:
 		dbio=(BIO *)ptr;
 		dctx=(BIO_ENC_CTX *)dbio->ptr;
diff --git a/crypto/evp/c_all.c b/crypto/evp/c_all.c
index e77d1c8..f2e0500 100644
--- a/crypto/evp/c_all.c
+++ b/crypto/evp/c_all.c
@@ -79,16 +79,16 @@
 	EVP_add_cipher(EVP_des_ede3_ofb());
 
 	EVP_add_cipher(EVP_desx_cbc());
-	EVP_add_alias(SN_desx_cbc,"DESX");
-	EVP_add_alias(SN_desx_cbc,"desx");
+	EVP_add_cipher_alias(SN_desx_cbc,"DESX");
+	EVP_add_cipher_alias(SN_desx_cbc,"desx");
 
 	EVP_add_cipher(EVP_des_cbc());
-	EVP_add_alias(SN_des_cbc,"DES");
-	EVP_add_alias(SN_des_cbc,"des");
+	EVP_add_cipher_alias(SN_des_cbc,"DES");
+	EVP_add_cipher_alias(SN_des_cbc,"des");
 	EVP_add_cipher(EVP_des_ede_cbc());
 	EVP_add_cipher(EVP_des_ede3_cbc());
-	EVP_add_alias(SN_des_ede3_cbc,"DES3");
-	EVP_add_alias(SN_des_ede3_cbc,"des3");
+	EVP_add_cipher_alias(SN_des_ede3_cbc,"DES3");
+	EVP_add_cipher_alias(SN_des_ede3_cbc,"des3");
 
 	EVP_add_cipher(EVP_des_ecb());
 	EVP_add_cipher(EVP_des_ede());
@@ -105,8 +105,8 @@
 	EVP_add_cipher(EVP_idea_cfb());
 	EVP_add_cipher(EVP_idea_ofb());
 	EVP_add_cipher(EVP_idea_cbc());
-	EVP_add_alias(SN_idea_cbc,"IDEA");
-	EVP_add_alias(SN_idea_cbc,"idea");
+	EVP_add_cipher_alias(SN_idea_cbc,"IDEA");
+	EVP_add_cipher_alias(SN_idea_cbc,"idea");
 #endif
 
 #ifndef NO_RC2
@@ -115,8 +115,9 @@
 	EVP_add_cipher(EVP_rc2_ofb());
 	EVP_add_cipher(EVP_rc2_cbc());
 	EVP_add_cipher(EVP_rc2_40_cbc());
-	EVP_add_alias(SN_rc2_cbc,"RC2");
-	EVP_add_alias(SN_rc2_cbc,"rc2");
+	EVP_add_cipher(EVP_rc2_64_cbc());
+	EVP_add_cipher_alias(SN_rc2_cbc,"RC2");
+	EVP_add_cipher_alias(SN_rc2_cbc,"rc2");
 #endif
 
 #ifndef NO_BLOWFISH
@@ -124,9 +125,9 @@
 	EVP_add_cipher(EVP_bf_cfb());
 	EVP_add_cipher(EVP_bf_ofb());
 	EVP_add_cipher(EVP_bf_cbc());
-	EVP_add_alias(SN_bf_cbc,"BF");
-	EVP_add_alias(SN_bf_cbc,"bf");
-	EVP_add_alias(SN_bf_cbc,"blowfish");
+	EVP_add_cipher_alias(SN_bf_cbc,"BF");
+	EVP_add_cipher_alias(SN_bf_cbc,"bf");
+	EVP_add_cipher_alias(SN_bf_cbc,"blowfish");
 #endif
 
 #ifndef NO_CAST
@@ -134,10 +135,10 @@
 	EVP_add_cipher(EVP_cast5_cfb());
 	EVP_add_cipher(EVP_cast5_ofb());
 	EVP_add_cipher(EVP_cast5_cbc());
-	EVP_add_alias(SN_cast5_cbc,"CAST");
-	EVP_add_alias(SN_cast5_cbc,"cast");
-	EVP_add_alias(SN_cast5_cbc,"CAST-cbc");
-	EVP_add_alias(SN_cast5_cbc,"cast-cbc");
+	EVP_add_cipher_alias(SN_cast5_cbc,"CAST");
+	EVP_add_cipher_alias(SN_cast5_cbc,"cast");
+	EVP_add_cipher_alias(SN_cast5_cbc,"CAST-cbc");
+	EVP_add_cipher_alias(SN_cast5_cbc,"cast-cbc");
 #endif
 
 #ifndef NO_RC5
@@ -145,10 +146,8 @@
 	EVP_add_cipher(EVP_rc5_32_12_16_cfb());
 	EVP_add_cipher(EVP_rc5_32_12_16_ofb());
 	EVP_add_cipher(EVP_rc5_32_12_16_cbc());
-	EVP_add_alias(SN_rc5_cbc,"rc5");
-	EVP_add_alias(SN_rc5_cbc,"RC5");
-	EVP_add_alias(SN_rc5_cbc,"rc5-cbc");
-	EVP_add_alias(SN_rc5_cbc,"RC5-cbc");
+	EVP_add_cipher_alias(SN_rc5_cbc,"rc5");
+	EVP_add_cipher_alias(SN_rc5_cbc,"RC5");
 #endif
 	}
 
@@ -160,8 +159,8 @@
 #endif
 #ifndef NO_MD5
 	EVP_add_digest(EVP_md5());
-	EVP_add_alias(SN_md5,"ssl2-md5");
-	EVP_add_alias(SN_md5,"ssl3-md5");
+	EVP_add_digest_alias(SN_md5,"ssl2-md5");
+	EVP_add_digest_alias(SN_md5,"ssl3-md5");
 #endif
 #ifndef NO_SHA
 	EVP_add_digest(EVP_sha());
@@ -171,20 +170,21 @@
 #endif
 #ifndef NO_SHA1
 	EVP_add_digest(EVP_sha1());
-	EVP_add_alias(SN_sha1,"ssl3-sha1");
+	EVP_add_digest_alias(SN_sha1,"ssl3-sha1");
+	EVP_add_digest_alias(SN_sha1WithRSAEncryption,SN_sha1WithRSA);
 #ifndef NO_DSA
 	EVP_add_digest(EVP_dss1());
-	EVP_add_alias(SN_dsaWithSHA1,SN_dsaWithSHA1_2);
-	EVP_add_alias(SN_dsaWithSHA1,"DSS1");
-	EVP_add_alias(SN_dsaWithSHA1,"dss1");
+	EVP_add_digest_alias(SN_dsaWithSHA1,SN_dsaWithSHA1_2);
+	EVP_add_digest_alias(SN_dsaWithSHA1,"DSS1");
+	EVP_add_digest_alias(SN_dsaWithSHA1,"dss1");
 #endif
 #endif
 #if !defined(NO_MDC2) && !defined(NO_DES)
 	EVP_add_digest(EVP_mdc2());
 #endif
-#ifndef NO_RIPEMD160
+#ifndef NO_RMD160
 	EVP_add_digest(EVP_ripemd160());
-	EVP_add_alias(SN_ripemd160,"ripemd");
-	EVP_add_alias(SN_ripemd160,"rmd160");
+	EVP_add_digest_alias(SN_ripemd160,"ripemd");
+	EVP_add_digest_alias(SN_ripemd160,"rmd160");
 #endif
 	}
diff --git a/crypto/evp/e_cbc_r2.c b/crypto/evp/e_cbc_r2.c
index 4f8002f..9175e53 100644
--- a/crypto/evp/e_cbc_r2.c
+++ b/crypto/evp/e_cbc_r2.c
@@ -68,11 +68,25 @@
 	unsigned char *iv,int enc);
 static void rc2_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
 	unsigned char *in, unsigned int inl);
+static int rc2_meth_to_magic(EVP_CIPHER *e);
+static EVP_CIPHER *rc2_magic_to_meth(int i);
+static int rc2_set_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
+static int rc2_get_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
+
 #else
+
 static void rc2_cbc_init_key();
 static void rc2_cbc_cipher();
+static int rc2_meth_to_magic();
+static EVP_CIPHER *rc2_magic_to_meth();
+static int rc2_set_asn1_type_and_iv();
+static int rc2_get_asn1_type_and_iv();
 #endif
 
+#define RC2_40_MAGIC	0xa0
+#define RC2_64_MAGIC	0x78
+#define RC2_128_MAGIC	0x3a
+
 static EVP_CIPHER r2_cbc_cipher=
 	{
 	NID_rc2_cbc,
@@ -82,8 +96,21 @@
 	NULL,
 	sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+
 		sizeof((((EVP_CIPHER_CTX *)NULL)->c.rc2_ks)),
-	EVP_CIPHER_get_asn1_iv,
-	EVP_CIPHER_set_asn1_iv,
+	rc2_set_asn1_type_and_iv,
+	rc2_get_asn1_type_and_iv,
+	};
+
+static EVP_CIPHER r2_64_cbc_cipher=
+	{
+	NID_rc2_40_cbc,
+	8,8 /* 64 bit */,8,
+	rc2_cbc_init_key,
+	rc2_cbc_cipher,
+	NULL,
+	sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+
+		sizeof((((EVP_CIPHER_CTX *)NULL)->c.rc2_ks)),
+	rc2_set_asn1_type_and_iv,
+	rc2_get_asn1_type_and_iv,
 	};
 
 static EVP_CIPHER r2_40_cbc_cipher=
@@ -95,6 +122,8 @@
 	NULL,
 	sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+
 		sizeof((((EVP_CIPHER_CTX *)NULL)->c.rc2_ks)),
+	rc2_set_asn1_type_and_iv,
+	rc2_get_asn1_type_and_iv,
 	};
 
 EVP_CIPHER *EVP_rc2_cbc()
@@ -102,6 +131,11 @@
 	return(&r2_cbc_cipher);
 	}
 
+EVP_CIPHER *EVP_rc2_64_cbc()
+	{
+	return(&r2_64_cbc_cipher);
+	}
+
 EVP_CIPHER *EVP_rc2_40_cbc()
 	{
 	return(&r2_40_cbc_cipher);
@@ -133,4 +167,73 @@
 		ctx->encrypt);
 	}
 
+static int rc2_meth_to_magic(e)
+EVP_CIPHER *e;
+	{
+	int i;
+
+	i=EVP_CIPHER_key_length(e);
+	if 	(i == 128) return(RC2_128_MAGIC);
+	else if (i == 64)  return(RC2_64_MAGIC);
+	else if (i == 40)  return(RC2_40_MAGIC);
+	else return(0);
+	}
+
+static EVP_CIPHER *rc2_magic_to_meth(i)
+int i;
+	{
+	if      (i == RC2_128_MAGIC) return(EVP_rc2_cbc());
+	else if (i == RC2_64_MAGIC)  return(EVP_rc2_64_cbc());
+	else if (i == RC2_40_MAGIC)  return(EVP_rc2_40_cbc());
+	else
+		{
+		EVPerr(EVP_F_RC2_MAGIC_TO_METH,EVP_R_UNSUPPORTED_KEY_SIZE);
+		return(NULL);
+		}
+	}
+
+int rc2_get_asn1_type_and_iv(c,type)
+EVP_CIPHER_CTX *c;
+ASN1_TYPE *type;
+	{
+	long num=0;
+	int i=0,l;
+	EVP_CIPHER *e;
+
+	if (type != NULL)
+		{
+		l=EVP_CIPHER_CTX_iv_length(c);
+		i=ASN1_TYPE_get_int_octetstring(type,&num,c->oiv,l);
+		if (i != l)
+			return(-1);
+		else if (i > 0)
+			memcpy(c->iv,c->oiv,l);
+		e=rc2_magic_to_meth((int)num);
+		if (e == NULL)
+			return(-1);
+		if (e != EVP_CIPHER_CTX_cipher(c))
+			{
+			EVP_CIPHER_CTX_cipher(c)=e;
+			rc2_cbc_init_key(c,NULL,NULL,1);
+			}
+		}
+	return(i);
+	}
+
+static int rc2_set_asn1_type_and_iv(c,type)
+EVP_CIPHER_CTX *c;
+ASN1_TYPE *type;
+	{
+	long num;
+	int i=0,j;
+
+	if (type != NULL)
+		{
+		num=rc2_meth_to_magic(EVP_CIPHER_CTX_cipher(c));
+		j=EVP_CIPHER_CTX_iv_length(c);
+		i=ASN1_TYPE_set_int_octetstring(type,num,c->oiv,j);
+		}
+	return(i);
+	}
+
 #endif
diff --git a/crypto/evp/e_cfb_r2.c b/crypto/evp/e_cfb_r2.c
index af5a39d..849be7e 100644
--- a/crypto/evp/e_cfb_r2.c
+++ b/crypto/evp/e_cfb_r2.c
@@ -103,8 +103,8 @@
 		memcpy(&(ctx->oiv[0]),iv,8);
 	memcpy(&(ctx->iv[0]),&(ctx->oiv[0]),8);
 	if (key != NULL)
-		RC2_set_key(&(ctx->c.rc2_ks),EVP_RC2_KEY_SIZE,key,
-			EVP_RC2_KEY_SIZE*8);
+		RC2_set_key(&(ctx->c.rc2_ks),EVP_CIPHER_CTX_key_length(ctx),
+			key,EVP_CIPHER_CTX_key_length(ctx)*8);
 	}
 
 static void rc2_cfb_cipher(ctx,out,in,inl)
diff --git a/crypto/evp/e_ecb_r2.c b/crypto/evp/e_ecb_r2.c
index e35b06d..4e74af9 100644
--- a/crypto/evp/e_ecb_r2.c
+++ b/crypto/evp/e_ecb_r2.c
@@ -98,8 +98,8 @@
 int enc;
 	{
 	if (key != NULL)
-		RC2_set_key(&(ctx->c.rc2_ks),EVP_RC2_KEY_SIZE,key,
-			EVP_RC2_KEY_SIZE*8);
+		RC2_set_key(&(ctx->c.rc2_ks),EVP_CIPHER_CTX_key_length(ctx),
+			key,EVP_CIPHER_CTX_key_length(ctx)*8);
 	}
 
 static void rc2_ecb_cipher(ctx,out,in,inl)
diff --git a/crypto/evp/e_ofb_r2.c b/crypto/evp/e_ofb_r2.c
index 0f6d729..4ed67ea 100644
--- a/crypto/evp/e_ofb_r2.c
+++ b/crypto/evp/e_ofb_r2.c
@@ -103,8 +103,8 @@
 		memcpy(&(ctx->oiv[0]),iv,8);
 	memcpy(&(ctx->iv[0]),&(ctx->oiv[0]),8);
 	if (key != NULL)
-		RC2_set_key(&(ctx->c.rc2_ks),EVP_RC2_KEY_SIZE,key,
-			EVP_RC2_KEY_SIZE*8);
+		RC2_set_key(&(ctx->c.rc2_ks),EVP_CIPHER_CTX_key_length(ctx),
+			key,EVP_CIPHER_CTX_key_length(ctx)*8);
 	}
 
 static void rc2_ofb_cipher(ctx,out,in,inl)
diff --git a/crypto/evp/evp.err b/crypto/evp/evp.err
index cfc1743..b6ed829 100644
--- a/crypto/evp/evp.err
+++ b/crypto/evp/evp.err
@@ -10,6 +10,7 @@
 #define EVP_F_EVP_PKEY_NEW				 106
 #define EVP_F_EVP_SIGNFINAL				 107
 #define EVP_F_EVP_VERIFYFINAL				 108
+#define EVP_F_RC2_MAGIC_TO_METH				 109
 
 /* Reason codes. */
 #define EVP_R_BAD_DECRYPT				 100
@@ -20,5 +21,6 @@
 #define EVP_R_NO_VERIFY_FUNCTION_CONFIGURED		 105
 #define EVP_R_PUBLIC_KEY_NOT_RSA			 106
 #define EVP_R_UNSUPPORTED_CIPHER			 107
-#define EVP_R_WRONG_FINAL_BLOCK_LENGTH			 108
-#define EVP_R_WRONG_PUBLIC_KEY_TYPE			 109
+#define EVP_R_UNSUPPORTED_KEY_SIZE			 108
+#define EVP_R_WRONG_FINAL_BLOCK_LENGTH			 109
+#define EVP_R_WRONG_PUBLIC_KEY_TYPE			 110
diff --git a/crypto/evp/evp.h b/crypto/evp/evp.h
index b39fad9..e6296ce 100644
--- a/crypto/evp/evp.h
+++ b/crypto/evp/evp.h
@@ -72,7 +72,7 @@
 #if !defined(NO_SHA) || !defined(NO_SHA1)
 #include "sha.h"
 #endif
-#ifndef NO_RIPEMD
+#ifndef NO_RMD160
 #include "ripemd.h"
 #endif
 #ifndef NO_DES
@@ -183,7 +183,7 @@
  * This is required because for various smart-card perform the digest and
  * signing/verification on-board.  To handle this case, the specific
  * EVP_MD and EVP_PKEY_METHODs need to be closely associated.
- * When a PKEY is created, it will have a EVP_PKEY_METHOD ossociated with it.
+ * When a PKEY is created, it will have a EVP_PKEY_METHOD associated with it.
  * This can either be software or a token to provide the required low level
  * routines.
  */
@@ -296,7 +296,7 @@
 #ifndef NO_MD5
 		MD5_CTX md5;
 #endif
-#ifndef NO_MD5
+#ifndef NO_RMD160
 		RIPEMD160_CTX ripemd160;
 #endif
 #if !defined(NO_SHA) || !defined(NO_SHA1)
@@ -445,9 +445,19 @@
 #define BIO_get_md(b,mdp)		BIO_ctrl(b,BIO_C_GET_MD,0,(char *)mdp)
 #define BIO_get_md_ctx(b,mdcp)     BIO_ctrl(b,BIO_C_GET_MD_CTX,0,(char *)mdcp)
 #define BIO_get_cipher_status(b)	BIO_ctrl(b,BIO_C_GET_CIPHER_STATUS,0,NULL)
+#define BIO_get_cipher_ctx(b,c_pp)	BIO_ctrl(b,BIO_C_GET_CIPHER_CTX,0,(char *)c_pp)
 
 #define	EVP_Cipher(c,o,i,l)	(c)->cipher->do_cipher((c),(o),(i),(l))
 
+#define EVP_add_cipher_alias(n,alias) \
+	OBJ_NAME_add((alias),OBJ_NAME_TYPE_CIPHER_METH|OBJ_NAME_ALIAS,(n))
+#define EVP_add_digest_alias(n,alias) \
+	OBJ_NAME_add((alias),OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS,(n))
+#define EVP_delete_cipher_alias(alias) \
+	OBJ_NAME_remove(alias,OBJ_NAME_TYPE_CIPHER_METH|OBJ_NAME_ALIAS);
+#define EVP_delete_digest_alias(alias) \
+	OBJ_NAME_remove(alias,OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS);
+
 #ifndef NOPROTO
 
 void	EVP_DigestInit(EVP_MD_CTX *ctx, EVP_MD *type);
@@ -556,6 +566,7 @@
 EVP_CIPHER *EVP_rc2_ecb(void);
 EVP_CIPHER *EVP_rc2_cbc(void);
 EVP_CIPHER *EVP_rc2_40_cbc(void);
+EVP_CIPHER *EVP_rc2_64_cbc(void);
 EVP_CIPHER *EVP_rc2_cfb(void);
 EVP_CIPHER *EVP_rc2_ofb(void);
 EVP_CIPHER *EVP_bf_ecb(void);
@@ -577,8 +588,6 @@
 
 int EVP_add_cipher(EVP_CIPHER *cipher);
 int EVP_add_digest(EVP_MD *digest);
-int EVP_add_alias(char *name,char *alias);
-int EVP_delete_alias(char *name);
 
 EVP_CIPHER *EVP_get_cipherbyname(char *name);
 EVP_MD *EVP_get_digestbyname(char *name);
@@ -705,6 +714,7 @@
 EVP_CIPHER *EVP_rc2_ecb();
 EVP_CIPHER *EVP_rc2_cbc();
 EVP_CIPHER *EVP_rc2_40_cbc();
+EVP_CIPHER *EVP_rc2_64_cbc();
 EVP_CIPHER *EVP_rc2_cfb();
 EVP_CIPHER *EVP_rc2_ofb();
 EVP_CIPHER *EVP_bf_ecb();
@@ -726,8 +736,6 @@
 
 int EVP_add_cipher();
 int EVP_add_digest();
-int EVP_add_alias();
-int EVP_delete_alias();
 
 EVP_CIPHER *EVP_get_cipherbyname();
 EVP_MD *EVP_get_digestbyname();
@@ -773,6 +781,7 @@
 #define EVP_F_EVP_PKEY_NEW				 106
 #define EVP_F_EVP_SIGNFINAL				 107
 #define EVP_F_EVP_VERIFYFINAL				 108
+#define EVP_F_RC2_MAGIC_TO_METH				 109
 
 /* Reason codes. */
 #define EVP_R_BAD_DECRYPT				 100
@@ -783,8 +792,9 @@
 #define EVP_R_NO_VERIFY_FUNCTION_CONFIGURED		 105
 #define EVP_R_PUBLIC_KEY_NOT_RSA			 106
 #define EVP_R_UNSUPPORTED_CIPHER			 107
-#define EVP_R_WRONG_FINAL_BLOCK_LENGTH			 108
-#define EVP_R_WRONG_PUBLIC_KEY_TYPE			 109
+#define EVP_R_UNSUPPORTED_KEY_SIZE			 108
+#define EVP_R_WRONG_FINAL_BLOCK_LENGTH			 109
+#define EVP_R_WRONG_PUBLIC_KEY_TYPE			 110
  
 #ifdef  __cplusplus
 }
diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c
index 93cc3a9..ea580b1 100644
--- a/crypto/evp/evp_enc.c
+++ b/crypto/evp/evp_enc.c
@@ -60,7 +60,7 @@
 #include "cryptlib.h"
 #include "evp.h"
 
-char *EVP_version="EVP part of SSLeay 0.9.0b 29-Jun-1998";
+char *EVP_version="EVP part of SSLeay 0.9.1a 06-Jul-1998";
 
 void EVP_CIPHER_CTX_init(ctx)
 EVP_CIPHER_CTX *ctx;
diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c
index 2b0a0ab..c7caa3b 100644
--- a/crypto/evp/evp_err.c
+++ b/crypto/evp/evp_err.c
@@ -72,6 +72,7 @@
 {ERR_PACK(0,EVP_F_EVP_PKEY_NEW,0),	"EVP_PKEY_new"},
 {ERR_PACK(0,EVP_F_EVP_SIGNFINAL,0),	"EVP_SignFinal"},
 {ERR_PACK(0,EVP_F_EVP_VERIFYFINAL,0),	"EVP_VerifyFinal"},
+{ERR_PACK(0,EVP_F_RC2_MAGIC_TO_METH,0),	"RC2_MAGIC_TO_METH"},
 {0,NULL},
 	};
 
@@ -85,6 +86,7 @@
 {EVP_R_NO_VERIFY_FUNCTION_CONFIGURED     ,"no verify function configured"},
 {EVP_R_PUBLIC_KEY_NOT_RSA                ,"public key not rsa"},
 {EVP_R_UNSUPPORTED_CIPHER                ,"unsupported cipher"},
+{EVP_R_UNSUPPORTED_KEY_SIZE              ,"unsupported key size"},
 {EVP_R_WRONG_FINAL_BLOCK_LENGTH          ,"wrong final block length"},
 {EVP_R_WRONG_PUBLIC_KEY_TYPE             ,"wrong public key type"},
 {0,NULL},
@@ -96,8 +98,8 @@
 	{
 	static int init=1;
 
-	if (init);
-		{;
+	if (init)
+		{
 		init=0;
 #ifndef NO_ERR
 		ERR_load_strings(ERR_LIB_EVP,EVP_str_functs);
diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c
index 69784eb..729fc8f 100644
--- a/crypto/evp/evp_lib.c
+++ b/crypto/evp/evp_lib.c
@@ -97,7 +97,10 @@
 		{
 		l=EVP_CIPHER_CTX_iv_length(c);
 		i=ASN1_TYPE_get_octetstring(type,c->oiv,l);
-		memcpy(c->iv,c->oiv,l);
+		if (i != l)
+			return(-1);
+		else if (i > 0)
+			memcpy(c->iv,c->oiv,l);
 		}
 	return(i);
 	}
diff --git a/crypto/evp/names.c b/crypto/evp/names.c
index e0774da..4cc7156 100644
--- a/crypto/evp/names.c
+++ b/crypto/evp/names.c
@@ -61,225 +61,60 @@
 #include "evp.h"
 #include "objects.h"
 
-typedef struct aliases_st {
-	char *alias;
-	/* This must be the last field becaue I will allocate things
-	 * so they go off the end of it */
-	char name[4];
-	} ALIASES;
-
-static STACK /* ALIASES */ *aliases=NULL;
-static STACK /* EVP_CIPHERS */ *ciphers=NULL;
-static STACK /* EVP_MD */ *digests=NULL;
-
-static int cipher_nid_cmp(a,b)
-EVP_CIPHER **a,**b;
-	{ return((*a)->nid - (*b)->nid); }
-
-static int digest_type_cmp(a,b)
-EVP_MD **a,**b;
-	{ return((*a)->pkey_type - (*b)->pkey_type); }
-
 int EVP_add_cipher(c)
 EVP_CIPHER *c;
 	{
-	int i;
+	int r;
 
-	if (ciphers == NULL)
-		{
-		ciphers=sk_new(cipher_nid_cmp);
-		if (ciphers == NULL) return(0);
-		}
-	if ((i=sk_find(ciphers,(char *)c)) >= 0)
-		{
-		if (sk_value(ciphers,i) == (char *)c)
-			return(1);
-		sk_delete(ciphers,i);
-		}
-	return(sk_push(ciphers,(char *)c));
+	r=OBJ_NAME_add(OBJ_nid2sn(c->nid),OBJ_NAME_TYPE_CIPHER_METH,(char *)c);
+	if (r == 0) return(0);
+	r=OBJ_NAME_add(OBJ_nid2ln(c->nid),OBJ_NAME_TYPE_CIPHER_METH,(char *)c);
+	return(r);
 	}
 
 int EVP_add_digest(md)
 EVP_MD *md;
 	{
-	int i;
-	char *n;
+	int r;
+	char *name;
 
-	if (digests == NULL)
-		{
-		digests=sk_new(digest_type_cmp);
-		if (digests == NULL) return(0);
-		}
-	if ((i=sk_find(digests,(char *)md)) >= 0)
-		{
-		if (sk_value(digests,i) == (char *)md)
-			return(1);
-		sk_delete(digests,i);
-		}
+	name=OBJ_nid2sn(md->type);
+	r=OBJ_NAME_add(name,OBJ_NAME_TYPE_MD_METH,(char *)md);
+	if (r == 0) return(0);
+	r=OBJ_NAME_add(OBJ_nid2ln(md->type),OBJ_NAME_TYPE_MD_METH,(char *)md);
+	if (r == 0) return(0);
+
 	if (md->type != md->pkey_type)
 		{
-		n=OBJ_nid2sn(md->pkey_type);
-		EVP_add_alias(n,OBJ_nid2sn(md->type));
-		EVP_add_alias(n,OBJ_nid2ln(md->type));
+		r=OBJ_NAME_add(OBJ_nid2sn(md->pkey_type),
+			OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS,name);
+		if (r == 0) return(0);
+		r=OBJ_NAME_add(OBJ_nid2ln(md->pkey_type),
+			OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS,name);
 		}
-	sk_push(digests,(char *)md);
-	return(1);
-	}
-
-static int alias_cmp(a,b)
-ALIASES **a,**b;
-	{
-	return(strcmp((*a)->alias,(*b)->alias));
-	}
-
-int EVP_add_alias(name,aname)
-char *name;
-char *aname;
-	{
-	int l1,l2,i;
-	ALIASES *a;
-	char *p;
-
-	if ((name == NULL) || (aname == NULL)) return(0);
-	l1=strlen(name)+1;
-	l2=strlen(aname)+1;
-	i=sizeof(ALIASES)+l1+l2;
-	if ((a=(ALIASES *)Malloc(i)) == NULL)
-		return(0);
-	strcpy(a->name,name);
-	p= &(a->name[l1]);
-	strcpy(p,aname);
-	a->alias=p;
-
-	if (aliases == NULL)
-		{
-		aliases=sk_new(alias_cmp);
-		if (aliases == NULL) goto err;
-		}
-
-	if ((i=sk_find(aliases,(char *)a)) >= 0)
-		{
-		Free(sk_delete(aliases,i));
-		}
-	if (!sk_push(aliases,(char *)a)) goto err;
-	return(1);
-err:
-	return(0);
-	}
-
-int EVP_delete_alias(name)
-char *name;
-	{
-	ALIASES a;
-	int i;
-
-	if (aliases != NULL)
-		{
-		a.alias=name;
-		if ((i=sk_find(aliases,(char *)&a)) >= 0)
-			{
-			Free(sk_delete(aliases,i));
-			return(1);
-			}
-		}
-	return(0);
+	return(r);
 	}
 
 EVP_CIPHER *EVP_get_cipherbyname(name)
 char *name;
 	{
-	int nid,num=6,i;
-	EVP_CIPHER c,*cp;
-	ALIASES a,*ap;
+	EVP_CIPHER *cp;
 
-	if (ciphers == NULL) return(NULL);
-	for (;;)
-		{
-		if (num-- <= 0) return(NULL);
-		if (aliases != NULL)
-			{
-			a.alias=name;
-			i=sk_find(aliases,(char *)&a);
-			if (i >= 0)
-				{
-				ap=(ALIASES *)sk_value(aliases,i);
-				name=ap->name;
-				continue;
-				}
-			}
-
-		nid=OBJ_txt2nid(name);
-		if (nid == NID_undef) return(NULL);
-		c.nid=nid;
-		i=sk_find(ciphers,(char *)&c);
-		if (i >= 0)
-			{
-			cp=(EVP_CIPHER *)sk_value(ciphers,i);
-			return(cp);
-			}
-		else
-			return(NULL);
-		}
+	cp=(EVP_CIPHER *)OBJ_NAME_get(name,OBJ_NAME_TYPE_CIPHER_METH);
+	return(cp);
 	}
 
 EVP_MD *EVP_get_digestbyname(name)
 char *name;
 	{
-	int nid,num=6,i;
-	EVP_MD c,*cp;
-	ALIASES a,*ap;
+	EVP_MD *cp;
 
-	if (digests == NULL) return(NULL);
-
-	for (;;)
-		{
-		if (num-- <= 0) return(NULL);
-
-		if (aliases != NULL)
-			{
-			a.alias=name;
-			i=sk_find(aliases,(char *)&a);
-			if (i >= 0)
-				{
-				ap=(ALIASES *)sk_value(aliases,i);
-				name=ap->name;
-				continue;
-				}
-			}
-
-		nid=OBJ_txt2nid(name);
-		if (nid == NID_undef) return(NULL);
-		c.pkey_type=nid;
-		i=sk_find(digests,(char *)&c);
-		if (i >= 0)
-			{
-			cp=(EVP_MD *)sk_value(digests,i);
-			return(cp);
-			}
-		else
-			return(NULL);
-		}
+	cp=(EVP_MD *)OBJ_NAME_get(name,OBJ_NAME_TYPE_MD_METH);
+	return(cp);
 	}
 
 void EVP_cleanup()
 	{
-	int i;
-
-	if (aliases != NULL)
-		{
-		for (i=0; i<sk_num(aliases); i++)
-			Free(sk_value(aliases,i));
-		sk_free(aliases);
-		aliases=NULL;
-		}
-	if (ciphers != NULL)
-		{
-		sk_free(ciphers);
-		ciphers=NULL;
-		}
-	if (digests != NULL)
-		{
-		sk_free(digests);
-		digests=NULL;
-		}
+	OBJ_NAME_cleanup(OBJ_NAME_TYPE_CIPHER_METH);
+	OBJ_NAME_cleanup(OBJ_NAME_TYPE_MD_METH);
 	}
diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c
index 395351b..581df86 100644
--- a/crypto/evp/p_lib.c
+++ b/crypto/evp/p_lib.c
@@ -90,6 +90,8 @@
 int EVP_PKEY_size(pkey)
 EVP_PKEY *pkey;
 	{
+	if (pkey == NULL)
+		return(0);
 #ifndef NO_RSA
 	if (pkey->type == EVP_PKEY_RSA)
 		return(RSA_size(pkey->pkey.rsa));
diff --git a/crypto/ex_data.c b/crypto/ex_data.c
index c858b51..42b8b9d 100644
--- a/crypto/ex_data.c
+++ b/crypto/ex_data.c
@@ -72,20 +72,22 @@
 int (*dup_func)();
 void (*free_func)();
 	{
+	int ret= -1;
 	CRYPTO_EX_DATA_FUNCS *a;
 
+	MemCheck_off();
 	if (*skp == NULL)
 		*skp=sk_new_null();
 	if (*skp == NULL)
 		{
 		CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX,ERR_R_MALLOC_FAILURE);
-		return(-1);
+		goto err;
 		}
 	a=(CRYPTO_EX_DATA_FUNCS *)Malloc(sizeof(CRYPTO_EX_DATA_FUNCS));
 	if (a == NULL)
 		{
 		CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX,ERR_R_MALLOC_FAILURE);
-		return(-1);
+		goto err;
 		}
 	a->argl=argl;
 	a->argp=argp;
@@ -98,10 +100,13 @@
 			{
 			CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX,ERR_R_MALLOC_FAILURE);
 			Free(a);
-			return(-1);
+			goto err;
 			}
 		}
 	sk_value(*skp,idx)=(char *)a;
+	ret=idx;
+err:
+	MemCheck_on();
 	return(idx);
 	}
 
diff --git a/crypto/idea/i_ecb.c b/crypto/idea/i_ecb.c
index 6721126..5d5f8e0 100644
--- a/crypto/idea/i_ecb.c
+++ b/crypto/idea/i_ecb.c
@@ -59,7 +59,7 @@
 #include "idea.h"
 #include "idea_lcl.h"
 
-char *IDEA_version="IDEA part of SSLeay 0.9.0b 29-Jun-1998";
+char *IDEA_version="IDEA part of SSLeay 0.9.1a 06-Jul-1998";
 
 char *idea_options()
 	{
diff --git a/crypto/idea/idea_spd.c b/crypto/idea/idea_spd.c
index 4b3eec5..98060d9 100644
--- a/crypto/idea/idea_spd.c
+++ b/crypto/idea/idea_spd.c
@@ -92,7 +92,8 @@
 #include <sys/timeb.h>
 #endif
 
-#ifdef sun
+#if defined(sun) || defined(__ultrix)
+#define _POSIX_SOURCE
 #include <limits.h>
 #include <sys/param.h>
 #endif
diff --git a/crypto/lhash/lhash.c b/crypto/lhash/lhash.c
index 6dfb5c9..97006c4 100644
--- a/crypto/lhash/lhash.c
+++ b/crypto/lhash/lhash.c
@@ -56,11 +56,16 @@
  * [including the GNU Public Licence.]
  */
 
-char *lh_version="lhash part of SSLeay 0.9.0b 29-Jun-1998";
+char *lh_version="lhash part of SSLeay 0.9.1a 06-Jul-1998";
 
 /* Code for dynamic hash table routines
  * Author - Eric Young v 2.0
  *
+ * 2.2 eay - added #include "crypto.h" so the memory leak checking code is
+ *	     present. eay 18-Jun-98
+ *
+ * 2.1 eay - Added an 'error in last operation' flag. eay 6-May-98
+ *
  * 2.0 eay - Fixed a bug that occured when using lh_delete
  *	     from inside lh_doall().  As entries were deleted,
  *	     the 'table' was 'contract()ed', making some entries
@@ -94,6 +99,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
+#include "crypto.h"
 #include "lhash.h"
 
 #undef MIN_NODES 
@@ -126,9 +132,9 @@
 	LHASH *ret;
 	int i;
 
-	if ((ret=(LHASH *)malloc(sizeof(LHASH))) == NULL)
+	if ((ret=(LHASH *)Malloc(sizeof(LHASH))) == NULL)
 		goto err0;
-	if ((ret->b=(LHASH_NODE **)malloc(sizeof(LHASH_NODE *)*MIN_NODES)) == NULL)
+	if ((ret->b=(LHASH_NODE **)Malloc(sizeof(LHASH_NODE *)*MIN_NODES)) == NULL)
 		goto err1;
 	for (i=0; i<MIN_NODES; i++)
 		ret->b[i]=NULL;
@@ -156,9 +162,10 @@
 	ret->num_retrieve_miss=0;
 	ret->num_hash_comps=0;
 
+	ret->error=0;
 	return(ret);
 err1:
-	free((char *)ret);
+	Free((char *)ret);
 err0:
 	return(NULL);
 	}
@@ -175,12 +182,12 @@
 		while (n != NULL)
 			{
 			nn=n->next;
-			free(n);
+			Free(n);
 			n=nn;
 			}
 		}
-	free((char *)lh->b);
-	free((char *)lh);
+	Free((char *)lh->b);
+	Free((char *)lh);
 	}
 
 char *lh_insert(lh, data)
@@ -191,6 +198,7 @@
 	LHASH_NODE *nn,**rn;
 	char *ret;
 
+	lh->error=0;
 	if (lh->up_load <= (lh->num_items*LH_LOAD_MULT/lh->num_nodes))
 		expand(lh);
 
@@ -198,8 +206,11 @@
 
 	if (*rn == NULL)
 		{
-		if ((nn=(LHASH_NODE *)malloc(sizeof(LHASH_NODE))) == NULL)
+		if ((nn=(LHASH_NODE *)Malloc(sizeof(LHASH_NODE))) == NULL)
+			{
+			lh->error++;
 			return(NULL);
+			}
 		nn->data=data;
 		nn->next=NULL;
 #ifndef NO_HASH_COMP
@@ -227,6 +238,7 @@
 	LHASH_NODE *nn,**rn;
 	char *ret;
 
+	lh->error=0;
 	rn=getrn(lh,data,&hash);
 
 	if (*rn == NULL)
@@ -239,7 +251,7 @@
 		nn= *rn;
 		*rn=nn->next;
 		ret=nn->data;
-		free((char *)nn);
+		Free((char *)nn);
 		lh->num_delete++;
 		}
 
@@ -259,6 +271,7 @@
 	LHASH_NODE **rn;
 	char *ret;
 
+	lh->error=0;
 	rn=getrn(lh,data,&hash);
 
 	if (*rn == NULL)
@@ -342,11 +355,12 @@
 	if ((lh->p) >= lh->pmax)
 		{
 		j=(int)lh->num_alloc_nodes*2;
-		n=(LHASH_NODE **)realloc((char *)lh->b,
+		n=(LHASH_NODE **)Realloc((char *)lh->b,
 			(unsigned int)sizeof(LHASH_NODE *)*j);
 		if (n == NULL)
 			{
 /*			fputs("realloc error in lhash",stderr); */
+			lh->error++;
 			lh->p=0;
 			return;
 			}
@@ -370,11 +384,12 @@
 	lh->b[lh->p+lh->pmax-1]=NULL; /* 24/07-92 - eay - weird but :-( */
 	if (lh->p == 0)
 		{
-		n=(LHASH_NODE **)realloc((char *)lh->b,
+		n=(LHASH_NODE **)Realloc((char *)lh->b,
 			(unsigned int)(sizeof(LHASH_NODE *)*lh->pmax));
 		if (n == NULL)
 			{
 /*			fputs("realloc error in lhash",stderr); */
+			lh->error++;
 			return;
 			}
 		lh->num_contract_reallocs++;
diff --git a/crypto/lhash/lhash.h b/crypto/lhash/lhash.h
index 70cbc6d..06aad87 100644
--- a/crypto/lhash/lhash.h
+++ b/crypto/lhash/lhash.h
@@ -102,10 +102,16 @@
 	unsigned long num_retrieve;
 	unsigned long num_retrieve_miss;
 	unsigned long num_hash_comps;
+
+	int error;
 	} LHASH;
 
 #define LH_LOAD_MULT	256
 
+/* Indicates a malloc() error in the last call, this is only bad
+ * in lh_insert(). */
+#define lh_error(lh)	((lh)->error)
+
 #ifndef NOPROTO
 LHASH *lh_new(unsigned long (*h)(), int (*c)());
 void lh_free(LHASH *lh);
diff --git a/crypto/md2/md2_dgst.c b/crypto/md2/md2_dgst.c
index 5cbd36f..6a60dd2 100644
--- a/crypto/md2/md2_dgst.c
+++ b/crypto/md2/md2_dgst.c
@@ -61,7 +61,7 @@
 #include <string.h>
 #include "md2.h"
 
-char *MD2_version="MD2 part of SSLeay 0.9.0b 29-Jun-1998";
+char *MD2_version="MD2 part of SSLeay 0.9.1a 06-Jul-1998";
 
 /* Implemented from RFC1319 The MD2 Message-Digest Algorithm
  */
diff --git a/crypto/md5/Makefile.ssl b/crypto/md5/Makefile.ssl
index 47e1ce0..abbe2ee 100644
--- a/crypto/md5/Makefile.ssl
+++ b/crypto/md5/Makefile.ssl
@@ -59,7 +59,7 @@
 
 # bsdi
 asm/mx86bsdi.o: asm/mx86unix.cpp
-	$(CPP) -DBSDI asm/mx86unix.cpp | as -o asm/mx86bsdi.o
+	$(CPP) -DBSDI asm/mx86unix.cpp | sed 's/ :/:/' | as -o asm/mx86bsdi.o
 
 asm/mx86unix.cpp:
 	(cd asm; perl md5-586.pl cpp >mx86unix.cpp)
diff --git a/crypto/md5/f b/crypto/md5/f
new file mode 100644
index 0000000..b21505c
--- /dev/null
+++ b/crypto/md5/f
@@ -0,0 +1,731 @@
+# 1 "asm/mx86unix.cpp"
+ 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 
+	 
+	 
+	 
+	 
+	 
+
+	.file	"md5-586.s"
+	.version	"01.01"
+gcc2_compiled.:
+.text
+	.align 4 
+.globl _md5_block_x86 
+	 
+_md5_block_x86 :
+	pushl	%esi
+	pushl	%edi
+	movl	12(%esp),	%edi
+	movl	16(%esp),	%esi
+	movl	20(%esp),	%ecx
+	pushl	%ebp
+	pushl	%ebx
+	addl	%esi,		%ecx
+	subl	$64,		%ecx
+	movl	(%edi),		%eax
+	pushl	%ecx
+	movl	4(%edi),	%ebx
+	movl	8(%edi),	%ecx
+	movl	12(%edi),	%edx
+.L000start:
+
+	 
+	movl	%ecx,		%edi
+	movl	(%esi),		%ebp
+	 
+	xorl	%edx,		%edi
+	andl	%ebx,		%edi
+	leal	3614090360(%eax,%ebp,1),%eax
+	movl	4(%esi),	%ebp
+	xorl	%edx,		%edi
+	addl	%edi,		%eax
+	movl	%ebx,		%edi
+	roll	$7,		%eax
+	addl	%ebx,		%eax
+	 
+	xorl	%ecx,		%edi
+	andl	%eax,		%edi
+	leal	3905402710(%edx,%ebp,1),%edx
+	movl	8(%esi),	%ebp
+	xorl	%ecx,		%edi
+	addl	%edi,		%edx
+	movl	%eax,		%edi
+	roll	$12,		%edx
+	addl	%eax,		%edx
+	 
+	xorl	%ebx,		%edi
+	andl	%edx,		%edi
+	leal	606105819(%ecx,%ebp,1),%ecx
+	movl	12(%esi),	%ebp
+	xorl	%ebx,		%edi
+	addl	%edi,		%ecx
+	movl	%edx,		%edi
+	roll	$17,		%ecx
+	addl	%edx,		%ecx
+	 
+	xorl	%eax,		%edi
+	andl	%ecx,		%edi
+	leal	3250441966(%ebx,%ebp,1),%ebx
+	movl	16(%esi),	%ebp
+	xorl	%eax,		%edi
+	addl	%edi,		%ebx
+	movl	%ecx,		%edi
+	roll	$22,		%ebx
+	addl	%ecx,		%ebx
+	 
+	xorl	%edx,		%edi
+	andl	%ebx,		%edi
+	leal	4118548399(%eax,%ebp,1),%eax
+	movl	20(%esi),	%ebp
+	xorl	%edx,		%edi
+	addl	%edi,		%eax
+	movl	%ebx,		%edi
+	roll	$7,		%eax
+	addl	%ebx,		%eax
+	 
+	xorl	%ecx,		%edi
+	andl	%eax,		%edi
+	leal	1200080426(%edx,%ebp,1),%edx
+	movl	24(%esi),	%ebp
+	xorl	%ecx,		%edi
+	addl	%edi,		%edx
+	movl	%eax,		%edi
+	roll	$12,		%edx
+	addl	%eax,		%edx
+	 
+	xorl	%ebx,		%edi
+	andl	%edx,		%edi
+	leal	2821735955(%ecx,%ebp,1),%ecx
+	movl	28(%esi),	%ebp
+	xorl	%ebx,		%edi
+	addl	%edi,		%ecx
+	movl	%edx,		%edi
+	roll	$17,		%ecx
+	addl	%edx,		%ecx
+	 
+	xorl	%eax,		%edi
+	andl	%ecx,		%edi
+	leal	4249261313(%ebx,%ebp,1),%ebx
+	movl	32(%esi),	%ebp
+	xorl	%eax,		%edi
+	addl	%edi,		%ebx
+	movl	%ecx,		%edi
+	roll	$22,		%ebx
+	addl	%ecx,		%ebx
+	 
+	xorl	%edx,		%edi
+	andl	%ebx,		%edi
+	leal	1770035416(%eax,%ebp,1),%eax
+	movl	36(%esi),	%ebp
+	xorl	%edx,		%edi
+	addl	%edi,		%eax
+	movl	%ebx,		%edi
+	roll	$7,		%eax
+	addl	%ebx,		%eax
+	 
+	xorl	%ecx,		%edi
+	andl	%eax,		%edi
+	leal	2336552879(%edx,%ebp,1),%edx
+	movl	40(%esi),	%ebp
+	xorl	%ecx,		%edi
+	addl	%edi,		%edx
+	movl	%eax,		%edi
+	roll	$12,		%edx
+	addl	%eax,		%edx
+	 
+	xorl	%ebx,		%edi
+	andl	%edx,		%edi
+	leal	4294925233(%ecx,%ebp,1),%ecx
+	movl	44(%esi),	%ebp
+	xorl	%ebx,		%edi
+	addl	%edi,		%ecx
+	movl	%edx,		%edi
+	roll	$17,		%ecx
+	addl	%edx,		%ecx
+	 
+	xorl	%eax,		%edi
+	andl	%ecx,		%edi
+	leal	2304563134(%ebx,%ebp,1),%ebx
+	movl	48(%esi),	%ebp
+	xorl	%eax,		%edi
+	addl	%edi,		%ebx
+	movl	%ecx,		%edi
+	roll	$22,		%ebx
+	addl	%ecx,		%ebx
+	 
+	xorl	%edx,		%edi
+	andl	%ebx,		%edi
+	leal	1804603682(%eax,%ebp,1),%eax
+	movl	52(%esi),	%ebp
+	xorl	%edx,		%edi
+	addl	%edi,		%eax
+	movl	%ebx,		%edi
+	roll	$7,		%eax
+	addl	%ebx,		%eax
+	 
+	xorl	%ecx,		%edi
+	andl	%eax,		%edi
+	leal	4254626195(%edx,%ebp,1),%edx
+	movl	56(%esi),	%ebp
+	xorl	%ecx,		%edi
+	addl	%edi,		%edx
+	movl	%eax,		%edi
+	roll	$12,		%edx
+	addl	%eax,		%edx
+	 
+	xorl	%ebx,		%edi
+	andl	%edx,		%edi
+	leal	2792965006(%ecx,%ebp,1),%ecx
+	movl	60(%esi),	%ebp
+	xorl	%ebx,		%edi
+	addl	%edi,		%ecx
+	movl	%edx,		%edi
+	roll	$17,		%ecx
+	addl	%edx,		%ecx
+	 
+	xorl	%eax,		%edi
+	andl	%ecx,		%edi
+	leal	1236535329(%ebx,%ebp,1),%ebx
+	movl	4(%esi),	%ebp
+	xorl	%eax,		%edi
+	addl	%edi,		%ebx
+	movl	%ecx,		%edi
+	roll	$22,		%ebx
+	addl	%ecx,		%ebx
+
+	 
+	 
+	leal	4129170786(%eax,%ebp,1),%eax
+	xorl	%ebx,		%edi
+	andl	%edx,		%edi
+	movl	24(%esi),	%ebp
+	xorl	%ecx,		%edi
+	addl	%edi,		%eax
+	movl	%ebx,		%edi
+	roll	$5,		%eax
+	addl	%ebx,		%eax
+	 
+	leal	3225465664(%edx,%ebp,1),%edx
+	xorl	%eax,		%edi
+	andl	%ecx,		%edi
+	movl	44(%esi),	%ebp
+	xorl	%ebx,		%edi
+	addl	%edi,		%edx
+	movl	%eax,		%edi
+	roll	$9,		%edx
+	addl	%eax,		%edx
+	 
+	leal	643717713(%ecx,%ebp,1),%ecx
+	xorl	%edx,		%edi
+	andl	%ebx,		%edi
+	movl	(%esi),		%ebp
+	xorl	%eax,		%edi
+	addl	%edi,		%ecx
+	movl	%edx,		%edi
+	roll	$14,		%ecx
+	addl	%edx,		%ecx
+	 
+	leal	3921069994(%ebx,%ebp,1),%ebx
+	xorl	%ecx,		%edi
+	andl	%eax,		%edi
+	movl	20(%esi),	%ebp
+	xorl	%edx,		%edi
+	addl	%edi,		%ebx
+	movl	%ecx,		%edi
+	roll	$20,		%ebx
+	addl	%ecx,		%ebx
+	 
+	leal	3593408605(%eax,%ebp,1),%eax
+	xorl	%ebx,		%edi
+	andl	%edx,		%edi
+	movl	40(%esi),	%ebp
+	xorl	%ecx,		%edi
+	addl	%edi,		%eax
+	movl	%ebx,		%edi
+	roll	$5,		%eax
+	addl	%ebx,		%eax
+	 
+	leal	38016083(%edx,%ebp,1),%edx
+	xorl	%eax,		%edi
+	andl	%ecx,		%edi
+	movl	60(%esi),	%ebp
+	xorl	%ebx,		%edi
+	addl	%edi,		%edx
+	movl	%eax,		%edi
+	roll	$9,		%edx
+	addl	%eax,		%edx
+	 
+	leal	3634488961(%ecx,%ebp,1),%ecx
+	xorl	%edx,		%edi
+	andl	%ebx,		%edi
+	movl	16(%esi),	%ebp
+	xorl	%eax,		%edi
+	addl	%edi,		%ecx
+	movl	%edx,		%edi
+	roll	$14,		%ecx
+	addl	%edx,		%ecx
+	 
+	leal	3889429448(%ebx,%ebp,1),%ebx
+	xorl	%ecx,		%edi
+	andl	%eax,		%edi
+	movl	36(%esi),	%ebp
+	xorl	%edx,		%edi
+	addl	%edi,		%ebx
+	movl	%ecx,		%edi
+	roll	$20,		%ebx
+	addl	%ecx,		%ebx
+	 
+	leal	568446438(%eax,%ebp,1),%eax
+	xorl	%ebx,		%edi
+	andl	%edx,		%edi
+	movl	56(%esi),	%ebp
+	xorl	%ecx,		%edi
+	addl	%edi,		%eax
+	movl	%ebx,		%edi
+	roll	$5,		%eax
+	addl	%ebx,		%eax
+	 
+	leal	3275163606(%edx,%ebp,1),%edx
+	xorl	%eax,		%edi
+	andl	%ecx,		%edi
+	movl	12(%esi),	%ebp
+	xorl	%ebx,		%edi
+	addl	%edi,		%edx
+	movl	%eax,		%edi
+	roll	$9,		%edx
+	addl	%eax,		%edx
+	 
+	leal	4107603335(%ecx,%ebp,1),%ecx
+	xorl	%edx,		%edi
+	andl	%ebx,		%edi
+	movl	32(%esi),	%ebp
+	xorl	%eax,		%edi
+	addl	%edi,		%ecx
+	movl	%edx,		%edi
+	roll	$14,		%ecx
+	addl	%edx,		%ecx
+	 
+	leal	1163531501(%ebx,%ebp,1),%ebx
+	xorl	%ecx,		%edi
+	andl	%eax,		%edi
+	movl	52(%esi),	%ebp
+	xorl	%edx,		%edi
+	addl	%edi,		%ebx
+	movl	%ecx,		%edi
+	roll	$20,		%ebx
+	addl	%ecx,		%ebx
+	 
+	leal	2850285829(%eax,%ebp,1),%eax
+	xorl	%ebx,		%edi
+	andl	%edx,		%edi
+	movl	8(%esi),	%ebp
+	xorl	%ecx,		%edi
+	addl	%edi,		%eax
+	movl	%ebx,		%edi
+	roll	$5,		%eax
+	addl	%ebx,		%eax
+	 
+	leal	4243563512(%edx,%ebp,1),%edx
+	xorl	%eax,		%edi
+	andl	%ecx,		%edi
+	movl	28(%esi),	%ebp
+	xorl	%ebx,		%edi
+	addl	%edi,		%edx
+	movl	%eax,		%edi
+	roll	$9,		%edx
+	addl	%eax,		%edx
+	 
+	leal	1735328473(%ecx,%ebp,1),%ecx
+	xorl	%edx,		%edi
+	andl	%ebx,		%edi
+	movl	48(%esi),	%ebp
+	xorl	%eax,		%edi
+	addl	%edi,		%ecx
+	movl	%edx,		%edi
+	roll	$14,		%ecx
+	addl	%edx,		%ecx
+	 
+	leal	2368359562(%ebx,%ebp,1),%ebx
+	xorl	%ecx,		%edi
+	andl	%eax,		%edi
+	movl	20(%esi),	%ebp
+	xorl	%edx,		%edi
+	addl	%edi,		%ebx
+	movl	%ecx,		%edi
+	roll	$20,		%ebx
+	addl	%ecx,		%ebx
+
+	 
+	 
+	xorl	%edx,		%edi
+	xorl	%ebx,		%edi
+	leal	4294588738(%eax,%ebp,1),%eax
+	addl	%edi,		%eax
+	movl	32(%esi),	%ebp
+	roll	$4,		%eax
+	movl	%ebx,		%edi
+	 
+	leal	2272392833(%edx,%ebp,1),%edx
+	addl	%ebx,		%eax
+	xorl	%ecx,		%edi
+	xorl	%eax,		%edi
+	movl	44(%esi),	%ebp
+	addl	%edi,		%edx
+	movl	%eax,		%edi
+	roll	$11,		%edx
+	addl	%eax,		%edx
+	 
+	xorl	%ebx,		%edi
+	xorl	%edx,		%edi
+	leal	1839030562(%ecx,%ebp,1),%ecx
+	addl	%edi,		%ecx
+	movl	56(%esi),	%ebp
+	roll	$16,		%ecx
+	movl	%edx,		%edi
+	 
+	leal	4259657740(%ebx,%ebp,1),%ebx
+	addl	%edx,		%ecx
+	xorl	%eax,		%edi
+	xorl	%ecx,		%edi
+	movl	4(%esi),	%ebp
+	addl	%edi,		%ebx
+	movl	%ecx,		%edi
+	roll	$23,		%ebx
+	addl	%ecx,		%ebx
+	 
+	xorl	%edx,		%edi
+	xorl	%ebx,		%edi
+	leal	2763975236(%eax,%ebp,1),%eax
+	addl	%edi,		%eax
+	movl	16(%esi),	%ebp
+	roll	$4,		%eax
+	movl	%ebx,		%edi
+	 
+	leal	1272893353(%edx,%ebp,1),%edx
+	addl	%ebx,		%eax
+	xorl	%ecx,		%edi
+	xorl	%eax,		%edi
+	movl	28(%esi),	%ebp
+	addl	%edi,		%edx
+	movl	%eax,		%edi
+	roll	$11,		%edx
+	addl	%eax,		%edx
+	 
+	xorl	%ebx,		%edi
+	xorl	%edx,		%edi
+	leal	4139469664(%ecx,%ebp,1),%ecx
+	addl	%edi,		%ecx
+	movl	40(%esi),	%ebp
+	roll	$16,		%ecx
+	movl	%edx,		%edi
+	 
+	leal	3200236656(%ebx,%ebp,1),%ebx
+	addl	%edx,		%ecx
+	xorl	%eax,		%edi
+	xorl	%ecx,		%edi
+	movl	52(%esi),	%ebp
+	addl	%edi,		%ebx
+	movl	%ecx,		%edi
+	roll	$23,		%ebx
+	addl	%ecx,		%ebx
+	 
+	xorl	%edx,		%edi
+	xorl	%ebx,		%edi
+	leal	681279174(%eax,%ebp,1),%eax
+	addl	%edi,		%eax
+	movl	(%esi),		%ebp
+	roll	$4,		%eax
+	movl	%ebx,		%edi
+	 
+	leal	3936430074(%edx,%ebp,1),%edx
+	addl	%ebx,		%eax
+	xorl	%ecx,		%edi
+	xorl	%eax,		%edi
+	movl	12(%esi),	%ebp
+	addl	%edi,		%edx
+	movl	%eax,		%edi
+	roll	$11,		%edx
+	addl	%eax,		%edx
+	 
+	xorl	%ebx,		%edi
+	xorl	%edx,		%edi
+	leal	3572445317(%ecx,%ebp,1),%ecx
+	addl	%edi,		%ecx
+	movl	24(%esi),	%ebp
+	roll	$16,		%ecx
+	movl	%edx,		%edi
+	 
+	leal	76029189(%ebx,%ebp,1),%ebx
+	addl	%edx,		%ecx
+	xorl	%eax,		%edi
+	xorl	%ecx,		%edi
+	movl	36(%esi),	%ebp
+	addl	%edi,		%ebx
+	movl	%ecx,		%edi
+	roll	$23,		%ebx
+	addl	%ecx,		%ebx
+	 
+	xorl	%edx,		%edi
+	xorl	%ebx,		%edi
+	leal	3654602809(%eax,%ebp,1),%eax
+	addl	%edi,		%eax
+	movl	48(%esi),	%ebp
+	roll	$4,		%eax
+	movl	%ebx,		%edi
+	 
+	leal	3873151461(%edx,%ebp,1),%edx
+	addl	%ebx,		%eax
+	xorl	%ecx,		%edi
+	xorl	%eax,		%edi
+	movl	60(%esi),	%ebp
+	addl	%edi,		%edx
+	movl	%eax,		%edi
+	roll	$11,		%edx
+	addl	%eax,		%edx
+	 
+	xorl	%ebx,		%edi
+	xorl	%edx,		%edi
+	leal	530742520(%ecx,%ebp,1),%ecx
+	addl	%edi,		%ecx
+	movl	8(%esi),	%ebp
+	roll	$16,		%ecx
+	movl	%edx,		%edi
+	 
+	leal	3299628645(%ebx,%ebp,1),%ebx
+	addl	%edx,		%ecx
+	xorl	%eax,		%edi
+	xorl	%ecx,		%edi
+	movl	(%esi),		%ebp
+	addl	%edi,		%ebx
+	movl	$-1,		%edi
+	roll	$23,		%ebx
+	addl	%ecx,		%ebx
+
+	 
+	 
+	xorl	%edx,		%edi
+	orl	%ebx,		%edi
+	leal	4096336452(%eax,%ebp,1),%eax
+	xorl	%ecx,		%edi
+	movl	28(%esi),	%ebp
+	addl	%edi,		%eax
+	movl	$-1,		%edi
+	roll	$6,		%eax
+	xorl	%ecx,		%edi
+	addl	%ebx,		%eax
+	 
+	orl	%eax,		%edi
+	leal	1126891415(%edx,%ebp,1),%edx
+	xorl	%ebx,		%edi
+	movl	56(%esi),	%ebp
+	addl	%edi,		%edx
+	movl	$-1,		%edi
+	roll	$10,		%edx
+	xorl	%ebx,		%edi
+	addl	%eax,		%edx
+	 
+	orl	%edx,		%edi
+	leal	2878612391(%ecx,%ebp,1),%ecx
+	xorl	%eax,		%edi
+	movl	20(%esi),	%ebp
+	addl	%edi,		%ecx
+	movl	$-1,		%edi
+	roll	$15,		%ecx
+	xorl	%eax,		%edi
+	addl	%edx,		%ecx
+	 
+	orl	%ecx,		%edi
+	leal	4237533241(%ebx,%ebp,1),%ebx
+	xorl	%edx,		%edi
+	movl	48(%esi),	%ebp
+	addl	%edi,		%ebx
+	movl	$-1,		%edi
+	roll	$21,		%ebx
+	xorl	%edx,		%edi
+	addl	%ecx,		%ebx
+	 
+	orl	%ebx,		%edi
+	leal	1700485571(%eax,%ebp,1),%eax
+	xorl	%ecx,		%edi
+	movl	12(%esi),	%ebp
+	addl	%edi,		%eax
+	movl	$-1,		%edi
+	roll	$6,		%eax
+	xorl	%ecx,		%edi
+	addl	%ebx,		%eax
+	 
+	orl	%eax,		%edi
+	leal	2399980690(%edx,%ebp,1),%edx
+	xorl	%ebx,		%edi
+	movl	40(%esi),	%ebp
+	addl	%edi,		%edx
+	movl	$-1,		%edi
+	roll	$10,		%edx
+	xorl	%ebx,		%edi
+	addl	%eax,		%edx
+	 
+	orl	%edx,		%edi
+	leal	4293915773(%ecx,%ebp,1),%ecx
+	xorl	%eax,		%edi
+	movl	4(%esi),	%ebp
+	addl	%edi,		%ecx
+	movl	$-1,		%edi
+	roll	$15,		%ecx
+	xorl	%eax,		%edi
+	addl	%edx,		%ecx
+	 
+	orl	%ecx,		%edi
+	leal	2240044497(%ebx,%ebp,1),%ebx
+	xorl	%edx,		%edi
+	movl	32(%esi),	%ebp
+	addl	%edi,		%ebx
+	movl	$-1,		%edi
+	roll	$21,		%ebx
+	xorl	%edx,		%edi
+	addl	%ecx,		%ebx
+	 
+	orl	%ebx,		%edi
+	leal	1873313359(%eax,%ebp,1),%eax
+	xorl	%ecx,		%edi
+	movl	60(%esi),	%ebp
+	addl	%edi,		%eax
+	movl	$-1,		%edi
+	roll	$6,		%eax
+	xorl	%ecx,		%edi
+	addl	%ebx,		%eax
+	 
+	orl	%eax,		%edi
+	leal	4264355552(%edx,%ebp,1),%edx
+	xorl	%ebx,		%edi
+	movl	24(%esi),	%ebp
+	addl	%edi,		%edx
+	movl	$-1,		%edi
+	roll	$10,		%edx
+	xorl	%ebx,		%edi
+	addl	%eax,		%edx
+	 
+	orl	%edx,		%edi
+	leal	2734768916(%ecx,%ebp,1),%ecx
+	xorl	%eax,		%edi
+	movl	52(%esi),	%ebp
+	addl	%edi,		%ecx
+	movl	$-1,		%edi
+	roll	$15,		%ecx
+	xorl	%eax,		%edi
+	addl	%edx,		%ecx
+	 
+	orl	%ecx,		%edi
+	leal	1309151649(%ebx,%ebp,1),%ebx
+	xorl	%edx,		%edi
+	movl	16(%esi),	%ebp
+	addl	%edi,		%ebx
+	movl	$-1,		%edi
+	roll	$21,		%ebx
+	xorl	%edx,		%edi
+	addl	%ecx,		%ebx
+	 
+	orl	%ebx,		%edi
+	leal	4149444226(%eax,%ebp,1),%eax
+	xorl	%ecx,		%edi
+	movl	44(%esi),	%ebp
+	addl	%edi,		%eax
+	movl	$-1,		%edi
+	roll	$6,		%eax
+	xorl	%ecx,		%edi
+	addl	%ebx,		%eax
+	 
+	orl	%eax,		%edi
+	leal	3174756917(%edx,%ebp,1),%edx
+	xorl	%ebx,		%edi
+	movl	8(%esi),	%ebp
+	addl	%edi,		%edx
+	movl	$-1,		%edi
+	roll	$10,		%edx
+	xorl	%ebx,		%edi
+	addl	%eax,		%edx
+	 
+	orl	%edx,		%edi
+	leal	718787259(%ecx,%ebp,1),%ecx
+	xorl	%eax,		%edi
+	movl	36(%esi),	%ebp
+	addl	%edi,		%ecx
+	movl	$-1,		%edi
+	roll	$15,		%ecx
+	xorl	%eax,		%edi
+	addl	%edx,		%ecx
+	 
+	orl	%ecx,		%edi
+	leal	3951481745(%ebx,%ebp,1),%ebx
+	xorl	%edx,		%edi
+	movl	24(%esp),	%ebp
+	addl	%edi,		%ebx
+	addl	$64,		%esi
+	roll	$21,		%ebx
+	movl	(%ebp),		%edi
+	addl	%ecx,		%ebx
+	addl	%edi,		%eax
+	movl	4(%ebp),	%edi
+	addl	%edi,		%ebx
+	movl	8(%ebp),	%edi
+	addl	%edi,		%ecx
+	movl	12(%ebp),	%edi
+	addl	%edi,		%edx
+	movl	%eax,		(%ebp)
+	movl	%ebx,		4(%ebp)
+	movl	(%esp),		%edi
+	movl	%ecx,		8(%ebp)
+	movl	%edx,		12(%ebp)
+	cmpl	%esi,		%edi
+	jge	.L000start
+	popl	%eax
+	popl	%ebx
+	popl	%ebp
+	popl	%edi
+	popl	%esi
+	ret
+.md5_block_x86_end:
+	 
+.ident	"desasm.pl"
diff --git a/crypto/md5/md5_dgst.c b/crypto/md5/md5_dgst.c
index 43b3498..367b5bc 100644
--- a/crypto/md5/md5_dgst.c
+++ b/crypto/md5/md5_dgst.c
@@ -59,7 +59,7 @@
 #include <stdio.h>
 #include "md5_locl.h"
 
-char *MD5_version="MD5 part of SSLeay 0.9.0b 29-Jun-1998";
+char *MD5_version="MD5 part of SSLeay 0.9.1a 06-Jul-1998";
 
 /* Implemented from RFC1321 The MD5 Message-Digest Algorithm
  */
diff --git a/crypto/mdc2/mdc2dgst.c b/crypto/mdc2/mdc2dgst.c
index 3f3d11a..2a086c0 100644
--- a/crypto/mdc2/mdc2dgst.c
+++ b/crypto/mdc2/mdc2dgst.c
@@ -150,9 +150,11 @@
 		(*h)[0]=((*h)[0]&0x9f)|0x40;
 		(*hh)[0]=((*hh)[0]&0x9f)|0x20;
 
+		des_set_odd_parity(h);
 		des_set_key(h,k);
 		des_encrypt((DES_LONG *)d,k,1);
 
+		des_set_odd_parity(hh);
 		des_set_key(hh,k);
 		des_encrypt((DES_LONG *)dd,k,1);
 
diff --git a/crypto/mem.c b/crypto/mem.c
index 72e501a..e5f2492 100644
--- a/crypto/mem.c
+++ b/crypto/mem.c
@@ -63,7 +63,11 @@
 #include "lhash.h"
 #include "cryptlib.h"
 
+#ifdef CRYPTO_MDEBUG
+static int mh_mode=CRYPTO_MEM_CHECK_ON;
+#else
 static int mh_mode=CRYPTO_MEM_CHECK_OFF;
+#endif
 static unsigned long order=0;
 
 static LHASH *mh=NULL;
@@ -91,6 +95,13 @@
 	case CRYPTO_MEM_CHECK_OFF:
 		mh_mode&= ~CRYPTO_MEM_CHECK_ON;
 		break;
+	case CRYPTO_MEM_CHECK_DISABLE:
+		mh_mode&= ~CRYPTO_MEM_CHECK_ENABLE;
+		break;
+	case CRYPTO_MEM_CHECK_ENABLE:
+		if (mh_mode&CRYPTO_MEM_CHECK_ON)
+			mh_mode|=CRYPTO_MEM_CHECK_ENABLE;
+		break;
 	default:
 		break;
 		}
@@ -115,6 +126,8 @@
 	return(ret);
 	}
 
+static char *(*malloc_locked_func)()=(char *(*)())malloc;
+static void (*free_locked_func)()=(void (*)())free;
 static char *(*malloc_func)()=	(char *(*)())malloc;
 static char *(*realloc_func)()=	(char *(*)())realloc;
 static void (*free_func)()=	(void (*)())free;
@@ -128,6 +141,17 @@
 	malloc_func=m;
 	realloc_func=r;
 	free_func=f;
+	malloc_locked_func=m;
+	free_locked_func=f;
+	}
+
+void CRYPTO_set_locked_mem_functions(m,f)
+char *(*m)();
+void (*f)();
+	{
+	if ((m == NULL) || (f == NULL)) return;
+	malloc_locked_func=m;
+	free_locked_func=f;
 	}
 
 void CRYPTO_get_mem_functions(m,r,f)
@@ -140,6 +164,26 @@
 	if (f != NULL) *f=free_func;
 	}
 
+void CRYPTO_get_locked_mem_functions(m,f)
+char *(**m)();
+void (**f)();
+	{
+	if (m != NULL) *m=malloc_locked_func;
+	if (f != NULL) *f=free_locked_func;
+	}
+
+char *CRYPTO_malloc_locked(num)
+int num;
+	{
+	return(malloc_locked_func(num));
+	}
+
+void CRYPTO_free_locked(str)
+char *str;
+	{
+	free_locked_func(str);
+	}
+
 char *CRYPTO_malloc(num)
 int num;
 	{
@@ -159,6 +203,7 @@
 	free_func(str);
 	}
 
+static unsigned long break_order_num=0;
 char *CRYPTO_dbg_malloc(num,file,line)
 int num;
 char *file;
@@ -170,11 +215,13 @@
 	if ((ret=malloc_func(num)) == NULL)
 		return(NULL);
 
-	if (mh_mode & CRYPTO_MEM_CHECK_ON)
+	if (mh_mode & CRYPTO_MEM_CHECK_ENABLE)
 		{
-		if ((m=(MEM *)malloc(sizeof(MEM))) == NULL)
+		MemCheck_off();
+		if ((m=(MEM *)Malloc(sizeof(MEM))) == NULL)
 			{
-			free(ret);
+			Free(ret);
+			MemCheck_on();
 			return(NULL);
 			}
 		CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
@@ -182,9 +229,10 @@
 			{
 			if ((mh=lh_new(mem_hash,mem_cmp)) == NULL)
 				{
-				free(ret);
-				free(m);
-				return(NULL);
+				Free(ret);
+				Free(m);
+				ret=NULL;
+				goto err;
 				}
 			}
 
@@ -192,13 +240,20 @@
 		m->file=file;
 		m->line=line;
 		m->num=num;
+		if (order == break_order_num)
+			{
+			/* BREAK HERE */
+			m->order=order;
+			}
 		m->order=order++;
 		if ((mm=(MEM *)lh_insert(mh,(char *)m)) != NULL)
 			{
 			/* Not good, but don't sweat it */
-			free(mm);
+			Free(mm);
 			}
+err:
 		CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
+		MemCheck_on();
 		}
 	return(ret);
 	}
@@ -208,14 +263,16 @@
 	{
 	MEM m,*mp;
 
-	if ((mh_mode & CRYPTO_MEM_CHECK_ON) && (mh != NULL))
+	if ((mh_mode & CRYPTO_MEM_CHECK_ENABLE) && (mh != NULL))
 		{
+		MemCheck_off();
 		CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
 		m.addr=addr;
 		mp=(MEM *)lh_delete(mh,(char *)&m);
 		if (mp != NULL)
-			free(mp);
+			Free(mp);
 		CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
+		MemCheck_on();
 		}
 	free_func(addr);
 	}
@@ -232,8 +289,9 @@
 	ret=realloc_func(addr,num);
 	if (ret == addr) return(ret);
 
-	if (mh_mode & CRYPTO_MEM_CHECK_ON)
+	if (mh_mode & CRYPTO_MEM_CHECK_ENABLE)
 		{
+		MemCheck_off();
 		if (ret == NULL) return(NULL);
 		m.addr=addr;
 		CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
@@ -244,6 +302,7 @@
 			lh_insert(mh,(char *)mp);
 			}
 		CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
+		MemCheck_on();
 		}
 	return(ret);
 	}
@@ -308,11 +367,12 @@
 			ml.bytes,ml.chunks);
 		BIO_puts(b,buf);
 		}
-	/*
+
+#if 0
 	lh_stats_bio(mh,b);
         lh_node_stats_bio(mh,b);
         lh_node_usage_stats_bio(mh,b);
-	*/
+#endif
 	}
 
 static void (*mem_cb)()=NULL;
diff --git a/crypto/objects/Makefile.ssl b/crypto/objects/Makefile.ssl
index 320523c..4fa4a7d 100644
--- a/crypto/objects/Makefile.ssl
+++ b/crypto/objects/Makefile.ssl
@@ -22,8 +22,8 @@
 APPS=
 
 LIB=$(TOP)/libcrypto.a
-LIBSRC=	obj_dat.c obj_lib.c $(ERRC).c
-LIBOBJ= obj_dat.o obj_lib.o $(ERRC).o
+LIBSRC=	o_names.c obj_dat.c obj_lib.c $(ERRC).c
+LIBOBJ= o_names.o obj_dat.o obj_lib.o $(ERRC).o
 
 SRC= $(LIBSRC)
 
diff --git a/crypto/objects/o_names.c b/crypto/objects/o_names.c
new file mode 100644
index 0000000..8995869
--- /dev/null
+++ b/crypto/objects/o_names.c
@@ -0,0 +1,254 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "lhash.h"
+#include "objects.h"
+
+/* I use the ex_data stuff to manage the identifiers for the obj_name_types
+ * that applications may define.  I only really use the free function field.
+ */
+static LHASH *names_lh=NULL;
+static int names_type_num=OBJ_NAME_TYPE_NUM;
+static STACK *names_cmp=NULL;
+static STACK *names_hash=NULL;
+static STACK *names_free=NULL;
+
+static unsigned long obj_name_hash(OBJ_NAME *a);
+static int obj_name_cmp(OBJ_NAME *a,OBJ_NAME *b);
+
+int OBJ_NAME_init()
+	{
+	if (names_lh != NULL) return(1);
+	MemCheck_off();
+	names_lh=lh_new(obj_name_hash,obj_name_cmp);
+	MemCheck_on();
+	return(names_lh != NULL);
+	}
+
+int OBJ_NAME_new_index(hash_func,cmp_func,free_func)
+unsigned long (*hash_func)();
+int (*cmp_func)();
+void (*free_func)();
+	{
+	int ret;
+	int i;
+
+	if (names_free == NULL)
+		{
+		MemCheck_off();
+		names_hash=sk_new_null();
+		names_cmp=sk_new_null();
+		names_free=sk_new_null();
+		MemCheck_on();
+		}
+	if ((names_free == NULL) || (names_hash == NULL) || (names_cmp == NULL))
+		{
+		/* ERROR */
+		return(0);
+		}
+	ret=names_type_num;
+	names_type_num++;
+	for (i=sk_num(names_free); i<names_type_num; i++)
+		{
+		MemCheck_off();
+		sk_push(names_hash,(char *)strcmp);
+		sk_push(names_cmp,(char *)lh_strhash);
+		sk_push(names_free,NULL);
+		MemCheck_on();
+		}
+	if (hash_func != NULL)
+		sk_value(names_hash,ret)=(char *)hash_func;
+	if (cmp_func != NULL)
+		sk_value(names_cmp,ret)= (char *)cmp_func;
+	if (free_func != NULL)
+		sk_value(names_free,ret)=(char *)free_func;
+	return(ret);
+	}
+
+static int obj_name_cmp(a,b)
+OBJ_NAME *a;
+OBJ_NAME *b;
+	{
+	int ret;
+	int (*cmp)();
+
+	ret=a->type-b->type;
+	if (ret == 0)
+		{
+		if ((names_cmp != NULL) && (sk_num(names_cmp) > a->type))
+			{
+			cmp=(int (*)())sk_value(names_cmp,a->type);
+			ret=cmp(a->name,b->name);
+			}
+		else
+			ret=strcmp(a->name,b->name);
+		}
+	return(ret);
+	}
+
+static unsigned long obj_name_hash(a)
+OBJ_NAME *a;
+	{
+	unsigned long ret;
+	unsigned long (*hash)();
+
+	if ((names_hash != NULL) && (sk_num(names_hash) > a->type))
+		{
+		hash=(unsigned long (*)())sk_value(names_hash,a->type);
+		ret=hash(a->name);
+		}
+	else
+		{
+		ret=lh_strhash(a->name);
+		}
+	ret^=a->type;
+	return(ret);
+	}
+
+char *OBJ_NAME_get(name,type)
+char *name;
+int type;
+	{
+	OBJ_NAME on,*ret;
+	int num=0,alias;
+
+	if (name == NULL) return(NULL);
+	if ((names_lh == NULL) && !OBJ_NAME_init()) return(NULL);
+
+	alias=type&OBJ_NAME_ALIAS;
+	type&= ~OBJ_NAME_ALIAS;
+
+	on.name=name;
+	on.type=type;
+
+	for (;;)
+		{
+		ret=(OBJ_NAME *)lh_retrieve(names_lh,(char *)&on);
+		if (ret == NULL) return(NULL);
+		if ((ret->alias) && !alias)
+			{
+			if (++num > 10) return(NULL);
+			on.name=ret->data;
+			}
+		else
+			{
+			return(ret->data);
+			}
+		}
+	}
+
+int OBJ_NAME_add(name,type,data)
+char *name;
+int type;
+char *data;
+	{
+	void (*f)();
+	OBJ_NAME *onp,*ret;
+	int alias;
+
+	if ((names_lh == NULL) && !OBJ_NAME_init()) return(0);
+
+	alias=type&OBJ_NAME_ALIAS;
+	type&= ~OBJ_NAME_ALIAS;
+
+	onp=(OBJ_NAME *)Malloc(sizeof(OBJ_NAME));
+	if (onp == NULL)
+		{
+		/* ERROR */
+		return(0);
+		}
+
+	onp->name=name;
+	onp->alias=alias;
+	onp->type=type;
+	onp->data=data;
+
+	ret=(OBJ_NAME *)lh_insert(names_lh,(char *)onp);
+	if (ret != NULL)
+		{
+		/* free things */
+		if ((names_free != NULL) && (sk_num(names_free) > ret->type))
+			{
+			f=(void (*)())sk_value(names_free,ret->type);
+			f(ret->name,ret->type,ret->data);
+			}
+		Free((char *)ret);
+		}
+	else
+		{
+		if (lh_error(names_lh))
+			{
+			/* ERROR */
+			return(0);
+			}
+		}
+	return(1);
+	}
+
+int OBJ_NAME_remove(name,type)
+char *name;
+int type;
+	{
+	OBJ_NAME on,*ret;
+	void (*f)();
+
+	if (names_lh == NULL) return(0);
+
+	type&= ~OBJ_NAME_ALIAS;
+	on.name=name;
+	on.type=type;
+	ret=(OBJ_NAME *)lh_delete(names_lh,(char *)&on);
+	if (ret != NULL)
+		{
+		/* free things */
+		if ((names_free != NULL) && (sk_num(names_free) > type))
+			{
+			f=(void (*)())sk_value(names_free,type);
+			f(ret->name,ret->type,ret->data);
+			}
+		Free((char *)ret);
+		return(1);
+		}
+	else
+		return(0);
+	}
+
+static int free_type;
+
+static void names_lh_free(onp,type)
+OBJ_NAME *onp;
+	{
+	if ((free_type < 0) || (free_type == onp->type))
+		{
+		OBJ_NAME_remove(onp->name,onp->type);
+		}
+	}
+
+void OBJ_NAME_cleanup(type)
+int type;
+	{
+	unsigned long down_load;
+
+	if (names_lh == NULL) return;
+
+	free_type=type;
+	down_load=names_lh->down_load;
+	names_lh->down_load=0;
+
+	lh_doall(names_lh,names_lh_free);
+	if (type < 0)
+		{
+		lh_free(names_lh);
+		sk_free(names_hash);
+		sk_free(names_cmp);
+		sk_free(names_free);
+		names_lh=NULL;
+		names_hash=NULL;
+		names_cmp=NULL;
+		names_free=NULL;
+		}
+	else
+		names_lh->down_load=down_load;
+	}
+
diff --git a/crypto/objects/obj_dat.c b/crypto/objects/obj_dat.c
index 34866eb..93424a3 100644
--- a/crypto/objects/obj_dat.c
+++ b/crypto/objects/obj_dat.c
@@ -64,7 +64,20 @@
 #include "objects.h"
 
 /* obj_dat.h is generated from objects.h by obj_dat.pl */
+#ifndef NO_OBJECT
 #include "obj_dat.h"
+#else
+/* You will have to load all the objects needed manually in the application */
+#define NUM_NID 0
+#define NUM_SN 0
+#define NUM_LN 0
+#define NUM_OBJ 0
+static unsigned char lvalues[1];
+static ASN1_OBJECT nid_objs[1];
+static ASN1_OBJECT *sn_objs[1];
+static ASN1_OBJECT *ln_objs[1];
+static ASN1_OBJECT *obj_objs[1];
+#endif
 
 #ifndef NOPROTO
 static int sn_cmp(ASN1_OBJECT **a, ASN1_OBJECT **b);
@@ -163,6 +176,7 @@
 	default:
 		abort();
 		}
+	return(1); /* should not get here */
 	}
 
 static int init_added()
@@ -177,7 +191,8 @@
 	{
 	a->obj->nid=0;
 	a->obj->flags|=ASN1_OBJECT_FLAG_DYNAMIC|
-	                ASN1_OBJECT_FLAG_DYNAMIC_STRINGS;
+	                ASN1_OBJECT_FLAG_DYNAMIC_STRINGS|
+			ASN1_OBJECT_FLAG_DYNAMIC_DATA;
 	}
 
 static void cleanup2(a)
@@ -247,7 +262,9 @@
 				Free(aop);
 			}
 		}
-	o->flags&= ~(ASN1_OBJECT_FLAG_DYNAMIC|ASN1_OBJECT_FLAG_DYNAMIC_STRINGS);
+	o->flags&= ~(ASN1_OBJECT_FLAG_DYNAMIC|ASN1_OBJECT_FLAG_DYNAMIC_STRINGS|
+			ASN1_OBJECT_FLAG_DYNAMIC_DATA);
+
 	return(o->nid);
 err:
 	for (i=ADDED_DATA; i<=ADDED_NID; i++)
@@ -502,7 +519,7 @@
 BIO *in;
 	{
 	MS_STATIC char buf[512];
-	int i,num= -1;
+	int i,num=0;
 	char *o,*s,*l=NULL;
 
 	for (;;)
@@ -544,7 +561,7 @@
 		if (!OBJ_create(o,s,l)) return(num);
 		num++;
 		}
-	return(num);
+	/* return(num); */
 	}
 
 int OBJ_create(oid,sn,ln)
diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h
index 6f10675..ea79d47 100644
--- a/crypto/objects/obj_dat.h
+++ b/crypto/objects/obj_dat.h
@@ -61,276 +61,281 @@
  * perl obj_dat.pl < objects.h > obj_dat.h
  */
 
-#define NUM_NID 124
-#define NUM_SN 95
-#define NUM_LN 122
-#define NUM_OBJ 95
+#define NUM_NID 126
+#define NUM_SN 97
+#define NUM_LN 124
+#define NUM_OBJ 98
 
-static unsigned char lvalues[600]={
-0x2A,0x86,0x48,0x86,0xF7,0x0D,               /* [  0] OBJ_rsadsi */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,          /* [  6] OBJ_pkcs */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x02,     /* [ 13] OBJ_md2 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x05,     /* [ 21] OBJ_md5 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x03,0x04,     /* [ 29] OBJ_rc4 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,/* [ 37] OBJ_rsaEncryption */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x02,/* [ 46] OBJ_md2WithRSAEncryption */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x04,/* [ 55] OBJ_md5WithRSAEncryption */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x01,/* [ 64] OBJ_pbeWithMD2AndDES_CBC */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x03,/* [ 73] OBJ_pbeWithMD5AndDES_CBC */
-0x55,                                        /* [ 82] OBJ_X500 */
-0x55,0x04,                                   /* [ 83] OBJ_X509 */
-0x55,0x04,0x03,                              /* [ 85] OBJ_commonName */
-0x55,0x04,0x06,                              /* [ 88] OBJ_countryName */
-0x55,0x04,0x07,                              /* [ 91] OBJ_localityName */
-0x55,0x04,0x08,                              /* [ 94] OBJ_stateOrProvinceName */
-0x55,0x04,0x0A,                              /* [ 97] OBJ_organizationName */
-0x55,0x04,0x0B,                              /* [100] OBJ_organizationalUnitName */
-0x55,0x08,0x01,0x01,                         /* [103] OBJ_rsa */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,     /* [107] OBJ_pkcs7 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x01,/* [115] OBJ_pkcs7_data */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x02,/* [124] OBJ_pkcs7_signed */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x03,/* [133] OBJ_pkcs7_enveloped */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x04,/* [142] OBJ_pkcs7_signedAndEnveloped */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x05,/* [151] OBJ_pkcs7_digest */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x06,/* [160] OBJ_pkcs7_encrypted */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x03,     /* [169] OBJ_pkcs3 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x03,0x01,/* [177] OBJ_dhKeyAgreement */
-0x2B,0x0E,0x03,0x02,0x06,                    /* [186] OBJ_des_ecb */
-0x2B,0x0E,0x03,0x02,0x09,                    /* [191] OBJ_des_cfb64 */
-0x2B,0x0E,0x03,0x02,0x07,                    /* [196] OBJ_des_cbc */
-0x2B,0x0E,0x03,0x02,0x11,                    /* [201] OBJ_des_ede */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x03,0x02,     /* [206] OBJ_rc2_cbc */
-0x2B,0x0E,0x03,0x02,0x12,                    /* [214] OBJ_sha */
-0x2B,0x0E,0x03,0x02,0x0F,                    /* [219] OBJ_shaWithRSAEncryption */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x03,0x07,     /* [224] OBJ_des_ede3_cbc */
-0x2B,0x0E,0x03,0x02,0x08,                    /* [232] OBJ_des_ofb64 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,     /* [237] OBJ_pkcs9 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x01,/* [245] OBJ_pkcs9_emailAddress */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x02,/* [254] OBJ_pkcs9_unstructuredName */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x03,/* [263] OBJ_pkcs9_contentType */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x04,/* [272] OBJ_pkcs9_messageDigest */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x05,/* [281] OBJ_pkcs9_signingTime */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x06,/* [290] OBJ_pkcs9_countersignature */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x07,/* [299] OBJ_pkcs9_challengePassword */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x08,/* [308] OBJ_pkcs9_unstructuredAddress */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x09,/* [317] OBJ_pkcs9_extCertAttributes */
-0x60,0x86,0x48,0x01,0x86,0xF8,0x42,          /* [326] OBJ_netscape */
-0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,     /* [333] OBJ_netscape_cert_extension */
-0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x02,     /* [341] OBJ_netscape_data_type */
-0x2B,0x0E,0x03,0x02,0x1A,                    /* [349] OBJ_sha1 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,/* [354] OBJ_sha1WithRSAEncryption */
-0x2B,0x0E,0x03,0x02,0x0D,                    /* [363] OBJ_dsaWithSHA */
-0x2B,0x0E,0x03,0x02,0x0C,                    /* [368] OBJ_dsa_2 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x0B,/* [373] OBJ_pbeWithSHA1AndRC2_CBC */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x0C,/* [382] OBJ_pbeWithSHA1AndRC4 */
-0x2B,0x0E,0x03,0x02,0x1B,                    /* [391] OBJ_dsaWithSHA1_2 */
-0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x01,/* [396] OBJ_netscape_cert_type */
-0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x02,/* [405] OBJ_netscape_base_url */
-0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x03,/* [414] OBJ_netscape_revocation_url */
-0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x04,/* [423] OBJ_netscape_ca_revocation_url */
-0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x07,/* [432] OBJ_netscape_renewal_url */
-0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x08,/* [441] OBJ_netscape_ca_policy_url */
-0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x0C,/* [450] OBJ_netscape_ssl_server_name */
-0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x0D,/* [459] OBJ_netscape_comment */
-0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x02,0x05,/* [468] OBJ_netscape_cert_sequence */
-0x55,0x1D,                                   /* [477] OBJ_ld_ce */
-0x55,0x1D,0x0E,                              /* [479] OBJ_subject_key_identifier */
-0x55,0x1D,0x0F,                              /* [482] OBJ_key_usage */
-0x55,0x1D,0x10,                              /* [485] OBJ_private_key_usage_period */
-0x55,0x1D,0x11,                              /* [488] OBJ_subject_alt_name */
-0x55,0x1D,0x12,                              /* [491] OBJ_issuer_alt_name */
-0x55,0x1D,0x13,                              /* [494] OBJ_basic_constraints */
-0x55,0x1D,0x14,                              /* [497] OBJ_crl_number */
-0x55,0x1D,0x20,                              /* [500] OBJ_certificate_policies */
-0x55,0x1D,0x23,                              /* [503] OBJ_authority_key_identifier */
-0x55,0x08,0x03,0x65,                         /* [506] OBJ_mdc2 */
-0x55,0x08,0x03,0x64,                         /* [510] OBJ_mdc2WithRSA */
-0x55,0x04,0x2A,                              /* [514] OBJ_givenName */
-0x55,0x04,0x04,                              /* [517] OBJ_surname */
-0x55,0x04,0x2B,                              /* [520] OBJ_initials */
-0x55,0x04,0x2D,                              /* [523] OBJ_uniqueIdentifier */
-0x55,0x1D,0x1F,                              /* [526] OBJ_crl_distribution_points */
-0x2B,0x0E,0x03,0x02,0x03,                    /* [529] OBJ_md5WithRSA */
-0x55,0x04,0x05,                              /* [534] OBJ_serialNumber */
-0x55,0x04,0x0C,                              /* [537] OBJ_title */
-0x55,0x04,0x0D,                              /* [540] OBJ_description */
-0x2A,0x86,0x48,0x86,0xF6,0x7D,0x07,0x42,0x0A,/* [543] OBJ_cast5_cbc */
-0x2A,0x86,0x48,0x86,0xF6,0x7D,0x07,0x42,0x0C,/* [552] OBJ_pbeWithMD5AndCast5_CBC */
-0x2A,0x86,0x48,0xCE,0x38,0x04,0x03,          /* [561] OBJ_dsaWithSHA1 */
-0x2B,0x0E,0x03,0x02,0x1D,                    /* [568] OBJ_sha1WithRSA */
-0x2A,0x86,0x48,0xCE,0x38,0x04,0x01,          /* [573] OBJ_dsa */
-0x2B,0x24,0x03,0x02,0x01,                    /* [580] OBJ_ripemd160 */
-0x2B,0x24,0x03,0x03,0x01,0x02,               /* [585] OBJ_ripemd160WithRSA */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x03,0x08,     /* [591] OBJ_rc5_cbc */
+static unsigned char lvalues[611]={
+0x00,                                        /* [  0] OBJ_undef */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,               /* [  1] OBJ_rsadsi */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,          /* [  7] OBJ_pkcs */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x02,     /* [ 14] OBJ_md2 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x05,     /* [ 22] OBJ_md5 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x03,0x04,     /* [ 30] OBJ_rc4 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,/* [ 38] OBJ_rsaEncryption */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x02,/* [ 47] OBJ_md2WithRSAEncryption */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x04,/* [ 56] OBJ_md5WithRSAEncryption */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x01,/* [ 65] OBJ_pbeWithMD2AndDES_CBC */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x03,/* [ 74] OBJ_pbeWithMD5AndDES_CBC */
+0x55,                                        /* [ 83] OBJ_X500 */
+0x55,0x04,                                   /* [ 84] OBJ_X509 */
+0x55,0x04,0x03,                              /* [ 86] OBJ_commonName */
+0x55,0x04,0x06,                              /* [ 89] OBJ_countryName */
+0x55,0x04,0x07,                              /* [ 92] OBJ_localityName */
+0x55,0x04,0x08,                              /* [ 95] OBJ_stateOrProvinceName */
+0x55,0x04,0x0A,                              /* [ 98] OBJ_organizationName */
+0x55,0x04,0x0B,                              /* [101] OBJ_organizationalUnitName */
+0x55,0x08,0x01,0x01,                         /* [104] OBJ_rsa */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,     /* [108] OBJ_pkcs7 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x01,/* [116] OBJ_pkcs7_data */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x02,/* [125] OBJ_pkcs7_signed */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x03,/* [134] OBJ_pkcs7_enveloped */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x04,/* [143] OBJ_pkcs7_signedAndEnveloped */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x05,/* [152] OBJ_pkcs7_digest */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x06,/* [161] OBJ_pkcs7_encrypted */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x03,     /* [170] OBJ_pkcs3 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x03,0x01,/* [178] OBJ_dhKeyAgreement */
+0x2B,0x0E,0x03,0x02,0x06,                    /* [187] OBJ_des_ecb */
+0x2B,0x0E,0x03,0x02,0x09,                    /* [192] OBJ_des_cfb64 */
+0x2B,0x0E,0x03,0x02,0x07,                    /* [197] OBJ_des_cbc */
+0x2B,0x0E,0x03,0x02,0x11,                    /* [202] OBJ_des_ede */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x03,0x02,     /* [207] OBJ_rc2_cbc */
+0x2B,0x0E,0x03,0x02,0x12,                    /* [215] OBJ_sha */
+0x2B,0x0E,0x03,0x02,0x0F,                    /* [220] OBJ_shaWithRSAEncryption */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x03,0x07,     /* [225] OBJ_des_ede3_cbc */
+0x2B,0x0E,0x03,0x02,0x08,                    /* [233] OBJ_des_ofb64 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,     /* [238] OBJ_pkcs9 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x01,/* [246] OBJ_pkcs9_emailAddress */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x02,/* [255] OBJ_pkcs9_unstructuredName */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x03,/* [264] OBJ_pkcs9_contentType */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x04,/* [273] OBJ_pkcs9_messageDigest */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x05,/* [282] OBJ_pkcs9_signingTime */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x06,/* [291] OBJ_pkcs9_countersignature */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x07,/* [300] OBJ_pkcs9_challengePassword */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x08,/* [309] OBJ_pkcs9_unstructuredAddress */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x09,/* [318] OBJ_pkcs9_extCertAttributes */
+0x60,0x86,0x48,0x01,0x86,0xF8,0x42,          /* [327] OBJ_netscape */
+0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,     /* [334] OBJ_netscape_cert_extension */
+0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x02,     /* [342] OBJ_netscape_data_type */
+0x2B,0x0E,0x03,0x02,0x1A,                    /* [350] OBJ_sha1 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,/* [355] OBJ_sha1WithRSAEncryption */
+0x2B,0x0E,0x03,0x02,0x0D,                    /* [364] OBJ_dsaWithSHA */
+0x2B,0x0E,0x03,0x02,0x0C,                    /* [369] OBJ_dsa_2 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x0B,/* [374] OBJ_pbeWithSHA1AndRC2_CBC */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x0C,/* [383] OBJ_pbeWithSHA1AndRC4 */
+0x2B,0x0E,0x03,0x02,0x1B,                    /* [392] OBJ_dsaWithSHA1_2 */
+0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x01,/* [397] OBJ_netscape_cert_type */
+0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x02,/* [406] OBJ_netscape_base_url */
+0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x03,/* [415] OBJ_netscape_revocation_url */
+0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x04,/* [424] OBJ_netscape_ca_revocation_url */
+0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x07,/* [433] OBJ_netscape_renewal_url */
+0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x08,/* [442] OBJ_netscape_ca_policy_url */
+0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x0C,/* [451] OBJ_netscape_ssl_server_name */
+0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x0D,/* [460] OBJ_netscape_comment */
+0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x02,0x05,/* [469] OBJ_netscape_cert_sequence */
+0x55,0x1D,                                   /* [478] OBJ_ld_ce */
+0x55,0x1D,0x0E,                              /* [480] OBJ_subject_key_identifier */
+0x55,0x1D,0x0F,                              /* [483] OBJ_key_usage */
+0x55,0x1D,0x10,                              /* [486] OBJ_private_key_usage_period */
+0x55,0x1D,0x11,                              /* [489] OBJ_subject_alt_name */
+0x55,0x1D,0x12,                              /* [492] OBJ_issuer_alt_name */
+0x55,0x1D,0x13,                              /* [495] OBJ_basic_constraints */
+0x55,0x1D,0x14,                              /* [498] OBJ_crl_number */
+0x55,0x1D,0x20,                              /* [501] OBJ_certificate_policies */
+0x55,0x1D,0x23,                              /* [504] OBJ_authority_key_identifier */
+0x55,0x08,0x03,0x65,                         /* [507] OBJ_mdc2 */
+0x55,0x08,0x03,0x64,                         /* [511] OBJ_mdc2WithRSA */
+0x55,0x04,0x2A,                              /* [515] OBJ_givenName */
+0x55,0x04,0x04,                              /* [518] OBJ_surname */
+0x55,0x04,0x2B,                              /* [521] OBJ_initials */
+0x55,0x04,0x2D,                              /* [524] OBJ_uniqueIdentifier */
+0x55,0x1D,0x1F,                              /* [527] OBJ_crl_distribution_points */
+0x2B,0x0E,0x03,0x02,0x03,                    /* [530] OBJ_md5WithRSA */
+0x55,0x04,0x05,                              /* [535] OBJ_serialNumber */
+0x55,0x04,0x0C,                              /* [538] OBJ_title */
+0x55,0x04,0x0D,                              /* [541] OBJ_description */
+0x2A,0x86,0x48,0x86,0xF6,0x7D,0x07,0x42,0x0A,/* [544] OBJ_cast5_cbc */
+0x2A,0x86,0x48,0x86,0xF6,0x7D,0x07,0x42,0x0C,/* [553] OBJ_pbeWithMD5AndCast5_CBC */
+0x2A,0x86,0x48,0xCE,0x38,0x04,0x03,          /* [562] OBJ_dsaWithSHA1 */
+0x2B,0x0E,0x03,0x02,0x1D,                    /* [569] OBJ_sha1WithRSA */
+0x2A,0x86,0x48,0xCE,0x38,0x04,0x01,          /* [574] OBJ_dsa */
+0x2B,0x24,0x03,0x02,0x01,                    /* [581] OBJ_ripemd160 */
+0x2B,0x24,0x03,0x03,0x01,0x02,               /* [586] OBJ_ripemd160WithRSA */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x03,0x08,     /* [592] OBJ_rc5_cbc */
+0x29,0x01,0x01,0x85,0x1A,                    /* [600] OBJ_rle_compression */
+0x29,0x01,0x01,0x85,0x1A,                    /* [605] OBJ_zlib_compression */
 };
 
 static ASN1_OBJECT nid_objs[NUM_NID]={
-{"UNDEF","undefined",NID_undef,0,NULL},
-{"rsadsi","rsadsi",NID_rsadsi,6,&(lvalues[0]),0},
-{"pkcs","pkcs",NID_pkcs,7,&(lvalues[6]),0},
-{"MD2","md2",NID_md2,8,&(lvalues[13]),0},
-{"MD5","md5",NID_md5,8,&(lvalues[21]),0},
-{"RC4","rc4",NID_rc4,8,&(lvalues[29]),0},
-{"rsaEncryption","rsaEncryption",NID_rsaEncryption,9,&(lvalues[37]),0},
+{"UNDEF","undefined",NID_undef,1,&(lvalues[0]),0},
+{"rsadsi","rsadsi",NID_rsadsi,6,&(lvalues[1]),0},
+{"pkcs","pkcs",NID_pkcs,7,&(lvalues[7]),0},
+{"MD2","md2",NID_md2,8,&(lvalues[14]),0},
+{"MD5","md5",NID_md5,8,&(lvalues[22]),0},
+{"RC4","rc4",NID_rc4,8,&(lvalues[30]),0},
+{"rsaEncryption","rsaEncryption",NID_rsaEncryption,9,&(lvalues[38]),0},
 {"RSA-MD2","md2WithRSAEncryption",NID_md2WithRSAEncryption,9,
-	&(lvalues[46]),0},
+	&(lvalues[47]),0},
 {"RSA-MD5","md5WithRSAEncryption",NID_md5WithRSAEncryption,9,
-	&(lvalues[55]),0},
+	&(lvalues[56]),0},
 {"pbeWithMD2AndDES-CBC","pbeWithMD2AndDES-CBC",
-	NID_pbeWithMD2AndDES_CBC,9,&(lvalues[64]),0},
+	NID_pbeWithMD2AndDES_CBC,9,&(lvalues[65]),0},
 {"pbeWithMD5AndDES-CBC","pbeWithMD5AndDES-CBC",
-	NID_pbeWithMD5AndDES_CBC,9,&(lvalues[73]),0},
-{"X500","X500",NID_X500,1,&(lvalues[82]),0},
-{"X509","X509",NID_X509,2,&(lvalues[83]),0},
-{"CN","commonName",NID_commonName,3,&(lvalues[85]),0},
-{"C","countryName",NID_countryName,3,&(lvalues[88]),0},
-{"L","localityName",NID_localityName,3,&(lvalues[91]),0},
-{"ST","stateOrProvinceName",NID_stateOrProvinceName,3,&(lvalues[94]),0},
-{"O","organizationName",NID_organizationName,3,&(lvalues[97]),0},
+	NID_pbeWithMD5AndDES_CBC,9,&(lvalues[74]),0},
+{"X500","X500",NID_X500,1,&(lvalues[83]),0},
+{"X509","X509",NID_X509,2,&(lvalues[84]),0},
+{"CN","commonName",NID_commonName,3,&(lvalues[86]),0},
+{"C","countryName",NID_countryName,3,&(lvalues[89]),0},
+{"L","localityName",NID_localityName,3,&(lvalues[92]),0},
+{"ST","stateOrProvinceName",NID_stateOrProvinceName,3,&(lvalues[95]),0},
+{"O","organizationName",NID_organizationName,3,&(lvalues[98]),0},
 {"OU","organizationalUnitName",NID_organizationalUnitName,3,
-	&(lvalues[100]),0},
-{"RSA","rsa",NID_rsa,4,&(lvalues[103]),0},
-{"pkcs7","pkcs7",NID_pkcs7,8,&(lvalues[107]),0},
-{"pkcs7-data","pkcs7-data",NID_pkcs7_data,9,&(lvalues[115]),0},
+	&(lvalues[101]),0},
+{"RSA","rsa",NID_rsa,4,&(lvalues[104]),0},
+{"pkcs7","pkcs7",NID_pkcs7,8,&(lvalues[108]),0},
+{"pkcs7-data","pkcs7-data",NID_pkcs7_data,9,&(lvalues[116]),0},
 {"pkcs7-signedData","pkcs7-signedData",NID_pkcs7_signed,9,
-	&(lvalues[124]),0},
+	&(lvalues[125]),0},
 {"pkcs7-envelopedData","pkcs7-envelopedData",NID_pkcs7_enveloped,9,
-	&(lvalues[133]),0},
+	&(lvalues[134]),0},
 {"pkcs7-signedAndEnvelopedData","pkcs7-signedAndEnvelopedData",
-	NID_pkcs7_signedAndEnveloped,9,&(lvalues[142]),0},
+	NID_pkcs7_signedAndEnveloped,9,&(lvalues[143]),0},
 {"pkcs7-digestData","pkcs7-digestData",NID_pkcs7_digest,9,
-	&(lvalues[151]),0},
+	&(lvalues[152]),0},
 {"pkcs7-encryptedData","pkcs7-encryptedData",NID_pkcs7_encrypted,9,
-	&(lvalues[160]),0},
-{"pkcs3","pkcs3",NID_pkcs3,8,&(lvalues[169]),0},
+	&(lvalues[161]),0},
+{"pkcs3","pkcs3",NID_pkcs3,8,&(lvalues[170]),0},
 {"dhKeyAgreement","dhKeyAgreement",NID_dhKeyAgreement,9,
-	&(lvalues[177]),0},
-{"DES-ECB","des-ecb",NID_des_ecb,5,&(lvalues[186]),0},
-{"DES-CFB","des-cfb",NID_des_cfb64,5,&(lvalues[191]),0},
-{"DES-CBC","des-cbc",NID_des_cbc,5,&(lvalues[196]),0},
-{"DES-EDE","des-ede",NID_des_ede,5,&(lvalues[201]),0},
+	&(lvalues[178]),0},
+{"DES-ECB","des-ecb",NID_des_ecb,5,&(lvalues[187]),0},
+{"DES-CFB","des-cfb",NID_des_cfb64,5,&(lvalues[192]),0},
+{"DES-CBC","des-cbc",NID_des_cbc,5,&(lvalues[197]),0},
+{"DES-EDE","des-ede",NID_des_ede,5,&(lvalues[202]),0},
 {"DES-EDE3","des-ede3",NID_des_ede3,0,NULL},
 {"IDEA-CBC","idea-cbc",NID_idea_cbc,0,NULL},
 {"IDEA-CFB","idea-cfb",NID_idea_cfb64,0,NULL},
 {"IDEA-ECB","idea-ecb",NID_idea_ecb,0,NULL},
-{"RC2-CBC","rc2-cbc",NID_rc2_cbc,8,&(lvalues[206]),0},
+{"RC2-CBC","rc2-cbc",NID_rc2_cbc,8,&(lvalues[207]),0},
 {"RC2-ECB","rc2-ecb",NID_rc2_ecb,0,NULL},
 {"RC2-CFB","rc2-cfb",NID_rc2_cfb64,0,NULL},
 {"RC2-OFB","rc2-ofb",NID_rc2_ofb64,0,NULL},
-{"SHA","sha",NID_sha,5,&(lvalues[214]),0},
+{"SHA","sha",NID_sha,5,&(lvalues[215]),0},
 {"RSA-SHA","shaWithRSAEncryption",NID_shaWithRSAEncryption,5,
-	&(lvalues[219]),0},
+	&(lvalues[220]),0},
 {"DES-EDE-CBC","des-ede-cbc",NID_des_ede_cbc,0,NULL},
-{"DES-EDE3-CBC","des-ede3-cbc",NID_des_ede3_cbc,8,&(lvalues[224]),0},
-{"DES-OFB","des-ofb",NID_des_ofb64,5,&(lvalues[232]),0},
+{"DES-EDE3-CBC","des-ede3-cbc",NID_des_ede3_cbc,8,&(lvalues[225]),0},
+{"DES-OFB","des-ofb",NID_des_ofb64,5,&(lvalues[233]),0},
 {"IDEA-OFB","idea-ofb",NID_idea_ofb64,0,NULL},
-{"pkcs9","pkcs9",NID_pkcs9,8,&(lvalues[237]),0},
-{"Email","emailAddress",NID_pkcs9_emailAddress,9,&(lvalues[245]),0},
+{"pkcs9","pkcs9",NID_pkcs9,8,&(lvalues[238]),0},
+{"Email","emailAddress",NID_pkcs9_emailAddress,9,&(lvalues[246]),0},
 {"unstructuredName","unstructuredName",NID_pkcs9_unstructuredName,9,
-	&(lvalues[254]),0},
-{"contentType","contentType",NID_pkcs9_contentType,9,&(lvalues[263]),0},
+	&(lvalues[255]),0},
+{"contentType","contentType",NID_pkcs9_contentType,9,&(lvalues[264]),0},
 {"messageDigest","messageDigest",NID_pkcs9_messageDigest,9,
-	&(lvalues[272]),0},
-{"signingTime","signingTime",NID_pkcs9_signingTime,9,&(lvalues[281]),0},
+	&(lvalues[273]),0},
+{"signingTime","signingTime",NID_pkcs9_signingTime,9,&(lvalues[282]),0},
 {"countersignature","countersignature",NID_pkcs9_countersignature,9,
-	&(lvalues[290]),0},
+	&(lvalues[291]),0},
 {"challengePassword","challengePassword",NID_pkcs9_challengePassword,
-	9,&(lvalues[299]),0},
+	9,&(lvalues[300]),0},
 {"unstructuredAddress","unstructuredAddress",
-	NID_pkcs9_unstructuredAddress,9,&(lvalues[308]),0},
+	NID_pkcs9_unstructuredAddress,9,&(lvalues[309]),0},
 {"extendedCertificateAttributes","extendedCertificateAttributes",
-	NID_pkcs9_extCertAttributes,9,&(lvalues[317]),0},
+	NID_pkcs9_extCertAttributes,9,&(lvalues[318]),0},
 {"Netscape","Netscape Communications Corp.",NID_netscape,7,
-	&(lvalues[326]),0},
+	&(lvalues[327]),0},
 {"nsCertExt","Netscape Certificate Extension",
-	NID_netscape_cert_extension,8,&(lvalues[333]),0},
+	NID_netscape_cert_extension,8,&(lvalues[334]),0},
 {"nsDataType","Netscape Data Type",NID_netscape_data_type,8,
-	&(lvalues[341]),0},
+	&(lvalues[342]),0},
 {"DES-EDE-CFB","des-ede-cfb",NID_des_ede_cfb64,0,NULL},
 {"DES-EDE3-CFB","des-ede3-cfb",NID_des_ede3_cfb64,0,NULL},
 {"DES-EDE-OFB","des-ede-ofb",NID_des_ede_ofb64,0,NULL},
 {"DES-EDE3-OFB","des-ede3-ofb",NID_des_ede3_ofb64,0,NULL},
-{"SHA1","sha1",NID_sha1,5,&(lvalues[349]),0},
+{"SHA1","sha1",NID_sha1,5,&(lvalues[350]),0},
 {"RSA-SHA1","sha1WithRSAEncryption",NID_sha1WithRSAEncryption,9,
-	&(lvalues[354]),0},
-{"DSA-SHA","dsaWithSHA",NID_dsaWithSHA,5,&(lvalues[363]),0},
-{"DSA-old","dsaEncryption-old",NID_dsa_2,5,&(lvalues[368]),0},
+	&(lvalues[355]),0},
+{"DSA-SHA","dsaWithSHA",NID_dsaWithSHA,5,&(lvalues[364]),0},
+{"DSA-old","dsaEncryption-old",NID_dsa_2,5,&(lvalues[369]),0},
 {"pbeWithSHA1AndRC2-CBC","pbeWithSHA1AndRC2-CBC",
-	NID_pbeWithSHA1AndRC2_CBC,9,&(lvalues[373]),0},
+	NID_pbeWithSHA1AndRC2_CBC,9,&(lvalues[374]),0},
 {"pbeWithSHA1AndRC4","pbeWithSHA1AndRC4",NID_pbeWithSHA1AndRC4,9,
-	&(lvalues[382]),0},
-{"DSA-SHA1-old","dsaWithSHA1",NID_dsaWithSHA1_2,5,&(lvalues[391]),0},
+	&(lvalues[383]),0},
+{"DSA-SHA1-old","dsaWithSHA1-old",NID_dsaWithSHA1_2,5,&(lvalues[392]),0},
 {"nsCertType","Netscape Cert Type",NID_netscape_cert_type,9,
-	&(lvalues[396]),0},
+	&(lvalues[397]),0},
 {"nsBaseUrl","Netscape Base Url",NID_netscape_base_url,9,
-	&(lvalues[405]),0},
+	&(lvalues[406]),0},
 {"nsRevocationUrl","Netscape Revocation Url",
-	NID_netscape_revocation_url,9,&(lvalues[414]),0},
+	NID_netscape_revocation_url,9,&(lvalues[415]),0},
 {"nsCaRevocationUrl","Netscape CA Revocation Url",
-	NID_netscape_ca_revocation_url,9,&(lvalues[423]),0},
+	NID_netscape_ca_revocation_url,9,&(lvalues[424]),0},
 {"nsRenewalUrl","Netscape Renewal Url",NID_netscape_renewal_url,9,
-	&(lvalues[432]),0},
+	&(lvalues[433]),0},
 {"nsCaPolicyUrl","Netscape CA Policy Url",NID_netscape_ca_policy_url,
-	9,&(lvalues[441]),0},
+	9,&(lvalues[442]),0},
 {"nsSslServerName","Netscape SSL Server Name",
-	NID_netscape_ssl_server_name,9,&(lvalues[450]),0},
-{"nsComment","Netscape Comment",NID_netscape_comment,9,&(lvalues[459]),0},
+	NID_netscape_ssl_server_name,9,&(lvalues[451]),0},
+{"nsComment","Netscape Comment",NID_netscape_comment,9,&(lvalues[460]),0},
 {"nsCertSequence","Netscape Certificate Sequence",
-	NID_netscape_cert_sequence,9,&(lvalues[468]),0},
+	NID_netscape_cert_sequence,9,&(lvalues[469]),0},
 {"DESX-CBC","desx-cbc",NID_desx_cbc,0,NULL},
-{"ld-ce","ld-ce",NID_ld_ce,2,&(lvalues[477]),0},
+{"ld-ce","ld-ce",NID_ld_ce,2,&(lvalues[478]),0},
 {"subjectKeyIdentifier","X509v3 Subject Key Identifier",
-	NID_subject_key_identifier,3,&(lvalues[479]),0},
-{"keyUsage","X509v3 Key Usage",NID_key_usage,3,&(lvalues[482]),0},
+	NID_subject_key_identifier,3,&(lvalues[480]),0},
+{"keyUsage","X509v3 Key Usage",NID_key_usage,3,&(lvalues[483]),0},
 {"privateKeyUsagePeriod","X509v3 Private Key Usage Period",
-	NID_private_key_usage_period,3,&(lvalues[485]),0},
+	NID_private_key_usage_period,3,&(lvalues[486]),0},
 {"subjectAltName","X509v3 Subject Alternative Name",
-	NID_subject_alt_name,3,&(lvalues[488]),0},
+	NID_subject_alt_name,3,&(lvalues[489]),0},
 {"issuerAltName","X509v3 Issuer Alternative Name",NID_issuer_alt_name,
-	3,&(lvalues[491]),0},
+	3,&(lvalues[492]),0},
 {"basicConstraints","X509v3 Basic Constraints",NID_basic_constraints,
-	3,&(lvalues[494]),0},
-{"crlNumber","X509v3 CRL Number",NID_crl_number,3,&(lvalues[497]),0},
+	3,&(lvalues[495]),0},
+{"crlNumber","X509v3 CRL Number",NID_crl_number,3,&(lvalues[498]),0},
 {"certificatePolicies","X509v3 Certificate Policies",
-	NID_certificate_policies,3,&(lvalues[500]),0},
+	NID_certificate_policies,3,&(lvalues[501]),0},
 {"authorityKeyIdentifier","X509v3 Authority Key Identifier",
-	NID_authority_key_identifier,3,&(lvalues[503]),0},
+	NID_authority_key_identifier,3,&(lvalues[504]),0},
 {"BF-CBC","bf-cbc",NID_bf_cbc,0,NULL},
 {"BF-ECB","bf-ecb",NID_bf_ecb,0,NULL},
 {"BF-CFB","bf-cfb",NID_bf_cfb64,0,NULL},
 {"BF-OFB","bf-ofb",NID_bf_ofb64,0,NULL},
-{"MDC2","mdc2",NID_mdc2,4,&(lvalues[506]),0},
-{"RSA-MDC2","mdc2withRSA",NID_mdc2WithRSA,4,&(lvalues[510]),0},
+{"MDC2","mdc2",NID_mdc2,4,&(lvalues[507]),0},
+{"RSA-MDC2","mdc2withRSA",NID_mdc2WithRSA,4,&(lvalues[511]),0},
 {"RC4-40","rc4-40",NID_rc4_40,0,NULL},
 {"RC2-40-CBC","rc2-40-cbc",NID_rc2_40_cbc,0,NULL},
-{"G","givenName",NID_givenName,3,&(lvalues[514]),0},
-{"S","surname",NID_surname,3,&(lvalues[517]),0},
-{"I","initials",NID_initials,3,&(lvalues[520]),0},
-{"UID","uniqueIdentifier",NID_uniqueIdentifier,3,&(lvalues[523]),0},
+{"G","givenName",NID_givenName,3,&(lvalues[515]),0},
+{"S","surname",NID_surname,3,&(lvalues[518]),0},
+{"I","initials",NID_initials,3,&(lvalues[521]),0},
+{"UID","uniqueIdentifier",NID_uniqueIdentifier,3,&(lvalues[524]),0},
 {"crlDistributionPoints","X509v3 CRL Distribution Points",
-	NID_crl_distribution_points,3,&(lvalues[526]),0},
-{"RSA-NP-MD5","md5WithRSA",NID_md5WithRSA,5,&(lvalues[529]),0},
-{"SN","serialNumber",NID_serialNumber,3,&(lvalues[534]),0},
-{"T","title",NID_title,3,&(lvalues[537]),0},
-{"D","description",NID_description,3,&(lvalues[540]),0},
-{"CAST5-CBC","cast5-cbc",NID_cast5_cbc,9,&(lvalues[543]),0},
+	NID_crl_distribution_points,3,&(lvalues[527]),0},
+{"RSA-NP-MD5","md5WithRSA",NID_md5WithRSA,5,&(lvalues[530]),0},
+{"SN","serialNumber",NID_serialNumber,3,&(lvalues[535]),0},
+{"T","title",NID_title,3,&(lvalues[538]),0},
+{"D","description",NID_description,3,&(lvalues[541]),0},
+{"CAST5-CBC","cast5-cbc",NID_cast5_cbc,9,&(lvalues[544]),0},
 {"CAST5-ECB","cast5-ecb",NID_cast5_ecb,0,NULL},
 {"CAST5-CFB","cast5-cfb",NID_cast5_cfb64,0,NULL},
 {"CAST5-OFB","cast5-ofb",NID_cast5_ofb64,0,NULL},
 {"pbeWithMD5AndCast5CBC","pbeWithMD5AndCast5CBC",
-	NID_pbeWithMD5AndCast5_CBC,9,&(lvalues[552]),0},
-{"DSA-SHA1","dsaWithSHA1",NID_dsaWithSHA1,7,&(lvalues[561]),0},
+	NID_pbeWithMD5AndCast5_CBC,9,&(lvalues[553]),0},
+{"DSA-SHA1","dsaWithSHA1",NID_dsaWithSHA1,7,&(lvalues[562]),0},
 {"MD5-SHA1","md5-sha1",NID_md5_sha1,0,NULL},
-{"RSA-SHA1-2","sha1WithRSA",NID_sha1WithRSA,5,&(lvalues[568]),0},
-{"DSA","dsaEncryption",NID_dsa,7,&(lvalues[573]),0},
-{"RIPEMD160","ripemd160",NID_ripemd160,5,&(lvalues[580]),0},
+{"RSA-SHA1-2","sha1WithRSA",NID_sha1WithRSA,5,&(lvalues[569]),0},
+{"DSA","dsaEncryption",NID_dsa,7,&(lvalues[574]),0},
+{"RIPEMD160","ripemd160",NID_ripemd160,5,&(lvalues[581]),0},
 {NULL,NULL,NID_undef,0,NULL},
 {"RSA-RIPEMD160","ripemd160WithRSA",NID_ripemd160WithRSA,6,
-	&(lvalues[585]),0},
-{"RC5-CBC","rc5-cbc",NID_rc5_cbc,8,&(lvalues[591]),0},
+	&(lvalues[586]),0},
+{"RC5-CBC","rc5-cbc",NID_rc5_cbc,8,&(lvalues[592]),0},
 {"RC5-ECB","rc5-ecb",NID_rc5_ecb,0,NULL},
 {"RC5-CFB","rc5-cfb",NID_rc5_cfb64,0,NULL},
 {"RC5-OFB","rc5-ofb",NID_rc5_ofb64,0,NULL},
+{"RLE","run length compression",NID_rle_compression,5,&(lvalues[600]),0},
+{"ZLIB","zlib compression",NID_zlib_compression,5,&(lvalues[605]),0},
 };
 
 static ASN1_OBJECT *sn_objs[NUM_SN]={
@@ -390,6 +395,7 @@
 &(nid_objs[121]),/* "RC5-ECB" */
 &(nid_objs[123]),/* "RC5-OFB" */
 &(nid_objs[117]),/* "RIPEMD160" */
+&(nid_objs[124]),/* "RLE" */
 &(nid_objs[19]),/* "RSA" */
 &(nid_objs[ 7]),/* "RSA-MD2" */
 &(nid_objs[ 8]),/* "RSA-MD5" */
@@ -407,6 +413,7 @@
 &(nid_objs[106]),/* "T" */
 &(nid_objs[102]),/* "UID" */
 &(nid_objs[ 0]),/* "UNDEF" */
+&(nid_objs[125]),/* "ZLIB" */
 &(nid_objs[90]),/* "authorityKeyIdentifier" */
 &(nid_objs[87]),/* "basicConstraints" */
 &(nid_objs[89]),/* "certificatePolicies" */
@@ -487,8 +494,8 @@
 &(nid_objs[116]),/* "dsaEncryption" */
 &(nid_objs[67]),/* "dsaEncryption-old" */
 &(nid_objs[66]),/* "dsaWithSHA" */
-&(nid_objs[70]),/* "dsaWithSHA1" */
 &(nid_objs[113]),/* "dsaWithSHA1" */
+&(nid_objs[70]),/* "dsaWithSHA1-old" */
 &(nid_objs[48]),/* "emailAddress" */
 &(nid_objs[56]),/* "extendedCertificateAttributes" */
 &(nid_objs[99]),/* "givenName" */
@@ -540,6 +547,7 @@
 &(nid_objs[19]),/* "rsa" */
 &(nid_objs[ 6]),/* "rsaEncryption" */
 &(nid_objs[ 1]),/* "rsadsi" */
+&(nid_objs[124]),/* "run length compression" */
 &(nid_objs[105]),/* "serialNumber" */
 &(nid_objs[41]),/* "sha" */
 &(nid_objs[64]),/* "sha1" */
@@ -554,9 +562,11 @@
 &(nid_objs[102]),/* "uniqueIdentifier" */
 &(nid_objs[55]),/* "unstructuredAddress" */
 &(nid_objs[49]),/* "unstructuredName" */
+&(nid_objs[125]),/* "zlib compression" */
 };
 
 static ASN1_OBJECT *obj_objs[NUM_OBJ]={
+&(nid_objs[ 0]),/* OBJ_undef                        0 */
 &(nid_objs[11]),/* OBJ_X500                         2 5 */
 &(nid_objs[12]),/* OBJ_X509                         2 5 4 */
 &(nid_objs[81]),/* OBJ_ld_ce                        2 5 29 */
@@ -586,6 +596,8 @@
 &(nid_objs[19]),/* OBJ_rsa                          2 5 8 1 1 */
 &(nid_objs[96]),/* OBJ_mdc2WithRSA                  2 5 8 3 100 */
 &(nid_objs[95]),/* OBJ_mdc2                         2 5 8 3 101 */
+&(nid_objs[124]),/* OBJ_rle_compression              1 1 1 1 666.1 */
+&(nid_objs[125]),/* OBJ_zlib_compression             1 1 1 1 666.2 */
 &(nid_objs[104]),/* OBJ_md5WithRSA                   1 3 14 3 2 3 */
 &(nid_objs[29]),/* OBJ_des_ecb                      1 3 14 3 2 6 */
 &(nid_objs[31]),/* OBJ_des_cbc                      1 3 14 3 2 7 */
diff --git a/crypto/objects/obj_err.c b/crypto/objects/obj_err.c
index 45206c6..5625306 100644
--- a/crypto/objects/obj_err.c
+++ b/crypto/objects/obj_err.c
@@ -84,8 +84,8 @@
 	{
 	static int init=1;
 
-	if (init);
-		{;
+	if (init)
+		{
 		init=0;
 #ifndef NO_ERR
 		ERR_load_strings(ERR_LIB_OBJ,OBJ_str_functs);
diff --git a/crypto/objects/obj_lib.c b/crypto/objects/obj_lib.c
index 0a9c756..16ff852 100644
--- a/crypto/objects/obj_lib.c
+++ b/crypto/objects/obj_lib.c
@@ -101,7 +101,7 @@
 		memcpy(r->sn,o->sn,i);
 		}
 	r->flags=o->flags|(ASN1_OBJECT_FLAG_DYNAMIC|
-		ASN1_OBJECT_FLAG_DYNAMIC_STRINGS);
+		ASN1_OBJECT_FLAG_DYNAMIC_STRINGS|ASN1_OBJECT_FLAG_DYNAMIC_DATA);
 	return(r);
 err:
 	OBJerr(OBJ_F_OBJ_DUP,ERR_R_MALLOC_FAILURE);
diff --git a/crypto/objects/objects.h b/crypto/objects/objects.h
index e1d555b..8e1a9d3 100644
--- a/crypto/objects/objects.h
+++ b/crypto/objects/objects.h
@@ -66,6 +66,7 @@
 #define SN_undef			"UNDEF"
 #define LN_undef			"undefined"
 #define NID_undef			0
+#define OBJ_undef			0L
 
 #define SN_Algorithm			"Algorithm"
 #define LN_algorithm			"algorithm"
@@ -389,7 +390,7 @@
 #define OBJ_pbeWithSHA1AndRC4		OBJ_pkcs,5L,12L 
 
 #define SN_dsaWithSHA1_2		"DSA-SHA1-old"
-#define LN_dsaWithSHA1_2		"dsaWithSHA1"
+#define LN_dsaWithSHA1_2		"dsaWithSHA1-old"
 #define NID_dsaWithSHA1_2		70
 /* Got this one from 'sdn706r20.pdf' which is actually an NSA document :-) */
 #define OBJ_dsaWithSHA1_2		OBJ_algorithm,27L
@@ -654,13 +655,49 @@
 #define LN_rc5_ofb64			"rc5-ofb"
 #define NID_rc5_ofb64			123
 
+#define SN_rle_compression		"RLE"
+#define LN_rle_compression		"run length compression"
+#define NID_rle_compression		124
+#define OBJ_rle_compression		1L,1L,1L,1L,666L.1L
+
+#define SN_zlib_compression		"ZLIB"
+#define LN_zlib_compression		"zlib compression"
+#define NID_zlib_compression		125
+#define OBJ_zlib_compression		1L,1L,1L,1L,666L.2L
+
 #include "bio.h"
 #include "asn1.h"
 
+#define	OBJ_NAME_TYPE_UNDEF		0x00
+#define	OBJ_NAME_TYPE_MD_METH		0x01
+#define	OBJ_NAME_TYPE_CIPHER_METH	0x02
+#define	OBJ_NAME_TYPE_PKEY_METH		0x03
+#define	OBJ_NAME_TYPE_COMP_METH		0x04
+#define	OBJ_NAME_TYPE_NUM		0x05
+
+#define	OBJ_NAME_ALIAS		0x8000
+
+
+typedef struct obj_name_st
+	{
+	int type;
+	int alias;
+	char *name;
+	char *data;
+	} OBJ_NAME;
+
 #define		OBJ_create_and_add_object(a,b,c) OBJ_create(a,b,c)
 
 #ifndef NOPROTO
 
+int OBJ_NAME_init(void);
+int OBJ_NAME_new_index(unsigned long (*hash_func)(),int (*cmp_func)(),
+	void (*free_func)());
+char *OBJ_NAME_get(char *name,int type);
+int OBJ_NAME_add(char *name,int type,char *data);
+int OBJ_NAME_remove(char *name,int type);
+void OBJ_NAME_cleanup(int type); /* -1 for everything */
+
 ASN1_OBJECT *	OBJ_dup(ASN1_OBJECT *o);
 ASN1_OBJECT *	OBJ_nid2obj(int n);
 char *		OBJ_nid2ln(int n);
@@ -682,6 +719,13 @@
 
 #else
 
+int OBJ_NAME_init();
+int OBJ_NAME_new_index();
+char *OBJ_NAME_get();
+int OBJ_NAME_add();
+int OBJ_NAME_remove();
+void OBJ_NAME_cleanup();
+
 ASN1_OBJECT *	OBJ_dup();
 ASN1_OBJECT *	OBJ_nid2obj();
 char *		OBJ_nid2ln();
diff --git a/crypto/pem/gmon.out b/crypto/pem/gmon.out
new file mode 100644
index 0000000..f26186d
--- /dev/null
+++ b/crypto/pem/gmon.out
Binary files differ
diff --git a/crypto/pem/pem_err.c b/crypto/pem/pem_err.c
index e17fcdb..1bd5c16 100644
--- a/crypto/pem/pem_err.c
+++ b/crypto/pem/pem_err.c
@@ -110,8 +110,8 @@
 	{
 	static int init=1;
 
-	if (init);
-		{;
+	if (init)
+		{
 		init=0;
 #ifndef NO_ERR
 		ERR_load_strings(ERR_LIB_PEM,PEM_str_functs);
diff --git a/crypto/pem/pem_lib.c b/crypto/pem/pem_lib.c
index 7a2c0ad..7908471 100644
--- a/crypto/pem/pem_lib.c
+++ b/crypto/pem/pem_lib.c
@@ -68,7 +68,7 @@
 #include "des.h"
 #endif
 
-char *PEM_version="PEM part of SSLeay 0.9.0b 29-Jun-1998";
+char *PEM_version="PEM part of SSLeay 0.9.1a 06-Jul-1998";
 
 #define MIN_LENGTH	4
 
diff --git a/crypto/perlasm/alpha.pl b/crypto/perlasm/alpha.pl
new file mode 100644
index 0000000..3dac571
--- /dev/null
+++ b/crypto/perlasm/alpha.pl
@@ -0,0 +1,434 @@
+#!/usr/local/bin/perl
+
+package alpha;
+use Carp qw(croak cluck);
+
+$label="100";
+
+$n_debug=0;
+$smear_regs=1;
+$reg_alloc=1;
+
+$align="3";
+$com_start="#";
+
+sub main'asm_init_output { @out=(); }
+sub main'asm_get_output { return(@out); }
+sub main'get_labels { return(@labels); }
+sub main'external_label { push(@labels,@_); }
+
+# General registers
+
+%regs=(	'r0',	'$0',
+	'r1',	'$1',
+	'r2',	'$2',
+	'r3',	'$3',
+	'r4',	'$4',
+	'r5',	'$5',
+	'r6',	'$6',
+	'r7',	'$7',
+	'r8',	'$8',
+	'r9',	'$22',
+	'r10',	'$23',
+	'r11',	'$24',
+	'r12',	'$25',
+	'r13',	'$27',
+	'r14',	'$28',
+	'r15',	'$21', # argc == 5
+	'r16',	'$20', # argc == 4
+	'r17',	'$19', # argc == 3
+	'r18',	'$18', # argc == 2
+	'r19',	'$17', # argc == 1
+	'r20',	'$16', # argc == 0
+	'r21',	'$9',  # save 0
+	'r22',	'$10', # save 1
+	'r23',	'$11', # save 2
+	'r24',	'$12', # save 3
+	'r25',	'$13', # save 4
+	'r26',	'$14', # save 5
+
+	'a0',	'$16',
+	'a1',	'$17',
+	'a2',	'$18',
+	'a3',	'$19',
+	'a4',	'$20',
+	'a5',	'$21',
+
+	's0',	'$9',
+	's1',	'$10',
+	's2',	'$11',
+	's3',	'$12',
+	's4',	'$13',
+	's5',	'$14',
+	'zero',	'$31',
+	'sp',	'$30',
+	);
+
+$main'reg_s0="r21";
+$main'reg_s1="r22";
+$main'reg_s2="r23";
+$main'reg_s3="r24";
+$main'reg_s4="r25";
+$main'reg_s5="r26";
+
+@reg=(  '$0', '$1' ,'$2' ,'$3' ,'$4' ,'$5' ,'$6' ,'$7' ,'$8',
+	'$22','$23','$24','$25','$20','$21','$27','$28');
+
+
+sub main'sub	{ &out3("subq",@_); }
+sub main'add	{ &out3("addq",@_); }
+sub main'mov	{ &out3("bis",$_[0],$_[0],$_[1]); }
+sub main'or	{ &out3("bis",@_); }
+sub main'bis	{ &out3("bis",@_); }
+sub main'br	{ &out1("br",@_); }
+sub main'ld	{ &out2("ldq",@_); }
+sub main'st	{ &out2("stq",@_); }
+sub main'cmpult	{ &out3("cmpult",@_); }
+sub main'cmplt	{ &out3("cmplt",@_); }
+sub main'bgt	{ &out2("bgt",@_); }
+sub main'ble	{ &out2("ble",@_); }
+sub main'blt	{ &out2("blt",@_); }
+sub main'mul	{ &out3("mulq",@_); }
+sub main'muh	{ &out3("umulh",@_); }
+
+$main'QWS=8;
+
+sub main'asm_add
+	{
+	push(@out,@_);
+	}
+
+sub main'asm_finish
+	{
+	&main'file_end();
+	print &main'asm_get_output();
+	}
+
+sub main'asm_init
+	{
+	($type,$fn)=@_;
+	$filename=$fn;
+
+	&main'asm_init_output();
+	&main'comment("Don't even think of reading this code");
+	&main'comment("It was automatically generated by $filename");
+	&main'comment("Which is a perl program used to generate the alpha assember.");
+	&main'comment("eric <eay\@cryptsoft.com>");
+	&main'comment("");
+
+	$filename =~ s/\.pl$//;
+	&main'file($filename);
+	}
+
+sub conv
+	{
+	local($r)=@_;
+	local($v);
+
+	return($regs{$r}) if defined($regs{$r});
+	return($r);
+	}
+
+sub main'QWPw
+	{
+	local($off,$reg)=@_;
+
+	return(&main'QWP($off*8,$reg));
+	}
+
+sub main'QWP
+	{
+	local($off,$reg)=@_;
+
+	$ret="$off(".&conv($reg).")";
+	return($ret);
+	}
+
+sub out3
+	{
+	local($name,$p1,$p2,$p3)=@_;
+
+	$p1=&conv($p1);
+	$p2=&conv($p2);
+	$p3=&conv($p3);
+	push(@out,"\t$name\t");
+	$l=length($p1)+1;
+	push(@out,$p1.",");
+	$ll=3-($l+9)/8;
+	$tmp1=sprintf("\t" x $ll);
+	push(@out,$tmp1);
+
+	$l=length($p2)+1;
+	push(@out,$p2.",");
+	$ll=3-($l+9)/8;
+	$tmp1=sprintf("\t" x $ll);
+	push(@out,$tmp1);
+
+	push(@out,&conv($p3)."\n");
+	}
+
+sub out2
+	{
+	local($name,$p1,$p2,$p3)=@_;
+
+	$p1=&conv($p1);
+	$p2=&conv($p2);
+	push(@out,"\t$name\t");
+	$l=length($p1)+1;
+	push(@out,$p1.",");
+	$ll=3-($l+9)/8;
+	$tmp1=sprintf("\t" x $ll);
+	push(@out,$tmp1);
+
+	push(@out,&conv($p2)."\n");
+	}
+
+sub out1
+	{
+	local($name,$p1)=@_;
+
+	$p1=&conv($p1);
+	push(@out,"\t$name\t".$p1."\n");
+	}
+
+sub out0
+	{
+	push(@out,"\t$_[0]\n");
+	}
+
+sub main'file
+	{
+	local($file)=@_;
+
+	local($tmp)=<<"EOF";
+ # DEC Alpha assember
+ # Generated from perl scripts contains in SSLeay
+	.file	1 "$file.s"
+	.set noat
+EOF
+	push(@out,$tmp);
+	}
+
+sub main'function_begin
+	{
+	local($func)=@_;
+
+print STDERR "$func\n";
+	local($tmp)=<<"EOF";
+	.text
+	.align $align
+	.globl $func
+	.ent $func
+${func}:
+${func}..ng:
+	.frame \$30,0,\$26,0
+	.prologue 0
+EOF
+	push(@out,$tmp);
+	$stack=0;
+	}
+
+sub main'function_end
+	{
+	local($func)=@_;
+
+	local($tmp)=<<"EOF";
+	ret	\$31,(\$26),1
+	.end $func
+EOF
+	push(@out,$tmp);
+	$stack=0;
+	%label=();
+	}
+
+sub main'function_end_A
+	{
+	local($func)=@_;
+
+	local($tmp)=<<"EOF";
+	ret	\$31,(\$26),1
+EOF
+	push(@out,$tmp);
+	}
+
+sub main'function_end_B
+	{
+	local($func)=@_;
+
+	$func=$under.$func;
+
+	push(@out,"\t.end $func\n");
+	$stack=0;
+	%label=();
+	}
+
+sub main'wparam
+	{
+	local($num)=@_;
+
+	if ($num < 6)
+		{
+		$num=20-$num;
+		return("r$num");
+		}
+	else
+		{ return(&main'QWP($stack+$num*8,"sp")); }
+	}
+
+sub main'stack_push
+	{
+	local($num)=@_;
+	$stack+=$num*8;
+	&main'sub("sp",$num*8,"sp");
+	}
+
+sub main'stack_pop
+	{
+	local($num)=@_;
+	$stack-=$num*8;
+	&main'add("sp",$num*8,"sp");
+	}
+
+sub main'swtmp
+	{
+	return(&main'QWP(($_[0])*8,"sp"));
+	}
+
+# Should use swtmp, which is above sp.  Linix can trash the stack above esp
+#sub main'wtmp
+#	{
+#	local($num)=@_;
+#
+#	return(&main'QWP(-($num+1)*4,"esp","",0));
+#	}
+
+sub main'comment
+	{
+	foreach (@_)
+		{
+		if (/^\s*$/)
+			{ push(@out,"\n"); }
+		else
+			{ push(@out,"\t$com_start $_ $com_end\n"); }
+		}
+	}
+
+sub main'label
+	{
+	if (!defined($label{$_[0]}))
+		{
+		$label{$_[0]}=$label;
+		$label++;
+		}
+	return('$'.$label{$_[0]});
+	}
+
+sub main'set_label
+	{
+	if (!defined($label{$_[0]}))
+		{
+		$label{$_[0]}=$label;
+		$label++;
+		}
+#	push(@out,".align $align\n") if ($_[1] != 0);
+	push(@out,'$'."$label{$_[0]}:\n");
+	}
+
+sub main'file_end
+	{
+	}
+
+sub main'data_word
+	{
+	push(@out,"\t.long $_[0]\n");
+	}
+
+@pool_free=();
+@pool_taken=();
+$curr_num=0;
+$max=0;
+
+sub main'init_pool
+	{
+	local($args)=@_;
+	local($i);
+
+	@pool_free=();
+	for ($i=(14+(6-$args)); $i >= 0; $i--)
+		{
+		push(@pool_free,"r$i");
+		}
+	print STDERR "START :register pool:@pool_free\n";
+	$curr_num=$max=0;
+	}
+
+sub main'fin_pool
+	{
+	printf STDERR "END %2d:register pool:@pool_free\n",$max;
+	}
+
+sub main'GR
+	{
+	local($r)=@_;
+	local($i,@n,$_);
+
+	foreach (@pool_free)
+		{
+		if ($r ne $_)
+			{ push(@n,$_); }
+		else
+			{
+			$curr_num++;
+			$max=$curr_num if ($curr_num > $max);
+			}
+		}
+	@pool_free=@n;
+print STDERR "GR:@pool_free\n" if $reg_alloc;
+	return(@_);
+	}
+
+sub main'NR
+	{
+	local($num)=@_;
+	local(@ret);
+
+	$num=1 if $num == 0;
+	($#pool_free >= ($num-1)) || croak "out of registers: want $num, have @pool_free";
+	while ($num > 0)
+		{
+		push(@ret,pop @pool_free);
+		$curr_num++;
+		$max=$curr_num if ($curr_num > $max);
+		$num--
+		}
+	print STDERR "nr @ret\n" if $n_debug;
+print STDERR "NR:@pool_free\n" if $reg_alloc;
+	return(@ret);
+
+	}
+
+sub main'FR
+	{
+	local(@r)=@_;
+	local(@a,$v,$w);
+
+	print STDERR "fr @r\n" if $n_debug;
+#	cluck "fr @r";
+	for $w (@pool_free)
+		{
+		foreach $v (@r)
+			{
+			croak "double register free of $v (@pool_free)" if $w eq $v;
+			}
+		}
+	foreach $v (@r)
+		{
+		croak "bad argument to FR" if ($v !~ /^r\d+$/);
+		if ($smear_regs)
+			{ unshift(@pool_free,$v); }
+		else	{ push(@pool_free,$v); }
+		$curr_num--;
+		}
+print STDERR "FR:@pool_free\n" if $reg_alloc;
+	}
+1;
diff --git a/crypto/perlasm/f b/crypto/perlasm/f
new file mode 100644
index 0000000..80da809
--- /dev/null
+++ b/crypto/perlasm/f
@@ -0,0 +1,19 @@
+sub out3
+	{
+	local($name,$p1,$p2,$p3)=@_;
+
+	push(@out,"\t$name\t");
+	$l=length($p1)+1;
+	push(@out,$p1.",");
+	$ll=4-($l+9)/8;
+	$tmp1=sprintf("\t" x $ll);
+	push(@out,$tmp1);
+
+	$l=length($p2)+1;
+	push(@out,$p2.",");
+	$ll=4-($l+9)/8;
+	$tmp1=sprintf("\t" x $ll);
+	push(@out,$tmp1);
+
+	push(@out,&conv($p3)."\n");
+	}
diff --git a/crypto/pkcs7/bio_ber.c b/crypto/pkcs7/bio_ber.c
new file mode 100644
index 0000000..df4d9a5
--- /dev/null
+++ b/crypto/pkcs7/bio_ber.c
@@ -0,0 +1,479 @@
+/* crypto/evp/bio_ber.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include "cryptlib.h"
+#include "buffer.h"
+#include "evp.h"
+
+#ifndef NOPROTO
+static int ber_write(BIO *h,char *buf,int num);
+static int ber_read(BIO *h,char *buf,int size);
+/*static int ber_puts(BIO *h,char *str); */
+/*static int ber_gets(BIO *h,char *str,int size); */
+static long ber_ctrl(BIO *h,int cmd,long arg1,char *arg2);
+static int ber_new(BIO *h);
+static int ber_free(BIO *data);
+#else
+static int ber_write();
+static int ber_read();
+/*static int ber_puts(); */
+/*static int ber_gets(); */
+static long ber_ctrl();
+static int ber_new();
+static int ber_free();
+#endif
+
+#define BER_BUF_SIZE	(32)
+
+/* This is used to hold the state of the BER objects being read. */
+typedef struct ber_struct
+	{
+	int tag;
+	int class;
+	long length;
+	int inf;
+	int num_left;
+	int depth;
+	} BER_CTX;
+
+typedef struct bio_ber_struct
+	{
+	int tag;
+	int class;
+	long length;
+	int inf;
+
+	/* most of the following are used when doing non-blocking IO */
+	/* reading */
+	long num_left;	/* number of bytes still to read/write in block */
+	int depth;	/* used with idefinite encoding. */
+	int finished;	/* No more read data */
+
+	/* writting */ 
+	char *w_addr;
+	int w_offset;
+	int w_left;
+
+	int buf_len;
+	int buf_off;
+	unsigned char buf[BER_BUF_SIZE];
+	} BIO_BER_CTX;
+
+static BIO_METHOD methods_ber=
+	{
+	BIO_TYPE_CIPHER,"cipher",
+	ber_write,
+	ber_read,
+	NULL, /* ber_puts, */
+	NULL, /* ber_gets, */
+	ber_ctrl,
+	ber_new,
+	ber_free,
+	};
+
+BIO_METHOD *BIO_f_ber()
+	{
+	return(&methods_ber);
+	}
+
+static int ber_new(bi)
+BIO *bi;
+	{
+	BIO_BER_CTX *ctx;
+
+	ctx=(BIO_BER_CTX *)Malloc(sizeof(BIO_BER_CTX));
+	if (ctx == NULL) return(0);
+
+	memset((char *)ctx,0,sizeof(BIO_BER_CTX));
+
+	bi->init=0;
+	bi->ptr=(char *)ctx;
+	bi->flags=0;
+	return(1);
+	}
+
+static int ber_free(a)
+BIO *a;
+	{
+	BIO_BER_CTX *b;
+
+	if (a == NULL) return(0);
+	b=(BIO_BER_CTX *)a->ptr;
+	memset(a->ptr,0,sizeof(BIO_BER_CTX));
+	Free(a->ptr);
+	a->ptr=NULL;
+	a->init=0;
+	a->flags=0;
+	return(1);
+	}
+
+int bio_ber_get_header(bio,ctx)
+BIO *bio;
+BIO_BER_CTX *ctx;
+	{
+	char buf[64];
+	int i,j,n;
+	int ret;
+	unsigned char *p;
+	unsigned long length
+	int tag;
+	int class;
+	long max;
+
+	BIO_clear_retry_flags(b);
+
+	/* Pack the buffer down if there is a hole at the front */
+	if (ctx->buf_off != 0)
+		{
+		p=ctx->buf;
+		j=ctx->buf_off;
+		n=ctx->buf_len-j;
+		for (i=0; i<n; i++)
+			{
+			p[0]=p[j];
+			p++;
+			}
+		ctx->buf_len-j;
+		ctx->buf_off=0;
+		}
+
+	/* If there is more room, read some more data */
+	i=BER_BUF_SIZE-ctx->buf_len;
+	if (i)
+		{
+		i=BIO_read(bio->next_bio,&(ctx->buf[ctx->buf_len]),i);
+		if (i <= 0)
+			{
+			BIO_copy_next_retry(b);
+			return(i);
+			}
+		else
+			ctx->buf_len+=i;
+		}
+
+	max=ctx->buf_len;
+	p=ctx->buf;
+	ret=ASN1_get_object(&p,&length,&tag,&class,max);
+
+	if (ret & 0x80)
+		{
+		if ((ctx->buf_len < BER_BUF_SIZE) &&
+			(ERR_GET_REASON(ERR_peek_error()) == ASN1_R_TOO_LONG))
+			{
+			ERR_get_error(); /* clear the error */
+			BIO_set_retry_read(b);
+			}
+		return(-1);
+		}
+
+	/* We have no error, we have a header, so make use of it */
+
+	if ((ctx->tag  >= 0) && (ctx->tag != tag))
+		{
+		BIOerr(BIO_F_BIO_BER_GET_HEADER,BIO_R_TAG_MISMATCH);
+		sprintf(buf,"tag=%d, got %d",ctx->tag,tag);
+		ERR_add_error_data(1,buf);
+		return(-1);
+		}
+	if (ret & 0x01)
+	if (ret & V_ASN1_CONSTRUCTED)
+	}
+	
+static int ber_read(b,out,outl)
+BIO *b;
+char *out;
+int outl;
+	{
+	int ret=0,i,n;
+	BIO_BER_CTX *ctx;
+
+	BIO_clear_retry_flags(b);
+
+	if (out == NULL) return(0);
+	ctx=(BIO_BER_CTX *)b->ptr;
+
+	if ((ctx == NULL) || (b->next_bio == NULL)) return(0);
+
+	if (ctx->finished) return(0);
+
+again:
+	/* First see if we are half way through reading a block */
+	if (ctx->num_left > 0)
+		{
+		if (ctx->num_left < outl)
+			n=ctx->num_left;
+		else
+			n=outl;
+		i=BIO_read(b->next_bio,out,n);
+		if (i <= 0)
+			{
+			BIO_copy_next_retry(b);
+			return(i);
+			}
+		ctx->num_left-=i;
+		outl-=i;
+		ret+=i;
+		if (ctx->num_left <= 0)
+			{
+			ctx->depth--;
+			if (ctx->depth <= 0)
+				ctx->finished=1;
+			}
+		if (outl <= 0)
+			return(ret);
+		else
+			goto again;
+		}
+	else	/* we need to read another BER header */
+		{
+		}
+	}
+
+static int ber_write(b,in,inl)
+BIO *b;
+char *in;
+int inl;
+	{
+	int ret=0,n,i;
+	BIO_ENC_CTX *ctx;
+
+	ctx=(BIO_ENC_CTX *)b->ptr;
+	ret=inl;
+
+	BIO_clear_retry_flags(b);
+	n=ctx->buf_len-ctx->buf_off;
+	while (n > 0)
+		{
+		i=BIO_write(b->next_bio,&(ctx->buf[ctx->buf_off]),n);
+		if (i <= 0)
+			{
+			BIO_copy_next_retry(b);
+			return(i);
+			}
+		ctx->buf_off+=i;
+		n-=i;
+		}
+	/* at this point all pending data has been written */
+
+	if ((in == NULL) || (inl <= 0)) return(0);
+
+	ctx->buf_off=0;
+	while (inl > 0)
+		{
+		n=(inl > ENC_BLOCK_SIZE)?ENC_BLOCK_SIZE:inl;
+		EVP_CipherUpdate(&(ctx->cipher),
+			(unsigned char *)ctx->buf,&ctx->buf_len,
+			(unsigned char *)in,n);
+		inl-=n;
+		in+=n;
+
+		ctx->buf_off=0;
+		n=ctx->buf_len;
+		while (n > 0)
+			{
+			i=BIO_write(b->next_bio,&(ctx->buf[ctx->buf_off]),n);
+			if (i <= 0)
+				{
+				BIO_copy_next_retry(b);
+				return(i);
+				}
+			n-=i;
+			ctx->buf_off+=i;
+			}
+		ctx->buf_len=0;
+		ctx->buf_off=0;
+		}
+	BIO_copy_next_retry(b);
+	return(ret);
+	}
+
+static long ber_ctrl(b,cmd,num,ptr)
+BIO *b;
+int cmd;
+long num;
+char *ptr;
+	{
+	BIO *dbio;
+	BIO_ENC_CTX *ctx,*dctx;
+	long ret=1;
+	int i;
+
+	ctx=(BIO_ENC_CTX *)b->ptr;
+
+	switch (cmd)
+		{
+	case BIO_CTRL_RESET:
+		ctx->ok=1;
+		ctx->finished=0;
+		EVP_CipherInit(&(ctx->cipher),NULL,NULL,NULL,
+			ctx->cipher.berrypt);
+		ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
+		break;
+	case BIO_CTRL_EOF:	/* More to read */
+		if (ctx->cont <= 0)
+			ret=1;
+		else
+			ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
+		break;
+	case BIO_CTRL_WPENDING:
+		ret=ctx->buf_len-ctx->buf_off;
+		if (ret <= 0)
+			ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
+		break;
+	case BIO_CTRL_PENDING: /* More to read in buffer */
+		ret=ctx->buf_len-ctx->buf_off;
+		if (ret <= 0)
+			ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
+		break;
+	case BIO_CTRL_FLUSH:
+		/* do a final write */
+again:
+		while (ctx->buf_len != ctx->buf_off)
+			{
+			i=ber_write(b,NULL,0);
+			if (i < 0)
+				{
+				ret=i;
+				break;
+				}
+			}
+
+		if (!ctx->finished)
+			{
+			ctx->finished=1;
+			ctx->buf_off=0;
+			ret=EVP_CipherFinal(&(ctx->cipher),
+				(unsigned char *)ctx->buf,
+				&(ctx->buf_len));
+			ctx->ok=(int)ret;
+			if (ret <= 0) break;
+
+			/* push out the bytes */
+			goto again;
+			}
+		
+		/* Finally flush the underlying BIO */
+		ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
+		break;
+	case BIO_C_GET_CIPHER_STATUS:
+		ret=(long)ctx->ok;
+		break;
+	case BIO_C_DO_STATE_MACHINE:
+		BIO_clear_retry_flags(b);
+		ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
+		BIO_copy_next_retry(b);
+		break;
+
+	case BIO_CTRL_DUP:
+		dbio=(BIO *)ptr;
+		dctx=(BIO_ENC_CTX *)dbio->ptr;
+		memcpy(&(dctx->cipher),&(ctx->cipher),sizeof(ctx->cipher));
+		dbio->init=1;
+		break;
+	default:
+		ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
+		break;
+		}
+	return(ret);
+	}
+
+/*
+void BIO_set_cipher_ctx(b,c)
+BIO *b;
+EVP_CIPHER_ctx *c;
+	{
+	if (b == NULL) return;
+
+	if ((b->callback != NULL) &&
+		(b->callback(b,BIO_CB_CTRL,(char *)c,BIO_CTRL_SET,e,0L) <= 0))
+		return;
+
+	b->init=1;
+	ctx=(BIO_ENC_CTX *)b->ptr;
+	memcpy(ctx->cipher,c,sizeof(EVP_CIPHER_CTX));
+	
+	if (b->callback != NULL)
+		b->callback(b,BIO_CB_CTRL,(char *)c,BIO_CTRL_SET,e,1L);
+	}
+*/
+
+void BIO_set_cipher(b,c,k,i,e)
+BIO *b;
+EVP_CIPHER *c;
+unsigned char *k;
+unsigned char *i;
+int e;
+	{
+	BIO_ENC_CTX *ctx;
+
+	if (b == NULL) return;
+
+	if ((b->callback != NULL) &&
+		(b->callback(b,BIO_CB_CTRL,(char *)c,BIO_CTRL_SET,e,0L) <= 0))
+		return;
+
+	b->init=1;
+	ctx=(BIO_ENC_CTX *)b->ptr;
+	EVP_CipherInit(&(ctx->cipher),c,k,i,e);
+	
+	if (b->callback != NULL)
+		b->callback(b,BIO_CB_CTRL,(char *)c,BIO_CTRL_SET,e,1L);
+	}
+
diff --git a/crypto/pkcs7/build b/crypto/pkcs7/build
new file mode 100755
index 0000000..05eb70f
--- /dev/null
+++ b/crypto/pkcs7/build
@@ -0,0 +1,5 @@
+#!/bin/sh -x
+
+make
+gcc -I../../include -g -o enc enc.c ../../libcrypto.a
+gcc -I../../include -g -o dec dec.c ../../libcrypto.a
diff --git a/crypto/pkcs7/dec.c b/crypto/pkcs7/dec.c
new file mode 100644
index 0000000..2622cbd
--- /dev/null
+++ b/crypto/pkcs7/dec.c
@@ -0,0 +1,245 @@
+/* crypto/pkcs7/verify.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 "asn1.h"
+#include "bio.h"
+#include "x509.h"
+#include "pem.h"
+
+int verify_callback(int ok, X509_STORE_CTX *ctx);
+
+BIO *bio_err=NULL;
+
+main(argc,argv)
+int argc;
+char *argv[];
+	{
+	BIO *in;
+	X509 *x509,*x;
+	EVP_PKEY *pkey;
+	PKCS7 *p7;
+	PKCS7_SIGNED *s;
+	PKCS7_SIGNER_INFO *si;
+	PKCS7_ISSUER_AND_SERIAL *ias;
+	X509_STORE_CTX cert_ctx;
+	X509_STORE *cert_store=NULL;
+	X509_LOOKUP *lookup=NULL;
+	BIO *data,*detached=NULL,*p7bio=NULL;
+	char buf[1024*4];
+	unsigned char *p,*pp;
+	int i,j,printit=0;
+	STACK *sk;
+
+	SSLeay_add_all_algorithms();
+	bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
+	EVP_add_digest(EVP_sha1());
+	EVP_add_cipher(EVP_des_ede3_cbc());
+
+        if ((in=BIO_new_file("server.pem","r")) == NULL) goto err;
+        if ((x509=PEM_read_bio_X509(in,NULL,NULL)) == NULL) goto err;
+        BIO_reset(in);
+        if ((pkey=PEM_read_bio_PrivateKey(in,NULL,NULL)) == NULL) goto err;
+        BIO_free(in);
+
+	data=BIO_new(BIO_s_file());
+again:
+	pp=NULL;
+	while (argc > 1)
+		{
+		argc--;
+		argv++;
+		if (strcmp(argv[0],"-p") == 0)
+			{
+			printit=1;
+			}
+		else if ((strcmp(argv[0],"-d") == 0) && (argc >= 2))
+			{
+			detached=BIO_new(BIO_s_file());
+			if (!BIO_read_filename(detached,argv[1]))
+				goto err;
+			argc--;
+			argv++;
+			}
+		else
+			{
+			pp=argv[0];
+			if (!BIO_read_filename(data,argv[0]))
+				goto err;
+			}
+		}
+
+	if (pp == NULL)
+		BIO_set_fp(data,stdin,BIO_NOCLOSE);
+
+
+	/* Load the PKCS7 object from a file */
+	if ((p7=PEM_read_bio_PKCS7(data,NULL,NULL)) == NULL) goto err;
+
+
+
+	/* This stuff is being setup for certificate verification.
+	 * When using SSL, it could be replaced with a 
+	 * cert_stre=SSL_CTX_get_cert_store(ssl_ctx); */
+	cert_store=X509_STORE_new();
+	X509_STORE_set_default_paths(cert_store);
+	X509_STORE_load_locations(cert_store,NULL,"../../certs");
+	X509_STORE_set_verify_cb_func(cert_store,verify_callback);
+
+	ERR_clear_error();
+
+	/* We need to process the data */
+	/* We cannot support detached encryption */
+	p7bio=PKCS7_dataDecode(p7,pkey,detached,cert_store);
+	
+	if (p7bio == NULL)
+		{
+		printf("problems decoding\n");
+		goto err;
+		}
+
+	/* We now have to 'read' from p7bio to calculate digests etc. */
+	for (;;)
+		{
+		i=BIO_read(p7bio,buf,sizeof(buf));
+		/* print it? */
+		if (i <= 0) break;
+		write(fileno(stdout),buf,i);
+		}
+
+	/* We can now verify signatures */
+	sk=PKCS7_get_signer_info(p7);
+	if (sk == NULL)
+		{
+		printf("there are no signatures on this data\n");
+		}
+	else
+		{
+		/* Ok, first we need to, for each subject entry,
+		 * see if we can verify */
+		ERR_clear_error();
+		for (i=0; i<sk_num(sk); i++)
+			{
+			si=(PKCS7_SIGNER_INFO *)sk_value(sk,i);
+			i=PKCS7_dataVerify(cert_store,&cert_ctx,p7bio,p7,si);
+			if (i <= 0)
+				goto err;
+			else
+				fprintf(stderr,"Signature verified\n");
+			}
+		}
+	X509_STORE_free(cert_store);
+
+	exit(0);
+err:
+	ERR_load_crypto_strings();
+	ERR_print_errors_fp(stderr);
+	exit(1);
+	}
+
+/* should be X509 * but we can just have them as char *. */
+int verify_callback(ok, ctx)
+int ok;
+X509_STORE_CTX *ctx;
+	{
+	char buf[256];
+	X509 *err_cert;
+	int err,depth;
+
+	err_cert=X509_STORE_CTX_get_current_cert(ctx);
+	err=	X509_STORE_CTX_get_error(ctx);
+	depth=	X509_STORE_CTX_get_error_depth(ctx);
+
+	X509_NAME_oneline(X509_get_subject_name(err_cert),buf,256);
+	BIO_printf(bio_err,"depth=%d %s\n",depth,buf);
+	if (!ok)
+		{
+		BIO_printf(bio_err,"verify error:num=%d:%s\n",err,
+			X509_verify_cert_error_string(err));
+		if (depth < 6)
+			{
+			ok=1;
+			X509_STORE_CTX_set_error(ctx,X509_V_OK);
+			}
+		else
+			{
+			ok=0;
+			X509_STORE_CTX_set_error(ctx,X509_V_ERR_CERT_CHAIN_TOO_LONG);
+			}
+		}
+	switch (ctx->error)
+		{
+	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
+		X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert),buf,256);
+		BIO_printf(bio_err,"issuer= %s\n",buf);
+		break;
+	case X509_V_ERR_CERT_NOT_YET_VALID:
+	case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
+		BIO_printf(bio_err,"notBefore=");
+		ASN1_UTCTIME_print(bio_err,X509_get_notBefore(ctx->current_cert));
+		BIO_printf(bio_err,"\n");
+		break;
+	case X509_V_ERR_CERT_HAS_EXPIRED:
+	case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
+		BIO_printf(bio_err,"notAfter=");
+		ASN1_UTCTIME_print(bio_err,X509_get_notAfter(ctx->current_cert));
+		BIO_printf(bio_err,"\n");
+		break;
+		}
+	BIO_printf(bio_err,"verify return:%d\n",ok);
+	return(ok);
+	}
diff --git a/crypto/pkcs7/des.pem b/crypto/pkcs7/des.pem
new file mode 100644
index 0000000..62d1657
--- /dev/null
+++ b/crypto/pkcs7/des.pem
@@ -0,0 +1,15 @@
+
+MIAGCSqGSIb3DQEHA6CAMIACAQAxggHmMIHwAgEAMIGZMIGSMQswCQYDVQQGEwJBVTETMBEG
+A1UECBMKUXVlZW5zbGFuZDERMA8GA1UEBxMIQnJpc2JhbmUxGjAYBgNVBAoTEUNyeXB0c29m
+dCBQdHkgTHRkMSIwIAYDVQQLExlERU1PTlNUUkFUSU9OIEFORCBURVNUSU5HMRswGQYDVQQD
+ExJERU1PIFpFUk8gVkFMVUUgQ0ECAgR+MA0GCSqGSIb3DQEBAQUABEC2vXI1xQDW6lUHM3zQ
+/9uBEBOO5A3TtkrklAXq7v01gsIC21t52qSk36REXY+slhNZ0OQ349tgkTsoETHFLoEwMIHw
+AgEAMIGZMIGSMQswCQYDVQQGEwJBVTETMBEGA1UECBMKUXVlZW5zbGFuZDERMA8GA1UEBxMI
+QnJpc2JhbmUxGjAYBgNVBAoTEUNyeXB0c29mdCBQdHkgTHRkMSIwIAYDVQQLExlERU1PTlNU
+UkFUSU9OIEFORCBURVNUSU5HMRswGQYDVQQDExJERU1PIFpFUk8gVkFMVUUgQ0ECAgR9MA0G
+CSqGSIb3DQEBAQUABEB8ujxbabxXUYJhopuDm3oDq4JNqX6Io4p3ro+ShqfIndsXTZ1v5a2N
+WtLLCWlHn/habjBwZ/DgQgcKASbZ7QxNMIAGCSqGSIb3DQEHATAaBggqhkiG9w0DAjAOAgIA
+oAQIbsL5v1wX98KggAQoAaJ4WHm68fXY1WE5OIjfVBIDpO1K+i8dmKhjnAjrjoyZ9Bwc8rDL
+lgQg4CXb805h5xl+GfvSwUaHJayte1m2mcOhs3J2YyqbQ+MEIMIiJQccmhO3oDKm36CFvYR8
+5PjpclVcZyX2ngbwPFMnBAgy0clOAE6UKAAAAAAAAAAAAAA=
+
diff --git a/crypto/pkcs7/enc.c b/crypto/pkcs7/enc.c
index 625a7c2..8c3f937 100644
--- a/crypto/pkcs7/enc.c
+++ b/crypto/pkcs7/enc.c
@@ -73,10 +73,10 @@
 	BIO *data,*p7bio;
 	char buf[1024*4];
 	int i,j;
-	int nodetach=0;
+	int nodetach=1;
 
 	EVP_add_digest(EVP_sha1());
-	EVP_add_cipher(EVP_des_cbc());
+	EVP_add_cipher(EVP_des_ede3_cbc());
 
 	data=BIO_new(BIO_s_file());
 again:
@@ -105,7 +105,7 @@
 	 
 	if (PKCS7_add_signature(p7,x509,pkey,EVP_sha1()) == NULL) goto err;
 
-	if (!PKCS7_set_cipher(p7,EVP_des_cbc())) goto err;
+	if (!PKCS7_set_cipher(p7,EVP_des_ede3_cbc())) goto err;
 	if (PKCS7_add_recipient(p7,x509) == NULL) goto err;
 
 	/* we may want to add more */
@@ -129,7 +129,7 @@
 		}
 	BIO_flush(p7bio);
 
-	if (!PKCS7_dataSign(p7,p7bio)) goto err;
+	if (!PKCS7_dataFinal(p7,p7bio)) goto err;
 	BIO_free(p7bio);
 
 	PEM_write_PKCS7(stdout,p7);
diff --git a/crypto/pkcs7/es1.pem b/crypto/pkcs7/es1.pem
new file mode 100644
index 0000000..47112a2
--- /dev/null
+++ b/crypto/pkcs7/es1.pem
@@ -0,0 +1,66 @@
+-----BEGIN PKCS7-----
+MIAGCSqGSIb3DQEHA6CAMIACAQAxggHmMIHwAgEAMIGZMIGSMQswCQYDVQQGEwJBVTETMBEG
+A1UECBMKUXVlZW5zbGFuZDERMA8GA1UEBxMIQnJpc2JhbmUxGjAYBgNVBAoTEUNyeXB0c29m
+dCBQdHkgTHRkMSIwIAYDVQQLExlERU1PTlNUUkFUSU9OIEFORCBURVNUSU5HMRswGQYDVQQD
+ExJERU1PIFpFUk8gVkFMVUUgQ0ECAgRuMA0GCSqGSIb3DQEBAQUABEDWak0y/5XZJhQJeCLo
+KECcHXkTEbjzYkYNHIinbiPmRK4QbNfs9z2mA3z/c2ykQ4eAqFR2jyNrUMN/+I5XEiv6MIHw
+AgEAMIGZMIGSMQswCQYDVQQGEwJBVTETMBEGA1UECBMKUXVlZW5zbGFuZDERMA8GA1UEBxMI
+QnJpc2JhbmUxGjAYBgNVBAoTEUNyeXB0c29mdCBQdHkgTHRkMSIwIAYDVQQLExlERU1PTlNU
+UkFUSU9OIEFORCBURVNUSU5HMRswGQYDVQQDExJERU1PIFpFUk8gVkFMVUUgQ0ECAgR9MA0G
+CSqGSIb3DQEBAQUABEAWg9+KgtCjc77Jdj1Ve4wGgHjVHbbSYEA1ZqKFDoi15vSr9hfpHmC4
+ycZzcRo16JkTfolefiHZzmyjVz94vSN6MIAGCSqGSIb3DQEHATAaBggqhkiG9w0DAjAOAgIA
+oAQI7X4Tk4mcbV6ggASBsHl1mCaJ3RhXWlNPCgCRU53d7M5x6TDZRkvwdtdvW96m1lupT03F
+XtonkBqk7oMkH7kGfs5/REQOPjx0QE2Ixmgt1W3szum82EZwA7pZNppcraK7W/odw/7bYZO+
+II3HPmRklE2N9qiu1LPaPUsnYogkO6SennyeL5tZ382vBweL/8pnG0qsbT1OBb65v+llnsjT
+pa1T/p+fIx/iJJGE6K9fYFokC6gXLQ6ozXRdOu5oBDB8mPCYYvAqKycidM/MrGGUkpEtS4f0
+lS31PwQi5YTim8Ig3/TOwVpPX32i46FTuEIEIMHkD/OvpfwCCzXUHHJnKnKUAUvIsSY3vGBs
+8ezpUDfBBBj9LHDy32hZ2tQilkDefP5VM2LLdrWgamYEgfiyITQvn08Ul5lQOQxbFKBheFq5
+otCCN4MR+w5eq12xQu6y+f9z0159ag2ru87D0lLtUtXXtCELbO1nUkT2sJ0k/iDs9TOXr6Cx
+go1XKYho83hlkXYiCteVizdAbgVGNsNRD4wtIdajsorET/LuJECgp11YeL9w1dlDB0HLEZfi
+XCsUphH4jGagba3hDeUSibnjSiJlN0ukfuQurBBbI2UkBAujiEAubKPn7C1FZJRSw6CPPX5t
+KEpmcqT1JNk6LO8Js6/1sCmmBh1VGCy1+EuTI9J1p7Dagf4nQ8cHitoCRpHuKZlFHnZyv7tw
+Rn/KOhHaYP2VzAh40gQIvKMAAWh9oFsEEIMwIoOmLwLH5wf+8QdbDhoECH8HwZt9a12dBAjL
+r4j2zlvtfgQIt7nmEM3wz1EECKlc3EIy1irCBBCAKINcermK3A+jI6ISN2RzBFA3dsh/xwMu
+l61aWMBBZzEz/SF92k6n35KZhCC0d6fIVC/1WMv0fnCwQ8oEDynSre216VEFiYKBaQLJe5o/
+mTAxC7Ht3goXnuc+i1FItOkLrgRI/wyvTICEn2WsNZiMADnGaee2bqPnUopo+VMGexJEtCPk
+l0ZNlDJGquPDkpUwaEtecVZzCNyVPYyyF4J/l8rmGDhDdYUIC8IKBEg/ip/E0BuubBLWVbv+
+HRl4QrnGpyCyeXRXXK603QP3sT1Zbbm1v5pI/loOhVHi724LmtXHSyp5qv9MDcxE1PoX10LY
+gBRtlwwESPeCF8bK5jk4xIQMhK5NMHj1Y1KQWTZ9NGITBL4hjRq2qp4Qk5GIpGgOVPopAuCo
+TIyPikpqBRNtLSPRSsDs6QPUPzWBh6JgxwRQblnDKKUkxUcnJiD4i9QtGa/ZabMn4KxtNOBL
+5JSh1nJkaLXCZY070131WWPAByLcd5TiXq8x84pmzV5NNk4tiMpoXhJNsx8e4rskQQlKd6ME
+SCe2eYDHKcKPX3WJbUzhrJSQ92/aWnI2iUY8WQ+kSNyiZ2QUjyuUg9Z66g/0d2STlvPOBHT/
+y5ODP2CwbcWX4QmCbUc9TT66fQRIrRVuwvtOfnUueyGgYhJ3HpAJfVaB/7kap5bj7Fi/azW4
+9JDfd1bC/W9h0Kyk7RO2gxvE0hIHc26mZJHTm9MNP5D328MnM2MdBEjKjQBtgrp+lFIii7MP
+nGHFTKUkG4WAIZJCf/CsT+p6/SW0qG71Me/YcSw5STB24j+a+HgMV8RVIeUlkP4z0IWWrSoB
+Gh4d/Z0EUMCVHs/HZ/bWgiyhtHpvuVAzidm8D81p1LJ5BQX5/5f/m+q5+fS/npL27dTEbNqs
+LSB6ij3MZAi7LwHWpTn9zWnDajCMEj9vlaV7mcKtHK5iBEg85agFi1h3MvicqLtoFe5hVv9T
+tG0j6CRkjkixPzivltlrf44KHv14gLM0XJxCGyq7vd3l8QYr3+9at0zNnX/yqTiBnsnE5dUE
+SIgrYuz87M2gi/ER9PcDoTtONH3+CkcqVy03q/Sj8cVWD/b1KgEhqnNOfc8Ak9PctyR/ItcR
+8Me5XVn1GJKkQJk4O29fxvgNoAQIrIESvUWGshAEQByXiFoFTDUByjTlgjcy77H1lrH+y3P/
+wAInJjJAut9kCNyGJV0PA4kdPB5USWltuO6t8gk4Pd2YBMl09zqUWkAEUCjFrtZ3mapjcGZI
+uQTASKR5LSjXoWxTT5gae/+64MerF/oCEeO3ehRTpjnPrsiRDo0rWIQTaj9+Nro8Z2xtWstw
+RnfoAHIxV1lEamPwjsceBEi2SD9hiifFeO5ECiVoaE1FdXUXhU+jwYAMx6jHWO9hMkYzS9pM
+Y3IyWR5ybtOjiQgkUdvRJPUPGf5DVVMPnymGX25aDh5PYpIESPbsM9akCpOOVuscywcUswmU
+o7dXvlB48WWCfg/al3BQKAZbn5ZXtWNwpUZkrEdHsrxAVv3rxRcdkT3Z1fzUbIuYkLJN200o
+WgRIJvn6RO8KEj7/HOg2sYuuM8nz1kR0TSgwX7/0y/7JfjBa0JIlP7o75sNJscE8oyoIMzuy
+Dvn6/U9g3BCDXn83A/s+ke60qn9gBFC6NAeLOlXal1YVWYhMQNOqCyUfAjiXBTawaysQb1Mk
+YgeNlF8xuEFcUQWIP+vNG7FJ5JPMaMRL4YEoaQ3sVFhYOERJR1cSb+8xt4QCYtBKQgRIUOmJ
+CHW5o1hXJWJiTkZK2qWFcEMzTINSj5EpYFySr8aVBjkRnI7vxegRT/+XZZXoYedQ3UNsnGI3
+DdkWii5VzX0PNF6C60pfBEiVpausYuX7Wjb3Lfm8cBj7GgN69i6Pm2gxtobVcmpo2nS4D714
+ePyhlX9n8kJ6QAcqWMRj22smDPrHVGNTizfzHBh5zNllK9gESJizILOWI327og3ZWp+qUht5
+kNDJCzMK7Z09UAy+h+vq0VTQuEo3FgLzVdqkJujjSL4Nx97lXg51AovrEn3nd4evydwcjKLX
+1wRIo72NaeWuUEQ+rt1SlCsOJ7k1ioJSqhrPOfvwcaFcb4beVet1JWiy4yvowTjLDGbUje2s
+xjrlVt4BJWI/uA6jbQsrxSe89ADZBAi5YAlR4qszeAQIXD3VSBVKbRUECNTtyvw9vvqXBAhb
+IZNn4H4cxgQI+XW7GkfL+ekECCCCg2reMyGDBAh1PYqkg3lw3gQQkNlggEPU+BH8eh7Gm7n7
+7AQIjC5EWbkil5cEEKcpuqwTWww/X89KnQAg8TcECJPomqHvrlZFBBiRSuIiHpmN+PaujXpv
+qZV2VhjkB2j09GEECOIdv8AVOJgKBAjlHgIqAD9jZQQIXHbs44+wogcEIGGqTACRJxrhMcMG
+X8drNjksIPt+snxTXUBIkTVpZWoABAh6unXPTyIr8QQgBF8xKoX27MWk7iTNmkSNZggZXa2a
+DWCGHSYLngbSOHIECD9XmO6VsvTgBAjfqB70CEW4WwQIVIBkbCocznUEEHB/zFXy/sR4OYHe
+UfbNPnIEEDWBB/NTCLMGE+o8BfyujcAECFik7GQnnF9VBBAhLXExQeWAofZNc6NtN7qZBCC1
+gVIS3ruTwKltmcrgx3heT3M8ZJhCfWa+6KzchnmKygQQ+1NL5sSzR4m/fdrqxHFyUAQYCT2x
+PamQr3wK3h0lyZER+4H0zPM86AhFBBC3CkmvL2vjflMfujnzPBVpBBge9rMbI5+0q9DLrTiT
+5F3AIgXLpD8PQWAECHkHVo6RomV3BAgMbi8E271UeAQIqtS8wnI3XngECG3TWmOMb3/iBEha
+y+mvCS6I3n3JfL8e1B5P4qX9/czJRaERLuKpGNjLiL4A+zxN0LZ0UHd0qfmJjwOTxAx3iJAC
+lGXX4nB9ATYPUT5EU+o1Y4sECN01pP6vWNIdBDAsiE0Ts8/9ltJlqX2B3AoOM4qOt9EaCjXf
+lB+aEmrhtjUwuZ6GqS5Ke7P6XnakTk4ECCLIMatNdootAAAAAAAAAAAAAA==
+-----END PKCS7-----
diff --git a/crypto/pkcs7/example.c b/crypto/pkcs7/example.c
new file mode 100644
index 0000000..9309e1d
--- /dev/null
+++ b/crypto/pkcs7/example.c
@@ -0,0 +1,357 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include "pkcs7.h"
+
+int add_signed_time(si)
+PKCS7_SIGNER_INFO *si;
+	{
+	ASN1_UTCTIME *sign_time;
+
+	/* The last parameter is the amount to add/subtract from the current
+	 * time (in seconds) */
+	sign_time=X509_gmtime_adj(NULL,0);
+	PKCS7_add_signed_attribute(si,NID_pkcs9_signingTime,
+		V_ASN1_UTCTIME,(char *)sign_time);
+	return(1);
+	}
+
+ASN1_UTCTIME *get_signed_time(si)
+PKCS7_SIGNER_INFO *si;
+	{
+	ASN1_TYPE *so;
+	ASN1_UTCTIME *ut;
+
+	so=PKCS7_get_signed_attribute(si,NID_pkcs9_signingTime);
+	if (so->type == V_ASN1_UTCTIME)
+		{
+		ut=so->value.utctime;
+		}
+	return(ut);
+	}
+	
+static int signed_string_nid= -1;
+
+int add_signed_string(si,str)
+PKCS7_SIGNER_INFO *si;
+char *str;
+	{
+	ASN1_OCTET_STRING *os;
+
+	/* To a an object of OID 1.2.3.4.5, which is an octet string */
+	if (signed_string_nid == -1)
+		signed_string_nid=
+			OBJ_create("1.2.3.4.5","OID_example","Our example OID");
+	os=ASN1_OCTET_STRING_new();
+	ASN1_OCTET_STRING_set(os,str,strlen(str));
+	/* When we add, we do not free */
+	PKCS7_add_signed_attribute(si,signed_string_nid,
+		V_ASN1_OCTET_STRING,(char *)os);
+	}
+
+int get_signed_string(si,buf,len)
+PKCS7_SIGNER_INFO *si;
+char *buf;
+int len;
+	{
+	ASN1_TYPE *so;
+	ASN1_OCTET_STRING *os;
+	int i;
+
+	if (signed_string_nid == -1)
+		signed_string_nid=
+			OBJ_create("1.2.3.4.5","OID_example","Our example OID");
+	/* To retrieve */
+	so=PKCS7_get_signed_attribute(si,signed_string_nid);
+	if (so != NULL)
+		{
+		if (so->type == V_ASN1_OCTET_STRING)
+			{
+			os=so->value.octet_string;
+			i=os->length;
+			if ((i+1) > len)
+				i=len-1;
+			memcpy(buf,os->data,i);
+			return(i);
+			}
+		}
+	return(0);
+	}
+
+static signed_seq2string_nid= -1;
+/* ########################################### */
+int add_signed_seq2string(si,str1,str2)
+PKCS7_SIGNER_INFO *si;
+char *str1;
+char *str2;
+	/* To add an object of OID 1.9.999, which is a sequence containing
+	 * 2 octet strings */
+	{
+	unsigned char *p;
+	ASN1_OCTET_STRING *os1,*os2;
+	ASN1_STRING *seq;
+	char *data;
+	int i,total;
+
+	if (signed_seq2string_nid == -1)
+		signed_seq2string_nid=
+			OBJ_create("1.9.9999","OID_example","Our example OID");
+
+	os1=ASN1_OCTET_STRING_new();
+	os2=ASN1_OCTET_STRING_new();
+	ASN1_OCTET_STRING_set(os1,str1,strlen(str1));
+	ASN1_OCTET_STRING_set(os2,str1,strlen(str1));
+	i =i2d_ASN1_OCTET_STRING(os1,NULL);
+	i+=i2d_ASN1_OCTET_STRING(os2,NULL);
+	total=ASN1_object_size(1,i,V_ASN1_SEQUENCE);
+
+	data=malloc(total);
+	p=data;
+	ASN1_put_object(&p,1,i,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL);
+	i2d_ASN1_OCTET_STRING(os1,&p);
+	i2d_ASN1_OCTET_STRING(os2,&p);
+
+	seq=ASN1_STRING_new();
+	ASN1_STRING_set(seq,data,total);
+	free(data);
+	ASN1_OCTET_STRING_free(os1);
+	ASN1_OCTET_STRING_free(os2);
+
+	PKCS7_add_signed_attribute(si,signed_seq2string_nid,
+		V_ASN1_SEQUENCE,(char *)seq);
+	return(1);
+	}
+
+/* For this case, I will malloc the return strings */
+int get_signed_seq2string(si,str1,str2)
+PKCS7_SIGNER_INFO *si;
+char **str1;
+char **str2;
+	{
+	ASN1_TYPE *so;
+
+	if (signed_seq2string_nid == -1)
+		signed_seq2string_nid=
+			OBJ_create("1.9.9999","OID_example","Our example OID");
+	/* To retrieve */
+	so=PKCS7_get_signed_attribute(si,signed_seq2string_nid);
+	if (so->type == V_ASN1_SEQUENCE)
+		{
+		ASN1_CTX c;
+		ASN1_STRING *s;
+		long length;
+		ASN1_OCTET_STRING *os1,*os2;
+
+		s=so->value.sequence;
+		c.p=ASN1_STRING_data(s);
+		c.max=c.p+ASN1_STRING_length(s);
+		if (!asn1_GetSequence(&c,&length)) goto err;
+		/* Length is the length of the seqence */
+
+		c.q=c.p;
+		if ((os1=d2i_ASN1_OCTET_STRING(NULL,&c.p,c.slen)) == NULL) 
+			goto err;
+		c.slen-=(c.p-c.q);
+
+		c.q=c.p;
+		if ((os2=d2i_ASN1_OCTET_STRING(NULL,&c.p,c.slen)) == NULL) 
+			goto err;
+		c.slen-=(c.p-c.q);
+
+		if (!asn1_Finish(&c)) goto err;
+		*str1=malloc(os1->length+1);
+		*str2=malloc(os2->length+1);
+		memcpy(*str1,os1->data,os1->length);
+		memcpy(*str2,os2->data,os2->length);
+		(*str1)[os1->length]='\0';
+		(*str2)[os2->length]='\0';
+		ASN1_OCTET_STRING_free(os1);
+		ASN1_OCTET_STRING_free(os2);
+		return(1);
+		}
+err:
+	return(0);
+	}
+
+
+/* #######################################
+ * THE OTHER WAY TO DO THINGS
+ * #######################################
+ */
+X509_ATTRIBUTE *create_time()
+	{
+	ASN1_UTCTIME *sign_time;
+	X509_ATTRIBUTE *ret;
+
+	/* The last parameter is the amount to add/subtract from the current
+	 * time (in seconds) */
+	sign_time=X509_gmtime_adj(NULL,0);
+	ret=X509_ATTRIBUTE_create(NID_pkcs9_signingTime,
+		V_ASN1_UTCTIME,(char *)sign_time);
+	return(ret);
+	}
+
+ASN1_UTCTIME *sk_get_time(sk)
+STACK *sk;
+	{
+	ASN1_TYPE *so;
+	ASN1_UTCTIME *ut;
+	PKCS7_SIGNER_INFO si;
+
+	si.auth_attr=sk;
+	so=PKCS7_get_signed_attribute(&si,NID_pkcs9_signingTime);
+	if (so->type == V_ASN1_UTCTIME)
+		{
+		ut=so->value.utctime;
+		}
+	return(ut);
+	}
+	
+X509_ATTRIBUTE *create_string(si,str)
+char *str;
+	{
+	ASN1_OCTET_STRING *os;
+	X509_ATTRIBUTE *ret;
+
+	/* To a an object of OID 1.2.3.4.5, which is an octet string */
+	if (signed_string_nid == -1)
+		signed_string_nid=
+			OBJ_create("1.2.3.4.5","OID_example","Our example OID");
+	os=ASN1_OCTET_STRING_new();
+	ASN1_OCTET_STRING_set(os,str,strlen(str));
+	/* When we add, we do not free */
+	ret=X509_ATTRIBUTE_create(signed_string_nid,
+		V_ASN1_OCTET_STRING,(char *)os);
+	return(ret);
+	}
+
+int sk_get_string(sk,buf,len)
+STACK *sk;
+char *buf;
+int len;
+	{
+	ASN1_TYPE *so;
+	ASN1_OCTET_STRING *os;
+	int i;
+	PKCS7_SIGNER_INFO si;
+
+	si.auth_attr=sk;
+
+	if (signed_string_nid == -1)
+		signed_string_nid=
+			OBJ_create("1.2.3.4.5","OID_example","Our example OID");
+	/* To retrieve */
+	so=PKCS7_get_signed_attribute(&si,signed_string_nid);
+	if (so != NULL)
+		{
+		if (so->type == V_ASN1_OCTET_STRING)
+			{
+			os=so->value.octet_string;
+			i=os->length;
+			if ((i+1) > len)
+				i=len-1;
+			memcpy(buf,os->data,i);
+			return(i);
+			}
+		}
+	return(0);
+	}
+
+X509_ATTRIBUTE *add_seq2string(si,str1,str2)
+PKCS7_SIGNER_INFO *si;
+char *str1;
+char *str2;
+	/* To add an object of OID 1.9.999, which is a sequence containing
+	 * 2 octet strings */
+	{
+	unsigned char *p;
+	ASN1_OCTET_STRING *os1,*os2;
+	ASN1_STRING *seq;
+	X509_ATTRIBUTE *ret;
+	char *data;
+	int i,total;
+
+	if (signed_seq2string_nid == -1)
+		signed_seq2string_nid=
+			OBJ_create("1.9.9999","OID_example","Our example OID");
+
+	os1=ASN1_OCTET_STRING_new();
+	os2=ASN1_OCTET_STRING_new();
+	ASN1_OCTET_STRING_set(os1,str1,strlen(str1));
+	ASN1_OCTET_STRING_set(os2,str1,strlen(str1));
+	i =i2d_ASN1_OCTET_STRING(os1,NULL);
+	i+=i2d_ASN1_OCTET_STRING(os2,NULL);
+	total=ASN1_object_size(1,i,V_ASN1_SEQUENCE);
+
+	data=malloc(total);
+	p=data;
+	ASN1_put_object(&p,1,i,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL);
+	i2d_ASN1_OCTET_STRING(os1,&p);
+	i2d_ASN1_OCTET_STRING(os2,&p);
+
+	seq=ASN1_STRING_new();
+	ASN1_STRING_set(seq,data,total);
+	free(data);
+	ASN1_OCTET_STRING_free(os1);
+	ASN1_OCTET_STRING_free(os2);
+
+	ret=X509_ATTRIBUTE_create(signed_seq2string_nid,
+		V_ASN1_SEQUENCE,(char *)seq);
+	return(ret);
+	}
+
+/* For this case, I will malloc the return strings */
+int sk_get_seq2string(sk,str1,str2)
+STACK *sk;
+char **str1;
+char **str2;
+	{
+	ASN1_TYPE *so;
+	PKCS7_SIGNER_INFO si;
+
+	if (signed_seq2string_nid == -1)
+		signed_seq2string_nid=
+			OBJ_create("1.9.9999","OID_example","Our example OID");
+
+	si.auth_attr=sk;
+	/* To retrieve */
+	so=PKCS7_get_signed_attribute(&si,signed_seq2string_nid);
+	if (so->type == V_ASN1_SEQUENCE)
+		{
+		ASN1_CTX c;
+		ASN1_STRING *s;
+		long length;
+		ASN1_OCTET_STRING *os1,*os2;
+
+		s=so->value.sequence;
+		c.p=ASN1_STRING_data(s);
+		c.max=c.p+ASN1_STRING_length(s);
+		if (!asn1_GetSequence(&c,&length)) goto err;
+		/* Length is the length of the seqence */
+
+		c.q=c.p;
+		if ((os1=d2i_ASN1_OCTET_STRING(NULL,&c.p,c.slen)) == NULL) 
+			goto err;
+		c.slen-=(c.p-c.q);
+
+		c.q=c.p;
+		if ((os2=d2i_ASN1_OCTET_STRING(NULL,&c.p,c.slen)) == NULL) 
+			goto err;
+		c.slen-=(c.p-c.q);
+
+		if (!asn1_Finish(&c)) goto err;
+		*str1=malloc(os1->length+1);
+		*str2=malloc(os2->length+1);
+		memcpy(*str1,os1->data,os1->length);
+		memcpy(*str2,os2->data,os2->length);
+		(*str1)[os1->length]='\0';
+		(*str2)[os2->length]='\0';
+		ASN1_OCTET_STRING_free(os1);
+		ASN1_OCTET_STRING_free(os2);
+		return(1);
+		}
+err:
+	return(0);
+	}
+
+
diff --git a/crypto/pkcs7/info.pem b/crypto/pkcs7/info.pem
new file mode 100644
index 0000000..989baf8
--- /dev/null
+++ b/crypto/pkcs7/info.pem
@@ -0,0 +1,57 @@
+issuer :/C=AU/SP=Queensland/L=Brisbane/O=Cryptsoft Pty Ltd/OU=DEMONSTRATION AND TESTING/CN=DEMO ZERO VALUE CA
+subject:/C=AU/SP=Queensland/L=Brisbane/O=Cryptsoft Pty Ltd/OU=SMIME 003/CN=Information/Email=info@cryptsoft.com
+serial :047D
+
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1149 (0x47d)
+        Signature Algorithm: md5withRSAEncryption
+        Issuer: C=AU, SP=Queensland, L=Brisbane, O=Cryptsoft Pty Ltd, OU=DEMONSTRATION AND TESTING, CN=DEMO ZERO VALUE CA
+        Validity
+            Not Before: May 13 05:40:58 1998 GMT
+            Not After : May 12 05:40:58 2000 GMT
+        Subject: C=AU, SP=Queensland, L=Brisbane, O=Cryptsoft Pty Ltd, OU=SMIME 003, CN=Information/Email=info@cryptsoft.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Modulus:
+                    00:ad:e7:23:89:ee:0d:87:b7:9c:32:44:4b:95:81:
+                    73:dd:22:80:4b:2d:c5:60:b8:fe:1e:18:63:ef:dc:
+                    89:89:22:df:95:3c:7a:db:3d:9a:06:a8:08:d6:29:
+                    fd:ef:41:09:91:ed:bc:ad:98:f9:f6:28:90:62:6f:
+                    e7:e7:0c:4d:0b
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            Netscape Comment: 
+                Generated with SSLeay
+    Signature Algorithm: md5withRSAEncryption
+        52:15:ea:88:f4:f0:f9:0b:ef:ce:d5:f8:83:40:61:16:5e:55:
+        f9:ce:2d:d1:8b:31:5c:03:c6:2d:10:7c:61:d5:5c:0a:42:97:
+        d1:fd:65:b6:b6:84:a5:39:ec:46:ec:fc:e0:0d:d9:22:da:1b:
+        50:74:ad:92:cb:4e:90:e5:fa:7d
+
+-----BEGIN CERTIFICATE-----
+MIICTDCCAfagAwIBAgICBH0wDQYJKoZIhvcNAQEEBQAwgZIxCzAJBgNVBAYTAkFV
+MRMwEQYDVQQIEwpRdWVlbnNsYW5kMREwDwYDVQQHEwhCcmlzYmFuZTEaMBgGA1UE
+ChMRQ3J5cHRzb2Z0IFB0eSBMdGQxIjAgBgNVBAsTGURFTU9OU1RSQVRJT04gQU5E
+IFRFU1RJTkcxGzAZBgNVBAMTEkRFTU8gWkVSTyBWQUxVRSBDQTAeFw05ODA1MTMw
+NTQwNThaFw0wMDA1MTIwNTQwNThaMIGeMQswCQYDVQQGEwJBVTETMBEGA1UECBMK
+UXVlZW5zbGFuZDERMA8GA1UEBxMIQnJpc2JhbmUxGjAYBgNVBAoTEUNyeXB0c29m
+dCBQdHkgTHRkMRIwEAYDVQQLEwlTTUlNRSAwMDMxFDASBgNVBAMTC0luZm9ybWF0
+aW9uMSEwHwYJKoZIhvcNAQkBFhJpbmZvQGNyeXB0c29mdC5jb20wXDANBgkqhkiG
+9w0BAQEFAANLADBIAkEArecjie4Nh7ecMkRLlYFz3SKASy3FYLj+Hhhj79yJiSLf
+lTx62z2aBqgI1in970EJke28rZj59iiQYm/n5wxNCwIDAQABoygwJjAkBglghkgB
+hvhCAQ0EFxYVR2VuZXJhdGVkIHdpdGggU1NMZWF5MA0GCSqGSIb3DQEBBAUAA0EA
+UhXqiPTw+QvvztX4g0BhFl5V+c4t0YsxXAPGLRB8YdVcCkKX0f1ltraEpTnsRuz8
+4A3ZItobUHStkstOkOX6fQ==
+-----END CERTIFICATE-----
+
+-----BEGIN RSA PRIVATE KEY-----
+MIIBOgIBAAJBAK3nI4nuDYe3nDJES5WBc90igEstxWC4/h4YY+/ciYki35U8ets9
+mgaoCNYp/e9BCZHtvK2Y+fYokGJv5+cMTQsCAwEAAQJBAIHpvXvqEcOEoDRRHuIG
+fkcB4jPHcr9KE9TpxabH6xs9beN6OJnkePXAHwaz5MnUgSnbpOKq+cw8miKjXwe/
+zVECIQDVLwncT2lRmXarEYHzb+q/0uaSvKhWKKt3kJasLNTrAwIhANDUc/ghut29
+p3jJYjurzUKuG774/5eLjPLsxPPIZzNZAiA/10hSq41UnGqHLEUIS9m2/EeEZe7b
+bm567dfRU9OnVQIgDo8ROrZXSchEGbaog5J5r/Fle83uO8l93R3GqVxKXZkCIFfk
+IPD5PIYQAyyod3hyKKza7ZP4CGY4oOfZetbkSGGG
+-----END RSA PRIVATE KEY-----
diff --git a/crypto/pkcs7/infokey.pem b/crypto/pkcs7/infokey.pem
new file mode 100644
index 0000000..1e2acc9
--- /dev/null
+++ b/crypto/pkcs7/infokey.pem
@@ -0,0 +1,9 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIBOgIBAAJBAK3nI4nuDYe3nDJES5WBc90igEstxWC4/h4YY+/ciYki35U8ets9
+mgaoCNYp/e9BCZHtvK2Y+fYokGJv5+cMTQsCAwEAAQJBAIHpvXvqEcOEoDRRHuIG
+fkcB4jPHcr9KE9TpxabH6xs9beN6OJnkePXAHwaz5MnUgSnbpOKq+cw8miKjXwe/
+zVECIQDVLwncT2lRmXarEYHzb+q/0uaSvKhWKKt3kJasLNTrAwIhANDUc/ghut29
+p3jJYjurzUKuG774/5eLjPLsxPPIZzNZAiA/10hSq41UnGqHLEUIS9m2/EeEZe7b
+bm567dfRU9OnVQIgDo8ROrZXSchEGbaog5J5r/Fle83uO8l93R3GqVxKXZkCIFfk
+IPD5PIYQAyyod3hyKKza7ZP4CGY4oOfZetbkSGGG
+-----END RSA PRIVATE KEY-----
diff --git a/crypto/pkcs7/pk7_doit.c b/crypto/pkcs7/pk7_doit.c
index b5689b3..d761c3e 100644
--- a/crypto/pkcs7/pk7_doit.c
+++ b/crypto/pkcs7/pk7_doit.c
@@ -62,12 +62,16 @@
 #include "objects.h"
 #include "x509.h"
 
+static int add_attribute(STACK **sk, int nid, int atrtype, char *value);
+static ASN1_TYPE *get_attribute(STACK *sk, int nid);
+
+#if 1
 BIO *PKCS7_dataInit(p7,bio)
 PKCS7 *p7;
 BIO *bio;
 	{
 	int i,j;
-	BIO *out=NULL,*btmp;
+	BIO *out=NULL,*btmp=NULL;
 	X509_ALGOR *xa;
 	EVP_MD *evp_md;
 	EVP_CIPHER *evp_cipher=NULL;
@@ -95,6 +99,16 @@
 			}
 		xalg=p7->d.signed_and_enveloped->enc_data->algorithm;
 		break;
+	case NID_pkcs7_enveloped:
+		rsk=p7->d.enveloped->recipientinfo;
+		evp_cipher=EVP_get_cipherbyname(OBJ_nid2sn(OBJ_obj2nid(p7->d.enveloped->enc_data->algorithm->algorithm)));
+		if (evp_cipher == NULL)
+			{
+			PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
+			goto err;
+			}
+		xalg=p7->d.enveloped->enc_data->algorithm;
+		break;
 	default:
 		PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
 	        goto err;
@@ -105,7 +119,11 @@
 		for (i=0; i<sk_num(md_sk); i++)
 			{
 			xa=(X509_ALGOR *)sk_value(md_sk,i);
-			if ((btmp=BIO_new(BIO_f_md())) == NULL) goto err;
+			if ((btmp=BIO_new(BIO_f_md())) == NULL)
+				{
+				PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_BIO_LIB);
+				goto err;
+				}
 
 			j=OBJ_obj2nid(xa->algorithm);
 			evp_md=EVP_get_digestbyname(OBJ_nid2sn(j));
@@ -120,6 +138,7 @@
 				out=btmp;
 			else
 				BIO_push(out,btmp);
+			btmp=NULL;
 			}
 		}
 
@@ -131,7 +150,11 @@
 		int jj,max;
 		unsigned char *tmp;
 
-		if ((btmp=BIO_new(BIO_f_cipher())) == NULL) goto err;
+		if ((btmp=BIO_new(BIO_f_cipher())) == NULL)
+			{
+			PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_BIO_LIB);
+			goto err;
+			}
 		keylen=EVP_CIPHER_key_length(evp_cipher);
 		ivlen=EVP_CIPHER_iv_length(evp_cipher);
 
@@ -142,9 +165,12 @@
 			RAND_bytes(iv,ivlen);
 			os=ASN1_OCTET_STRING_new();
 			ASN1_OCTET_STRING_set(os,iv,ivlen);
-		/*	ASN1_TYPE_set(xalg->parameter,V_ASN1_OCTET_STRING,
+/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX this needs to change */
+			if (xalg->parameter == NULL)
+				xalg->parameter=ASN1_TYPE_new();
+			ASN1_TYPE_set(xalg->parameter,V_ASN1_OCTET_STRING,
 				(char *)os);
-		*/	}
+			}
 		RAND_bytes(key,keylen);
 
 		/* Lets do the pub key stuff :-) */
@@ -152,20 +178,34 @@
 		for (i=0; i<sk_num(rsk); i++)
 			{
 			ri=(PKCS7_RECIP_INFO *)sk_value(rsk,i);
-			if (ri->cert == NULL) abort();
+			if (ri->cert == NULL)
+				{
+				PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_MISSING_CERIPEND_INFO);
+				goto err;
+				}
 			pkey=X509_get_pubkey(ri->cert);
 			jj=EVP_PKEY_size(pkey);
 			if (max < jj) max=jj;
 			}
-		if ((tmp=(unsigned char *)Malloc(max)) == NULL) abort();
+		if ((tmp=(unsigned char *)Malloc(max)) == NULL)
+			{
+			PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
 		for (i=0; i<sk_num(rsk); i++)
 			{
 			ri=(PKCS7_RECIP_INFO *)sk_value(rsk,i);
 			pkey=X509_get_pubkey(ri->cert);
 			jj=EVP_PKEY_encrypt(tmp,key,keylen,pkey);
-			if (jj <= 0) abort();
+			if (jj <= 0)
+				{
+				PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_EVP_LIB);
+				Free(tmp);
+				goto err;
+				}
 			ASN1_OCTET_STRING_set(ri->enc_key,tmp,jj);
 			}
+		Free(tmp);
 
 		BIO_set_cipher(btmp,evp_cipher,key,iv,1);
 
@@ -173,6 +213,7 @@
 			out=btmp;
 		else
 			BIO_push(out,btmp);
+		btmp=NULL;
 		}
 
 	if (bio == NULL) /* ??????????? */
@@ -182,6 +223,11 @@
 		else
 			{
 			bio=BIO_new(BIO_s_mem());
+			/* We need to set this so that when we have read all
+			 * the data, the encrypt BIO, if present, will read
+			 * EOF and encode the last few bytes */
+			BIO_set_mem_eof_return(bio,0);
+
 			if (PKCS7_type_is_signed(p7) &&
 				PKCS7_type_is_data(p7->d.sign->contents))
 				{
@@ -195,12 +241,234 @@
 			}
 		}
 	BIO_push(out,bio);
-	return(out);
+	bio=NULL;
+	if (0)
+		{
 err:
-	return(NULL);
+		if (out != NULL)
+			BIO_free_all(out);
+		if (btmp != NULL)
+			BIO_free_all(btmp);
+		out=NULL;
+		}
+	return(out);
 	}
 
-int PKCS7_dataSign(p7,bio)
+/* int */
+BIO *PKCS7_dataDecode(p7,pkey,in_bio,xs)
+PKCS7 *p7;
+EVP_PKEY *pkey;
+BIO *in_bio;
+X509_STORE *xs;
+	{
+	int i,j;
+	BIO *out=NULL,*btmp=NULL,*etmp=NULL,*bio=NULL;
+	char *tmp=NULL;
+	X509_ALGOR *xa;
+	ASN1_OCTET_STRING *data_body=NULL;
+	EVP_MD *evp_md;
+	EVP_CIPHER *evp_cipher=NULL;
+	EVP_CIPHER_CTX *evp_ctx=NULL;
+	X509_ALGOR *enc_alg=NULL;
+	STACK *md_sk=NULL,*rsk=NULL;
+	X509_ALGOR *xalg=NULL;
+	PKCS7_RECIP_INFO *ri=NULL;
+/*	EVP_PKEY *pkey; */
+#if 0
+	X509_STORE_CTX s_ctx;
+#endif
+
+	i=OBJ_obj2nid(p7->type);
+	p7->state=PKCS7_S_HEADER;
+
+	switch (i)
+		{
+	case NID_pkcs7_signed:
+		data_body=p7->d.sign->contents->d.data;
+		md_sk=p7->d.sign->md_algs;
+		break;
+	case NID_pkcs7_signedAndEnveloped:
+		rsk=p7->d.signed_and_enveloped->recipientinfo;
+		md_sk=p7->d.signed_and_enveloped->md_algs;
+		data_body=p7->d.signed_and_enveloped->enc_data->enc_data;
+		enc_alg=p7->d.signed_and_enveloped->enc_data->algorithm;
+		evp_cipher=EVP_get_cipherbyname(OBJ_nid2sn(OBJ_obj2nid(enc_alg->algorithm)));
+		if (evp_cipher == NULL)
+			{
+			PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
+			goto err;
+			}
+		xalg=p7->d.signed_and_enveloped->enc_data->algorithm;
+		break;
+	case NID_pkcs7_enveloped:
+		rsk=p7->d.enveloped->recipientinfo;
+		enc_alg=p7->d.enveloped->enc_data->algorithm;
+		data_body=p7->d.enveloped->enc_data->enc_data;
+		evp_cipher=EVP_get_cipherbyname(OBJ_nid2sn(OBJ_obj2nid(enc_alg->algorithm)));
+		if (evp_cipher == NULL)
+			{
+			PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
+			goto err;
+			}
+		xalg=p7->d.enveloped->enc_data->algorithm;
+		break;
+	default:
+		PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
+	        goto err;
+		}
+
+	/* We will be checking the signature */
+	if (md_sk != NULL)
+		{
+		for (i=0; i<sk_num(md_sk); i++)
+			{
+			xa=(X509_ALGOR *)sk_value(md_sk,i);
+			if ((btmp=BIO_new(BIO_f_md())) == NULL)
+				{
+				PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,ERR_R_BIO_LIB);
+				goto err;
+				}
+
+			j=OBJ_obj2nid(xa->algorithm);
+			evp_md=EVP_get_digestbyname(OBJ_nid2sn(j));
+			if (evp_md == NULL)
+				{
+				PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,PKCS7_R_UNKNOWN_DIGEST_TYPE);
+				goto err;
+				}
+
+			BIO_set_md(btmp,evp_md);
+			if (out == NULL)
+				out=btmp;
+			else
+				BIO_push(out,btmp);
+			btmp=NULL;
+			}
+		}
+
+	if (evp_cipher != NULL)
+		{
+#if 0
+		unsigned char key[EVP_MAX_KEY_LENGTH];
+		unsigned char iv[EVP_MAX_IV_LENGTH];
+		unsigned char *p;
+		int keylen,ivlen;
+		int max;
+		X509_OBJECT ret;
+#endif
+		int jj;
+
+		if ((etmp=BIO_new(BIO_f_cipher())) == NULL)
+			{
+			PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,ERR_R_BIO_LIB);
+			goto err;
+			}
+
+		/* It was encrypted, we need to decrypt the secret key
+		 * with the private key */
+
+		/* We need to find a private key for one of the people in the
+		 * recipentinfo list */
+		if (rsk == NULL)
+			return(NULL);
+
+		ri=(PKCS7_RECIP_INFO *)sk_value(rsk,0);
+#if 0
+		X509_STORE_CTX_init(&s_ctx,xs,NULL,NULL);
+		for (i=0; i<sk_num(rsk); i++)
+			{
+			ri=(PKCS7_RECIP_INFO *)sk_value(rsk,i);
+			uf (X509_STORE_get_by_issuer_serial(&s_ctx,
+				X509_LU_PKEY,
+				ri->issuer_and_serial->issuer,
+				ri->issuer_and_serial->serial,
+				&ret))
+				break;
+			ri=NULL;
+			}
+		if (ri == NULL) return(NULL);	
+		pkey=ret.data.pkey;
+#endif
+		if (pkey == NULL)
+			{
+			return(NULL);
+			}
+
+		jj=EVP_PKEY_size(pkey);
+		tmp=Malloc(jj+10);
+		if (tmp == NULL)
+			{
+			PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+
+		jj=EVP_PKEY_decrypt((unsigned char *)tmp,
+			ASN1_STRING_data(ri->enc_key),
+			ASN1_STRING_length(ri->enc_key),
+			pkey);
+		if (jj <= 0)
+			{
+			PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,ERR_R_EVP_LIB);
+			goto err;
+			}
+
+		evp_ctx=NULL;
+		BIO_get_cipher_ctx(etmp,&evp_ctx);
+		EVP_CipherInit(evp_ctx,evp_cipher,NULL,NULL,0);
+		if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0)
+			return(NULL);
+
+		if (jj != EVP_CIPHER_CTX_key_length(evp_ctx))
+			{
+			PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH);
+			goto err;
+			}
+		EVP_CipherInit(evp_ctx,NULL,(unsigned char *)tmp,NULL,0);
+
+		memset(tmp,0,jj);
+
+		if (out == NULL)
+			out=etmp;
+		else
+			BIO_push(out,etmp);
+		etmp=NULL;
+		}
+
+#if 1
+	if (p7->detached || (in_bio != NULL))
+		{
+		bio=in_bio;
+		}
+	else 
+		{
+		bio=BIO_new(BIO_s_mem());
+		/* We need to set this so that when we have read all
+		 * the data, the encrypt BIO, if present, will read
+		 * EOF and encode the last few bytes */
+		BIO_set_mem_eof_return(bio,0);
+
+		if (data_body->length > 0)
+			BIO_write(bio,(char *)data_body->data,data_body->length);
+		}
+	BIO_push(out,bio);
+	bio=NULL;
+#endif
+	if (0)
+		{
+err:
+		if (out != NULL) BIO_free_all(out);
+		if (btmp != NULL) BIO_free_all(btmp);
+		if (etmp != NULL) BIO_free_all(etmp);
+		if (bio != NULL) BIO_free_all(bio);
+		out=NULL;
+		}
+	if (tmp != NULL)
+		Free(tmp);
+	return(out);
+	}
+#endif
+
+int PKCS7_dataFinal(p7,bio)
 PKCS7 *p7;
 BIO *bio;
 	{
@@ -227,6 +495,11 @@
 		os=ASN1_OCTET_STRING_new();
 		p7->d.signed_and_enveloped->enc_data->enc_data=os;
 		break;
+	case NID_pkcs7_enveloped:
+		/* XXXXXXXXXXXXXXXX */
+		os=ASN1_OCTET_STRING_new();
+		p7->d.enveloped->enc_data->enc_data=os;
+		break;
 	case NID_pkcs7_signed:
 		si_sk=p7->d.sign->signer_info;
 		os=p7->d.sign->contents->d.data;
@@ -235,14 +508,18 @@
 
 	if (si_sk != NULL)
 		{
-		if ((buf=BUF_MEM_new()) == NULL) goto err;
+		if ((buf=BUF_MEM_new()) == NULL)
+			{
+			PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_BIO_LIB);
+			goto err;
+			}
 		for (i=0; i<sk_num(si_sk); i++)
 			{
 			si=(PKCS7_SIGNER_INFO *)
 				sk_value(si_sk,i);
-			if (si->pkey == NULL)
-				continue;
-			j=OBJ_obj2nid(si->digest_enc_alg->algorithm);
+			if (si->pkey == NULL) continue;
+
+			j=OBJ_obj2nid(si->digest_alg->algorithm);
 
 			btmp=bio;
 			for (;;)
@@ -259,7 +536,7 @@
 					PKCS7err(PKCS7_F_PKCS7_DATASIGN,PKCS7_R_INTERNAL_ERROR);
 					goto err;
 					}
-				if (EVP_MD_pkey_type(EVP_MD_CTX_type(mdc)) == j)
+				if (EVP_MD_type(EVP_MD_CTX_type(mdc)) == j)
 					break;
 				else
 					btmp=btmp->next_bio;
@@ -269,46 +546,85 @@
 			 * signing. */
 			memcpy(&ctx_tmp,mdc,sizeof(ctx_tmp));
 			if (!BUF_MEM_grow(buf,EVP_PKEY_size(si->pkey)))
+				{
+				PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_BIO_LIB);
 				goto err;
+				}
 
 			sk=si->auth_attr;
+
+			/* If there are attributes, we add the digest
+			 * attribute and only sign the attributes */
 			if ((sk != NULL) && (sk_num(sk) != 0))
 				{
+				unsigned char md_data[EVP_MAX_MD_SIZE];
+				unsigned int md_len;
+				ASN1_OCTET_STRING *digest;
+				ASN1_UTCTIME *sign_time;
+				EVP_MD *md_tmp;
+
+				/* Add signing time */
+				sign_time=X509_gmtime_adj(NULL,0);
+				PKCS7_add_signed_attribute(si,
+					NID_pkcs9_signingTime,
+					V_ASN1_UTCTIME,(char *)sign_time);
+
+				/* Add digest */
+				md_tmp=EVP_MD_CTX_type(&ctx_tmp);
+				EVP_DigestFinal(&ctx_tmp,md_data,&md_len);
+				digest=ASN1_OCTET_STRING_new();
+				ASN1_OCTET_STRING_set(digest,md_data,md_len);
+				PKCS7_add_signed_attribute(si,NID_pkcs9_messageDigest,
+					V_ASN1_OCTET_STRING,(char *)digest);
+
+				/* Now sign the mess */
+				EVP_SignInit(&ctx_tmp,md_tmp);
 				x=i2d_ASN1_SET(sk,NULL,i2d_X509_ATTRIBUTE,
 					V_ASN1_SET,V_ASN1_UNIVERSAL);
-				pp=(unsigned char *)Malloc(i);
+				pp=(unsigned char *)Malloc(x);
 				p=pp;
 				i2d_ASN1_SET(sk,&p,i2d_X509_ATTRIBUTE,
 					V_ASN1_SET,V_ASN1_UNIVERSAL);
 				EVP_SignUpdate(&ctx_tmp,pp,x);
 				Free(pp);
+				pp=NULL;
 				}
 
+			if (si->pkey->type == EVP_PKEY_DSA)
+				ctx_tmp.digest=EVP_dss1();
+
 			if (!EVP_SignFinal(&ctx_tmp,(unsigned char *)buf->data,
 				(unsigned int *)&buf->length,si->pkey))
-				goto err;
-			if (!ASN1_STRING_set(si->enc_digest,
-				(unsigned char *)buf->data,buf->length))
-				goto err;
-			}
-		if (p7->detached)
-			ASN1_OCTET_STRING_set(os,(unsigned char *)"",0);
-		else
-			{
-			btmp=BIO_find_type(bio,BIO_TYPE_MEM);
-			if (btmp == NULL)
 				{
-				PKCS7err(PKCS7_F_PKCS7_DATASIGN,PKCS7_R_UNABLE_TO_FIND_MEM_BIO);
+				PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_EVP_LIB);
 				goto err;
 				}
-			BIO_get_mem_ptr(btmp,&buf_mem);
-			ASN1_OCTET_STRING_set(os,
-				(unsigned char *)buf_mem->data,buf_mem->length);
+			if (!ASN1_STRING_set(si->enc_digest,
+				(unsigned char *)buf->data,buf->length))
+				{
+				PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_ASN1_LIB);
+				goto err;
+				}
 			}
-		if (pp != NULL) Free(pp);
-		pp=NULL;
 		}
 
+	if (p7->detached)
+		ASN1_OCTET_STRING_set(os,(unsigned char *)"",0);
+	else
+		{
+		btmp=BIO_find_type(bio,BIO_TYPE_MEM);
+		if (btmp == NULL)
+			{
+			PKCS7err(PKCS7_F_PKCS7_DATASIGN,PKCS7_R_UNABLE_TO_FIND_MEM_BIO);
+			goto err;
+			}
+		BIO_get_mem_ptr(btmp,&buf_mem);
+		ASN1_OCTET_STRING_set(os,
+			(unsigned char *)buf_mem->data,buf_mem->length);
+		}
+	if (pp != NULL) Free(pp);
+	pp=NULL;
+
 	ret=1;
 err:
 	if (buf != NULL) BUF_MEM_free(buf);
@@ -322,22 +638,34 @@
 PKCS7 *p7;
 PKCS7_SIGNER_INFO *si;
 	{
-	PKCS7_SIGNED *s;
+/*	PKCS7_SIGNED *s; */
 	ASN1_OCTET_STRING *os;
 	EVP_MD_CTX mdc_tmp,*mdc;
 	unsigned char *pp,*p;
 	PKCS7_ISSUER_AND_SERIAL *ias;
-	int ret=0,md_type,i;
-	STACK *sk;
+	int ret=0,i;
+	int md_type;
+	STACK *sk,*cert;
 	BIO *btmp;
 	X509 *x509;
 
-	if (!PKCS7_type_is_signed(p7)) abort();
+	if (PKCS7_type_is_signed(p7))
+		{
+		cert=p7->d.sign->cert;
+		}
+	else if (PKCS7_type_is_signedAndEnveloped(p7))
+		{
+		cert=p7->d.signed_and_enveloped->cert;
+		}
+	else
+		{
+		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_WRONG_PKCS7_TYPE);
+		goto err;
+		}
 	/* XXXXXXXXXXXXXXXXXXXXXXX */
 	ias=si->issuer_and_serial;
-	s=p7->d.sign;
 
-	x509=X509_find_by_issuer_and_serial(s->cert,ias->issuer,ias->serial);
+	x509=X509_find_by_issuer_and_serial(cert,ias->issuer,ias->serial);
 
 	/* were we able to find the cert in passed to us */
 	if (x509 == NULL)
@@ -347,9 +675,13 @@
 		}
 
 	/* Lets verify */
-	X509_STORE_CTX_init(ctx,cert_store,x509,s->cert);
+	X509_STORE_CTX_init(ctx,cert_store,x509,cert);
 	i=X509_verify_cert(ctx);
-	if (i <= 0) goto err;
+	if (i <= 0) 
+		{
+		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB);
+		goto err;
+		}
 	X509_STORE_CTX_cleanup(ctx);
 
 	/* So we like 'x509', lets check the signature. */
@@ -375,23 +707,55 @@
 		btmp=btmp->next_bio;	
 		}
 
-	/* mdc is the digest ctx that we want */
+	/* mdc is the digest ctx that we want, unless there are attributes,
+	 * in which case the digest is the signed attributes */
 	memcpy(&mdc_tmp,mdc,sizeof(mdc_tmp));
 
 	sk=si->auth_attr;
 	if ((sk != NULL) && (sk_num(sk) != 0))
 		{
+		unsigned char md_dat[EVP_MAX_MD_SIZE];
+		int md_len;
+		ASN1_OCTET_STRING *message_digest;
+
+		EVP_DigestFinal(&mdc_tmp,md_dat,&md_len);
+		message_digest=PKCS7_digest_from_attributes(sk);
+		if (!message_digest)
+			{
+			PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
+			goto err;
+			}
+		if ((message_digest->length != md_len) ||
+			(memcmp(message_digest->data,md_dat,md_len)))
+			{
+#if 0
+{
+int ii;
+for (ii=0; ii<message_digest->length; ii++)
+	printf("%02X",message_digest->data[ii]); printf(" sent\n");
+for (ii=0; ii<md_len; ii++) printf("%02X",md_dat[ii]); printf(" calc\n");
+}
+#endif
+			PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_DIGEST_FAILURE);
+			ret= -1;
+			goto err;
+			}
+
+		EVP_VerifyInit(&mdc_tmp,EVP_get_digestbynid(md_type));
 		i=i2d_ASN1_SET(sk,NULL,i2d_X509_ATTRIBUTE,
 			V_ASN1_SET,V_ASN1_UNIVERSAL);
-		pp=(unsigned char *)malloc(i);
+		pp=(unsigned char *)Malloc(i);
 		p=pp;
 		i2d_ASN1_SET(sk,&p,i2d_X509_ATTRIBUTE,
 			V_ASN1_SET,V_ASN1_UNIVERSAL);
 		EVP_VerifyUpdate(&mdc_tmp,pp,i);
-		free(pp);
+		Free(pp);
 		}
 
 	os=si->enc_digest;
+	if (X509_get_pubkey(x509)->type == EVP_PKEY_DSA)
+		mdc_tmp.digest=EVP_dss1();
+
 	i=EVP_VerifyFinal(&mdc_tmp,os->data,os->length,
 		X509_get_pubkey(x509));
 	if (i <= 0)
@@ -406,3 +770,172 @@
 	return(ret);
 	}
 
+PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(p7,idx)
+PKCS7 *p7;
+int idx;
+	{
+	STACK *rsk;
+	PKCS7_RECIP_INFO *ri;
+	int i;
+
+	i=OBJ_obj2nid(p7->type);
+	if (i != NID_pkcs7_signedAndEnveloped) return(NULL);
+	rsk=p7->d.signed_and_enveloped->recipientinfo;
+	ri=(PKCS7_RECIP_INFO *)sk_value(rsk,0);
+	if (sk_num(rsk) <= idx) return(NULL);
+	ri=(PKCS7_RECIP_INFO *)sk_value(rsk,idx);
+	return(ri->issuer_and_serial);
+	}
+
+ASN1_TYPE *PKCS7_get_signed_attribute(si,nid)
+PKCS7_SIGNER_INFO *si;
+int nid;
+	{
+	return(get_attribute(si->auth_attr,nid));
+	}
+
+ASN1_TYPE *PKCS7_get_attribute(si,nid)
+PKCS7_SIGNER_INFO *si;
+int nid;
+	{
+	return(get_attribute(si->unauth_attr,nid));
+	}
+
+static ASN1_TYPE *get_attribute(sk,nid)
+STACK *sk;
+int nid;
+	{
+	int i;
+	X509_ATTRIBUTE *xa;
+	ASN1_OBJECT *o;
+
+	o=OBJ_nid2obj(nid);
+	if (o == NULL) return(NULL);
+	for (i=0; i<sk_num(sk); i++)
+		{
+		xa=(X509_ATTRIBUTE *)sk_value(sk,i);
+		if (OBJ_cmp(xa->object,o) == 0)
+			{
+			if (xa->set && sk_num(xa->value.set))
+				return((ASN1_TYPE *)sk_value(xa->value.set,0));
+			else
+				return(NULL);
+			}
+		}
+	return(NULL);
+	}
+
+ASN1_OCTET_STRING *PKCS7_digest_from_attributes(sk)
+STACK *sk;
+	{
+	X509_ATTRIBUTE *attr;
+	ASN1_TYPE *astype;
+	int i;
+	if (!sk || !sk_num(sk)) return NULL;
+	/* Search the attributes for a digest */
+	for (i = 0; i < sk_num(sk); i++)
+		{
+		attr = (X509_ATTRIBUTE *) sk_value(sk, i);
+		if (OBJ_obj2nid(attr->object) == NID_pkcs9_messageDigest)
+			{
+			if (!attr->set) return NULL;
+			if (!attr->value.set ||
+				 !sk_num (attr->value.set) ) return NULL;
+			astype = (ASN1_TYPE *) sk_value(attr->value.set, 0);
+			return astype->value.octet_string;
+			}
+		}
+	return NULL;
+	}
+
+int PKCS7_set_signed_attributes(p7si,sk)
+PKCS7_SIGNER_INFO *p7si;
+STACK *sk;
+	{
+	int i;
+
+	if (p7si->auth_attr != NULL)
+		sk_pop_free(p7si->auth_attr,X509_ATTRIBUTE_free);
+	p7si->auth_attr=sk_dup(sk);
+	for (i=0; i<sk_num(sk); i++)
+		{
+		if ((sk_value(p7si->auth_attr,i)=(char *)X509_ATTRIBUTE_dup(
+			(X509_ATTRIBUTE *)sk_value(sk,i))) == NULL)
+			return(0);
+		}
+	return(1);
+	}
+
+int PKCS7_set_attributes(p7si,sk)
+PKCS7_SIGNER_INFO *p7si;
+STACK *sk;
+	{
+	int i;
+
+	if (p7si->unauth_attr != NULL)
+		sk_pop_free(p7si->unauth_attr,X509_ATTRIBUTE_free);
+	p7si->unauth_attr=sk_dup(sk);
+	for (i=0; i<sk_num(sk); i++)
+		{
+		if ((sk_value(p7si->unauth_attr,i)=(char *)X509_ATTRIBUTE_dup(
+			(X509_ATTRIBUTE *)sk_value(sk,i))) == NULL)
+			return(0);
+		}
+	return(1);
+	}
+
+int PKCS7_add_signed_attribute(p7si,nid,atrtype,value)
+PKCS7_SIGNER_INFO *p7si;
+int nid;
+int atrtype;
+char *value;
+	{
+	return(add_attribute(&(p7si->auth_attr),nid,atrtype,value));
+	}
+
+int PKCS7_add_attribute(p7si,nid,atrtype,value)
+PKCS7_SIGNER_INFO *p7si;
+int nid;
+int atrtype;
+char *value;
+	{
+	return(add_attribute(&(p7si->unauth_attr),nid,atrtype,value));
+	}
+
+static int add_attribute(sk, nid, atrtype, value)
+STACK **sk;
+int nid;
+int atrtype;
+char *value;
+	{
+	X509_ATTRIBUTE *attr=NULL;
+	ASN1_TYPE *val=NULL;
+
+	if (*sk == NULL)
+		{
+		*sk = sk_new(NULL);
+new_attrib:
+		attr=X509_ATTRIBUTE_create(nid,atrtype,value);
+		sk_push(*sk,(char *)attr);
+		}
+	else
+		{
+		int i;
+
+		for (i=0; i<sk_num(*sk); i++)
+			{
+			attr=(X509_ATTRIBUTE *)sk_value(*sk,i);
+			if (OBJ_obj2nid(attr->object) == nid)
+				{
+				X509_ATTRIBUTE_free(attr);
+				attr=X509_ATTRIBUTE_create(nid,atrtype,value);
+				sk_value(*sk,i)=(char *)attr;
+				goto end;
+				}
+			}
+		goto new_attrib;
+		}
+end:
+	return(1);
+	}
+
diff --git a/crypto/pkcs7/pk7_lib.c b/crypto/pkcs7/pk7_lib.c
index 7d14ad1..7534f4c 100644
--- a/crypto/pkcs7/pk7_lib.c
+++ b/crypto/pkcs7/pk7_lib.c
@@ -98,7 +98,8 @@
 			
 		break;
 	default:
-		abort();
+		PKCS7err(PKCS7_F_PKCS7_CTRL,PKCS7_R_UNKNOWN_OPERATION);
+		ret=0;
 		}
 	return(ret);
 	}
@@ -172,12 +173,19 @@
 	case NID_pkcs7_signedAndEnveloped:
 		p7->type=obj;
 		if ((p7->d.signed_and_enveloped=PKCS7_SIGN_ENVELOPE_new())
-			== NULL)
-			goto err;
-		ASN1_INTEGER_set(p7->d.sign->version,1);
+			== NULL) goto err;
+		ASN1_INTEGER_set(p7->d.signed_and_enveloped->version,1);
+/*		p7->d.signed_and_enveloped->enc_data->content_type=
+			OBJ_nid2obj(NID_pkcs7_encrypted);*/
+			
+		break;
+	case NID_pkcs7_enveloped:
+		p7->type=obj;
+		if ((p7->d.enveloped=PKCS7_ENVELOPE_new())
+			== NULL) goto err;
+		ASN1_INTEGER_set(p7->d.enveloped->version,0);
 		break;
 	case NID_pkcs7_digest:
-	case NID_pkcs7_enveloped:
 	case NID_pkcs7_encrypted:
 	default:
 		PKCS7err(PKCS7_F_PKCS7_SET_TYPE,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
@@ -316,7 +324,10 @@
 	p7i->pkey=pkey;
 
 	/* Set the algorithms */
-	p7i->digest_alg->algorithm=OBJ_nid2obj(EVP_MD_type(dgst));
+	if (pkey->type == EVP_PKEY_DSA)
+		p7i->digest_alg->algorithm=OBJ_nid2obj(NID_sha1);
+	else	
+		p7i->digest_alg->algorithm=OBJ_nid2obj(EVP_MD_type(dgst));
 	p7i->digest_enc_alg->algorithm=OBJ_nid2obj(EVP_MD_pkey_type(dgst));
 
 #if 1
@@ -355,6 +366,10 @@
 		{
 		return(p7->d.sign->signer_info);
 		}
+	else if (PKCS7_type_is_signedAndEnveloped(p7))
+		{
+		return(p7->d.signed_and_enveloped->signer_info);
+		}
 	else
 		return(NULL);
 	}
@@ -386,6 +401,9 @@
 	case NID_pkcs7_signedAndEnveloped:
 		sk=	p7->d.signed_and_enveloped->recipientinfo;
 		break;
+	case NID_pkcs7_enveloped:
+		sk=	p7->d.enveloped->recipientinfo;
+		break;
 	default:
 		PKCS7err(PKCS7_F_PKCS7_ADD_RECIPIENT_INFO,PKCS7_R_WRONG_CONTENT_TYPE);
 		return(0);
@@ -407,6 +425,11 @@
 	p7i->issuer_and_serial->serial=
 		ASN1_INTEGER_dup(X509_get_serialNumber(x509));
 
+	X509_ALGOR_free(p7i->key_enc_algor);
+	p7i->key_enc_algor=(X509_ALGOR *)ASN1_dup(i2d_X509_ALGOR,
+		(char *(*)())d2i_X509_ALGOR,
+		(char *)x509->cert_info->key->algor);
+
 	CRYPTO_add(&x509->references,1,CRYPTO_LOCK_X509);
 	p7i->cert=x509;
 
@@ -438,6 +461,9 @@
 	case NID_pkcs7_signedAndEnveloped:
 		ec=p7->d.signed_and_enveloped->enc_data;
 		break;
+	case NID_pkcs7_enveloped:
+		ec=p7->d.enveloped->enc_data;
+		break;
 	default:
 		PKCS7err(PKCS7_F_PKCS7_SET_CIPHER,PKCS7_R_WRONG_CONTENT_TYPE);
 		return(0);
diff --git a/crypto/pkcs7/pkcs7.err b/crypto/pkcs7/pkcs7.err
index 91413aa..115721e 100644
--- a/crypto/pkcs7/pkcs7.err
+++ b/crypto/pkcs7/pkcs7.err
@@ -12,15 +12,21 @@
 #define PKCS7_F_PKCS7_SET_CIPHER			 108
 #define PKCS7_F_PKCS7_SET_CONTENT			 109
 #define PKCS7_F_PKCS7_SET_TYPE				 110
+#define PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT		 111
 
 /* Reason codes. */
-#define PKCS7_R_INTERNAL_ERROR				 100
-#define PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE	 101
-#define PKCS7_R_SIGNATURE_FAILURE			 102
-#define PKCS7_R_UNABLE_TO_FIND_CERTIFICATE		 103
-#define PKCS7_R_UNABLE_TO_FIND_MEM_BIO			 104
-#define PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST		 105
-#define PKCS7_R_UNKNOWN_DIGEST_TYPE			 106
-#define PKCS7_R_UNSUPPORTED_CIPHER_TYPE			 107
-#define PKCS7_R_UNSUPPORTED_CONTENT_TYPE		 108
-#define PKCS7_R_WRONG_CONTENT_TYPE			 109
+#define PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH		 100
+#define PKCS7_R_DIGEST_FAILURE				 101
+#define PKCS7_R_INTERNAL_ERROR				 102
+#define PKCS7_R_MISSING_CERIPEND_INFO			 103
+#define PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE	 104
+#define PKCS7_R_SIGNATURE_FAILURE			 105
+#define PKCS7_R_UNABLE_TO_FIND_CERTIFICATE		 106
+#define PKCS7_R_UNABLE_TO_FIND_MEM_BIO			 107
+#define PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST		 108
+#define PKCS7_R_UNKNOWN_DIGEST_TYPE			 109
+#define PKCS7_R_UNKNOWN_OPERATION			 110
+#define PKCS7_R_UNSUPPORTED_CIPHER_TYPE			 111
+#define PKCS7_R_UNSUPPORTED_CONTENT_TYPE		 112
+#define PKCS7_R_WRONG_CONTENT_TYPE			 113
+#define PKCS7_R_WRONG_PKCS7_TYPE			 114
diff --git a/crypto/pkcs7/pkcs7.h b/crypto/pkcs7/pkcs7.h
index ee12f67..01afa5a 100644
--- a/crypto/pkcs7/pkcs7.h
+++ b/crypto/pkcs7/pkcs7.h
@@ -199,7 +199,12 @@
 #define PKCS7_OP_SET_DETACHED_SIGNATURE	1
 #define PKCS7_OP_GET_DETACHED_SIGNATURE	2
 
+#define PKCS7_get_signed_attributes(si)	((si)->auth_attr)
+#define PKCS7_get_attributes(si)	((si)->unauth_attr)
+
 #define PKCS7_type_is_signed(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_signed)
+#define PKCS7_type_is_signedAndEnveloped(a) \
+		(OBJ_obj2nid((a)->type) == NID_pkcs7_signedAndEnveloped)
 #define PKCS7_type_is_data(a)   (OBJ_obj2nid((a)->type) == NID_pkcs7_data)
 
 #define PKCS7_set_detached(p,v) \
@@ -208,11 +213,12 @@
 		PKCS7_ctrl(p,PKCS7_OP_GET_DETACHED_SIGNATURE,0,NULL)
 
 #ifdef SSLEAY_MACROS
-
+#ifndef PKCS7_ISSUER_AND_SERIAL_digest
 #define PKCS7_ISSUER_AND_SERIAL_digest(data,type,md,len) \
         ASN1_digest((int (*)())i2d_PKCS7_ISSUER_AND_SERIAL,type,\
 	                (char *)data,md,len)
 #endif
+#endif
 
 
 #ifndef NOPROTO
@@ -314,12 +320,13 @@
 int PKCS7_add_certificate(PKCS7 *p7, X509 *x509);
 int PKCS7_add_crl(PKCS7 *p7, X509_CRL *x509);
 int PKCS7_content_new(PKCS7 *p7, int nid);
-int PKCS7_dataSign(PKCS7 *p7, BIO *bio);
 int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx,
 	BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si); 
 
 BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio);
-/*int PKCS7_DataFinal(PKCS7 *p7, BIO *bio); */
+int PKCS7_dataFinal(PKCS7 *p7, BIO *bio);
+BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509_STORE *xs);
+
 
 PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509,
 	EVP_PKEY *pkey, EVP_MD *dgst);
@@ -331,6 +338,16 @@
 int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509);
 int PKCS7_set_cipher(PKCS7 *p7, EVP_CIPHER *cipher);
 
+PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx);
+ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK *sk);
+int PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si,int nid,int type,
+	char *data);
+int PKCS7_add_attribute (PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
+	char *value);
+ASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid);
+ASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid);
+int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si, STACK *sk);
+int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, STACK *sk);
 
 
 #else
@@ -400,7 +417,6 @@
 int PKCS7_add_certificate();
 int PKCS7_add_crl();
 int PKCS7_content_new();
-int PKCS7_dataSign();
 int PKCS7_dataVerify();
 BIO *PKCS7_dataInit();
 PKCS7_SIGNER_INFO *PKCS7_add_signature();
@@ -412,8 +428,18 @@
 int PKCS7_RECIP_INFO_set();
 int PKCS7_set_cipher();
 
+PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial();
+ASN1_OCTET_STRING *PKCS7_digest_from_attributes();
+int PKCS7_add_signed_attribute();
+int PKCS7_add_attribute();
+ASN1_TYPE *PKCS7_get_attribute();
+ASN1_TYPE *PKCS7_get_signed_attribute();
+void PKCS7_set_signed_attributes();
+void PKCS7_set_attributes();
+
 #endif
 
+
 /* BEGIN ERROR CODES */
 /* Error codes for the PKCS7 functions. */
 
@@ -429,18 +455,24 @@
 #define PKCS7_F_PKCS7_SET_CIPHER			 108
 #define PKCS7_F_PKCS7_SET_CONTENT			 109
 #define PKCS7_F_PKCS7_SET_TYPE				 110
+#define PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT		 111
 
 /* Reason codes. */
-#define PKCS7_R_INTERNAL_ERROR				 100
-#define PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE	 101
-#define PKCS7_R_SIGNATURE_FAILURE			 102
-#define PKCS7_R_UNABLE_TO_FIND_CERTIFICATE		 103
-#define PKCS7_R_UNABLE_TO_FIND_MEM_BIO			 104
-#define PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST		 105
-#define PKCS7_R_UNKNOWN_DIGEST_TYPE			 106
-#define PKCS7_R_UNSUPPORTED_CIPHER_TYPE			 107
-#define PKCS7_R_UNSUPPORTED_CONTENT_TYPE		 108
-#define PKCS7_R_WRONG_CONTENT_TYPE			 109
+#define PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH		 100
+#define PKCS7_R_DIGEST_FAILURE				 101
+#define PKCS7_R_INTERNAL_ERROR				 102
+#define PKCS7_R_MISSING_CERIPEND_INFO			 103
+#define PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE	 104
+#define PKCS7_R_SIGNATURE_FAILURE			 105
+#define PKCS7_R_UNABLE_TO_FIND_CERTIFICATE		 106
+#define PKCS7_R_UNABLE_TO_FIND_MEM_BIO			 107
+#define PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST		 108
+#define PKCS7_R_UNKNOWN_DIGEST_TYPE			 109
+#define PKCS7_R_UNKNOWN_OPERATION			 110
+#define PKCS7_R_UNSUPPORTED_CIPHER_TYPE			 111
+#define PKCS7_R_UNSUPPORTED_CONTENT_TYPE		 112
+#define PKCS7_R_WRONG_CONTENT_TYPE			 113
+#define PKCS7_R_WRONG_PKCS7_TYPE			 114
  
 #ifdef  __cplusplus
 }
diff --git a/crypto/pkcs7/pkcs7err.c b/crypto/pkcs7/pkcs7err.c
index f851057..f60c856 100644
--- a/crypto/pkcs7/pkcs7err.c
+++ b/crypto/pkcs7/pkcs7err.c
@@ -74,21 +74,27 @@
 {ERR_PACK(0,PKCS7_F_PKCS7_SET_CIPHER,0),	"PKCS7_set_cipher"},
 {ERR_PACK(0,PKCS7_F_PKCS7_SET_CONTENT,0),	"PKCS7_set_content"},
 {ERR_PACK(0,PKCS7_F_PKCS7_SET_TYPE,0),	"PKCS7_set_type"},
+{ERR_PACK(0,PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,0),	"PKCS7_SIGNENVELOPEDECRYPT"},
 {0,NULL},
 	};
 
 static ERR_STRING_DATA PKCS7_str_reasons[]=
 	{
+{PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH   ,"decrypted key is wrong length"},
+{PKCS7_R_DIGEST_FAILURE                  ,"digest failure"},
 {PKCS7_R_INTERNAL_ERROR                  ,"internal error"},
+{PKCS7_R_MISSING_CERIPEND_INFO           ,"missing ceripend info"},
 {PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE,"operation not supported on this type"},
 {PKCS7_R_SIGNATURE_FAILURE               ,"signature failure"},
 {PKCS7_R_UNABLE_TO_FIND_CERTIFICATE      ,"unable to find certificate"},
 {PKCS7_R_UNABLE_TO_FIND_MEM_BIO          ,"unable to find mem bio"},
 {PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST   ,"unable to find message digest"},
 {PKCS7_R_UNKNOWN_DIGEST_TYPE             ,"unknown digest type"},
+{PKCS7_R_UNKNOWN_OPERATION               ,"unknown operation"},
 {PKCS7_R_UNSUPPORTED_CIPHER_TYPE         ,"unsupported cipher type"},
 {PKCS7_R_UNSUPPORTED_CONTENT_TYPE        ,"unsupported content type"},
 {PKCS7_R_WRONG_CONTENT_TYPE              ,"wrong content type"},
+{PKCS7_R_WRONG_PKCS7_TYPE                ,"wrong pkcs7 type"},
 {0,NULL},
 	};
 
@@ -98,8 +104,8 @@
 	{
 	static int init=1;
 
-	if (init);
-		{;
+	if (init)
+		{
 		init=0;
 #ifndef NO_ERR
 		ERR_load_strings(ERR_LIB_PKCS7,PKCS7_str_functs);
diff --git a/crypto/pkcs7/sign.c b/crypto/pkcs7/sign.c
index ead1cb6..6ad88d4 100644
--- a/crypto/pkcs7/sign.c
+++ b/crypto/pkcs7/sign.c
@@ -105,7 +105,13 @@
 	p7=PKCS7_new();
 	PKCS7_set_type(p7,NID_pkcs7_signed);
 	 
-	if (PKCS7_add_signature(p7,x509,pkey,EVP_sha1()) == NULL) goto err;
+	si=PKCS7_add_signature(p7,x509,pkey,EVP_sha1());
+	if (si == NULL) goto err;
+
+	/* Add some extra attributes */
+	if (!add_signed_time(si)) goto err;
+	if (!add_signed_string(si,"SIGNED STRING")) goto err;
+	if (!add_signed_seq2string(si,"STRING1","STRING2")) goto err;
 
 	/* we may want to add more */
 	PKCS7_add_certificate(p7,x509);
@@ -125,7 +131,7 @@
 		BIO_write(p7bio,buf,i);
 		}
 
-	if (!PKCS7_dataSign(p7,p7bio)) goto err;
+	if (!PKCS7_dataFinal(p7,p7bio)) goto err;
 	BIO_free(p7bio);
 
 	PEM_write_PKCS7(stdout,p7);
diff --git a/crypto/pkcs7/t/3des.pem b/crypto/pkcs7/t/3des.pem
new file mode 100644
index 0000000..b2b5081
--- /dev/null
+++ b/crypto/pkcs7/t/3des.pem
@@ -0,0 +1,16 @@
+-----BEGIN PKCS7-----
+MIAGCSqGSIb3DQEHA6CAMIACAQAxggHmMIHwAgEAMIGZMIGSMQswCQYDVQQGEwJBVTETMBEG
+A1UECBMKUXVlZW5zbGFuZDERMA8GA1UEBxMIQnJpc2JhbmUxGjAYBgNVBAoTEUNyeXB0c29m
+dCBQdHkgTHRkMSIwIAYDVQQLExlERU1PTlNUUkFUSU9OIEFORCBURVNUSU5HMRswGQYDVQQD
+ExJERU1PIFpFUk8gVkFMVUUgQ0ECAgR+MA0GCSqGSIb3DQEBAQUABEC2vXI1xQDW6lUHM3zQ
+/9uBEBOO5A3TtkrklAXq7v01gsIC21t52qSk36REXY+slhNZ0OQ349tgkTsoETHFLoEwMIHw
+AgEAMIGZMIGSMQswCQYDVQQGEwJBVTETMBEGA1UECBMKUXVlZW5zbGFuZDERMA8GA1UEBxMI
+QnJpc2JhbmUxGjAYBgNVBAoTEUNyeXB0c29mdCBQdHkgTHRkMSIwIAYDVQQLExlERU1PTlNU
+UkFUSU9OIEFORCBURVNUSU5HMRswGQYDVQQDExJERU1PIFpFUk8gVkFMVUUgQ0ECAgR9MA0G
+CSqGSIb3DQEBAQUABEB8ujxbabxXUYJhopuDm3oDq4JNqX6Io4p3ro+ShqfIndsXTZ1v5a2N
+WtLLCWlHn/habjBwZ/DgQgcKASbZ7QxNMIAGCSqGSIb3DQEHATAaBggqhkiG9w0DAjAOAgIA
+oAQIbsL5v1wX98KggAQoAaJ4WHm68fXY1WE5OIjfVBIDpO1K+i8dmKhjnAjrjoyZ9Bwc8rDL
+lgQg4CXb805h5xl+GfvSwUaHJayte1m2mcOhs3J2YyqbQ+MEIMIiJQccmhO3oDKm36CFvYR8
+5PjpclVcZyX2ngbwPFMnBAgy0clOAE6UKAAAAAAAAAAAAAA=
+-----END PKCS7-----
+
diff --git a/crypto/pkcs7/t/3dess.pem b/crypto/pkcs7/t/3dess.pem
new file mode 100644
index 0000000..23f0135
--- /dev/null
+++ b/crypto/pkcs7/t/3dess.pem
@@ -0,0 +1,32 @@
+-----BEGIN PKCS7-----
+MIIGHgYJKoZIhvcNAQcCoIIGDzCCBgsCAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHAaCC
+BGswggJTMIIB/aADAgECAgIEfjANBgkqhkiG9w0BAQQFADCBkjELMAkGA1UEBhMCQVUxEzAR
+BgNVBAgTClF1ZWVuc2xhbmQxETAPBgNVBAcTCEJyaXNiYW5lMRowGAYDVQQKExFDcnlwdHNv
+ZnQgUHR5IEx0ZDEiMCAGA1UECxMZREVNT05TVFJBVElPTiBBTkQgVEVTVElORzEbMBkGA1UE
+AxMSREVNTyBaRVJPIFZBTFVFIENBMB4XDTk4MDUxMzA2MjY1NloXDTAwMDUxMjA2MjY1Nlow
+gaUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpRdWVlbnNsYW5kMREwDwYDVQQHEwhCcmlzYmFu
+ZTEaMBgGA1UEChMRQ3J5cHRzb2Z0IFB0eSBMdGQxEjAQBgNVBAsTCVNNSU1FIDAwMzEZMBcG
+A1UEAxMQQW5nZWxhIHZhbiBMZWVudDEjMCEGCSqGSIb3DQEJARYUYW5nZWxhQGNyeXB0c29m
+dC5jb20wXDANBgkqhkiG9w0BAQEFAANLADBIAkEAuC3+7dAb2LhuO7gt2cTM8vsNjhG5JfDh
+hX1Vl/wVGbKEEj0MA6vWEolvefQlxB+EzwCtR0YZ7eEC/T/4JoCyeQIDAQABoygwJjAkBglg
+hkgBhvhCAQ0EFxYVR2VuZXJhdGVkIHdpdGggU1NMZWF5MA0GCSqGSIb3DQEBBAUAA0EAUnSP
+igs6TMFISTjw8cBtJYb98czgAVkVFjKyJQwYMH8FbDnCyx6NocM555nsyDstaw8fKR11Khds
+syd3ikkrhDCCAhAwggG6AgEDMA0GCSqGSIb3DQEBBAUAMIGSMQswCQYDVQQGEwJBVTETMBEG
+A1UECBMKUXVlZW5zbGFuZDERMA8GA1UEBxMIQnJpc2JhbmUxGjAYBgNVBAoTEUNyeXB0c29m
+dCBQdHkgTHRkMSIwIAYDVQQLExlERU1PTlNUUkFUSU9OIEFORCBURVNUSU5HMRswGQYDVQQD
+ExJERU1PIFpFUk8gVkFMVUUgQ0EwHhcNOTgwMzAzMDc0MTMyWhcNMDgwMjI5MDc0MTMyWjCB
+kjELMAkGA1UEBhMCQVUxEzARBgNVBAgTClF1ZWVuc2xhbmQxETAPBgNVBAcTCEJyaXNiYW5l
+MRowGAYDVQQKExFDcnlwdHNvZnQgUHR5IEx0ZDEiMCAGA1UECxMZREVNT05TVFJBVElPTiBB
+TkQgVEVTVElORzEbMBkGA1UEAxMSREVNTyBaRVJPIFZBTFVFIENBMFwwDQYJKoZIhvcNAQEB
+BQADSwAwSAJBAL+0E2fLej3FSCwe2A2iRnMuC3z12qHIp6Ky1wo2zZcxft7AI+RfkrWrSGtf
+mfzBEuPrLdfulncC5Y1pNcM8RTUCAwEAATANBgkqhkiG9w0BAQQFAANBAGSbLMphL6F5pp3s
+8o0Xyh86FHFdpVOwYx09ELLkuG17V/P9pgIc0Eo/gDMbN+KT3IdgECf8S//pCRA6RrNjcXIx
+ggF7MIIBdwIBATCBmTCBkjELMAkGA1UEBhMCQVUxEzARBgNVBAgTClF1ZWVuc2xhbmQxETAP
+BgNVBAcTCEJyaXNiYW5lMRowGAYDVQQKExFDcnlwdHNvZnQgUHR5IEx0ZDEiMCAGA1UECxMZ
+REVNT05TVFJBVElPTiBBTkQgVEVTVElORzEbMBkGA1UEAxMSREVNTyBaRVJPIFZBTFVFIENB
+AgIEfjAJBgUrDgMCGgUAoHowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAbBgkqhkiG9w0B
+CQ8xDjAMMAoGCCqGSIb3DQMHMBwGCSqGSIb3DQEJBTEPFw05ODA1MTQwMzM5MzdaMCMGCSqG
+SIb3DQEJBDEWBBQstNMnSV26ba8PapQEDhO21yNFrjANBgkqhkiG9w0BAQEFAARAW9Xb9YXv
+BfcNkutgFX9Gr8iXhBVsNtGEVrjrpkQwpKa7jHI8SjAlLhk/4RFwDHf+ISB9Np3Z1WDWnLcA
+9CWR6g==
+-----END PKCS7-----
diff --git a/crypto/pkcs7/t/c.pem b/crypto/pkcs7/t/c.pem
new file mode 100644
index 0000000..a4b55e3
--- /dev/null
+++ b/crypto/pkcs7/t/c.pem
@@ -0,0 +1,48 @@
+issuer :/C=AU/SP=Queensland/L=Brisbane/O=Cryptsoft Pty Ltd/OU=DEMONSTRATION AND TESTING/CN=DEMO ZERO VALUE CA
+subject:/C=AU/SP=Queensland/L=Brisbane/O=Cryptsoft Pty Ltd/OU=SMIME 003/CN=Information/Email=info@cryptsoft.com
+serial :047D
+
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1149 (0x47d)
+        Signature Algorithm: md5withRSAEncryption
+        Issuer: C=AU, SP=Queensland, L=Brisbane, O=Cryptsoft Pty Ltd, OU=DEMONSTRATION AND TESTING, CN=DEMO ZERO VALUE CA
+        Validity
+            Not Before: May 13 05:40:58 1998 GMT
+            Not After : May 12 05:40:58 2000 GMT
+        Subject: C=AU, SP=Queensland, L=Brisbane, O=Cryptsoft Pty Ltd, OU=SMIME 003, CN=Information/Email=info@cryptsoft.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Modulus:
+                    00:ad:e7:23:89:ee:0d:87:b7:9c:32:44:4b:95:81:
+                    73:dd:22:80:4b:2d:c5:60:b8:fe:1e:18:63:ef:dc:
+                    89:89:22:df:95:3c:7a:db:3d:9a:06:a8:08:d6:29:
+                    fd:ef:41:09:91:ed:bc:ad:98:f9:f6:28:90:62:6f:
+                    e7:e7:0c:4d:0b
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            Netscape Comment: 
+                Generated with SSLeay
+    Signature Algorithm: md5withRSAEncryption
+        52:15:ea:88:f4:f0:f9:0b:ef:ce:d5:f8:83:40:61:16:5e:55:
+        f9:ce:2d:d1:8b:31:5c:03:c6:2d:10:7c:61:d5:5c:0a:42:97:
+        d1:fd:65:b6:b6:84:a5:39:ec:46:ec:fc:e0:0d:d9:22:da:1b:
+        50:74:ad:92:cb:4e:90:e5:fa:7d
+
+-----BEGIN CERTIFICATE-----
+MIICTDCCAfagAwIBAgICBH0wDQYJKoZIhvcNAQEEBQAwgZIxCzAJBgNVBAYTAkFV
+MRMwEQYDVQQIEwpRdWVlbnNsYW5kMREwDwYDVQQHEwhCcmlzYmFuZTEaMBgGA1UE
+ChMRQ3J5cHRzb2Z0IFB0eSBMdGQxIjAgBgNVBAsTGURFTU9OU1RSQVRJT04gQU5E
+IFRFU1RJTkcxGzAZBgNVBAMTEkRFTU8gWkVSTyBWQUxVRSBDQTAeFw05ODA1MTMw
+NTQwNThaFw0wMDA1MTIwNTQwNThaMIGeMQswCQYDVQQGEwJBVTETMBEGA1UECBMK
+UXVlZW5zbGFuZDERMA8GA1UEBxMIQnJpc2JhbmUxGjAYBgNVBAoTEUNyeXB0c29m
+dCBQdHkgTHRkMRIwEAYDVQQLEwlTTUlNRSAwMDMxFDASBgNVBAMTC0luZm9ybWF0
+aW9uMSEwHwYJKoZIhvcNAQkBFhJpbmZvQGNyeXB0c29mdC5jb20wXDANBgkqhkiG
+9w0BAQEFAANLADBIAkEArecjie4Nh7ecMkRLlYFz3SKASy3FYLj+Hhhj79yJiSLf
+lTx62z2aBqgI1in970EJke28rZj59iiQYm/n5wxNCwIDAQABoygwJjAkBglghkgB
+hvhCAQ0EFxYVR2VuZXJhdGVkIHdpdGggU1NMZWF5MA0GCSqGSIb3DQEBBAUAA0EA
+UhXqiPTw+QvvztX4g0BhFl5V+c4t0YsxXAPGLRB8YdVcCkKX0f1ltraEpTnsRuz8
+4A3ZItobUHStkstOkOX6fQ==
+-----END CERTIFICATE-----
+
diff --git a/crypto/pkcs7/t/f b/crypto/pkcs7/t/f
new file mode 100644
index 0000000..7f5dc67
--- /dev/null
+++ b/crypto/pkcs7/t/f
@@ -0,0 +1,2 @@
+signed body
+
diff --git a/crypto/pkcs7/t/ff b/crypto/pkcs7/t/ff
new file mode 100644
index 0000000..23f0135
--- /dev/null
+++ b/crypto/pkcs7/t/ff
@@ -0,0 +1,32 @@
+-----BEGIN PKCS7-----
+MIIGHgYJKoZIhvcNAQcCoIIGDzCCBgsCAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHAaCC
+BGswggJTMIIB/aADAgECAgIEfjANBgkqhkiG9w0BAQQFADCBkjELMAkGA1UEBhMCQVUxEzAR
+BgNVBAgTClF1ZWVuc2xhbmQxETAPBgNVBAcTCEJyaXNiYW5lMRowGAYDVQQKExFDcnlwdHNv
+ZnQgUHR5IEx0ZDEiMCAGA1UECxMZREVNT05TVFJBVElPTiBBTkQgVEVTVElORzEbMBkGA1UE
+AxMSREVNTyBaRVJPIFZBTFVFIENBMB4XDTk4MDUxMzA2MjY1NloXDTAwMDUxMjA2MjY1Nlow
+gaUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpRdWVlbnNsYW5kMREwDwYDVQQHEwhCcmlzYmFu
+ZTEaMBgGA1UEChMRQ3J5cHRzb2Z0IFB0eSBMdGQxEjAQBgNVBAsTCVNNSU1FIDAwMzEZMBcG
+A1UEAxMQQW5nZWxhIHZhbiBMZWVudDEjMCEGCSqGSIb3DQEJARYUYW5nZWxhQGNyeXB0c29m
+dC5jb20wXDANBgkqhkiG9w0BAQEFAANLADBIAkEAuC3+7dAb2LhuO7gt2cTM8vsNjhG5JfDh
+hX1Vl/wVGbKEEj0MA6vWEolvefQlxB+EzwCtR0YZ7eEC/T/4JoCyeQIDAQABoygwJjAkBglg
+hkgBhvhCAQ0EFxYVR2VuZXJhdGVkIHdpdGggU1NMZWF5MA0GCSqGSIb3DQEBBAUAA0EAUnSP
+igs6TMFISTjw8cBtJYb98czgAVkVFjKyJQwYMH8FbDnCyx6NocM555nsyDstaw8fKR11Khds
+syd3ikkrhDCCAhAwggG6AgEDMA0GCSqGSIb3DQEBBAUAMIGSMQswCQYDVQQGEwJBVTETMBEG
+A1UECBMKUXVlZW5zbGFuZDERMA8GA1UEBxMIQnJpc2JhbmUxGjAYBgNVBAoTEUNyeXB0c29m
+dCBQdHkgTHRkMSIwIAYDVQQLExlERU1PTlNUUkFUSU9OIEFORCBURVNUSU5HMRswGQYDVQQD
+ExJERU1PIFpFUk8gVkFMVUUgQ0EwHhcNOTgwMzAzMDc0MTMyWhcNMDgwMjI5MDc0MTMyWjCB
+kjELMAkGA1UEBhMCQVUxEzARBgNVBAgTClF1ZWVuc2xhbmQxETAPBgNVBAcTCEJyaXNiYW5l
+MRowGAYDVQQKExFDcnlwdHNvZnQgUHR5IEx0ZDEiMCAGA1UECxMZREVNT05TVFJBVElPTiBB
+TkQgVEVTVElORzEbMBkGA1UEAxMSREVNTyBaRVJPIFZBTFVFIENBMFwwDQYJKoZIhvcNAQEB
+BQADSwAwSAJBAL+0E2fLej3FSCwe2A2iRnMuC3z12qHIp6Ky1wo2zZcxft7AI+RfkrWrSGtf
+mfzBEuPrLdfulncC5Y1pNcM8RTUCAwEAATANBgkqhkiG9w0BAQQFAANBAGSbLMphL6F5pp3s
+8o0Xyh86FHFdpVOwYx09ELLkuG17V/P9pgIc0Eo/gDMbN+KT3IdgECf8S//pCRA6RrNjcXIx
+ggF7MIIBdwIBATCBmTCBkjELMAkGA1UEBhMCQVUxEzARBgNVBAgTClF1ZWVuc2xhbmQxETAP
+BgNVBAcTCEJyaXNiYW5lMRowGAYDVQQKExFDcnlwdHNvZnQgUHR5IEx0ZDEiMCAGA1UECxMZ
+REVNT05TVFJBVElPTiBBTkQgVEVTVElORzEbMBkGA1UEAxMSREVNTyBaRVJPIFZBTFVFIENB
+AgIEfjAJBgUrDgMCGgUAoHowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAbBgkqhkiG9w0B
+CQ8xDjAMMAoGCCqGSIb3DQMHMBwGCSqGSIb3DQEJBTEPFw05ODA1MTQwMzM5MzdaMCMGCSqG
+SIb3DQEJBDEWBBQstNMnSV26ba8PapQEDhO21yNFrjANBgkqhkiG9w0BAQEFAARAW9Xb9YXv
+BfcNkutgFX9Gr8iXhBVsNtGEVrjrpkQwpKa7jHI8SjAlLhk/4RFwDHf+ISB9Np3Z1WDWnLcA
+9CWR6g==
+-----END PKCS7-----
diff --git a/crypto/pkcs7/t/msie-e b/crypto/pkcs7/t/msie-e
new file mode 100644
index 0000000..aafae69
--- /dev/null
+++ b/crypto/pkcs7/t/msie-e
@@ -0,0 +1,20 @@
+
+MIAGCSqGSIb3DQEHA6CAMIACAQAxggHCMIHMAgEAMHYwYjERMA8GA1UEBxMISW50ZXJuZXQxFzAV
+BgNVBAoTDlZlcmlTaWduLCBJbmMuMTQwMgYDVQQLEytWZXJpU2lnbiBDbGFzcyAxIENBIC0gSW5k
+aXZpZHVhbCBTdWJzY3JpYmVyAhBgQJiC3qfbCbjdj5INYLnKMA0GCSqGSIb3DQEBAQUABECMzu8y
+wQ/qZbO8cAGMRBF+mPruv3+Dvb9aWNZ2k8njUgqF6mcdhVB2MkGcsG3memRXJBixvMYWVkU3qK4Z
+VuKsMIHwAgEAMIGZMIGSMQswCQYDVQQGEwJBVTETMBEGA1UECBMKUXVlZW5zbGFuZDERMA8GA1UE
+BxMIQnJpc2JhbmUxGjAYBgNVBAoTEUNyeXB0c29mdCBQdHkgTHRkMSIwIAYDVQQLExlERU1PTlNU
+UkFUSU9OIEFORCBURVNUSU5HMRswGQYDVQQDExJERU1PIFpFUk8gVkFMVUUgQ0ECAgRuMA0GCSqG
+SIb3DQEBAQUABEBcWwYFHJbJGhiztt7lzue3Lc9CH5WAbyR+2BZ3uv+JxZfRs1PuaWPOwRa0Vgs3
+YwSJoRfxQj2Gk0wFqG1qt6d1MIAGCSqGSIb3DQEHATAaBggqhkiG9w0DAjAOAgIAoAQI8vRlP/Nx
+2iSggASCAZhR5srxyspy7DfomRJ9ff8eMCtaNwEoEx7G25PZRonC57hBvGoScLtEPU3Wp9FEbPN7
+oJESeC+AqMTyTLNy8aQsyC5s53E9UkoIvg62ekYZBbXZqXsrxx4PhiiX3NH8GVh42phB0Chjw0nK
+HZeRDmxGY3Cmk+J+l0uVKxbNIfJIKOguLBnhqmnKH/PrnzDt591u0ULy2aTLqRm+4/1Yat/QPb6J
+eoKGwNPBbS9ogBdrCNCp9ZFg3Xar2AtQHzyTQIfYeH3SRQUpKmRm5U5o9p5emgEdT+ZfJm/J4tSH
+OmbgAFsbHQakA4MBZ4J5qfDJhOA2g5lWk1hIeu5Dn/AaLRZd0yz3oY0Ieo/erPWx/bCqtBzYbMe9
+qSFTedKlbc9EGe3opOTdBZVzK8KH3w3zsy5luxKdOUG59YYb5F1IZiWGiDyuo/HuacX+griu5LeD
+bEzOtZnko+TZXvWIko30fD79j3T4MRRhWXbgj2HKza+4vJ0mzcC/1+GPsJjAEAA/JgIEDU4w6/DI
+/HQHhLAO3G+9xKD7MvmrzkoAAAAAAAAAAAAA
+
+
diff --git a/crypto/pkcs7/t/msie-e.pem b/crypto/pkcs7/t/msie-e.pem
new file mode 100644
index 0000000..a2a5e24
--- /dev/null
+++ b/crypto/pkcs7/t/msie-e.pem
@@ -0,0 +1,22 @@
+-----BEGIN PKCS7-----
+MIAGCSqGSIb3DQEHA6CAMIIDkAIBADGCAcIwgcwCAQAwdjBiMREwDwYDVQQHEwhJ
+bnRlcm5ldDEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNDAyBgNVBAsTK1ZlcmlT
+aWduIENsYXNzIDEgQ0EgLSBJbmRpdmlkdWFsIFN1YnNjcmliZXICEGBAmILep9sJ
+uN2Pkg1gucowDQYJKoZIhvcNAQEBBQAEQIzO7zLBD+pls7xwAYxEEX6Y+u6/f4O9
+v1pY1naTyeNSCoXqZx2FUHYyQZywbeZ6ZFckGLG8xhZWRTeorhlW4qwwgfACAQAw
+gZkwgZIxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpRdWVlbnNsYW5kMREwDwYDVQQH
+EwhCcmlzYmFuZTEaMBgGA1UEChMRQ3J5cHRzb2Z0IFB0eSBMdGQxIjAgBgNVBAsT
+GURFTU9OU1RSQVRJT04gQU5EIFRFU1RJTkcxGzAZBgNVBAMTEkRFTU8gWkVSTyBW
+QUxVRSBDQQICBG4wDQYJKoZIhvcNAQEBBQAEQFxbBgUclskaGLO23uXO57ctz0If
+lYBvJH7YFne6/4nFl9GzU+5pY87BFrRWCzdjBImhF/FCPYaTTAWobWq3p3UwggHD
+BgkqhkiG9w0BBwEwGgYIKoZIhvcNAwIwDgICAKAECPL0ZT/zcdokgIIBmFHmyvHK
+ynLsN+iZEn19/x4wK1o3ASgTHsbbk9lGicLnuEG8ahJwu0Q9Tdan0URs83ugkRJ4
+L4CoxPJMs3LxpCzILmzncT1SSgi+DrZ6RhkFtdmpeyvHHg+GKJfc0fwZWHjamEHQ
+KGPDScodl5EObEZjcKaT4n6XS5UrFs0h8kgo6C4sGeGqacof8+ufMO3n3W7RQvLZ
+pMupGb7j/Vhq39A9vol6gobA08FtL2iAF2sI0Kn1kWDddqvYC1AfPJNAh9h4fdJF
+BSkqZGblTmj2nl6aAR1P5l8mb8ni1Ic6ZuAAWxsdBqQDgwFngnmp8MmE4DaDmVaT
+WEh67kOf8BotFl3TLPehjQh6j96s9bH9sKq0HNhsx72pIVN50qVtz0QZ7eik5N0F
+lXMrwoffDfOzLmW7Ep05Qbn1hhvkXUhmJYaIPK6j8e5pxf6CuK7kt4NsTM61meSj
+5Nle9YiSjfR8Pv2PdPgxFGFZduCPYcrNr7i8nSbNwL/X4Y+wmMAQAD8mAgQNTjDr
+8Mj8dAeEsA7cb73EoPsy+avOSgAAAAA=
+-----END PKCS7-----
diff --git a/crypto/pkcs7/t/msie-enc-01 b/crypto/pkcs7/t/msie-enc-01
new file mode 100644
index 0000000..2c93ab6
--- /dev/null
+++ b/crypto/pkcs7/t/msie-enc-01
@@ -0,0 +1,62 @@
+
+MIAGCSqGSIb3DQEHA6CAMIACAQAxgfMwgfACAQAwgZkwgZIxCzAJBgNVBAYTAkFVMRMwEQYD
+VQQIEwpRdWVlbnNsYW5kMREwDwYDVQQHEwhCcmlzYmFuZTEaMBgGA1UEChMRQ3J5cHRzb2Z0
+IFB0eSBMdGQxIjAgBgNVBAsTGURFTU9OU1RSQVRJT04gQU5EIFRFU1RJTkcxGzAZBgNVBAMT
+EkRFTU8gWkVSTyBWQUxVRSBDQQICBG4wDQYJKoZIhvcNAQEBBQAEQKvMaW8xh6oF/X+CJivz
+IZV7yHxlp4O3NHQtWG0A8MOZB+CtKlU7/6g5e/a9Du/TOqxRMqtYRp63pa2Q/mM4IYMwgAYJ
+KoZIhvcNAQcBMBoGCCqGSIb3DQMCMA4CAgCgBAifz6RvzOPYlKCABIGwxtGA/FLBBRs1wbBP
+gDCbSG0yCwjJNsFg89/k6xuXo8c5YTwsw8+XlIVq03navpew6XxxzY090rD2OJ0t6HA6GqrI
+pd8WiSh/Atqn0yfLFmkLqgIAPRfzxUxqUocxLpQsLIFp2YNUGE+yps+UZmIjw/WHfdqrcWTm
+STSvKuy3UkIJZCkGDBpTvqk4BFaHh4oTXEpgpNY+GKxjf9TDN9GQPqQZR7sgQki4t2g4/Saq
+Kl4EMISgluk6swdND0tiHY7v5d6YR29ePCl2/STJ98eJpWkEEC22GNNvOy7ru/Rv2He4MgQg
+optd7sk9MMd9xhJppg7CcH/yDx//HrtgpOcWmn6VxpgECFqon4uXkQtIBIH4PaNclFn7/hLx
+Pw2VmBGaC0SYF3U1jyN96EBxdjqy8Aa6ByMXYDW5BcfqniD5mYXfw+b81lh1kutxaPaV4YJ9
+ZlRUW752N7VHo/fG0/fukoe5W9a8kIhgLpygllb/GP4oSF4wM6n1/OgRzZj2IWFiobKO4d/t
+Mnh+C+PoEVAuFZcxQwi9GqvsK5OoIjVwNx0XcVSOl1TTYS9SwC7ugMBCab73JiruC24pL78Y
+M+NaIpIQ3On4DokJA2ZHtjBjZIxF4tKA144RvFN6pBd6TVE5XM6KD/Vh9bjSmujtEAfdQ3Te
+dvKJsbZuu0stErbvWcRy11I328l557EECAJT7d44OJ3rBBBj6bnnx6dDU2SRqp2CEoQaBAhK
+RBuyhNxkygQIOY9/NhwqAJAECOvX0Zd0DqgoBAjobPpMHhVV3gQQWLU2vEoZ51BwzxdzCmxO
+wwQI4oKfudaNqoAESKzBNAqv5kGumHOlMKsRfrs7jZCcSaOuEj97pYx08FLEgF23cav39MOQ
+NUEM1dNU+EYslL4o3RoSHRjUgPU+2t9c0prS9A/bPARIEOP94PynaTNxwHi3VTK7SzuQmgzA
+4n942E9joSiqsQPlsKAb3sPUaLC3SuUxSjNBgfpvD0bmrA/5h+WZoYXvIogFpwjkSmnFBEie
+0lh5Ov1aRrvCw5/j3Q/W/4ZtN5U+aeVBJMtA8n0Mxd5kPxHbNVh4oGprZ6wEegV8ht3voyZa
+mZ5Cyxc8ffMYnM/JJI6/oEYEUEMyyiS5FnYyvxKzfMtyn2lZ2st9nZGNNgMc9N62r5HgNbdD
+FHuRdKKzV+8kQfuMc3mOPpK1t9TFY+QgrxiB5p6S7VooI97YtP3PbfknszCEBEh4PdXYbbaR
+3AacN3Q5kYYmWsq3WW6xgrg0mmEGosGvwSQxBBuiXZrxScCa4ivEq05UZwyShePvKduOvnUE
+2zDO6IXFLZxhTZAESEm9/FovLgGAiJ7iMGmYvsISLJScwG4n+wrSaQNQXizs9N3ykys54wBN
+d/+BQ4F7pncHhDQ2Dyt5MekB8Y8iNOocUTFCu524vQRIaWCXmXP3vU7D21dp0XnAMzRQJ565
+JV3aHRoY7XDa4LePa7PP9ywyafOE5yCW7ndqx3J+2JhTDvSFsW8/q3H3iyeFhykuJVS6BFDK
+6CmKbnyyjOfE2iLGJmTFa905V2KrVDCmlEu/xyGMs80yTyZC+ySzM83FMVvLEQmSzcTNUZVp
+DfA1kNXbXkPouBXXT6g8r8JCRljaKKABmgRIlMheOJQRUUU4cgvhMreXPayhq5Ao4VMSCkA5
+hYRCBczm4Di/MMohF0SxIsdRY6gY9CPnrBXAsY6h1RbR7Tw0iQZmeXi52DCiBEj0by+SYMAa
+9z0CReIzl8JLL6EVIFz8kFxlkGWjr4dnOzhhPOq/mCpp0WxbavDfdhE87MdXJZBnLwoT62QG
+955HlAoEQBOGJbcESCgd5XSirZ9Y3AbCfuKOqoMBvEUGn+w/pMaqnGvnr5FZhuBDKrhRXqtx
+QsxA//drGUxsrZOuSL/0+fbvo7n2h1Z8Ny86jOvVZAQIAjw2l1Yc5RAESNc9i3I8pKEOVQf/
+UBczJ0NR9aTEF80dRg2lpXwD0ho4N0AvSiVbgxC7cPZHQwIqvq9LHRUs/4n+Vu3SVYU3cAxo
+lUTiCGUSlARIF+TD57SI5+RI+MNtnD9rs4E1ml51YoHGWFj3UPriDmY0FKEwIgqtMXMY3fZ9
+Kq8d83bjDzxwbDX7WwR7KbSeJWT42pCz7kM+BEjjPsOnZHuusXT3x2rrsBnYtYsbt98mSFiS
+KzTtFmXfkOBbCQdit1P76QnYJ1aXMGs6zP6GypQTadK/zYWvlm38QkVwueaJ0woESKW2pqKA
+70h2UMDHOrpepU1lj0YMzmotDHSTU3L909VvUMNg9uqfrQ6mSkb9j5Tl8oF2otOw5EzA1Yda
+KPmgsv62RWLYl80wXQRQwG0e/mgG75jp9lOhJdVXqcYbQpS9viwVaVkwH+69mu/bQI4gjoEs
+UYX6O71Re2z+cYhcm9UrK+DXuSFBXQOIlAFxKMW4B0apd6fU84FsZLMESOorXE5OE0A2B2ji
+J8QI0Exk4hUvWrMNJfUZwFyS7E05xV9ORuX1xmsKqkT4tVR5Nqln4vhvAY860VBoloz0CDkd
+8seSBEjeMgRI9FvpYuflIeHg9urkwp6N+1f0DrJJhJY9ZQ0HTQhziJmIfvbEjNqCl7hEC28+
+F8I5tuViLgfSwcFFCvnS6WFoN4X6QdFdqMCbBEjdlI1c+IQGA/IuTDMJYCuQ/v+8BG5ZeWVH
+icPZmXfRat9eFK1dGKAJef6+Tf9HPuDjSpDyffrifsp7Dc34lmm7GN1+ON3ZMtwEUNm6epb8
+1RKWjoI7jIKUV/M2p/0eeGSqs4b06KF/VR6dBwsJVL5DpnTsp3MV4j/CAOlRdSPZ5++tsKbM
+aplk+ceqQtpEFz1MYTtVV4+rlrWaBEA1okJyNZ5/tNOwM7B+XfOZ0xw+uyVi9v4byTZM2Qds
+J+d3YGYLAugTGHISLqQEerD8/gGK+/SL06b2gNedXPHtBAiBKX+Mdy3wFQQIqE9gVgvrFNUE
+CKKoTFoMGqnPBAjDPgLCklNfrwQI3Ek1vSq68w8ECBodu2FOZJVkBAgzwjfSr2N9WQQQTCoQ
+KkAbrS9tnjXn1I3+ZwQIrPx3eINo/YUECIeYWCFskxlYBAiDUdvZXwD3vgQIkEyZbbZWbUUE
+CH4+odl1Isk3BBj68fkqJ0fKJRWVLWuW/O3VE4BOPKwFlaIECFseVTdDUho8BAj+cOKvV2WA
+hgQgaXr+wwq+ItblG0Qxz8IVUXX6PV2mIdHwz4SCCvnCsaIECJhBYxdfLI/XBCDswamPn9MR
+yXi2HVQBineV+GtWVkIoZ2dCLFB9mQRMoAQI0nUR5a5AOJoECA+AunKlAlx8BAi5RtFeF4g1
+FQQIz/ie+16LlQcECOmNuVg5DXjMBAjH2nkfpXZgWwQIVdLuO/+kuHAECO/5rEHmyI9vBBD4
+16BU4Rd3YerDQnHtrwOQBCCkho1XxK5Maz8KLCNi20wvcGt8wsIXlj2h5q9ITBq7IgQQvKVY
+4OfJ7bKbItP2dylwQgQYPIGxwkkbRXNraONYvN19G8UdF35rFOuIBAjf0sKz/618ZQQIxObr
+xJkRe0sECIC+ssnjEb2NBBBI+XM4OntVWGsRV9Td3sFgBAinGwIroo8O0gQQMGAwgc9PaLaG
+gBCiwSTrYQQIVHjfCQgOtygEUIoraFoANfhZgIShpOd/RRxFU4/7xZR5tMdGoYz/g0thR0lM
++Hi88FtFD4mAh/Oat4Ri8B7bv04aokjN2UHz6nPbHHjZ8zIqpbYTCy043GNZBAhOqjyB2JbD
+NwQoR23XCYD9x6E20ChHJRXmaHwyMdYXKl5CUxypl7ois+sy2D7jDukS3wQIsTyyPgJi0GsA
+AAAAAAAAAAAA
+
diff --git a/crypto/pkcs7/t/msie-enc-01.pem b/crypto/pkcs7/t/msie-enc-01.pem
new file mode 100644
index 0000000..9abf00b
--- /dev/null
+++ b/crypto/pkcs7/t/msie-enc-01.pem
@@ -0,0 +1,66 @@
+-----BEGIN PKCS7-----
+MIAGCSqGSIb3DQEHA6CAMIILyAIBADGB8zCB8AIBADCBmTCBkjELMAkGA1UEBhMC
+QVUxEzARBgNVBAgTClF1ZWVuc2xhbmQxETAPBgNVBAcTCEJyaXNiYW5lMRowGAYD
+VQQKExFDcnlwdHNvZnQgUHR5IEx0ZDEiMCAGA1UECxMZREVNT05TVFJBVElPTiBB
+TkQgVEVTVElORzEbMBkGA1UEAxMSREVNTyBaRVJPIFZBTFVFIENBAgIEbjANBgkq
+hkiG9w0BAQEFAARAq8xpbzGHqgX9f4ImK/MhlXvIfGWng7c0dC1YbQDww5kH4K0q
+VTv/qDl79r0O79M6rFEyq1hGnrelrZD+YzghgzCCCssGCSqGSIb3DQEHATAaBggq
+hkiG9w0DAjAOAgIAoAQIn8+kb8zj2JSAggqgxtGA/FLBBRs1wbBPgDCbSG0yCwjJ
+NsFg89/k6xuXo8c5YTwsw8+XlIVq03navpew6XxxzY090rD2OJ0t6HA6GqrIpd8W
+iSh/Atqn0yfLFmkLqgIAPRfzxUxqUocxLpQsLIFp2YNUGE+yps+UZmIjw/WHfdqr
+cWTmSTSvKuy3UkIJZCkGDBpTvqk4BFaHh4oTXEpgpNY+GKxjf9TDN9GQPqQZR7sg
+Qki4t2g4/SaqKl6EoJbpOrMHTQ9LYh2O7+XemEdvXjwpdv0kyffHiaVpBBAtthjT
+bzsu67v0b9h3uDKim13uyT0wx33GEmmmDsJwf/IPH/8eu2Ck5xaafpXGmFqon4uX
+kQtIPaNclFn7/hLxPw2VmBGaC0SYF3U1jyN96EBxdjqy8Aa6ByMXYDW5BcfqniD5
+mYXfw+b81lh1kutxaPaV4YJ9ZlRUW752N7VHo/fG0/fukoe5W9a8kIhgLpygllb/
+GP4oSF4wM6n1/OgRzZj2IWFiobKO4d/tMnh+C+PoEVAuFZcxQwi9GqvsK5OoIjVw
+Nx0XcVSOl1TTYS9SwC7ugMBCab73JiruC24pL78YM+NaIpIQ3On4DokJA2ZHtjBj
+ZIxF4tKA144RvFN6pBd6TVE5XM6KD/Vh9bjSmujtEAfdQ3TedvKJsbZuu0stErbv
+WcRy11I328l557ECU+3eODid62PpuefHp0NTZJGqnYIShBpKRBuyhNxkyjmPfzYc
+KgCQ69fRl3QOqCjobPpMHhVV3li1NrxKGedQcM8XcwpsTsPigp+51o2qgKzBNAqv
+5kGumHOlMKsRfrs7jZCcSaOuEj97pYx08FLEgF23cav39MOQNUEM1dNU+EYslL4o
+3RoSHRjUgPU+2t9c0prS9A/bPBDj/eD8p2kzccB4t1Uyu0s7kJoMwOJ/eNhPY6Eo
+qrED5bCgG97D1Giwt0rlMUozQYH6bw9G5qwP+YflmaGF7yKIBacI5EppxZ7SWHk6
+/VpGu8LDn+PdD9b/hm03lT5p5UEky0DyfQzF3mQ/Eds1WHigamtnrAR6BXyG3e+j
+JlqZnkLLFzx98xicz8kkjr+gRkMyyiS5FnYyvxKzfMtyn2lZ2st9nZGNNgMc9N62
+r5HgNbdDFHuRdKKzV+8kQfuMc3mOPpK1t9TFY+QgrxiB5p6S7VooI97YtP3Pbfkn
+szCEeD3V2G22kdwGnDd0OZGGJlrKt1lusYK4NJphBqLBr8EkMQQbol2a8UnAmuIr
+xKtOVGcMkoXj7ynbjr51BNswzuiFxS2cYU2QSb38Wi8uAYCInuIwaZi+whIslJzA
+bif7CtJpA1BeLOz03fKTKznjAE13/4FDgXumdweENDYPK3kx6QHxjyI06hxRMUK7
+nbi9aWCXmXP3vU7D21dp0XnAMzRQJ565JV3aHRoY7XDa4LePa7PP9ywyafOE5yCW
+7ndqx3J+2JhTDvSFsW8/q3H3iyeFhykuJVS6yugpim58soznxNoixiZkxWvdOVdi
+q1QwppRLv8chjLPNMk8mQvskszPNxTFbyxEJks3EzVGVaQ3wNZDV215D6LgV10+o
+PK/CQkZY2iigAZqUyF44lBFRRThyC+Eyt5c9rKGrkCjhUxIKQDmFhEIFzObgOL8w
+yiEXRLEix1FjqBj0I+esFcCxjqHVFtHtPDSJBmZ5eLnYMKL0by+SYMAa9z0CReIz
+l8JLL6EVIFz8kFxlkGWjr4dnOzhhPOq/mCpp0WxbavDfdhE87MdXJZBnLwoT62QG
+955HlAoEQBOGJbcoHeV0oq2fWNwGwn7ijqqDAbxFBp/sP6TGqpxr56+RWYbgQyq4
+UV6rcULMQP/3axlMbK2Trki/9Pn276O59odWfDcvOozr1WQCPDaXVhzlENc9i3I8
+pKEOVQf/UBczJ0NR9aTEF80dRg2lpXwD0ho4N0AvSiVbgxC7cPZHQwIqvq9LHRUs
+/4n+Vu3SVYU3cAxolUTiCGUSlBfkw+e0iOfkSPjDbZw/a7OBNZpedWKBxlhY91D6
+4g5mNBShMCIKrTFzGN32fSqvHfN24w88cGw1+1sEeym0niVk+NqQs+5DPuM+w6dk
+e66xdPfHauuwGdi1ixu33yZIWJIrNO0WZd+Q4FsJB2K3U/vpCdgnVpcwazrM/obK
+lBNp0r/Nha+WbfxCRXC55onTCqW2pqKA70h2UMDHOrpepU1lj0YMzmotDHSTU3L9
+09VvUMNg9uqfrQ6mSkb9j5Tl8oF2otOw5EzA1YdaKPmgsv62RWLYl80wXcBtHv5o
+Bu+Y6fZToSXVV6nGG0KUvb4sFWlZMB/uvZrv20COII6BLFGF+ju9UXts/nGIXJvV
+Kyvg17khQV0DiJQBcSjFuAdGqXen1POBbGSz6itcTk4TQDYHaOInxAjQTGTiFS9a
+sw0l9RnAXJLsTTnFX05G5fXGawqqRPi1VHk2qWfi+G8BjzrRUGiWjPQIOR3yx5IE
+SN4y9FvpYuflIeHg9urkwp6N+1f0DrJJhJY9ZQ0HTQhziJmIfvbEjNqCl7hEC28+
+F8I5tuViLgfSwcFFCvnS6WFoN4X6QdFdqMCb3ZSNXPiEBgPyLkwzCWArkP7/vARu
+WXllR4nD2Zl30WrfXhStXRigCXn+vk3/Rz7g40qQ8n364n7Kew3N+JZpuxjdfjjd
+2TLc2bp6lvzVEpaOgjuMgpRX8zan/R54ZKqzhvTooX9VHp0HCwlUvkOmdOyncxXi
+P8IA6VF1I9nn762wpsxqmWT5x6pC2kQXPUxhO1VXj6uWtZo1okJyNZ5/tNOwM7B+
+XfOZ0xw+uyVi9v4byTZM2QdsJ+d3YGYLAugTGHISLqQEerD8/gGK+/SL06b2gNed
+XPHtgSl/jHct8BWoT2BWC+sU1aKoTFoMGqnPwz4CwpJTX6/cSTW9KrrzDxodu2FO
+ZJVkM8I30q9jfVlMKhAqQButL22eNefUjf5nrPx3eINo/YWHmFghbJMZWINR29lf
+APe+kEyZbbZWbUV+PqHZdSLJN/rx+SonR8olFZUta5b87dUTgE48rAWVolseVTdD
+Uho8/nDir1dlgIZpev7DCr4i1uUbRDHPwhVRdfo9XaYh0fDPhIIK+cKxophBYxdf
+LI/X7MGpj5/TEcl4th1UAYp3lfhrVlZCKGdnQixQfZkETKDSdRHlrkA4mg+AunKl
+Alx8uUbRXheINRXP+J77XouVB+mNuVg5DXjMx9p5H6V2YFtV0u47/6S4cO/5rEHm
+yI9v+NegVOEXd2Hqw0Jx7a8DkKSGjVfErkxrPwosI2LbTC9wa3zCwheWPaHmr0hM
+GrsivKVY4OfJ7bKbItP2dylwQjyBscJJG0Vza2jjWLzdfRvFHRd+axTriN/SwrP/
+rXxlxObrxJkRe0uAvrLJ4xG9jUj5czg6e1VYaxFX1N3ewWCnGwIroo8O0jBgMIHP
+T2i2hoAQosEk62FUeN8JCA63KIoraFoANfhZgIShpOd/RRxFU4/7xZR5tMdGoYz/
+g0thR0lM+Hi88FtFD4mAh/Oat4Ri8B7bv04aokjN2UHz6nPbHHjZ8zIqpbYTCy04
+3GNZTqo8gdiWwzdHbdcJgP3HoTbQKEclFeZofDIx1hcqXkJTHKmXuiKz6zLYPuMO
+6RLfsTyyPgJi0GsAAAAA
+-----END PKCS7-----
diff --git a/crypto/pkcs7/t/msie-enc-02 b/crypto/pkcs7/t/msie-enc-02
new file mode 100644
index 0000000..7017055
--- /dev/null
+++ b/crypto/pkcs7/t/msie-enc-02
@@ -0,0 +1,90 @@
+
+MIAGCSqGSIb3DQEHA6CAMIACAQAxggHCMIHMAgEAMHYwYjERMA8GA1UEBxMISW50ZXJuZXQxFzAV
+BgNVBAoTDlZlcmlTaWduLCBJbmMuMTQwMgYDVQQLEytWZXJpU2lnbiBDbGFzcyAxIENBIC0gSW5k
+aXZpZHVhbCBTdWJzY3JpYmVyAhBgQJiC3qfbCbjdj5INYLnKMA0GCSqGSIb3DQEBAQUABEACr4tn
+kSzvo3aIlHfJLGbfokNCV6FjdDP1vQhL+kdXONqcFCEf9ReETCvaHslIr/Wepc5j2hjZselzgqLn
+rM1ZMIHwAgEAMIGZMIGSMQswCQYDVQQGEwJBVTETMBEGA1UECBMKUXVlZW5zbGFuZDERMA8GA1UE
+BxMIQnJpc2JhbmUxGjAYBgNVBAoTEUNyeXB0c29mdCBQdHkgTHRkMSIwIAYDVQQLExlERU1PTlNU
+UkFUSU9OIEFORCBURVNUSU5HMRswGQYDVQQDExJERU1PIFpFUk8gVkFMVUUgQ0ECAgRuMA0GCSqG
+SIb3DQEBAQUABEBanBxKOvUoRn3DiFY55lly2TPu2Cv+dI/GLrzW6qvnUMZPWGPGaUlPyWLMZrXJ
+xGXZUiRJKTBwDu91fnodUEK9MIAGCSqGSIb3DQEHATAaBggqhkiG9w0DAjAOAgIAoAQImxKZEDWP
+EuOggASCBACBi1bX/qc3geqFyfRpX7JyIo/g4CDr62GlwvassAGlIO8zJ5Z/UDIIooeV6QS4D4OW
+PymKd0WXhwcJI0yBcJTWEoxND27LM7CWFJpA07AoxVCRHTOPgm794NynLecNUOqVTFyS4CRuLhVG
+PAk0nFZG/RE2yMtx4rAkSiVgOexES7wq/xWuoDSSmuTMNQOTbKfkEKqdFLkM/d62gD2wnaph7vKk
+PPK82wdZP8rF3nUUC5c4ahbNoa8g+5B3tIF/Jz3ZZK3vGLU0IWO+i7W451dna13MglDDjXOeikNl
+XLsQdAVo0nsjfGu+f66besJojPzysNA+IEZl6gNWUetl9lim4SqrxubUExdS2rmXnXXmEuEW/HC7
+dlTAeYq5Clqx5id6slhC2C2oegMww3XH9yxHw6OqzvXY6pVPEScEtBMQLgaKFQT+m2SRtbTVFG7c
+QcnUODyVB1IbpQTF1DHeeOX1W/HfpWZym8dzkti6SCyeumHmqO406xDiIMVKtHOqM86nEHuAMZsr
+cLy+ey6TEJvR6S4N8QRzng8JJDZDTJXQN6q84aEudsnOrw2KyOVwPpI6ey4qBsHUgQ8kAFy5lsQa
+WV45h6exgUwbBcKLgPZGFj+OdD2RKJsTb83/UqbJS5Q/lGXhzBlnaYucyJxEprRxbntmcnOEPFJe
++tRDUwOTd7qlJljdhIJL+uDcooL9Ahgo6Cwep6tduekv2cSEohJeTE8Dvy34YRhMbLvnFNdmnpNy
+rNZDYVVxxaKoyd2AfB8NPFZh1VdAYfI3R1QAQ2kXEef5NNIfVQfMzD9akJn4RP+Kv32Qaxm4FrnK
+xmwRyGJShavIBc2ax+F1r1+NZXuSBHn5vfoRTxOk0ST4dXsw74dnlYUMRaSu4qqUdM9jsXSyeX4Z
+gQgkR2bkaYO6ezFgenFIa7QWVw8rXZAEZ5aibCxbnY1VE41PYIvhlLdbFJhH9gY22s+fFAuwnzyA
+SRjC40A9aAEItRlaPStWSGiqlLRgNkBBwdpv2l2YPBd2QzHx6ek6XGrvRJuAC+Nh62rtQKwpNH54
+YAOHW55maBFW2SQ3TF+cZ6NbbqhCmHTyyR7mcSYc9sXSVDWEhYKQ1iyU870zhHWVpvglZizZetJC
+ZFjYex3b1ngVdcgargOvpPq9urCKKi2mbkqv/EFpzSWGXkKSpfCG/XfMnEOtkNrB8S06vnk2JcJB
+OBqJot+uuSH5hOg0vTpxX2DuONJSiWSWyfRE/lTfJJFXwhod7SXclUyXPeSyibcSic2hVAzDmwjD
+31js/j2k02PI/agPhr3UQ8cMgcNAiaoCKbNaWfn6BGbCAbTchxzUlo2cSJiLlrX2IDZmfXbXmZCo
+m1smWIG+BIIEALiuAxDb6dWLAYyVBoN9hYI4AiPeZAY9MtvQ6AV8o2/EFm6PvYGXy3Hei5830CH0
+PBeX7Kdd6ff1y33TW/l5qSkIL1ULTGR7okFfJePHDmq1dFt6/JOMptiQ8WSu7CsJQvZ9VTFXeYFc
+ZqCPPZc1NrPegNK70Zf9QxWIbDAevJ5KLBf1c6j8pU2/6LnvDY6VjaTvYSgr7vTR8eVzH4Rm77W0
+iOHxg5VcODv6cGSVyuvbX8UAGo8Cmb58ERDtBDJBQXVpWKLNAuDJ9GX8n2zNkpjZLbPSkcmuhqGa
+BJBE/BaCTkUQWlY9dIbRtEnxIU1mfbPPdx1Ppa8DqGDjSOsQdKcKYNNZtayEw++EIpmpdBNsKphC
+fB8UEK2Wkk4ZVW+qyGoi/r0MFsvO1NmSOOZ0o/jy/YHmoeURHhPy97AO3eVTkEAa5CfJEJybmo56
+7CDw/FwoGAUCgsoz7rlxzMudr/IhHIH+APinncxXlHO2ecvHD9i8DaHGA8tVifgsUhqQoZieULut
+eF94O5UAxOkv41UZssYTwN4nYrN1QkesZl3BX4ORS4EE30/PQ23ARf3WZptZrCJevGm2ZYzGeh8x
+g17mCDfiLO+bff4qP/4mC96Pu4ia6j4to5BwKIJS/+DCuoD8WeSKF4pugXQkMUiHdQnNnVP9Sp2O
+/4ly5mO8JzrQC59V2bnTNBqPhpno8kfJvK5TypPSVC+bTzern3rJ6UceB3srcn9zxKx9GdNydJQj
+yWjv8ec3n3d1nuQwhz5Q053NBhIjwoGg3Go7LO6i78ZOlpF7dcoAO13NfHLyNjnyHCaiWtVRTct9
+rLf5vN00urSn8YJngHk1eTKK8nHGIcOg6YdYDOD2nE5XwRijKmieG8Xa3eKRzfbL06GrBQENle6J
+mC131bp3cRVxpjq+o6RAbGoMm4yICsL4eTarCQrsyHmoPHqr91UHo91avyxU7knWmEhX27ybmsrs
+8aeZwPHixL14TeyhruCqRVvkf1Ks7P+z8MPUboGNqQe2WLN8ktCGEr15O8MJR/em86G03Jfo4oaw
+/DVUH5RwLT6acedOGuzMh/2r8BcmemhVQ8/cWvV4YJ0tOW4hzyVHC5hQf8sZ3LzxXLH6Ohnrbprh
+xvrdbaSdChWZDDP0bCCbxEhkwuBkBeKZrMbwRTP+TPTPYLVTH/CmKLzKh/114tkGkyO3hHS4qExU
+V39F2Sj4mylx+hD0+20D9pntpNi7htccGlOm6yNM69at/3+kLgJJyoIlaxLcCUYHNMifDt+T3p/t
+5U4XmD53uUQ6M8dvj/udqPekNSUfse15yrd9pjOt5PcJuqW28q0sFHf9pHIgz3XZFMe5PD7ppw6r
+S+C6Ir4PrYIEggQA7ZDVtiCm+BbtNNB/UJm79/OQ5mp5bTI0kPmDeycaWTa0Ojpum+c/dpG/iJOB
+DICj7jHOXSHT7JlGyX6aSFJUltucAnZvwzhPDmdDaIDiKSk85GqgdDWVfGosSCX9Ph/T3WpIxnwf
+WSDRtIHkWTjly+pe4yy5K6/XISy/L5Zh/fhiI5fjHjgzmlibs2ru4nVw6hBhUvlSSe2BEs5d9h/y
+NH8Wy3qvb2D3jh7hkepFtZJGNTHp8ZUC7Ns2JIpQYObsaxdI65i3mMOu7fRwI+0/4ejsWhP6KCEi
+LgwvLg0qM82ma6YB7qHAHboaczRVEffDcJUG4a5uycB0DoZFn+uEaEFyili20hCn4hVfsqUQk2PT
+8Mo1tSl5e30xI1YJZrRgiJm9nHRX6fLizngP+ILJLPHZsPvlSVIfY+/v/FR8feKOjaGhyGF51BAx
+aM2NIQ4jMP5/X+U5gQybi0E6u7rroDhaHsKmCMgXqszwXWCpedA/sEbeHpiTC59YlPPSlIOMc9vP
+Ko/mQCfWy/9icUaIfKQldvkllUxxNkqu6AbIpHVscbAEzSPs5xbQXU8EZNNCDisFnnpY3nQ3eLnl
+m89saTJxRb7NWHRMlmPv7qgD7uMIq3vdOGA7i5wT9MeoNIgK1/DsgH30s6RWjJy4YyyLmRTXPzbj
+hbQVpEmiMRbEidIvUx2OjKVxVQIcgtLsa2lvHQ4XL1cpLr5GVtOgy0fMg5OCDUUDsvjgjgLQ3P2U
+p2nVY5FM6/QpPc5DTLuuR9ekI2/c9Biz09RtcYDUQK2ajdo8h1IyKqHFoB7h48OXxXKKY94DY0TG
+x6PonB/epj8orAw4QKmm5M0vXYwBOqRymCTHTqOJGObdLx1euFFyqguzHJOU2gAGZI0z9Lg1yRuF
+yhdPZyuniIcmtLNxRZ1duYHErcAyX56qndmLXt7UVkATai/rIMuoJLfAsUnVuTUS5p7tJM754UZT
+7lTcXvDJgOUNnBRaIcxC3pxvbrYDJ2iFJ72xkxUP2p74gucqg25XnCVmQuLg6zDDxF6CLuw9isxy
+Xg4pkneMN//7fpp8GYl9nyZm2yqYYM+jcw0fcVc64L+X4w/gL3H2UMGgxIHSJp7HIG7VKHtXrNyj
+dPXXPVUsMsAAimqOr0Lr2sZWirfuivLaPTqhbkvG5PF7K3gT80AOIcd/6EIHBy2hZ7ukfjHmdP4L
+yQOhTQklaKzGHI0mypq0uFLWJOUlZnVrMiLP1xrWkpC8Ro9eo6mfjjQ45z8adC43a47klwTEzvod
+3rNEFIGJJUEjAN3mbqie7IxoSJknBBJK0D9lZEQ8lZWlq7vuN8JdqPM6xh155jMVsPwjLK6Tzkj5
+BpRD9Tgm3u6HPQSCBADgkWEN75Mu9TGosXY0xm1k6K6sPv8L949CrLWo4r1I2LA072bTGvQP28Vs
+hUA76jgcT1ocC++9PoktIK10YCq5w+FfMAQ04KeCXuAdmiY2iAT4Slea61PMCMta3mVGyLUZCLEm
+P+I0UKR5mlO0fGEcjU9j8TmbjZqxNFqloLsU7oSi7Os0EtYHkdAVrExUyOc/ZDie6fBjdLTmLdCm
+bE9JNwjlbXypdTZupGgLNhKGDIskUAAMwZYayI6YfSIMkNCeAYTnjOuGZZ1msCXGXsfMBR1sfUIj
+9UeGjwD8gq+UVVHX/oeoH/m0eJ5ppqi3+nUlgc9DvpYsC/Fg0G2KuYb9B+VJ+a4GMzQSPREoFtQp
+B9dtLkBb7Ha/hpGWTIdqzW0eAo5llyN8FNvl2Fu2IcLaNmWFO69gLjRKQopp0dvFOuwAVI6fvGDj
+p1WigoNbFZl8N+iiWmzKOjoG2ZLbez1clZCms/JPJrXhEMMOxWpVzkQyN336VWHmGgMcjaKCGSeA
+2nnESIGuiCXMrkHlGfabYIsKcHFCo2t13uXyZPf0zSPTkuD0Eh92wqC9pvA3gvrrCUfo9Mn3bs+e
+KWKmDlpcs8mDn032oIg+zrQhIduMqXVn3evzeVM3B5MBOGMvg51/SXg7R+MC/463juQQEb9IVe/I
+YGnO//oWm9lw/377Af/qH+FnN02obJw1FvesQIs9e5RHNQykKbO+vmVJQl1nd9DZWrHDNO7/80Yz
+2hCm7Tws5nSRN2iFlyRaYJHr7ypxkU2rCak2r6ua7XDwu1qU2RT3+qPjT1RuxQ2oTlHyGkKPMZGC
+Rc+CSWz5aeeCmHZVwdb3nC8YpfsujMiYqygLeuQ82pjKuR7DIKGmnfcOLdv5F+Ek2Wyy0D98iSgk
++aoQGYLhL9llU13pn21uRsDY5uGcXiIw1IETFlTdgENEv8futZuJsegrp7fmFXyNoNyFNyypeDrM
+6ZqR4vKxFjg3tKKeVpkw/W4EAklzMxmNiazGNDBHsnYV3rwPlKa+HeeE2YxnsKwGLCNgRYUXTaJk
+461vS160z3dvh/mLfdZ7MYCkmO3bNE3ELUDAw7YQkSuo9ujzdFKte9LC34sjg9fOex3ThAg5Y50n
+wYm4zBmGM7yEqL8O6QgnM6tIDFS9XryDaLNzcGhMWqMvhzO6sC/AA2WfLgwS517Cp03IkJQWqG9q
+w52+E+GAtpioJfczEhlv9BrhjttdugRSjJrG8SYVYE4zG3Aur5eNBoGaALIOHOtPw8+JovQmIWcF
+oaJ/WQuglFrWtew51IK6F8RiHAOBVavZOuZcO7tV+5enVfreOd0rX8ZOy4hYmHhmF1hOrrWOn+Ee
+E0SYKonXN01BM9xMBIIBSLCvNAppnGPTUGjwbMJRg1VJ2KMiBWH5oJp8tyfIAxMuWFdtaLYbRSOD
+XbOAshPVK8JAY8DQDkzqaCTAkLTfSRAt9yY6SbUpMsRv7xa8nMZNJBJzJT9b/wNjgiOJgaGuJMkV
+2g/DX2jfP3PrMM/Sbnz7edORXHj1Pa5XTT8nG5MS0FuZgvevdq3o/gVVAz+ZCKOH3ShMzZvfp01l
+SX5gaJTflmU6cdNwtn2yZ6IScF7OrjUeA9iEoSVR9dQcA+4lB3RAG3LMwcnxXY35D7+PMJzHIZdF
+cSnq+n03ACY2/E/T31iijRH29rvYHGI+mP/ieYs45iq4fTWo6i1HofeWLdP0fX7xW3XO0/hWYFiw
+BxKu66whAbRhaib3XJNvetVs25ToYXyiDpjG+cd5rCMei8sGQwTBj9Zeh0URoeMW1inTP0JvCmMU
+rZgAAAAAAAAAAAAA
+
diff --git a/crypto/pkcs7/t/msie-enc-02.pem b/crypto/pkcs7/t/msie-enc-02.pem
new file mode 100644
index 0000000..279c5d8
--- /dev/null
+++ b/crypto/pkcs7/t/msie-enc-02.pem
@@ -0,0 +1,106 @@
+-----BEGIN PKCS7-----
+MIAGCSqGSIb3DQEHA6CAMIITQAIBADGCAcIwgcwCAQAwdjBiMREwDwYDVQQHEwhJ
+bnRlcm5ldDEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNDAyBgNVBAsTK1ZlcmlT
+aWduIENsYXNzIDEgQ0EgLSBJbmRpdmlkdWFsIFN1YnNjcmliZXICEGBAmILep9sJ
+uN2Pkg1gucowDQYJKoZIhvcNAQEBBQAEQAKvi2eRLO+jdoiUd8ksZt+iQ0JXoWN0
+M/W9CEv6R1c42pwUIR/1F4RMK9oeyUiv9Z6lzmPaGNmx6XOCoueszVkwgfACAQAw
+gZkwgZIxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpRdWVlbnNsYW5kMREwDwYDVQQH
+EwhCcmlzYmFuZTEaMBgGA1UEChMRQ3J5cHRzb2Z0IFB0eSBMdGQxIjAgBgNVBAsT
+GURFTU9OU1RSQVRJT04gQU5EIFRFU1RJTkcxGzAZBgNVBAMTEkRFTU8gWkVSTyBW
+QUxVRSBDQQICBG4wDQYJKoZIhvcNAQEBBQAEQFqcHEo69ShGfcOIVjnmWXLZM+7Y
+K/50j8YuvNbqq+dQxk9YY8ZpSU/JYsxmtcnEZdlSJEkpMHAO73V+eh1QQr0wghFz
+BgkqhkiG9w0BBwEwGgYIKoZIhvcNAwIwDgICAKAECJsSmRA1jxLjgIIRSIGLVtf+
+pzeB6oXJ9GlfsnIij+DgIOvrYaXC9qywAaUg7zMnln9QMgiih5XpBLgPg5Y/KYp3
+RZeHBwkjTIFwlNYSjE0PbsszsJYUmkDTsCjFUJEdM4+Cbv3g3Kct5w1Q6pVMXJLg
+JG4uFUY8CTScVkb9ETbIy3HisCRKJWA57ERLvCr/Fa6gNJKa5Mw1A5Nsp+QQqp0U
+uQz93raAPbCdqmHu8qQ88rzbB1k/ysXedRQLlzhqFs2hryD7kHe0gX8nPdlkre8Y
+tTQhY76LtbjnV2drXcyCUMONc56KQ2VcuxB0BWjSeyN8a75/rpt6wmiM/PKw0D4g
+RmXqA1ZR62X2WKbhKqvG5tQTF1LauZeddeYS4Rb8cLt2VMB5irkKWrHmJ3qyWELY
+Lah6AzDDdcf3LEfDo6rO9djqlU8RJwS0ExAuBooVBP6bZJG1tNUUbtxBydQ4PJUH
+UhulBMXUMd545fVb8d+lZnKbx3OS2LpILJ66Yeao7jTrEOIgxUq0c6ozzqcQe4Ax
+mytwvL57LpMQm9HpLg3xBHOeDwkkNkNMldA3qrzhoS52yc6vDYrI5XA+kjp7LioG
+wdSBDyQAXLmWxBpZXjmHp7GBTBsFwouA9kYWP450PZEomxNvzf9SpslLlD+UZeHM
+GWdpi5zInESmtHFue2Zyc4Q8Ul761ENTA5N3uqUmWN2Egkv64Nyigv0CGCjoLB6n
+q1256S/ZxISiEl5MTwO/LfhhGExsu+cU12aek3Ks1kNhVXHFoqjJ3YB8Hw08VmHV
+V0Bh8jdHVABDaRcR5/k00h9VB8zMP1qQmfhE/4q/fZBrGbgWucrGbBHIYlKFq8gF
+zZrH4XWvX41le5IEefm9+hFPE6TRJPh1ezDvh2eVhQxFpK7iqpR0z2OxdLJ5fhmB
+CCRHZuRpg7p7MWB6cUhrtBZXDytdkARnlqJsLFudjVUTjU9gi+GUt1sUmEf2Bjba
+z58UC7CfPIBJGMLjQD1oAQi1GVo9K1ZIaKqUtGA2QEHB2m/aXZg8F3ZDMfHp6Tpc
+au9Em4AL42Hrau1ArCk0fnhgA4dbnmZoEVbZJDdMX5xno1tuqEKYdPLJHuZxJhz2
+xdJUNYSFgpDWLJTzvTOEdZWm+CVmLNl60kJkWNh7HdvWeBV1yBquA6+k+r26sIoq
+LaZuSq/8QWnNJYZeQpKl8Ib9d8ycQ62Q2sHxLTq+eTYlwkE4Gomi3665IfmE6DS9
+OnFfYO440lKJZJbJ9ET+VN8kkVfCGh3tJdyVTJc95LKJtxKJzaFUDMObCMPfWOz+
+PaTTY8j9qA+GvdRDxwyBw0CJqgIps1pZ+foEZsIBtNyHHNSWjZxImIuWtfYgNmZ9
+dteZkKibWyZYgb64rgMQ2+nViwGMlQaDfYWCOAIj3mQGPTLb0OgFfKNvxBZuj72B
+l8tx3oufN9Ah9DwXl+ynXen39ct901v5eakpCC9VC0xke6JBXyXjxw5qtXRbevyT
+jKbYkPFkruwrCUL2fVUxV3mBXGagjz2XNTaz3oDSu9GX/UMViGwwHryeSiwX9XOo
+/KVNv+i57w2OlY2k72EoK+700fHlcx+EZu+1tIjh8YOVXDg7+nBklcrr21/FABqP
+Apm+fBEQ7QQyQUF1aViizQLgyfRl/J9szZKY2S2z0pHJroahmgSQRPwWgk5FEFpW
+PXSG0bRJ8SFNZn2zz3cdT6WvA6hg40jrEHSnCmDTWbWshMPvhCKZqXQTbCqYQnwf
+FBCtlpJOGVVvqshqIv69DBbLztTZkjjmdKP48v2B5qHlER4T8vewDt3lU5BAGuQn
+yRCcm5qOeuwg8PxcKBgFAoLKM+65cczLna/yIRyB/gD4p53MV5RztnnLxw/YvA2h
+xgPLVYn4LFIakKGYnlC7rXhfeDuVAMTpL+NVGbLGE8DeJ2KzdUJHrGZdwV+DkUuB
+BN9Pz0NtwEX91mabWawiXrxptmWMxnofMYNe5gg34izvm33+Kj/+Jgvej7uImuo+
+LaOQcCiCUv/gwrqA/FnkiheKboF0JDFIh3UJzZ1T/Uqdjv+JcuZjvCc60AufVdm5
+0zQaj4aZ6PJHybyuU8qT0lQvm083q596yelHHgd7K3J/c8SsfRnTcnSUI8lo7/Hn
+N593dZ7kMIc+UNOdzQYSI8KBoNxqOyzuou/GTpaRe3XKADtdzXxy8jY58hwmolrV
+UU3Lfay3+bzdNLq0p/GCZ4B5NXkyivJxxiHDoOmHWAzg9pxOV8EYoyponhvF2t3i
+kc32y9OhqwUBDZXuiZgtd9W6d3EVcaY6vqOkQGxqDJuMiArC+Hk2qwkK7Mh5qDx6
+q/dVB6PdWr8sVO5J1phIV9u8m5rK7PGnmcDx4sS9eE3soa7gqkVb5H9SrOz/s/DD
+1G6BjakHtlizfJLQhhK9eTvDCUf3pvOhtNyX6OKGsPw1VB+UcC0+mnHnThrszIf9
+q/AXJnpoVUPP3Fr1eGCdLTluIc8lRwuYUH/LGdy88Vyx+joZ626a4cb63W2knQoV
+mQwz9Gwgm8RIZMLgZAXimazG8EUz/kz0z2C1Ux/wpii8yof9deLZBpMjt4R0uKhM
+VFd/Rdko+JspcfoQ9PttA/aZ7aTYu4bXHBpTpusjTOvWrf9/pC4CScqCJWsS3AlG
+BzTInw7fk96f7eVOF5g+d7lEOjPHb4/7naj3pDUlH7Htecq3faYzreT3CbqltvKt
+LBR3/aRyIM912RTHuTw+6acOq0vguiK+D62C7ZDVtiCm+BbtNNB/UJm79/OQ5mp5
+bTI0kPmDeycaWTa0Ojpum+c/dpG/iJOBDICj7jHOXSHT7JlGyX6aSFJUltucAnZv
+wzhPDmdDaIDiKSk85GqgdDWVfGosSCX9Ph/T3WpIxnwfWSDRtIHkWTjly+pe4yy5
+K6/XISy/L5Zh/fhiI5fjHjgzmlibs2ru4nVw6hBhUvlSSe2BEs5d9h/yNH8Wy3qv
+b2D3jh7hkepFtZJGNTHp8ZUC7Ns2JIpQYObsaxdI65i3mMOu7fRwI+0/4ejsWhP6
+KCEiLgwvLg0qM82ma6YB7qHAHboaczRVEffDcJUG4a5uycB0DoZFn+uEaEFyili2
+0hCn4hVfsqUQk2PT8Mo1tSl5e30xI1YJZrRgiJm9nHRX6fLizngP+ILJLPHZsPvl
+SVIfY+/v/FR8feKOjaGhyGF51BAxaM2NIQ4jMP5/X+U5gQybi0E6u7rroDhaHsKm
+CMgXqszwXWCpedA/sEbeHpiTC59YlPPSlIOMc9vPKo/mQCfWy/9icUaIfKQldvkl
+lUxxNkqu6AbIpHVscbAEzSPs5xbQXU8EZNNCDisFnnpY3nQ3eLnlm89saTJxRb7N
+WHRMlmPv7qgD7uMIq3vdOGA7i5wT9MeoNIgK1/DsgH30s6RWjJy4YyyLmRTXPzbj
+hbQVpEmiMRbEidIvUx2OjKVxVQIcgtLsa2lvHQ4XL1cpLr5GVtOgy0fMg5OCDUUD
+svjgjgLQ3P2Up2nVY5FM6/QpPc5DTLuuR9ekI2/c9Biz09RtcYDUQK2ajdo8h1Iy
+KqHFoB7h48OXxXKKY94DY0TGx6PonB/epj8orAw4QKmm5M0vXYwBOqRymCTHTqOJ
+GObdLx1euFFyqguzHJOU2gAGZI0z9Lg1yRuFyhdPZyuniIcmtLNxRZ1duYHErcAy
+X56qndmLXt7UVkATai/rIMuoJLfAsUnVuTUS5p7tJM754UZT7lTcXvDJgOUNnBRa
+IcxC3pxvbrYDJ2iFJ72xkxUP2p74gucqg25XnCVmQuLg6zDDxF6CLuw9isxyXg4p
+kneMN//7fpp8GYl9nyZm2yqYYM+jcw0fcVc64L+X4w/gL3H2UMGgxIHSJp7HIG7V
+KHtXrNyjdPXXPVUsMsAAimqOr0Lr2sZWirfuivLaPTqhbkvG5PF7K3gT80AOIcd/
+6EIHBy2hZ7ukfjHmdP4LyQOhTQklaKzGHI0mypq0uFLWJOUlZnVrMiLP1xrWkpC8
+Ro9eo6mfjjQ45z8adC43a47klwTEzvod3rNEFIGJJUEjAN3mbqie7IxoSJknBBJK
+0D9lZEQ8lZWlq7vuN8JdqPM6xh155jMVsPwjLK6Tzkj5BpRD9Tgm3u6HPeCRYQ3v
+ky71MaixdjTGbWTorqw+/wv3j0KstajivUjYsDTvZtMa9A/bxWyFQDvqOBxPWhwL
+770+iS0grXRgKrnD4V8wBDTgp4Je4B2aJjaIBPhKV5rrU8wIy1reZUbItRkIsSY/
+4jRQpHmaU7R8YRyNT2PxOZuNmrE0WqWguxTuhKLs6zQS1geR0BWsTFTI5z9kOJ7p
+8GN0tOYt0KZsT0k3COVtfKl1Nm6kaAs2EoYMiyRQAAzBlhrIjph9IgyQ0J4BhOeM
+64ZlnWawJcZex8wFHWx9QiP1R4aPAPyCr5RVUdf+h6gf+bR4nmmmqLf6dSWBz0O+
+liwL8WDQbYq5hv0H5Un5rgYzNBI9ESgW1CkH120uQFvsdr+GkZZMh2rNbR4CjmWX
+I3wU2+XYW7Yhwto2ZYU7r2AuNEpCimnR28U67ABUjp+8YOOnVaKCg1sVmXw36KJa
+bMo6OgbZktt7PVyVkKaz8k8mteEQww7FalXORDI3ffpVYeYaAxyNooIZJ4DaecRI
+ga6IJcyuQeUZ9ptgiwpwcUKja3Xe5fJk9/TNI9OS4PQSH3bCoL2m8DeC+usJR+j0
+yfduz54pYqYOWlyzyYOfTfagiD7OtCEh24ypdWfd6/N5UzcHkwE4Yy+DnX9JeDtH
+4wL/jreO5BARv0hV78hgac7/+hab2XD/fvsB/+of4Wc3TahsnDUW96xAiz17lEc1
+DKQps76+ZUlCXWd30NlascM07v/zRjPaEKbtPCzmdJE3aIWXJFpgkevvKnGRTasJ
+qTavq5rtcPC7WpTZFPf6o+NPVG7FDahOUfIaQo8xkYJFz4JJbPlp54KYdlXB1vec
+Lxil+y6MyJirKAt65DzamMq5HsMgoaad9w4t2/kX4STZbLLQP3yJKCT5qhAZguEv
+2WVTXemfbW5GwNjm4ZxeIjDUgRMWVN2AQ0S/x+61m4mx6Cunt+YVfI2g3IU3LKl4
+OszpmpHi8rEWODe0op5WmTD9bgQCSXMzGY2JrMY0MEeydhXevA+Upr4d54TZjGew
+rAYsI2BFhRdNomTjrW9LXrTPd2+H+Yt91nsxgKSY7ds0TcQtQMDDthCRK6j26PN0
+Uq170sLfiyOD1857HdOECDljnSfBibjMGYYzvISovw7pCCczq0gMVL1evINos3Nw
+aExaoy+HM7qwL8ADZZ8uDBLnXsKnTciQlBaob2rDnb4T4YC2mKgl9zMSGW/0GuGO
+2126BFKMmsbxJhVgTjMbcC6vl40GgZoAsg4c60/Dz4mi9CYhZwWhon9ZC6CUWta1
+7DnUgroXxGIcA4FVq9k65lw7u1X7l6dV+t453Stfxk7LiFiYeGYXWE6utY6f4R4T
+RJgqidc3TUEz3EywrzQKaZxj01Bo8GzCUYNVSdijIgVh+aCafLcnyAMTLlhXbWi2
+G0Ujg12zgLIT1SvCQGPA0A5M6mgkwJC030kQLfcmOkm1KTLEb+8WvJzGTSQScyU/
+W/8DY4IjiYGhriTJFdoPw19o3z9z6zDP0m58+3nTkVx49T2uV00/JxuTEtBbmYL3
+r3at6P4FVQM/mQijh90oTM2b36dNZUl+YGiU35ZlOnHTcLZ9smeiEnBezq41HgPY
+hKElUfXUHAPuJQd0QBtyzMHJ8V2N+Q+/jzCcxyGXRXEp6vp9NwAmNvxP099Yoo0R
+9va72BxiPpj/4nmLOOYquH01qOotR6H3li3T9H1+8Vt1ztP4VmBYsAcSruusIQG0
+YWom91yTb3rVbNuU6GF8og6YxvnHeawjHovLBkMEwY/WXodFEaHjFtYp0z9Cbwpj
+FK2YAAAAAA==
+-----END PKCS7-----
diff --git a/crypto/pkcs7/t/msie-s-a-e b/crypto/pkcs7/t/msie-s-a-e
new file mode 100644
index 0000000..0067794
--- /dev/null
+++ b/crypto/pkcs7/t/msie-s-a-e
@@ -0,0 +1,91 @@
+
+MIAGCSqGSIb3DQEHA6CAMIACAQAxggHCMIHMAgEAMHYwYjERMA8GA1UEBxMISW50ZXJuZXQxFzAV
+BgNVBAoTDlZlcmlTaWduLCBJbmMuMTQwMgYDVQQLEytWZXJpU2lnbiBDbGFzcyAxIENBIC0gSW5k
+aXZpZHVhbCBTdWJzY3JpYmVyAhBgQJiC3qfbCbjdj5INYLnKMA0GCSqGSIb3DQEBAQUABECjscaS
+G0U299fqiEAgTqTFQBp8Ai6zzjl557cVb3k6z4QZ7CbqBjSXAjLbh5e7S5Hd/FrFcDnxl1Ka06ha
+VHGPMIHwAgEAMIGZMIGSMQswCQYDVQQGEwJBVTETMBEGA1UECBMKUXVlZW5zbGFuZDERMA8GA1UE
+BxMIQnJpc2JhbmUxGjAYBgNVBAoTEUNyeXB0c29mdCBQdHkgTHRkMSIwIAYDVQQLExlERU1PTlNU
+UkFUSU9OIEFORCBURVNUSU5HMRswGQYDVQQDExJERU1PIFpFUk8gVkFMVUUgQ0ECAgRuMA0GCSqG
+SIb3DQEBAQUABECsyHXZ1xaiv0UQRvOmVYsaF38AL2XX75wxbCsz5/wOg7g3RP4aicZxaR4sBog0
+f2G1o9om/hu+A0rIYF/L4/GUMIAGCSqGSIb3DQEHATAaBggqhkiG9w0DAjAOAgIAoAQIsozQrnwj
+cc2ggASCBAAQz/LPoJe/+iYWeTwSebz6Q9UeKZzQ2UWm7GLtEM3s3c9SCvpmkwIRdEhLjWaBJMyI
+DiL7t1I1vMf9inB8LXgAcIEYkpNScjS8ERA9Ebb7ieNKSBg7w7B8ATHFxLSlDADqRgoZrB1Ctfgf
+ximp3EgxTgnhtyQhZxXW7kBQyFRwumplrJXOp7albP7IothrOKncw30IJT1fwPxWNMItI9juXF0U
+CbWVSjPzGBo4+XNXMvUO6MplOQEz/ywEQ9E8OZAQex1Zw9qq5ppsXB2pMsYV5sLJGikukMYKquiz
+3YK+tN6J8ahLcDUs+VGwqvZi17gpBTlbEP+ZmXJpnO63t1yTEB0V5AZcRKWUOhzlCBM5YUagqNoY
+cpsmSvOK6bYzkUKOrzWpDCAtGZ/Dvul5dTZZmxs2WpM+iyeHXMxO3huy8K1brPTqt1f1sHhuq1jD
+1eXedaCjIgUW9qV18vNAQCof/Yb6T/1fxztf/jD7pPLQJ+7LJkKCAEHGcaizpoKqhYcttaEhLq1G
+O+Ohqf7yFegMdTJ3wwP324w5ZYSU5fLo2Z34/Edf6EGvXyTIqVfAmEBALd6JGVdN5GlYYTxrL+eO
+P80Z4ao4YKoxwEmRp5bmQsQ8B29QhOFKmC6eiG5B96qLMtp7Zmu1grDNxTd6OXShWVwYARD0/B1P
+Sy0PAfk9Gb4fAkO9fZJDQYZ7s0mM5iOPEeSR7820TolOb+KfRabLA9d714jsc2jEykKlpP66Bh4j
+aCsyqJ0uUQcE8SnzrKAqGwgWiCGQpiTa+HBiP6eRlRGOKQj5Y06vcNx6Ija4cGe6+yCN8HV8tCY0
+okZK98NQCl5t79R/ZB2c3NvBJH+/g3ulU48ikT3tVmDxE3mOZofZyGFEM99P+YCMScLDxTl3hzGy
+0YkI8U855P7qOAbcFfh2T5n+LSELwLhbkymEfZT917GWTfmypBWMvJx0WHeDhKwQYPdzbKgWETnc
+yeKasaCW+oLdhBwrd6Ws2r4MA8cwiYXDLbwYmCxJA8VF++8kubF2HJOjSyMBS+QT2PSV/0D9UWoi
+Vfk7R4OvWBJVvq7nV+lXS0O5igjExxlmx1OaBfg7+Cr/MbK4zVNrKSJn82NnKKt6LC6RaTmvFYay
+0sDFxQ7Xo+Th6tDNKmKWJt6Kegfjc+qTWJTKb3kL+UI8vS0zTLy1+M/rZ4ekos/JiS5rYIcAswvg
+58kBgp/0rc6upBeWjBaK5O0aLAeBQfLulo1axWX04OSVKmYeoAltyR6UO9ME3acurQyg7Ta24yqO
+whi/PrIaEiO7dsWvFtzsshVzBLic02NlAkPkMUzliPYnZHWQglDAVxL5K2qhvK1OFCkQpIgBsBDM
+6KYRL/mkBIIEALIl927rIkaN37/BQIcxLcSa05YfC0Hl3mxWESt1A0D4lA37A9S8EbYmDfAYlMc0
+3HhZGdZEtawfpJFyDHzNZceNWBch6nxeNZCY4YFdsbzuGS0RKpwNA9S/czOJ4p9ymBCxuhGepI3U
+PKbC8C749Www1/wMdAot1n+K7M/PBGR8hWmaH5SS7U3yMwAB1fq2NDjx4ur+Um+MclSdN01MDXzG
+EO+eAo1pdAY8479234l8dB2YVAhZ1ZlJ4KmbqMKJrGJXnQUEYS6/cTDRjsUocsoW7uGg1ci2GiHa
+qjlkfpBfie3SdhFW/K8hwAH0HALs56oFN66wUkP/AaJAPfIUNhR6RpHKzZ9zCC42oB2mNawQRMnF
+ETBl1s/SwMxLKRp7jAfKs4NZxSY6I9z/2dTpzS3tsHMjxVDuxkolvRNWBILEMeL1CBvip2HhmoUw
+/Sz5NDgyzk1aQLV6DQNJ2RZLMZDRCtSwZSBu6lhhSgTJGazP0+NbqXXC5aQTrqrFIcWyDXz+ADle
+kszzYM/gSaQTCALTwfDDaU9Ek3xVgW+XBtExtJ3U+0AN3l0j86rUIdIvp6eWdxWQqv9LtpoorKMD
+KfUc5PYV09Z1JgsT4X51Zzq+74l5dz7udIM7UNbdTpmRm9PDj3TUbGCvNR9hqOEGTLbkvb1ZR24a
+h6uGRl2znB25IpDAGRhNRb9is/pO2tvHwHTDMOjrgvZG/pNvXgSUxz0pRjUjXIcqBe2X2gcQfeal
+r8gY76o83WEGL6ODryV9vTQVHt52+izgpYoBZaVlpgqbZl54c+OE0Zxf9RwXwDbcYu5Ku5E0MPL0
+qUjc0y2+Y6E4P5bAWaZGMGT+ORkyVUzcaWmM/+XlO7PER5wrWlCIMZCX1L/nvioY0q0CKqALn7DJ
+QU+qenbwrb6uwS7uNZY6V86s0aDYpU7yRyqxC5SbuyNJb02gdxUCgpIscFaMUjMVRml4M4BIjX/b
+U+HgHoVMUm8SnN9gRcT2izPrgOGVcMTJjfenzoCKoCPo9RjgGMctgB4DvKamErNU7OrilIfuoqzE
+PNSeP9SPw/zkDmNvMebM499We9CVnsHUWqF00/ZJWoua77+0f1bLS/tmci1JBvIcMo/4SJvgH+KF
+o0gijP9gqAPd5iCOnpnJlHUqRIym42SmyKEDuzdSwXKjAR6j7uXda39JyMJr8gGzEsu0jYRkAmj1
+YdiqwKXUcLMkcj1AKeU/PxTUVw0YKsv/rowrPYww3xQUWqNivrXB7GCHE3BzsYNdHsmziaGIXQbA
++EBHdkuKrM8BcC+fxhF/l/KUxngsD1E75IcUv8zFDF+sk4CBYHqks9S4JYlcubuizqsILbdGzIMN
+Z7w34k0XT+sEggQAyzr8MHeIJGsT+AYnZr08PeTbyr01JEoT7lPYT6PzX4F63QKKDl+mB+PwLMzY
+CXrxZcUmuay6/MV8w/f5T6vQXdoSw5puWodBYwVReYh1IaEN+jiTapm9YBVmcIsJPO6abHowknSV
+OWSvST0AtAX57fFOTckm+facfBK9s9T1lUUgF44Bh5e8f9qKqfOV44nqdCOEyUm0Dao497ieN4Eg
+XBLNvOZY9+irMiXjp0lcyFvhrJOczfyCr9EiiaiH1TfSzKGKsf2W84iKn/JH6x2eOo7xjwJ40BQD
+c6S1cUNEuqBhP6by0FioOXYOKVyifpxk84Eb+F/4CNdTJTvCPwsiegdfsX/Q53DvKVtXp9Ycam5J
+TmKRHXK/bMHF4ONv3p/O/kn/BqRx+fbbP2eMX8Z1F/ltHKfp6B+06HljUwQLBJs9XtCfqH5Zgdz9
+gad5WZF5ykFArmHDgeFlgggvbZ7z9vqnjN/TH68TxJzauYQ5vLHQ6wGXik4/4uq7/TqNmhxlQEM4
+zVkwsn203bUmKLyz+yl1zItDpn5zy1uXfGo99rBdUzdbdE9LmEFPMaFsaHd4a8oDaUroD7FgCbeD
+JJVld3ac6F8+3QbExPs48OrgA1kI3/UwXr52ldjiYzTLfAGR9BjqNFTw45FUHuMf8TEM5hcHx56w
+95eKAqraDk28o9k+M2UKpcmrdlWoWzdqVVFeWGpM8x9Y9Nt0lf/4VUQgrXjqTkUCQkJyqTeTeGgH
+rn3QBk2XAgpxZhaJs3InW0BkAlBmK99cMinUiJeFt5a4p5wPeXrVuh6V9m7Mpl9hzpogg++EZqah
+fzzNnDgxOZfW342DX052PdgXo0NnkhCk005LvFt6M2mRn0fLgNVfyUZZoOp8cO5ZWbhXXlrhrgUt
+j2zKPK6Q94Zj4kdXHBGpAkrB8ZQ4EGGODE0Dqusm8WPXzB+9236IMHPU7lFbyjBrFNI7O4jg+qRI
+Ipi+7tX0FsilqEbmjG+OPwhZXrdqUqyF+rjKQuSRq7lOeDB4c6S2dq4OOny01i5HCbbyc9UvSHRm
+hOhGqUlzHyHLo3W7j+26V/MhkDXJ+Tx+qfylv4pbliwTteJJj+CZwzjv29qb6lxYi+38Bw10ERap
+m8UCRFBecVN7xXlcIfyeAl666Vi7EBJZv3EdFNrx1nlLwM65nYya7uj6L7IwJWotIUx8E0XH0/cU
+xS/dG8bxf9L/8652h5gq3LI+wTNGuEX0DMuz7BGQG+NtgabrZ6SsKGthGa7eULTpz0McWTLRU0y/
+/tkckpm5pDnXSFbIMskwwjECz82UZBSPpigdN/Pjg5d+0yWu7s3VJxw4ENWPPpzZ+j7sOXmdvn9P
+O1tQd60EO+3awASCBAAZQvWV3/yJ6FxPttbP+qeURpJoPEZfpN2UYZmd8HqtR0YbaOZ6Rln9nvpd
+K9fylXdw9z2xeCbjDWUttJB4VqZxGJM8eCTC1VDVyAOsQ5n7SY55dMkQbU+o4Z/4J5m8+wz50BBI
+LfruL1eZ6/CF6CdvxVRiJ10sXc0Tn2sVMXqkw7Adp1GYoCI9c6VFSFK74+n+y7LVFQ5HBnbQyKJc
+dvdLOXwZOPaFHC5UNXRmOpcwdPqyXUe+xIsOMYbzdlAnI9eGDNeRDktUa/Rh0CbZCxjmJzoZEYOE
+ZjsYZlEfp1Kb61t8z4m28hGLEg88T1Ihmxa2HeUWes1RpmgIOP+/2Lb3smj/l/fpSu4gabFgyCAV
+H5HdCYMScUv8SVu55+tpeO8ELoHHQUXV4rr084O4budzhgNSOPyLGDl5sfDUXiyusPCxS4JVO/KY
+6V2Qrtg/q2wtmXpEkZnGT+Qi3WDzwt4W81alztnYMP17oGLmxX71KV9OEiMZjI4WaaGt+OOINLtR
+qefioZ1NI2L1s5M0tybwTsyU9WERM+3pUwXIfJVsbMZRlNaO2OogcHbaR4UWvhOj+3CTG1sThiYQ
+MxMnp1Rpqx3nhyzqLO3TRrkYvxnA3cdPBn9EeqpgBMg7X3hCiMV3Fl5cj/WOMhtHYgY7BgeCXo46
+EFVZ4+WroGZ46xGiRDiIblo8bzLd7QCxvukzxy3mUDgsZQ8pds4N28weSUhBk5MAPbfBpRvXUVJx
+MhKqXucQU1Md1qSGLbuuIQuz9pAGp1JFUx/vEkCgm74daSoVWCZuB+1ZE4f48clvrBj51xMNf8CP
+EFE7vySzVb6X2H1i5X3Z+Y3DdIcWw4Y2FClfcJk4Mwq8Cq2GALGFEge9YSEE9YmyuU6OFeU0ICon
+iXAgZ72SM8fBwJPruLFbdsNYKW+oAfmPisXSWMcZmdSbfk0GYv+vKtu3eegSbWw1UsCVtZOh9E5Z
+uQ83l59CBqO9sV/SFU3WrrJ0qNWxrmXu9nJn5Qf5iCRoFGYNHYHkIG5FS6N00GEDZxGkxmro2d++
+Adj5LVHc/b1cYWmrux+jEqI8ZK8cyTB0XMbBA/HYbx9NXazr7znP4/Mlv3pZToEcYt+lgLHAArtU
+AdhybhbLIwNMq0gr6EwtDklBa3ns4Wx/rJU8H7LGs6gV8uqeaSketv+nz+sQhfctxZ1rx+5qzXfy
+FOQVpO23KDQunBi1Bl9k61Di4q9JWcyADBXPHXJzp7mL8Fk7zdvMAEfuED1phdRm6GgDYoYUs4yQ
+IrhSjFlWyk7hT8475xk3BIv++obvWSAv/3+pF6A6U2RXDChVmnG0JnPa9wYYtdzBmLfZKBjX+DjD
+yEMsuhPsCzuN4R6tBIIBWCVRKmKwdkatmpsQBgDw48u0/Arffl5/DRlS9ee+QffFecUitDdCK+kt
+X5L2fGYrL5g6SltncMIeV1ptx4nuSjC/O944q1KYtqvQiPFWJqEXIRMNbbYOC47sjLza0tEFrimN
+wxcrWGSzsy5R9beFQ1aHPcMrDWfCoviNRk2qPtxuKIC5Qk2ZuOmJLjCiLwUGEb0/1Mpzv3MqQa7d
+mRayXg3DZWJPajxNZv6eS357ElMvwGQmqafb2mlQJwWLsg9m9PG7uqEoyrqSc6MiuY+icLEFib9j
+OfRQrx70rTSKUfTr4MtP0aZZAefjCrpVIyTekhFDOk0Nmx057eonlyGgmGpl5/Uo+t1J1Z11Ya/l
+bNbfmebRISJeTVW0I8FhseAZMI1GSwp/ludJxSLYOgyRkh+GX134MexNo7O9F1SxLCfWaSG9Fc3s
+5ify04ua9/t8SGrYZPm/l3MkAAAAAAAAAAAAAA==
+
+
diff --git a/crypto/pkcs7/t/msie-s-a-e.pem b/crypto/pkcs7/t/msie-s-a-e.pem
new file mode 100644
index 0000000..55dbd8f
--- /dev/null
+++ b/crypto/pkcs7/t/msie-s-a-e.pem
@@ -0,0 +1,106 @@
+-----BEGIN PKCS7-----
+MIAGCSqGSIb3DQEHA6CAMIITUAIBADGCAcIwgcwCAQAwdjBiMREwDwYDVQQHEwhJ
+bnRlcm5ldDEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNDAyBgNVBAsTK1ZlcmlT
+aWduIENsYXNzIDEgQ0EgLSBJbmRpdmlkdWFsIFN1YnNjcmliZXICEGBAmILep9sJ
+uN2Pkg1gucowDQYJKoZIhvcNAQEBBQAEQKOxxpIbRTb31+qIQCBOpMVAGnwCLrPO
+OXnntxVveTrPhBnsJuoGNJcCMtuHl7tLkd38WsVwOfGXUprTqFpUcY8wgfACAQAw
+gZkwgZIxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpRdWVlbnNsYW5kMREwDwYDVQQH
+EwhCcmlzYmFuZTEaMBgGA1UEChMRQ3J5cHRzb2Z0IFB0eSBMdGQxIjAgBgNVBAsT
+GURFTU9OU1RSQVRJT04gQU5EIFRFU1RJTkcxGzAZBgNVBAMTEkRFTU8gWkVSTyBW
+QUxVRSBDQQICBG4wDQYJKoZIhvcNAQEBBQAEQKzIddnXFqK/RRBG86ZVixoXfwAv
+ZdfvnDFsKzPn/A6DuDdE/hqJxnFpHiwGiDR/YbWj2ib+G74DSshgX8vj8ZQwghGD
+BgkqhkiG9w0BBwEwGgYIKoZIhvcNAwIwDgICAKAECLKM0K58I3HNgIIRWBDP8s+g
+l7/6JhZ5PBJ5vPpD1R4pnNDZRabsYu0Qzezdz1IK+maTAhF0SEuNZoEkzIgOIvu3
+UjW8x/2KcHwteABwgRiSk1JyNLwRED0RtvuJ40pIGDvDsHwBMcXEtKUMAOpGChms
+HUK1+B/GKancSDFOCeG3JCFnFdbuQFDIVHC6amWslc6ntqVs/sii2Gs4qdzDfQgl
+PV/A/FY0wi0j2O5cXRQJtZVKM/MYGjj5c1cy9Q7oymU5ATP/LARD0Tw5kBB7HVnD
+2qrmmmxcHakyxhXmwskaKS6Qxgqq6LPdgr603onxqEtwNSz5UbCq9mLXuCkFOVsQ
+/5mZcmmc7re3XJMQHRXkBlxEpZQ6HOUIEzlhRqCo2hhymyZK84rptjORQo6vNakM
+IC0Zn8O+6Xl1NlmbGzZakz6LJ4dczE7eG7LwrVus9Oq3V/WweG6rWMPV5d51oKMi
+BRb2pXXy80BAKh/9hvpP/V/HO1/+MPuk8tAn7ssmQoIAQcZxqLOmgqqFhy21oSEu
+rUY746Gp/vIV6Ax1MnfDA/fbjDllhJTl8ujZnfj8R1/oQa9fJMipV8CYQEAt3okZ
+V03kaVhhPGsv544/zRnhqjhgqjHASZGnluZCxDwHb1CE4UqYLp6IbkH3qosy2ntm
+a7WCsM3FN3o5dKFZXBgBEPT8HU9LLQ8B+T0Zvh8CQ719kkNBhnuzSYzmI48R5JHv
+zbROiU5v4p9FpssD13vXiOxzaMTKQqWk/roGHiNoKzKonS5RBwTxKfOsoCobCBaI
+IZCmJNr4cGI/p5GVEY4pCPljTq9w3HoiNrhwZ7r7II3wdXy0JjSiRkr3w1AKXm3v
+1H9kHZzc28Ekf7+De6VTjyKRPe1WYPETeY5mh9nIYUQz30/5gIxJwsPFOXeHMbLR
+iQjxTznk/uo4BtwV+HZPmf4tIQvAuFuTKYR9lP3XsZZN+bKkFYy8nHRYd4OErBBg
+93NsqBYROdzJ4pqxoJb6gt2EHCt3pazavgwDxzCJhcMtvBiYLEkDxUX77yS5sXYc
+k6NLIwFL5BPY9JX/QP1RaiJV+TtHg69YElW+rudX6VdLQ7mKCMTHGWbHU5oF+Dv4
+Kv8xsrjNU2spImfzY2coq3osLpFpOa8VhrLSwMXFDtej5OHq0M0qYpYm3op6B+Nz
+6pNYlMpveQv5Qjy9LTNMvLX4z+tnh6Siz8mJLmtghwCzC+DnyQGCn/Stzq6kF5aM
+Fork7RosB4FB8u6WjVrFZfTg5JUqZh6gCW3JHpQ70wTdpy6tDKDtNrbjKo7CGL8+
+shoSI7t2xa8W3OyyFXMEuJzTY2UCQ+QxTOWI9idkdZCCUMBXEvkraqG8rU4UKRCk
+iAGwEMzophEv+aSyJfdu6yJGjd+/wUCHMS3EmtOWHwtB5d5sVhErdQNA+JQN+wPU
+vBG2Jg3wGJTHNNx4WRnWRLWsH6SRcgx8zWXHjVgXIep8XjWQmOGBXbG87hktESqc
+DQPUv3MzieKfcpgQsboRnqSN1DymwvAu+PVsMNf8DHQKLdZ/iuzPzwRkfIVpmh+U
+ku1N8jMAAdX6tjQ48eLq/lJvjHJUnTdNTA18xhDvngKNaXQGPOO/dt+JfHQdmFQI
+WdWZSeCpm6jCiaxiV50FBGEuv3Ew0Y7FKHLKFu7hoNXIthoh2qo5ZH6QX4nt0nYR
+VvyvIcAB9BwC7OeqBTeusFJD/wGiQD3yFDYUekaRys2fcwguNqAdpjWsEETJxREw
+ZdbP0sDMSykae4wHyrODWcUmOiPc/9nU6c0t7bBzI8VQ7sZKJb0TVgSCxDHi9Qgb
+4qdh4ZqFMP0s+TQ4Ms5NWkC1eg0DSdkWSzGQ0QrUsGUgbupYYUoEyRmsz9PjW6l1
+wuWkE66qxSHFsg18/gA5XpLM82DP4EmkEwgC08Hww2lPRJN8VYFvlwbRMbSd1PtA
+Dd5dI/Oq1CHSL6enlncVkKr/S7aaKKyjAyn1HOT2FdPWdSYLE+F+dWc6vu+JeXc+
+7nSDO1DW3U6ZkZvTw4901GxgrzUfYajhBky25L29WUduGoerhkZds5wduSKQwBkY
+TUW/YrP6Ttrbx8B0wzDo64L2Rv6Tb14ElMc9KUY1I1yHKgXtl9oHEH3mpa/IGO+q
+PN1hBi+jg68lfb00FR7edvos4KWKAWWlZaYKm2ZeeHPjhNGcX/UcF8A23GLuSruR
+NDDy9KlI3NMtvmOhOD+WwFmmRjBk/jkZMlVM3GlpjP/l5TuzxEecK1pQiDGQl9S/
+574qGNKtAiqgC5+wyUFPqnp28K2+rsEu7jWWOlfOrNGg2KVO8kcqsQuUm7sjSW9N
+oHcVAoKSLHBWjFIzFUZpeDOASI1/21Ph4B6FTFJvEpzfYEXE9osz64DhlXDEyY33
+p86AiqAj6PUY4BjHLYAeA7ymphKzVOzq4pSH7qKsxDzUnj/Uj8P85A5jbzHmzOPf
+VnvQlZ7B1FqhdNP2SVqLmu+/tH9Wy0v7ZnItSQbyHDKP+Eib4B/ihaNIIoz/YKgD
+3eYgjp6ZyZR1KkSMpuNkpsihA7s3UsFyowEeo+7l3Wt/ScjCa/IBsxLLtI2EZAJo
+9WHYqsCl1HCzJHI9QCnlPz8U1FcNGCrL/66MKz2MMN8UFFqjYr61wexghxNwc7GD
+XR7Js4mhiF0GwPhAR3ZLiqzPAXAvn8YRf5fylMZ4LA9RO+SHFL/MxQxfrJOAgWB6
+pLPUuCWJXLm7os6rCC23RsyDDWe8N+JNF0/ryzr8MHeIJGsT+AYnZr08PeTbyr01
+JEoT7lPYT6PzX4F63QKKDl+mB+PwLMzYCXrxZcUmuay6/MV8w/f5T6vQXdoSw5pu
+WodBYwVReYh1IaEN+jiTapm9YBVmcIsJPO6abHowknSVOWSvST0AtAX57fFOTckm
++facfBK9s9T1lUUgF44Bh5e8f9qKqfOV44nqdCOEyUm0Dao497ieN4EgXBLNvOZY
+9+irMiXjp0lcyFvhrJOczfyCr9EiiaiH1TfSzKGKsf2W84iKn/JH6x2eOo7xjwJ4
+0BQDc6S1cUNEuqBhP6by0FioOXYOKVyifpxk84Eb+F/4CNdTJTvCPwsiegdfsX/Q
+53DvKVtXp9Ycam5JTmKRHXK/bMHF4ONv3p/O/kn/BqRx+fbbP2eMX8Z1F/ltHKfp
+6B+06HljUwQLBJs9XtCfqH5Zgdz9gad5WZF5ykFArmHDgeFlgggvbZ7z9vqnjN/T
+H68TxJzauYQ5vLHQ6wGXik4/4uq7/TqNmhxlQEM4zVkwsn203bUmKLyz+yl1zItD
+pn5zy1uXfGo99rBdUzdbdE9LmEFPMaFsaHd4a8oDaUroD7FgCbeDJJVld3ac6F8+
+3QbExPs48OrgA1kI3/UwXr52ldjiYzTLfAGR9BjqNFTw45FUHuMf8TEM5hcHx56w
+95eKAqraDk28o9k+M2UKpcmrdlWoWzdqVVFeWGpM8x9Y9Nt0lf/4VUQgrXjqTkUC
+QkJyqTeTeGgHrn3QBk2XAgpxZhaJs3InW0BkAlBmK99cMinUiJeFt5a4p5wPeXrV
+uh6V9m7Mpl9hzpogg++EZqahfzzNnDgxOZfW342DX052PdgXo0NnkhCk005LvFt6
+M2mRn0fLgNVfyUZZoOp8cO5ZWbhXXlrhrgUtj2zKPK6Q94Zj4kdXHBGpAkrB8ZQ4
+EGGODE0Dqusm8WPXzB+9236IMHPU7lFbyjBrFNI7O4jg+qRIIpi+7tX0FsilqEbm
+jG+OPwhZXrdqUqyF+rjKQuSRq7lOeDB4c6S2dq4OOny01i5HCbbyc9UvSHRmhOhG
+qUlzHyHLo3W7j+26V/MhkDXJ+Tx+qfylv4pbliwTteJJj+CZwzjv29qb6lxYi+38
+Bw10ERapm8UCRFBecVN7xXlcIfyeAl666Vi7EBJZv3EdFNrx1nlLwM65nYya7uj6
+L7IwJWotIUx8E0XH0/cUxS/dG8bxf9L/8652h5gq3LI+wTNGuEX0DMuz7BGQG+Nt
+gabrZ6SsKGthGa7eULTpz0McWTLRU0y//tkckpm5pDnXSFbIMskwwjECz82UZBSP
+pigdN/Pjg5d+0yWu7s3VJxw4ENWPPpzZ+j7sOXmdvn9PO1tQd60EO+3awBlC9ZXf
+/InoXE+21s/6p5RGkmg8Rl+k3ZRhmZ3weq1HRhto5npGWf2e+l0r1/KVd3D3PbF4
+JuMNZS20kHhWpnEYkzx4JMLVUNXIA6xDmftJjnl0yRBtT6jhn/gnmbz7DPnQEEgt
++u4vV5nr8IXoJ2/FVGInXSxdzROfaxUxeqTDsB2nUZigIj1zpUVIUrvj6f7LstUV
+DkcGdtDIolx290s5fBk49oUcLlQ1dGY6lzB0+rJdR77Eiw4xhvN2UCcj14YM15EO
+S1Rr9GHQJtkLGOYnOhkRg4RmOxhmUR+nUpvrW3zPibbyEYsSDzxPUiGbFrYd5RZ6
+zVGmaAg4/7/YtveyaP+X9+lK7iBpsWDIIBUfkd0JgxJxS/xJW7nn62l47wQugcdB
+RdXiuvTzg7hu53OGA1I4/IsYOXmx8NReLK6w8LFLglU78pjpXZCu2D+rbC2ZekSR
+mcZP5CLdYPPC3hbzVqXO2dgw/XugYubFfvUpX04SIxmMjhZpoa3444g0u1Gp5+Kh
+nU0jYvWzkzS3JvBOzJT1YREz7elTBch8lWxsxlGU1o7Y6iBwdtpHhRa+E6P7cJMb
+WxOGJhAzEyenVGmrHeeHLOos7dNGuRi/GcDdx08Gf0R6qmAEyDtfeEKIxXcWXlyP
+9Y4yG0diBjsGB4JejjoQVVnj5augZnjrEaJEOIhuWjxvMt3tALG+6TPHLeZQOCxl
+Dyl2zg3bzB5JSEGTkwA9t8GlG9dRUnEyEqpe5xBTUx3WpIYtu64hC7P2kAanUkVT
+H+8SQKCbvh1pKhVYJm4H7VkTh/jxyW+sGPnXEw1/wI8QUTu/JLNVvpfYfWLlfdn5
+jcN0hxbDhjYUKV9wmTgzCrwKrYYAsYUSB71hIQT1ibK5To4V5TQgKieJcCBnvZIz
+x8HAk+u4sVt2w1gpb6gB+Y+KxdJYxxmZ1Jt+TQZi/68q27d56BJtbDVSwJW1k6H0
+Tlm5DzeXn0IGo72xX9IVTdausnSo1bGuZe72cmflB/mIJGgUZg0dgeQgbkVLo3TQ
+YQNnEaTGaujZ374B2PktUdz9vVxhaau7H6MSojxkrxzJMHRcxsED8dhvH01drOvv
+Oc/j8yW/ellOgRxi36WAscACu1QB2HJuFssjA0yrSCvoTC0OSUFreezhbH+slTwf
+ssazqBXy6p5pKR62/6fP6xCF9y3FnWvH7mrNd/IU5BWk7bcoNC6cGLUGX2TrUOLi
+r0lZzIAMFc8dcnOnuYvwWTvN28wAR+4QPWmF1GboaANihhSzjJAiuFKMWVbKTuFP
+zjvnGTcEi/76hu9ZIC//f6kXoDpTZFcMKFWacbQmc9r3Bhi13MGYt9koGNf4OMPI
+Qyy6E+wLO43hHq0lUSpisHZGrZqbEAYA8OPLtPwK335efw0ZUvXnvkH3xXnFIrQ3
+QivpLV+S9nxmKy+YOkpbZ3DCHldabceJ7kowvzveOKtSmLar0IjxViahFyETDW22
+DguO7Iy82tLRBa4pjcMXK1hks7MuUfW3hUNWhz3DKw1nwqL4jUZNqj7cbiiAuUJN
+mbjpiS4woi8FBhG9P9TKc79zKkGu3ZkWsl4Nw2ViT2o8TWb+nkt+exJTL8BkJqmn
+29ppUCcFi7IPZvTxu7qhKMq6knOjIrmPonCxBYm/Yzn0UK8e9K00ilH06+DLT9Gm
+WQHn4wq6VSMk3pIRQzpNDZsdOe3qJ5choJhqZef1KPrdSdWddWGv5WzW35nm0SEi
+Xk1VtCPBYbHgGTCNRksKf5bnScUi2DoMkZIfhl9d+DHsTaOzvRdUsSwn1mkhvRXN
+7OYn8tOLmvf7fEhq2GT5v5dzJAAAAAA=
+-----END PKCS7-----
diff --git a/crypto/pkcs7/t/nav-smime b/crypto/pkcs7/t/nav-smime
new file mode 100644
index 0000000..6ee4b59
--- /dev/null
+++ b/crypto/pkcs7/t/nav-smime
@@ -0,0 +1,157 @@
+From angela@c2.net.au Thu May 14 13:32:27 1998
+X-UIDL: 83c94dd550e54329bf9571b72038b8c8
+Return-Path: angela@c2.net.au
+Received: from cryptsoft.com (play.cryptsoft.com [203.56.44.3]) by pandora.cryptsoft.com (8.8.3/8.7.3) with ESMTP id NAA27838 for <tjh@cryptsoft.com>; Thu, 14 May 1998 13:32:26 +1000 (EST)
+Message-ID: <355A6779.4B63E64C@cryptsoft.com>
+Date: Thu, 14 May 1998 13:39:37 +1000
+From: Angela van Lent <angela@c2.net.au>
+X-Mailer: Mozilla 4.03 [en] (Win95; U)
+MIME-Version: 1.0
+To: tjh@cryptsoft.com
+Subject: signed
+Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg=sha1; boundary="------------ms9A58844C95949ECC78A1C54C"
+Content-Length: 2604
+Status: OR
+
+This is a cryptographically signed message in MIME format.
+
+--------------ms9A58844C95949ECC78A1C54C
+Content-Type: text/plain; charset=us-ascii
+Content-Transfer-Encoding: 7bit
+
+signed body
+
+--------------ms9A58844C95949ECC78A1C54C
+Content-Type: application/x-pkcs7-signature; name="smime.p7s"
+Content-Transfer-Encoding: base64
+Content-Disposition: attachment; filename="smime.p7s"
+Content-Description: S/MIME Cryptographic Signature
+
+MIIGHgYJKoZIhvcNAQcCoIIGDzCCBgsCAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHAaCC
+BGswggJTMIIB/aADAgECAgIEfjANBgkqhkiG9w0BAQQFADCBkjELMAkGA1UEBhMCQVUxEzAR
+BgNVBAgTClF1ZWVuc2xhbmQxETAPBgNVBAcTCEJyaXNiYW5lMRowGAYDVQQKExFDcnlwdHNv
+ZnQgUHR5IEx0ZDEiMCAGA1UECxMZREVNT05TVFJBVElPTiBBTkQgVEVTVElORzEbMBkGA1UE
+AxMSREVNTyBaRVJPIFZBTFVFIENBMB4XDTk4MDUxMzA2MjY1NloXDTAwMDUxMjA2MjY1Nlow
+gaUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpRdWVlbnNsYW5kMREwDwYDVQQHEwhCcmlzYmFu
+ZTEaMBgGA1UEChMRQ3J5cHRzb2Z0IFB0eSBMdGQxEjAQBgNVBAsTCVNNSU1FIDAwMzEZMBcG
+A1UEAxMQQW5nZWxhIHZhbiBMZWVudDEjMCEGCSqGSIb3DQEJARYUYW5nZWxhQGNyeXB0c29m
+dC5jb20wXDANBgkqhkiG9w0BAQEFAANLADBIAkEAuC3+7dAb2LhuO7gt2cTM8vsNjhG5JfDh
+hX1Vl/wVGbKEEj0MA6vWEolvefQlxB+EzwCtR0YZ7eEC/T/4JoCyeQIDAQABoygwJjAkBglg
+hkgBhvhCAQ0EFxYVR2VuZXJhdGVkIHdpdGggU1NMZWF5MA0GCSqGSIb3DQEBBAUAA0EAUnSP
+igs6TMFISTjw8cBtJYb98czgAVkVFjKyJQwYMH8FbDnCyx6NocM555nsyDstaw8fKR11Khds
+syd3ikkrhDCCAhAwggG6AgEDMA0GCSqGSIb3DQEBBAUAMIGSMQswCQYDVQQGEwJBVTETMBEG
+A1UECBMKUXVlZW5zbGFuZDERMA8GA1UEBxMIQnJpc2JhbmUxGjAYBgNVBAoTEUNyeXB0c29m
+dCBQdHkgTHRkMSIwIAYDVQQLExlERU1PTlNUUkFUSU9OIEFORCBURVNUSU5HMRswGQYDVQQD
+ExJERU1PIFpFUk8gVkFMVUUgQ0EwHhcNOTgwMzAzMDc0MTMyWhcNMDgwMjI5MDc0MTMyWjCB
+kjELMAkGA1UEBhMCQVUxEzARBgNVBAgTClF1ZWVuc2xhbmQxETAPBgNVBAcTCEJyaXNiYW5l
+MRowGAYDVQQKExFDcnlwdHNvZnQgUHR5IEx0ZDEiMCAGA1UECxMZREVNT05TVFJBVElPTiBB
+TkQgVEVTVElORzEbMBkGA1UEAxMSREVNTyBaRVJPIFZBTFVFIENBMFwwDQYJKoZIhvcNAQEB
+BQADSwAwSAJBAL+0E2fLej3FSCwe2A2iRnMuC3z12qHIp6Ky1wo2zZcxft7AI+RfkrWrSGtf
+mfzBEuPrLdfulncC5Y1pNcM8RTUCAwEAATANBgkqhkiG9w0BAQQFAANBAGSbLMphL6F5pp3s
+8o0Xyh86FHFdpVOwYx09ELLkuG17V/P9pgIc0Eo/gDMbN+KT3IdgECf8S//pCRA6RrNjcXIx
+ggF7MIIBdwIBATCBmTCBkjELMAkGA1UEBhMCQVUxEzARBgNVBAgTClF1ZWVuc2xhbmQxETAP
+BgNVBAcTCEJyaXNiYW5lMRowGAYDVQQKExFDcnlwdHNvZnQgUHR5IEx0ZDEiMCAGA1UECxMZ
+REVNT05TVFJBVElPTiBBTkQgVEVTVElORzEbMBkGA1UEAxMSREVNTyBaRVJPIFZBTFVFIENB
+AgIEfjAJBgUrDgMCGgUAoHowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAbBgkqhkiG9w0B
+CQ8xDjAMMAoGCCqGSIb3DQMHMBwGCSqGSIb3DQEJBTEPFw05ODA1MTQwMzM5MzdaMCMGCSqG
+SIb3DQEJBDEWBBQstNMnSV26ba8PapQEDhO21yNFrjANBgkqhkiG9w0BAQEFAARAW9Xb9YXv
+BfcNkutgFX9Gr8iXhBVsNtGEVrjrpkQwpKa7jHI8SjAlLhk/4RFwDHf+ISB9Np3Z1WDWnLcA
+9CWR6g==
+--------------ms9A58844C95949ECC78A1C54C--
+
+
+From angela@c2.net.au Thu May 14 13:33:16 1998
+X-UIDL: 8f076c44ff7c5967fd5b00c4588a8731
+Return-Path: angela@c2.net.au
+Received: from cryptsoft.com (play.cryptsoft.com [203.56.44.3]) by pandora.cryptsoft.com (8.8.3/8.7.3) with ESMTP id NAA27847 for <tjh@cryptsoft.com>; Thu, 14 May 1998 13:33:15 +1000 (EST)
+Message-ID: <355A67AB.2AF38806@cryptsoft.com>
+Date: Thu, 14 May 1998 13:40:27 +1000
+From: Angela van Lent <angela@c2.net.au>
+X-Mailer: Mozilla 4.03 [en] (Win95; U)
+MIME-Version: 1.0
+To: tjh@cryptsoft.com
+Subject: signed
+Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg=sha1; boundary="------------msD7863B84BD61E02C407F2F5E"
+Content-Length: 2679
+Status: OR
+
+This is a cryptographically signed message in MIME format.
+
+--------------msD7863B84BD61E02C407F2F5E
+Content-Type: text/plain; charset=us-ascii
+Content-Transfer-Encoding: 7bit
+
+signed body 2
+
+--------------msD7863B84BD61E02C407F2F5E
+Content-Type: application/x-pkcs7-signature; name="smime.p7s"
+Content-Transfer-Encoding: base64
+Content-Disposition: attachment; filename="smime.p7s"
+Content-Description: S/MIME Cryptographic Signature
+
+MIIGVgYJKoZIhvcNAQcCoIIGRzCCBkMCAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHAaCC
+BGswggJTMIIB/aADAgECAgIEfjANBgkqhkiG9w0BAQQFADCBkjELMAkGA1UEBhMCQVUxEzAR
+BgNVBAgTClF1ZWVuc2xhbmQxETAPBgNVBAcTCEJyaXNiYW5lMRowGAYDVQQKExFDcnlwdHNv
+ZnQgUHR5IEx0ZDEiMCAGA1UECxMZREVNT05TVFJBVElPTiBBTkQgVEVTVElORzEbMBkGA1UE
+AxMSREVNTyBaRVJPIFZBTFVFIENBMB4XDTk4MDUxMzA2MjY1NloXDTAwMDUxMjA2MjY1Nlow
+gaUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpRdWVlbnNsYW5kMREwDwYDVQQHEwhCcmlzYmFu
+ZTEaMBgGA1UEChMRQ3J5cHRzb2Z0IFB0eSBMdGQxEjAQBgNVBAsTCVNNSU1FIDAwMzEZMBcG
+A1UEAxMQQW5nZWxhIHZhbiBMZWVudDEjMCEGCSqGSIb3DQEJARYUYW5nZWxhQGNyeXB0c29m
+dC5jb20wXDANBgkqhkiG9w0BAQEFAANLADBIAkEAuC3+7dAb2LhuO7gt2cTM8vsNjhG5JfDh
+hX1Vl/wVGbKEEj0MA6vWEolvefQlxB+EzwCtR0YZ7eEC/T/4JoCyeQIDAQABoygwJjAkBglg
+hkgBhvhCAQ0EFxYVR2VuZXJhdGVkIHdpdGggU1NMZWF5MA0GCSqGSIb3DQEBBAUAA0EAUnSP
+igs6TMFISTjw8cBtJYb98czgAVkVFjKyJQwYMH8FbDnCyx6NocM555nsyDstaw8fKR11Khds
+syd3ikkrhDCCAhAwggG6AgEDMA0GCSqGSIb3DQEBBAUAMIGSMQswCQYDVQQGEwJBVTETMBEG
+A1UECBMKUXVlZW5zbGFuZDERMA8GA1UEBxMIQnJpc2JhbmUxGjAYBgNVBAoTEUNyeXB0c29m
+dCBQdHkgTHRkMSIwIAYDVQQLExlERU1PTlNUUkFUSU9OIEFORCBURVNUSU5HMRswGQYDVQQD
+ExJERU1PIFpFUk8gVkFMVUUgQ0EwHhcNOTgwMzAzMDc0MTMyWhcNMDgwMjI5MDc0MTMyWjCB
+kjELMAkGA1UEBhMCQVUxEzARBgNVBAgTClF1ZWVuc2xhbmQxETAPBgNVBAcTCEJyaXNiYW5l
+MRowGAYDVQQKExFDcnlwdHNvZnQgUHR5IEx0ZDEiMCAGA1UECxMZREVNT05TVFJBVElPTiBB
+TkQgVEVTVElORzEbMBkGA1UEAxMSREVNTyBaRVJPIFZBTFVFIENBMFwwDQYJKoZIhvcNAQEB
+BQADSwAwSAJBAL+0E2fLej3FSCwe2A2iRnMuC3z12qHIp6Ky1wo2zZcxft7AI+RfkrWrSGtf
+mfzBEuPrLdfulncC5Y1pNcM8RTUCAwEAATANBgkqhkiG9w0BAQQFAANBAGSbLMphL6F5pp3s
+8o0Xyh86FHFdpVOwYx09ELLkuG17V/P9pgIc0Eo/gDMbN+KT3IdgECf8S//pCRA6RrNjcXIx
+ggGzMIIBrwIBATCBmTCBkjELMAkGA1UEBhMCQVUxEzARBgNVBAgTClF1ZWVuc2xhbmQxETAP
+BgNVBAcTCEJyaXNiYW5lMRowGAYDVQQKExFDcnlwdHNvZnQgUHR5IEx0ZDEiMCAGA1UECxMZ
+REVNT05TVFJBVElPTiBBTkQgVEVTVElORzEbMBkGA1UEAxMSREVNTyBaRVJPIFZBTFVFIENB
+AgIEfjAJBgUrDgMCGgUAoIGxMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcN
+AQkFMQ8XDTk4MDUxNDAzNDAyN1owIwYJKoZIhvcNAQkEMRYEFOKcV8mNYJnM8rHQajcSEqJN
+rwdDMFIGCSqGSIb3DQEJDzFFMEMwCgYIKoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMAcGBSsO
+AwIHMA0GCCqGSIb3DQMCAgFAMA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABEADPE/N
+coH+zTFuX5YpolupTKxKK8eEjc48TuADuO8bIHHDE/fEYaWunlwDuTlcFJl1ig0idffPB1qC
+Zp8SSVVY
+--------------msD7863B84BD61E02C407F2F5E--
+
+
+From angela@c2.net.au Thu May 14 14:05:32 1998
+X-UIDL: a7d629b4b9acacaee8b39371b860a32a
+Return-Path: angela@c2.net.au
+Received: from cryptsoft.com (play.cryptsoft.com [203.56.44.3]) by pandora.cryptsoft.com (8.8.3/8.7.3) with ESMTP id OAA28033 for <tjh@cryptsoft.com>; Thu, 14 May 1998 14:05:32 +1000 (EST)
+Message-ID: <355A6F3B.AC385981@cryptsoft.com>
+Date: Thu, 14 May 1998 14:12:43 +1000
+From: Angela van Lent <angela@c2.net.au>
+X-Mailer: Mozilla 4.03 [en] (Win95; U)
+MIME-Version: 1.0
+To: tjh@cryptsoft.com
+Subject: encrypted
+Content-Type: application/x-pkcs7-mime; name="smime.p7m"
+Content-Transfer-Encoding: base64
+Content-Disposition: attachment; filename="smime.p7m"
+Content-Description: S/MIME Encrypted Message
+Content-Length: 905
+Status: OR
+
+MIAGCSqGSIb3DQEHA6CAMIACAQAxggHmMIHwAgEAMIGZMIGSMQswCQYDVQQGEwJBVTETMBEG
+A1UECBMKUXVlZW5zbGFuZDERMA8GA1UEBxMIQnJpc2JhbmUxGjAYBgNVBAoTEUNyeXB0c29m
+dCBQdHkgTHRkMSIwIAYDVQQLExlERU1PTlNUUkFUSU9OIEFORCBURVNUSU5HMRswGQYDVQQD
+ExJERU1PIFpFUk8gVkFMVUUgQ0ECAgR+MA0GCSqGSIb3DQEBAQUABEA92N29Yk39RUY2tIVd
+exGT2MFX3J6H8LB8aDRJjw7843ALgJ5zXpM5+f80QkAWwEN2A6Pl3VxiCeKLi435zXVyMIHw
+AgEAMIGZMIGSMQswCQYDVQQGEwJBVTETMBEGA1UECBMKUXVlZW5zbGFuZDERMA8GA1UEBxMI
+QnJpc2JhbmUxGjAYBgNVBAoTEUNyeXB0c29mdCBQdHkgTHRkMSIwIAYDVQQLExlERU1PTlNU
+UkFUSU9OIEFORCBURVNUSU5HMRswGQYDVQQDExJERU1PIFpFUk8gVkFMVUUgQ0ECAgRuMA0G
+CSqGSIb3DQEBAQUABECR9IfyHtvnjFmZ8B2oUCEs1vxMsG0u1kxKE4RMPFyDqDCEARq7zXMg
+nzSUI7Wgv5USSKDqcLRJeW+jvYURv/nJMIAGCSqGSIb3DQEHATAaBggqhkiG9w0DAjAOAgIA
+oAQIrLqrij2ZMpeggAQoibtn6reRZWuWk5Iv5IAhgitr8EYE4w4ySQ7EMB6mTlBoFpccUMWX
+BwQgQn1UoWCvYAlhDzURdbui64Dc0rS2wtj+kE/InS6y25EEEPe4NUKaF8/UlE+lo3LtILQE
+CL3uV8k7m0iqAAAAAAAAAAAAAA==
+
diff --git a/crypto/pkcs7/t/s.pem b/crypto/pkcs7/t/s.pem
new file mode 100644
index 0000000..4fa925b
--- /dev/null
+++ b/crypto/pkcs7/t/s.pem
@@ -0,0 +1,57 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIBOgIBAAJBAK3nI4nuDYe3nDJES5WBc90igEstxWC4/h4YY+/ciYki35U8ets9
+mgaoCNYp/e9BCZHtvK2Y+fYokGJv5+cMTQsCAwEAAQJBAIHpvXvqEcOEoDRRHuIG
+fkcB4jPHcr9KE9TpxabH6xs9beN6OJnkePXAHwaz5MnUgSnbpOKq+cw8miKjXwe/
+zVECIQDVLwncT2lRmXarEYHzb+q/0uaSvKhWKKt3kJasLNTrAwIhANDUc/ghut29
+p3jJYjurzUKuG774/5eLjPLsxPPIZzNZAiA/10hSq41UnGqHLEUIS9m2/EeEZe7b
+bm567dfRU9OnVQIgDo8ROrZXSchEGbaog5J5r/Fle83uO8l93R3GqVxKXZkCIFfk
+IPD5PIYQAyyod3hyKKza7ZP4CGY4oOfZetbkSGGG
+-----END RSA PRIVATE KEY-----
+issuer :/C=AU/SP=Queensland/L=Brisbane/O=Cryptsoft Pty Ltd/OU=DEMONSTRATION AND TESTING/CN=DEMO ZERO VALUE CA
+subject:/C=AU/SP=Queensland/L=Brisbane/O=Cryptsoft Pty Ltd/OU=SMIME 003/CN=Information/Email=info@cryptsoft.com
+serial :047D
+
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1149 (0x47d)
+        Signature Algorithm: md5withRSAEncryption
+        Issuer: C=AU, SP=Queensland, L=Brisbane, O=Cryptsoft Pty Ltd, OU=DEMONSTRATION AND TESTING, CN=DEMO ZERO VALUE CA
+        Validity
+            Not Before: May 13 05:40:58 1998 GMT
+            Not After : May 12 05:40:58 2000 GMT
+        Subject: C=AU, SP=Queensland, L=Brisbane, O=Cryptsoft Pty Ltd, OU=SMIME 003, CN=Information/Email=info@cryptsoft.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Modulus:
+                    00:ad:e7:23:89:ee:0d:87:b7:9c:32:44:4b:95:81:
+                    73:dd:22:80:4b:2d:c5:60:b8:fe:1e:18:63:ef:dc:
+                    89:89:22:df:95:3c:7a:db:3d:9a:06:a8:08:d6:29:
+                    fd:ef:41:09:91:ed:bc:ad:98:f9:f6:28:90:62:6f:
+                    e7:e7:0c:4d:0b
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            Netscape Comment: 
+                Generated with SSLeay
+    Signature Algorithm: md5withRSAEncryption
+        52:15:ea:88:f4:f0:f9:0b:ef:ce:d5:f8:83:40:61:16:5e:55:
+        f9:ce:2d:d1:8b:31:5c:03:c6:2d:10:7c:61:d5:5c:0a:42:97:
+        d1:fd:65:b6:b6:84:a5:39:ec:46:ec:fc:e0:0d:d9:22:da:1b:
+        50:74:ad:92:cb:4e:90:e5:fa:7d
+
+-----BEGIN CERTIFICATE-----
+MIICTDCCAfagAwIBAgICBH0wDQYJKoZIhvcNAQEEBQAwgZIxCzAJBgNVBAYTAkFV
+MRMwEQYDVQQIEwpRdWVlbnNsYW5kMREwDwYDVQQHEwhCcmlzYmFuZTEaMBgGA1UE
+ChMRQ3J5cHRzb2Z0IFB0eSBMdGQxIjAgBgNVBAsTGURFTU9OU1RSQVRJT04gQU5E
+IFRFU1RJTkcxGzAZBgNVBAMTEkRFTU8gWkVSTyBWQUxVRSBDQTAeFw05ODA1MTMw
+NTQwNThaFw0wMDA1MTIwNTQwNThaMIGeMQswCQYDVQQGEwJBVTETMBEGA1UECBMK
+UXVlZW5zbGFuZDERMA8GA1UEBxMIQnJpc2JhbmUxGjAYBgNVBAoTEUNyeXB0c29m
+dCBQdHkgTHRkMRIwEAYDVQQLEwlTTUlNRSAwMDMxFDASBgNVBAMTC0luZm9ybWF0
+aW9uMSEwHwYJKoZIhvcNAQkBFhJpbmZvQGNyeXB0c29mdC5jb20wXDANBgkqhkiG
+9w0BAQEFAANLADBIAkEArecjie4Nh7ecMkRLlYFz3SKASy3FYLj+Hhhj79yJiSLf
+lTx62z2aBqgI1in970EJke28rZj59iiQYm/n5wxNCwIDAQABoygwJjAkBglghkgB
+hvhCAQ0EFxYVR2VuZXJhdGVkIHdpdGggU1NMZWF5MA0GCSqGSIb3DQEBBAUAA0EA
+UhXqiPTw+QvvztX4g0BhFl5V+c4t0YsxXAPGLRB8YdVcCkKX0f1ltraEpTnsRuz8
+4A3ZItobUHStkstOkOX6fQ==
+-----END CERTIFICATE-----
+
diff --git a/crypto/pkcs7/t/server.pem b/crypto/pkcs7/t/server.pem
new file mode 100644
index 0000000..989baf8
--- /dev/null
+++ b/crypto/pkcs7/t/server.pem
@@ -0,0 +1,57 @@
+issuer :/C=AU/SP=Queensland/L=Brisbane/O=Cryptsoft Pty Ltd/OU=DEMONSTRATION AND TESTING/CN=DEMO ZERO VALUE CA
+subject:/C=AU/SP=Queensland/L=Brisbane/O=Cryptsoft Pty Ltd/OU=SMIME 003/CN=Information/Email=info@cryptsoft.com
+serial :047D
+
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1149 (0x47d)
+        Signature Algorithm: md5withRSAEncryption
+        Issuer: C=AU, SP=Queensland, L=Brisbane, O=Cryptsoft Pty Ltd, OU=DEMONSTRATION AND TESTING, CN=DEMO ZERO VALUE CA
+        Validity
+            Not Before: May 13 05:40:58 1998 GMT
+            Not After : May 12 05:40:58 2000 GMT
+        Subject: C=AU, SP=Queensland, L=Brisbane, O=Cryptsoft Pty Ltd, OU=SMIME 003, CN=Information/Email=info@cryptsoft.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Modulus:
+                    00:ad:e7:23:89:ee:0d:87:b7:9c:32:44:4b:95:81:
+                    73:dd:22:80:4b:2d:c5:60:b8:fe:1e:18:63:ef:dc:
+                    89:89:22:df:95:3c:7a:db:3d:9a:06:a8:08:d6:29:
+                    fd:ef:41:09:91:ed:bc:ad:98:f9:f6:28:90:62:6f:
+                    e7:e7:0c:4d:0b
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            Netscape Comment: 
+                Generated with SSLeay
+    Signature Algorithm: md5withRSAEncryption
+        52:15:ea:88:f4:f0:f9:0b:ef:ce:d5:f8:83:40:61:16:5e:55:
+        f9:ce:2d:d1:8b:31:5c:03:c6:2d:10:7c:61:d5:5c:0a:42:97:
+        d1:fd:65:b6:b6:84:a5:39:ec:46:ec:fc:e0:0d:d9:22:da:1b:
+        50:74:ad:92:cb:4e:90:e5:fa:7d
+
+-----BEGIN CERTIFICATE-----
+MIICTDCCAfagAwIBAgICBH0wDQYJKoZIhvcNAQEEBQAwgZIxCzAJBgNVBAYTAkFV
+MRMwEQYDVQQIEwpRdWVlbnNsYW5kMREwDwYDVQQHEwhCcmlzYmFuZTEaMBgGA1UE
+ChMRQ3J5cHRzb2Z0IFB0eSBMdGQxIjAgBgNVBAsTGURFTU9OU1RSQVRJT04gQU5E
+IFRFU1RJTkcxGzAZBgNVBAMTEkRFTU8gWkVSTyBWQUxVRSBDQTAeFw05ODA1MTMw
+NTQwNThaFw0wMDA1MTIwNTQwNThaMIGeMQswCQYDVQQGEwJBVTETMBEGA1UECBMK
+UXVlZW5zbGFuZDERMA8GA1UEBxMIQnJpc2JhbmUxGjAYBgNVBAoTEUNyeXB0c29m
+dCBQdHkgTHRkMRIwEAYDVQQLEwlTTUlNRSAwMDMxFDASBgNVBAMTC0luZm9ybWF0
+aW9uMSEwHwYJKoZIhvcNAQkBFhJpbmZvQGNyeXB0c29mdC5jb20wXDANBgkqhkiG
+9w0BAQEFAANLADBIAkEArecjie4Nh7ecMkRLlYFz3SKASy3FYLj+Hhhj79yJiSLf
+lTx62z2aBqgI1in970EJke28rZj59iiQYm/n5wxNCwIDAQABoygwJjAkBglghkgB
+hvhCAQ0EFxYVR2VuZXJhdGVkIHdpdGggU1NMZWF5MA0GCSqGSIb3DQEBBAUAA0EA
+UhXqiPTw+QvvztX4g0BhFl5V+c4t0YsxXAPGLRB8YdVcCkKX0f1ltraEpTnsRuz8
+4A3ZItobUHStkstOkOX6fQ==
+-----END CERTIFICATE-----
+
+-----BEGIN RSA PRIVATE KEY-----
+MIIBOgIBAAJBAK3nI4nuDYe3nDJES5WBc90igEstxWC4/h4YY+/ciYki35U8ets9
+mgaoCNYp/e9BCZHtvK2Y+fYokGJv5+cMTQsCAwEAAQJBAIHpvXvqEcOEoDRRHuIG
+fkcB4jPHcr9KE9TpxabH6xs9beN6OJnkePXAHwaz5MnUgSnbpOKq+cw8miKjXwe/
+zVECIQDVLwncT2lRmXarEYHzb+q/0uaSvKhWKKt3kJasLNTrAwIhANDUc/ghut29
+p3jJYjurzUKuG774/5eLjPLsxPPIZzNZAiA/10hSq41UnGqHLEUIS9m2/EeEZe7b
+bm567dfRU9OnVQIgDo8ROrZXSchEGbaog5J5r/Fle83uO8l93R3GqVxKXZkCIFfk
+IPD5PIYQAyyod3hyKKza7ZP4CGY4oOfZetbkSGGG
+-----END RSA PRIVATE KEY-----
diff --git a/crypto/pkcs7/t/z b/crypto/pkcs7/t/z
new file mode 100644
index 0000000..a5145e8
--- /dev/null
+++ b/crypto/pkcs7/t/z
@@ -0,0 +1 @@
+DQpzaWduZWQgYm9keQ0KDQo=

diff --git a/crypto/pkcs7/t/zz b/crypto/pkcs7/t/zz
new file mode 100644
index 0000000..aabbbb3
--- /dev/null
+++ b/crypto/pkcs7/t/zz
@@ -0,0 +1,16 @@
+-----BEGIN PKCS7-----
+MIAGCSqGSIb3DQEHA6CAMIICeQIBADGCAeYwgfACAQAwgZkwgZIxCzAJBgNVBAYT
+AkFVMRMwEQYDVQQIEwpRdWVlbnNsYW5kMREwDwYDVQQHEwhCcmlzYmFuZTEaMBgG
+A1UEChMRQ3J5cHRzb2Z0IFB0eSBMdGQxIjAgBgNVBAsTGURFTU9OU1RSQVRJT04g
+QU5EIFRFU1RJTkcxGzAZBgNVBAMTEkRFTU8gWkVSTyBWQUxVRSBDQQICBH4wDQYJ
+KoZIhvcNAQEBBQAEQD3Y3b1iTf1FRja0hV17EZPYwVfcnofwsHxoNEmPDvzjcAuA
+nnNekzn5/zRCQBbAQ3YDo+XdXGIJ4ouLjfnNdXIwgfACAQAwgZkwgZIxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIEwpRdWVlbnNsYW5kMREwDwYDVQQHEwhCcmlzYmFuZTEa
+MBgGA1UEChMRQ3J5cHRzb2Z0IFB0eSBMdGQxIjAgBgNVBAsTGURFTU9OU1RSQVRJ
+T04gQU5EIFRFU1RJTkcxGzAZBgNVBAMTEkRFTU8gWkVSTyBWQUxVRSBDQQICBG4w
+DQYJKoZIhvcNAQEBBQAEQJH0h/Ie2+eMWZnwHahQISzW/EywbS7WTEoThEw8XIOo
+MIQBGrvNcyCfNJQjtaC/lRJIoOpwtEl5b6O9hRG/+ckwgYkGCSqGSIb3DQEHATAa
+BggqhkiG9w0DAjAOAgIAoAQIrLqrij2ZMpeAYIm7Z+q3kWVrlpOSL+SAIYIra/BG
+BOMOMkkOxDAepk5QaBaXHFDFlwdCfVShYK9gCWEPNRF1u6LrgNzStLbC2P6QT8id
+LrLbkfe4NUKaF8/UlE+lo3LtILS97lfJO5tIqgAAAAA=
+-----END PKCS7-----
diff --git a/crypto/pkcs7/verify.c b/crypto/pkcs7/verify.c
index 0e1c1b2..7e0f6e5 100644
--- a/crypto/pkcs7/verify.c
+++ b/crypto/pkcs7/verify.c
@@ -64,6 +64,7 @@
 int verify_callback(int ok, X509_STORE_CTX *ctx);
 
 BIO *bio_err=NULL;
+BIO *bio_out=NULL;
 
 main(argc,argv)
 int argc;
@@ -84,6 +85,7 @@
 	STACK *sk;
 
 	bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
+	bio_out=BIO_new_fp(stdout,BIO_NOCLOSE);
 	EVP_add_digest(EVP_md2());
 	EVP_add_digest(EVP_md5());
 	EVP_add_digest(EVP_sha1());
@@ -131,10 +133,10 @@
 	X509_STORE_load_locations(cert_store,NULL,"../../certs");
 	X509_STORE_set_verify_cb_func(cert_store,verify_callback);
 
-	ERR_clear_errors();
+	ERR_clear_error();
 
 	/* We need to process the data */
-	if (PKCS7_get_detached(p7))
+	if ((PKCS7_get_detached(p7) || detached))
 		{
 		if (detached == NULL)
 			{
@@ -168,10 +170,27 @@
 	/* Ok, first we need to, for each subject entry, see if we can verify */
 	for (i=0; i<sk_num(sk); i++)
 		{
+		ASN1_UTCTIME *tm;
+		char *str1,*str2;
+
 		si=(PKCS7_SIGNER_INFO *)sk_value(sk,i);
 		i=PKCS7_dataVerify(cert_store,&cert_ctx,p7bio,p7,si);
 		if (i <= 0)
 			goto err;
+		printf("signer info\n");
+		if ((tm=get_signed_time(si)) != NULL)
+			{
+			BIO_printf(bio_out,"Signed time:");
+			ASN1_UTCTIME_print(bio_out,tm);
+			ASN1_UTCTIME_free(tm);
+			BIO_printf(bio_out,"\n");
+			}
+		if (get_signed_seq2string(si,&str1,&str2))
+			{
+			BIO_printf(bio_out,"String 1 is %s\n",str1);
+			BIO_printf(bio_out,"String 2 is %s\n",str2);
+			}
+			
 		}
 
 	X509_STORE_free(cert_store);
diff --git a/crypto/rand/Makefile.ssl b/crypto/rand/Makefile.ssl
index d04f0a9..ef693ae 100644
--- a/crypto/rand/Makefile.ssl
+++ b/crypto/rand/Makefile.ssl
@@ -20,8 +20,8 @@
 APPS=
 
 LIB=$(TOP)/libcrypto.a
-LIBSRC=md_rand.c randfile.c
-LIBOBJ=md_rand.o randfile.o
+LIBSRC=md_rand.c randfile.c rand_lib.c
+LIBOBJ=md_rand.o randfile.o rand_lib.o
 
 SRC= $(LIBSRC)
 
diff --git a/crypto/rand/md_rand.c b/crypto/rand/md_rand.c
index f44b36a..35defde 100644
--- a/crypto/rand/md_rand.c
+++ b/crypto/rand/md_rand.c
@@ -88,6 +88,7 @@
 #define MD_Init(a)		MD5_Init(a)
 #define MD_Update(a,b,c)	MD5_Update(a,b,c)
 #define	MD_Final(a,b)		MD5_Final(a,b)
+#define	MD(a,b,c)		MD5(a,b,c)
 #elif defined(USE_SHA1_RAND)
 #include "sha.h"
 #define MD_DIGEST_LENGTH	SHA_DIGEST_LENGTH
@@ -95,6 +96,7 @@
 #define MD_Init(a)		SHA1_Init(a)
 #define MD_Update(a,b,c)	SHA1_Update(a,b,c)
 #define	MD_Final(a,b)		SHA1_Final(a,b)
+#define	MD(a,b,c)		SHA1(a,b,c)
 #elif defined(USE_MDC2_RAND)
 #include "mdc2.h"
 #define MD_DIGEST_LENGTH	MDC2_DIGEST_LENGTH
@@ -102,6 +104,7 @@
 #define MD_Init(a)		MDC2_Init(a)
 #define MD_Update(a,b,c)	MDC2_Update(a,b,c)
 #define	MD_Final(a,b)		MDC2_Final(a,b)
+#define	MD(a,b,c)		MDC2(a,b,c)
 #elif defined(USE_MD2_RAND)
 #include "md2.h"
 #define MD_DIGEST_LENGTH	MD2_DIGEST_LENGTH
@@ -109,31 +112,48 @@
 #define MD_Init(a)		MD2_Init(a)
 #define MD_Update(a,b,c)	MD2_Update(a,b,c)
 #define	MD_Final(a,b)		MD2_Final(a,b)
+#define	MD(a,b,c)		MD2(a,b,c)
 #endif
 
 #include "rand.h"
 
-/*#define NORAND	1 */
-/*#define PREDICT	1 */
+/* #define NORAND	1 */
+/* #define PREDICT	1 */
 
 #define STATE_SIZE	1023
 static int state_num=0,state_index=0;
 static unsigned char state[STATE_SIZE+MD_DIGEST_LENGTH];
 static unsigned char md[MD_DIGEST_LENGTH];
-static int md_count=0;
+static long md_count[2]={0,0};
 
-char *RAND_version="RAND part of SSLeay 0.9.0b 29-Jun-1998";
+char *RAND_version="RAND part of SSLeay 0.9.1a 06-Jul-1998";
 
-void RAND_cleanup()
+static void ssleay_rand_cleanup(void);
+static void ssleay_rand_seed(unsigned char *buf, int num);
+static void ssleay_rand_bytes(unsigned char *buf, int num);
+
+RAND_METHOD rand_ssleay={
+	ssleay_rand_seed,
+	ssleay_rand_bytes,
+	ssleay_rand_cleanup,
+	}; 
+
+RAND_METHOD *RAND_SSLeay()
+	{
+	return(&rand_ssleay);
+	}
+
+static void ssleay_rand_cleanup()
 	{
 	memset(state,0,sizeof(state));
 	state_num=0;
 	state_index=0;
 	memset(md,0,MD_DIGEST_LENGTH);
-	md_count=0;
+	md_count[0]=0;
+	md_count[1]=0;
 	}
 
-void RAND_seed(buf,num)
+static void ssleay_rand_seed(buf,num)
 unsigned char *buf;
 int num;
 	{
@@ -178,7 +198,9 @@
 			MD_Update(&m,&(state[st_idx]),j);
 			
 		MD_Update(&m,buf,j);
+		MD_Update(&m,(unsigned char *)&(md_count[0]),sizeof(md_count));
 		MD_Final(md,&m);
+		md_count[1]++;
 
 		buf+=j;
 
@@ -195,7 +217,7 @@
 	memset((char *)&m,0,sizeof(m));
 	}
 
-void RAND_bytes(buf,num)
+static void ssleay_rand_bytes(buf,num)
 unsigned char *buf;
 int num;
 	{
@@ -277,6 +299,7 @@
 		num-=j;
 		MD_Init(&m);
 		MD_Update(&m,&(md[MD_DIGEST_LENGTH/2]),MD_DIGEST_LENGTH/2);
+		MD_Update(&m,(unsigned char *)&(md_count[0]),sizeof(md_count));
 #ifndef PURIFY
 		MD_Update(&m,buf,j); /* purify complains */
 #endif
@@ -300,7 +323,8 @@
 		}
 
 	MD_Init(&m);
-	MD_Update(&m,(unsigned char *)&md_count,sizeof(md_count)); md_count++;
+	MD_Update(&m,(unsigned char *)&(md_count[0]),sizeof(md_count));
+	md_count[0]++;
 	MD_Update(&m,md,MD_DIGEST_LENGTH);
 	MD_Final(md,&m);
 	memset(&m,0,sizeof(m));
@@ -385,7 +409,7 @@
 	GetBitmapBits(hBitmap, size, bmbits);
 
 	/* Get the MD5 of the bitmap */
-	MD5(bmbits,size,md);
+	MD(bmbits,size,md);
 
 	/* Seed the random generator with the MD5 digest */
 	RAND_seed(md, MD_DIGEST_LENGTH);
diff --git a/crypto/rand/rand.h b/crypto/rand/rand.h
index 477d7a1..f5edcb9 100644
--- a/crypto/rand/rand.h
+++ b/crypto/rand/rand.h
@@ -63,7 +63,23 @@
 extern "C" {
 #endif
 
+typedef struct rand_meth_st
+	{
 #ifndef NOPROTO
+	void (*seed)(unsigned char *buf, int num);
+	void (*bytes)(unsigned char *buf, int num);
+	void (*cleanup)(void);
+#else
+	void (*seed)();
+	void (*bytes)();
+	void (*cleanup)();
+#endif
+	} RAND_METHOD;
+
+#ifndef NOPROTO
+void RAND_set_rand_method(RAND_METHOD *meth);
+RAND_METHOD *RAND_get_rand_method(void );
+RAND_METHOD *RAND_SSLeay(void);
 void RAND_cleanup(void );
 void RAND_bytes( unsigned char *buf,int num);
 void RAND_seed( unsigned char *buf,int num);
@@ -74,6 +90,9 @@
 void RAND_screen(void);
 #endif
 #else
+void RAND_set_rand_method();
+RAND_METHOD *RAND_get_rand_method();
+RAND_METHOD *RAND_SSLeay();
 void RAND_cleanup();
 void RAND_bytes();
 void RAND_seed();
diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c
new file mode 100644
index 0000000..c4b44e5
--- /dev/null
+++ b/crypto/rand/rand_lib.c
@@ -0,0 +1,104 @@
+/* crypto/rand/rand_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 "cryptlib.h"
+#include <sys/types.h>
+#include <time.h>
+#include "rand.h"
+
+#ifdef NO_RAND
+static RAND_METHOD *rand_meth=NULL;
+#else
+extern RAND_METHOD rand_ssleay;
+static RAND_METHOD *rand_meth= &rand_ssleay;
+#endif
+
+void RAND_set_rand_method(meth)
+RAND_METHOD *meth;
+	{
+	rand_meth=meth;
+	}
+
+RAND_METHOD *RAND_get_rand_method()
+	{
+	return(rand_meth);
+	}
+
+void RAND_cleanup()
+	{
+	if (rand_meth != NULL)
+		rand_meth->cleanup();
+	}
+
+void RAND_seed(buf,num)
+unsigned char *buf;
+int num;
+	{
+	if (rand_meth != NULL)
+		rand_meth->seed(buf,num);
+	}
+
+void RAND_bytes(buf,num)
+unsigned char *buf;
+int num;
+	{
+	if (rand_meth != NULL)
+		rand_meth->bytes(buf,num);
+	}
+
diff --git a/crypto/rand/randfile.c b/crypto/rand/randfile.c
index f2b3746..4b38b2b 100644
--- a/crypto/rand/randfile.c
+++ b/crypto/rand/randfile.c
@@ -58,6 +58,7 @@
 
 #include <stdio.h>
 #include "cryptlib.h"
+#include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include "rand.h"
@@ -86,7 +87,7 @@
 	if (i < 0) return(0);
 	if (bytes <= 0) return(ret);
 
-	in=fopen(file,"r");
+	in=fopen(file,"br");
 	if (in == NULL) goto err;
 	for (;;)
 		{
diff --git a/crypto/rc2/rc2_ecb.c b/crypto/rc2/rc2_ecb.c
index 96239cd..5022982 100644
--- a/crypto/rc2/rc2_ecb.c
+++ b/crypto/rc2/rc2_ecb.c
@@ -59,7 +59,7 @@
 #include "rc2.h"
 #include "rc2_locl.h"
 
-char *RC2_version="RC2 part of SSLeay 0.9.0b 29-Jun-1998";
+char *RC2_version="RC2 part of SSLeay 0.9.1a 06-Jul-1998";
 
 /* RC2 as implemented frm a posting from
  * Newsgroups: sci.crypt
diff --git a/crypto/rc2/rc2speed.c b/crypto/rc2/rc2speed.c
index 6cd8ea8..d02f9d8 100644
--- a/crypto/rc2/rc2speed.c
+++ b/crypto/rc2/rc2speed.c
@@ -92,7 +92,8 @@
 #include <sys/timeb.h>
 #endif
 
-#ifdef sun
+#if defined(sun) || defined(__ultrix)
+#define _POSIX_SOURCE
 #include <limits.h>
 #include <sys/param.h>
 #endif
diff --git a/crypto/rc2/tab.c b/crypto/rc2/tab.c
new file mode 100644
index 0000000..25dc14e
--- /dev/null
+++ b/crypto/rc2/tab.c
@@ -0,0 +1,86 @@
+#include <stdio.h>
+
+unsigned char ebits_to_num[256]={
+	0xbd,0x56,0xea,0xf2,0xa2,0xf1,0xac,0x2a,
+	0xb0,0x93,0xd1,0x9c,0x1b,0x33,0xfd,0xd0,
+	0x30,0x04,0xb6,0xdc,0x7d,0xdf,0x32,0x4b,
+	0xf7,0xcb,0x45,0x9b,0x31,0xbb,0x21,0x5a,
+	0x41,0x9f,0xe1,0xd9,0x4a,0x4d,0x9e,0xda,
+	0xa0,0x68,0x2c,0xc3,0x27,0x5f,0x80,0x36,
+	0x3e,0xee,0xfb,0x95,0x1a,0xfe,0xce,0xa8,
+	0x34,0xa9,0x13,0xf0,0xa6,0x3f,0xd8,0x0c,
+	0x78,0x24,0xaf,0x23,0x52,0xc1,0x67,0x17,
+	0xf5,0x66,0x90,0xe7,0xe8,0x07,0xb8,0x60,
+	0x48,0xe6,0x1e,0x53,0xf3,0x92,0xa4,0x72,
+	0x8c,0x08,0x15,0x6e,0x86,0x00,0x84,0xfa,
+	0xf4,0x7f,0x8a,0x42,0x19,0xf6,0xdb,0xcd,
+	0x14,0x8d,0x50,0x12,0xba,0x3c,0x06,0x4e,
+	0xec,0xb3,0x35,0x11,0xa1,0x88,0x8e,0x2b,
+	0x94,0x99,0xb7,0x71,0x74,0xd3,0xe4,0xbf,
+	0x3a,0xde,0x96,0x0e,0xbc,0x0a,0xed,0x77,
+	0xfc,0x37,0x6b,0x03,0x79,0x89,0x62,0xc6,
+	0xd7,0xc0,0xd2,0x7c,0x6a,0x8b,0x22,0xa3,
+	0x5b,0x05,0x5d,0x02,0x75,0xd5,0x61,0xe3,
+	0x18,0x8f,0x55,0x51,0xad,0x1f,0x0b,0x5e,
+	0x85,0xe5,0xc2,0x57,0x63,0xca,0x3d,0x6c,
+	0xb4,0xc5,0xcc,0x70,0xb2,0x91,0x59,0x0d,
+	0x47,0x20,0xc8,0x4f,0x58,0xe0,0x01,0xe2,
+	0x16,0x38,0xc4,0x6f,0x3b,0x0f,0x65,0x46,
+	0xbe,0x7e,0x2d,0x7b,0x82,0xf9,0x40,0xb5,
+	0x1d,0x73,0xf8,0xeb,0x26,0xc7,0x87,0x97,
+	0x25,0x54,0xb1,0x28,0xaa,0x98,0x9d,0xa5,
+	0x64,0x6d,0x7a,0xd4,0x10,0x81,0x44,0xef,
+	0x49,0xd6,0xae,0x2e,0xdd,0x76,0x5c,0x2f,
+	0xa7,0x1c,0xc9,0x09,0x69,0x9a,0x83,0xcf,
+	0x29,0x39,0xb9,0xe9,0x4c,0xff,0x43,0xab,
+	};
+
+unsigned char num_to_ebits[256]={
+	0x5d,0xbe,0x9b,0x8b,0x11,0x99,0x6e,0x4d,
+	0x59,0xf3,0x85,0xa6,0x3f,0xb7,0x83,0xc5,
+	0xe4,0x73,0x6b,0x3a,0x68,0x5a,0xc0,0x47,
+	0xa0,0x64,0x34,0x0c,0xf1,0xd0,0x52,0xa5,
+	0xb9,0x1e,0x96,0x43,0x41,0xd8,0xd4,0x2c,
+	0xdb,0xf8,0x07,0x77,0x2a,0xca,0xeb,0xef,
+	0x10,0x1c,0x16,0x0d,0x38,0x72,0x2f,0x89,
+	0xc1,0xf9,0x80,0xc4,0x6d,0xae,0x30,0x3d,
+	0xce,0x20,0x63,0xfe,0xe6,0x1a,0xc7,0xb8,
+	0x50,0xe8,0x24,0x17,0xfc,0x25,0x6f,0xbb,
+	0x6a,0xa3,0x44,0x53,0xd9,0xa2,0x01,0xab,
+	0xbc,0xb6,0x1f,0x98,0xee,0x9a,0xa7,0x2d,
+	0x4f,0x9e,0x8e,0xac,0xe0,0xc6,0x49,0x46,
+	0x29,0xf4,0x94,0x8a,0xaf,0xe1,0x5b,0xc3,
+	0xb3,0x7b,0x57,0xd1,0x7c,0x9c,0xed,0x87,
+	0x40,0x8c,0xe2,0xcb,0x93,0x14,0xc9,0x61,
+	0x2e,0xe5,0xcc,0xf6,0x5e,0xa8,0x5c,0xd6,
+	0x75,0x8d,0x62,0x95,0x58,0x69,0x76,0xa1,
+	0x4a,0xb5,0x55,0x09,0x78,0x33,0x82,0xd7,
+	0xdd,0x79,0xf5,0x1b,0x0b,0xde,0x26,0x21,
+	0x28,0x74,0x04,0x97,0x56,0xdf,0x3c,0xf0,
+	0x37,0x39,0xdc,0xff,0x06,0xa4,0xea,0x42,
+	0x08,0xda,0xb4,0x71,0xb0,0xcf,0x12,0x7a,
+	0x4e,0xfa,0x6c,0x1d,0x84,0x00,0xc8,0x7f,
+	0x91,0x45,0xaa,0x2b,0xc2,0xb1,0x8f,0xd5,
+	0xba,0xf2,0xad,0x19,0xb2,0x67,0x36,0xf7,
+	0x0f,0x0a,0x92,0x7d,0xe3,0x9d,0xe9,0x90,
+	0x3e,0x23,0x27,0x66,0x13,0xec,0x81,0x15,
+	0xbd,0x22,0xbf,0x9f,0x7e,0xa9,0x51,0x4b,
+	0x4c,0xfb,0x02,0xd3,0x70,0x86,0x31,0xe7,
+	0x3b,0x05,0x03,0x54,0x60,0x48,0x65,0x18,
+	0xd2,0xcd,0x5f,0x32,0x88,0x0e,0x35,0xfd,
+	};
+	
+main()
+	{
+	int i,j;
+
+	for (i=0; i<256; i++)
+		{
+		for (j=0; j<256; j++)
+			if (ebits_to_num[j] == i)
+				{
+				printf("0x%02x,",j);
+				break;
+				}
+		}
+	}
diff --git a/crypto/rc4/Makefile.ssl b/crypto/rc4/Makefile.ssl
index 19c1e98..f5f38a4 100644
--- a/crypto/rc4/Makefile.ssl
+++ b/crypto/rc4/Makefile.ssl
@@ -63,7 +63,7 @@
 
 # bsdi
 asm/rx86bsdi.o: asm/rx86unix.cpp
-	$(CPP) -DBSDI asm/rx86unix.cpp | as -o asm/rx86bsdi.o
+	$(CPP) -DBSDI asm/rx86unix.cpp | sed 's/ :/:/' | as -o asm/rx86bsdi.o
 
 asm/rx86unix.cpp:
 	(cd asm; perl rc4-586.pl cpp >rx86unix.cpp)
diff --git a/crypto/rc4/rc4_enc.c b/crypto/rc4/rc4_enc.c
index ab8a111..26da6d5 100644
--- a/crypto/rc4/rc4_enc.c
+++ b/crypto/rc4/rc4_enc.c
@@ -95,7 +95,6 @@
 #define RC4_LOOP(a,b,i)	LOOP(a[i],b[i])
 #endif
 
-	i= -(int)len;
 	i=(int)(len>>3L);
 	if (i)
 		{
diff --git a/crypto/rc4/rc4_skey.c b/crypto/rc4/rc4_skey.c
index 0be5fde..03e69e1 100644
--- a/crypto/rc4/rc4_skey.c
+++ b/crypto/rc4/rc4_skey.c
@@ -59,7 +59,7 @@
 #include "rc4.h"
 #include "rc4_locl.h"
 
-char *RC4_version="RC4 part of SSLeay 0.9.0b 29-Jun-1998";
+char *RC4_version="RC4 part of SSLeay 0.9.1a 06-Jul-1998";
 
 char *RC4_options()
 	{
diff --git a/crypto/rc4/rc4speed.c b/crypto/rc4/rc4speed.c
index 5298dad..f796f7b 100644
--- a/crypto/rc4/rc4speed.c
+++ b/crypto/rc4/rc4speed.c
@@ -92,7 +92,8 @@
 #include <sys/timeb.h>
 #endif
 
-#ifdef sun
+#if defined(sun) || defined(__ultrix)
+#define _POSIX_SOURCE
 #include <limits.h>
 #include <sys/param.h>
 #endif
diff --git a/crypto/rc5/Makefile.ssl b/crypto/rc5/Makefile.ssl
index 5e98ee2..f7379b0 100644
--- a/crypto/rc5/Makefile.ssl
+++ b/crypto/rc5/Makefile.ssl
@@ -61,7 +61,7 @@
 
 # bsdi
 asm/r586bsdi.o: asm/r586unix.cpp
-	$(CPP) -DBSDI asm/r586unix.cpp | as -o asm/r586bsdi.o
+	$(CPP) -DBSDI asm/r586unix.cpp | sed 's/ :/:/' | as -o asm/r586bsdi.o
 
 asm/r586unix.cpp:
 	(cd asm; perl rc5-586.pl cpp >r586unix.cpp)
@@ -72,7 +72,7 @@
 links:
 	/bin/rm -f Makefile
 	$(TOP)/util/point.sh Makefile.ssl Makefile ;
-	$(TOP)/util/point.sh ../../doc/rc5.doc rc5.doc ;
+	# $(TOP)/util/point.sh ../../doc/rc5.doc rc5.doc ;
 	$(TOP)/util/mklink.sh ../../include $(EXHEADER)
 	$(TOP)/util/mklink.sh ../../test $(TEST)
 	$(TOP)/util/mklink.sh ../../apps $(APPS)
diff --git a/crypto/rc5/rc5_ecb.c b/crypto/rc5/rc5_ecb.c
index 82947f4..ab971a9 100644
--- a/crypto/rc5/rc5_ecb.c
+++ b/crypto/rc5/rc5_ecb.c
@@ -59,7 +59,7 @@
 #include "rc5.h"
 #include "rc5_locl.h"
 
-char *RC5_version="RC5 part of SSLeay 0.9.0b 29-Jun-1998";
+char *RC5_version="RC5 part of SSLeay 0.9.1a 06-Jul-1998";
 
 void RC5_32_ecb_encrypt(in, out, ks, encrypt)
 unsigned char *in;
diff --git a/crypto/rc5/rc5speed.c b/crypto/rc5/rc5speed.c
index 5eeb560..29148dc 100644
--- a/crypto/rc5/rc5speed.c
+++ b/crypto/rc5/rc5speed.c
@@ -92,7 +92,8 @@
 #include <sys/timeb.h>
 #endif
 
-#ifdef sun
+#if defined(sun) || defined(__ultrix)
+#define _POSIX_SOURCE
 #include <limits.h>
 #include <sys/param.h>
 #endif
diff --git a/crypto/ripemd/Makefile.ssl b/crypto/ripemd/Makefile.ssl
index 67d47ce..e865cdb 100644
--- a/crypto/ripemd/Makefile.ssl
+++ b/crypto/ripemd/Makefile.ssl
@@ -59,7 +59,7 @@
 
 # bsdi
 asm/rm86bsdi.o: asm/rm86unix.cpp
-	$(CPP) -DBSDI asm/rm86unix.cpp | as -o asm/rm86bsdi.o
+	$(CPP) -DBSDI asm/rm86unix.cpp | sed 's/ :/:/' | as -o asm/rm86bsdi.o
 
 asm/rm86unix.cpp:
 	(cd asm; perl rmd-586.pl cpp >rm86unix.cpp)
diff --git a/crypto/ripemd/rmd_dgst.c b/crypto/ripemd/rmd_dgst.c
index 210de19..904a45b 100644
--- a/crypto/ripemd/rmd_dgst.c
+++ b/crypto/ripemd/rmd_dgst.c
@@ -59,7 +59,7 @@
 #include <stdio.h>
 #include "rmd_locl.h"
 
-char *RMD160_version="RIPEMD160 part of SSLeay 0.9.0b 29-Jun-1998";
+char *RMD160_version="RIPEMD160 part of SSLeay 0.9.1a 06-Jul-1998";
 
 #ifndef NOPROTO
 #  ifdef RMD160_ASM
@@ -73,7 +73,7 @@
      void ripemd160_block_x86();
 #    define ripemd160_block ripemd160_block_x86
 #  else
-     static void ripemd160_block();
+     void ripemd160_block();
 #  endif
 #endif
 
diff --git a/crypto/rsa/f b/crypto/rsa/f
new file mode 100644
index 0000000..57528ef
--- /dev/null
+++ b/crypto/rsa/f
@@ -0,0 +1,6 @@
+	if ((rsa->method_mod_n == NULL) && (rsa->flags & RSA_FLAG_CACHE_PUBLIC))
+		{
+		if ((rsa->method_mod_n=(char *)BN_MONT_CTX_new()) != NULL)
+			if (!BN_MONT_CTX_set((BN_MONT_CTX *)rsa->method_mod_n,
+				rsa->n,ctx)) goto err;
+		}
diff --git a/crypto/rsa/rsa.err b/crypto/rsa/rsa.err
index 5ded1b5..e866635 100644
--- a/crypto/rsa/rsa.err
+++ b/crypto/rsa/rsa.err
@@ -1,26 +1,27 @@
 /* Error codes for the RSA functions. */
 
 /* Function codes. */
-#define RSA_F_RSA_EAY_PRIVATE_DECRYPT			 100
-#define RSA_F_RSA_EAY_PRIVATE_ENCRYPT			 101
-#define RSA_F_RSA_EAY_PUBLIC_DECRYPT			 102
-#define RSA_F_RSA_EAY_PUBLIC_ENCRYPT			 103
-#define RSA_F_RSA_GENERATE_KEY				 104
-#define RSA_F_RSA_NEW_METHOD				 105
-#define RSA_F_RSA_PADDING_ADD_NONE			 106
-#define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1		 107
-#define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2		 108
-#define RSA_F_RSA_PADDING_ADD_SSLV23			 109
-#define RSA_F_RSA_PADDING_CHECK_NONE			 110
-#define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1		 111
-#define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2		 112
-#define RSA_F_RSA_PADDING_CHECK_SSLV23			 113
-#define RSA_F_RSA_PRINT					 114
-#define RSA_F_RSA_PRINT_FP				 115
-#define RSA_F_RSA_SIGN					 116
-#define RSA_F_RSA_SIGN_ASN1_OCTET_STRING		 117
-#define RSA_F_RSA_VERIFY				 118
-#define RSA_F_RSA_VERIFY_ASN1_OCTET_STRING		 119
+#define RSA_F_MEMORY_LOCK				 100
+#define RSA_F_RSA_EAY_PRIVATE_DECRYPT			 101
+#define RSA_F_RSA_EAY_PRIVATE_ENCRYPT			 102
+#define RSA_F_RSA_EAY_PUBLIC_DECRYPT			 103
+#define RSA_F_RSA_EAY_PUBLIC_ENCRYPT			 104
+#define RSA_F_RSA_GENERATE_KEY				 105
+#define RSA_F_RSA_NEW_METHOD				 106
+#define RSA_F_RSA_PADDING_ADD_NONE			 107
+#define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1		 108
+#define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2		 109
+#define RSA_F_RSA_PADDING_ADD_SSLV23			 110
+#define RSA_F_RSA_PADDING_CHECK_NONE			 111
+#define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1		 112
+#define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2		 113
+#define RSA_F_RSA_PADDING_CHECK_SSLV23			 114
+#define RSA_F_RSA_PRINT					 115
+#define RSA_F_RSA_PRINT_FP				 116
+#define RSA_F_RSA_SIGN					 117
+#define RSA_F_RSA_SIGN_ASN1_OCTET_STRING		 118
+#define RSA_F_RSA_VERIFY				 119
+#define RSA_F_RSA_VERIFY_ASN1_OCTET_STRING		 120
 
 /* Reason codes. */
 #define RSA_R_ALGORITHM_MISMATCH			 100
diff --git a/crypto/rsa/rsa.h b/crypto/rsa/rsa.h
index aeb78ff..b7c02fd 100644
--- a/crypto/rsa/rsa.h
+++ b/crypto/rsa/rsa.h
@@ -102,11 +102,14 @@
 	int references;
 	int flags;
 
-	/* Normally used to cached montgomery values */
+	/* Normally used to cache montgomery values */
 	char *method_mod_n;
 	char *method_mod_p;
 	char *method_mod_q;
 
+	/* all BIGNUM values are actually in the following data, if it is not
+	 * NULL */
+	char *bignum_data;
 	BN_BLINDING *blinding;
 	} RSA;
 
@@ -114,6 +117,7 @@
 #define RSA_F4	0x10001L
 
 #define RSA_METHOD_FLAG_NO_CHECK	0x01 /* don't check pub/private match */
+
 #define RSA_FLAG_CACHE_PUBLIC		0x02
 #define RSA_FLAG_CACHE_PRIVATE		0x04
 #define RSA_FLAG_BLINDING		0x08
@@ -147,6 +151,9 @@
 
 void RSA_set_default_method(RSA_METHOD *meth);
 
+/* This function needs the memory locking malloc callbacks to be installed */
+int RSA_memory_lock(RSA *r);
+
 /* If you have RSAref compiled in. */
 RSA_METHOD *RSA_PKCS1_RSAref(void);
 
@@ -193,19 +200,19 @@
 int RSA_padding_add_PKCS1_type_1(unsigned char *to,int tlen,
 	unsigned char *f,int fl);
 int RSA_padding_check_PKCS1_type_1(unsigned char *to,int tlen,
-	unsigned char *f,int fl);
+	unsigned char *f,int fl,int rsa_len);
 int RSA_padding_add_PKCS1_type_2(unsigned char *to,int tlen,
 	unsigned char *f,int fl);
 int RSA_padding_check_PKCS1_type_2(unsigned char *to,int tlen,
-	unsigned char *f,int fl);
+	unsigned char *f,int fl,int rsa_len);
 int RSA_padding_add_SSLv23(unsigned char *to,int tlen,
 	unsigned char *f,int fl);
 int RSA_padding_check_SSLv23(unsigned char *to,int tlen,
-	unsigned char *f,int fl);
+	unsigned char *f,int fl,int rsa_len);
 int RSA_padding_add_none(unsigned char *to,int tlen,
 	unsigned char *f,int fl);
 int RSA_padding_check_none(unsigned char *to,int tlen,
-	unsigned char *f,int fl);
+	unsigned char *f,int fl,int rsa_len);
 
 int RSA_get_ex_new_index(long argl, char *argp, int (*new_func)(),
 	int (*dup_func)(), void (*free_func)());
@@ -227,6 +234,7 @@
 int	RSA_flags();
 
 void RSA_set_default_method();
+int RSA_memory_lock();
 
 /* RSA_METHOD *RSA_PKCS1_RSAref(); */
 RSA_METHOD *RSA_PKCS1_SSLeay();
@@ -274,26 +282,27 @@
 /* Error codes for the RSA functions. */
 
 /* Function codes. */
-#define RSA_F_RSA_EAY_PRIVATE_DECRYPT			 100
-#define RSA_F_RSA_EAY_PRIVATE_ENCRYPT			 101
-#define RSA_F_RSA_EAY_PUBLIC_DECRYPT			 102
-#define RSA_F_RSA_EAY_PUBLIC_ENCRYPT			 103
-#define RSA_F_RSA_GENERATE_KEY				 104
-#define RSA_F_RSA_NEW_METHOD				 105
-#define RSA_F_RSA_PADDING_ADD_NONE			 106
-#define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1		 107
-#define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2		 108
-#define RSA_F_RSA_PADDING_ADD_SSLV23			 109
-#define RSA_F_RSA_PADDING_CHECK_NONE			 110
-#define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1		 111
-#define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2		 112
-#define RSA_F_RSA_PADDING_CHECK_SSLV23			 113
-#define RSA_F_RSA_PRINT					 114
-#define RSA_F_RSA_PRINT_FP				 115
-#define RSA_F_RSA_SIGN					 116
-#define RSA_F_RSA_SIGN_ASN1_OCTET_STRING		 117
-#define RSA_F_RSA_VERIFY				 118
-#define RSA_F_RSA_VERIFY_ASN1_OCTET_STRING		 119
+#define RSA_F_MEMORY_LOCK				 100
+#define RSA_F_RSA_EAY_PRIVATE_DECRYPT			 101
+#define RSA_F_RSA_EAY_PRIVATE_ENCRYPT			 102
+#define RSA_F_RSA_EAY_PUBLIC_DECRYPT			 103
+#define RSA_F_RSA_EAY_PUBLIC_ENCRYPT			 104
+#define RSA_F_RSA_GENERATE_KEY				 105
+#define RSA_F_RSA_NEW_METHOD				 106
+#define RSA_F_RSA_PADDING_ADD_NONE			 107
+#define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1		 108
+#define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2		 109
+#define RSA_F_RSA_PADDING_ADD_SSLV23			 110
+#define RSA_F_RSA_PADDING_CHECK_NONE			 111
+#define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1		 112
+#define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2		 113
+#define RSA_F_RSA_PADDING_CHECK_SSLV23			 114
+#define RSA_F_RSA_PRINT					 115
+#define RSA_F_RSA_PRINT_FP				 116
+#define RSA_F_RSA_SIGN					 117
+#define RSA_F_RSA_SIGN_ASN1_OCTET_STRING		 118
+#define RSA_F_RSA_VERIFY				 119
+#define RSA_F_RSA_VERIFY_ASN1_OCTET_STRING		 120
 
 /* Reason codes. */
 #define RSA_R_ALGORITHM_MISMATCH			 100
diff --git a/crypto/rsa/rsa_eay.c b/crypto/rsa/rsa_eay.c
index 00f8ea9..7623189 100644
--- a/crypto/rsa/rsa_eay.c
+++ b/crypto/rsa/rsa_eay.c
@@ -110,11 +110,13 @@
 RSA *rsa;
 int padding;
 	{
-	BIGNUM *f=NULL,*ret=NULL;
+	BIGNUM f,ret;
 	int i,j,k,num=0,r= -1;
 	unsigned char *buf=NULL;
 	BN_CTX *ctx=NULL;
 
+	BN_init(&f);
+	BN_init(&ret);
 	if ((ctx=BN_CTX_new()) == NULL) goto err;
 	num=BN_num_bytes(rsa->n);
 	if ((buf=(unsigned char *)Malloc(num)) == NULL)
@@ -140,9 +142,7 @@
 		}
 	if (i <= 0) goto err;
 
-	if (((f=BN_new()) == NULL) || ((ret=BN_new()) == NULL)) goto err;
-
-	if (BN_bin2bn(buf,num,f) == NULL) goto err;
+	if (BN_bin2bn(buf,num,&f) == NULL) goto err;
 	
 	if ((rsa->method_mod_n == NULL) && (rsa->flags & RSA_FLAG_CACHE_PUBLIC))
 		{
@@ -151,21 +151,21 @@
 				rsa->n,ctx)) goto err;
 		}
 
-	if (!rsa->meth->bn_mod_exp(ret,f,rsa->e,rsa->n,ctx,
+	if (!rsa->meth->bn_mod_exp(&ret,&f,rsa->e,rsa->n,ctx,
 		rsa->method_mod_n)) goto err;
 
 	/* put in leading 0 bytes if the number is less than the
 	 * length of the modulus */
-	j=BN_num_bytes(ret);
-	i=BN_bn2bin(ret,&(to[num-j]));
+	j=BN_num_bytes(&ret);
+	i=BN_bn2bin(&ret,&(to[num-j]));
 	for (k=0; k<(num-i); k++)
 		to[k]=0;
 
 	r=num;
 err:
 	if (ctx != NULL) BN_CTX_free(ctx);
-	if (f != NULL) BN_free(f);
-	if (ret != NULL) BN_free(ret);
+	BN_clear_free(&f);
+	BN_clear_free(&ret);
 	if (buf != NULL) 
 		{
 		memset(buf,0,num);
@@ -181,11 +181,14 @@
 RSA *rsa;
 int padding;
 	{
-	BIGNUM *f=NULL,*ret=NULL;
+	BIGNUM f,ret;
 	int i,j,k,num=0,r= -1;
 	unsigned char *buf=NULL;
 	BN_CTX *ctx=NULL;
 
+	BN_init(&f);
+	BN_init(&ret);
+
 	if ((ctx=BN_CTX_new()) == NULL) goto err;
 	num=BN_num_bytes(rsa->n);
 	if ((buf=(unsigned char *)Malloc(num)) == NULL)
@@ -209,40 +212,39 @@
 		}
 	if (i <= 0) goto err;
 
-	if (((f=BN_new()) == NULL) || ((ret=BN_new()) == NULL)) goto err;
-	if (BN_bin2bn(buf,num,f) == NULL) goto err;
+	if (BN_bin2bn(buf,num,&f) == NULL) goto err;
 
 	if ((rsa->flags & RSA_FLAG_BLINDING) && (rsa->blinding == NULL))
 		RSA_blinding_on(rsa,ctx);
 	if (rsa->flags & RSA_FLAG_BLINDING)
-		if (!BN_BLINDING_convert(f,rsa->blinding,ctx)) goto err;
+		if (!BN_BLINDING_convert(&f,rsa->blinding,ctx)) goto err;
 
 	if (	(rsa->p != NULL) &&
 		(rsa->q != NULL) &&
 		(rsa->dmp1 != NULL) &&
 		(rsa->dmq1 != NULL) &&
 		(rsa->iqmp != NULL))
-		{ if (!rsa->meth->rsa_mod_exp(ret,f,rsa)) goto err; }
+		{ if (!rsa->meth->rsa_mod_exp(&ret,&f,rsa)) goto err; }
 	else
 		{
-		if (!rsa->meth->bn_mod_exp(ret,f,rsa->d,rsa->n,ctx)) goto err;
+		if (!rsa->meth->bn_mod_exp(&ret,&f,rsa->d,rsa->n,ctx,NULL)) goto err;
 		}
 
 	if (rsa->flags & RSA_FLAG_BLINDING)
-		if (!BN_BLINDING_invert(ret,rsa->blinding,ctx)) goto err;
+		if (!BN_BLINDING_invert(&ret,rsa->blinding,ctx)) goto err;
 
 	/* put in leading 0 bytes if the number is less than the
 	 * length of the modulus */
-	j=BN_num_bytes(ret);
-	i=BN_bn2bin(ret,&(to[num-j]));
+	j=BN_num_bytes(&ret);
+	i=BN_bn2bin(&ret,&(to[num-j]));
 	for (k=0; k<(num-i); k++)
 		to[k]=0;
 
 	r=num;
 err:
 	if (ctx != NULL) BN_CTX_free(ctx);
-	if (ret != NULL) BN_free(ret);
-	if (f != NULL) BN_free(f);
+	BN_clear_free(&ret);
+	BN_clear_free(&f);
 	if (buf != NULL)
 		{
 		memset(buf,0,num);
@@ -258,12 +260,14 @@
 RSA *rsa;
 int padding;
 	{
-	BIGNUM *f=NULL,*ret=NULL;
+	BIGNUM f,ret;
 	int j,num=0,r= -1;
 	unsigned char *p;
 	unsigned char *buf=NULL;
 	BN_CTX *ctx=NULL;
 
+	BN_init(&f);
+	BN_init(&ret);
 	ctx=BN_CTX_new();
 	if (ctx == NULL) goto err;
 
@@ -284,13 +288,12 @@
 		}
 
 	/* make data into a big number */
-	if (((ret=BN_new()) == NULL) || ((f=BN_new()) == NULL)) goto err;
-	if (BN_bin2bn(from,(int)flen,f) == NULL) goto err;
+	if (BN_bin2bn(from,(int)flen,&f) == NULL) goto err;
 
 	if ((rsa->flags & RSA_FLAG_BLINDING) && (rsa->blinding == NULL))
 		RSA_blinding_on(rsa,ctx);
 	if (rsa->flags & RSA_FLAG_BLINDING)
-		if (!BN_BLINDING_convert(f,rsa->blinding,ctx)) goto err;
+		if (!BN_BLINDING_convert(&f,rsa->blinding,ctx)) goto err;
 
 	/* do the decrypt */
 	if (	(rsa->p != NULL) &&
@@ -298,29 +301,29 @@
 		(rsa->dmp1 != NULL) &&
 		(rsa->dmq1 != NULL) &&
 		(rsa->iqmp != NULL))
-		{ if (!rsa->meth->rsa_mod_exp(ret,f,rsa)) goto err; }
+		{ if (!rsa->meth->rsa_mod_exp(&ret,&f,rsa)) goto err; }
 	else
 		{
-		if (!rsa->meth->bn_mod_exp(ret,f,rsa->d,rsa->n,ctx))
+		if (!rsa->meth->bn_mod_exp(&ret,&f,rsa->d,rsa->n,ctx,NULL))
 			goto err;
 		}
 
 	if (rsa->flags & RSA_FLAG_BLINDING)
-		if (!BN_BLINDING_invert(ret,rsa->blinding,ctx)) goto err;
+		if (!BN_BLINDING_invert(&ret,rsa->blinding,ctx)) goto err;
 
 	p=buf;
-	j=BN_bn2bin(ret,p); /* j is only used with no-padding mode */
+	j=BN_bn2bin(&ret,p); /* j is only used with no-padding mode */
 
 	switch (padding)
 		{
 	case RSA_PKCS1_PADDING:
-		r=RSA_padding_check_PKCS1_type_2(to,num,buf,j);
+		r=RSA_padding_check_PKCS1_type_2(to,num,buf,j,num);
 		break;
 	case RSA_SSLV23_PADDING:
-		r=RSA_padding_check_SSLv23(to,num,buf,j);
+		r=RSA_padding_check_SSLv23(to,num,buf,j,num);
 		break;
 	case RSA_NO_PADDING:
-		r=RSA_padding_check_none(to,num,buf,j);
+		r=RSA_padding_check_none(to,num,buf,j,num);
 		break;
 	default:
 		RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT,RSA_R_UNKNOWN_PADDING_TYPE);
@@ -331,8 +334,8 @@
 
 err:
 	if (ctx != NULL) BN_CTX_free(ctx);
-	if (f != NULL) BN_free(f);
-	if (ret != NULL) BN_free(ret);
+	BN_clear_free(&f);
+	BN_clear_free(&ret);
 	if (buf != NULL)
 		{
 		memset(buf,0,num);
@@ -348,12 +351,14 @@
 RSA *rsa;
 int padding;
 	{
-	BIGNUM *f=NULL,*ret=NULL;
+	BIGNUM f,ret;
 	int i,num=0,r= -1;
 	unsigned char *p;
 	unsigned char *buf=NULL;
 	BN_CTX *ctx=NULL;
 
+	BN_init(&f);
+	BN_init(&ret);
 	ctx=BN_CTX_new();
 	if (ctx == NULL) goto err;
 
@@ -373,10 +378,7 @@
 		goto err;
 		}
 
-	/* make data into a big number */
-	if (((ret=BN_new()) == NULL) || ((f=BN_new()) == NULL)) goto err;
-
-	if (BN_bin2bn(from,flen,f) == NULL) goto err;
+	if (BN_bin2bn(from,flen,&f) == NULL) goto err;
 	/* do the decrypt */
 	if ((rsa->method_mod_n == NULL) && (rsa->flags & RSA_FLAG_CACHE_PUBLIC))
 		{
@@ -385,19 +387,19 @@
 				rsa->n,ctx)) goto err;
 		}
 
-	if (!rsa->meth->bn_mod_exp(ret,f,rsa->e,rsa->n,ctx,
+	if (!rsa->meth->bn_mod_exp(&ret,&f,rsa->e,rsa->n,ctx,
 		rsa->method_mod_n)) goto err;
 
 	p=buf;
-	i=BN_bn2bin(ret,p);
+	i=BN_bn2bin(&ret,p);
 
 	switch (padding)
 		{
 	case RSA_PKCS1_PADDING:
-		r=RSA_padding_check_PKCS1_type_1(to,num,buf,i);
+		r=RSA_padding_check_PKCS1_type_1(to,num,buf,i,num);
 		break;
 	case RSA_NO_PADDING:
-		r=RSA_padding_check_none(to,num,buf,i);
+		r=RSA_padding_check_none(to,num,buf,i,num);
 		break;
 	default:
 		RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT,RSA_R_UNKNOWN_PADDING_TYPE);
@@ -408,8 +410,8 @@
 
 err:
 	if (ctx != NULL) BN_CTX_free(ctx);
-	if (f != NULL) BN_free(f);
-	if (ret != NULL) BN_free(ret);
+	BN_clear_free(&f);
+	BN_clear_free(&ret);
 	if (buf != NULL)
 		{
 		memset(buf,0,num);
@@ -423,14 +425,13 @@
 BIGNUM *I;
 RSA *rsa;
 	{
-	BIGNUM *r1=NULL,*m1=NULL;
+	BIGNUM r1,m1;
 	int ret=0;
 	BN_CTX *ctx;
 
 	if ((ctx=BN_CTX_new()) == NULL) goto err;
-	m1=BN_new();
-	r1=BN_new();
-	if ((m1 == NULL) || (r1 == NULL)) goto err;
+	BN_init(&m1);
+	BN_init(&r1);
 
 	if (rsa->flags & RSA_FLAG_CACHE_PRIVATE)
 		{
@@ -452,26 +453,29 @@
 			}
 		}
 
-	if (!BN_mod(r1,I,rsa->q,ctx)) goto err;
-	if (!rsa->meth->bn_mod_exp(m1,r1,rsa->dmq1,rsa->q,ctx,
+	if (!BN_mod(&r1,I,rsa->q,ctx)) goto err;
+	if (!rsa->meth->bn_mod_exp(&m1,&r1,rsa->dmq1,rsa->q,ctx,
 		rsa->method_mod_q)) goto err;
 
-	if (!BN_mod(r1,I,rsa->p,ctx)) goto err;
-	if (!rsa->meth->bn_mod_exp(r0,r1,rsa->dmp1,rsa->p,ctx,
+	if (!BN_mod(&r1,I,rsa->p,ctx)) goto err;
+	if (!rsa->meth->bn_mod_exp(r0,&r1,rsa->dmp1,rsa->p,ctx,
 		rsa->method_mod_p)) goto err;
 
-	if (!BN_add(r1,r0,rsa->p)) goto err;
-	if (!BN_sub(r0,r1,m1)) goto err;
+	if (!BN_sub(r0,r0,&m1)) goto err;
+	/* This will help stop the size of r0 increasing, which does
+	 * affect the multiply if it optimised for a power of 2 size */
+	if (r0->neg)
+		if (!BN_add(r0,r0,rsa->p)) goto err;
 
-	if (!BN_mul(r1,r0,rsa->iqmp)) goto err;
-	if (!BN_mod(r0,r1,rsa->p,ctx)) goto err;
-	if (!BN_mul(r1,r0,rsa->q)) goto err;
-	if (!BN_add(r0,r1,m1)) goto err;
+	if (!BN_mul(&r1,r0,rsa->iqmp,ctx)) goto err;
+	if (!BN_mod(r0,&r1,rsa->p,ctx)) goto err;
+	if (!BN_mul(&r1,r0,rsa->q,ctx)) goto err;
+	if (!BN_add(r0,&r1,&m1)) goto err;
 
 	ret=1;
 err:
-	if (m1 != NULL) BN_free(m1);
-	if (r1 != NULL) BN_free(r1);
+	BN_clear_free(&m1);
+	BN_clear_free(&r1);
 	BN_CTX_free(ctx);
 	return(ret);
 	}
diff --git a/crypto/rsa/rsa_err.c b/crypto/rsa/rsa_err.c
index 796b3af..7899a5d 100644
--- a/crypto/rsa/rsa_err.c
+++ b/crypto/rsa/rsa_err.c
@@ -63,6 +63,7 @@
 #ifndef NO_ERR
 static ERR_STRING_DATA RSA_str_functs[]=
 	{
+{ERR_PACK(0,RSA_F_MEMORY_LOCK,0),	"MEMORY_LOCK"},
 {ERR_PACK(0,RSA_F_RSA_EAY_PRIVATE_DECRYPT,0),	"RSA_EAY_PRIVATE_DECRYPT"},
 {ERR_PACK(0,RSA_F_RSA_EAY_PRIVATE_ENCRYPT,0),	"RSA_EAY_PRIVATE_ENCRYPT"},
 {ERR_PACK(0,RSA_F_RSA_EAY_PUBLIC_DECRYPT,0),	"RSA_EAY_PUBLIC_DECRYPT"},
@@ -117,8 +118,8 @@
 	{
 	static int init=1;
 
-	if (init);
-		{;
+	if (init)
+		{
 		init=0;
 #ifndef NO_ERR
 		ERR_load_strings(ERR_LIB_RSA,RSA_str_functs);
diff --git a/crypto/rsa/rsa_gen.c b/crypto/rsa/rsa_gen.c
index aed2351..936db49 100644
--- a/crypto/rsa/rsa_gen.c
+++ b/crypto/rsa/rsa_gen.c
@@ -70,17 +70,17 @@
 	{
 	RSA *rsa=NULL;
 	BIGNUM *r0=NULL,*r1=NULL,*r2=NULL,*r3=NULL,*tmp;
-	int bitsp,bitsq,ok= -1,n=0;
+	int bitsp,bitsq,ok= -1,n=0,i;
 	BN_CTX *ctx=NULL,*ctx2=NULL;
 
 	ctx=BN_CTX_new();
 	if (ctx == NULL) goto err;
 	ctx2=BN_CTX_new();
 	if (ctx2 == NULL) goto err;
-	r0=ctx->bn[0];
-	r1=ctx->bn[1];
-	r2=ctx->bn[2];
-	r3=ctx->bn[3];
+	r0= &(ctx->bn[0]);
+	r1= &(ctx->bn[1]);
+	r2= &(ctx->bn[2]);
+	r3= &(ctx->bn[3]);
 	ctx->tos+=4;
 
 	bitsp=(bits+1)/2;
@@ -91,12 +91,23 @@
 	/* set e */ 
 	rsa->e=BN_new();
 	if (rsa->e == NULL) goto err;
+
+#if 1
+	/* The problem is when building with 8, 16, or 32 BN_ULONG,
+	 * unsigned long can be larger */
+	for (i=0; i<sizeof(unsigned long)*8; i++)
+		{
+		if (e_value & (1<<i))
+			BN_set_bit(rsa->e,i);
+		}
+#else
 	if (!BN_set_word(rsa->e,e_value)) goto err;
+#endif
 
 	/* generate p and q */
 	for (;;)
 		{
-		rsa->p=BN_generate_prime(bitsp,0,NULL,NULL,callback,cb_arg);
+		rsa->p=BN_generate_prime(NULL,bitsp,0,NULL,NULL,callback,cb_arg);
 		if (rsa->p == NULL) goto err;
 		if (!BN_sub(r2,rsa->p,BN_value_one())) goto err;
 		if (!BN_gcd(r1,r2,rsa->e,ctx)) goto err;
@@ -107,7 +118,7 @@
 	if (callback != NULL) callback(3,0,cb_arg);
 	for (;;)
 		{
-		rsa->q=BN_generate_prime(bitsq,0,NULL,NULL,callback,cb_arg);
+		rsa->q=BN_generate_prime(NULL,bitsq,0,NULL,NULL,callback,cb_arg);
 		if (rsa->q == NULL) goto err;
 		if (!BN_sub(r2,rsa->q,BN_value_one())) goto err;
 		if (!BN_gcd(r1,r2,rsa->e,ctx)) goto err;
@@ -127,12 +138,12 @@
 	/* calculate n */
 	rsa->n=BN_new();
 	if (rsa->n == NULL) goto err;
-	if (!BN_mul(rsa->n,rsa->p,rsa->q)) goto err;
+	if (!BN_mul(rsa->n,rsa->p,rsa->q,ctx)) goto err;
 
 	/* calculate d */
 	if (!BN_sub(r1,rsa->p,BN_value_one())) goto err;	/* p-1 */
 	if (!BN_sub(r2,rsa->q,BN_value_one())) goto err;	/* q-1 */
-	if (!BN_mul(r0,r1,r2)) goto err;	/* (p-1)(q-1) */
+	if (!BN_mul(r0,r1,r2,ctx)) goto err;	/* (p-1)(q-1) */
 
 /* should not be needed, since gcd(p-1,e) == 1 and gcd(q-1,e) == 1 */
 /*	for (;;)
@@ -149,7 +160,7 @@
 		goto err;
 		}
 */
-	rsa->d=(BIGNUM *)BN_mod_inverse(rsa->e,r0,ctx2);	/* d */
+	rsa->d=(BIGNUM *)BN_mod_inverse(NULL,rsa->e,r0,ctx2);	/* d */
 	if (rsa->d == NULL) goto err;
 
 	/* calculate d mod (p-1) */
@@ -163,7 +174,7 @@
 	if (!BN_mod(rsa->dmq1,rsa->d,r2,ctx)) goto err;
 
 	/* calculate inverse of q mod p */
-	rsa->iqmp=BN_mod_inverse(rsa->q,rsa->p,ctx2);
+	rsa->iqmp=BN_mod_inverse(NULL,rsa->q,rsa->p,ctx2);
 	if (rsa->iqmp == NULL) goto err;
 
 	ok=1;
diff --git a/crypto/rsa/rsa_lib.c b/crypto/rsa/rsa_lib.c
index 95a56f8..5ce51f9 100644
--- a/crypto/rsa/rsa_lib.c
+++ b/crypto/rsa/rsa_lib.c
@@ -63,7 +63,7 @@
 #include "bn.h"
 #include "rsa.h"
 
-char *RSA_version="RSA part of SSLeay 0.9.0b 29-Jun-1998";
+char *RSA_version="RSA part of SSLeay 0.9.1a 06-Jul-1998";
 
 static RSA_METHOD *default_RSA_meth=NULL;
 static int rsa_meth_num=0;
@@ -120,13 +120,15 @@
 	ret->method_mod_p=NULL;
 	ret->method_mod_q=NULL;
 	ret->blinding=NULL;
+	ret->bignum_data=NULL;
 	ret->flags=ret->meth->flags;
 	if ((ret->meth->init != NULL) && !ret->meth->init(ret))
 		{
 		Free(ret);
 		ret=NULL;
 		}
-	CRYPTO_new_ex_data(rsa_meth,(char *)ret,&ret->ex_data);
+	else
+		CRYPTO_new_ex_data(rsa_meth,(char *)ret,&ret->ex_data);
 	return(ret);
 	}
 
@@ -164,6 +166,7 @@
 	if (r->dmq1 != NULL) BN_clear_free(r->dmq1);
 	if (r->iqmp != NULL) BN_clear_free(r->iqmp);
 	if (r->blinding != NULL) BN_BLINDING_free(r->blinding);
+	if (r->bignum_data != NULL) Free_locked(r->bignum_data);
 	Free(r);
 	}
 
@@ -275,10 +278,10 @@
 	if (rsa->blinding != NULL)
 		BN_BLINDING_free(rsa->blinding);
 
-	A=ctx->bn[0];
+	A= &(ctx->bn[0]);
 	ctx->tos++;
 	if (!BN_rand(A,BN_num_bits(rsa->n)-1,1,0)) goto err;
-	if ((Ai=BN_mod_inverse(A,rsa->n,ctx)) == NULL) goto err;
+	if ((Ai=BN_mod_inverse(NULL,A,rsa->n,ctx)) == NULL) goto err;
 
 	if (!rsa->meth->bn_mod_exp(A,A,rsa->e,rsa->n,ctx,
 		(char *)rsa->method_mod_n)) goto err;
@@ -292,3 +295,49 @@
 	return(ret);
 	}
 
+int RSA_memory_lock(r)
+RSA *r;
+	{
+	int i,j,k,off;
+	char *p;
+	BIGNUM *bn,**t[6],*b;
+	BN_ULONG *ul;
+
+	if (r->d == NULL) return(1);
+	t[0]= &r->d;
+	t[1]= &r->p;
+	t[2]= &r->q;
+	t[3]= &r->dmp1;
+	t[4]= &r->dmq1;
+	t[5]= &r->iqmp;
+	k=sizeof(BIGNUM)*6;
+	off=k/sizeof(BN_ULONG)+1;
+	j=1;
+	for (i=0; i<6; i++)
+		j+= (*t[i])->top;
+	if ((p=Malloc_locked((off+j)*sizeof(BN_ULONG))) == NULL)
+		{
+		RSAerr(RSA_F_MEMORY_LOCK,ERR_R_MALLOC_FAILURE);
+		return(0);
+		}
+	bn=(BIGNUM *)p;
+	ul=(BN_ULONG *)&(p[off]);
+	for (i=0; i<6; i++)
+		{
+		b= *(t[i]);
+		*(t[i])= &(bn[i]);
+		memcpy((char *)&(bn[i]),(char *)b,sizeof(BIGNUM));
+		bn[i].flags=BN_FLG_STATIC_DATA;
+		bn[i].d=ul;
+		memcpy((char *)ul,b->d,sizeof(BN_ULONG)*b->top);
+		ul+=b->top;
+		BN_clear_free(b);
+		}
+	
+	/* I should fix this so it can still be done */
+	r->flags&= ~(RSA_FLAG_CACHE_PRIVATE|RSA_FLAG_CACHE_PUBLIC);
+
+	r->bignum_data=p;
+	return(1);
+	}
+
diff --git a/crypto/rsa/rsa_none.c b/crypto/rsa/rsa_none.c
index f0dd943..6385b55 100644
--- a/crypto/rsa/rsa_none.c
+++ b/crypto/rsa/rsa_none.c
@@ -79,11 +79,12 @@
 	return(1);
 	}
 
-int RSA_padding_check_none(to,tlen,from,flen)
+int RSA_padding_check_none(to,tlen,from,flen,num)
 unsigned char *to;
 int tlen;
 unsigned char *from;
 int flen;
+int num;
 	{
 	int j;
 
@@ -93,7 +94,7 @@
 		RSAerr(RSA_F_RSA_PADDING_CHECK_NONE,RSA_R_DATA_TOO_LARGE);
 		return(-1);
 		}
-	if (*(from++) != 0)
+	if (flen+1 >= num)
 		{
 		RSAerr(RSA_F_RSA_PADDING_CHECK_NONE,RSA_R_BAD_ZERO_BYTE);
 		return(-1);
diff --git a/crypto/rsa/rsa_pk1.c b/crypto/rsa/rsa_pk1.c
index 2791291..4638187 100644
--- a/crypto/rsa/rsa_pk1.c
+++ b/crypto/rsa/rsa_pk1.c
@@ -103,17 +103,18 @@
 	return(1);
 	}
 
-int RSA_padding_check_PKCS1_type_1(to,tlen,from,flen)
+int RSA_padding_check_PKCS1_type_1(to,tlen,from,flen,num)
 unsigned char *to;
 int tlen;
 unsigned char *from;
 int flen;
+int num;
 	{
 	int i,j;
 	unsigned char *p;
 
 	p=from;
-	if (*(p++) != 01)
+	if ((num != (flen+1)) || (*(p++) != 01))
 		{
 		RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,RSA_R_BLOCK_TYPE_IS_NOT_01);
 		return(-1);
@@ -192,21 +193,25 @@
 	return(1);
 	}
 
-int RSA_padding_check_PKCS1_type_2(to,tlen,from,flen)
+int RSA_padding_check_PKCS1_type_2(to,tlen,from,flen,num)
 unsigned char *to;
 int tlen;
 unsigned char *from;
 int flen;
+int num;
 	{
 	int i,j;
 	unsigned char *p;
 
 	p=from;
-	if (*(p++) != 02)
+	if ((num != (flen+1)) || (*(p++) != 02))
 		{
 		RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2,RSA_R_BLOCK_TYPE_IS_NOT_02);
 		return(-1);
 		}
+#ifdef PKCS1_CHECK
+	return(num-11);
+#endif
 
 	/* scan over padding data */
 	j=flen-1; /* one for type. */
diff --git a/crypto/rsa/rsa_sign.c b/crypto/rsa/rsa_sign.c
index 28c5571..e389111 100644
--- a/crypto/rsa/rsa_sign.c
+++ b/crypto/rsa/rsa_sign.c
@@ -154,9 +154,11 @@
 
 	p=s;
 	sig=d2i_X509_SIG(NULL,&p,(long)i);
+
 	if (sig == NULL) goto err;
 	sigtype=OBJ_obj2nid(sig->algor->algorithm);
 
+
 #ifdef RSA_DEBUG
 	/* put a backward compatability flag in EAY */
 	fprintf(stderr,"in(%s) expect(%s)\n",OBJ_nid2ln(sigtype),
diff --git a/crypto/rsa/rsa_ssl.c b/crypto/rsa/rsa_ssl.c
index 9bcd4b2..42ee076 100644
--- a/crypto/rsa/rsa_ssl.c
+++ b/crypto/rsa/rsa_ssl.c
@@ -103,11 +103,12 @@
 	return(1);
 	}
 
-int RSA_padding_check_SSLv23(to,tlen,from,flen)
+int RSA_padding_check_SSLv23(to,tlen,from,flen,num)
 unsigned char *to;
 int tlen;
 unsigned char *from;
 int flen;
+int num;
 	{
 	int i,j,k;
 	unsigned char *p;
@@ -118,7 +119,7 @@
 		RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23,RSA_R_DATA_TOO_SMALL);
 		return(-1);
 		}
-	if (*(p++) != 02)
+	if ((num != (flen+1)) || (*(p++) != 02))
 		{
 		RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23,RSA_R_BLOCK_TYPE_IS_NOT_02);
 		return(-1);
diff --git a/crypto/sha/Makefile.ssl b/crypto/sha/Makefile.ssl
index eeb545d..fd389b1 100644
--- a/crypto/sha/Makefile.ssl
+++ b/crypto/sha/Makefile.ssl
@@ -58,7 +58,7 @@
 
 # bsdi
 asm/sx86bsdi.o: asm/sx86unix.cpp
-	$(CPP) -DBSDI asm/sx86unix.cpp | as -o asm/sx86bsdi.o
+	$(CPP) -DBSDI asm/sx86unix.cpp | sed 's/ :/:/' | as -o asm/sx86bsdi.o
 
 asm/sx86unix.cpp:
 	(cd asm; perl sha1-586.pl cpp >sx86unix.cpp)
diff --git a/crypto/sha/asm/a.out b/crypto/sha/asm/a.out
new file mode 100644
index 0000000..ca165d5
--- /dev/null
+++ b/crypto/sha/asm/a.out
Binary files differ
diff --git a/crypto/sha/asm/f b/crypto/sha/asm/f
new file mode 100644
index 0000000..3a702f5
--- /dev/null
+++ b/crypto/sha/asm/f
@@ -0,0 +1,2089 @@
+GAS LISTING f.s 			page 1
+
+
+   1              		# Don't even think of reading this code 
+   2              		# It was automatically generated by sha1-586.pl 
+   3              		# Which is a perl program used to generate the x86 assember for 
+   4              		# any of elf, a.out, BSDI,Win32, or Solaris 
+   5              		# eric <eay@cryptsoft.com> 
+   6              	
+   7              		.file	"sha1-586.s"
+   8              		.version	"01.01"
+   9              	gcc2_compiled.:
+  10              	.text
+  11              		.align 16
+  12              	.globl sha1_block_x86
+  13              		.type	sha1_block_x86,@function
+  14              	sha1_block_x86:
+  15 0000 56       		pushl	%esi
+  16 0001 55       		pushl	%ebp
+  17 0002 8B442414 		movl	20(%esp),	%eax
+  18 0006 8B742410 		movl	16(%esp),	%esi
+  19 000a 01F0     		addl	%esi,		%eax
+  20 000c 8B6C240C 		movl	12(%esp),	%ebp
+  21 0010 53       		pushl	%ebx
+  22 0011 83E840   		subl	$64,		%eax
+  23 0014 57       		pushl	%edi
+  24 0015 8B5D04   		movl	4(%ebp),	%ebx
+  25 0018 83EC48   		subl	$72,		%esp
+  26 001b 8B550C   		movl	12(%ebp),	%edx
+  27 001e 8B7D10   		movl	16(%ebp),	%edi
+  28 0021 8B4D08   		movl	8(%ebp),	%ecx
+  29 0024 89442444 		movl	%eax,		68(%esp)
+  30              		# First we need to setup the X array 
+  31 0028 8B06     		movl	(%esi),		%eax
+  32              	.L000start:
+  33              		# First, load the words onto the stack in network byte order 
+  34 002a 0F       	.byte 15
+  35 002b C8       	.byte 200		# bswapl  %eax 
+  36 002c 890424   		movl	%eax,		(%esp)
+  37 002f 8B4604   		movl	4(%esi),	%eax
+  38 0032 0F       	.byte 15
+  39 0033 C8       	.byte 200		# bswapl  %eax 
+  40 0034 89442404 		movl	%eax,		4(%esp)
+  41 0038 8B4608   		movl	8(%esi),	%eax
+  42 003b 0F       	.byte 15
+  43 003c C8       	.byte 200		# bswapl  %eax 
+  44 003d 89442408 		movl	%eax,		8(%esp)
+  45 0041 8B460C   		movl	12(%esi),	%eax
+  46 0044 0F       	.byte 15
+  47 0045 C8       	.byte 200		# bswapl  %eax 
+  48 0046 8944240C 		movl	%eax,		12(%esp)
+  49 004a 8B4610   		movl	16(%esi),	%eax
+  50 004d 0F       	.byte 15
+  51 004e C8       	.byte 200		# bswapl  %eax 
+  52 004f 89442410 		movl	%eax,		16(%esp)
+  53 0053 8B4614   		movl	20(%esi),	%eax
+  54 0056 0F       	.byte 15
+  55 0057 C8       	.byte 200		# bswapl  %eax 
+  56 0058 89442414 		movl	%eax,		20(%esp)
+  57 005c 8B4618   		movl	24(%esi),	%eax
+GAS LISTING f.s 			page 2
+
+
+  58 005f 0F       	.byte 15
+  59 0060 C8       	.byte 200		# bswapl  %eax 
+  60 0061 89442418 		movl	%eax,		24(%esp)
+  61 0065 8B461C   		movl	28(%esi),	%eax
+  62 0068 0F       	.byte 15
+  63 0069 C8       	.byte 200		# bswapl  %eax 
+  64 006a 8944241C 		movl	%eax,		28(%esp)
+  65 006e 8B4620   		movl	32(%esi),	%eax
+  66 0071 0F       	.byte 15
+  67 0072 C8       	.byte 200		# bswapl  %eax 
+  68 0073 89442420 		movl	%eax,		32(%esp)
+  69 0077 8B4624   		movl	36(%esi),	%eax
+  70 007a 0F       	.byte 15
+  71 007b C8       	.byte 200		# bswapl  %eax 
+  72 007c 89442424 		movl	%eax,		36(%esp)
+  73 0080 8B4628   		movl	40(%esi),	%eax
+  74 0083 0F       	.byte 15
+  75 0084 C8       	.byte 200		# bswapl  %eax 
+  76 0085 89442428 		movl	%eax,		40(%esp)
+  77 0089 8B462C   		movl	44(%esi),	%eax
+  78 008c 0F       	.byte 15
+  79 008d C8       	.byte 200		# bswapl  %eax 
+  80 008e 8944242C 		movl	%eax,		44(%esp)
+  81 0092 8B4630   		movl	48(%esi),	%eax
+  82 0095 0F       	.byte 15
+  83 0096 C8       	.byte 200		# bswapl  %eax 
+  84 0097 89442430 		movl	%eax,		48(%esp)
+  85 009b 8B4634   		movl	52(%esi),	%eax
+  86 009e 0F       	.byte 15
+  87 009f C8       	.byte 200		# bswapl  %eax 
+  88 00a0 89442434 		movl	%eax,		52(%esp)
+  89 00a4 8B4638   		movl	56(%esi),	%eax
+  90 00a7 0F       	.byte 15
+  91 00a8 C8       	.byte 200		# bswapl  %eax 
+  92 00a9 89442438 		movl	%eax,		56(%esp)
+  93 00ad 8B463C   		movl	60(%esi),	%eax
+  94 00b0 0F       	.byte 15
+  95 00b1 C8       	.byte 200		# bswapl  %eax 
+  96 00b2 8944243C 		movl	%eax,		60(%esp)
+  97              		# We now have the X array on the stack 
+  98              		# starting at sp-4 
+  99 00b6 89742440 		movl	%esi,		64(%esp)
+ 100              	
+ 101              		# Start processing 
+ 102 00ba 8B4500   		movl	(%ebp),		%eax
+ 103              		# 00_15 0 
+ 104 00bd 89CE     		movl	%ecx,		%esi
+ 105 00bf 89C5     		movl	%eax,		%ebp
+ 106 00c1 31D6     		xorl	%edx,		%esi
+ 107 00c3 C1C505   		roll	$5,		%ebp
+ 108 00c6 21DE     		andl	%ebx,		%esi
+ 109 00c8 01FD     		addl	%edi,		%ebp
+ 110 00ca D1       	.byte 209
+ 111 00cb CB       	.byte 203		# rorl $1 %ebx 
+ 112 00cc 8B3C24   		movl	(%esp),		%edi
+ 113 00cf D1       	.byte 209
+ 114 00d0 CB       	.byte 203		# rorl $1 %ebx 
+GAS LISTING f.s 			page 3
+
+
+ 115 00d1 31D6     		xorl	%edx,		%esi
+ 116 00d3 8DAC3D99 		leal	1518500249(%ebp,%edi,1),%ebp
+ 116      79825A
+ 117 00da 89DF     		movl	%ebx,		%edi
+ 118 00dc 01EE     		addl	%ebp,		%esi
+ 119 00de 31CF     		xorl	%ecx,		%edi
+ 120 00e0 89F5     		movl	%esi,		%ebp
+ 121 00e2 21C7     		andl	%eax,		%edi
+ 122 00e4 C1C505   		roll	$5,		%ebp
+ 123 00e7 01D5     		addl	%edx,		%ebp
+ 124 00e9 8B542404 		movl	4(%esp),	%edx
+ 125 00ed D1       	.byte 209
+ 126 00ee C8       	.byte 200		# rorl $1 %eax 
+ 127 00ef 31CF     		xorl	%ecx,		%edi
+ 128 00f1 D1       	.byte 209
+ 129 00f2 C8       	.byte 200		# rorl $1 %eax 
+ 130 00f3 8DAC1599 		leal	1518500249(%ebp,%edx,1),%ebp
+ 130      79825A
+ 131 00fa 01EF     		addl	%ebp,		%edi
+ 132              		# 00_15 2 
+ 133 00fc 89C2     		movl	%eax,		%edx
+ 134 00fe 89FD     		movl	%edi,		%ebp
+ 135 0100 31DA     		xorl	%ebx,		%edx
+ 136 0102 C1C505   		roll	$5,		%ebp
+ 137 0105 21F2     		andl	%esi,		%edx
+ 138 0107 01CD     		addl	%ecx,		%ebp
+ 139 0109 D1       	.byte 209
+ 140 010a CE       	.byte 206		# rorl $1 %esi 
+ 141 010b 8B4C2408 		movl	8(%esp),	%ecx
+ 142 010f D1       	.byte 209
+ 143 0110 CE       	.byte 206		# rorl $1 %esi 
+ 144 0111 31DA     		xorl	%ebx,		%edx
+ 145 0113 8DAC0D99 		leal	1518500249(%ebp,%ecx,1),%ebp
+ 145      79825A
+ 146 011a 89F1     		movl	%esi,		%ecx
+ 147 011c 01EA     		addl	%ebp,		%edx
+ 148 011e 31C1     		xorl	%eax,		%ecx
+ 149 0120 89D5     		movl	%edx,		%ebp
+ 150 0122 21F9     		andl	%edi,		%ecx
+ 151 0124 C1C505   		roll	$5,		%ebp
+ 152 0127 01DD     		addl	%ebx,		%ebp
+ 153 0129 8B5C240C 		movl	12(%esp),	%ebx
+ 154 012d D1       	.byte 209
+ 155 012e CF       	.byte 207		# rorl $1 %edi 
+ 156 012f 31C1     		xorl	%eax,		%ecx
+ 157 0131 D1       	.byte 209
+ 158 0132 CF       	.byte 207		# rorl $1 %edi 
+ 159 0133 8DAC1D99 		leal	1518500249(%ebp,%ebx,1),%ebp
+ 159      79825A
+ 160 013a 01E9     		addl	%ebp,		%ecx
+ 161              		# 00_15 4 
+ 162 013c 89FB     		movl	%edi,		%ebx
+ 163 013e 89CD     		movl	%ecx,		%ebp
+ 164 0140 31F3     		xorl	%esi,		%ebx
+ 165 0142 C1C505   		roll	$5,		%ebp
+ 166 0145 21D3     		andl	%edx,		%ebx
+ 167 0147 01C5     		addl	%eax,		%ebp
+GAS LISTING f.s 			page 4
+
+
+ 168 0149 D1       	.byte 209
+ 169 014a CA       	.byte 202		# rorl $1 %edx 
+ 170 014b 8B442410 		movl	16(%esp),	%eax
+ 171 014f D1       	.byte 209
+ 172 0150 CA       	.byte 202		# rorl $1 %edx 
+ 173 0151 31F3     		xorl	%esi,		%ebx
+ 174 0153 8DAC0599 		leal	1518500249(%ebp,%eax,1),%ebp
+ 174      79825A
+ 175 015a 89D0     		movl	%edx,		%eax
+ 176 015c 01EB     		addl	%ebp,		%ebx
+ 177 015e 31F8     		xorl	%edi,		%eax
+ 178 0160 89DD     		movl	%ebx,		%ebp
+ 179 0162 21C8     		andl	%ecx,		%eax
+ 180 0164 C1C505   		roll	$5,		%ebp
+ 181 0167 01F5     		addl	%esi,		%ebp
+ 182 0169 8B742414 		movl	20(%esp),	%esi
+ 183 016d D1       	.byte 209
+ 184 016e C9       	.byte 201		# rorl $1 %ecx 
+ 185 016f 31F8     		xorl	%edi,		%eax
+ 186 0171 D1       	.byte 209
+ 187 0172 C9       	.byte 201		# rorl $1 %ecx 
+ 188 0173 8DAC3599 		leal	1518500249(%ebp,%esi,1),%ebp
+ 188      79825A
+ 189 017a 01E8     		addl	%ebp,		%eax
+ 190              		# 00_15 6 
+ 191 017c 89CE     		movl	%ecx,		%esi
+ 192 017e 89C5     		movl	%eax,		%ebp
+ 193 0180 31D6     		xorl	%edx,		%esi
+ 194 0182 C1C505   		roll	$5,		%ebp
+ 195 0185 21DE     		andl	%ebx,		%esi
+ 196 0187 01FD     		addl	%edi,		%ebp
+ 197 0189 D1       	.byte 209
+ 198 018a CB       	.byte 203		# rorl $1 %ebx 
+ 199 018b 8B7C2418 		movl	24(%esp),	%edi
+ 200 018f D1       	.byte 209
+ 201 0190 CB       	.byte 203		# rorl $1 %ebx 
+ 202 0191 31D6     		xorl	%edx,		%esi
+ 203 0193 8DAC3D99 		leal	1518500249(%ebp,%edi,1),%ebp
+ 203      79825A
+ 204 019a 89DF     		movl	%ebx,		%edi
+ 205 019c 01EE     		addl	%ebp,		%esi
+ 206 019e 31CF     		xorl	%ecx,		%edi
+ 207 01a0 89F5     		movl	%esi,		%ebp
+ 208 01a2 21C7     		andl	%eax,		%edi
+ 209 01a4 C1C505   		roll	$5,		%ebp
+ 210 01a7 01D5     		addl	%edx,		%ebp
+ 211 01a9 8B54241C 		movl	28(%esp),	%edx
+ 212 01ad D1       	.byte 209
+ 213 01ae C8       	.byte 200		# rorl $1 %eax 
+ 214 01af 31CF     		xorl	%ecx,		%edi
+ 215 01b1 D1       	.byte 209
+ 216 01b2 C8       	.byte 200		# rorl $1 %eax 
+ 217 01b3 8DAC1599 		leal	1518500249(%ebp,%edx,1),%ebp
+ 217      79825A
+ 218 01ba 01EF     		addl	%ebp,		%edi
+ 219              		# 00_15 8 
+ 220 01bc 89C2     		movl	%eax,		%edx
+GAS LISTING f.s 			page 5
+
+
+ 221 01be 89FD     		movl	%edi,		%ebp
+ 222 01c0 31DA     		xorl	%ebx,		%edx
+ 223 01c2 C1C505   		roll	$5,		%ebp
+ 224 01c5 21F2     		andl	%esi,		%edx
+ 225 01c7 01CD     		addl	%ecx,		%ebp
+ 226 01c9 D1       	.byte 209
+ 227 01ca CE       	.byte 206		# rorl $1 %esi 
+ 228 01cb 8B4C2420 		movl	32(%esp),	%ecx
+ 229 01cf D1       	.byte 209
+ 230 01d0 CE       	.byte 206		# rorl $1 %esi 
+ 231 01d1 31DA     		xorl	%ebx,		%edx
+ 232 01d3 8DAC0D99 		leal	1518500249(%ebp,%ecx,1),%ebp
+ 232      79825A
+ 233 01da 89F1     		movl	%esi,		%ecx
+ 234 01dc 01EA     		addl	%ebp,		%edx
+ 235 01de 31C1     		xorl	%eax,		%ecx
+ 236 01e0 89D5     		movl	%edx,		%ebp
+ 237 01e2 21F9     		andl	%edi,		%ecx
+ 238 01e4 C1C505   		roll	$5,		%ebp
+ 239 01e7 01DD     		addl	%ebx,		%ebp
+ 240 01e9 8B5C2424 		movl	36(%esp),	%ebx
+ 241 01ed D1       	.byte 209
+ 242 01ee CF       	.byte 207		# rorl $1 %edi 
+ 243 01ef 31C1     		xorl	%eax,		%ecx
+ 244 01f1 D1       	.byte 209
+ 245 01f2 CF       	.byte 207		# rorl $1 %edi 
+ 246 01f3 8DAC1D99 		leal	1518500249(%ebp,%ebx,1),%ebp
+ 246      79825A
+ 247 01fa 01E9     		addl	%ebp,		%ecx
+ 248              		# 00_15 10 
+ 249 01fc 89FB     		movl	%edi,		%ebx
+ 250 01fe 89CD     		movl	%ecx,		%ebp
+ 251 0200 31F3     		xorl	%esi,		%ebx
+ 252 0202 C1C505   		roll	$5,		%ebp
+ 253 0205 21D3     		andl	%edx,		%ebx
+ 254 0207 01C5     		addl	%eax,		%ebp
+ 255 0209 D1       	.byte 209
+ 256 020a CA       	.byte 202		# rorl $1 %edx 
+ 257 020b 8B442428 		movl	40(%esp),	%eax
+ 258 020f D1       	.byte 209
+ 259 0210 CA       	.byte 202		# rorl $1 %edx 
+ 260 0211 31F3     		xorl	%esi,		%ebx
+ 261 0213 8DAC0599 		leal	1518500249(%ebp,%eax,1),%ebp
+ 261      79825A
+ 262 021a 89D0     		movl	%edx,		%eax
+ 263 021c 01EB     		addl	%ebp,		%ebx
+ 264 021e 31F8     		xorl	%edi,		%eax
+ 265 0220 89DD     		movl	%ebx,		%ebp
+ 266 0222 21C8     		andl	%ecx,		%eax
+ 267 0224 C1C505   		roll	$5,		%ebp
+ 268 0227 01F5     		addl	%esi,		%ebp
+ 269 0229 8B74242C 		movl	44(%esp),	%esi
+ 270 022d D1       	.byte 209
+ 271 022e C9       	.byte 201		# rorl $1 %ecx 
+ 272 022f 31F8     		xorl	%edi,		%eax
+ 273 0231 D1       	.byte 209
+ 274 0232 C9       	.byte 201		# rorl $1 %ecx 
+GAS LISTING f.s 			page 6
+
+
+ 275 0233 8DAC3599 		leal	1518500249(%ebp,%esi,1),%ebp
+ 275      79825A
+ 276 023a 01E8     		addl	%ebp,		%eax
+ 277              		# 00_15 12 
+ 278 023c 89CE     		movl	%ecx,		%esi
+ 279 023e 89C5     		movl	%eax,		%ebp
+ 280 0240 31D6     		xorl	%edx,		%esi
+ 281 0242 C1C505   		roll	$5,		%ebp
+ 282 0245 21DE     		andl	%ebx,		%esi
+ 283 0247 01FD     		addl	%edi,		%ebp
+ 284 0249 D1       	.byte 209
+ 285 024a CB       	.byte 203		# rorl $1 %ebx 
+ 286 024b 8B7C2430 		movl	48(%esp),	%edi
+ 287 024f D1       	.byte 209
+ 288 0250 CB       	.byte 203		# rorl $1 %ebx 
+ 289 0251 31D6     		xorl	%edx,		%esi
+ 290 0253 8DAC3D99 		leal	1518500249(%ebp,%edi,1),%ebp
+ 290      79825A
+ 291 025a 89DF     		movl	%ebx,		%edi
+ 292 025c 01EE     		addl	%ebp,		%esi
+ 293 025e 31CF     		xorl	%ecx,		%edi
+ 294 0260 89F5     		movl	%esi,		%ebp
+ 295 0262 21C7     		andl	%eax,		%edi
+ 296 0264 C1C505   		roll	$5,		%ebp
+ 297 0267 01D5     		addl	%edx,		%ebp
+ 298 0269 8B542434 		movl	52(%esp),	%edx
+ 299 026d D1       	.byte 209
+ 300 026e C8       	.byte 200		# rorl $1 %eax 
+ 301 026f 31CF     		xorl	%ecx,		%edi
+ 302 0271 D1       	.byte 209
+ 303 0272 C8       	.byte 200		# rorl $1 %eax 
+ 304 0273 8DAC1599 		leal	1518500249(%ebp,%edx,1),%ebp
+ 304      79825A
+ 305 027a 01EF     		addl	%ebp,		%edi
+ 306              		# 00_15 14 
+ 307 027c 89C2     		movl	%eax,		%edx
+ 308 027e 89FD     		movl	%edi,		%ebp
+ 309 0280 31DA     		xorl	%ebx,		%edx
+ 310 0282 C1C505   		roll	$5,		%ebp
+ 311 0285 21F2     		andl	%esi,		%edx
+ 312 0287 01CD     		addl	%ecx,		%ebp
+ 313 0289 D1       	.byte 209
+ 314 028a CE       	.byte 206		# rorl $1 %esi 
+ 315 028b 8B4C2438 		movl	56(%esp),	%ecx
+ 316 028f D1       	.byte 209
+ 317 0290 CE       	.byte 206		# rorl $1 %esi 
+ 318 0291 31DA     		xorl	%ebx,		%edx
+ 319 0293 8DAC0D99 		leal	1518500249(%ebp,%ecx,1),%ebp
+ 319      79825A
+ 320 029a 89F1     		movl	%esi,		%ecx
+ 321 029c 01EA     		addl	%ebp,		%edx
+ 322 029e 31C1     		xorl	%eax,		%ecx
+ 323 02a0 89D5     		movl	%edx,		%ebp
+ 324 02a2 21F9     		andl	%edi,		%ecx
+ 325 02a4 C1C505   		roll	$5,		%ebp
+ 326 02a7 01DD     		addl	%ebx,		%ebp
+ 327 02a9 8B5C243C 		movl	60(%esp),	%ebx
+GAS LISTING f.s 			page 7
+
+
+ 328 02ad D1       	.byte 209
+ 329 02ae CF       	.byte 207		# rorl $1 %edi 
+ 330 02af 31C1     		xorl	%eax,		%ecx
+ 331 02b1 D1       	.byte 209
+ 332 02b2 CF       	.byte 207		# rorl $1 %edi 
+ 333 02b3 8DAC1D99 		leal	1518500249(%ebp,%ebx,1),%ebp
+ 333      79825A
+ 334 02ba 01E9     		addl	%ebp,		%ecx
+ 335              		# 16_19 16 
+ 336 02bc 90       		nop
+ 337 02bd 8B2C24   		movl	(%esp),		%ebp
+ 338 02c0 8B5C2408 		movl	8(%esp),	%ebx
+ 339 02c4 31EB     		xorl	%ebp,		%ebx
+ 340 02c6 8B6C2420 		movl	32(%esp),	%ebp
+ 341 02ca 31EB     		xorl	%ebp,		%ebx
+ 342 02cc 8B6C2434 		movl	52(%esp),	%ebp
+ 343 02d0 31EB     		xorl	%ebp,		%ebx
+ 344 02d2 89FD     		movl	%edi,		%ebp
+ 345 02d4 D1       	.byte 209
+ 346 02d5 C3       	.byte 195		# roll $1 %ebx 
+ 347 02d6 31F5     		xorl	%esi,		%ebp
+ 348 02d8 891C24   		movl	%ebx,		(%esp)
+ 349 02db 21D5     		andl	%edx,		%ebp
+ 350 02dd 8D9C0399 		leal	1518500249(%ebx,%eax,1),%ebx
+ 350      79825A
+ 351 02e4 31F5     		xorl	%esi,		%ebp
+ 352 02e6 89C8     		movl	%ecx,		%eax
+ 353 02e8 01EB     		addl	%ebp,		%ebx
+ 354 02ea C1C005   		roll	$5,		%eax
+ 355 02ed D1       	.byte 209
+ 356 02ee CA       	.byte 202		# rorl $1 %edx 
+ 357 02ef 01C3     		addl	%eax,		%ebx
+ 358 02f1 8B442404 		movl	4(%esp),	%eax
+ 359 02f5 8B6C240C 		movl	12(%esp),	%ebp
+ 360 02f9 31E8     		xorl	%ebp,		%eax
+ 361 02fb 8B6C2424 		movl	36(%esp),	%ebp
+ 362 02ff 31E8     		xorl	%ebp,		%eax
+ 363 0301 8B6C2438 		movl	56(%esp),	%ebp
+ 364 0305 D1       	.byte 209
+ 365 0306 CA       	.byte 202		# rorl $1 %edx 
+ 366 0307 31E8     		xorl	%ebp,		%eax
+ 367 0309 D1       	.byte 209
+ 368 030a C0       	.byte 192		# roll $1 %eax 
+ 369 030b 89D5     		movl	%edx,		%ebp
+ 370 030d 31FD     		xorl	%edi,		%ebp
+ 371 030f 89442404 		movl	%eax,		4(%esp)
+ 372 0313 21CD     		andl	%ecx,		%ebp
+ 373 0315 8D843099 		leal	1518500249(%eax,%esi,1),%eax
+ 373      79825A
+ 374 031c 31FD     		xorl	%edi,		%ebp
+ 375 031e 89DE     		movl	%ebx,		%esi
+ 376 0320 C1C605   		roll	$5,		%esi
+ 377 0323 D1       	.byte 209
+ 378 0324 C9       	.byte 201		# rorl $1 %ecx 
+ 379 0325 01F0     		addl	%esi,		%eax
+ 380 0327 D1       	.byte 209
+ 381 0328 C9       	.byte 201		# rorl $1 %ecx 
+GAS LISTING f.s 			page 8
+
+
+ 382 0329 01E8     		addl	%ebp,		%eax
+ 383              		# 16_19 18 
+ 384 032b 8B6C2408 		movl	8(%esp),	%ebp
+ 385 032f 8B742410 		movl	16(%esp),	%esi
+ 386 0333 31EE     		xorl	%ebp,		%esi
+ 387 0335 8B6C2428 		movl	40(%esp),	%ebp
+ 388 0339 31EE     		xorl	%ebp,		%esi
+ 389 033b 8B6C243C 		movl	60(%esp),	%ebp
+ 390 033f 31EE     		xorl	%ebp,		%esi
+ 391 0341 89CD     		movl	%ecx,		%ebp
+ 392 0343 D1       	.byte 209
+ 393 0344 C6       	.byte 198		# roll $1 %esi 
+ 394 0345 31D5     		xorl	%edx,		%ebp
+ 395 0347 89742408 		movl	%esi,		8(%esp)
+ 396 034b 21DD     		andl	%ebx,		%ebp
+ 397 034d 8DB43E99 		leal	1518500249(%esi,%edi,1),%esi
+ 397      79825A
+ 398 0354 31D5     		xorl	%edx,		%ebp
+ 399 0356 89C7     		movl	%eax,		%edi
+ 400 0358 01EE     		addl	%ebp,		%esi
+ 401 035a C1C705   		roll	$5,		%edi
+ 402 035d D1       	.byte 209
+ 403 035e CB       	.byte 203		# rorl $1 %ebx 
+ 404 035f 01FE     		addl	%edi,		%esi
+ 405 0361 8B7C240C 		movl	12(%esp),	%edi
+ 406 0365 8B6C2414 		movl	20(%esp),	%ebp
+ 407 0369 31EF     		xorl	%ebp,		%edi
+ 408 036b 8B6C242C 		movl	44(%esp),	%ebp
+ 409 036f 31EF     		xorl	%ebp,		%edi
+ 410 0371 8B2C24   		movl	(%esp),		%ebp
+ 411 0374 D1       	.byte 209
+ 412 0375 CB       	.byte 203		# rorl $1 %ebx 
+ 413 0376 31EF     		xorl	%ebp,		%edi
+ 414 0378 D1       	.byte 209
+ 415 0379 C7       	.byte 199		# roll $1 %edi 
+ 416 037a 89DD     		movl	%ebx,		%ebp
+ 417 037c 31CD     		xorl	%ecx,		%ebp
+ 418 037e 897C240C 		movl	%edi,		12(%esp)
+ 419 0382 21C5     		andl	%eax,		%ebp
+ 420 0384 8DBC1799 		leal	1518500249(%edi,%edx,1),%edi
+ 420      79825A
+ 421 038b 31CD     		xorl	%ecx,		%ebp
+ 422 038d 89F2     		movl	%esi,		%edx
+ 423 038f C1C205   		roll	$5,		%edx
+ 424 0392 D1       	.byte 209
+ 425 0393 C8       	.byte 200		# rorl $1 %eax 
+ 426 0394 01D7     		addl	%edx,		%edi
+ 427 0396 D1       	.byte 209
+ 428 0397 C8       	.byte 200		# rorl $1 %eax 
+ 429 0398 01EF     		addl	%ebp,		%edi
+ 430              		# 20_39 20 
+ 431 039a 8B542410 		movl	16(%esp),	%edx
+ 432 039e 8B6C2418 		movl	24(%esp),	%ebp
+ 433 03a2 31EA     		xorl	%ebp,		%edx
+ 434 03a4 8B6C2430 		movl	48(%esp),	%ebp
+ 435 03a8 31EA     		xorl	%ebp,		%edx
+ 436 03aa 8B6C2404 		movl	4(%esp),	%ebp
+GAS LISTING f.s 			page 9
+
+
+ 437 03ae 31EA     		xorl	%ebp,		%edx
+ 438 03b0 89F5     		movl	%esi,		%ebp
+ 439 03b2 D1       	.byte 209
+ 440 03b3 C2       	.byte 194		# roll $1 %edx 
+ 441 03b4 31C5     		xorl	%eax,		%ebp
+ 442 03b6 89542410 		movl	%edx,		16(%esp)
+ 443 03ba 31DD     		xorl	%ebx,		%ebp
+ 444 03bc 8D940AA1 		leal	1859775393(%edx,%ecx,1),%edx
+ 444      EBD96E
+ 445 03c3 89F9     		movl	%edi,		%ecx
+ 446 03c5 C1C105   		roll	$5,		%ecx
+ 447 03c8 D1       	.byte 209
+ 448 03c9 CE       	.byte 206		# rorl $1 %esi 
+ 449 03ca 01E9     		addl	%ebp,		%ecx
+ 450 03cc D1       	.byte 209
+ 451 03cd CE       	.byte 206		# rorl $1 %esi 
+ 452 03ce 01CA     		addl	%ecx,		%edx
+ 453              		# 20_39 21 
+ 454 03d0 8B4C2414 		movl	20(%esp),	%ecx
+ 455 03d4 8B6C241C 		movl	28(%esp),	%ebp
+ 456 03d8 31E9     		xorl	%ebp,		%ecx
+ 457 03da 8B6C2434 		movl	52(%esp),	%ebp
+ 458 03de 31E9     		xorl	%ebp,		%ecx
+ 459 03e0 8B6C2408 		movl	8(%esp),	%ebp
+ 460 03e4 31E9     		xorl	%ebp,		%ecx
+ 461 03e6 89FD     		movl	%edi,		%ebp
+ 462 03e8 D1       	.byte 209
+ 463 03e9 C1       	.byte 193		# roll $1 %ecx 
+ 464 03ea 31F5     		xorl	%esi,		%ebp
+ 465 03ec 894C2414 		movl	%ecx,		20(%esp)
+ 466 03f0 31C5     		xorl	%eax,		%ebp
+ 467 03f2 8D8C19A1 		leal	1859775393(%ecx,%ebx,1),%ecx
+ 467      EBD96E
+ 468 03f9 89D3     		movl	%edx,		%ebx
+ 469 03fb C1C305   		roll	$5,		%ebx
+ 470 03fe D1       	.byte 209
+ 471 03ff CF       	.byte 207		# rorl $1 %edi 
+ 472 0400 01EB     		addl	%ebp,		%ebx
+ 473 0402 D1       	.byte 209
+ 474 0403 CF       	.byte 207		# rorl $1 %edi 
+ 475 0404 01D9     		addl	%ebx,		%ecx
+ 476              		# 20_39 22 
+ 477 0406 8B5C2418 		movl	24(%esp),	%ebx
+ 478 040a 8B6C2420 		movl	32(%esp),	%ebp
+ 479 040e 31EB     		xorl	%ebp,		%ebx
+ 480 0410 8B6C2438 		movl	56(%esp),	%ebp
+ 481 0414 31EB     		xorl	%ebp,		%ebx
+ 482 0416 8B6C240C 		movl	12(%esp),	%ebp
+ 483 041a 31EB     		xorl	%ebp,		%ebx
+ 484 041c 89D5     		movl	%edx,		%ebp
+ 485 041e D1       	.byte 209
+ 486 041f C3       	.byte 195		# roll $1 %ebx 
+ 487 0420 31FD     		xorl	%edi,		%ebp
+ 488 0422 895C2418 		movl	%ebx,		24(%esp)
+ 489 0426 31F5     		xorl	%esi,		%ebp
+ 490 0428 8D9C03A1 		leal	1859775393(%ebx,%eax,1),%ebx
+ 490      EBD96E
+GAS LISTING f.s 			page 10
+
+
+ 491 042f 89C8     		movl	%ecx,		%eax
+ 492 0431 C1C005   		roll	$5,		%eax
+ 493 0434 D1       	.byte 209
+ 494 0435 CA       	.byte 202		# rorl $1 %edx 
+ 495 0436 01E8     		addl	%ebp,		%eax
+ 496 0438 D1       	.byte 209
+ 497 0439 CA       	.byte 202		# rorl $1 %edx 
+ 498 043a 01C3     		addl	%eax,		%ebx
+ 499              		# 20_39 23 
+ 500 043c 8B44241C 		movl	28(%esp),	%eax
+ 501 0440 8B6C2424 		movl	36(%esp),	%ebp
+ 502 0444 31E8     		xorl	%ebp,		%eax
+ 503 0446 8B6C243C 		movl	60(%esp),	%ebp
+ 504 044a 31E8     		xorl	%ebp,		%eax
+ 505 044c 8B6C2410 		movl	16(%esp),	%ebp
+ 506 0450 31E8     		xorl	%ebp,		%eax
+ 507 0452 89CD     		movl	%ecx,		%ebp
+ 508 0454 D1       	.byte 209
+ 509 0455 C0       	.byte 192		# roll $1 %eax 
+ 510 0456 31D5     		xorl	%edx,		%ebp
+ 511 0458 8944241C 		movl	%eax,		28(%esp)
+ 512 045c 31FD     		xorl	%edi,		%ebp
+ 513 045e 8D8430A1 		leal	1859775393(%eax,%esi,1),%eax
+ 513      EBD96E
+ 514 0465 89DE     		movl	%ebx,		%esi
+ 515 0467 C1C605   		roll	$5,		%esi
+ 516 046a D1       	.byte 209
+ 517 046b C9       	.byte 201		# rorl $1 %ecx 
+ 518 046c 01EE     		addl	%ebp,		%esi
+ 519 046e D1       	.byte 209
+ 520 046f C9       	.byte 201		# rorl $1 %ecx 
+ 521 0470 01F0     		addl	%esi,		%eax
+ 522              		# 20_39 24 
+ 523 0472 8B742420 		movl	32(%esp),	%esi
+ 524 0476 8B6C2428 		movl	40(%esp),	%ebp
+ 525 047a 31EE     		xorl	%ebp,		%esi
+ 526 047c 8B2C24   		movl	(%esp),		%ebp
+ 527 047f 31EE     		xorl	%ebp,		%esi
+ 528 0481 8B6C2414 		movl	20(%esp),	%ebp
+ 529 0485 31EE     		xorl	%ebp,		%esi
+ 530 0487 89DD     		movl	%ebx,		%ebp
+ 531 0489 D1       	.byte 209
+ 532 048a C6       	.byte 198		# roll $1 %esi 
+ 533 048b 31CD     		xorl	%ecx,		%ebp
+ 534 048d 89742420 		movl	%esi,		32(%esp)
+ 535 0491 31D5     		xorl	%edx,		%ebp
+ 536 0493 8DB43EA1 		leal	1859775393(%esi,%edi,1),%esi
+ 536      EBD96E
+ 537 049a 89C7     		movl	%eax,		%edi
+ 538 049c C1C705   		roll	$5,		%edi
+ 539 049f D1       	.byte 209
+ 540 04a0 CB       	.byte 203		# rorl $1 %ebx 
+ 541 04a1 01EF     		addl	%ebp,		%edi
+ 542 04a3 D1       	.byte 209
+ 543 04a4 CB       	.byte 203		# rorl $1 %ebx 
+ 544 04a5 01FE     		addl	%edi,		%esi
+ 545              		# 20_39 25 
+GAS LISTING f.s 			page 11
+
+
+ 546 04a7 8B7C2424 		movl	36(%esp),	%edi
+ 547 04ab 8B6C242C 		movl	44(%esp),	%ebp
+ 548 04af 31EF     		xorl	%ebp,		%edi
+ 549 04b1 8B6C2404 		movl	4(%esp),	%ebp
+ 550 04b5 31EF     		xorl	%ebp,		%edi
+ 551 04b7 8B6C2418 		movl	24(%esp),	%ebp
+ 552 04bb 31EF     		xorl	%ebp,		%edi
+ 553 04bd 89C5     		movl	%eax,		%ebp
+ 554 04bf D1       	.byte 209
+ 555 04c0 C7       	.byte 199		# roll $1 %edi 
+ 556 04c1 31DD     		xorl	%ebx,		%ebp
+ 557 04c3 897C2424 		movl	%edi,		36(%esp)
+ 558 04c7 31CD     		xorl	%ecx,		%ebp
+ 559 04c9 8DBC17A1 		leal	1859775393(%edi,%edx,1),%edi
+ 559      EBD96E
+ 560 04d0 89F2     		movl	%esi,		%edx
+ 561 04d2 C1C205   		roll	$5,		%edx
+ 562 04d5 D1       	.byte 209
+ 563 04d6 C8       	.byte 200		# rorl $1 %eax 
+ 564 04d7 01EA     		addl	%ebp,		%edx
+ 565 04d9 D1       	.byte 209
+ 566 04da C8       	.byte 200		# rorl $1 %eax 
+ 567 04db 01D7     		addl	%edx,		%edi
+ 568              		# 20_39 26 
+ 569 04dd 8B542428 		movl	40(%esp),	%edx
+ 570 04e1 8B6C2430 		movl	48(%esp),	%ebp
+ 571 04e5 31EA     		xorl	%ebp,		%edx
+ 572 04e7 8B6C2408 		movl	8(%esp),	%ebp
+ 573 04eb 31EA     		xorl	%ebp,		%edx
+ 574 04ed 8B6C241C 		movl	28(%esp),	%ebp
+ 575 04f1 31EA     		xorl	%ebp,		%edx
+ 576 04f3 89F5     		movl	%esi,		%ebp
+ 577 04f5 D1       	.byte 209
+ 578 04f6 C2       	.byte 194		# roll $1 %edx 
+ 579 04f7 31C5     		xorl	%eax,		%ebp
+ 580 04f9 89542428 		movl	%edx,		40(%esp)
+ 581 04fd 31DD     		xorl	%ebx,		%ebp
+ 582 04ff 8D940AA1 		leal	1859775393(%edx,%ecx,1),%edx
+ 582      EBD96E
+ 583 0506 89F9     		movl	%edi,		%ecx
+ 584 0508 C1C105   		roll	$5,		%ecx
+ 585 050b D1       	.byte 209
+ 586 050c CE       	.byte 206		# rorl $1 %esi 
+ 587 050d 01E9     		addl	%ebp,		%ecx
+ 588 050f D1       	.byte 209
+ 589 0510 CE       	.byte 206		# rorl $1 %esi 
+ 590 0511 01CA     		addl	%ecx,		%edx
+ 591              		# 20_39 27 
+ 592 0513 8B4C242C 		movl	44(%esp),	%ecx
+ 593 0517 8B6C2434 		movl	52(%esp),	%ebp
+ 594 051b 31E9     		xorl	%ebp,		%ecx
+ 595 051d 8B6C240C 		movl	12(%esp),	%ebp
+ 596 0521 31E9     		xorl	%ebp,		%ecx
+ 597 0523 8B6C2420 		movl	32(%esp),	%ebp
+ 598 0527 31E9     		xorl	%ebp,		%ecx
+ 599 0529 89FD     		movl	%edi,		%ebp
+ 600 052b D1       	.byte 209
+GAS LISTING f.s 			page 12
+
+
+ 601 052c C1       	.byte 193		# roll $1 %ecx 
+ 602 052d 31F5     		xorl	%esi,		%ebp
+ 603 052f 894C242C 		movl	%ecx,		44(%esp)
+ 604 0533 31C5     		xorl	%eax,		%ebp
+ 605 0535 8D8C19A1 		leal	1859775393(%ecx,%ebx,1),%ecx
+ 605      EBD96E
+ 606 053c 89D3     		movl	%edx,		%ebx
+ 607 053e C1C305   		roll	$5,		%ebx
+ 608 0541 D1       	.byte 209
+ 609 0542 CF       	.byte 207		# rorl $1 %edi 
+ 610 0543 01EB     		addl	%ebp,		%ebx
+ 611 0545 D1       	.byte 209
+ 612 0546 CF       	.byte 207		# rorl $1 %edi 
+ 613 0547 01D9     		addl	%ebx,		%ecx
+ 614              		# 20_39 28 
+ 615 0549 8B5C2430 		movl	48(%esp),	%ebx
+ 616 054d 8B6C2438 		movl	56(%esp),	%ebp
+ 617 0551 31EB     		xorl	%ebp,		%ebx
+ 618 0553 8B6C2410 		movl	16(%esp),	%ebp
+ 619 0557 31EB     		xorl	%ebp,		%ebx
+ 620 0559 8B6C2424 		movl	36(%esp),	%ebp
+ 621 055d 31EB     		xorl	%ebp,		%ebx
+ 622 055f 89D5     		movl	%edx,		%ebp
+ 623 0561 D1       	.byte 209
+ 624 0562 C3       	.byte 195		# roll $1 %ebx 
+ 625 0563 31FD     		xorl	%edi,		%ebp
+ 626 0565 895C2430 		movl	%ebx,		48(%esp)
+ 627 0569 31F5     		xorl	%esi,		%ebp
+ 628 056b 8D9C03A1 		leal	1859775393(%ebx,%eax,1),%ebx
+ 628      EBD96E
+ 629 0572 89C8     		movl	%ecx,		%eax
+ 630 0574 C1C005   		roll	$5,		%eax
+ 631 0577 D1       	.byte 209
+ 632 0578 CA       	.byte 202		# rorl $1 %edx 
+ 633 0579 01E8     		addl	%ebp,		%eax
+ 634 057b D1       	.byte 209
+ 635 057c CA       	.byte 202		# rorl $1 %edx 
+ 636 057d 01C3     		addl	%eax,		%ebx
+ 637              		# 20_39 29 
+ 638 057f 8B442434 		movl	52(%esp),	%eax
+ 639 0583 8B6C243C 		movl	60(%esp),	%ebp
+ 640 0587 31E8     		xorl	%ebp,		%eax
+ 641 0589 8B6C2414 		movl	20(%esp),	%ebp
+ 642 058d 31E8     		xorl	%ebp,		%eax
+ 643 058f 8B6C2428 		movl	40(%esp),	%ebp
+ 644 0593 31E8     		xorl	%ebp,		%eax
+ 645 0595 89CD     		movl	%ecx,		%ebp
+ 646 0597 D1       	.byte 209
+ 647 0598 C0       	.byte 192		# roll $1 %eax 
+ 648 0599 31D5     		xorl	%edx,		%ebp
+ 649 059b 89442434 		movl	%eax,		52(%esp)
+ 650 059f 31FD     		xorl	%edi,		%ebp
+ 651 05a1 8D8430A1 		leal	1859775393(%eax,%esi,1),%eax
+ 651      EBD96E
+ 652 05a8 89DE     		movl	%ebx,		%esi
+ 653 05aa C1C605   		roll	$5,		%esi
+ 654 05ad D1       	.byte 209
+GAS LISTING f.s 			page 13
+
+
+ 655 05ae C9       	.byte 201		# rorl $1 %ecx 
+ 656 05af 01EE     		addl	%ebp,		%esi
+ 657 05b1 D1       	.byte 209
+ 658 05b2 C9       	.byte 201		# rorl $1 %ecx 
+ 659 05b3 01F0     		addl	%esi,		%eax
+ 660              		# 20_39 30 
+ 661 05b5 8B742438 		movl	56(%esp),	%esi
+ 662 05b9 8B2C24   		movl	(%esp),		%ebp
+ 663 05bc 31EE     		xorl	%ebp,		%esi
+ 664 05be 8B6C2418 		movl	24(%esp),	%ebp
+ 665 05c2 31EE     		xorl	%ebp,		%esi
+ 666 05c4 8B6C242C 		movl	44(%esp),	%ebp
+ 667 05c8 31EE     		xorl	%ebp,		%esi
+ 668 05ca 89DD     		movl	%ebx,		%ebp
+ 669 05cc D1       	.byte 209
+ 670 05cd C6       	.byte 198		# roll $1 %esi 
+ 671 05ce 31CD     		xorl	%ecx,		%ebp
+ 672 05d0 89742438 		movl	%esi,		56(%esp)
+ 673 05d4 31D5     		xorl	%edx,		%ebp
+ 674 05d6 8DB43EA1 		leal	1859775393(%esi,%edi,1),%esi
+ 674      EBD96E
+ 675 05dd 89C7     		movl	%eax,		%edi
+ 676 05df C1C705   		roll	$5,		%edi
+ 677 05e2 D1       	.byte 209
+ 678 05e3 CB       	.byte 203		# rorl $1 %ebx 
+ 679 05e4 01EF     		addl	%ebp,		%edi
+ 680 05e6 D1       	.byte 209
+ 681 05e7 CB       	.byte 203		# rorl $1 %ebx 
+ 682 05e8 01FE     		addl	%edi,		%esi
+ 683              		# 20_39 31 
+ 684 05ea 8B7C243C 		movl	60(%esp),	%edi
+ 685 05ee 8B6C2404 		movl	4(%esp),	%ebp
+ 686 05f2 31EF     		xorl	%ebp,		%edi
+ 687 05f4 8B6C241C 		movl	28(%esp),	%ebp
+ 688 05f8 31EF     		xorl	%ebp,		%edi
+ 689 05fa 8B6C2430 		movl	48(%esp),	%ebp
+ 690 05fe 31EF     		xorl	%ebp,		%edi
+ 691 0600 89C5     		movl	%eax,		%ebp
+ 692 0602 D1       	.byte 209
+ 693 0603 C7       	.byte 199		# roll $1 %edi 
+ 694 0604 31DD     		xorl	%ebx,		%ebp
+ 695 0606 897C243C 		movl	%edi,		60(%esp)
+ 696 060a 31CD     		xorl	%ecx,		%ebp
+ 697 060c 8DBC17A1 		leal	1859775393(%edi,%edx,1),%edi
+ 697      EBD96E
+ 698 0613 89F2     		movl	%esi,		%edx
+ 699 0615 C1C205   		roll	$5,		%edx
+ 700 0618 D1       	.byte 209
+ 701 0619 C8       	.byte 200		# rorl $1 %eax 
+ 702 061a 01EA     		addl	%ebp,		%edx
+ 703 061c D1       	.byte 209
+ 704 061d C8       	.byte 200		# rorl $1 %eax 
+ 705 061e 01D7     		addl	%edx,		%edi
+ 706              		# 20_39 32 
+ 707 0620 8B1424   		movl	(%esp),		%edx
+ 708 0623 8B6C2408 		movl	8(%esp),	%ebp
+ 709 0627 31EA     		xorl	%ebp,		%edx
+GAS LISTING f.s 			page 14
+
+
+ 710 0629 8B6C2420 		movl	32(%esp),	%ebp
+ 711 062d 31EA     		xorl	%ebp,		%edx
+ 712 062f 8B6C2434 		movl	52(%esp),	%ebp
+ 713 0633 31EA     		xorl	%ebp,		%edx
+ 714 0635 89F5     		movl	%esi,		%ebp
+ 715 0637 D1       	.byte 209
+ 716 0638 C2       	.byte 194		# roll $1 %edx 
+ 717 0639 31C5     		xorl	%eax,		%ebp
+ 718 063b 891424   		movl	%edx,		(%esp)
+ 719 063e 31DD     		xorl	%ebx,		%ebp
+ 720 0640 8D940AA1 		leal	1859775393(%edx,%ecx,1),%edx
+ 720      EBD96E
+ 721 0647 89F9     		movl	%edi,		%ecx
+ 722 0649 C1C105   		roll	$5,		%ecx
+ 723 064c D1       	.byte 209
+ 724 064d CE       	.byte 206		# rorl $1 %esi 
+ 725 064e 01E9     		addl	%ebp,		%ecx
+ 726 0650 D1       	.byte 209
+ 727 0651 CE       	.byte 206		# rorl $1 %esi 
+ 728 0652 01CA     		addl	%ecx,		%edx
+ 729              		# 20_39 33 
+ 730 0654 8B4C2404 		movl	4(%esp),	%ecx
+ 731 0658 8B6C240C 		movl	12(%esp),	%ebp
+ 732 065c 31E9     		xorl	%ebp,		%ecx
+ 733 065e 8B6C2424 		movl	36(%esp),	%ebp
+ 734 0662 31E9     		xorl	%ebp,		%ecx
+ 735 0664 8B6C2438 		movl	56(%esp),	%ebp
+ 736 0668 31E9     		xorl	%ebp,		%ecx
+ 737 066a 89FD     		movl	%edi,		%ebp
+ 738 066c D1       	.byte 209
+ 739 066d C1       	.byte 193		# roll $1 %ecx 
+ 740 066e 31F5     		xorl	%esi,		%ebp
+ 741 0670 894C2404 		movl	%ecx,		4(%esp)
+ 742 0674 31C5     		xorl	%eax,		%ebp
+ 743 0676 8D8C19A1 		leal	1859775393(%ecx,%ebx,1),%ecx
+ 743      EBD96E
+ 744 067d 89D3     		movl	%edx,		%ebx
+ 745 067f C1C305   		roll	$5,		%ebx
+ 746 0682 D1       	.byte 209
+ 747 0683 CF       	.byte 207		# rorl $1 %edi 
+ 748 0684 01EB     		addl	%ebp,		%ebx
+ 749 0686 D1       	.byte 209
+ 750 0687 CF       	.byte 207		# rorl $1 %edi 
+ 751 0688 01D9     		addl	%ebx,		%ecx
+ 752              		# 20_39 34 
+ 753 068a 8B5C2408 		movl	8(%esp),	%ebx
+ 754 068e 8B6C2410 		movl	16(%esp),	%ebp
+ 755 0692 31EB     		xorl	%ebp,		%ebx
+ 756 0694 8B6C2428 		movl	40(%esp),	%ebp
+ 757 0698 31EB     		xorl	%ebp,		%ebx
+ 758 069a 8B6C243C 		movl	60(%esp),	%ebp
+ 759 069e 31EB     		xorl	%ebp,		%ebx
+ 760 06a0 89D5     		movl	%edx,		%ebp
+ 761 06a2 D1       	.byte 209
+ 762 06a3 C3       	.byte 195		# roll $1 %ebx 
+ 763 06a4 31FD     		xorl	%edi,		%ebp
+ 764 06a6 895C2408 		movl	%ebx,		8(%esp)
+GAS LISTING f.s 			page 15
+
+
+ 765 06aa 31F5     		xorl	%esi,		%ebp
+ 766 06ac 8D9C03A1 		leal	1859775393(%ebx,%eax,1),%ebx
+ 766      EBD96E
+ 767 06b3 89C8     		movl	%ecx,		%eax
+ 768 06b5 C1C005   		roll	$5,		%eax
+ 769 06b8 D1       	.byte 209
+ 770 06b9 CA       	.byte 202		# rorl $1 %edx 
+ 771 06ba 01E8     		addl	%ebp,		%eax
+ 772 06bc D1       	.byte 209
+ 773 06bd CA       	.byte 202		# rorl $1 %edx 
+ 774 06be 01C3     		addl	%eax,		%ebx
+ 775              		# 20_39 35 
+ 776 06c0 8B44240C 		movl	12(%esp),	%eax
+ 777 06c4 8B6C2414 		movl	20(%esp),	%ebp
+ 778 06c8 31E8     		xorl	%ebp,		%eax
+ 779 06ca 8B6C242C 		movl	44(%esp),	%ebp
+ 780 06ce 31E8     		xorl	%ebp,		%eax
+ 781 06d0 8B2C24   		movl	(%esp),		%ebp
+ 782 06d3 31E8     		xorl	%ebp,		%eax
+ 783 06d5 89CD     		movl	%ecx,		%ebp
+ 784 06d7 D1       	.byte 209
+ 785 06d8 C0       	.byte 192		# roll $1 %eax 
+ 786 06d9 31D5     		xorl	%edx,		%ebp
+ 787 06db 8944240C 		movl	%eax,		12(%esp)
+ 788 06df 31FD     		xorl	%edi,		%ebp
+ 789 06e1 8D8430A1 		leal	1859775393(%eax,%esi,1),%eax
+ 789      EBD96E
+ 790 06e8 89DE     		movl	%ebx,		%esi
+ 791 06ea C1C605   		roll	$5,		%esi
+ 792 06ed D1       	.byte 209
+ 793 06ee C9       	.byte 201		# rorl $1 %ecx 
+ 794 06ef 01EE     		addl	%ebp,		%esi
+ 795 06f1 D1       	.byte 209
+ 796 06f2 C9       	.byte 201		# rorl $1 %ecx 
+ 797 06f3 01F0     		addl	%esi,		%eax
+ 798              		# 20_39 36 
+ 799 06f5 8B742410 		movl	16(%esp),	%esi
+ 800 06f9 8B6C2418 		movl	24(%esp),	%ebp
+ 801 06fd 31EE     		xorl	%ebp,		%esi
+ 802 06ff 8B6C2430 		movl	48(%esp),	%ebp
+ 803 0703 31EE     		xorl	%ebp,		%esi
+ 804 0705 8B6C2404 		movl	4(%esp),	%ebp
+ 805 0709 31EE     		xorl	%ebp,		%esi
+ 806 070b 89DD     		movl	%ebx,		%ebp
+ 807 070d D1       	.byte 209
+ 808 070e C6       	.byte 198		# roll $1 %esi 
+ 809 070f 31CD     		xorl	%ecx,		%ebp
+ 810 0711 89742410 		movl	%esi,		16(%esp)
+ 811 0715 31D5     		xorl	%edx,		%ebp
+ 812 0717 8DB43EA1 		leal	1859775393(%esi,%edi,1),%esi
+ 812      EBD96E
+ 813 071e 89C7     		movl	%eax,		%edi
+ 814 0720 C1C705   		roll	$5,		%edi
+ 815 0723 D1       	.byte 209
+ 816 0724 CB       	.byte 203		# rorl $1 %ebx 
+ 817 0725 01EF     		addl	%ebp,		%edi
+ 818 0727 D1       	.byte 209
+GAS LISTING f.s 			page 16
+
+
+ 819 0728 CB       	.byte 203		# rorl $1 %ebx 
+ 820 0729 01FE     		addl	%edi,		%esi
+ 821              		# 20_39 37 
+ 822 072b 8B7C2414 		movl	20(%esp),	%edi
+ 823 072f 8B6C241C 		movl	28(%esp),	%ebp
+ 824 0733 31EF     		xorl	%ebp,		%edi
+ 825 0735 8B6C2434 		movl	52(%esp),	%ebp
+ 826 0739 31EF     		xorl	%ebp,		%edi
+ 827 073b 8B6C2408 		movl	8(%esp),	%ebp
+ 828 073f 31EF     		xorl	%ebp,		%edi
+ 829 0741 89C5     		movl	%eax,		%ebp
+ 830 0743 D1       	.byte 209
+ 831 0744 C7       	.byte 199		# roll $1 %edi 
+ 832 0745 31DD     		xorl	%ebx,		%ebp
+ 833 0747 897C2414 		movl	%edi,		20(%esp)
+ 834 074b 31CD     		xorl	%ecx,		%ebp
+ 835 074d 8DBC17A1 		leal	1859775393(%edi,%edx,1),%edi
+ 835      EBD96E
+ 836 0754 89F2     		movl	%esi,		%edx
+ 837 0756 C1C205   		roll	$5,		%edx
+ 838 0759 D1       	.byte 209
+ 839 075a C8       	.byte 200		# rorl $1 %eax 
+ 840 075b 01EA     		addl	%ebp,		%edx
+ 841 075d D1       	.byte 209
+ 842 075e C8       	.byte 200		# rorl $1 %eax 
+ 843 075f 01D7     		addl	%edx,		%edi
+ 844              		# 20_39 38 
+ 845 0761 8B542418 		movl	24(%esp),	%edx
+ 846 0765 8B6C2420 		movl	32(%esp),	%ebp
+ 847 0769 31EA     		xorl	%ebp,		%edx
+ 848 076b 8B6C2438 		movl	56(%esp),	%ebp
+ 849 076f 31EA     		xorl	%ebp,		%edx
+ 850 0771 8B6C240C 		movl	12(%esp),	%ebp
+ 851 0775 31EA     		xorl	%ebp,		%edx
+ 852 0777 89F5     		movl	%esi,		%ebp
+ 853 0779 D1       	.byte 209
+ 854 077a C2       	.byte 194		# roll $1 %edx 
+ 855 077b 31C5     		xorl	%eax,		%ebp
+ 856 077d 89542418 		movl	%edx,		24(%esp)
+ 857 0781 31DD     		xorl	%ebx,		%ebp
+ 858 0783 8D940AA1 		leal	1859775393(%edx,%ecx,1),%edx
+ 858      EBD96E
+ 859 078a 89F9     		movl	%edi,		%ecx
+ 860 078c C1C105   		roll	$5,		%ecx
+ 861 078f D1       	.byte 209
+ 862 0790 CE       	.byte 206		# rorl $1 %esi 
+ 863 0791 01E9     		addl	%ebp,		%ecx
+ 864 0793 D1       	.byte 209
+ 865 0794 CE       	.byte 206		# rorl $1 %esi 
+ 866 0795 01CA     		addl	%ecx,		%edx
+ 867              		# 20_39 39 
+ 868 0797 8B4C241C 		movl	28(%esp),	%ecx
+ 869 079b 8B6C2424 		movl	36(%esp),	%ebp
+ 870 079f 31E9     		xorl	%ebp,		%ecx
+ 871 07a1 8B6C243C 		movl	60(%esp),	%ebp
+ 872 07a5 31E9     		xorl	%ebp,		%ecx
+ 873 07a7 8B6C2410 		movl	16(%esp),	%ebp
+GAS LISTING f.s 			page 17
+
+
+ 874 07ab 31E9     		xorl	%ebp,		%ecx
+ 875 07ad 89FD     		movl	%edi,		%ebp
+ 876 07af D1       	.byte 209
+ 877 07b0 C1       	.byte 193		# roll $1 %ecx 
+ 878 07b1 31F5     		xorl	%esi,		%ebp
+ 879 07b3 894C241C 		movl	%ecx,		28(%esp)
+ 880 07b7 31C5     		xorl	%eax,		%ebp
+ 881 07b9 8D8C19A1 		leal	1859775393(%ecx,%ebx,1),%ecx
+ 881      EBD96E
+ 882 07c0 89D3     		movl	%edx,		%ebx
+ 883 07c2 C1C305   		roll	$5,		%ebx
+ 884 07c5 D1       	.byte 209
+ 885 07c6 CF       	.byte 207		# rorl $1 %edi 
+ 886 07c7 01EB     		addl	%ebp,		%ebx
+ 887 07c9 D1       	.byte 209
+ 888 07ca CF       	.byte 207		# rorl $1 %edi 
+ 889 07cb 01D9     		addl	%ebx,		%ecx
+ 890              		# 40_59 40 
+ 891 07cd 8B5C2420 		movl	32(%esp),	%ebx
+ 892 07d1 8B6C2428 		movl	40(%esp),	%ebp
+ 893 07d5 31EB     		xorl	%ebp,		%ebx
+ 894 07d7 8B2C24   		movl	(%esp),		%ebp
+ 895 07da 31EB     		xorl	%ebp,		%ebx
+ 896 07dc 8B6C2414 		movl	20(%esp),	%ebp
+ 897 07e0 31EB     		xorl	%ebp,		%ebx
+ 898 07e2 89D5     		movl	%edx,		%ebp
+ 899 07e4 D1       	.byte 209
+ 900 07e5 C3       	.byte 195		# roll $1 %ebx 
+ 901 07e6 09FD     		orl	%edi,		%ebp
+ 902 07e8 895C2420 		movl	%ebx,		32(%esp)
+ 903 07ec 21F5     		andl	%esi,		%ebp
+ 904 07ee 8D9C03DC 		leal	2400959708(%ebx,%eax,1),%ebx
+ 904      BC1B8F
+ 905 07f5 89D0     		movl	%edx,		%eax
+ 906 07f7 D1       	.byte 209
+ 907 07f8 CA       	.byte 202		# rorl $1 %edx 
+ 908 07f9 21F8     		andl	%edi,		%eax
+ 909 07fb 09C5     		orl	%eax,		%ebp
+ 910 07fd 89C8     		movl	%ecx,		%eax
+ 911 07ff C1C005   		roll	$5,		%eax
+ 912 0802 01C5     		addl	%eax,		%ebp
+ 913 0804 8B442424 		movl	36(%esp),	%eax
+ 914 0808 01EB     		addl	%ebp,		%ebx
+ 915 080a 8B6C242C 		movl	44(%esp),	%ebp
+ 916 080e 31E8     		xorl	%ebp,		%eax
+ 917 0810 8B6C2404 		movl	4(%esp),	%ebp
+ 918 0814 31E8     		xorl	%ebp,		%eax
+ 919 0816 8B6C2418 		movl	24(%esp),	%ebp
+ 920 081a D1       	.byte 209
+ 921 081b CA       	.byte 202		# rorl $1 %edx 
+ 922 081c 31E8     		xorl	%ebp,		%eax
+ 923 081e D1       	.byte 209
+ 924 081f C0       	.byte 192		# roll $1 %eax 
+ 925 0820 89CD     		movl	%ecx,		%ebp
+ 926 0822 89442424 		movl	%eax,		36(%esp)
+ 927 0826 09D5     		orl	%edx,		%ebp
+ 928 0828 8D8430DC 		leal	2400959708(%eax,%esi,1),%eax
+GAS LISTING f.s 			page 18
+
+
+ 928      BC1B8F
+ 929 082f 89CE     		movl	%ecx,		%esi
+ 930 0831 21FD     		andl	%edi,		%ebp
+ 931 0833 21D6     		andl	%edx,		%esi
+ 932 0835 09F5     		orl	%esi,		%ebp
+ 933 0837 89DE     		movl	%ebx,		%esi
+ 934 0839 C1C605   		roll	$5,		%esi
+ 935 083c D1       	.byte 209
+ 936 083d C9       	.byte 201		# rorl $1 %ecx 
+ 937 083e 01F5     		addl	%esi,		%ebp
+ 938 0840 D1       	.byte 209
+ 939 0841 C9       	.byte 201		# rorl $1 %ecx 
+ 940 0842 01E8     		addl	%ebp,		%eax
+ 941              		# 40_59 41 
+ 942              		# 40_59 42 
+ 943 0844 8B742428 		movl	40(%esp),	%esi
+ 944 0848 8B6C2430 		movl	48(%esp),	%ebp
+ 945 084c 31EE     		xorl	%ebp,		%esi
+ 946 084e 8B6C2408 		movl	8(%esp),	%ebp
+ 947 0852 31EE     		xorl	%ebp,		%esi
+ 948 0854 8B6C241C 		movl	28(%esp),	%ebp
+ 949 0858 31EE     		xorl	%ebp,		%esi
+ 950 085a 89DD     		movl	%ebx,		%ebp
+ 951 085c D1       	.byte 209
+ 952 085d C6       	.byte 198		# roll $1 %esi 
+ 953 085e 09CD     		orl	%ecx,		%ebp
+ 954 0860 89742428 		movl	%esi,		40(%esp)
+ 955 0864 21D5     		andl	%edx,		%ebp
+ 956 0866 8DB43EDC 		leal	2400959708(%esi,%edi,1),%esi
+ 956      BC1B8F
+ 957 086d 89DF     		movl	%ebx,		%edi
+ 958 086f D1       	.byte 209
+ 959 0870 CB       	.byte 203		# rorl $1 %ebx 
+ 960 0871 21CF     		andl	%ecx,		%edi
+ 961 0873 09FD     		orl	%edi,		%ebp
+ 962 0875 89C7     		movl	%eax,		%edi
+ 963 0877 C1C705   		roll	$5,		%edi
+ 964 087a 01FD     		addl	%edi,		%ebp
+ 965 087c 8B7C242C 		movl	44(%esp),	%edi
+ 966 0880 01EE     		addl	%ebp,		%esi
+ 967 0882 8B6C2434 		movl	52(%esp),	%ebp
+ 968 0886 31EF     		xorl	%ebp,		%edi
+ 969 0888 8B6C240C 		movl	12(%esp),	%ebp
+ 970 088c 31EF     		xorl	%ebp,		%edi
+ 971 088e 8B6C2420 		movl	32(%esp),	%ebp
+ 972 0892 D1       	.byte 209
+ 973 0893 CB       	.byte 203		# rorl $1 %ebx 
+ 974 0894 31EF     		xorl	%ebp,		%edi
+ 975 0896 D1       	.byte 209
+ 976 0897 C7       	.byte 199		# roll $1 %edi 
+ 977 0898 89C5     		movl	%eax,		%ebp
+ 978 089a 897C242C 		movl	%edi,		44(%esp)
+ 979 089e 09DD     		orl	%ebx,		%ebp
+ 980 08a0 8DBC17DC 		leal	2400959708(%edi,%edx,1),%edi
+ 980      BC1B8F
+ 981 08a7 89C2     		movl	%eax,		%edx
+ 982 08a9 21CD     		andl	%ecx,		%ebp
+GAS LISTING f.s 			page 19
+
+
+ 983 08ab 21DA     		andl	%ebx,		%edx
+ 984 08ad 09D5     		orl	%edx,		%ebp
+ 985 08af 89F2     		movl	%esi,		%edx
+ 986 08b1 C1C205   		roll	$5,		%edx
+ 987 08b4 D1       	.byte 209
+ 988 08b5 C8       	.byte 200		# rorl $1 %eax 
+ 989 08b6 01D5     		addl	%edx,		%ebp
+ 990 08b8 D1       	.byte 209
+ 991 08b9 C8       	.byte 200		# rorl $1 %eax 
+ 992 08ba 01EF     		addl	%ebp,		%edi
+ 993              		# 40_59 43 
+ 994              		# 40_59 44 
+ 995 08bc 8B542430 		movl	48(%esp),	%edx
+ 996 08c0 8B6C2438 		movl	56(%esp),	%ebp
+ 997 08c4 31EA     		xorl	%ebp,		%edx
+ 998 08c6 8B6C2410 		movl	16(%esp),	%ebp
+ 999 08ca 31EA     		xorl	%ebp,		%edx
+ 1000 08cc 8B6C2424 		movl	36(%esp),	%ebp
+ 1001 08d0 31EA     		xorl	%ebp,		%edx
+ 1002 08d2 89F5     		movl	%esi,		%ebp
+ 1003 08d4 D1       	.byte 209
+ 1004 08d5 C2       	.byte 194		# roll $1 %edx 
+ 1005 08d6 09C5     		orl	%eax,		%ebp
+ 1006 08d8 89542430 		movl	%edx,		48(%esp)
+ 1007 08dc 21DD     		andl	%ebx,		%ebp
+ 1008 08de 8D940ADC 		leal	2400959708(%edx,%ecx,1),%edx
+ 1008      BC1B8F
+ 1009 08e5 89F1     		movl	%esi,		%ecx
+ 1010 08e7 D1       	.byte 209
+ 1011 08e8 CE       	.byte 206		# rorl $1 %esi 
+ 1012 08e9 21C1     		andl	%eax,		%ecx
+ 1013 08eb 09CD     		orl	%ecx,		%ebp
+ 1014 08ed 89F9     		movl	%edi,		%ecx
+ 1015 08ef C1C105   		roll	$5,		%ecx
+ 1016 08f2 01CD     		addl	%ecx,		%ebp
+ 1017 08f4 8B4C2434 		movl	52(%esp),	%ecx
+ 1018 08f8 01EA     		addl	%ebp,		%edx
+ 1019 08fa 8B6C243C 		movl	60(%esp),	%ebp
+ 1020 08fe 31E9     		xorl	%ebp,		%ecx
+ 1021 0900 8B6C2414 		movl	20(%esp),	%ebp
+ 1022 0904 31E9     		xorl	%ebp,		%ecx
+ 1023 0906 8B6C2428 		movl	40(%esp),	%ebp
+ 1024 090a D1       	.byte 209
+ 1025 090b CE       	.byte 206		# rorl $1 %esi 
+ 1026 090c 31E9     		xorl	%ebp,		%ecx
+ 1027 090e D1       	.byte 209
+ 1028 090f C1       	.byte 193		# roll $1 %ecx 
+ 1029 0910 89FD     		movl	%edi,		%ebp
+ 1030 0912 894C2434 		movl	%ecx,		52(%esp)
+ 1031 0916 09F5     		orl	%esi,		%ebp
+ 1032 0918 8D8C19DC 		leal	2400959708(%ecx,%ebx,1),%ecx
+ 1032      BC1B8F
+ 1033 091f 89FB     		movl	%edi,		%ebx
+ 1034 0921 21C5     		andl	%eax,		%ebp
+ 1035 0923 21F3     		andl	%esi,		%ebx
+ 1036 0925 09DD     		orl	%ebx,		%ebp
+ 1037 0927 89D3     		movl	%edx,		%ebx
+GAS LISTING f.s 			page 20
+
+
+ 1038 0929 C1C305   		roll	$5,		%ebx
+ 1039 092c D1       	.byte 209
+ 1040 092d CF       	.byte 207		# rorl $1 %edi 
+ 1041 092e 01DD     		addl	%ebx,		%ebp
+ 1042 0930 D1       	.byte 209
+ 1043 0931 CF       	.byte 207		# rorl $1 %edi 
+ 1044 0932 01E9     		addl	%ebp,		%ecx
+ 1045              		# 40_59 45 
+ 1046              		# 40_59 46 
+ 1047 0934 8B5C2438 		movl	56(%esp),	%ebx
+ 1048 0938 8B2C24   		movl	(%esp),		%ebp
+ 1049 093b 31EB     		xorl	%ebp,		%ebx
+ 1050 093d 8B6C2418 		movl	24(%esp),	%ebp
+ 1051 0941 31EB     		xorl	%ebp,		%ebx
+ 1052 0943 8B6C242C 		movl	44(%esp),	%ebp
+ 1053 0947 31EB     		xorl	%ebp,		%ebx
+ 1054 0949 89D5     		movl	%edx,		%ebp
+ 1055 094b D1       	.byte 209
+ 1056 094c C3       	.byte 195		# roll $1 %ebx 
+ 1057 094d 09FD     		orl	%edi,		%ebp
+ 1058 094f 895C2438 		movl	%ebx,		56(%esp)
+ 1059 0953 21F5     		andl	%esi,		%ebp
+ 1060 0955 8D9C03DC 		leal	2400959708(%ebx,%eax,1),%ebx
+ 1060      BC1B8F
+ 1061 095c 89D0     		movl	%edx,		%eax
+ 1062 095e D1       	.byte 209
+ 1063 095f CA       	.byte 202		# rorl $1 %edx 
+ 1064 0960 21F8     		andl	%edi,		%eax
+ 1065 0962 09C5     		orl	%eax,		%ebp
+ 1066 0964 89C8     		movl	%ecx,		%eax
+ 1067 0966 C1C005   		roll	$5,		%eax
+ 1068 0969 01C5     		addl	%eax,		%ebp
+ 1069 096b 8B44243C 		movl	60(%esp),	%eax
+ 1070 096f 01EB     		addl	%ebp,		%ebx
+ 1071 0971 8B6C2404 		movl	4(%esp),	%ebp
+ 1072 0975 31E8     		xorl	%ebp,		%eax
+ 1073 0977 8B6C241C 		movl	28(%esp),	%ebp
+ 1074 097b 31E8     		xorl	%ebp,		%eax
+ 1075 097d 8B6C2430 		movl	48(%esp),	%ebp
+ 1076 0981 D1       	.byte 209
+ 1077 0982 CA       	.byte 202		# rorl $1 %edx 
+ 1078 0983 31E8     		xorl	%ebp,		%eax
+ 1079 0985 D1       	.byte 209
+ 1080 0986 C0       	.byte 192		# roll $1 %eax 
+ 1081 0987 89CD     		movl	%ecx,		%ebp
+ 1082 0989 8944243C 		movl	%eax,		60(%esp)
+ 1083 098d 09D5     		orl	%edx,		%ebp
+ 1084 098f 8D8430DC 		leal	2400959708(%eax,%esi,1),%eax
+ 1084      BC1B8F
+ 1085 0996 89CE     		movl	%ecx,		%esi
+ 1086 0998 21FD     		andl	%edi,		%ebp
+ 1087 099a 21D6     		andl	%edx,		%esi
+ 1088 099c 09F5     		orl	%esi,		%ebp
+ 1089 099e 89DE     		movl	%ebx,		%esi
+ 1090 09a0 C1C605   		roll	$5,		%esi
+ 1091 09a3 D1       	.byte 209
+ 1092 09a4 C9       	.byte 201		# rorl $1 %ecx 
+GAS LISTING f.s 			page 21
+
+
+ 1093 09a5 01F5     		addl	%esi,		%ebp
+ 1094 09a7 D1       	.byte 209
+ 1095 09a8 C9       	.byte 201		# rorl $1 %ecx 
+ 1096 09a9 01E8     		addl	%ebp,		%eax
+ 1097              		# 40_59 47 
+ 1098              		# 40_59 48 
+ 1099 09ab 8B3424   		movl	(%esp),		%esi
+ 1100 09ae 8B6C2408 		movl	8(%esp),	%ebp
+ 1101 09b2 31EE     		xorl	%ebp,		%esi
+ 1102 09b4 8B6C2420 		movl	32(%esp),	%ebp
+ 1103 09b8 31EE     		xorl	%ebp,		%esi
+ 1104 09ba 8B6C2434 		movl	52(%esp),	%ebp
+ 1105 09be 31EE     		xorl	%ebp,		%esi
+ 1106 09c0 89DD     		movl	%ebx,		%ebp
+ 1107 09c2 D1       	.byte 209
+ 1108 09c3 C6       	.byte 198		# roll $1 %esi 
+ 1109 09c4 09CD     		orl	%ecx,		%ebp
+ 1110 09c6 893424   		movl	%esi,		(%esp)
+ 1111 09c9 21D5     		andl	%edx,		%ebp
+ 1112 09cb 8DB43EDC 		leal	2400959708(%esi,%edi,1),%esi
+ 1112      BC1B8F
+ 1113 09d2 89DF     		movl	%ebx,		%edi
+ 1114 09d4 D1       	.byte 209
+ 1115 09d5 CB       	.byte 203		# rorl $1 %ebx 
+ 1116 09d6 21CF     		andl	%ecx,		%edi
+ 1117 09d8 09FD     		orl	%edi,		%ebp
+ 1118 09da 89C7     		movl	%eax,		%edi
+ 1119 09dc C1C705   		roll	$5,		%edi
+ 1120 09df 01FD     		addl	%edi,		%ebp
+ 1121 09e1 8B7C2404 		movl	4(%esp),	%edi
+ 1122 09e5 01EE     		addl	%ebp,		%esi
+ 1123 09e7 8B6C240C 		movl	12(%esp),	%ebp
+ 1124 09eb 31EF     		xorl	%ebp,		%edi
+ 1125 09ed 8B6C2424 		movl	36(%esp),	%ebp
+ 1126 09f1 31EF     		xorl	%ebp,		%edi
+ 1127 09f3 8B6C2438 		movl	56(%esp),	%ebp
+ 1128 09f7 D1       	.byte 209
+ 1129 09f8 CB       	.byte 203		# rorl $1 %ebx 
+ 1130 09f9 31EF     		xorl	%ebp,		%edi
+ 1131 09fb D1       	.byte 209
+ 1132 09fc C7       	.byte 199		# roll $1 %edi 
+ 1133 09fd 89C5     		movl	%eax,		%ebp
+ 1134 09ff 897C2404 		movl	%edi,		4(%esp)
+ 1135 0a03 09DD     		orl	%ebx,		%ebp
+ 1136 0a05 8DBC17DC 		leal	2400959708(%edi,%edx,1),%edi
+ 1136      BC1B8F
+ 1137 0a0c 89C2     		movl	%eax,		%edx
+ 1138 0a0e 21CD     		andl	%ecx,		%ebp
+ 1139 0a10 21DA     		andl	%ebx,		%edx
+ 1140 0a12 09D5     		orl	%edx,		%ebp
+ 1141 0a14 89F2     		movl	%esi,		%edx
+ 1142 0a16 C1C205   		roll	$5,		%edx
+ 1143 0a19 D1       	.byte 209
+ 1144 0a1a C8       	.byte 200		# rorl $1 %eax 
+ 1145 0a1b 01D5     		addl	%edx,		%ebp
+ 1146 0a1d D1       	.byte 209
+ 1147 0a1e C8       	.byte 200		# rorl $1 %eax 
+GAS LISTING f.s 			page 22
+
+
+ 1148 0a1f 01EF     		addl	%ebp,		%edi
+ 1149              		# 40_59 49 
+ 1150              		# 40_59 50 
+ 1151 0a21 8B542408 		movl	8(%esp),	%edx
+ 1152 0a25 8B6C2410 		movl	16(%esp),	%ebp
+ 1153 0a29 31EA     		xorl	%ebp,		%edx
+ 1154 0a2b 8B6C2428 		movl	40(%esp),	%ebp
+ 1155 0a2f 31EA     		xorl	%ebp,		%edx
+ 1156 0a31 8B6C243C 		movl	60(%esp),	%ebp
+ 1157 0a35 31EA     		xorl	%ebp,		%edx
+ 1158 0a37 89F5     		movl	%esi,		%ebp
+ 1159 0a39 D1       	.byte 209
+ 1160 0a3a C2       	.byte 194		# roll $1 %edx 
+ 1161 0a3b 09C5     		orl	%eax,		%ebp
+ 1162 0a3d 89542408 		movl	%edx,		8(%esp)
+ 1163 0a41 21DD     		andl	%ebx,		%ebp
+ 1164 0a43 8D940ADC 		leal	2400959708(%edx,%ecx,1),%edx
+ 1164      BC1B8F
+ 1165 0a4a 89F1     		movl	%esi,		%ecx
+ 1166 0a4c D1       	.byte 209
+ 1167 0a4d CE       	.byte 206		# rorl $1 %esi 
+ 1168 0a4e 21C1     		andl	%eax,		%ecx
+ 1169 0a50 09CD     		orl	%ecx,		%ebp
+ 1170 0a52 89F9     		movl	%edi,		%ecx
+ 1171 0a54 C1C105   		roll	$5,		%ecx
+ 1172 0a57 01CD     		addl	%ecx,		%ebp
+ 1173 0a59 8B4C240C 		movl	12(%esp),	%ecx
+ 1174 0a5d 01EA     		addl	%ebp,		%edx
+ 1175 0a5f 8B6C2414 		movl	20(%esp),	%ebp
+ 1176 0a63 31E9     		xorl	%ebp,		%ecx
+ 1177 0a65 8B6C242C 		movl	44(%esp),	%ebp
+ 1178 0a69 31E9     		xorl	%ebp,		%ecx
+ 1179 0a6b 8B2C24   		movl	(%esp),		%ebp
+ 1180 0a6e D1       	.byte 209
+ 1181 0a6f CE       	.byte 206		# rorl $1 %esi 
+ 1182 0a70 31E9     		xorl	%ebp,		%ecx
+ 1183 0a72 D1       	.byte 209
+ 1184 0a73 C1       	.byte 193		# roll $1 %ecx 
+ 1185 0a74 89FD     		movl	%edi,		%ebp
+ 1186 0a76 894C240C 		movl	%ecx,		12(%esp)
+ 1187 0a7a 09F5     		orl	%esi,		%ebp
+ 1188 0a7c 8D8C19DC 		leal	2400959708(%ecx,%ebx,1),%ecx
+ 1188      BC1B8F
+ 1189 0a83 89FB     		movl	%edi,		%ebx
+ 1190 0a85 21C5     		andl	%eax,		%ebp
+ 1191 0a87 21F3     		andl	%esi,		%ebx
+ 1192 0a89 09DD     		orl	%ebx,		%ebp
+ 1193 0a8b 89D3     		movl	%edx,		%ebx
+ 1194 0a8d C1C305   		roll	$5,		%ebx
+ 1195 0a90 D1       	.byte 209
+ 1196 0a91 CF       	.byte 207		# rorl $1 %edi 
+ 1197 0a92 01DD     		addl	%ebx,		%ebp
+ 1198 0a94 D1       	.byte 209
+ 1199 0a95 CF       	.byte 207		# rorl $1 %edi 
+ 1200 0a96 01E9     		addl	%ebp,		%ecx
+ 1201              		# 40_59 51 
+ 1202              		# 40_59 52 
+GAS LISTING f.s 			page 23
+
+
+ 1203 0a98 8B5C2410 		movl	16(%esp),	%ebx
+ 1204 0a9c 8B6C2418 		movl	24(%esp),	%ebp
+ 1205 0aa0 31EB     		xorl	%ebp,		%ebx
+ 1206 0aa2 8B6C2430 		movl	48(%esp),	%ebp
+ 1207 0aa6 31EB     		xorl	%ebp,		%ebx
+ 1208 0aa8 8B6C2404 		movl	4(%esp),	%ebp
+ 1209 0aac 31EB     		xorl	%ebp,		%ebx
+ 1210 0aae 89D5     		movl	%edx,		%ebp
+ 1211 0ab0 D1       	.byte 209
+ 1212 0ab1 C3       	.byte 195		# roll $1 %ebx 
+ 1213 0ab2 09FD     		orl	%edi,		%ebp
+ 1214 0ab4 895C2410 		movl	%ebx,		16(%esp)
+ 1215 0ab8 21F5     		andl	%esi,		%ebp
+ 1216 0aba 8D9C03DC 		leal	2400959708(%ebx,%eax,1),%ebx
+ 1216      BC1B8F
+ 1217 0ac1 89D0     		movl	%edx,		%eax
+ 1218 0ac3 D1       	.byte 209
+ 1219 0ac4 CA       	.byte 202		# rorl $1 %edx 
+ 1220 0ac5 21F8     		andl	%edi,		%eax
+ 1221 0ac7 09C5     		orl	%eax,		%ebp
+ 1222 0ac9 89C8     		movl	%ecx,		%eax
+ 1223 0acb C1C005   		roll	$5,		%eax
+ 1224 0ace 01C5     		addl	%eax,		%ebp
+ 1225 0ad0 8B442414 		movl	20(%esp),	%eax
+ 1226 0ad4 01EB     		addl	%ebp,		%ebx
+ 1227 0ad6 8B6C241C 		movl	28(%esp),	%ebp
+ 1228 0ada 31E8     		xorl	%ebp,		%eax
+ 1229 0adc 8B6C2434 		movl	52(%esp),	%ebp
+ 1230 0ae0 31E8     		xorl	%ebp,		%eax
+ 1231 0ae2 8B6C2408 		movl	8(%esp),	%ebp
+ 1232 0ae6 D1       	.byte 209
+ 1233 0ae7 CA       	.byte 202		# rorl $1 %edx 
+ 1234 0ae8 31E8     		xorl	%ebp,		%eax
+ 1235 0aea D1       	.byte 209
+ 1236 0aeb C0       	.byte 192		# roll $1 %eax 
+ 1237 0aec 89CD     		movl	%ecx,		%ebp
+ 1238 0aee 89442414 		movl	%eax,		20(%esp)
+ 1239 0af2 09D5     		orl	%edx,		%ebp
+ 1240 0af4 8D8430DC 		leal	2400959708(%eax,%esi,1),%eax
+ 1240      BC1B8F
+ 1241 0afb 89CE     		movl	%ecx,		%esi
+ 1242 0afd 21FD     		andl	%edi,		%ebp
+ 1243 0aff 21D6     		andl	%edx,		%esi
+ 1244 0b01 09F5     		orl	%esi,		%ebp
+ 1245 0b03 89DE     		movl	%ebx,		%esi
+ 1246 0b05 C1C605   		roll	$5,		%esi
+ 1247 0b08 D1       	.byte 209
+ 1248 0b09 C9       	.byte 201		# rorl $1 %ecx 
+ 1249 0b0a 01F5     		addl	%esi,		%ebp
+ 1250 0b0c D1       	.byte 209
+ 1251 0b0d C9       	.byte 201		# rorl $1 %ecx 
+ 1252 0b0e 01E8     		addl	%ebp,		%eax
+ 1253              		# 40_59 53 
+ 1254              		# 40_59 54 
+ 1255 0b10 8B742418 		movl	24(%esp),	%esi
+ 1256 0b14 8B6C2420 		movl	32(%esp),	%ebp
+ 1257 0b18 31EE     		xorl	%ebp,		%esi
+GAS LISTING f.s 			page 24
+
+
+ 1258 0b1a 8B6C2438 		movl	56(%esp),	%ebp
+ 1259 0b1e 31EE     		xorl	%ebp,		%esi
+ 1260 0b20 8B6C240C 		movl	12(%esp),	%ebp
+ 1261 0b24 31EE     		xorl	%ebp,		%esi
+ 1262 0b26 89DD     		movl	%ebx,		%ebp
+ 1263 0b28 D1       	.byte 209
+ 1264 0b29 C6       	.byte 198		# roll $1 %esi 
+ 1265 0b2a 09CD     		orl	%ecx,		%ebp
+ 1266 0b2c 89742418 		movl	%esi,		24(%esp)
+ 1267 0b30 21D5     		andl	%edx,		%ebp
+ 1268 0b32 8DB43EDC 		leal	2400959708(%esi,%edi,1),%esi
+ 1268      BC1B8F
+ 1269 0b39 89DF     		movl	%ebx,		%edi
+ 1270 0b3b D1       	.byte 209
+ 1271 0b3c CB       	.byte 203		# rorl $1 %ebx 
+ 1272 0b3d 21CF     		andl	%ecx,		%edi
+ 1273 0b3f 09FD     		orl	%edi,		%ebp
+ 1274 0b41 89C7     		movl	%eax,		%edi
+ 1275 0b43 C1C705   		roll	$5,		%edi
+ 1276 0b46 01FD     		addl	%edi,		%ebp
+ 1277 0b48 8B7C241C 		movl	28(%esp),	%edi
+ 1278 0b4c 01EE     		addl	%ebp,		%esi
+ 1279 0b4e 8B6C2424 		movl	36(%esp),	%ebp
+ 1280 0b52 31EF     		xorl	%ebp,		%edi
+ 1281 0b54 8B6C243C 		movl	60(%esp),	%ebp
+ 1282 0b58 31EF     		xorl	%ebp,		%edi
+ 1283 0b5a 8B6C2410 		movl	16(%esp),	%ebp
+ 1284 0b5e D1       	.byte 209
+ 1285 0b5f CB       	.byte 203		# rorl $1 %ebx 
+ 1286 0b60 31EF     		xorl	%ebp,		%edi
+ 1287 0b62 D1       	.byte 209
+ 1288 0b63 C7       	.byte 199		# roll $1 %edi 
+ 1289 0b64 89C5     		movl	%eax,		%ebp
+ 1290 0b66 897C241C 		movl	%edi,		28(%esp)
+ 1291 0b6a 09DD     		orl	%ebx,		%ebp
+ 1292 0b6c 8DBC17DC 		leal	2400959708(%edi,%edx,1),%edi
+ 1292      BC1B8F
+ 1293 0b73 89C2     		movl	%eax,		%edx
+ 1294 0b75 21CD     		andl	%ecx,		%ebp
+ 1295 0b77 21DA     		andl	%ebx,		%edx
+ 1296 0b79 09D5     		orl	%edx,		%ebp
+ 1297 0b7b 89F2     		movl	%esi,		%edx
+ 1298 0b7d C1C205   		roll	$5,		%edx
+ 1299 0b80 D1       	.byte 209
+ 1300 0b81 C8       	.byte 200		# rorl $1 %eax 
+ 1301 0b82 01D5     		addl	%edx,		%ebp
+ 1302 0b84 D1       	.byte 209
+ 1303 0b85 C8       	.byte 200		# rorl $1 %eax 
+ 1304 0b86 01EF     		addl	%ebp,		%edi
+ 1305              		# 40_59 55 
+ 1306              		# 40_59 56 
+ 1307 0b88 8B542420 		movl	32(%esp),	%edx
+ 1308 0b8c 8B6C2428 		movl	40(%esp),	%ebp
+ 1309 0b90 31EA     		xorl	%ebp,		%edx
+ 1310 0b92 8B2C24   		movl	(%esp),		%ebp
+ 1311 0b95 31EA     		xorl	%ebp,		%edx
+ 1312 0b97 8B6C2414 		movl	20(%esp),	%ebp
+GAS LISTING f.s 			page 25
+
+
+ 1313 0b9b 31EA     		xorl	%ebp,		%edx
+ 1314 0b9d 89F5     		movl	%esi,		%ebp
+ 1315 0b9f D1       	.byte 209
+ 1316 0ba0 C2       	.byte 194		# roll $1 %edx 
+ 1317 0ba1 09C5     		orl	%eax,		%ebp
+ 1318 0ba3 89542420 		movl	%edx,		32(%esp)
+ 1319 0ba7 21DD     		andl	%ebx,		%ebp
+ 1320 0ba9 8D940ADC 		leal	2400959708(%edx,%ecx,1),%edx
+ 1320      BC1B8F
+ 1321 0bb0 89F1     		movl	%esi,		%ecx
+ 1322 0bb2 D1       	.byte 209
+ 1323 0bb3 CE       	.byte 206		# rorl $1 %esi 
+ 1324 0bb4 21C1     		andl	%eax,		%ecx
+ 1325 0bb6 09CD     		orl	%ecx,		%ebp
+ 1326 0bb8 89F9     		movl	%edi,		%ecx
+ 1327 0bba C1C105   		roll	$5,		%ecx
+ 1328 0bbd 01CD     		addl	%ecx,		%ebp
+ 1329 0bbf 8B4C2424 		movl	36(%esp),	%ecx
+ 1330 0bc3 01EA     		addl	%ebp,		%edx
+ 1331 0bc5 8B6C242C 		movl	44(%esp),	%ebp
+ 1332 0bc9 31E9     		xorl	%ebp,		%ecx
+ 1333 0bcb 8B6C2404 		movl	4(%esp),	%ebp
+ 1334 0bcf 31E9     		xorl	%ebp,		%ecx
+ 1335 0bd1 8B6C2418 		movl	24(%esp),	%ebp
+ 1336 0bd5 D1       	.byte 209
+ 1337 0bd6 CE       	.byte 206		# rorl $1 %esi 
+ 1338 0bd7 31E9     		xorl	%ebp,		%ecx
+ 1339 0bd9 D1       	.byte 209
+ 1340 0bda C1       	.byte 193		# roll $1 %ecx 
+ 1341 0bdb 89FD     		movl	%edi,		%ebp
+ 1342 0bdd 894C2424 		movl	%ecx,		36(%esp)
+ 1343 0be1 09F5     		orl	%esi,		%ebp
+ 1344 0be3 8D8C19DC 		leal	2400959708(%ecx,%ebx,1),%ecx
+ 1344      BC1B8F
+ 1345 0bea 89FB     		movl	%edi,		%ebx
+ 1346 0bec 21C5     		andl	%eax,		%ebp
+ 1347 0bee 21F3     		andl	%esi,		%ebx
+ 1348 0bf0 09DD     		orl	%ebx,		%ebp
+ 1349 0bf2 89D3     		movl	%edx,		%ebx
+ 1350 0bf4 C1C305   		roll	$5,		%ebx
+ 1351 0bf7 D1       	.byte 209
+ 1352 0bf8 CF       	.byte 207		# rorl $1 %edi 
+ 1353 0bf9 01DD     		addl	%ebx,		%ebp
+ 1354 0bfb D1       	.byte 209
+ 1355 0bfc CF       	.byte 207		# rorl $1 %edi 
+ 1356 0bfd 01E9     		addl	%ebp,		%ecx
+ 1357              		# 40_59 57 
+ 1358              		# 40_59 58 
+ 1359 0bff 8B5C2428 		movl	40(%esp),	%ebx
+ 1360 0c03 8B6C2430 		movl	48(%esp),	%ebp
+ 1361 0c07 31EB     		xorl	%ebp,		%ebx
+ 1362 0c09 8B6C2408 		movl	8(%esp),	%ebp
+ 1363 0c0d 31EB     		xorl	%ebp,		%ebx
+ 1364 0c0f 8B6C241C 		movl	28(%esp),	%ebp
+ 1365 0c13 31EB     		xorl	%ebp,		%ebx
+ 1366 0c15 89D5     		movl	%edx,		%ebp
+ 1367 0c17 D1       	.byte 209
+GAS LISTING f.s 			page 26
+
+
+ 1368 0c18 C3       	.byte 195		# roll $1 %ebx 
+ 1369 0c19 09FD     		orl	%edi,		%ebp
+ 1370 0c1b 895C2428 		movl	%ebx,		40(%esp)
+ 1371 0c1f 21F5     		andl	%esi,		%ebp
+ 1372 0c21 8D9C03DC 		leal	2400959708(%ebx,%eax,1),%ebx
+ 1372      BC1B8F
+ 1373 0c28 89D0     		movl	%edx,		%eax
+ 1374 0c2a D1       	.byte 209
+ 1375 0c2b CA       	.byte 202		# rorl $1 %edx 
+ 1376 0c2c 21F8     		andl	%edi,		%eax
+ 1377 0c2e 09C5     		orl	%eax,		%ebp
+ 1378 0c30 89C8     		movl	%ecx,		%eax
+ 1379 0c32 C1C005   		roll	$5,		%eax
+ 1380 0c35 01C5     		addl	%eax,		%ebp
+ 1381 0c37 8B44242C 		movl	44(%esp),	%eax
+ 1382 0c3b 01EB     		addl	%ebp,		%ebx
+ 1383 0c3d 8B6C2434 		movl	52(%esp),	%ebp
+ 1384 0c41 31E8     		xorl	%ebp,		%eax
+ 1385 0c43 8B6C240C 		movl	12(%esp),	%ebp
+ 1386 0c47 31E8     		xorl	%ebp,		%eax
+ 1387 0c49 8B6C2420 		movl	32(%esp),	%ebp
+ 1388 0c4d D1       	.byte 209
+ 1389 0c4e CA       	.byte 202		# rorl $1 %edx 
+ 1390 0c4f 31E8     		xorl	%ebp,		%eax
+ 1391 0c51 D1       	.byte 209
+ 1392 0c52 C0       	.byte 192		# roll $1 %eax 
+ 1393 0c53 89CD     		movl	%ecx,		%ebp
+ 1394 0c55 8944242C 		movl	%eax,		44(%esp)
+ 1395 0c59 09D5     		orl	%edx,		%ebp
+ 1396 0c5b 8D8430DC 		leal	2400959708(%eax,%esi,1),%eax
+ 1396      BC1B8F
+ 1397 0c62 89CE     		movl	%ecx,		%esi
+ 1398 0c64 21FD     		andl	%edi,		%ebp
+ 1399 0c66 21D6     		andl	%edx,		%esi
+ 1400 0c68 09F5     		orl	%esi,		%ebp
+ 1401 0c6a 89DE     		movl	%ebx,		%esi
+ 1402 0c6c C1C605   		roll	$5,		%esi
+ 1403 0c6f D1       	.byte 209
+ 1404 0c70 C9       	.byte 201		# rorl $1 %ecx 
+ 1405 0c71 01F5     		addl	%esi,		%ebp
+ 1406 0c73 D1       	.byte 209
+ 1407 0c74 C9       	.byte 201		# rorl $1 %ecx 
+ 1408 0c75 01E8     		addl	%ebp,		%eax
+ 1409              		# 40_59 59 
+ 1410              		# 20_39 60 
+ 1411 0c77 8B742430 		movl	48(%esp),	%esi
+ 1412 0c7b 8B6C2438 		movl	56(%esp),	%ebp
+ 1413 0c7f 31EE     		xorl	%ebp,		%esi
+ 1414 0c81 8B6C2410 		movl	16(%esp),	%ebp
+ 1415 0c85 31EE     		xorl	%ebp,		%esi
+ 1416 0c87 8B6C2424 		movl	36(%esp),	%ebp
+ 1417 0c8b 31EE     		xorl	%ebp,		%esi
+ 1418 0c8d 89DD     		movl	%ebx,		%ebp
+ 1419 0c8f D1       	.byte 209
+ 1420 0c90 C6       	.byte 198		# roll $1 %esi 
+ 1421 0c91 31CD     		xorl	%ecx,		%ebp
+ 1422 0c93 89742430 		movl	%esi,		48(%esp)
+GAS LISTING f.s 			page 27
+
+
+ 1423 0c97 31D5     		xorl	%edx,		%ebp
+ 1424 0c99 8DB43ED6 		leal	3395469782(%esi,%edi,1),%esi
+ 1424      C162CA
+ 1425 0ca0 89C7     		movl	%eax,		%edi
+ 1426 0ca2 C1C705   		roll	$5,		%edi
+ 1427 0ca5 D1       	.byte 209
+ 1428 0ca6 CB       	.byte 203		# rorl $1 %ebx 
+ 1429 0ca7 01EF     		addl	%ebp,		%edi
+ 1430 0ca9 D1       	.byte 209
+ 1431 0caa CB       	.byte 203		# rorl $1 %ebx 
+ 1432 0cab 01FE     		addl	%edi,		%esi
+ 1433              		# 20_39 61 
+ 1434 0cad 8B7C2434 		movl	52(%esp),	%edi
+ 1435 0cb1 8B6C243C 		movl	60(%esp),	%ebp
+ 1436 0cb5 31EF     		xorl	%ebp,		%edi
+ 1437 0cb7 8B6C2414 		movl	20(%esp),	%ebp
+ 1438 0cbb 31EF     		xorl	%ebp,		%edi
+ 1439 0cbd 8B6C2428 		movl	40(%esp),	%ebp
+ 1440 0cc1 31EF     		xorl	%ebp,		%edi
+ 1441 0cc3 89C5     		movl	%eax,		%ebp
+ 1442 0cc5 D1       	.byte 209
+ 1443 0cc6 C7       	.byte 199		# roll $1 %edi 
+ 1444 0cc7 31DD     		xorl	%ebx,		%ebp
+ 1445 0cc9 897C2434 		movl	%edi,		52(%esp)
+ 1446 0ccd 31CD     		xorl	%ecx,		%ebp
+ 1447 0ccf 8DBC17D6 		leal	3395469782(%edi,%edx,1),%edi
+ 1447      C162CA
+ 1448 0cd6 89F2     		movl	%esi,		%edx
+ 1449 0cd8 C1C205   		roll	$5,		%edx
+ 1450 0cdb D1       	.byte 209
+ 1451 0cdc C8       	.byte 200		# rorl $1 %eax 
+ 1452 0cdd 01EA     		addl	%ebp,		%edx
+ 1453 0cdf D1       	.byte 209
+ 1454 0ce0 C8       	.byte 200		# rorl $1 %eax 
+ 1455 0ce1 01D7     		addl	%edx,		%edi
+ 1456              		# 20_39 62 
+ 1457 0ce3 8B542438 		movl	56(%esp),	%edx
+ 1458 0ce7 8B2C24   		movl	(%esp),		%ebp
+ 1459 0cea 31EA     		xorl	%ebp,		%edx
+ 1460 0cec 8B6C2418 		movl	24(%esp),	%ebp
+ 1461 0cf0 31EA     		xorl	%ebp,		%edx
+ 1462 0cf2 8B6C242C 		movl	44(%esp),	%ebp
+ 1463 0cf6 31EA     		xorl	%ebp,		%edx
+ 1464 0cf8 89F5     		movl	%esi,		%ebp
+ 1465 0cfa D1       	.byte 209
+ 1466 0cfb C2       	.byte 194		# roll $1 %edx 
+ 1467 0cfc 31C5     		xorl	%eax,		%ebp
+ 1468 0cfe 89542438 		movl	%edx,		56(%esp)
+ 1469 0d02 31DD     		xorl	%ebx,		%ebp
+ 1470 0d04 8D940AD6 		leal	3395469782(%edx,%ecx,1),%edx
+ 1470      C162CA
+ 1471 0d0b 89F9     		movl	%edi,		%ecx
+ 1472 0d0d C1C105   		roll	$5,		%ecx
+ 1473 0d10 D1       	.byte 209
+ 1474 0d11 CE       	.byte 206		# rorl $1 %esi 
+ 1475 0d12 01E9     		addl	%ebp,		%ecx
+ 1476 0d14 D1       	.byte 209
+GAS LISTING f.s 			page 28
+
+
+ 1477 0d15 CE       	.byte 206		# rorl $1 %esi 
+ 1478 0d16 01CA     		addl	%ecx,		%edx
+ 1479              		# 20_39 63 
+ 1480 0d18 8B4C243C 		movl	60(%esp),	%ecx
+ 1481 0d1c 8B6C2404 		movl	4(%esp),	%ebp
+ 1482 0d20 31E9     		xorl	%ebp,		%ecx
+ 1483 0d22 8B6C241C 		movl	28(%esp),	%ebp
+ 1484 0d26 31E9     		xorl	%ebp,		%ecx
+ 1485 0d28 8B6C2430 		movl	48(%esp),	%ebp
+ 1486 0d2c 31E9     		xorl	%ebp,		%ecx
+ 1487 0d2e 89FD     		movl	%edi,		%ebp
+ 1488 0d30 D1       	.byte 209
+ 1489 0d31 C1       	.byte 193		# roll $1 %ecx 
+ 1490 0d32 31F5     		xorl	%esi,		%ebp
+ 1491 0d34 894C243C 		movl	%ecx,		60(%esp)
+ 1492 0d38 31C5     		xorl	%eax,		%ebp
+ 1493 0d3a 8D8C19D6 		leal	3395469782(%ecx,%ebx,1),%ecx
+ 1493      C162CA
+ 1494 0d41 89D3     		movl	%edx,		%ebx
+ 1495 0d43 C1C305   		roll	$5,		%ebx
+ 1496 0d46 D1       	.byte 209
+ 1497 0d47 CF       	.byte 207		# rorl $1 %edi 
+ 1498 0d48 01EB     		addl	%ebp,		%ebx
+ 1499 0d4a D1       	.byte 209
+ 1500 0d4b CF       	.byte 207		# rorl $1 %edi 
+ 1501 0d4c 01D9     		addl	%ebx,		%ecx
+ 1502              		# 20_39 64 
+ 1503 0d4e 8B1C24   		movl	(%esp),		%ebx
+ 1504 0d51 8B6C2408 		movl	8(%esp),	%ebp
+ 1505 0d55 31EB     		xorl	%ebp,		%ebx
+ 1506 0d57 8B6C2420 		movl	32(%esp),	%ebp
+ 1507 0d5b 31EB     		xorl	%ebp,		%ebx
+ 1508 0d5d 8B6C2434 		movl	52(%esp),	%ebp
+ 1509 0d61 31EB     		xorl	%ebp,		%ebx
+ 1510 0d63 89D5     		movl	%edx,		%ebp
+ 1511 0d65 D1       	.byte 209
+ 1512 0d66 C3       	.byte 195		# roll $1 %ebx 
+ 1513 0d67 31FD     		xorl	%edi,		%ebp
+ 1514 0d69 891C24   		movl	%ebx,		(%esp)
+ 1515 0d6c 31F5     		xorl	%esi,		%ebp
+ 1516 0d6e 8D9C03D6 		leal	3395469782(%ebx,%eax,1),%ebx
+ 1516      C162CA
+ 1517 0d75 89C8     		movl	%ecx,		%eax
+ 1518 0d77 C1C005   		roll	$5,		%eax
+ 1519 0d7a D1       	.byte 209
+ 1520 0d7b CA       	.byte 202		# rorl $1 %edx 
+ 1521 0d7c 01E8     		addl	%ebp,		%eax
+ 1522 0d7e D1       	.byte 209
+ 1523 0d7f CA       	.byte 202		# rorl $1 %edx 
+ 1524 0d80 01C3     		addl	%eax,		%ebx
+ 1525              		# 20_39 65 
+ 1526 0d82 8B442404 		movl	4(%esp),	%eax
+ 1527 0d86 8B6C240C 		movl	12(%esp),	%ebp
+ 1528 0d8a 31E8     		xorl	%ebp,		%eax
+ 1529 0d8c 8B6C2424 		movl	36(%esp),	%ebp
+ 1530 0d90 31E8     		xorl	%ebp,		%eax
+ 1531 0d92 8B6C2438 		movl	56(%esp),	%ebp
+GAS LISTING f.s 			page 29
+
+
+ 1532 0d96 31E8     		xorl	%ebp,		%eax
+ 1533 0d98 89CD     		movl	%ecx,		%ebp
+ 1534 0d9a D1       	.byte 209
+ 1535 0d9b C0       	.byte 192		# roll $1 %eax 
+ 1536 0d9c 31D5     		xorl	%edx,		%ebp
+ 1537 0d9e 89442404 		movl	%eax,		4(%esp)
+ 1538 0da2 31FD     		xorl	%edi,		%ebp
+ 1539 0da4 8D8430D6 		leal	3395469782(%eax,%esi,1),%eax
+ 1539      C162CA
+ 1540 0dab 89DE     		movl	%ebx,		%esi
+ 1541 0dad C1C605   		roll	$5,		%esi
+ 1542 0db0 D1       	.byte 209
+ 1543 0db1 C9       	.byte 201		# rorl $1 %ecx 
+ 1544 0db2 01EE     		addl	%ebp,		%esi
+ 1545 0db4 D1       	.byte 209
+ 1546 0db5 C9       	.byte 201		# rorl $1 %ecx 
+ 1547 0db6 01F0     		addl	%esi,		%eax
+ 1548              		# 20_39 66 
+ 1549 0db8 8B742408 		movl	8(%esp),	%esi
+ 1550 0dbc 8B6C2410 		movl	16(%esp),	%ebp
+ 1551 0dc0 31EE     		xorl	%ebp,		%esi
+ 1552 0dc2 8B6C2428 		movl	40(%esp),	%ebp
+ 1553 0dc6 31EE     		xorl	%ebp,		%esi
+ 1554 0dc8 8B6C243C 		movl	60(%esp),	%ebp
+ 1555 0dcc 31EE     		xorl	%ebp,		%esi
+ 1556 0dce 89DD     		movl	%ebx,		%ebp
+ 1557 0dd0 D1       	.byte 209
+ 1558 0dd1 C6       	.byte 198		# roll $1 %esi 
+ 1559 0dd2 31CD     		xorl	%ecx,		%ebp
+ 1560 0dd4 89742408 		movl	%esi,		8(%esp)
+ 1561 0dd8 31D5     		xorl	%edx,		%ebp
+ 1562 0dda 8DB43ED6 		leal	3395469782(%esi,%edi,1),%esi
+ 1562      C162CA
+ 1563 0de1 89C7     		movl	%eax,		%edi
+ 1564 0de3 C1C705   		roll	$5,		%edi
+ 1565 0de6 D1       	.byte 209
+ 1566 0de7 CB       	.byte 203		# rorl $1 %ebx 
+ 1567 0de8 01EF     		addl	%ebp,		%edi
+ 1568 0dea D1       	.byte 209
+ 1569 0deb CB       	.byte 203		# rorl $1 %ebx 
+ 1570 0dec 01FE     		addl	%edi,		%esi
+ 1571              		# 20_39 67 
+ 1572 0dee 8B7C240C 		movl	12(%esp),	%edi
+ 1573 0df2 8B6C2414 		movl	20(%esp),	%ebp
+ 1574 0df6 31EF     		xorl	%ebp,		%edi
+ 1575 0df8 8B6C242C 		movl	44(%esp),	%ebp
+ 1576 0dfc 31EF     		xorl	%ebp,		%edi
+ 1577 0dfe 8B2C24   		movl	(%esp),		%ebp
+ 1578 0e01 31EF     		xorl	%ebp,		%edi
+ 1579 0e03 89C5     		movl	%eax,		%ebp
+ 1580 0e05 D1       	.byte 209
+ 1581 0e06 C7       	.byte 199		# roll $1 %edi 
+ 1582 0e07 31DD     		xorl	%ebx,		%ebp
+ 1583 0e09 897C240C 		movl	%edi,		12(%esp)
+ 1584 0e0d 31CD     		xorl	%ecx,		%ebp
+ 1585 0e0f 8DBC17D6 		leal	3395469782(%edi,%edx,1),%edi
+ 1585      C162CA
+GAS LISTING f.s 			page 30
+
+
+ 1586 0e16 89F2     		movl	%esi,		%edx
+ 1587 0e18 C1C205   		roll	$5,		%edx
+ 1588 0e1b D1       	.byte 209
+ 1589 0e1c C8       	.byte 200		# rorl $1 %eax 
+ 1590 0e1d 01EA     		addl	%ebp,		%edx
+ 1591 0e1f D1       	.byte 209
+ 1592 0e20 C8       	.byte 200		# rorl $1 %eax 
+ 1593 0e21 01D7     		addl	%edx,		%edi
+ 1594              		# 20_39 68 
+ 1595 0e23 8B542410 		movl	16(%esp),	%edx
+ 1596 0e27 8B6C2418 		movl	24(%esp),	%ebp
+ 1597 0e2b 31EA     		xorl	%ebp,		%edx
+ 1598 0e2d 8B6C2430 		movl	48(%esp),	%ebp
+ 1599 0e31 31EA     		xorl	%ebp,		%edx
+ 1600 0e33 8B6C2404 		movl	4(%esp),	%ebp
+ 1601 0e37 31EA     		xorl	%ebp,		%edx
+ 1602 0e39 89F5     		movl	%esi,		%ebp
+ 1603 0e3b D1       	.byte 209
+ 1604 0e3c C2       	.byte 194		# roll $1 %edx 
+ 1605 0e3d 31C5     		xorl	%eax,		%ebp
+ 1606 0e3f 89542410 		movl	%edx,		16(%esp)
+ 1607 0e43 31DD     		xorl	%ebx,		%ebp
+ 1608 0e45 8D940AD6 		leal	3395469782(%edx,%ecx,1),%edx
+ 1608      C162CA
+ 1609 0e4c 89F9     		movl	%edi,		%ecx
+ 1610 0e4e C1C105   		roll	$5,		%ecx
+ 1611 0e51 D1       	.byte 209
+ 1612 0e52 CE       	.byte 206		# rorl $1 %esi 
+ 1613 0e53 01E9     		addl	%ebp,		%ecx
+ 1614 0e55 D1       	.byte 209
+ 1615 0e56 CE       	.byte 206		# rorl $1 %esi 
+ 1616 0e57 01CA     		addl	%ecx,		%edx
+ 1617              		# 20_39 69 
+ 1618 0e59 8B4C2414 		movl	20(%esp),	%ecx
+ 1619 0e5d 8B6C241C 		movl	28(%esp),	%ebp
+ 1620 0e61 31E9     		xorl	%ebp,		%ecx
+ 1621 0e63 8B6C2434 		movl	52(%esp),	%ebp
+ 1622 0e67 31E9     		xorl	%ebp,		%ecx
+ 1623 0e69 8B6C2408 		movl	8(%esp),	%ebp
+ 1624 0e6d 31E9     		xorl	%ebp,		%ecx
+ 1625 0e6f 89FD     		movl	%edi,		%ebp
+ 1626 0e71 D1       	.byte 209
+ 1627 0e72 C1       	.byte 193		# roll $1 %ecx 
+ 1628 0e73 31F5     		xorl	%esi,		%ebp
+ 1629 0e75 894C2414 		movl	%ecx,		20(%esp)
+ 1630 0e79 31C5     		xorl	%eax,		%ebp
+ 1631 0e7b 8D8C19D6 		leal	3395469782(%ecx,%ebx,1),%ecx
+ 1631      C162CA
+ 1632 0e82 89D3     		movl	%edx,		%ebx
+ 1633 0e84 C1C305   		roll	$5,		%ebx
+ 1634 0e87 D1       	.byte 209
+ 1635 0e88 CF       	.byte 207		# rorl $1 %edi 
+ 1636 0e89 01EB     		addl	%ebp,		%ebx
+ 1637 0e8b D1       	.byte 209
+ 1638 0e8c CF       	.byte 207		# rorl $1 %edi 
+ 1639 0e8d 01D9     		addl	%ebx,		%ecx
+ 1640              		# 20_39 70 
+GAS LISTING f.s 			page 31
+
+
+ 1641 0e8f 8B5C2418 		movl	24(%esp),	%ebx
+ 1642 0e93 8B6C2420 		movl	32(%esp),	%ebp
+ 1643 0e97 31EB     		xorl	%ebp,		%ebx
+ 1644 0e99 8B6C2438 		movl	56(%esp),	%ebp
+ 1645 0e9d 31EB     		xorl	%ebp,		%ebx
+ 1646 0e9f 8B6C240C 		movl	12(%esp),	%ebp
+ 1647 0ea3 31EB     		xorl	%ebp,		%ebx
+ 1648 0ea5 89D5     		movl	%edx,		%ebp
+ 1649 0ea7 D1       	.byte 209
+ 1650 0ea8 C3       	.byte 195		# roll $1 %ebx 
+ 1651 0ea9 31FD     		xorl	%edi,		%ebp
+ 1652 0eab 895C2418 		movl	%ebx,		24(%esp)
+ 1653 0eaf 31F5     		xorl	%esi,		%ebp
+ 1654 0eb1 8D9C03D6 		leal	3395469782(%ebx,%eax,1),%ebx
+ 1654      C162CA
+ 1655 0eb8 89C8     		movl	%ecx,		%eax
+ 1656 0eba C1C005   		roll	$5,		%eax
+ 1657 0ebd D1       	.byte 209
+ 1658 0ebe CA       	.byte 202		# rorl $1 %edx 
+ 1659 0ebf 01E8     		addl	%ebp,		%eax
+ 1660 0ec1 D1       	.byte 209
+ 1661 0ec2 CA       	.byte 202		# rorl $1 %edx 
+ 1662 0ec3 01C3     		addl	%eax,		%ebx
+ 1663              		# 20_39 71 
+ 1664 0ec5 8B44241C 		movl	28(%esp),	%eax
+ 1665 0ec9 8B6C2424 		movl	36(%esp),	%ebp
+ 1666 0ecd 31E8     		xorl	%ebp,		%eax
+ 1667 0ecf 8B6C243C 		movl	60(%esp),	%ebp
+ 1668 0ed3 31E8     		xorl	%ebp,		%eax
+ 1669 0ed5 8B6C2410 		movl	16(%esp),	%ebp
+ 1670 0ed9 31E8     		xorl	%ebp,		%eax
+ 1671 0edb 89CD     		movl	%ecx,		%ebp
+ 1672 0edd D1       	.byte 209
+ 1673 0ede C0       	.byte 192		# roll $1 %eax 
+ 1674 0edf 31D5     		xorl	%edx,		%ebp
+ 1675 0ee1 8944241C 		movl	%eax,		28(%esp)
+ 1676 0ee5 31FD     		xorl	%edi,		%ebp
+ 1677 0ee7 8D8430D6 		leal	3395469782(%eax,%esi,1),%eax
+ 1677      C162CA
+ 1678 0eee 89DE     		movl	%ebx,		%esi
+ 1679 0ef0 C1C605   		roll	$5,		%esi
+ 1680 0ef3 D1       	.byte 209
+ 1681 0ef4 C9       	.byte 201		# rorl $1 %ecx 
+ 1682 0ef5 01EE     		addl	%ebp,		%esi
+ 1683 0ef7 D1       	.byte 209
+ 1684 0ef8 C9       	.byte 201		# rorl $1 %ecx 
+ 1685 0ef9 01F0     		addl	%esi,		%eax
+ 1686              		# 20_39 72 
+ 1687 0efb 8B742420 		movl	32(%esp),	%esi
+ 1688 0eff 8B6C2428 		movl	40(%esp),	%ebp
+ 1689 0f03 31EE     		xorl	%ebp,		%esi
+ 1690 0f05 8B2C24   		movl	(%esp),		%ebp
+ 1691 0f08 31EE     		xorl	%ebp,		%esi
+ 1692 0f0a 8B6C2414 		movl	20(%esp),	%ebp
+ 1693 0f0e 31EE     		xorl	%ebp,		%esi
+ 1694 0f10 89DD     		movl	%ebx,		%ebp
+ 1695 0f12 D1       	.byte 209
+GAS LISTING f.s 			page 32
+
+
+ 1696 0f13 C6       	.byte 198		# roll $1 %esi 
+ 1697 0f14 31CD     		xorl	%ecx,		%ebp
+ 1698 0f16 89742420 		movl	%esi,		32(%esp)
+ 1699 0f1a 31D5     		xorl	%edx,		%ebp
+ 1700 0f1c 8DB43ED6 		leal	3395469782(%esi,%edi,1),%esi
+ 1700      C162CA
+ 1701 0f23 89C7     		movl	%eax,		%edi
+ 1702 0f25 C1C705   		roll	$5,		%edi
+ 1703 0f28 D1       	.byte 209
+ 1704 0f29 CB       	.byte 203		# rorl $1 %ebx 
+ 1705 0f2a 01EF     		addl	%ebp,		%edi
+ 1706 0f2c D1       	.byte 209
+ 1707 0f2d CB       	.byte 203		# rorl $1 %ebx 
+ 1708 0f2e 01FE     		addl	%edi,		%esi
+ 1709              		# 20_39 73 
+ 1710 0f30 8B7C2424 		movl	36(%esp),	%edi
+ 1711 0f34 8B6C242C 		movl	44(%esp),	%ebp
+ 1712 0f38 31EF     		xorl	%ebp,		%edi
+ 1713 0f3a 8B6C2404 		movl	4(%esp),	%ebp
+ 1714 0f3e 31EF     		xorl	%ebp,		%edi
+ 1715 0f40 8B6C2418 		movl	24(%esp),	%ebp
+ 1716 0f44 31EF     		xorl	%ebp,		%edi
+ 1717 0f46 89C5     		movl	%eax,		%ebp
+ 1718 0f48 D1       	.byte 209
+ 1719 0f49 C7       	.byte 199		# roll $1 %edi 
+ 1720 0f4a 31DD     		xorl	%ebx,		%ebp
+ 1721 0f4c 897C2424 		movl	%edi,		36(%esp)
+ 1722 0f50 31CD     		xorl	%ecx,		%ebp
+ 1723 0f52 8DBC17D6 		leal	3395469782(%edi,%edx,1),%edi
+ 1723      C162CA
+ 1724 0f59 89F2     		movl	%esi,		%edx
+ 1725 0f5b C1C205   		roll	$5,		%edx
+ 1726 0f5e D1       	.byte 209
+ 1727 0f5f C8       	.byte 200		# rorl $1 %eax 
+ 1728 0f60 01EA     		addl	%ebp,		%edx
+ 1729 0f62 D1       	.byte 209
+ 1730 0f63 C8       	.byte 200		# rorl $1 %eax 
+ 1731 0f64 01D7     		addl	%edx,		%edi
+ 1732              		# 20_39 74 
+ 1733 0f66 8B542428 		movl	40(%esp),	%edx
+ 1734 0f6a 8B6C2430 		movl	48(%esp),	%ebp
+ 1735 0f6e 31EA     		xorl	%ebp,		%edx
+ 1736 0f70 8B6C2408 		movl	8(%esp),	%ebp
+ 1737 0f74 31EA     		xorl	%ebp,		%edx
+ 1738 0f76 8B6C241C 		movl	28(%esp),	%ebp
+ 1739 0f7a 31EA     		xorl	%ebp,		%edx
+ 1740 0f7c 89F5     		movl	%esi,		%ebp
+ 1741 0f7e D1       	.byte 209
+ 1742 0f7f C2       	.byte 194		# roll $1 %edx 
+ 1743 0f80 31C5     		xorl	%eax,		%ebp
+ 1744 0f82 89542428 		movl	%edx,		40(%esp)
+ 1745 0f86 31DD     		xorl	%ebx,		%ebp
+ 1746 0f88 8D940AD6 		leal	3395469782(%edx,%ecx,1),%edx
+ 1746      C162CA
+ 1747 0f8f 89F9     		movl	%edi,		%ecx
+ 1748 0f91 C1C105   		roll	$5,		%ecx
+ 1749 0f94 D1       	.byte 209
+GAS LISTING f.s 			page 33
+
+
+ 1750 0f95 CE       	.byte 206		# rorl $1 %esi 
+ 1751 0f96 01E9     		addl	%ebp,		%ecx
+ 1752 0f98 D1       	.byte 209
+ 1753 0f99 CE       	.byte 206		# rorl $1 %esi 
+ 1754 0f9a 01CA     		addl	%ecx,		%edx
+ 1755              		# 20_39 75 
+ 1756 0f9c 8B4C242C 		movl	44(%esp),	%ecx
+ 1757 0fa0 8B6C2434 		movl	52(%esp),	%ebp
+ 1758 0fa4 31E9     		xorl	%ebp,		%ecx
+ 1759 0fa6 8B6C240C 		movl	12(%esp),	%ebp
+ 1760 0faa 31E9     		xorl	%ebp,		%ecx
+ 1761 0fac 8B6C2420 		movl	32(%esp),	%ebp
+ 1762 0fb0 31E9     		xorl	%ebp,		%ecx
+ 1763 0fb2 89FD     		movl	%edi,		%ebp
+ 1764 0fb4 D1       	.byte 209
+ 1765 0fb5 C1       	.byte 193		# roll $1 %ecx 
+ 1766 0fb6 31F5     		xorl	%esi,		%ebp
+ 1767 0fb8 894C242C 		movl	%ecx,		44(%esp)
+ 1768 0fbc 31C5     		xorl	%eax,		%ebp
+ 1769 0fbe 8D8C19D6 		leal	3395469782(%ecx,%ebx,1),%ecx
+ 1769      C162CA
+ 1770 0fc5 89D3     		movl	%edx,		%ebx
+ 1771 0fc7 C1C305   		roll	$5,		%ebx
+ 1772 0fca D1       	.byte 209
+ 1773 0fcb CF       	.byte 207		# rorl $1 %edi 
+ 1774 0fcc 01EB     		addl	%ebp,		%ebx
+ 1775 0fce D1       	.byte 209
+ 1776 0fcf CF       	.byte 207		# rorl $1 %edi 
+ 1777 0fd0 01D9     		addl	%ebx,		%ecx
+ 1778              		# 20_39 76 
+ 1779 0fd2 8B5C2430 		movl	48(%esp),	%ebx
+ 1780 0fd6 8B6C2438 		movl	56(%esp),	%ebp
+ 1781 0fda 31EB     		xorl	%ebp,		%ebx
+ 1782 0fdc 8B6C2410 		movl	16(%esp),	%ebp
+ 1783 0fe0 31EB     		xorl	%ebp,		%ebx
+ 1784 0fe2 8B6C2424 		movl	36(%esp),	%ebp
+ 1785 0fe6 31EB     		xorl	%ebp,		%ebx
+ 1786 0fe8 89D5     		movl	%edx,		%ebp
+ 1787 0fea D1       	.byte 209
+ 1788 0feb C3       	.byte 195		# roll $1 %ebx 
+ 1789 0fec 31FD     		xorl	%edi,		%ebp
+ 1790 0fee 895C2430 		movl	%ebx,		48(%esp)
+ 1791 0ff2 31F5     		xorl	%esi,		%ebp
+ 1792 0ff4 8D9C03D6 		leal	3395469782(%ebx,%eax,1),%ebx
+ 1792      C162CA
+ 1793 0ffb 89C8     		movl	%ecx,		%eax
+ 1794 0ffd C1C005   		roll	$5,		%eax
+ 1795 1000 D1       	.byte 209
+ 1796 1001 CA       	.byte 202		# rorl $1 %edx 
+ 1797 1002 01E8     		addl	%ebp,		%eax
+ 1798 1004 D1       	.byte 209
+ 1799 1005 CA       	.byte 202		# rorl $1 %edx 
+ 1800 1006 01C3     		addl	%eax,		%ebx
+ 1801              		# 20_39 77 
+ 1802 1008 8B442434 		movl	52(%esp),	%eax
+ 1803 100c 8B6C243C 		movl	60(%esp),	%ebp
+ 1804 1010 31E8     		xorl	%ebp,		%eax
+GAS LISTING f.s 			page 34
+
+
+ 1805 1012 8B6C2414 		movl	20(%esp),	%ebp
+ 1806 1016 31E8     		xorl	%ebp,		%eax
+ 1807 1018 8B6C2428 		movl	40(%esp),	%ebp
+ 1808 101c 31E8     		xorl	%ebp,		%eax
+ 1809 101e 89CD     		movl	%ecx,		%ebp
+ 1810 1020 D1       	.byte 209
+ 1811 1021 C0       	.byte 192		# roll $1 %eax 
+ 1812 1022 31D5     		xorl	%edx,		%ebp
+ 1813 1024 89442434 		movl	%eax,		52(%esp)
+ 1814 1028 31FD     		xorl	%edi,		%ebp
+ 1815 102a 8D8430D6 		leal	3395469782(%eax,%esi,1),%eax
+ 1815      C162CA
+ 1816 1031 89DE     		movl	%ebx,		%esi
+ 1817 1033 C1C605   		roll	$5,		%esi
+ 1818 1036 D1       	.byte 209
+ 1819 1037 C9       	.byte 201		# rorl $1 %ecx 
+ 1820 1038 01EE     		addl	%ebp,		%esi
+ 1821 103a D1       	.byte 209
+ 1822 103b C9       	.byte 201		# rorl $1 %ecx 
+ 1823 103c 01F0     		addl	%esi,		%eax
+ 1824              		# 20_39 78 
+ 1825 103e 8B742438 		movl	56(%esp),	%esi
+ 1826 1042 8B2C24   		movl	(%esp),		%ebp
+ 1827 1045 31EE     		xorl	%ebp,		%esi
+ 1828 1047 8B6C2418 		movl	24(%esp),	%ebp
+ 1829 104b 31EE     		xorl	%ebp,		%esi
+ 1830 104d 8B6C242C 		movl	44(%esp),	%ebp
+ 1831 1051 31EE     		xorl	%ebp,		%esi
+ 1832 1053 89DD     		movl	%ebx,		%ebp
+ 1833 1055 D1       	.byte 209
+ 1834 1056 C6       	.byte 198		# roll $1 %esi 
+ 1835 1057 31CD     		xorl	%ecx,		%ebp
+ 1836 1059 89742438 		movl	%esi,		56(%esp)
+ 1837 105d 31D5     		xorl	%edx,		%ebp
+ 1838 105f 8DB43ED6 		leal	3395469782(%esi,%edi,1),%esi
+ 1838      C162CA
+ 1839 1066 89C7     		movl	%eax,		%edi
+ 1840 1068 C1C705   		roll	$5,		%edi
+ 1841 106b D1       	.byte 209
+ 1842 106c CB       	.byte 203		# rorl $1 %ebx 
+ 1843 106d 01EF     		addl	%ebp,		%edi
+ 1844 106f D1       	.byte 209
+ 1845 1070 CB       	.byte 203		# rorl $1 %ebx 
+ 1846 1071 01FE     		addl	%edi,		%esi
+ 1847              		# 20_39 79 
+ 1848 1073 8B7C243C 		movl	60(%esp),	%edi
+ 1849 1077 8B6C2404 		movl	4(%esp),	%ebp
+ 1850 107b 31EF     		xorl	%ebp,		%edi
+ 1851 107d 8B6C241C 		movl	28(%esp),	%ebp
+ 1852 1081 31EF     		xorl	%ebp,		%edi
+ 1853 1083 8B6C2430 		movl	48(%esp),	%ebp
+ 1854 1087 31EF     		xorl	%ebp,		%edi
+ 1855 1089 89C5     		movl	%eax,		%ebp
+ 1856 108b D1       	.byte 209
+ 1857 108c C7       	.byte 199		# roll $1 %edi 
+ 1858 108d 31DD     		xorl	%ebx,		%ebp
+ 1859 108f 897C243C 		movl	%edi,		60(%esp)
+GAS LISTING f.s 			page 35
+
+
+ 1860 1093 31CD     		xorl	%ecx,		%ebp
+ 1861 1095 8DBC17D6 		leal	3395469782(%edi,%edx,1),%edi
+ 1861      C162CA
+ 1862 109c 89F2     		movl	%esi,		%edx
+ 1863 109e C1C205   		roll	$5,		%edx
+ 1864 10a1 01EA     		addl	%ebp,		%edx
+ 1865 10a3 8B6C245C 		movl	92(%esp),	%ebp
+ 1866 10a7 D1       	.byte 209
+ 1867 10a8 C8       	.byte 200		# rorl $1 %eax 
+ 1868 10a9 01D7     		addl	%edx,		%edi
+ 1869 10ab D1       	.byte 209
+ 1870 10ac C8       	.byte 200		# rorl $1 %eax 
+ 1871              		# End processing 
+ 1872              	
+ 1873 10ad 8B550C   		movl	12(%ebp),	%edx
+ 1874 10b0 01DA     		addl	%ebx,		%edx
+ 1875 10b2 8B5D04   		movl	4(%ebp),	%ebx
+ 1876 10b5 01F3     		addl	%esi,		%ebx
+ 1877 10b7 89C6     		movl	%eax,		%esi
+ 1878 10b9 8B4500   		movl	(%ebp),		%eax
+ 1879 10bc 89550C   		movl	%edx,		12(%ebp)
+ 1880 10bf 01F8     		addl	%edi,		%eax
+ 1881 10c1 8B7D10   		movl	16(%ebp),	%edi
+ 1882 10c4 01CF     		addl	%ecx,		%edi
+ 1883 10c6 8B4D08   		movl	8(%ebp),	%ecx
+ 1884 10c9 01F1     		addl	%esi,		%ecx
+ 1885 10cb 894500   		movl	%eax,		(%ebp)
+ 1886 10ce 894D08   		movl	%ecx,		8(%ebp)
+ 1887 10d1 8B742440 		movl	64(%esp),	%esi
+ 1888 10d5 897D10   		movl	%edi,		16(%ebp)
+ 1889 10d8 83C640   		addl	$64,		%esi
+ 1890 10db 8B442444 		movl	68(%esp),	%eax
+ 1891 10df 895D04   		movl	%ebx,		4(%ebp)
+ 1892 10e2 39F0     		cmpl	%esi,		%eax
+ 1893 10e4 8B06     		movl	(%esi),		%eax
+ 1894 10e6 0F8D3EEF 		jge	.L000start
+ 1894      FFFF
+ 1895 10ec 83C448   		addl	$72,		%esp
+ 1896 10ef 5F       		popl	%edi
+ 1897 10f0 5B       		popl	%ebx
+ 1898 10f1 5D       		popl	%ebp
+ 1899 10f2 5E       		popl	%esi
+ 1900 10f3 C3       		ret
+ 1901              	.sha1_block_x86_end:
+ 1902              		.size	sha1_block_x86,.sha1_block_x86_end-sha1_block_x86
+ 1903              	.ident	"desasm.pl"
diff --git a/crypto/sha/asm/f.s b/crypto/sha/asm/f.s
new file mode 100644
index 0000000..9f56d18
--- /dev/null
+++ b/crypto/sha/asm/f.s
@@ -0,0 +1,1905 @@
+	# Don't even think of reading this code 
+	# It was automatically generated by sha1-586.pl 
+	# Which is a perl program used to generate the x86 assember for 
+	# any of elf, a.out, BSDI,Win32, or Solaris 
+	# eric <eay@cryptsoft.com> 
+
+	.file	"sha1-586.s"
+	.version	"01.01"
+gcc2_compiled.:
+.text
+	.align 16
+.globl sha1_block_x86
+	.type	sha1_block_x86,@function
+sha1_block_x86:
+	pushl	%esi
+	pushl	%ebp
+	movl	20(%esp),	%eax
+	movl	16(%esp),	%esi
+	addl	%esi,		%eax
+	movl	12(%esp),	%ebp
+	pushl	%ebx
+	subl	$64,		%eax
+	pushl	%edi
+	movl	4(%ebp),	%ebx
+	subl	$72,		%esp
+	movl	12(%ebp),	%edx
+	movl	16(%ebp),	%edi
+	movl	8(%ebp),	%ecx
+	movl	%eax,		68(%esp)
+	# First we need to setup the X array 
+	movl	(%esi),		%eax
+.L000start:
+	# First, load the words onto the stack in network byte order 
+.byte 15
+.byte 200		# bswapl  %eax 
+	movl	%eax,		(%esp)
+	movl	4(%esi),	%eax
+.byte 15
+.byte 200		# bswapl  %eax 
+	movl	%eax,		4(%esp)
+	movl	8(%esi),	%eax
+.byte 15
+.byte 200		# bswapl  %eax 
+	movl	%eax,		8(%esp)
+	movl	12(%esi),	%eax
+.byte 15
+.byte 200		# bswapl  %eax 
+	movl	%eax,		12(%esp)
+	movl	16(%esi),	%eax
+.byte 15
+.byte 200		# bswapl  %eax 
+	movl	%eax,		16(%esp)
+	movl	20(%esi),	%eax
+.byte 15
+.byte 200		# bswapl  %eax 
+	movl	%eax,		20(%esp)
+	movl	24(%esi),	%eax
+.byte 15
+.byte 200		# bswapl  %eax 
+	movl	%eax,		24(%esp)
+	movl	28(%esi),	%eax
+.byte 15
+.byte 200		# bswapl  %eax 
+	movl	%eax,		28(%esp)
+	movl	32(%esi),	%eax
+.byte 15
+.byte 200		# bswapl  %eax 
+	movl	%eax,		32(%esp)
+	movl	36(%esi),	%eax
+.byte 15
+.byte 200		# bswapl  %eax 
+	movl	%eax,		36(%esp)
+	movl	40(%esi),	%eax
+.byte 15
+.byte 200		# bswapl  %eax 
+	movl	%eax,		40(%esp)
+	movl	44(%esi),	%eax
+.byte 15
+.byte 200		# bswapl  %eax 
+	movl	%eax,		44(%esp)
+	movl	48(%esi),	%eax
+.byte 15
+.byte 200		# bswapl  %eax 
+	movl	%eax,		48(%esp)
+	movl	52(%esi),	%eax
+.byte 15
+.byte 200		# bswapl  %eax 
+	movl	%eax,		52(%esp)
+	movl	56(%esi),	%eax
+.byte 15
+.byte 200		# bswapl  %eax 
+	movl	%eax,		56(%esp)
+	movl	60(%esi),	%eax
+.byte 15
+.byte 200		# bswapl  %eax 
+	movl	%eax,		60(%esp)
+	# We now have the X array on the stack 
+	# starting at sp-4 
+	movl	%esi,		64(%esp)
+
+	# Start processing 
+	movl	(%ebp),		%eax
+	# 00_15 0 
+	movl	%ecx,		%esi
+	movl	%eax,		%ebp
+	xorl	%edx,		%esi
+	roll	$5,		%ebp
+	andl	%ebx,		%esi
+	addl	%edi,		%ebp
+.byte 209
+.byte 203		# rorl $1 %ebx 
+	movl	(%esp),		%edi
+.byte 209
+.byte 203		# rorl $1 %ebx 
+	xorl	%edx,		%esi
+	leal	1518500249(%ebp,%edi,1),%ebp
+	movl	%ebx,		%edi
+	addl	%ebp,		%esi
+	xorl	%ecx,		%edi
+	movl	%esi,		%ebp
+	andl	%eax,		%edi
+	roll	$5,		%ebp
+	addl	%edx,		%ebp
+	movl	4(%esp),	%edx
+.byte 209
+.byte 200		# rorl $1 %eax 
+	xorl	%ecx,		%edi
+.byte 209
+.byte 200		# rorl $1 %eax 
+	leal	1518500249(%ebp,%edx,1),%ebp
+	addl	%ebp,		%edi
+	# 00_15 2 
+	movl	%eax,		%edx
+	movl	%edi,		%ebp
+	xorl	%ebx,		%edx
+	roll	$5,		%ebp
+	andl	%esi,		%edx
+	addl	%ecx,		%ebp
+.byte 209
+.byte 206		# rorl $1 %esi 
+	movl	8(%esp),	%ecx
+.byte 209
+.byte 206		# rorl $1 %esi 
+	xorl	%ebx,		%edx
+	leal	1518500249(%ebp,%ecx,1),%ebp
+	movl	%esi,		%ecx
+	addl	%ebp,		%edx
+	xorl	%eax,		%ecx
+	movl	%edx,		%ebp
+	andl	%edi,		%ecx
+	roll	$5,		%ebp
+	addl	%ebx,		%ebp
+	movl	12(%esp),	%ebx
+.byte 209
+.byte 207		# rorl $1 %edi 
+	xorl	%eax,		%ecx
+.byte 209
+.byte 207		# rorl $1 %edi 
+	leal	1518500249(%ebp,%ebx,1),%ebp
+	addl	%ebp,		%ecx
+	# 00_15 4 
+	movl	%edi,		%ebx
+	movl	%ecx,		%ebp
+	xorl	%esi,		%ebx
+	roll	$5,		%ebp
+	andl	%edx,		%ebx
+	addl	%eax,		%ebp
+.byte 209
+.byte 202		# rorl $1 %edx 
+	movl	16(%esp),	%eax
+.byte 209
+.byte 202		# rorl $1 %edx 
+	xorl	%esi,		%ebx
+	leal	1518500249(%ebp,%eax,1),%ebp
+	movl	%edx,		%eax
+	addl	%ebp,		%ebx
+	xorl	%edi,		%eax
+	movl	%ebx,		%ebp
+	andl	%ecx,		%eax
+	roll	$5,		%ebp
+	addl	%esi,		%ebp
+	movl	20(%esp),	%esi
+.byte 209
+.byte 201		# rorl $1 %ecx 
+	xorl	%edi,		%eax
+.byte 209
+.byte 201		# rorl $1 %ecx 
+	leal	1518500249(%ebp,%esi,1),%ebp
+	addl	%ebp,		%eax
+	# 00_15 6 
+	movl	%ecx,		%esi
+	movl	%eax,		%ebp
+	xorl	%edx,		%esi
+	roll	$5,		%ebp
+	andl	%ebx,		%esi
+	addl	%edi,		%ebp
+.byte 209
+.byte 203		# rorl $1 %ebx 
+	movl	24(%esp),	%edi
+.byte 209
+.byte 203		# rorl $1 %ebx 
+	xorl	%edx,		%esi
+	leal	1518500249(%ebp,%edi,1),%ebp
+	movl	%ebx,		%edi
+	addl	%ebp,		%esi
+	xorl	%ecx,		%edi
+	movl	%esi,		%ebp
+	andl	%eax,		%edi
+	roll	$5,		%ebp
+	addl	%edx,		%ebp
+	movl	28(%esp),	%edx
+.byte 209
+.byte 200		# rorl $1 %eax 
+	xorl	%ecx,		%edi
+.byte 209
+.byte 200		# rorl $1 %eax 
+	leal	1518500249(%ebp,%edx,1),%ebp
+	addl	%ebp,		%edi
+	# 00_15 8 
+	movl	%eax,		%edx
+	movl	%edi,		%ebp
+	xorl	%ebx,		%edx
+	roll	$5,		%ebp
+	andl	%esi,		%edx
+	addl	%ecx,		%ebp
+.byte 209
+.byte 206		# rorl $1 %esi 
+	movl	32(%esp),	%ecx
+.byte 209
+.byte 206		# rorl $1 %esi 
+	xorl	%ebx,		%edx
+	leal	1518500249(%ebp,%ecx,1),%ebp
+	movl	%esi,		%ecx
+	addl	%ebp,		%edx
+	xorl	%eax,		%ecx
+	movl	%edx,		%ebp
+	andl	%edi,		%ecx
+	roll	$5,		%ebp
+	addl	%ebx,		%ebp
+	movl	36(%esp),	%ebx
+.byte 209
+.byte 207		# rorl $1 %edi 
+	xorl	%eax,		%ecx
+.byte 209
+.byte 207		# rorl $1 %edi 
+	leal	1518500249(%ebp,%ebx,1),%ebp
+	addl	%ebp,		%ecx
+	# 00_15 10 
+	movl	%edi,		%ebx
+	movl	%ecx,		%ebp
+	xorl	%esi,		%ebx
+	roll	$5,		%ebp
+	andl	%edx,		%ebx
+	addl	%eax,		%ebp
+.byte 209
+.byte 202		# rorl $1 %edx 
+	movl	40(%esp),	%eax
+.byte 209
+.byte 202		# rorl $1 %edx 
+	xorl	%esi,		%ebx
+	leal	1518500249(%ebp,%eax,1),%ebp
+	movl	%edx,		%eax
+	addl	%ebp,		%ebx
+	xorl	%edi,		%eax
+	movl	%ebx,		%ebp
+	andl	%ecx,		%eax
+	roll	$5,		%ebp
+	addl	%esi,		%ebp
+	movl	44(%esp),	%esi
+.byte 209
+.byte 201		# rorl $1 %ecx 
+	xorl	%edi,		%eax
+.byte 209
+.byte 201		# rorl $1 %ecx 
+	leal	1518500249(%ebp,%esi,1),%ebp
+	addl	%ebp,		%eax
+	# 00_15 12 
+	movl	%ecx,		%esi
+	movl	%eax,		%ebp
+	xorl	%edx,		%esi
+	roll	$5,		%ebp
+	andl	%ebx,		%esi
+	addl	%edi,		%ebp
+.byte 209
+.byte 203		# rorl $1 %ebx 
+	movl	48(%esp),	%edi
+.byte 209
+.byte 203		# rorl $1 %ebx 
+	xorl	%edx,		%esi
+	leal	1518500249(%ebp,%edi,1),%ebp
+	movl	%ebx,		%edi
+	addl	%ebp,		%esi
+	xorl	%ecx,		%edi
+	movl	%esi,		%ebp
+	andl	%eax,		%edi
+	roll	$5,		%ebp
+	addl	%edx,		%ebp
+	movl	52(%esp),	%edx
+.byte 209
+.byte 200		# rorl $1 %eax 
+	xorl	%ecx,		%edi
+.byte 209
+.byte 200		# rorl $1 %eax 
+	leal	1518500249(%ebp,%edx,1),%ebp
+	addl	%ebp,		%edi
+	# 00_15 14 
+	movl	%eax,		%edx
+	movl	%edi,		%ebp
+	xorl	%ebx,		%edx
+	roll	$5,		%ebp
+	andl	%esi,		%edx
+	addl	%ecx,		%ebp
+.byte 209
+.byte 206		# rorl $1 %esi 
+	movl	56(%esp),	%ecx
+.byte 209
+.byte 206		# rorl $1 %esi 
+	xorl	%ebx,		%edx
+	leal	1518500249(%ebp,%ecx,1),%ebp
+	movl	%esi,		%ecx
+	addl	%ebp,		%edx
+	xorl	%eax,		%ecx
+	movl	%edx,		%ebp
+	andl	%edi,		%ecx
+	roll	$5,		%ebp
+	addl	%ebx,		%ebp
+	movl	60(%esp),	%ebx
+.byte 209
+.byte 207		# rorl $1 %edi 
+	xorl	%eax,		%ecx
+.byte 209
+.byte 207		# rorl $1 %edi 
+	leal	1518500249(%ebp,%ebx,1),%ebp
+	addl	%ebp,		%ecx
+	# 16_19 16 
+	nop
+	movl	(%esp),		%ebp
+	movl	8(%esp),	%ebx
+	xorl	%ebp,		%ebx
+	movl	32(%esp),	%ebp
+	xorl	%ebp,		%ebx
+	movl	52(%esp),	%ebp
+	xorl	%ebp,		%ebx
+	movl	%edi,		%ebp
+.byte 209
+.byte 195		# roll $1 %ebx 
+	xorl	%esi,		%ebp
+	movl	%ebx,		(%esp)
+	andl	%edx,		%ebp
+	leal	1518500249(%ebx,%eax,1),%ebx
+	xorl	%esi,		%ebp
+	movl	%ecx,		%eax
+	addl	%ebp,		%ebx
+	roll	$5,		%eax
+.byte 209
+.byte 202		# rorl $1 %edx 
+	addl	%eax,		%ebx
+	movl	4(%esp),	%eax
+	movl	12(%esp),	%ebp
+	xorl	%ebp,		%eax
+	movl	36(%esp),	%ebp
+	xorl	%ebp,		%eax
+	movl	56(%esp),	%ebp
+.byte 209
+.byte 202		# rorl $1 %edx 
+	xorl	%ebp,		%eax
+.byte 209
+.byte 192		# roll $1 %eax 
+	movl	%edx,		%ebp
+	xorl	%edi,		%ebp
+	movl	%eax,		4(%esp)
+	andl	%ecx,		%ebp
+	leal	1518500249(%eax,%esi,1),%eax
+	xorl	%edi,		%ebp
+	movl	%ebx,		%esi
+	roll	$5,		%esi
+.byte 209
+.byte 201		# rorl $1 %ecx 
+	addl	%esi,		%eax
+.byte 209
+.byte 201		# rorl $1 %ecx 
+	addl	%ebp,		%eax
+	# 16_19 18 
+	movl	8(%esp),	%ebp
+	movl	16(%esp),	%esi
+	xorl	%ebp,		%esi
+	movl	40(%esp),	%ebp
+	xorl	%ebp,		%esi
+	movl	60(%esp),	%ebp
+	xorl	%ebp,		%esi
+	movl	%ecx,		%ebp
+.byte 209
+.byte 198		# roll $1 %esi 
+	xorl	%edx,		%ebp
+	movl	%esi,		8(%esp)
+	andl	%ebx,		%ebp
+	leal	1518500249(%esi,%edi,1),%esi
+	xorl	%edx,		%ebp
+	movl	%eax,		%edi
+	addl	%ebp,		%esi
+	roll	$5,		%edi
+.byte 209
+.byte 203		# rorl $1 %ebx 
+	addl	%edi,		%esi
+	movl	12(%esp),	%edi
+	movl	20(%esp),	%ebp
+	xorl	%ebp,		%edi
+	movl	44(%esp),	%ebp
+	xorl	%ebp,		%edi
+	movl	(%esp),		%ebp
+.byte 209
+.byte 203		# rorl $1 %ebx 
+	xorl	%ebp,		%edi
+.byte 209
+.byte 199		# roll $1 %edi 
+	movl	%ebx,		%ebp
+	xorl	%ecx,		%ebp
+	movl	%edi,		12(%esp)
+	andl	%eax,		%ebp
+	leal	1518500249(%edi,%edx,1),%edi
+	xorl	%ecx,		%ebp
+	movl	%esi,		%edx
+	roll	$5,		%edx
+.byte 209
+.byte 200		# rorl $1 %eax 
+	addl	%edx,		%edi
+.byte 209
+.byte 200		# rorl $1 %eax 
+	addl	%ebp,		%edi
+	# 20_39 20 
+	movl	16(%esp),	%edx
+	movl	24(%esp),	%ebp
+	xorl	%ebp,		%edx
+	movl	48(%esp),	%ebp
+	xorl	%ebp,		%edx
+	movl	4(%esp),	%ebp
+	xorl	%ebp,		%edx
+	movl	%esi,		%ebp
+.byte 209
+.byte 194		# roll $1 %edx 
+	xorl	%eax,		%ebp
+	movl	%edx,		16(%esp)
+	xorl	%ebx,		%ebp
+	leal	1859775393(%edx,%ecx,1),%edx
+	movl	%edi,		%ecx
+	roll	$5,		%ecx
+.byte 209
+.byte 206		# rorl $1 %esi 
+	addl	%ebp,		%ecx
+.byte 209
+.byte 206		# rorl $1 %esi 
+	addl	%ecx,		%edx
+	# 20_39 21 
+	movl	20(%esp),	%ecx
+	movl	28(%esp),	%ebp
+	xorl	%ebp,		%ecx
+	movl	52(%esp),	%ebp
+	xorl	%ebp,		%ecx
+	movl	8(%esp),	%ebp
+	xorl	%ebp,		%ecx
+	movl	%edi,		%ebp
+.byte 209
+.byte 193		# roll $1 %ecx 
+	xorl	%esi,		%ebp
+	movl	%ecx,		20(%esp)
+	xorl	%eax,		%ebp
+	leal	1859775393(%ecx,%ebx,1),%ecx
+	movl	%edx,		%ebx
+	roll	$5,		%ebx
+.byte 209
+.byte 207		# rorl $1 %edi 
+	addl	%ebp,		%ebx
+.byte 209
+.byte 207		# rorl $1 %edi 
+	addl	%ebx,		%ecx
+	# 20_39 22 
+	movl	24(%esp),	%ebx
+	movl	32(%esp),	%ebp
+	xorl	%ebp,		%ebx
+	movl	56(%esp),	%ebp
+	xorl	%ebp,		%ebx
+	movl	12(%esp),	%ebp
+	xorl	%ebp,		%ebx
+	movl	%edx,		%ebp
+.byte 209
+.byte 195		# roll $1 %ebx 
+	xorl	%edi,		%ebp
+	movl	%ebx,		24(%esp)
+	xorl	%esi,		%ebp
+	leal	1859775393(%ebx,%eax,1),%ebx
+	movl	%ecx,		%eax
+	roll	$5,		%eax
+.byte 209
+.byte 202		# rorl $1 %edx 
+	addl	%ebp,		%eax
+.byte 209
+.byte 202		# rorl $1 %edx 
+	addl	%eax,		%ebx
+	# 20_39 23 
+	movl	28(%esp),	%eax
+	movl	36(%esp),	%ebp
+	xorl	%ebp,		%eax
+	movl	60(%esp),	%ebp
+	xorl	%ebp,		%eax
+	movl	16(%esp),	%ebp
+	xorl	%ebp,		%eax
+	movl	%ecx,		%ebp
+.byte 209
+.byte 192		# roll $1 %eax 
+	xorl	%edx,		%ebp
+	movl	%eax,		28(%esp)
+	xorl	%edi,		%ebp
+	leal	1859775393(%eax,%esi,1),%eax
+	movl	%ebx,		%esi
+	roll	$5,		%esi
+.byte 209
+.byte 201		# rorl $1 %ecx 
+	addl	%ebp,		%esi
+.byte 209
+.byte 201		# rorl $1 %ecx 
+	addl	%esi,		%eax
+	# 20_39 24 
+	movl	32(%esp),	%esi
+	movl	40(%esp),	%ebp
+	xorl	%ebp,		%esi
+	movl	(%esp),		%ebp
+	xorl	%ebp,		%esi
+	movl	20(%esp),	%ebp
+	xorl	%ebp,		%esi
+	movl	%ebx,		%ebp
+.byte 209
+.byte 198		# roll $1 %esi 
+	xorl	%ecx,		%ebp
+	movl	%esi,		32(%esp)
+	xorl	%edx,		%ebp
+	leal	1859775393(%esi,%edi,1),%esi
+	movl	%eax,		%edi
+	roll	$5,		%edi
+.byte 209
+.byte 203		# rorl $1 %ebx 
+	addl	%ebp,		%edi
+.byte 209
+.byte 203		# rorl $1 %ebx 
+	addl	%edi,		%esi
+	# 20_39 25 
+	movl	36(%esp),	%edi
+	movl	44(%esp),	%ebp
+	xorl	%ebp,		%edi
+	movl	4(%esp),	%ebp
+	xorl	%ebp,		%edi
+	movl	24(%esp),	%ebp
+	xorl	%ebp,		%edi
+	movl	%eax,		%ebp
+.byte 209
+.byte 199		# roll $1 %edi 
+	xorl	%ebx,		%ebp
+	movl	%edi,		36(%esp)
+	xorl	%ecx,		%ebp
+	leal	1859775393(%edi,%edx,1),%edi
+	movl	%esi,		%edx
+	roll	$5,		%edx
+.byte 209
+.byte 200		# rorl $1 %eax 
+	addl	%ebp,		%edx
+.byte 209
+.byte 200		# rorl $1 %eax 
+	addl	%edx,		%edi
+	# 20_39 26 
+	movl	40(%esp),	%edx
+	movl	48(%esp),	%ebp
+	xorl	%ebp,		%edx
+	movl	8(%esp),	%ebp
+	xorl	%ebp,		%edx
+	movl	28(%esp),	%ebp
+	xorl	%ebp,		%edx
+	movl	%esi,		%ebp
+.byte 209
+.byte 194		# roll $1 %edx 
+	xorl	%eax,		%ebp
+	movl	%edx,		40(%esp)
+	xorl	%ebx,		%ebp
+	leal	1859775393(%edx,%ecx,1),%edx
+	movl	%edi,		%ecx
+	roll	$5,		%ecx
+.byte 209
+.byte 206		# rorl $1 %esi 
+	addl	%ebp,		%ecx
+.byte 209
+.byte 206		# rorl $1 %esi 
+	addl	%ecx,		%edx
+	# 20_39 27 
+	movl	44(%esp),	%ecx
+	movl	52(%esp),	%ebp
+	xorl	%ebp,		%ecx
+	movl	12(%esp),	%ebp
+	xorl	%ebp,		%ecx
+	movl	32(%esp),	%ebp
+	xorl	%ebp,		%ecx
+	movl	%edi,		%ebp
+.byte 209
+.byte 193		# roll $1 %ecx 
+	xorl	%esi,		%ebp
+	movl	%ecx,		44(%esp)
+	xorl	%eax,		%ebp
+	leal	1859775393(%ecx,%ebx,1),%ecx
+	movl	%edx,		%ebx
+	roll	$5,		%ebx
+.byte 209
+.byte 207		# rorl $1 %edi 
+	addl	%ebp,		%ebx
+.byte 209
+.byte 207		# rorl $1 %edi 
+	addl	%ebx,		%ecx
+	# 20_39 28 
+	movl	48(%esp),	%ebx
+	movl	56(%esp),	%ebp
+	xorl	%ebp,		%ebx
+	movl	16(%esp),	%ebp
+	xorl	%ebp,		%ebx
+	movl	36(%esp),	%ebp
+	xorl	%ebp,		%ebx
+	movl	%edx,		%ebp
+.byte 209
+.byte 195		# roll $1 %ebx 
+	xorl	%edi,		%ebp
+	movl	%ebx,		48(%esp)
+	xorl	%esi,		%ebp
+	leal	1859775393(%ebx,%eax,1),%ebx
+	movl	%ecx,		%eax
+	roll	$5,		%eax
+.byte 209
+.byte 202		# rorl $1 %edx 
+	addl	%ebp,		%eax
+.byte 209
+.byte 202		# rorl $1 %edx 
+	addl	%eax,		%ebx
+	# 20_39 29 
+	movl	52(%esp),	%eax
+	movl	60(%esp),	%ebp
+	xorl	%ebp,		%eax
+	movl	20(%esp),	%ebp
+	xorl	%ebp,		%eax
+	movl	40(%esp),	%ebp
+	xorl	%ebp,		%eax
+	movl	%ecx,		%ebp
+.byte 209
+.byte 192		# roll $1 %eax 
+	xorl	%edx,		%ebp
+	movl	%eax,		52(%esp)
+	xorl	%edi,		%ebp
+	leal	1859775393(%eax,%esi,1),%eax
+	movl	%ebx,		%esi
+	roll	$5,		%esi
+.byte 209
+.byte 201		# rorl $1 %ecx 
+	addl	%ebp,		%esi
+.byte 209
+.byte 201		# rorl $1 %ecx 
+	addl	%esi,		%eax
+	# 20_39 30 
+	movl	56(%esp),	%esi
+	movl	(%esp),		%ebp
+	xorl	%ebp,		%esi
+	movl	24(%esp),	%ebp
+	xorl	%ebp,		%esi
+	movl	44(%esp),	%ebp
+	xorl	%ebp,		%esi
+	movl	%ebx,		%ebp
+.byte 209
+.byte 198		# roll $1 %esi 
+	xorl	%ecx,		%ebp
+	movl	%esi,		56(%esp)
+	xorl	%edx,		%ebp
+	leal	1859775393(%esi,%edi,1),%esi
+	movl	%eax,		%edi
+	roll	$5,		%edi
+.byte 209
+.byte 203		# rorl $1 %ebx 
+	addl	%ebp,		%edi
+.byte 209
+.byte 203		# rorl $1 %ebx 
+	addl	%edi,		%esi
+	# 20_39 31 
+	movl	60(%esp),	%edi
+	movl	4(%esp),	%ebp
+	xorl	%ebp,		%edi
+	movl	28(%esp),	%ebp
+	xorl	%ebp,		%edi
+	movl	48(%esp),	%ebp
+	xorl	%ebp,		%edi
+	movl	%eax,		%ebp
+.byte 209
+.byte 199		# roll $1 %edi 
+	xorl	%ebx,		%ebp
+	movl	%edi,		60(%esp)
+	xorl	%ecx,		%ebp
+	leal	1859775393(%edi,%edx,1),%edi
+	movl	%esi,		%edx
+	roll	$5,		%edx
+.byte 209
+.byte 200		# rorl $1 %eax 
+	addl	%ebp,		%edx
+.byte 209
+.byte 200		# rorl $1 %eax 
+	addl	%edx,		%edi
+	# 20_39 32 
+	movl	(%esp),		%edx
+	movl	8(%esp),	%ebp
+	xorl	%ebp,		%edx
+	movl	32(%esp),	%ebp
+	xorl	%ebp,		%edx
+	movl	52(%esp),	%ebp
+	xorl	%ebp,		%edx
+	movl	%esi,		%ebp
+.byte 209
+.byte 194		# roll $1 %edx 
+	xorl	%eax,		%ebp
+	movl	%edx,		(%esp)
+	xorl	%ebx,		%ebp
+	leal	1859775393(%edx,%ecx,1),%edx
+	movl	%edi,		%ecx
+	roll	$5,		%ecx
+.byte 209
+.byte 206		# rorl $1 %esi 
+	addl	%ebp,		%ecx
+.byte 209
+.byte 206		# rorl $1 %esi 
+	addl	%ecx,		%edx
+	# 20_39 33 
+	movl	4(%esp),	%ecx
+	movl	12(%esp),	%ebp
+	xorl	%ebp,		%ecx
+	movl	36(%esp),	%ebp
+	xorl	%ebp,		%ecx
+	movl	56(%esp),	%ebp
+	xorl	%ebp,		%ecx
+	movl	%edi,		%ebp
+.byte 209
+.byte 193		# roll $1 %ecx 
+	xorl	%esi,		%ebp
+	movl	%ecx,		4(%esp)
+	xorl	%eax,		%ebp
+	leal	1859775393(%ecx,%ebx,1),%ecx
+	movl	%edx,		%ebx
+	roll	$5,		%ebx
+.byte 209
+.byte 207		# rorl $1 %edi 
+	addl	%ebp,		%ebx
+.byte 209
+.byte 207		# rorl $1 %edi 
+	addl	%ebx,		%ecx
+	# 20_39 34 
+	movl	8(%esp),	%ebx
+	movl	16(%esp),	%ebp
+	xorl	%ebp,		%ebx
+	movl	40(%esp),	%ebp
+	xorl	%ebp,		%ebx
+	movl	60(%esp),	%ebp
+	xorl	%ebp,		%ebx
+	movl	%edx,		%ebp
+.byte 209
+.byte 195		# roll $1 %ebx 
+	xorl	%edi,		%ebp
+	movl	%ebx,		8(%esp)
+	xorl	%esi,		%ebp
+	leal	1859775393(%ebx,%eax,1),%ebx
+	movl	%ecx,		%eax
+	roll	$5,		%eax
+.byte 209
+.byte 202		# rorl $1 %edx 
+	addl	%ebp,		%eax
+.byte 209
+.byte 202		# rorl $1 %edx 
+	addl	%eax,		%ebx
+	# 20_39 35 
+	movl	12(%esp),	%eax
+	movl	20(%esp),	%ebp
+	xorl	%ebp,		%eax
+	movl	44(%esp),	%ebp
+	xorl	%ebp,		%eax
+	movl	(%esp),		%ebp
+	xorl	%ebp,		%eax
+	movl	%ecx,		%ebp
+.byte 209
+.byte 192		# roll $1 %eax 
+	xorl	%edx,		%ebp
+	movl	%eax,		12(%esp)
+	xorl	%edi,		%ebp
+	leal	1859775393(%eax,%esi,1),%eax
+	movl	%ebx,		%esi
+	roll	$5,		%esi
+.byte 209
+.byte 201		# rorl $1 %ecx 
+	addl	%ebp,		%esi
+.byte 209
+.byte 201		# rorl $1 %ecx 
+	addl	%esi,		%eax
+	# 20_39 36 
+	movl	16(%esp),	%esi
+	movl	24(%esp),	%ebp
+	xorl	%ebp,		%esi
+	movl	48(%esp),	%ebp
+	xorl	%ebp,		%esi
+	movl	4(%esp),	%ebp
+	xorl	%ebp,		%esi
+	movl	%ebx,		%ebp
+.byte 209
+.byte 198		# roll $1 %esi 
+	xorl	%ecx,		%ebp
+	movl	%esi,		16(%esp)
+	xorl	%edx,		%ebp
+	leal	1859775393(%esi,%edi,1),%esi
+	movl	%eax,		%edi
+	roll	$5,		%edi
+.byte 209
+.byte 203		# rorl $1 %ebx 
+	addl	%ebp,		%edi
+.byte 209
+.byte 203		# rorl $1 %ebx 
+	addl	%edi,		%esi
+	# 20_39 37 
+	movl	20(%esp),	%edi
+	movl	28(%esp),	%ebp
+	xorl	%ebp,		%edi
+	movl	52(%esp),	%ebp
+	xorl	%ebp,		%edi
+	movl	8(%esp),	%ebp
+	xorl	%ebp,		%edi
+	movl	%eax,		%ebp
+.byte 209
+.byte 199		# roll $1 %edi 
+	xorl	%ebx,		%ebp
+	movl	%edi,		20(%esp)
+	xorl	%ecx,		%ebp
+	leal	1859775393(%edi,%edx,1),%edi
+	movl	%esi,		%edx
+	roll	$5,		%edx
+.byte 209
+.byte 200		# rorl $1 %eax 
+	addl	%ebp,		%edx
+.byte 209
+.byte 200		# rorl $1 %eax 
+	addl	%edx,		%edi
+	# 20_39 38 
+	movl	24(%esp),	%edx
+	movl	32(%esp),	%ebp
+	xorl	%ebp,		%edx
+	movl	56(%esp),	%ebp
+	xorl	%ebp,		%edx
+	movl	12(%esp),	%ebp
+	xorl	%ebp,		%edx
+	movl	%esi,		%ebp
+.byte 209
+.byte 194		# roll $1 %edx 
+	xorl	%eax,		%ebp
+	movl	%edx,		24(%esp)
+	xorl	%ebx,		%ebp
+	leal	1859775393(%edx,%ecx,1),%edx
+	movl	%edi,		%ecx
+	roll	$5,		%ecx
+.byte 209
+.byte 206		# rorl $1 %esi 
+	addl	%ebp,		%ecx
+.byte 209
+.byte 206		# rorl $1 %esi 
+	addl	%ecx,		%edx
+	# 20_39 39 
+	movl	28(%esp),	%ecx
+	movl	36(%esp),	%ebp
+	xorl	%ebp,		%ecx
+	movl	60(%esp),	%ebp
+	xorl	%ebp,		%ecx
+	movl	16(%esp),	%ebp
+	xorl	%ebp,		%ecx
+	movl	%edi,		%ebp
+.byte 209
+.byte 193		# roll $1 %ecx 
+	xorl	%esi,		%ebp
+	movl	%ecx,		28(%esp)
+	xorl	%eax,		%ebp
+	leal	1859775393(%ecx,%ebx,1),%ecx
+	movl	%edx,		%ebx
+	roll	$5,		%ebx
+.byte 209
+.byte 207		# rorl $1 %edi 
+	addl	%ebp,		%ebx
+.byte 209
+.byte 207		# rorl $1 %edi 
+	addl	%ebx,		%ecx
+	# 40_59 40 
+	movl	32(%esp),	%ebx
+	movl	40(%esp),	%ebp
+	xorl	%ebp,		%ebx
+	movl	(%esp),		%ebp
+	xorl	%ebp,		%ebx
+	movl	20(%esp),	%ebp
+	xorl	%ebp,		%ebx
+	movl	%edx,		%ebp
+.byte 209
+.byte 195		# roll $1 %ebx 
+	orl	%edi,		%ebp
+	movl	%ebx,		32(%esp)
+	andl	%esi,		%ebp
+	leal	2400959708(%ebx,%eax,1),%ebx
+	movl	%edx,		%eax
+.byte 209
+.byte 202		# rorl $1 %edx 
+	andl	%edi,		%eax
+	orl	%eax,		%ebp
+	movl	%ecx,		%eax
+	roll	$5,		%eax
+	addl	%eax,		%ebp
+	movl	36(%esp),	%eax
+	addl	%ebp,		%ebx
+	movl	44(%esp),	%ebp
+	xorl	%ebp,		%eax
+	movl	4(%esp),	%ebp
+	xorl	%ebp,		%eax
+	movl	24(%esp),	%ebp
+.byte 209
+.byte 202		# rorl $1 %edx 
+	xorl	%ebp,		%eax
+.byte 209
+.byte 192		# roll $1 %eax 
+	movl	%ecx,		%ebp
+	movl	%eax,		36(%esp)
+	orl	%edx,		%ebp
+	leal	2400959708(%eax,%esi,1),%eax
+	movl	%ecx,		%esi
+	andl	%edi,		%ebp
+	andl	%edx,		%esi
+	orl	%esi,		%ebp
+	movl	%ebx,		%esi
+	roll	$5,		%esi
+.byte 209
+.byte 201		# rorl $1 %ecx 
+	addl	%esi,		%ebp
+.byte 209
+.byte 201		# rorl $1 %ecx 
+	addl	%ebp,		%eax
+	# 40_59 41 
+	# 40_59 42 
+	movl	40(%esp),	%esi
+	movl	48(%esp),	%ebp
+	xorl	%ebp,		%esi
+	movl	8(%esp),	%ebp
+	xorl	%ebp,		%esi
+	movl	28(%esp),	%ebp
+	xorl	%ebp,		%esi
+	movl	%ebx,		%ebp
+.byte 209
+.byte 198		# roll $1 %esi 
+	orl	%ecx,		%ebp
+	movl	%esi,		40(%esp)
+	andl	%edx,		%ebp
+	leal	2400959708(%esi,%edi,1),%esi
+	movl	%ebx,		%edi
+.byte 209
+.byte 203		# rorl $1 %ebx 
+	andl	%ecx,		%edi
+	orl	%edi,		%ebp
+	movl	%eax,		%edi
+	roll	$5,		%edi
+	addl	%edi,		%ebp
+	movl	44(%esp),	%edi
+	addl	%ebp,		%esi
+	movl	52(%esp),	%ebp
+	xorl	%ebp,		%edi
+	movl	12(%esp),	%ebp
+	xorl	%ebp,		%edi
+	movl	32(%esp),	%ebp
+.byte 209
+.byte 203		# rorl $1 %ebx 
+	xorl	%ebp,		%edi
+.byte 209
+.byte 199		# roll $1 %edi 
+	movl	%eax,		%ebp
+	movl	%edi,		44(%esp)
+	orl	%ebx,		%ebp
+	leal	2400959708(%edi,%edx,1),%edi
+	movl	%eax,		%edx
+	andl	%ecx,		%ebp
+	andl	%ebx,		%edx
+	orl	%edx,		%ebp
+	movl	%esi,		%edx
+	roll	$5,		%edx
+.byte 209
+.byte 200		# rorl $1 %eax 
+	addl	%edx,		%ebp
+.byte 209
+.byte 200		# rorl $1 %eax 
+	addl	%ebp,		%edi
+	# 40_59 43 
+	# 40_59 44 
+	movl	48(%esp),	%edx
+	movl	56(%esp),	%ebp
+	xorl	%ebp,		%edx
+	movl	16(%esp),	%ebp
+	xorl	%ebp,		%edx
+	movl	36(%esp),	%ebp
+	xorl	%ebp,		%edx
+	movl	%esi,		%ebp
+.byte 209
+.byte 194		# roll $1 %edx 
+	orl	%eax,		%ebp
+	movl	%edx,		48(%esp)
+	andl	%ebx,		%ebp
+	leal	2400959708(%edx,%ecx,1),%edx
+	movl	%esi,		%ecx
+.byte 209
+.byte 206		# rorl $1 %esi 
+	andl	%eax,		%ecx
+	orl	%ecx,		%ebp
+	movl	%edi,		%ecx
+	roll	$5,		%ecx
+	addl	%ecx,		%ebp
+	movl	52(%esp),	%ecx
+	addl	%ebp,		%edx
+	movl	60(%esp),	%ebp
+	xorl	%ebp,		%ecx
+	movl	20(%esp),	%ebp
+	xorl	%ebp,		%ecx
+	movl	40(%esp),	%ebp
+.byte 209
+.byte 206		# rorl $1 %esi 
+	xorl	%ebp,		%ecx
+.byte 209
+.byte 193		# roll $1 %ecx 
+	movl	%edi,		%ebp
+	movl	%ecx,		52(%esp)
+	orl	%esi,		%ebp
+	leal	2400959708(%ecx,%ebx,1),%ecx
+	movl	%edi,		%ebx
+	andl	%eax,		%ebp
+	andl	%esi,		%ebx
+	orl	%ebx,		%ebp
+	movl	%edx,		%ebx
+	roll	$5,		%ebx
+.byte 209
+.byte 207		# rorl $1 %edi 
+	addl	%ebx,		%ebp
+.byte 209
+.byte 207		# rorl $1 %edi 
+	addl	%ebp,		%ecx
+	# 40_59 45 
+	# 40_59 46 
+	movl	56(%esp),	%ebx
+	movl	(%esp),		%ebp
+	xorl	%ebp,		%ebx
+	movl	24(%esp),	%ebp
+	xorl	%ebp,		%ebx
+	movl	44(%esp),	%ebp
+	xorl	%ebp,		%ebx
+	movl	%edx,		%ebp
+.byte 209
+.byte 195		# roll $1 %ebx 
+	orl	%edi,		%ebp
+	movl	%ebx,		56(%esp)
+	andl	%esi,		%ebp
+	leal	2400959708(%ebx,%eax,1),%ebx
+	movl	%edx,		%eax
+.byte 209
+.byte 202		# rorl $1 %edx 
+	andl	%edi,		%eax
+	orl	%eax,		%ebp
+	movl	%ecx,		%eax
+	roll	$5,		%eax
+	addl	%eax,		%ebp
+	movl	60(%esp),	%eax
+	addl	%ebp,		%ebx
+	movl	4(%esp),	%ebp
+	xorl	%ebp,		%eax
+	movl	28(%esp),	%ebp
+	xorl	%ebp,		%eax
+	movl	48(%esp),	%ebp
+.byte 209
+.byte 202		# rorl $1 %edx 
+	xorl	%ebp,		%eax
+.byte 209
+.byte 192		# roll $1 %eax 
+	movl	%ecx,		%ebp
+	movl	%eax,		60(%esp)
+	orl	%edx,		%ebp
+	leal	2400959708(%eax,%esi,1),%eax
+	movl	%ecx,		%esi
+	andl	%edi,		%ebp
+	andl	%edx,		%esi
+	orl	%esi,		%ebp
+	movl	%ebx,		%esi
+	roll	$5,		%esi
+.byte 209
+.byte 201		# rorl $1 %ecx 
+	addl	%esi,		%ebp
+.byte 209
+.byte 201		# rorl $1 %ecx 
+	addl	%ebp,		%eax
+	# 40_59 47 
+	# 40_59 48 
+	movl	(%esp),		%esi
+	movl	8(%esp),	%ebp
+	xorl	%ebp,		%esi
+	movl	32(%esp),	%ebp
+	xorl	%ebp,		%esi
+	movl	52(%esp),	%ebp
+	xorl	%ebp,		%esi
+	movl	%ebx,		%ebp
+.byte 209
+.byte 198		# roll $1 %esi 
+	orl	%ecx,		%ebp
+	movl	%esi,		(%esp)
+	andl	%edx,		%ebp
+	leal	2400959708(%esi,%edi,1),%esi
+	movl	%ebx,		%edi
+.byte 209
+.byte 203		# rorl $1 %ebx 
+	andl	%ecx,		%edi
+	orl	%edi,		%ebp
+	movl	%eax,		%edi
+	roll	$5,		%edi
+	addl	%edi,		%ebp
+	movl	4(%esp),	%edi
+	addl	%ebp,		%esi
+	movl	12(%esp),	%ebp
+	xorl	%ebp,		%edi
+	movl	36(%esp),	%ebp
+	xorl	%ebp,		%edi
+	movl	56(%esp),	%ebp
+.byte 209
+.byte 203		# rorl $1 %ebx 
+	xorl	%ebp,		%edi
+.byte 209
+.byte 199		# roll $1 %edi 
+	movl	%eax,		%ebp
+	movl	%edi,		4(%esp)
+	orl	%ebx,		%ebp
+	leal	2400959708(%edi,%edx,1),%edi
+	movl	%eax,		%edx
+	andl	%ecx,		%ebp
+	andl	%ebx,		%edx
+	orl	%edx,		%ebp
+	movl	%esi,		%edx
+	roll	$5,		%edx
+.byte 209
+.byte 200		# rorl $1 %eax 
+	addl	%edx,		%ebp
+.byte 209
+.byte 200		# rorl $1 %eax 
+	addl	%ebp,		%edi
+	# 40_59 49 
+	# 40_59 50 
+	movl	8(%esp),	%edx
+	movl	16(%esp),	%ebp
+	xorl	%ebp,		%edx
+	movl	40(%esp),	%ebp
+	xorl	%ebp,		%edx
+	movl	60(%esp),	%ebp
+	xorl	%ebp,		%edx
+	movl	%esi,		%ebp
+.byte 209
+.byte 194		# roll $1 %edx 
+	orl	%eax,		%ebp
+	movl	%edx,		8(%esp)
+	andl	%ebx,		%ebp
+	leal	2400959708(%edx,%ecx,1),%edx
+	movl	%esi,		%ecx
+.byte 209
+.byte 206		# rorl $1 %esi 
+	andl	%eax,		%ecx
+	orl	%ecx,		%ebp
+	movl	%edi,		%ecx
+	roll	$5,		%ecx
+	addl	%ecx,		%ebp
+	movl	12(%esp),	%ecx
+	addl	%ebp,		%edx
+	movl	20(%esp),	%ebp
+	xorl	%ebp,		%ecx
+	movl	44(%esp),	%ebp
+	xorl	%ebp,		%ecx
+	movl	(%esp),		%ebp
+.byte 209
+.byte 206		# rorl $1 %esi 
+	xorl	%ebp,		%ecx
+.byte 209
+.byte 193		# roll $1 %ecx 
+	movl	%edi,		%ebp
+	movl	%ecx,		12(%esp)
+	orl	%esi,		%ebp
+	leal	2400959708(%ecx,%ebx,1),%ecx
+	movl	%edi,		%ebx
+	andl	%eax,		%ebp
+	andl	%esi,		%ebx
+	orl	%ebx,		%ebp
+	movl	%edx,		%ebx
+	roll	$5,		%ebx
+.byte 209
+.byte 207		# rorl $1 %edi 
+	addl	%ebx,		%ebp
+.byte 209
+.byte 207		# rorl $1 %edi 
+	addl	%ebp,		%ecx
+	# 40_59 51 
+	# 40_59 52 
+	movl	16(%esp),	%ebx
+	movl	24(%esp),	%ebp
+	xorl	%ebp,		%ebx
+	movl	48(%esp),	%ebp
+	xorl	%ebp,		%ebx
+	movl	4(%esp),	%ebp
+	xorl	%ebp,		%ebx
+	movl	%edx,		%ebp
+.byte 209
+.byte 195		# roll $1 %ebx 
+	orl	%edi,		%ebp
+	movl	%ebx,		16(%esp)
+	andl	%esi,		%ebp
+	leal	2400959708(%ebx,%eax,1),%ebx
+	movl	%edx,		%eax
+.byte 209
+.byte 202		# rorl $1 %edx 
+	andl	%edi,		%eax
+	orl	%eax,		%ebp
+	movl	%ecx,		%eax
+	roll	$5,		%eax
+	addl	%eax,		%ebp
+	movl	20(%esp),	%eax
+	addl	%ebp,		%ebx
+	movl	28(%esp),	%ebp
+	xorl	%ebp,		%eax
+	movl	52(%esp),	%ebp
+	xorl	%ebp,		%eax
+	movl	8(%esp),	%ebp
+.byte 209
+.byte 202		# rorl $1 %edx 
+	xorl	%ebp,		%eax
+.byte 209
+.byte 192		# roll $1 %eax 
+	movl	%ecx,		%ebp
+	movl	%eax,		20(%esp)
+	orl	%edx,		%ebp
+	leal	2400959708(%eax,%esi,1),%eax
+	movl	%ecx,		%esi
+	andl	%edi,		%ebp
+	andl	%edx,		%esi
+	orl	%esi,		%ebp
+	movl	%ebx,		%esi
+	roll	$5,		%esi
+.byte 209
+.byte 201		# rorl $1 %ecx 
+	addl	%esi,		%ebp
+.byte 209
+.byte 201		# rorl $1 %ecx 
+	addl	%ebp,		%eax
+	# 40_59 53 
+	# 40_59 54 
+	movl	24(%esp),	%esi
+	movl	32(%esp),	%ebp
+	xorl	%ebp,		%esi
+	movl	56(%esp),	%ebp
+	xorl	%ebp,		%esi
+	movl	12(%esp),	%ebp
+	xorl	%ebp,		%esi
+	movl	%ebx,		%ebp
+.byte 209
+.byte 198		# roll $1 %esi 
+	orl	%ecx,		%ebp
+	movl	%esi,		24(%esp)
+	andl	%edx,		%ebp
+	leal	2400959708(%esi,%edi,1),%esi
+	movl	%ebx,		%edi
+.byte 209
+.byte 203		# rorl $1 %ebx 
+	andl	%ecx,		%edi
+	orl	%edi,		%ebp
+	movl	%eax,		%edi
+	roll	$5,		%edi
+	addl	%edi,		%ebp
+	movl	28(%esp),	%edi
+	addl	%ebp,		%esi
+	movl	36(%esp),	%ebp
+	xorl	%ebp,		%edi
+	movl	60(%esp),	%ebp
+	xorl	%ebp,		%edi
+	movl	16(%esp),	%ebp
+.byte 209
+.byte 203		# rorl $1 %ebx 
+	xorl	%ebp,		%edi
+.byte 209
+.byte 199		# roll $1 %edi 
+	movl	%eax,		%ebp
+	movl	%edi,		28(%esp)
+	orl	%ebx,		%ebp
+	leal	2400959708(%edi,%edx,1),%edi
+	movl	%eax,		%edx
+	andl	%ecx,		%ebp
+	andl	%ebx,		%edx
+	orl	%edx,		%ebp
+	movl	%esi,		%edx
+	roll	$5,		%edx
+.byte 209
+.byte 200		# rorl $1 %eax 
+	addl	%edx,		%ebp
+.byte 209
+.byte 200		# rorl $1 %eax 
+	addl	%ebp,		%edi
+	# 40_59 55 
+	# 40_59 56 
+	movl	32(%esp),	%edx
+	movl	40(%esp),	%ebp
+	xorl	%ebp,		%edx
+	movl	(%esp),		%ebp
+	xorl	%ebp,		%edx
+	movl	20(%esp),	%ebp
+	xorl	%ebp,		%edx
+	movl	%esi,		%ebp
+.byte 209
+.byte 194		# roll $1 %edx 
+	orl	%eax,		%ebp
+	movl	%edx,		32(%esp)
+	andl	%ebx,		%ebp
+	leal	2400959708(%edx,%ecx,1),%edx
+	movl	%esi,		%ecx
+.byte 209
+.byte 206		# rorl $1 %esi 
+	andl	%eax,		%ecx
+	orl	%ecx,		%ebp
+	movl	%edi,		%ecx
+	roll	$5,		%ecx
+	addl	%ecx,		%ebp
+	movl	36(%esp),	%ecx
+	addl	%ebp,		%edx
+	movl	44(%esp),	%ebp
+	xorl	%ebp,		%ecx
+	movl	4(%esp),	%ebp
+	xorl	%ebp,		%ecx
+	movl	24(%esp),	%ebp
+.byte 209
+.byte 206		# rorl $1 %esi 
+	xorl	%ebp,		%ecx
+.byte 209
+.byte 193		# roll $1 %ecx 
+	movl	%edi,		%ebp
+	movl	%ecx,		36(%esp)
+	orl	%esi,		%ebp
+	leal	2400959708(%ecx,%ebx,1),%ecx
+	movl	%edi,		%ebx
+	andl	%eax,		%ebp
+	andl	%esi,		%ebx
+	orl	%ebx,		%ebp
+	movl	%edx,		%ebx
+	roll	$5,		%ebx
+.byte 209
+.byte 207		# rorl $1 %edi 
+	addl	%ebx,		%ebp
+.byte 209
+.byte 207		# rorl $1 %edi 
+	addl	%ebp,		%ecx
+	# 40_59 57 
+	# 40_59 58 
+	movl	40(%esp),	%ebx
+	movl	48(%esp),	%ebp
+	xorl	%ebp,		%ebx
+	movl	8(%esp),	%ebp
+	xorl	%ebp,		%ebx
+	movl	28(%esp),	%ebp
+	xorl	%ebp,		%ebx
+	movl	%edx,		%ebp
+.byte 209
+.byte 195		# roll $1 %ebx 
+	orl	%edi,		%ebp
+	movl	%ebx,		40(%esp)
+	andl	%esi,		%ebp
+	leal	2400959708(%ebx,%eax,1),%ebx
+	movl	%edx,		%eax
+.byte 209
+.byte 202		# rorl $1 %edx 
+	andl	%edi,		%eax
+	orl	%eax,		%ebp
+	movl	%ecx,		%eax
+	roll	$5,		%eax
+	addl	%eax,		%ebp
+	movl	44(%esp),	%eax
+	addl	%ebp,		%ebx
+	movl	52(%esp),	%ebp
+	xorl	%ebp,		%eax
+	movl	12(%esp),	%ebp
+	xorl	%ebp,		%eax
+	movl	32(%esp),	%ebp
+.byte 209
+.byte 202		# rorl $1 %edx 
+	xorl	%ebp,		%eax
+.byte 209
+.byte 192		# roll $1 %eax 
+	movl	%ecx,		%ebp
+	movl	%eax,		44(%esp)
+	orl	%edx,		%ebp
+	leal	2400959708(%eax,%esi,1),%eax
+	movl	%ecx,		%esi
+	andl	%edi,		%ebp
+	andl	%edx,		%esi
+	orl	%esi,		%ebp
+	movl	%ebx,		%esi
+	roll	$5,		%esi
+.byte 209
+.byte 201		# rorl $1 %ecx 
+	addl	%esi,		%ebp
+.byte 209
+.byte 201		# rorl $1 %ecx 
+	addl	%ebp,		%eax
+	# 40_59 59 
+	# 20_39 60 
+	movl	48(%esp),	%esi
+	movl	56(%esp),	%ebp
+	xorl	%ebp,		%esi
+	movl	16(%esp),	%ebp
+	xorl	%ebp,		%esi
+	movl	36(%esp),	%ebp
+	xorl	%ebp,		%esi
+	movl	%ebx,		%ebp
+.byte 209
+.byte 198		# roll $1 %esi 
+	xorl	%ecx,		%ebp
+	movl	%esi,		48(%esp)
+	xorl	%edx,		%ebp
+	leal	3395469782(%esi,%edi,1),%esi
+	movl	%eax,		%edi
+	roll	$5,		%edi
+.byte 209
+.byte 203		# rorl $1 %ebx 
+	addl	%ebp,		%edi
+.byte 209
+.byte 203		# rorl $1 %ebx 
+	addl	%edi,		%esi
+	# 20_39 61 
+	movl	52(%esp),	%edi
+	movl	60(%esp),	%ebp
+	xorl	%ebp,		%edi
+	movl	20(%esp),	%ebp
+	xorl	%ebp,		%edi
+	movl	40(%esp),	%ebp
+	xorl	%ebp,		%edi
+	movl	%eax,		%ebp
+.byte 209
+.byte 199		# roll $1 %edi 
+	xorl	%ebx,		%ebp
+	movl	%edi,		52(%esp)
+	xorl	%ecx,		%ebp
+	leal	3395469782(%edi,%edx,1),%edi
+	movl	%esi,		%edx
+	roll	$5,		%edx
+.byte 209
+.byte 200		# rorl $1 %eax 
+	addl	%ebp,		%edx
+.byte 209
+.byte 200		# rorl $1 %eax 
+	addl	%edx,		%edi
+	# 20_39 62 
+	movl	56(%esp),	%edx
+	movl	(%esp),		%ebp
+	xorl	%ebp,		%edx
+	movl	24(%esp),	%ebp
+	xorl	%ebp,		%edx
+	movl	44(%esp),	%ebp
+	xorl	%ebp,		%edx
+	movl	%esi,		%ebp
+.byte 209
+.byte 194		# roll $1 %edx 
+	xorl	%eax,		%ebp
+	movl	%edx,		56(%esp)
+	xorl	%ebx,		%ebp
+	leal	3395469782(%edx,%ecx,1),%edx
+	movl	%edi,		%ecx
+	roll	$5,		%ecx
+.byte 209
+.byte 206		# rorl $1 %esi 
+	addl	%ebp,		%ecx
+.byte 209
+.byte 206		# rorl $1 %esi 
+	addl	%ecx,		%edx
+	# 20_39 63 
+	movl	60(%esp),	%ecx
+	movl	4(%esp),	%ebp
+	xorl	%ebp,		%ecx
+	movl	28(%esp),	%ebp
+	xorl	%ebp,		%ecx
+	movl	48(%esp),	%ebp
+	xorl	%ebp,		%ecx
+	movl	%edi,		%ebp
+.byte 209
+.byte 193		# roll $1 %ecx 
+	xorl	%esi,		%ebp
+	movl	%ecx,		60(%esp)
+	xorl	%eax,		%ebp
+	leal	3395469782(%ecx,%ebx,1),%ecx
+	movl	%edx,		%ebx
+	roll	$5,		%ebx
+.byte 209
+.byte 207		# rorl $1 %edi 
+	addl	%ebp,		%ebx
+.byte 209
+.byte 207		# rorl $1 %edi 
+	addl	%ebx,		%ecx
+	# 20_39 64 
+	movl	(%esp),		%ebx
+	movl	8(%esp),	%ebp
+	xorl	%ebp,		%ebx
+	movl	32(%esp),	%ebp
+	xorl	%ebp,		%ebx
+	movl	52(%esp),	%ebp
+	xorl	%ebp,		%ebx
+	movl	%edx,		%ebp
+.byte 209
+.byte 195		# roll $1 %ebx 
+	xorl	%edi,		%ebp
+	movl	%ebx,		(%esp)
+	xorl	%esi,		%ebp
+	leal	3395469782(%ebx,%eax,1),%ebx
+	movl	%ecx,		%eax
+	roll	$5,		%eax
+.byte 209
+.byte 202		# rorl $1 %edx 
+	addl	%ebp,		%eax
+.byte 209
+.byte 202		# rorl $1 %edx 
+	addl	%eax,		%ebx
+	# 20_39 65 
+	movl	4(%esp),	%eax
+	movl	12(%esp),	%ebp
+	xorl	%ebp,		%eax
+	movl	36(%esp),	%ebp
+	xorl	%ebp,		%eax
+	movl	56(%esp),	%ebp
+	xorl	%ebp,		%eax
+	movl	%ecx,		%ebp
+.byte 209
+.byte 192		# roll $1 %eax 
+	xorl	%edx,		%ebp
+	movl	%eax,		4(%esp)
+	xorl	%edi,		%ebp
+	leal	3395469782(%eax,%esi,1),%eax
+	movl	%ebx,		%esi
+	roll	$5,		%esi
+.byte 209
+.byte 201		# rorl $1 %ecx 
+	addl	%ebp,		%esi
+.byte 209
+.byte 201		# rorl $1 %ecx 
+	addl	%esi,		%eax
+	# 20_39 66 
+	movl	8(%esp),	%esi
+	movl	16(%esp),	%ebp
+	xorl	%ebp,		%esi
+	movl	40(%esp),	%ebp
+	xorl	%ebp,		%esi
+	movl	60(%esp),	%ebp
+	xorl	%ebp,		%esi
+	movl	%ebx,		%ebp
+.byte 209
+.byte 198		# roll $1 %esi 
+	xorl	%ecx,		%ebp
+	movl	%esi,		8(%esp)
+	xorl	%edx,		%ebp
+	leal	3395469782(%esi,%edi,1),%esi
+	movl	%eax,		%edi
+	roll	$5,		%edi
+.byte 209
+.byte 203		# rorl $1 %ebx 
+	addl	%ebp,		%edi
+.byte 209
+.byte 203		# rorl $1 %ebx 
+	addl	%edi,		%esi
+	# 20_39 67 
+	movl	12(%esp),	%edi
+	movl	20(%esp),	%ebp
+	xorl	%ebp,		%edi
+	movl	44(%esp),	%ebp
+	xorl	%ebp,		%edi
+	movl	(%esp),		%ebp
+	xorl	%ebp,		%edi
+	movl	%eax,		%ebp
+.byte 209
+.byte 199		# roll $1 %edi 
+	xorl	%ebx,		%ebp
+	movl	%edi,		12(%esp)
+	xorl	%ecx,		%ebp
+	leal	3395469782(%edi,%edx,1),%edi
+	movl	%esi,		%edx
+	roll	$5,		%edx
+.byte 209
+.byte 200		# rorl $1 %eax 
+	addl	%ebp,		%edx
+.byte 209
+.byte 200		# rorl $1 %eax 
+	addl	%edx,		%edi
+	# 20_39 68 
+	movl	16(%esp),	%edx
+	movl	24(%esp),	%ebp
+	xorl	%ebp,		%edx
+	movl	48(%esp),	%ebp
+	xorl	%ebp,		%edx
+	movl	4(%esp),	%ebp
+	xorl	%ebp,		%edx
+	movl	%esi,		%ebp
+.byte 209
+.byte 194		# roll $1 %edx 
+	xorl	%eax,		%ebp
+	movl	%edx,		16(%esp)
+	xorl	%ebx,		%ebp
+	leal	3395469782(%edx,%ecx,1),%edx
+	movl	%edi,		%ecx
+	roll	$5,		%ecx
+.byte 209
+.byte 206		# rorl $1 %esi 
+	addl	%ebp,		%ecx
+.byte 209
+.byte 206		# rorl $1 %esi 
+	addl	%ecx,		%edx
+	# 20_39 69 
+	movl	20(%esp),	%ecx
+	movl	28(%esp),	%ebp
+	xorl	%ebp,		%ecx
+	movl	52(%esp),	%ebp
+	xorl	%ebp,		%ecx
+	movl	8(%esp),	%ebp
+	xorl	%ebp,		%ecx
+	movl	%edi,		%ebp
+.byte 209
+.byte 193		# roll $1 %ecx 
+	xorl	%esi,		%ebp
+	movl	%ecx,		20(%esp)
+	xorl	%eax,		%ebp
+	leal	3395469782(%ecx,%ebx,1),%ecx
+	movl	%edx,		%ebx
+	roll	$5,		%ebx
+.byte 209
+.byte 207		# rorl $1 %edi 
+	addl	%ebp,		%ebx
+.byte 209
+.byte 207		# rorl $1 %edi 
+	addl	%ebx,		%ecx
+	# 20_39 70 
+	movl	24(%esp),	%ebx
+	movl	32(%esp),	%ebp
+	xorl	%ebp,		%ebx
+	movl	56(%esp),	%ebp
+	xorl	%ebp,		%ebx
+	movl	12(%esp),	%ebp
+	xorl	%ebp,		%ebx
+	movl	%edx,		%ebp
+.byte 209
+.byte 195		# roll $1 %ebx 
+	xorl	%edi,		%ebp
+	movl	%ebx,		24(%esp)
+	xorl	%esi,		%ebp
+	leal	3395469782(%ebx,%eax,1),%ebx
+	movl	%ecx,		%eax
+	roll	$5,		%eax
+.byte 209
+.byte 202		# rorl $1 %edx 
+	addl	%ebp,		%eax
+.byte 209
+.byte 202		# rorl $1 %edx 
+	addl	%eax,		%ebx
+	# 20_39 71 
+	movl	28(%esp),	%eax
+	movl	36(%esp),	%ebp
+	xorl	%ebp,		%eax
+	movl	60(%esp),	%ebp
+	xorl	%ebp,		%eax
+	movl	16(%esp),	%ebp
+	xorl	%ebp,		%eax
+	movl	%ecx,		%ebp
+.byte 209
+.byte 192		# roll $1 %eax 
+	xorl	%edx,		%ebp
+	movl	%eax,		28(%esp)
+	xorl	%edi,		%ebp
+	leal	3395469782(%eax,%esi,1),%eax
+	movl	%ebx,		%esi
+	roll	$5,		%esi
+.byte 209
+.byte 201		# rorl $1 %ecx 
+	addl	%ebp,		%esi
+.byte 209
+.byte 201		# rorl $1 %ecx 
+	addl	%esi,		%eax
+	# 20_39 72 
+	movl	32(%esp),	%esi
+	movl	40(%esp),	%ebp
+	xorl	%ebp,		%esi
+	movl	(%esp),		%ebp
+	xorl	%ebp,		%esi
+	movl	20(%esp),	%ebp
+	xorl	%ebp,		%esi
+	movl	%ebx,		%ebp
+.byte 209
+.byte 198		# roll $1 %esi 
+	xorl	%ecx,		%ebp
+	movl	%esi,		32(%esp)
+	xorl	%edx,		%ebp
+	leal	3395469782(%esi,%edi,1),%esi
+	movl	%eax,		%edi
+	roll	$5,		%edi
+.byte 209
+.byte 203		# rorl $1 %ebx 
+	addl	%ebp,		%edi
+.byte 209
+.byte 203		# rorl $1 %ebx 
+	addl	%edi,		%esi
+	# 20_39 73 
+	movl	36(%esp),	%edi
+	movl	44(%esp),	%ebp
+	xorl	%ebp,		%edi
+	movl	4(%esp),	%ebp
+	xorl	%ebp,		%edi
+	movl	24(%esp),	%ebp
+	xorl	%ebp,		%edi
+	movl	%eax,		%ebp
+.byte 209
+.byte 199		# roll $1 %edi 
+	xorl	%ebx,		%ebp
+	movl	%edi,		36(%esp)
+	xorl	%ecx,		%ebp
+	leal	3395469782(%edi,%edx,1),%edi
+	movl	%esi,		%edx
+	roll	$5,		%edx
+.byte 209
+.byte 200		# rorl $1 %eax 
+	addl	%ebp,		%edx
+.byte 209
+.byte 200		# rorl $1 %eax 
+	addl	%edx,		%edi
+	# 20_39 74 
+	movl	40(%esp),	%edx
+	movl	48(%esp),	%ebp
+	xorl	%ebp,		%edx
+	movl	8(%esp),	%ebp
+	xorl	%ebp,		%edx
+	movl	28(%esp),	%ebp
+	xorl	%ebp,		%edx
+	movl	%esi,		%ebp
+.byte 209
+.byte 194		# roll $1 %edx 
+	xorl	%eax,		%ebp
+	movl	%edx,		40(%esp)
+	xorl	%ebx,		%ebp
+	leal	3395469782(%edx,%ecx,1),%edx
+	movl	%edi,		%ecx
+	roll	$5,		%ecx
+.byte 209
+.byte 206		# rorl $1 %esi 
+	addl	%ebp,		%ecx
+.byte 209
+.byte 206		# rorl $1 %esi 
+	addl	%ecx,		%edx
+	# 20_39 75 
+	movl	44(%esp),	%ecx
+	movl	52(%esp),	%ebp
+	xorl	%ebp,		%ecx
+	movl	12(%esp),	%ebp
+	xorl	%ebp,		%ecx
+	movl	32(%esp),	%ebp
+	xorl	%ebp,		%ecx
+	movl	%edi,		%ebp
+.byte 209
+.byte 193		# roll $1 %ecx 
+	xorl	%esi,		%ebp
+	movl	%ecx,		44(%esp)
+	xorl	%eax,		%ebp
+	leal	3395469782(%ecx,%ebx,1),%ecx
+	movl	%edx,		%ebx
+	roll	$5,		%ebx
+.byte 209
+.byte 207		# rorl $1 %edi 
+	addl	%ebp,		%ebx
+.byte 209
+.byte 207		# rorl $1 %edi 
+	addl	%ebx,		%ecx
+	# 20_39 76 
+	movl	48(%esp),	%ebx
+	movl	56(%esp),	%ebp
+	xorl	%ebp,		%ebx
+	movl	16(%esp),	%ebp
+	xorl	%ebp,		%ebx
+	movl	36(%esp),	%ebp
+	xorl	%ebp,		%ebx
+	movl	%edx,		%ebp
+.byte 209
+.byte 195		# roll $1 %ebx 
+	xorl	%edi,		%ebp
+	movl	%ebx,		48(%esp)
+	xorl	%esi,		%ebp
+	leal	3395469782(%ebx,%eax,1),%ebx
+	movl	%ecx,		%eax
+	roll	$5,		%eax
+.byte 209
+.byte 202		# rorl $1 %edx 
+	addl	%ebp,		%eax
+.byte 209
+.byte 202		# rorl $1 %edx 
+	addl	%eax,		%ebx
+	# 20_39 77 
+	movl	52(%esp),	%eax
+	movl	60(%esp),	%ebp
+	xorl	%ebp,		%eax
+	movl	20(%esp),	%ebp
+	xorl	%ebp,		%eax
+	movl	40(%esp),	%ebp
+	xorl	%ebp,		%eax
+	movl	%ecx,		%ebp
+.byte 209
+.byte 192		# roll $1 %eax 
+	xorl	%edx,		%ebp
+	movl	%eax,		52(%esp)
+	xorl	%edi,		%ebp
+	leal	3395469782(%eax,%esi,1),%eax
+	movl	%ebx,		%esi
+	roll	$5,		%esi
+.byte 209
+.byte 201		# rorl $1 %ecx 
+	addl	%ebp,		%esi
+.byte 209
+.byte 201		# rorl $1 %ecx 
+	addl	%esi,		%eax
+	# 20_39 78 
+	movl	56(%esp),	%esi
+	movl	(%esp),		%ebp
+	xorl	%ebp,		%esi
+	movl	24(%esp),	%ebp
+	xorl	%ebp,		%esi
+	movl	44(%esp),	%ebp
+	xorl	%ebp,		%esi
+	movl	%ebx,		%ebp
+.byte 209
+.byte 198		# roll $1 %esi 
+	xorl	%ecx,		%ebp
+	movl	%esi,		56(%esp)
+	xorl	%edx,		%ebp
+	leal	3395469782(%esi,%edi,1),%esi
+	movl	%eax,		%edi
+	roll	$5,		%edi
+.byte 209
+.byte 203		# rorl $1 %ebx 
+	addl	%ebp,		%edi
+.byte 209
+.byte 203		# rorl $1 %ebx 
+	addl	%edi,		%esi
+	# 20_39 79 
+	movl	60(%esp),	%edi
+	movl	4(%esp),	%ebp
+	xorl	%ebp,		%edi
+	movl	28(%esp),	%ebp
+	xorl	%ebp,		%edi
+	movl	48(%esp),	%ebp
+	xorl	%ebp,		%edi
+	movl	%eax,		%ebp
+.byte 209
+.byte 199		# roll $1 %edi 
+	xorl	%ebx,		%ebp
+	movl	%edi,		60(%esp)
+	xorl	%ecx,		%ebp
+	leal	3395469782(%edi,%edx,1),%edi
+	movl	%esi,		%edx
+	roll	$5,		%edx
+	addl	%ebp,		%edx
+	movl	92(%esp),	%ebp
+.byte 209
+.byte 200		# rorl $1 %eax 
+	addl	%edx,		%edi
+.byte 209
+.byte 200		# rorl $1 %eax 
+	# End processing 
+
+	movl	12(%ebp),	%edx
+	addl	%ebx,		%edx
+	movl	4(%ebp),	%ebx
+	addl	%esi,		%ebx
+	movl	%eax,		%esi
+	movl	(%ebp),		%eax
+	movl	%edx,		12(%ebp)
+	addl	%edi,		%eax
+	movl	16(%ebp),	%edi
+	addl	%ecx,		%edi
+	movl	8(%ebp),	%ecx
+	addl	%esi,		%ecx
+	movl	%eax,		(%ebp)
+	movl	64(%esp),	%esi
+	movl	%ecx,		8(%ebp)
+	addl	$64,		%esi
+	movl	68(%esp),	%eax
+	movl	%edi,		16(%ebp)
+	cmpl	%esi,		%eax
+	movl	%ebx,		4(%ebp)
+	jl	.L001end
+	movl	(%esi),		%eax
+	jmp	.L000start
+.L001end:
+	addl	$72,		%esp
+	popl	%edi
+	popl	%ebx
+	popl	%ebp
+	popl	%esi
+	ret
+.sha1_block_x86_end:
+	.size	sha1_block_x86,.sha1_block_x86_end-sha1_block_x86
+.ident	"desasm.pl"
diff --git a/crypto/sha/sha1dgst.c b/crypto/sha/sha1dgst.c
index 2b0ae1f..32449ac 100644
--- a/crypto/sha/sha1dgst.c
+++ b/crypto/sha/sha1dgst.c
@@ -63,7 +63,7 @@
 #include "sha.h"
 #include "sha_locl.h"
 
-char *SHA1_version="SHA1 part of SSLeay 0.9.0b 29-Jun-1998";
+char *SHA1_version="SHA1 part of SSLeay 0.9.1a 06-Jul-1998";
 
 /* Implemented from SHA-1 document - The Secure Hash Algorithm
  */
@@ -197,7 +197,7 @@
 	 */
 #if 1
 #if defined(B_ENDIAN) || defined(SHA1_ASM)
-	if ((((unsigned int)data)%sizeof(ULONG)) == 0)
+	if ((((unsigned long)data)%sizeof(ULONG)) == 0)
 		{
 		sw=len/SHA_CBLOCK;
 		if (sw)
diff --git a/crypto/sha/sha_dgst.c b/crypto/sha/sha_dgst.c
index 8ed533e..7c8434f 100644
--- a/crypto/sha/sha_dgst.c
+++ b/crypto/sha/sha_dgst.c
@@ -63,7 +63,7 @@
 #include "sha.h"
 #include "sha_locl.h"
 
-char *SHA_version="SHA part of SSLeay 0.9.0b 29-Jun-1998";
+char *SHA_version="SHA part of SSLeay 0.9.1a 06-Jul-1998";
 
 /* Implemented from SHA-0 document - The Secure Hash Algorithm
  */
@@ -178,7 +178,7 @@
 	 */
 #if 1
 #if defined(B_ENDIAN) || defined(SHA_ASM)
-	if ((((unsigned int)data)%sizeof(ULONG)) == 0)
+	if ((((unsigned long)data)%sizeof(ULONG)) == 0)
 		{
 		sw=len/SHA_CBLOCK;
 		if (sw)
diff --git a/crypto/stack/stack.c b/crypto/stack/stack.c
index 610ccbb..1e29adf 100644
--- a/crypto/stack/stack.c
+++ b/crypto/stack/stack.c
@@ -72,7 +72,7 @@
 #undef MIN_NODES
 #define MIN_NODES	4
 
-char *STACK_version="STACK part of SSLeay 0.9.0b 29-Jun-1998";
+char *STACK_version="STACK part of SSLeay 0.9.1a 06-Jul-1998";
 
 #ifndef NOPROTO
 #define	FP_ICC	(int (*)(const void *,const void *))
diff --git a/crypto/threads/f b/crypto/threads/f
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/crypto/threads/f
diff --git a/crypto/tmdiff.c b/crypto/tmdiff.c
index b93799f..a5b1c8b 100644
--- a/crypto/tmdiff.c
+++ b/crypto/tmdiff.c
@@ -57,10 +57,17 @@
  */
 #include <stdio.h>
 #include <stdlib.h>
+#include "cryptlib.h"
+#include "tmdiff.h"
+
+#ifdef TIMEB
+#undef WIN32
+#undef TIMES
+#endif
 
 #ifndef MSDOS
 #  ifndef WIN32
-#  define TIMES
+#    define TIMES
 #  endif
 #endif
 
@@ -82,7 +89,8 @@
 		}
 #endif /* VMS */
 
-#ifdef sun
+#if defined(sun) || defined(__ultrix)
+#define _POSIX_SOURCE
 #include <limits.h>
 #include <sys/param.h>
 #endif
@@ -126,11 +134,11 @@
 #endif
 	} MS_TM;
 
-char *ms_time_init()
+char *ms_time_new()
 	{
 	MS_TM *ret;
 
-	ret=malloc(sizeof(MS_TM));
+	ret=(MS_TM *)Malloc(sizeof(MS_TM));
 	if (ret == NULL)
 		return(NULL);
 	memset(ret,0,sizeof(MS_TM));
@@ -140,28 +148,28 @@
 	return((char *)ret);
 	}
 
-void ms_time_final(a)
+void ms_time_free(a)
 char *a;
 	{
 	if (a != NULL)
-		free(a);
+		Free(a);
 	}
 
 void ms_time_get(a)
 char *a;
 	{
 	MS_TM *tm=(MS_TM *)a;
-    FILETIME tmpa,tmpb,tmpc;
+#ifdef WIN32
+	FILETIME tmpa,tmpb,tmpc;
+#endif
 
 #ifdef TIMES
-    printf("AAA\n");
 	times(&tm->ms_tms);
 #else
 #  ifdef WIN32
 	GetThreadTimes(tm->thread_id,&tmpa,&tmpb,&tmpc,&(tm->ms_win32));
 #  else
-    printf("CCC\n");
-	ftime(tm->ms_timeb);
+	ftime(&tm->ms_timeb);
 #  endif
 #endif
 	}
@@ -177,12 +185,20 @@
 	ret=(b->ms_tms.tms_utime-a->ms_tms.tms_utime)/HZ;
 #else
 # ifdef WIN32
-	ret =(double)(b->ms_win32.dwHighDateTime&0x000fffff)*10+
-		b->ms_win32.dwLowDateTime/1e7;
-	ret-=(double)(a->ms_win32.dwHighDateTime&0x000fffff)*10+a->ms_win32.dwLowDateTime/1e7;
+	{
+	signed _int64 la,lb;
+	la=a->ms_win32.dwHighDateTime;
+	lb=b->ms_win32.dwHighDateTime;
+	la<<=32;
+	lb<<=32;
+	la+=a->ms_win32.dwLowDateTime;
+	lb+=b->ms_win32.dwLowDateTime;
+	ret=((double)(lb-la))/1e7;
+	}
 # else
-	ret=	 (double)(b->time-a->time)+
-		((double)((unsigned long)b->mullitm-(unsigned long)))/1000.0;
+	ret=	 (double)(b->ms_timeb.time-a->ms_timeb.time)+
+		(((double)b->ms_timeb.millitm)-
+		((double)a->ms_timeb.millitm))/1000.0;
 #  endif
 #endif
 	return((ret < 0.0000001)?0.0000001:ret);
@@ -202,8 +218,8 @@
 	d =(b->ms_win32.dwHighDateTime&0x000fffff)*10+b->ms_win32.dwLowDateTime/1e7;
 	d-=(a->ms_win32.dwHighDateTime&0x000fffff)*10+a->ms_win32.dwLowDateTime/1e7;
 # else
-	d=	 (double)(b->time-a->time)+
-		((double)((unsigned long)b->mullitm-(unsigned long)))/1000.0;
+	d=	 (double)(b->ms_timeb.time-a->ms_timeb.time)+
+		(((double)b->ms_timeb.millitm)-(double)a->ms_timeb.millitm)/1000.0;
 #  endif
 #endif
 	if (d == 0.0)
diff --git a/crypto/tmdiff.h b/crypto/tmdiff.h
new file mode 100644
index 0000000..4561211
--- /dev/null
+++ b/crypto/tmdiff.h
@@ -0,0 +1,91 @@
+/* crypto/tmdiff.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.]
+ */
+
+/* Header for dynamic hash table routines
+ * Author - Eric Young
+ */
+
+#ifndef HEADER_TMDIFF_H
+#define HEADER_TMDIFF_H
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#ifndef NOPROTO
+char *ms_time_new(void );
+void ms_time_free(char *a);
+void ms_time_get(char *a);
+double ms_time_diff(char *start,char *end);
+int ms_time_cmp(char *ap,char *bp);
+
+#else
+
+char *ms_time_new();
+void ms_time_free();
+void ms_time_get();
+double ms_time_diff();
+int ms_time_cmp();
+#endif
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/crypto/txt_db/txt_db.c b/crypto/txt_db/txt_db.c
index e34ce4e..c704468 100644
--- a/crypto/txt_db/txt_db.c
+++ b/crypto/txt_db/txt_db.c
@@ -66,7 +66,7 @@
 #undef BUFSIZE
 #define BUFSIZE	512
 
-char *TXT_DB_version="TXT_DB part of SSLeay 0.9.0b 29-Jun-1998";
+char *TXT_DB_version="TXT_DB part of SSLeay 0.9.1a 06-Jul-1998";
 
 TXT_DB *TXT_DB_read(in,num)
 BIO *in;
diff --git a/crypto/x509/v3_x509.c b/crypto/x509/v3_x509.c
index f685aa4..fcf30f7 100644
--- a/crypto/x509/v3_x509.c
+++ b/crypto/x509/v3_x509.c
@@ -174,6 +174,7 @@
 				key_usage_data[i].name);
 			first=0;
 			}
+		break;
 		}
 	return(1);
 	}
diff --git a/crypto/x509/x509.h b/crypto/x509/x509.h
index 95114f7..4ae05bc 100644
--- a/crypto/x509/x509.h
+++ b/crypto/x509/x509.h
@@ -355,6 +355,9 @@
 
 #define X509_dup(x509) (X509 *)ASN1_dup((int (*)())i2d_X509, \
 		(char *(*)())d2i_X509,(char *)x509)
+#define X509_ATTRIBUTE_dup(xa) (X509_ATTRIBUTE *)ASN1_dup(\
+		(int (*)())i2d_X509_ATTRIBUTE, \
+		(char *(*)())d2i_X509_ATTRIBUTE,(char *)xa)
 #define X509_EXTENSION_dup(ex) (X509_EXTENSION *)ASN1_dup( \
 		(int (*)())i2d_X509_EXTENSION, \
 		(char *(*)())d2i_X509_EXTENSION,(char *)ex)
@@ -442,6 +445,9 @@
 #define i2d_DSAPrivateKey_bio(bp,dsa) ASN1_i2d_bio(i2d_DSAPrivateKey,bp, \
 		(unsigned char *)dsa)
 
+#define X509_ALGOR_dup(xn) (X509_ALGOR *)ASN1_dup((int (*)())i2d_X509_ALGOR,\
+		(char *(*)())d2i_X509_ALGOR,(char *)xn)
+
 #define X509_NAME_dup(xn) (X509_NAME *)ASN1_dup((int (*)())i2d_X509_NAME, \
 		(char *(*)())d2i_X509_NAME,(char *)xn)
 #define X509_NAME_ENTRY_dup(ne) (X509_NAME_ENTRY *)ASN1_dup( \
@@ -453,10 +459,12 @@
 	ASN1_digest((int (*)())i2d_X509,type,(char *)data,md,len)
 #define X509_NAME_digest(data,type,md,len) \
 	ASN1_digest((int (*)())i2d_X509_NAME,type,(char *)data,md,len)
+#ifndef PKCS7_ISSUER_AND_SERIAL_digest
 #define PKCS7_ISSUER_AND_SERIAL_digest(data,type,md,len) \
 	ASN1_digest((int (*)())i2d_PKCS7_ISSUER_AND_SERIAL,type,\
 		(char *)data,md,len)
 #endif
+#endif
 
 #define X509_EXT_PACK_UNKNOWN	1
 #define X509_EXT_PACK_STRING	2
@@ -528,9 +536,11 @@
 #endif
 
 X509 *X509_dup(X509 *x509);
+X509_ATTRIBUTE *X509_ATTRIBUTE_dup(X509_ATTRIBUTE *xa);
 X509_EXTENSION *X509_EXTENSION_dup(X509_EXTENSION *ex);
 X509_CRL *X509_CRL_dup(X509_CRL *crl);
 X509_REQ *X509_REQ_dup(X509_REQ *req);
+X509_ALGOR *X509_ALGOR_dup(X509_ALGOR *xn);
 X509_NAME *X509_NAME_dup(X509_NAME *xn);
 X509_NAME_ENTRY *X509_NAME_ENTRY_dup(X509_NAME_ENTRY *ne);
 RSA *RSAPublicKey_dup(RSA *rsa);
@@ -595,6 +605,8 @@
 int		i2d_X509_ATTRIBUTE(X509_ATTRIBUTE *a,unsigned char **pp);
 X509_ATTRIBUTE *d2i_X509_ATTRIBUTE(X509_ATTRIBUTE **a,unsigned char **pp,
 			long length);
+X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, char *value);
+
 
 X509_EXTENSION *X509_EXTENSION_new(void );
 void		X509_EXTENSION_free(X509_EXTENSION *a);
@@ -852,6 +864,7 @@
 int i2d_RSAPublicKey_bio();
 
 X509 *X509_dup();
+X509_ATTRIBUTE *X509_ATTRIBUTE_dup();
 X509_EXTENSION *X509_EXTENSION_dup();
 X509_CRL *X509_CRL_dup();
 X509_REQ *X509_REQ_dup();
@@ -913,6 +926,7 @@
 void		X509_ATTRIBUTE_free();
 int		i2d_X509_ATTRIBUTE();
 X509_ATTRIBUTE *d2i_X509_ATTRIBUTE();
+X509_ATTRIBUTE *X509_ATTRIBUTE_create();
 
 X509_EXTENSION *X509_EXTENSION_new();
 void		X509_EXTENSION_free();
diff --git a/crypto/x509/x509_cmp.c b/crypto/x509/x509_cmp.c
index f9d9510..ea6a65d 100644
--- a/crypto/x509/x509_cmp.c
+++ b/crypto/x509/x509_cmp.c
@@ -255,3 +255,47 @@
 	return(NULL);
 	}
 
+EVP_PKEY *X509_get_pubkey(x)
+X509 *x;
+	{
+	if ((x == NULL) || (x->cert_info == NULL))
+		return(NULL);
+	return(X509_PUBKEY_get(x->cert_info->key));
+	}
+
+int X509_check_private_key(x,k)
+X509 *x;
+EVP_PKEY *k;
+	{
+	EVP_PKEY *xk=NULL;
+	int ok=0;
+
+	xk=X509_get_pubkey(x);
+	if (xk->type != k->type) goto err;
+	switch (k->type)
+		{
+#ifndef NO_RSA
+	case EVP_PKEY_RSA:
+		if (BN_cmp(xk->pkey.rsa->n,k->pkey.rsa->n) != 0) goto err;
+		if (BN_cmp(xk->pkey.rsa->e,k->pkey.rsa->e) != 0) goto err;
+		break;
+#endif
+#ifndef NO_DSA
+	case EVP_PKEY_DSA:
+		if (BN_cmp(xk->pkey.dsa->pub_key,k->pkey.dsa->pub_key) != 0)
+			goto err;
+		break;
+#endif
+#ifndef NO_DH
+	case EVP_PKEY_DH:
+		/* No idea */
+		goto err;
+#endif
+	default:
+		goto err;
+		}
+
+	ok=1;
+err:
+	return(ok);
+	}
diff --git a/crypto/x509/x509_err.c b/crypto/x509/x509_err.c
index 9304721..0c7e30b 100644
--- a/crypto/x509/x509_err.c
+++ b/crypto/x509/x509_err.c
@@ -118,8 +118,8 @@
 	{
 	static int init=1;
 
-	if (init);
-		{;
+	if (init)
+		{
 		init=0;
 #ifndef NO_ERR
 		ERR_load_strings(ERR_LIB_X509,X509_str_functs);
diff --git a/crypto/x509/x509_lu.c b/crypto/x509/x509_lu.c
index 2c7e10a..a740510 100644
--- a/crypto/x509/x509_lu.c
+++ b/crypto/x509/x509_lu.c
@@ -109,7 +109,7 @@
 X509_LOOKUP *ctx;
 	{
 	if (ctx->method == NULL) return(0);
-	if (ctx->method->init != NULL)
+	if (ctx->method->shutdown != NULL)
 		return(ctx->method->shutdown(ctx));
 	else
 		return(1);
@@ -318,7 +318,7 @@
 	X509_OBJECT stmp,*tmp;
 	int i,j;
 
-	tmp=X509_OBJECT_retrive_by_subject(ctx->certs,type,name);
+	tmp=X509_OBJECT_retrieve_by_subject(ctx->certs,type,name);
 
 	if (tmp == NULL)
 		{
@@ -381,7 +381,7 @@
 		}
 	}
 
-X509_OBJECT *X509_OBJECT_retrive_by_subject(h,type,name)
+X509_OBJECT *X509_OBJECT_retrieve_by_subject(h,type,name)
 LHASH *h;
 int type;
 X509_NAME *name;
diff --git a/crypto/x509/x509_r2x.c b/crypto/x509/x509_r2x.c
index 6aec242..2d87213 100644
--- a/crypto/x509/x509_r2x.c
+++ b/crypto/x509/x509_r2x.c
@@ -72,8 +72,6 @@
 EVP_PKEY *pkey;
 	{
 	X509 *ret=NULL;
-	int er=1;
-	X509_REQ_INFO *ri=NULL;
 	X509_CINF *xi=NULL;
 	X509_NAME *xn;
 
@@ -84,13 +82,9 @@
 		}
 
 	/* duplicate the request */
-	ri=(X509_REQ_INFO *)ASN1_dup(i2d_X509_REQ_INFO,
-		(char *(*)())d2i_X509_REQ_INFO,(char *)r->req_info);
-	if (ri == NULL) goto err;
-
 	xi=ret->cert_info;
 
-	if (sk_num(ri->attributes) != 0)
+	if (sk_num(r->req_info->attributes) != 0)
 		{
 		if ((xi->version=ASN1_INTEGER_new()) == NULL) goto err;
 		if (!ASN1_INTEGER_set(xi->version,2)) goto err;
@@ -109,13 +103,11 @@
 
 	if (!X509_sign(ret,pkey,EVP_md5()))
 		goto err;
-	er=0;
-err:
-	if (er)
+	if (0)
 		{
+err:
 		X509_free(ret);
-		X509_REQ_INFO_free(ri);
-		return(NULL);
+		ret=NULL;
 		}
 	return(ret);
 	}
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
index c1be91e..1d62f2d 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -80,7 +80,7 @@
 static int internal_verify();
 #endif
 
-char *X509_version="X509 part of SSLeay 0.9.0b 29-Jun-1998";
+char *X509_version="X509 part of SSLeay 0.9.1a 06-Jul-1998";
 static STACK *x509_store_ctx_method=NULL;
 static int x509_store_ctx_num=0;
 #if 0
@@ -285,7 +285,11 @@
 		ok=ctx->ctx->verify(ctx);
 	else
 		ok=internal_verify(ctx);
+	if (0)
+		{
 end:
+		X509_get_pubkey_parameters(NULL,ctx->chain);
+		}
 	if (sktmp != NULL) sk_free(sktmp);
 	if (chain_ss != NULL) X509_free(chain_ss);
 	return(ok);
@@ -434,7 +438,7 @@
 		offset=((str[1]-'0')*10+(str[2]-'0'))*60;
 		offset+=(str[3]-'0')*10+(str[4]-'0');
 		if (*str == '-')
-			offset=-offset;
+			offset= -offset;
 		}
 	atm.type=V_ASN1_UTCTIME;
 	atm.length=sizeof(buff2);
@@ -509,51 +513,6 @@
 	return(1);
 	}
 
-EVP_PKEY *X509_get_pubkey(x)
-X509 *x;
-	{
-	if ((x == NULL) || (x->cert_info == NULL))
-		return(NULL);
-	return(X509_PUBKEY_get(x->cert_info->key));
-	}
-
-int X509_check_private_key(x,k)
-X509 *x;
-EVP_PKEY *k;
-	{
-	EVP_PKEY *xk=NULL;
-	int ok=0;
-
-	xk=X509_get_pubkey(x);
-	if (xk->type != k->type) goto err;
-	switch (k->type)
-		{
-#ifndef NO_RSA
-	case EVP_PKEY_RSA:
-		if (BN_cmp(xk->pkey.rsa->n,k->pkey.rsa->n) != 0) goto err;
-		if (BN_cmp(xk->pkey.rsa->e,k->pkey.rsa->e) != 0) goto err;
-		break;
-#endif
-#ifndef NO_DSA
-	case EVP_PKEY_DSA:
-		if (BN_cmp(xk->pkey.dsa->pub_key,k->pkey.dsa->pub_key) != 0)
-			goto err;
-		break;
-#endif
-#ifndef NO_DH
-	case EVP_PKEY_DH:
-		/* No idea */
-		goto err;
-#endif
-	default:
-		goto err;
-		}
-
-	ok=1;
-err:
-	return(ok);
-	}
-
 int X509_STORE_add_cert(ctx,x)
 X509_STORE *ctx;
 X509 *x;
diff --git a/crypto/x509/x509_vfy.h b/crypto/x509/x509_vfy.h
index dfc060f..6849a8c 100644
--- a/crypto/x509/x509_vfy.h
+++ b/crypto/x509/x509_vfy.h
@@ -245,7 +245,7 @@
 
 #ifndef NOPROTO
 #ifdef HEADER_LHASH_H
-X509_OBJECT *X509_OBJECT_retrive_by_subject(LHASH *h,int type,X509_NAME *name);
+X509_OBJECT *X509_OBJECT_retrieve_by_subject(LHASH *h,int type,X509_NAME *name);
 #endif
 void X509_OBJECT_up_ref_count(X509_OBJECT *a);
 void X509_OBJECT_free_contents(X509_OBJECT *a);
@@ -313,7 +313,7 @@
 #else
 
 #ifdef HEADER_LHASH_H
-X509_OBJECT *X509_OBJECT_retrive_by_subject();
+X509_OBJECT *X509_OBJECT_retrieve_by_subject();
 #endif
 void X509_OBJECT_up_ref_count();
 void X509_OBJECT_free_contents();
@@ -359,6 +359,7 @@
 int	X509_STORE_set_default_paths();
 #endif
 
+int X509_STORE_CTX_get_ex_new_index();
 int	X509_STORE_CTX_set_ex_data();
 char *	X509_STORE_CTX_get_ex_data();
 int	X509_STORE_CTX_get_error();
diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c
index b7dde23..682de16 100644
--- a/crypto/x509/x_all.c
+++ b/crypto/x509/x_all.c
@@ -133,6 +133,13 @@
 		x->signature, (char *)x->spkac,pkey,md));
 	}
 
+X509_ATTRIBUTE *X509_ATTRIBUTE_dup(xa)
+X509_ATTRIBUTE *xa;
+	{
+	return((X509_ATTRIBUTE *)ASN1_dup((int (*)())i2d_X509_ATTRIBUTE,
+		(char *(*)())d2i_X509_ATTRIBUTE,(char *)xa));
+	}
+
 X509 *X509_dup(x509)
 X509 *x509;
 	{
@@ -421,6 +428,13 @@
 	}
 #endif
 
+X509_ALGOR *X509_ALGOR_dup(xn)
+X509_ALGOR *xn;
+	{
+	return((X509_ALGOR *)ASN1_dup((int (*)())i2d_X509_ALGOR,
+	(char *(*)())d2i_X509_ALGOR,(char *)xn));
+	}
+
 X509_NAME *X509_NAME_dup(xn)
 X509_NAME *xn;
 	{