From a0fdc9ec41594852f67ec77dfad9cb06bacc4186 Mon Sep 17 00:00:00 2001
From: djm <>
Date: Fri, 9 Jan 2009 12:14:11 +0000
Subject: import openssl-0.9.8j

---
 src/lib/libcrypto/aes/aes.h             |   4 +
 src/lib/libcrypto/aes/aes_cbc.c         |   2 +
 src/lib/libcrypto/aes/aes_core.c        |   8 +
 src/lib/libcrypto/aes/asm/aes-586.pl    |   3 +-
 src/lib/libcrypto/aes/asm/aes-x86_64.pl |   7 +-
 src/lib/libcrypto/asn1/a_mbstr.c        |   2 +-
 src/lib/libcrypto/asn1/a_sign.c         |   7 +-
 src/lib/libcrypto/asn1/a_strex.c        |   2 +-
 src/lib/libcrypto/asn1/a_strnid.c       |   2 +-
 src/lib/libcrypto/asn1/a_verify.c       |   7 +-
 src/lib/libcrypto/asn1/asn1_gen.c       |   2 +-
 src/lib/libcrypto/asn1/asn1t.h          |   2 +-
 src/lib/libcrypto/asn1/asn_mime.c       |   2 +
 src/lib/libcrypto/asn1/asn_moid.c       |   2 +-
 src/lib/libcrypto/asn1/asn_pack.c       |   2 +-
 src/lib/libcrypto/asn1/nsseq.c          |   2 +-
 src/lib/libcrypto/asn1/p5_pbe.c         |   2 +-
 src/lib/libcrypto/asn1/p5_pbev2.c       |   2 +-
 src/lib/libcrypto/asn1/p8_pkey.c        |   2 +-
 src/lib/libcrypto/asn1/t_bitst.c        |   2 +-
 src/lib/libcrypto/asn1/t_crl.c          |   2 +-
 src/lib/libcrypto/asn1/t_spki.c         |   2 +-
 src/lib/libcrypto/asn1/t_x509.c         |  11 +-
 src/lib/libcrypto/asn1/t_x509a.c        |   2 +-
 src/lib/libcrypto/asn1/tasn_dec.c       |   2 +-
 src/lib/libcrypto/asn1/tasn_enc.c       |   2 +-
 src/lib/libcrypto/asn1/tasn_fre.c       |   2 +-
 src/lib/libcrypto/asn1/tasn_new.c       |   2 +-
 src/lib/libcrypto/asn1/tasn_prn.c       |   2 +-
 src/lib/libcrypto/asn1/tasn_typ.c       |   2 +-
 src/lib/libcrypto/asn1/tasn_utl.c       |   2 +-
 src/lib/libcrypto/asn1/x_algor.c        |   2 +-
 src/lib/libcrypto/asn1/x_bignum.c       |   2 +-
 src/lib/libcrypto/asn1/x_exten.c        |   2 +-
 src/lib/libcrypto/asn1/x_long.c         |   2 +-
 src/lib/libcrypto/asn1/x_x509a.c        |   2 +-
 src/lib/libcrypto/bf/bf_skey.c          |   7 +-
 src/lib/libcrypto/bf/blowfish.h         |   4 +-
 src/lib/libcrypto/bio/bss_bio.c         |   2 +-
 src/lib/libcrypto/bio/bss_dgram.c       |  64 ++-
 src/lib/libcrypto/bio/bss_file.c        |   2 +-
 src/lib/libcrypto/bn/bn.h               |  15 +-
 src/lib/libcrypto/bn/bn_div.c           |  15 +-
 src/lib/libcrypto/bn/bn_gf2m.c          |   6 +-
 src/lib/libcrypto/bn/bn_lib.c           |  19 -
 src/lib/libcrypto/bn/bn_nist.c          | 776 ++++++++++++++++++-------------
 src/lib/libcrypto/bn/bn_rand.c          |   6 +-
 src/lib/libcrypto/bn/bn_shift.c         |   2 +-
 src/lib/libcrypto/bn/bn_x931p.c         |  40 +-
 src/lib/libcrypto/buffer/buf_str.c      | 116 +++++
 src/lib/libcrypto/buffer/buffer.c       |  58 ---
 src/lib/libcrypto/camellia/camellia.h   |   5 +
 src/lib/libcrypto/camellia/cmll_misc.c  |  13 +
 src/lib/libcrypto/cast/c_skey.c         |   7 +-
 src/lib/libcrypto/cast/cast.h           |   4 +-
 src/lib/libcrypto/cms/cms_sd.c          |   2 +-
 src/lib/libcrypto/cms/cms_smime.c       |   9 +-
 src/lib/libcrypto/comp/c_zlib.c         |   4 +-
 src/lib/libcrypto/conf/conf_mall.c      |   4 +-
 src/lib/libcrypto/conf/conf_mod.c       |   2 +-
 src/lib/libcrypto/conf/conf_sap.c       |   2 +-
 src/lib/libcrypto/cryptlib.c            | 351 +++-----------
 src/lib/libcrypto/cryptlib.h            |   1 -
 src/lib/libcrypto/crypto.h              |  85 +++-
 src/lib/libcrypto/des/des_enc.c         |   4 +
 src/lib/libcrypto/des/ecb_enc.c         |  47 --
 src/lib/libcrypto/des/enc_read.c        |   4 +
 src/lib/libcrypto/des/enc_writ.c        |   4 +
 src/lib/libcrypto/des/set_key.c         |   9 +
 src/lib/libcrypto/dh/dh.h               |  11 +
 src/lib/libcrypto/dh/dh_asn1.c          |   2 +-
 src/lib/libcrypto/dh/dh_check.c         |   4 +
 src/lib/libcrypto/dh/dh_err.c           |   6 +-
 src/lib/libcrypto/dh/dh_gen.c           |   4 +
 src/lib/libcrypto/dh/dh_key.c           |   4 +
 src/lib/libcrypto/dsa/dsa.h             |  39 ++
 src/lib/libcrypto/dsa/dsa_asn1.c        |  82 +++-
 src/lib/libcrypto/dsa/dsa_err.c         |  10 +-
 src/lib/libcrypto/dsa/dsa_gen.c         |   3 +
 src/lib/libcrypto/dsa/dsa_key.c         |   4 +
 src/lib/libcrypto/dsa/dsa_lib.c         |  49 +-
 src/lib/libcrypto/dsa/dsa_ossl.c        |   3 +
 src/lib/libcrypto/dsa/dsa_sign.c        |  31 +-
 src/lib/libcrypto/dsa/dsa_vrf.c         |  32 +-
 src/lib/libcrypto/ec/ec_key.c           |  16 +-
 src/lib/libcrypto/engine/eng_all.c      |   3 +
 src/lib/libcrypto/engine/eng_cnf.c      |  11 +-
 src/lib/libcrypto/engine/eng_err.c      |   3 +-
 src/lib/libcrypto/engine/eng_int.h      |   2 +
 src/lib/libcrypto/engine/eng_padlock.c  |   4 +-
 src/lib/libcrypto/engine/eng_pkey.c     |  42 ++
 src/lib/libcrypto/engine/engine.h       |  16 +
 src/lib/libcrypto/err/err.c             | 781 ++------------------------------
 src/lib/libcrypto/err/err.h             |  12 +-
 src/lib/libcrypto/err/err_all.c         |  13 +
 src/lib/libcrypto/err/err_prn.c         |  70 ++-
 src/lib/libcrypto/err/openssl.ec        |   2 +
 src/lib/libcrypto/evp/bio_md.c          |   9 +-
 src/lib/libcrypto/evp/digest.c          | 154 ++++++-
 src/lib/libcrypto/evp/e_aes.c           |  35 +-
 src/lib/libcrypto/evp/e_camellia.c      |   2 +-
 src/lib/libcrypto/evp/e_des.c           |   9 +-
 src/lib/libcrypto/evp/e_des3.c          |  29 +-
 src/lib/libcrypto/evp/e_null.c          |   2 +-
 src/lib/libcrypto/evp/e_rc4.c           |   1 +
 src/lib/libcrypto/evp/evp.h             |  80 ++++
 src/lib/libcrypto/evp/evp_enc.c         | 267 +++--------
 src/lib/libcrypto/evp/evp_err.c         |  16 +-
 src/lib/libcrypto/evp/evp_lib.c         |  39 +-
 src/lib/libcrypto/evp/evp_locl.h        |  30 +-
 src/lib/libcrypto/evp/evp_pbe.c         |   2 +-
 src/lib/libcrypto/evp/evp_pkey.c        |   2 +-
 src/lib/libcrypto/evp/m_dss.c           |   2 +-
 src/lib/libcrypto/evp/m_dss1.c          |   3 +
 src/lib/libcrypto/evp/m_md4.c           |   1 +
 src/lib/libcrypto/evp/m_md5.c           |   1 +
 src/lib/libcrypto/evp/m_sha1.c          |   7 +-
 src/lib/libcrypto/evp/names.c           |   7 +
 src/lib/libcrypto/evp/p5_crpt.c         |   2 +-
 src/lib/libcrypto/evp/p5_crpt2.c        |   2 +-
 src/lib/libcrypto/evp/p_sign.c          |  24 +-
 src/lib/libcrypto/evp/p_verify.c        |  26 +-
 src/lib/libcrypto/hmac/hmac.c           |  10 +
 src/lib/libcrypto/hmac/hmac.h           |   1 +
 src/lib/libcrypto/idea/idea.h           |   3 +
 src/lib/libcrypto/md32_common.h         |   2 +-
 src/lib/libcrypto/md4/md4.h             |   3 +
 src/lib/libcrypto/md4/md4_dgst.c        |   7 +-
 src/lib/libcrypto/md5/md5.h             |   3 +
 src/lib/libcrypto/md5/md5_dgst.c        |   7 +-
 src/lib/libcrypto/mem_dbg.c             |  28 +-
 src/lib/libcrypto/o_init.c              |  86 ++++
 src/lib/libcrypto/objects/obj_dat.pl    |   4 +-
 src/lib/libcrypto/objects/obj_mac.num   |  68 +++
 src/lib/libcrypto/objects/objects.txt   | 108 ++++-
 src/lib/libcrypto/ocsp/ocsp_asn.c       |   2 +-
 src/lib/libcrypto/ocsp/ocsp_ht.c        |   5 +-
 src/lib/libcrypto/ocsp/ocsp_srv.c       |   2 +-
 src/lib/libcrypto/ocsp/ocsp_vfy.c       |   2 +-
 src/lib/libcrypto/opensslv.h            |   6 +-
 src/lib/libcrypto/ossl_typ.h            |   4 +
 src/lib/libcrypto/pem/pem.h             |   1 +
 src/lib/libcrypto/pem/pem_all.c         | 174 +++++++
 src/lib/libcrypto/pem/pem_lib.c         |   3 +
 src/lib/libcrypto/pem/pem_x509.c        |   2 +-
 src/lib/libcrypto/pem/pem_xaux.c        |   2 +-
 src/lib/libcrypto/pkcs12/p12_add.c      |   2 +-
 src/lib/libcrypto/pkcs12/p12_asn.c      |   2 +-
 src/lib/libcrypto/pkcs12/p12_attr.c     |   2 +-
 src/lib/libcrypto/pkcs12/p12_crpt.c     |   2 +-
 src/lib/libcrypto/pkcs12/p12_crt.c      |  39 +-
 src/lib/libcrypto/pkcs12/p12_decr.c     |   2 +-
 src/lib/libcrypto/pkcs12/p12_init.c     |   2 +-
 src/lib/libcrypto/pkcs12/p12_key.c      |   2 +-
 src/lib/libcrypto/pkcs12/p12_kiss.c     |   2 +-
 src/lib/libcrypto/pkcs12/p12_mutl.c     |   2 +-
 src/lib/libcrypto/pkcs12/p12_npas.c     |   2 +-
 src/lib/libcrypto/pkcs12/p12_p8d.c      |   2 +-
 src/lib/libcrypto/pkcs12/p12_p8e.c      |   2 +-
 src/lib/libcrypto/pkcs12/p12_utl.c      |   2 +-
 src/lib/libcrypto/pkcs12/pkcs12.h       |   2 +-
 src/lib/libcrypto/pkcs7/pk7_asn1.c      |   2 +-
 src/lib/libcrypto/pkcs7/pk7_attr.c      |   2 +-
 src/lib/libcrypto/pkcs7/pk7_mime.c      |   2 +-
 src/lib/libcrypto/pkcs7/pk7_smime.c     |   3 +-
 src/lib/libcrypto/rand/rand.h           |  29 +-
 src/lib/libcrypto/rand/rand_err.c       |  20 +-
 src/lib/libcrypto/rand/rand_lib.c       |  71 ++-
 src/lib/libcrypto/rand/randfile.c       |  66 ++-
 src/lib/libcrypto/rc2/rc2.h             |   4 +-
 src/lib/libcrypto/rc2/rc2_skey.c        |  17 +
 src/lib/libcrypto/rc4/asm/rc4-x86_64.pl |   2 +
 src/lib/libcrypto/rc4/rc4.h             |   3 +
 src/lib/libcrypto/rc4/rc4_skey.c        |  16 +-
 src/lib/libcrypto/ripemd/ripemd.h       |   4 +-
 src/lib/libcrypto/ripemd/rmd_dgst.c     |   7 +-
 src/lib/libcrypto/ripemd/rmd_locl.h     |   2 +-
 src/lib/libcrypto/rsa/rsa.h             |  41 ++
 src/lib/libcrypto/rsa/rsa_asn1.c        |   2 +-
 src/lib/libcrypto/rsa/rsa_eay.c         |  41 +-
 src/lib/libcrypto/rsa/rsa_err.c         |  10 +-
 src/lib/libcrypto/rsa/rsa_gen.c         |   3 +
 src/lib/libcrypto/rsa/rsa_lib.c         | 272 +----------
 src/lib/libcrypto/rsa/rsa_oaep.c        |   2 +-
 src/lib/libcrypto/rsa/rsa_pss.c         |   6 +-
 src/lib/libcrypto/rsa/rsa_sign.c        |  24 +-
 src/lib/libcrypto/rsa/rsa_ssl.c         |   2 +-
 src/lib/libcrypto/rsa/rsa_x931.c        |   2 +-
 src/lib/libcrypto/sha/asm/sha1-586.pl   |   2 +-
 src/lib/libcrypto/sha/sha.h             |   3 +
 src/lib/libcrypto/sha/sha1_one.c        |   2 +-
 src/lib/libcrypto/sha/sha1dgst.c        |   4 +
 src/lib/libcrypto/sha/sha256.c          |  10 +
 src/lib/libcrypto/sha/sha512.c          |  12 +-
 src/lib/libcrypto/sha/sha_locl.h        |   7 +
 src/lib/libcrypto/stack/safestack.h     |  44 ++
 src/lib/libcrypto/ui/ui_openssl.c       |   2 +
 src/lib/libcrypto/util/mkerr.pl         |   3 +-
 src/lib/libcrypto/x509/by_dir.c         |   4 +
 src/lib/libcrypto/x509/x509_att.c       |  12 +-
 src/lib/libcrypto/x509/x509_cmp.c       |   8 +-
 src/lib/libcrypto/x509/x509_trs.c       |   2 +-
 src/lib/libcrypto/x509/x509_vfy.c       |  12 +-
 src/lib/libcrypto/x509/x509_vpm.c       |   2 +-
 src/lib/libcrypto/x509/x509cset.c       |   2 +-
 src/lib/libcrypto/x509/x509spki.c       |   2 +-
 src/lib/libcrypto/x509v3/ext_dat.h      |   2 +-
 src/lib/libcrypto/x509v3/pcy_cache.c    |   2 +-
 src/lib/libcrypto/x509v3/pcy_data.c     |  10 +-
 src/lib/libcrypto/x509v3/pcy_int.h      |   2 +-
 src/lib/libcrypto/x509v3/pcy_lib.c      |   2 +-
 src/lib/libcrypto/x509v3/pcy_map.c      |   2 +-
 src/lib/libcrypto/x509v3/pcy_node.c     |   2 +-
 src/lib/libcrypto/x509v3/pcy_tree.c     |  20 +-
 src/lib/libcrypto/x509v3/v3_akey.c      |   2 +-
 src/lib/libcrypto/x509v3/v3_akeya.c     |   2 +-
 src/lib/libcrypto/x509v3/v3_alt.c       |   5 +-
 src/lib/libcrypto/x509v3/v3_bcons.c     |   2 +-
 src/lib/libcrypto/x509v3/v3_bitst.c     |   2 +-
 src/lib/libcrypto/x509v3/v3_conf.c      |   2 +-
 src/lib/libcrypto/x509v3/v3_cpols.c     |   2 +-
 src/lib/libcrypto/x509v3/v3_crld.c      |   2 +-
 src/lib/libcrypto/x509v3/v3_enum.c      |   2 +-
 src/lib/libcrypto/x509v3/v3_extku.c     |   2 +-
 src/lib/libcrypto/x509v3/v3_genn.c      |   2 +-
 src/lib/libcrypto/x509v3/v3_ia5.c       |   2 +-
 src/lib/libcrypto/x509v3/v3_info.c      |   2 +-
 src/lib/libcrypto/x509v3/v3_int.c       |   2 +-
 src/lib/libcrypto/x509v3/v3_lib.c       |   2 +-
 src/lib/libcrypto/x509v3/v3_ncons.c     |   2 +-
 src/lib/libcrypto/x509v3/v3_ocsp.c      |   2 +-
 src/lib/libcrypto/x509v3/v3_pcons.c     |   2 +-
 src/lib/libcrypto/x509v3/v3_pku.c       |   2 +-
 src/lib/libcrypto/x509v3/v3_pmaps.c     |   2 +-
 src/lib/libcrypto/x509v3/v3_prn.c       |   2 +-
 src/lib/libcrypto/x509v3/v3_purp.c      |   8 +-
 src/lib/libcrypto/x509v3/v3_skey.c      |   2 +-
 src/lib/libcrypto/x509v3/v3_sxnet.c     |   2 +-
 src/lib/libcrypto/x509v3/v3_utl.c       |  23 +-
 src/lib/libcrypto/x509v3/x509v3.h       |   6 +-
 src/lib/libssl/d1_clnt.c                |   3 +-
 src/lib/libssl/d1_enc.c                 |  19 +-
 src/lib/libssl/d1_lib.c                 |   1 +
 src/lib/libssl/d1_pkt.c                 |  22 +-
 src/lib/libssl/d1_srvr.c                |   6 +-
 src/lib/libssl/dtls1.h                  |   7 +
 src/lib/libssl/s23_clnt.c               |  16 +
 src/lib/libssl/s23_srvr.c               |   9 +
 src/lib/libssl/s3_clnt.c                |  52 ++-
 src/lib/libssl/s3_lib.c                 |  40 +-
 src/lib/libssl/s3_pkt.c                 |  16 +-
 src/lib/libssl/s3_srvr.c                |  42 +-
 src/lib/libssl/ssl.h                    |  16 +-
 src/lib/libssl/ssl_asn1.c               |   2 +-
 src/lib/libssl/ssl_ciph.c               |  13 +
 src/lib/libssl/ssl_err.c                |   5 +-
 src/lib/libssl/ssl_lib.c                |  36 ++
 src/lib/libssl/ssl_locl.h               |   8 +-
 src/lib/libssl/ssl_sess.c               |  22 +
 src/lib/libssl/t1_enc.c                 |  42 +-
 src/lib/libssl/t1_lib.c                 |  14 +-
 src/lib/libssl/test/CAss.cnf            |   2 +-
 src/lib/libssl/test/Uss.cnf             |   2 +-
 263 files changed, 3222 insertions(+), 2494 deletions(-)
 create mode 100644 src/lib/libcrypto/buffer/buf_str.c
 create mode 100644 src/lib/libcrypto/o_init.c

(limited to 'src')

diff --git a/src/lib/libcrypto/aes/aes.h b/src/lib/libcrypto/aes/aes.h
index baf0222d49..450f2b4051 100644
--- a/src/lib/libcrypto/aes/aes.h
+++ b/src/lib/libcrypto/aes/aes.h
@@ -66,6 +66,10 @@
 #define AES_MAXNR 14
 #define AES_BLOCK_SIZE 16
 
+#ifdef OPENSSL_FIPS
+#define FIPS_AES_SIZE_T	int
+#endif
+
 #ifdef  __cplusplus
 extern "C" {
 #endif
diff --git a/src/lib/libcrypto/aes/aes_cbc.c b/src/lib/libcrypto/aes/aes_cbc.c
index d2ba6bcdb4..373864cd4b 100644
--- a/src/lib/libcrypto/aes/aes_cbc.c
+++ b/src/lib/libcrypto/aes/aes_cbc.c
@@ -59,6 +59,7 @@
 #include <openssl/aes.h>
 #include "aes_locl.h"
 
+#if !defined(OPENSSL_FIPS_AES_ASM)
 void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
 		     const unsigned long length, const AES_KEY *key,
 		     unsigned char *ivec, const int enc) {
@@ -129,3 +130,4 @@ void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
 		}
 	}
 }
+#endif
diff --git a/src/lib/libcrypto/aes/aes_core.c b/src/lib/libcrypto/aes/aes_core.c
index 3a80e18b0a..cffdd4daec 100644
--- a/src/lib/libcrypto/aes/aes_core.c
+++ b/src/lib/libcrypto/aes/aes_core.c
@@ -37,6 +37,10 @@
 
 #include <stdlib.h>
 #include <openssl/aes.h>
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
+
 #include "aes_locl.h"
 
 /*
@@ -631,6 +635,10 @@ int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
    	int i = 0;
 	u32 temp;
 
+#ifdef OPENSSL_FIPS
+	FIPS_selftest_check();
+#endif
+
 	if (!userKey || !key)
 		return -1;
 	if (bits != 128 && bits != 192 && bits != 256)
diff --git a/src/lib/libcrypto/aes/asm/aes-586.pl b/src/lib/libcrypto/aes/asm/aes-586.pl
index 89fa261794..3bc46a968e 100644
--- a/src/lib/libcrypto/aes/asm/aes-586.pl
+++ b/src/lib/libcrypto/aes/asm/aes-586.pl
@@ -955,8 +955,9 @@ my $mark=&DWP(60+240,"esp");	#copy of aes_key->rounds
 
     &align	(4);
     &set_label("enc_tail");
-	&push	($key eq "edi" ? $key : "");	# push ivp
+	&mov	($s0,$key eq "edi" ? $key : "");
 	&mov	($key,$_out);			# load out
+	&push	($s0);				# push ivp
 	&mov	($s1,16);
 	&sub	($s1,$s2);
 	&cmp	($key,$acc);			# compare with inp
diff --git a/src/lib/libcrypto/aes/asm/aes-x86_64.pl b/src/lib/libcrypto/aes/asm/aes-x86_64.pl
index 44e0bf8cae..f616f1751f 100755
--- a/src/lib/libcrypto/aes/asm/aes-x86_64.pl
+++ b/src/lib/libcrypto/aes/asm/aes-x86_64.pl
@@ -1198,19 +1198,20 @@ AES_cbc_encrypt:
 	ret
 .align	4
 .Lcbc_enc_tail:
-	cmp	$inp,$out
-	je	.Lcbc_enc_in_place
+	mov	%rax,%r11
+	mov	%rcx,%r12
 	mov	%r10,%rcx
 	mov	$inp,%rsi
 	mov	$out,%rdi
 	.long	0xF689A4F3		# rep movsb
-.Lcbc_enc_in_place:
 	mov	\$16,%rcx		# zero tail
 	sub	%r10,%rcx
 	xor	%rax,%rax
 	.long	0xF689AAF3		# rep stosb
 	mov	$out,$inp		# this is not a mistake!
 	movq	\$16,$_len		# len=16
+	mov	%r11,%rax
+	mov	%r12,%rcx
 	jmp	.Lcbc_enc_loop		# one more spin...
 #----------------------------- DECRYPT -----------------------------#
 .align	16
diff --git a/src/lib/libcrypto/asn1/a_mbstr.c b/src/lib/libcrypto/asn1/a_mbstr.c
index 2d4800a22a..1bcd046893 100644
--- a/src/lib/libcrypto/asn1/a_mbstr.c
+++ b/src/lib/libcrypto/asn1/a_mbstr.c
@@ -1,5 +1,5 @@
 /* a_mbstr.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/asn1/a_sign.c b/src/lib/libcrypto/asn1/a_sign.c
index 1081950518..4dee45fbb8 100644
--- a/src/lib/libcrypto/asn1/a_sign.c
+++ b/src/lib/libcrypto/asn1/a_sign.c
@@ -267,7 +267,12 @@ int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
 		goto err;
 		}
 
-	EVP_SignInit_ex(&ctx,type, NULL);
+	if (!EVP_SignInit_ex(&ctx,type, NULL))
+		{
+		outl=0;
+		ASN1err(ASN1_F_ASN1_ITEM_SIGN,ERR_R_EVP_LIB);
+		goto err;
+		}
 	EVP_SignUpdate(&ctx,(unsigned char *)buf_in,inl);
 	if (!EVP_SignFinal(&ctx,(unsigned char *)buf_out,
 			(unsigned int *)&outl,pkey))
diff --git a/src/lib/libcrypto/asn1/a_strex.c b/src/lib/libcrypto/asn1/a_strex.c
index c2dbb6f9a5..7fc14d3296 100644
--- a/src/lib/libcrypto/asn1/a_strex.c
+++ b/src/lib/libcrypto/asn1/a_strex.c
@@ -1,5 +1,5 @@
 /* a_strex.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2000.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/asn1/a_strnid.c b/src/lib/libcrypto/asn1/a_strnid.c
index 613bbc4a7d..fe515b52ba 100644
--- a/src/lib/libcrypto/asn1/a_strnid.c
+++ b/src/lib/libcrypto/asn1/a_strnid.c
@@ -1,5 +1,5 @@
 /* a_strnid.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/asn1/a_verify.c b/src/lib/libcrypto/asn1/a_verify.c
index fdce6e4380..da3efaaf8d 100644
--- a/src/lib/libcrypto/asn1/a_verify.c
+++ b/src/lib/libcrypto/asn1/a_verify.c
@@ -100,7 +100,12 @@ int ASN1_verify(i2d_of_void *i2d, X509_ALGOR *a, ASN1_BIT_STRING *signature,
 	p=buf_in;
 
 	i2d(data,&p);
-	EVP_VerifyInit_ex(&ctx,type, NULL);
+	if (!EVP_VerifyInit_ex(&ctx,type, NULL))
+		{
+		ASN1err(ASN1_F_ASN1_VERIFY,ERR_R_EVP_LIB);
+		ret=0;
+		goto err;
+		}
 	EVP_VerifyUpdate(&ctx,(unsigned char *)buf_in,inl);
 
 	OPENSSL_cleanse(buf_in,(unsigned int)inl);
diff --git a/src/lib/libcrypto/asn1/asn1_gen.c b/src/lib/libcrypto/asn1/asn1_gen.c
index 26c832781e..2da38292c8 100644
--- a/src/lib/libcrypto/asn1/asn1_gen.c
+++ b/src/lib/libcrypto/asn1/asn1_gen.c
@@ -1,5 +1,5 @@
 /* asn1_gen.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2002.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/asn1/asn1t.h b/src/lib/libcrypto/asn1/asn1t.h
index bf315e65ed..ac14f9415b 100644
--- a/src/lib/libcrypto/asn1/asn1t.h
+++ b/src/lib/libcrypto/asn1/asn1t.h
@@ -1,5 +1,5 @@
 /* asn1t.h */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2000.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/asn1/asn_mime.c b/src/lib/libcrypto/asn1/asn_mime.c
index fe7c4ec7ab..bc80b20d63 100644
--- a/src/lib/libcrypto/asn1/asn_mime.c
+++ b/src/lib/libcrypto/asn1/asn_mime.c
@@ -526,6 +526,8 @@ int SMIME_text(BIO *in, BIO *out)
 	sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
 	while ((len = BIO_read(in, iobuf, sizeof(iobuf))) > 0)
 						BIO_write(out, iobuf, len);
+	if (len < 0)
+		return 0;
 	return 1;
 }
 
diff --git a/src/lib/libcrypto/asn1/asn_moid.c b/src/lib/libcrypto/asn1/asn_moid.c
index 9132350f10..1ea6a59248 100644
--- a/src/lib/libcrypto/asn1/asn_moid.c
+++ b/src/lib/libcrypto/asn1/asn_moid.c
@@ -1,5 +1,5 @@
 /* asn_moid.c */
-/* Written by Stephen Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Stephen Henson (steve@openssl.org) for the OpenSSL
  * project 2001.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/asn1/asn_pack.c b/src/lib/libcrypto/asn1/asn_pack.c
index e8b671b7b5..f1a5a05632 100644
--- a/src/lib/libcrypto/asn1/asn_pack.c
+++ b/src/lib/libcrypto/asn1/asn_pack.c
@@ -1,5 +1,5 @@
 /* asn_pack.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/asn1/nsseq.c b/src/lib/libcrypto/asn1/nsseq.c
index 50e2d4d07a..e551c57d59 100644
--- a/src/lib/libcrypto/asn1/nsseq.c
+++ b/src/lib/libcrypto/asn1/nsseq.c
@@ -1,5 +1,5 @@
 /* nsseq.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/asn1/p5_pbe.c b/src/lib/libcrypto/asn1/p5_pbe.c
index da91170094..c4582f8041 100644
--- a/src/lib/libcrypto/asn1/p5_pbe.c
+++ b/src/lib/libcrypto/asn1/p5_pbe.c
@@ -1,5 +1,5 @@
 /* p5_pbe.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/asn1/p5_pbev2.c b/src/lib/libcrypto/asn1/p5_pbev2.c
index c834a38ddf..2b0516afee 100644
--- a/src/lib/libcrypto/asn1/p5_pbev2.c
+++ b/src/lib/libcrypto/asn1/p5_pbev2.c
@@ -1,5 +1,5 @@
 /* p5_pbev2.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999-2004.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/asn1/p8_pkey.c b/src/lib/libcrypto/asn1/p8_pkey.c
index 24b409132f..0a1957556e 100644
--- a/src/lib/libcrypto/asn1/p8_pkey.c
+++ b/src/lib/libcrypto/asn1/p8_pkey.c
@@ -1,5 +1,5 @@
 /* p8_pkey.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/asn1/t_bitst.c b/src/lib/libcrypto/asn1/t_bitst.c
index 397332d9b8..2e59a25fa1 100644
--- a/src/lib/libcrypto/asn1/t_bitst.c
+++ b/src/lib/libcrypto/asn1/t_bitst.c
@@ -1,5 +1,5 @@
 /* t_bitst.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/asn1/t_crl.c b/src/lib/libcrypto/asn1/t_crl.c
index 929b3e5904..bdb244c015 100644
--- a/src/lib/libcrypto/asn1/t_crl.c
+++ b/src/lib/libcrypto/asn1/t_crl.c
@@ -1,5 +1,5 @@
 /* t_crl.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/asn1/t_spki.c b/src/lib/libcrypto/asn1/t_spki.c
index c2a5797dd8..a73369b949 100644
--- a/src/lib/libcrypto/asn1/t_spki.c
+++ b/src/lib/libcrypto/asn1/t_spki.c
@@ -1,5 +1,5 @@
 /* t_spki.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/asn1/t_x509.c b/src/lib/libcrypto/asn1/t_x509.c
index eb776b7b3b..8b09e5890f 100644
--- a/src/lib/libcrypto/asn1/t_x509.c
+++ b/src/lib/libcrypto/asn1/t_x509.c
@@ -393,8 +393,9 @@ int ASN1_GENERALIZEDTIME_print(BIO *bp, ASN1_GENERALIZEDTIME *tm)
 	d= (v[6]-'0')*10+(v[7]-'0');
 	h= (v[8]-'0')*10+(v[9]-'0');
 	m=  (v[10]-'0')*10+(v[11]-'0');
-	if (	(v[12] >= '0') && (v[12] <= '9') &&
-		(v[13] >= '0') && (v[13] <= '9'))
+	if (tm->length >= 14 &&
+	    (v[12] >= '0') && (v[12] <= '9') &&
+	    (v[13] >= '0') && (v[13] <= '9'))
 		s=  (v[12]-'0')*10+(v[13]-'0');
 
 	if (BIO_printf(bp,"%s %2d %02d:%02d:%02d %d%s",
@@ -428,8 +429,9 @@ int ASN1_UTCTIME_print(BIO *bp, ASN1_UTCTIME *tm)
 	d= (v[4]-'0')*10+(v[5]-'0');
 	h= (v[6]-'0')*10+(v[7]-'0');
 	m=  (v[8]-'0')*10+(v[9]-'0');
-	if (	(v[10] >= '0') && (v[10] <= '9') &&
-		(v[11] >= '0') && (v[11] <= '9'))
+	if (tm->length >=12 &&
+	    (v[10] >= '0') && (v[10] <= '9') &&
+	    (v[11] >= '0') && (v[11] <= '9'))
 		s=  (v[10]-'0')*10+(v[11]-'0');
 
 	if (BIO_printf(bp,"%s %2d %02d:%02d:%02d %d%s",
@@ -501,4 +503,3 @@ err:
 	OPENSSL_free(b);
 	return(ret);
 	}
-
diff --git a/src/lib/libcrypto/asn1/t_x509a.c b/src/lib/libcrypto/asn1/t_x509a.c
index ffbbfb51f4..8b18801a17 100644
--- a/src/lib/libcrypto/asn1/t_x509a.c
+++ b/src/lib/libcrypto/asn1/t_x509a.c
@@ -1,5 +1,5 @@
 /* t_x509a.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/asn1/tasn_dec.c b/src/lib/libcrypto/asn1/tasn_dec.c
index 0ee406231e..ced641698e 100644
--- a/src/lib/libcrypto/asn1/tasn_dec.c
+++ b/src/lib/libcrypto/asn1/tasn_dec.c
@@ -1,5 +1,5 @@
 /* tasn_dec.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2000.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/asn1/tasn_enc.c b/src/lib/libcrypto/asn1/tasn_enc.c
index be19b36acd..2721f904a6 100644
--- a/src/lib/libcrypto/asn1/tasn_enc.c
+++ b/src/lib/libcrypto/asn1/tasn_enc.c
@@ -1,5 +1,5 @@
 /* tasn_enc.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2000.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/asn1/tasn_fre.c b/src/lib/libcrypto/asn1/tasn_fre.c
index bb7c1e2af4..d7c017fa1d 100644
--- a/src/lib/libcrypto/asn1/tasn_fre.c
+++ b/src/lib/libcrypto/asn1/tasn_fre.c
@@ -1,5 +1,5 @@
 /* tasn_fre.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2000.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/asn1/tasn_new.c b/src/lib/libcrypto/asn1/tasn_new.c
index 531dad365c..5c6a2ebd4d 100644
--- a/src/lib/libcrypto/asn1/tasn_new.c
+++ b/src/lib/libcrypto/asn1/tasn_new.c
@@ -1,5 +1,5 @@
 /* tasn_new.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2000.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/asn1/tasn_prn.c b/src/lib/libcrypto/asn1/tasn_prn.c
index 719639b511..b9c96a6dbe 100644
--- a/src/lib/libcrypto/asn1/tasn_prn.c
+++ b/src/lib/libcrypto/asn1/tasn_prn.c
@@ -1,5 +1,5 @@
 /* tasn_prn.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2000.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/asn1/tasn_typ.c b/src/lib/libcrypto/asn1/tasn_typ.c
index 6f17f1bec7..6252213d15 100644
--- a/src/lib/libcrypto/asn1/tasn_typ.c
+++ b/src/lib/libcrypto/asn1/tasn_typ.c
@@ -1,5 +1,5 @@
 /* tasn_typ.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2000.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/asn1/tasn_utl.c b/src/lib/libcrypto/asn1/tasn_utl.c
index 34d520b180..ca9ec7a32f 100644
--- a/src/lib/libcrypto/asn1/tasn_utl.c
+++ b/src/lib/libcrypto/asn1/tasn_utl.c
@@ -1,5 +1,5 @@
 /* tasn_utl.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2000.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/asn1/x_algor.c b/src/lib/libcrypto/asn1/x_algor.c
index 33533aba86..99e53429b7 100644
--- a/src/lib/libcrypto/asn1/x_algor.c
+++ b/src/lib/libcrypto/asn1/x_algor.c
@@ -1,5 +1,5 @@
 /* x_algor.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2000.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/asn1/x_bignum.c b/src/lib/libcrypto/asn1/x_bignum.c
index 869c05d931..9cf3204a1b 100644
--- a/src/lib/libcrypto/asn1/x_bignum.c
+++ b/src/lib/libcrypto/asn1/x_bignum.c
@@ -1,5 +1,5 @@
 /* x_bignum.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2000.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/asn1/x_exten.c b/src/lib/libcrypto/asn1/x_exten.c
index 1732e66712..3a21239926 100644
--- a/src/lib/libcrypto/asn1/x_exten.c
+++ b/src/lib/libcrypto/asn1/x_exten.c
@@ -1,5 +1,5 @@
 /* x_exten.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2000.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/asn1/x_long.c b/src/lib/libcrypto/asn1/x_long.c
index 0db233cb95..bf35457c1f 100644
--- a/src/lib/libcrypto/asn1/x_long.c
+++ b/src/lib/libcrypto/asn1/x_long.c
@@ -1,5 +1,5 @@
 /* x_long.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2000.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/asn1/x_x509a.c b/src/lib/libcrypto/asn1/x_x509a.c
index 13db5fd03f..b603f82de7 100644
--- a/src/lib/libcrypto/asn1/x_x509a.c
+++ b/src/lib/libcrypto/asn1/x_x509a.c
@@ -1,5 +1,5 @@
 /* a_x509a.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/bf/bf_skey.c b/src/lib/libcrypto/bf/bf_skey.c
index 3673cdee6e..6ac2aeb279 100644
--- a/src/lib/libcrypto/bf/bf_skey.c
+++ b/src/lib/libcrypto/bf/bf_skey.c
@@ -59,10 +59,15 @@
 #include <stdio.h>
 #include <string.h>
 #include <openssl/blowfish.h>
+#include <openssl/crypto.h>
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
+
 #include "bf_locl.h"
 #include "bf_pi.h"
 
-void BF_set_key(BF_KEY *key, int len, const unsigned char *data)
+FIPS_NON_FIPS_VCIPHER_Init(BF)
 	{
 	int i;
 	BF_LONG *p,ri,in[2];
diff --git a/src/lib/libcrypto/bf/blowfish.h b/src/lib/libcrypto/bf/blowfish.h
index cd49e85ab2..d24ffccb65 100644
--- a/src/lib/libcrypto/bf/blowfish.h
+++ b/src/lib/libcrypto/bf/blowfish.h
@@ -104,7 +104,9 @@ typedef struct bf_key_st
 	BF_LONG S[4*256];
 	} BF_KEY;
 
- 
+#ifdef OPENSSL_FIPS 
+void private_BF_set_key(BF_KEY *key, int len, const unsigned char *data);
+#endif
 void BF_set_key(BF_KEY *key, int len, const unsigned char *data);
 
 void BF_encrypt(BF_LONG *data,const BF_KEY *key);
diff --git a/src/lib/libcrypto/bio/bss_bio.c b/src/lib/libcrypto/bio/bss_bio.c
index 0f9f0955b4..76bd48e767 100644
--- a/src/lib/libcrypto/bio/bss_bio.c
+++ b/src/lib/libcrypto/bio/bss_bio.c
@@ -919,6 +919,6 @@ int BIO_nwrite(BIO *bio, char **buf, int num)
 
 	ret = BIO_ctrl(bio, BIO_C_NWRITE, num, buf);
 	if (ret > 0)
-		bio->num_read += ret;
+		bio->num_write += ret;
 	return ret;
 	}
diff --git a/src/lib/libcrypto/bio/bss_dgram.c b/src/lib/libcrypto/bio/bss_dgram.c
index ea2c3fff63..c3da6dc82f 100644
--- a/src/lib/libcrypto/bio/bss_dgram.c
+++ b/src/lib/libcrypto/bio/bss_dgram.c
@@ -82,7 +82,7 @@ static int dgram_new(BIO *h);
 static int dgram_free(BIO *data);
 static int dgram_clear(BIO *bio);
 
-int BIO_dgram_should_retry(int s);
+static int BIO_dgram_should_retry(int s);
 
 static BIO_METHOD methods_dgramp=
 	{
@@ -345,30 +345,90 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
 
         memcpy(&(data->peer), to, sizeof(struct sockaddr));
         break;
+#if defined(SO_RCVTIMEO)
 	case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT:
+#ifdef OPENSSL_SYS_WINDOWS
+		{
+		struct timeval *tv = (struct timeval *)ptr;
+		int timeout = tv->tv_sec * 1000 + tv->tv_usec/1000;
+		if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
+			(void*)&timeout, sizeof(timeout)) < 0)
+			{ perror("setsockopt"); ret = -1; }
+		}
+#else
 		if ( setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, ptr,
 			sizeof(struct timeval)) < 0)
 			{ perror("setsockopt");	ret = -1; }
+#endif
 		break;
 	case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT:
+#ifdef OPENSSL_SYS_WINDOWS
+		{
+		int timeout, sz = sizeof(timeout);
+		struct timeval *tv = (struct timeval *)ptr;
+		if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
+			(void*)&timeout, &sz) < 0)
+			{ perror("getsockopt"); ret = -1; }
+		else
+			{
+			tv->tv_sec = timeout / 1000;
+			tv->tv_usec = (timeout % 1000) * 1000;
+			ret = sizeof(*tv);
+			}
+		}
+#else
 		if ( getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, 
 			ptr, (void *)&ret) < 0)
 			{ perror("getsockopt"); ret = -1; }
+#endif
 		break;
+#endif
+#if defined(SO_SNDTIMEO)
 	case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT:
+#ifdef OPENSSL_SYS_WINDOWS
+		{
+		struct timeval *tv = (struct timeval *)ptr;
+		int timeout = tv->tv_sec * 1000 + tv->tv_usec/1000;
+		if (setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO,
+			(void*)&timeout, sizeof(timeout)) < 0)
+			{ perror("setsockopt"); ret = -1; }
+		}
+#else
 		if ( setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, ptr,
 			sizeof(struct timeval)) < 0)
 			{ perror("setsockopt");	ret = -1; }
+#endif
 		break;
 	case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT:
+#ifdef OPENSSL_SYS_WINDOWS
+		{
+		int timeout, sz = sizeof(timeout);
+		struct timeval *tv = (struct timeval *)ptr;
+		if (getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO,
+			(void*)&timeout, &sz) < 0)
+			{ perror("getsockopt"); ret = -1; }
+		else
+			{
+			tv->tv_sec = timeout / 1000;
+			tv->tv_usec = (timeout % 1000) * 1000;
+			ret = sizeof(*tv);
+			}
+		}
+#else
 		if ( getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, 
 			ptr, (void *)&ret) < 0)
 			{ perror("getsockopt"); ret = -1; }
+#endif
 		break;
+#endif
 	case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP:
 		/* fall-through */
 	case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP:
+#ifdef OPENSSL_SYS_WINDOWS
+		if ( data->_errno == WSAETIMEDOUT)
+#else
 		if ( data->_errno == EAGAIN)
+#endif
 			{
 			ret = 1;
 			data->_errno = 0;
@@ -403,7 +463,7 @@ static int dgram_puts(BIO *bp, const char *str)
 	return(ret);
 	}
 
-int BIO_dgram_should_retry(int i)
+static int BIO_dgram_should_retry(int i)
 	{
 	int err;
 
diff --git a/src/lib/libcrypto/bio/bss_file.c b/src/lib/libcrypto/bio/bss_file.c
index 4df9927c43..9ad46fa081 100644
--- a/src/lib/libcrypto/bio/bss_file.c
+++ b/src/lib/libcrypto/bio/bss_file.c
@@ -279,7 +279,7 @@ static long MS_CALLBACK file_ctrl(BIO *b, int cmd, long num, void *ptr)
 #endif
 		{
 #if defined(OPENSSL_SYS_WINDOWS)
-		int fd = fileno((FILE*)ptr);
+		int fd = _fileno((FILE*)ptr);
 		if (num & BIO_FP_TEXT)
 			_setmode(fd,_O_TEXT);
 		else
diff --git a/src/lib/libcrypto/bn/bn.h b/src/lib/libcrypto/bn/bn.h
index 6d754d5547..f1719a5877 100644
--- a/src/lib/libcrypto/bn/bn.h
+++ b/src/lib/libcrypto/bn/bn.h
@@ -408,8 +408,8 @@ BIGNUM *BN_CTX_get(BN_CTX *ctx);
 void	BN_CTX_end(BN_CTX *ctx);
 int     BN_rand(BIGNUM *rnd, int bits, int top,int bottom);
 int     BN_pseudo_rand(BIGNUM *rnd, int bits, int top,int bottom);
-int	BN_rand_range(BIGNUM *rnd, BIGNUM *range);
-int	BN_pseudo_rand_range(BIGNUM *rnd, BIGNUM *range);
+int	BN_rand_range(BIGNUM *rnd, const BIGNUM *range);
+int	BN_pseudo_rand_range(BIGNUM *rnd, const BIGNUM *range);
 int	BN_num_bits(const BIGNUM *a);
 int	BN_num_bits_word(BN_ULONG);
 BIGNUM *BN_new(void);
@@ -531,6 +531,17 @@ int	BN_is_prime_ex(const BIGNUM *p,int nchecks, BN_CTX *ctx, BN_GENCB *cb);
 int	BN_is_prime_fasttest_ex(const BIGNUM *p,int nchecks, BN_CTX *ctx,
 		int do_trial_division, BN_GENCB *cb);
 
+int BN_X931_generate_Xpq(BIGNUM *Xp, BIGNUM *Xq, int nbits, BN_CTX *ctx);
+
+int BN_X931_derive_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
+			const BIGNUM *Xp, const BIGNUM *Xp1, const BIGNUM *Xp2,
+			const BIGNUM *e, BN_CTX *ctx, BN_GENCB *cb);
+int BN_X931_generate_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
+			BIGNUM *Xp1, BIGNUM *Xp2,
+			const BIGNUM *Xp,
+			const BIGNUM *e, BN_CTX *ctx,
+			BN_GENCB *cb);
+
 BN_MONT_CTX *BN_MONT_CTX_new(void );
 void BN_MONT_CTX_init(BN_MONT_CTX *ctx);
 int BN_mod_mul_montgomery(BIGNUM *r,const BIGNUM *a,const BIGNUM *b,
diff --git a/src/lib/libcrypto/bn/bn_div.c b/src/lib/libcrypto/bn/bn_div.c
index 8655eb118e..1e8e57626b 100644
--- a/src/lib/libcrypto/bn/bn_div.c
+++ b/src/lib/libcrypto/bn/bn_div.c
@@ -187,6 +187,17 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
 	BN_ULONG d0,d1;
 	int num_n,div_n;
 
+	/* Invalid zero-padding would have particularly bad consequences
+	 * in the case of 'num', so don't just rely on bn_check_top() for this one
+	 * (bn_check_top() works only for BN_DEBUG builds) */
+	if (num->top > 0 && num->d[num->top - 1] == 0)
+		{
+		BNerr(BN_F_BN_DIV,BN_R_NOT_INITIALIZED);
+		return 0;
+		}
+
+	bn_check_top(num);
+
 	if ((BN_get_flags(num, BN_FLG_CONSTTIME) != 0) || (BN_get_flags(divisor, BN_FLG_CONSTTIME) != 0))
 		{
 		return BN_div_no_branch(dv, rm, num, divisor, ctx);
@@ -194,7 +205,7 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
 
 	bn_check_top(dv);
 	bn_check_top(rm);
-	bn_check_top(num);
+	/* bn_check_top(num); */ /* 'num' has been checked already */
 	bn_check_top(divisor);
 
 	if (BN_is_zero(divisor))
@@ -419,7 +430,7 @@ static int BN_div_no_branch(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num,
 
 	bn_check_top(dv);
 	bn_check_top(rm);
-	bn_check_top(num);
+	/* bn_check_top(num); */ /* 'num' has been checked in BN_div() */
 	bn_check_top(divisor);
 
 	if (BN_is_zero(divisor))
diff --git a/src/lib/libcrypto/bn/bn_gf2m.c b/src/lib/libcrypto/bn/bn_gf2m.c
index 6a793857e1..306f029f27 100644
--- a/src/lib/libcrypto/bn/bn_gf2m.c
+++ b/src/lib/libcrypto/bn/bn_gf2m.c
@@ -384,7 +384,11 @@ int BN_GF2m_mod_arr(BIGNUM *r, const BIGNUM *a, const unsigned int p[])
 		if (zz == 0) break;
 		d1 = BN_BITS2 - d0;
 		
-		if (d0) z[dN] = (z[dN] << d1) >> d1; /* clear up the top d1 bits */
+		/* clear up the top d1 bits */
+		if (d0)
+			z[dN] = (z[dN] << d1) >> d1;
+		else
+			z[dN] = 0;
 		z[0] ^= zz; /* reduction t^0 component */
 
 		for (k = 1; p[k] != 0; k++)
diff --git a/src/lib/libcrypto/bn/bn_lib.c b/src/lib/libcrypto/bn/bn_lib.c
index 2649b8c538..32a8fbaf51 100644
--- a/src/lib/libcrypto/bn/bn_lib.c
+++ b/src/lib/libcrypto/bn/bn_lib.c
@@ -139,25 +139,6 @@ const BIGNUM *BN_value_one(void)
 	return(&const_one);
 	}
 
-char *BN_options(void)
-	{
-	static int init=0;
-	static char data[16];
-
-	if (!init)
-		{
-		init++;
-#ifdef BN_LLONG
-		BIO_snprintf(data,sizeof data,"bn(%d,%d)",
-			     (int)sizeof(BN_ULLONG)*8,(int)sizeof(BN_ULONG)*8);
-#else
-		BIO_snprintf(data,sizeof data,"bn(%d,%d)",
-			     (int)sizeof(BN_ULONG)*8,(int)sizeof(BN_ULONG)*8);
-#endif
-		}
-	return(data);
-	}
-
 int BN_num_bits_word(BN_ULONG l)
 	{
 	static const char bits[256]={
diff --git a/src/lib/libcrypto/bn/bn_nist.c b/src/lib/libcrypto/bn/bn_nist.c
index e14232fdbb..2ca5b01391 100644
--- a/src/lib/libcrypto/bn/bn_nist.c
+++ b/src/lib/libcrypto/bn/bn_nist.c
@@ -59,109 +59,266 @@
 #include "bn_lcl.h"
 #include "cryptlib.h"
 
+
 #define BN_NIST_192_TOP	(192+BN_BITS2-1)/BN_BITS2
 #define BN_NIST_224_TOP	(224+BN_BITS2-1)/BN_BITS2
 #define BN_NIST_256_TOP	(256+BN_BITS2-1)/BN_BITS2
 #define BN_NIST_384_TOP	(384+BN_BITS2-1)/BN_BITS2
 #define BN_NIST_521_TOP	(521+BN_BITS2-1)/BN_BITS2
 
+/* pre-computed tables are "carry-less" values of modulus*(i+1) */
 #if BN_BITS2 == 64
-static const BN_ULONG _nist_p_192[] =
-	{0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFEULL,
-	0xFFFFFFFFFFFFFFFFULL};
-static const BN_ULONG _nist_p_224[] =
+static const BN_ULONG _nist_p_192[][BN_NIST_192_TOP] = {
+	{0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFEULL,0xFFFFFFFFFFFFFFFFULL},
+	{0xFFFFFFFFFFFFFFFEULL,0xFFFFFFFFFFFFFFFDULL,0xFFFFFFFFFFFFFFFFULL},
+	{0xFFFFFFFFFFFFFFFDULL,0xFFFFFFFFFFFFFFFCULL,0xFFFFFFFFFFFFFFFFULL}
+	};
+static const BN_ULONG _nist_p_192_sqr[] = {
+	0x0000000000000001ULL,0x0000000000000002ULL,0x0000000000000001ULL,
+	0xFFFFFFFFFFFFFFFEULL,0xFFFFFFFFFFFFFFFDULL,0xFFFFFFFFFFFFFFFFULL
+	};
+static const BN_ULONG _nist_p_224[][BN_NIST_224_TOP] = {
 	{0x0000000000000001ULL,0xFFFFFFFF00000000ULL,
-	0xFFFFFFFFFFFFFFFFULL,0x00000000FFFFFFFFULL};
-static const BN_ULONG _nist_p_256[] =
+	 0xFFFFFFFFFFFFFFFFULL,0x00000000FFFFFFFFULL},
+	{0x0000000000000002ULL,0xFFFFFFFE00000000ULL,
+	 0xFFFFFFFFFFFFFFFFULL,0x00000001FFFFFFFFULL} /* this one is "carry-full" */
+	};
+static const BN_ULONG _nist_p_224_sqr[] = {
+	0x0000000000000001ULL,0xFFFFFFFE00000000ULL,
+	0xFFFFFFFFFFFFFFFFULL,0x0000000200000000ULL,
+	0x0000000000000000ULL,0xFFFFFFFFFFFFFFFEULL,
+	0xFFFFFFFFFFFFFFFFULL
+	};
+static const BN_ULONG _nist_p_256[][BN_NIST_256_TOP] = {
 	{0xFFFFFFFFFFFFFFFFULL,0x00000000FFFFFFFFULL,
-	0x0000000000000000ULL,0xFFFFFFFF00000001ULL};
-static const BN_ULONG _nist_p_384[] =
-	{0x00000000FFFFFFFFULL,0xFFFFFFFF00000000ULL,
-	0xFFFFFFFFFFFFFFFEULL,0xFFFFFFFFFFFFFFFFULL,
-	0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL};
+	 0x0000000000000000ULL,0xFFFFFFFF00000001ULL},
+	{0xFFFFFFFFFFFFFFFEULL,0x00000001FFFFFFFFULL,
+	 0x0000000000000000ULL,0xFFFFFFFE00000002ULL},
+	{0xFFFFFFFFFFFFFFFDULL,0x00000002FFFFFFFFULL,
+	 0x0000000000000000ULL,0xFFFFFFFD00000003ULL},
+	{0xFFFFFFFFFFFFFFFCULL,0x00000003FFFFFFFFULL,
+	 0x0000000000000000ULL,0xFFFFFFFC00000004ULL},
+	{0xFFFFFFFFFFFFFFFBULL,0x00000004FFFFFFFFULL,
+	 0x0000000000000000ULL,0xFFFFFFFB00000005ULL},
+	};
+static const BN_ULONG _nist_p_256_sqr[] = {
+	0x0000000000000001ULL,0xFFFFFFFE00000000ULL,
+	0xFFFFFFFFFFFFFFFFULL,0x00000001FFFFFFFEULL,
+	0x00000001FFFFFFFEULL,0x00000001FFFFFFFEULL,
+	0xFFFFFFFE00000001ULL,0xFFFFFFFE00000002ULL
+	};
+static const BN_ULONG _nist_p_384[][BN_NIST_384_TOP] = {
+	{0x00000000FFFFFFFFULL,0xFFFFFFFF00000000ULL,0xFFFFFFFFFFFFFFFEULL,
+	 0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL},
+	{0x00000001FFFFFFFEULL,0xFFFFFFFE00000000ULL,0xFFFFFFFFFFFFFFFDULL,
+	 0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL},
+	{0x00000002FFFFFFFDULL,0xFFFFFFFD00000000ULL,0xFFFFFFFFFFFFFFFCULL,
+	 0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL},
+	{0x00000003FFFFFFFCULL,0xFFFFFFFC00000000ULL,0xFFFFFFFFFFFFFFFBULL,
+	 0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL},
+	{0x00000004FFFFFFFBULL,0xFFFFFFFB00000000ULL,0xFFFFFFFFFFFFFFFAULL,
+	 0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL},
+	};
+static const BN_ULONG _nist_p_384_sqr[] = {
+	0xFFFFFFFE00000001ULL,0x0000000200000000ULL,0xFFFFFFFE00000000ULL,
+	0x0000000200000000ULL,0x0000000000000001ULL,0x0000000000000000ULL,
+	0x00000001FFFFFFFEULL,0xFFFFFFFE00000000ULL,0xFFFFFFFFFFFFFFFDULL,
+	0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL
+	};
 static const BN_ULONG _nist_p_521[] =
 	{0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,
 	0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,
 	0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,
 	0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,
 	0x00000000000001FFULL};
+static const BN_ULONG _nist_p_521_sqr[] = {
+	0x0000000000000001ULL,0x0000000000000000ULL,0x0000000000000000ULL,
+	0x0000000000000000ULL,0x0000000000000000ULL,0x0000000000000000ULL,
+	0x0000000000000000ULL,0x0000000000000000ULL,0xFFFFFFFFFFFFFC00ULL,
+	0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,
+	0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,
+	0xFFFFFFFFFFFFFFFFULL,0x000000000003FFFFULL
+	};
 #elif BN_BITS2 == 32
-static const BN_ULONG _nist_p_192[] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFE,
-	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
-static const BN_ULONG _nist_p_224[] = {0x00000001,0x00000000,0x00000000,
-	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
-static const BN_ULONG _nist_p_256[] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
-	0x00000000,0x00000000,0x00000000,0x00000001,0xFFFFFFFF};
-static const BN_ULONG _nist_p_384[] = {0xFFFFFFFF,0x00000000,0x00000000,
-	0xFFFFFFFF,0xFFFFFFFE,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
-	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
+static const BN_ULONG _nist_p_192[][BN_NIST_192_TOP] = {
+	{0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFE,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
+	{0xFFFFFFFE,0xFFFFFFFF,0xFFFFFFFD,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
+	{0xFFFFFFFD,0xFFFFFFFF,0xFFFFFFFC,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}
+	};
+static const BN_ULONG _nist_p_192_sqr[] = {
+	0x00000001,0x00000000,0x00000002,0x00000000,0x00000001,0x00000000,
+	0xFFFFFFFE,0xFFFFFFFF,0xFFFFFFFD,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF
+	};
+static const BN_ULONG _nist_p_224[][BN_NIST_224_TOP] = {
+	{0x00000001,0x00000000,0x00000000,0xFFFFFFFF,
+	 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
+	{0x00000002,0x00000000,0x00000000,0xFFFFFFFE,
+	 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}
+	};
+static const BN_ULONG _nist_p_224_sqr[] = {
+	0x00000001,0x00000000,0x00000000,0xFFFFFFFE,
+	0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000002,
+	0x00000000,0x00000000,0xFFFFFFFE,0xFFFFFFFF,
+	0xFFFFFFFF,0xFFFFFFFF
+	};
+static const BN_ULONG _nist_p_256[][BN_NIST_256_TOP] = {
+	{0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0x00000000,
+	 0x00000000,0x00000000,0x00000001,0xFFFFFFFF},
+	{0xFFFFFFFE,0xFFFFFFFF,0xFFFFFFFF,0x00000001,
+	 0x00000000,0x00000000,0x00000002,0xFFFFFFFE},
+	{0xFFFFFFFD,0xFFFFFFFF,0xFFFFFFFF,0x00000002,
+	 0x00000000,0x00000000,0x00000003,0xFFFFFFFD},
+	{0xFFFFFFFC,0xFFFFFFFF,0xFFFFFFFF,0x00000003,
+	 0x00000000,0x00000000,0x00000004,0xFFFFFFFC},
+	{0xFFFFFFFB,0xFFFFFFFF,0xFFFFFFFF,0x00000004,
+	 0x00000000,0x00000000,0x00000005,0xFFFFFFFB},
+	};
+static const BN_ULONG _nist_p_256_sqr[] = {
+	0x00000001,0x00000000,0x00000000,0xFFFFFFFE,
+	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFE,0x00000001,
+	0xFFFFFFFE,0x00000001,0xFFFFFFFE,0x00000001,
+	0x00000001,0xFFFFFFFE,0x00000002,0xFFFFFFFE
+	};
+static const BN_ULONG _nist_p_384[][BN_NIST_384_TOP] = {
+	{0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFE,0xFFFFFFFF,
+	 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
+	{0xFFFFFFFE,0x00000001,0x00000000,0xFFFFFFFE,0xFFFFFFFD,0xFFFFFFFF,
+	 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
+	{0xFFFFFFFD,0x00000002,0x00000000,0xFFFFFFFD,0xFFFFFFFC,0xFFFFFFFF,
+	 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
+	{0xFFFFFFFC,0x00000003,0x00000000,0xFFFFFFFC,0xFFFFFFFB,0xFFFFFFFF,
+	 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
+	{0xFFFFFFFB,0x00000004,0x00000000,0xFFFFFFFB,0xFFFFFFFA,0xFFFFFFFF,
+	 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
+	};
+static const BN_ULONG _nist_p_384_sqr[] = {
+	0x00000001,0xFFFFFFFE,0x00000000,0x00000002,0x00000000,0xFFFFFFFE,
+	0x00000000,0x00000002,0x00000001,0x00000000,0x00000000,0x00000000,
+	0xFFFFFFFE,0x00000001,0x00000000,0xFFFFFFFE,0xFFFFFFFD,0xFFFFFFFF,
+	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF
+	};
 static const BN_ULONG _nist_p_521[] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
 	0xFFFFFFFF,0x000001FF};
+static const BN_ULONG _nist_p_521_sqr[] = {
+	0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
+	0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
+	0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFC00,0xFFFFFFFF,
+	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
+	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
+	0xFFFFFFFF,0xFFFFFFFF,0x0003FFFF
+	};
+#else
+#error "unsupported BN_BITS2"
 #endif
 
+
+static const BIGNUM _bignum_nist_p_192 =
+	{
+	(BN_ULONG *)_nist_p_192[0],
+	BN_NIST_192_TOP,
+	BN_NIST_192_TOP,
+	0,
+	BN_FLG_STATIC_DATA
+	};
+
+static const BIGNUM _bignum_nist_p_224 =
+	{
+	(BN_ULONG *)_nist_p_224[0],
+	BN_NIST_224_TOP,
+	BN_NIST_224_TOP,
+	0,
+	BN_FLG_STATIC_DATA
+	};
+
+static const BIGNUM _bignum_nist_p_256 =
+	{
+	(BN_ULONG *)_nist_p_256[0],
+	BN_NIST_256_TOP,
+	BN_NIST_256_TOP,
+	0,
+	BN_FLG_STATIC_DATA
+	};
+
+static const BIGNUM _bignum_nist_p_384 =
+	{
+	(BN_ULONG *)_nist_p_384[0],
+	BN_NIST_384_TOP,
+	BN_NIST_384_TOP,
+	0,
+	BN_FLG_STATIC_DATA
+	};
+
+static const BIGNUM _bignum_nist_p_521 =
+	{
+	(BN_ULONG *)_nist_p_521,
+	BN_NIST_521_TOP,
+	BN_NIST_521_TOP,
+	0,
+	BN_FLG_STATIC_DATA
+	};
+
+
 const BIGNUM *BN_get0_nist_prime_192(void)
 	{
-	static BIGNUM const_nist_192 = { (BN_ULONG *)_nist_p_192,
-		BN_NIST_192_TOP, BN_NIST_192_TOP, 0, BN_FLG_STATIC_DATA };
-	return &const_nist_192;
+	return &_bignum_nist_p_192;
 	}
 
 const BIGNUM *BN_get0_nist_prime_224(void)
 	{
-	static BIGNUM const_nist_224 = { (BN_ULONG *)_nist_p_224,
-		BN_NIST_224_TOP, BN_NIST_224_TOP, 0, BN_FLG_STATIC_DATA };
-	return &const_nist_224;
+	return &_bignum_nist_p_224;
 	}
 
 const BIGNUM *BN_get0_nist_prime_256(void)
 	{
-	static BIGNUM const_nist_256 = { (BN_ULONG *)_nist_p_256,
-		BN_NIST_256_TOP, BN_NIST_256_TOP, 0, BN_FLG_STATIC_DATA };
-	return &const_nist_256;
+	return &_bignum_nist_p_256;
 	}
 
 const BIGNUM *BN_get0_nist_prime_384(void)
 	{
-	static BIGNUM const_nist_384 = { (BN_ULONG *)_nist_p_384,
-		BN_NIST_384_TOP, BN_NIST_384_TOP, 0, BN_FLG_STATIC_DATA };
-	return &const_nist_384;
+	return &_bignum_nist_p_384;
 	}
 
 const BIGNUM *BN_get0_nist_prime_521(void)
 	{
-	static BIGNUM const_nist_521 = { (BN_ULONG *)_nist_p_521,
-		BN_NIST_521_TOP, BN_NIST_521_TOP, 0, BN_FLG_STATIC_DATA };
-	return &const_nist_521;
+	return &_bignum_nist_p_521;
 	}
 
-#define BN_NIST_ADD_ONE(a)	while (!(*(a)=(*(a)+1)&BN_MASK2)) ++(a);
 
 static void nist_cp_bn_0(BN_ULONG *buf, BN_ULONG *a, int top, int max)
-        {
+	{
 	int i;
-        BN_ULONG *_tmp1 = (buf), *_tmp2 = (a);
-        for (i = (top); i != 0; i--)
-                *_tmp1++ = *_tmp2++;
-        for (i = (max) - (top); i != 0; i--)
-                *_tmp1++ = (BN_ULONG) 0;
-        }
+	BN_ULONG *_tmp1 = (buf), *_tmp2 = (a);
+
+#ifdef BN_DEBUG
+	OPENSSL_assert(top <= max);
+#endif
+	for (i = (top); i != 0; i--)
+		*_tmp1++ = *_tmp2++;
+	for (i = (max) - (top); i != 0; i--)
+		*_tmp1++ = (BN_ULONG) 0;
+	}
 
 static void nist_cp_bn(BN_ULONG *buf, BN_ULONG *a, int top)
-        { 
+	{ 
 	int i;
-        BN_ULONG *_tmp1 = (buf), *_tmp2 = (a);
-        for (i = (top); i != 0; i--)
-                *_tmp1++ = *_tmp2++;
-        }
+	BN_ULONG *_tmp1 = (buf), *_tmp2 = (a);
+	for (i = (top); i != 0; i--)
+		*_tmp1++ = *_tmp2++;
+	}
 
 #if BN_BITS2 == 64
 #define bn_cp_64(to, n, from, m)	(to)[n] = (m>=0)?((from)[m]):0;
 #define bn_64_set_0(to, n)		(to)[n] = (BN_ULONG)0;
-/* TBD */
-#define bn_cp_32(to, n, from, m)	(to)[n] = (m>=0)?((from)[m]):0;
-#define bn_32_set_0(to, n)		(to)[n] = (BN_ULONG)0;
+/*
+ * two following macros are implemented under assumption that they
+ * are called in a sequence with *ascending* n, i.e. as they are...
+ */
+#define bn_cp_32_naked(to, n, from, m)	(((n)&1)?(to[(n)/2]|=((m)&1)?(from[(m)/2]&BN_MASK2h):(from[(m)/2]<<32))\
+						:(to[(n)/2] =((m)&1)?(from[(m)/2]>>32):(from[(m)/2]&BN_MASK2l)))
+#define bn_32_set_0(to, n)		(((n)&1)?(to[(n)/2]&=BN_MASK2l):(to[(n)/2]=0));
+#define bn_cp_32(to,n,from,m)		((m)>=0)?bn_cp_32_naked(to,n,from,m):bn_32_set_0(to,n)
 #else
 #define bn_cp_64(to, n, from, m) \
 	{ \
@@ -182,9 +339,9 @@ static void nist_cp_bn(BN_ULONG *buf, BN_ULONG *a, int top)
 
 #define nist_set_192(to, from, a1, a2, a3) \
 	{ \
-	if (a3 != 0) bn_cp_64(to, 0, from, (a3) - 3) else bn_64_set_0(to, 0)\
+	bn_cp_64(to, 0, from, (a3) - 3) \
 	bn_cp_64(to, 1, from, (a2) - 3) \
-	if (a1 != 0) bn_cp_64(to, 2, from, (a1) - 3) else bn_64_set_0(to, 2)\
+	bn_cp_64(to, 2, from, (a1) - 3) \
 	}
 
 int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
@@ -198,6 +355,16 @@ int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
 		 c_d[BN_NIST_192_TOP],
 		*res;
 	size_t   mask;
+	static const BIGNUM _bignum_nist_p_192_sqr = {
+		(BN_ULONG *)_nist_p_192_sqr,
+		sizeof(_nist_p_192_sqr)/sizeof(_nist_p_192_sqr[0]),
+		sizeof(_nist_p_192_sqr)/sizeof(_nist_p_192_sqr[0]),
+		0,BN_FLG_STATIC_DATA };
+
+	field = &_bignum_nist_p_192; /* just to make sure */
+
+ 	if (BN_is_negative(a) || BN_ucmp(a,&_bignum_nist_p_192_sqr)>=0)
+		return BN_nnmod(r, a, field, ctx);
 
 	i = BN_ucmp(field, a);
 	if (i == 0)
@@ -208,9 +375,6 @@ int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
 	else if (i > 0)
 		return (r == a) ? 1 : (BN_copy(r ,a) != NULL);
 
-	if (top == BN_NIST_192_TOP)
-		return BN_usub(r, a, field);
-
 	if (r != a)
 		{
 		if (!bn_wexpand(r, BN_NIST_192_TOP))
@@ -224,23 +388,26 @@ int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
 	nist_cp_bn_0(buf, a_d + BN_NIST_192_TOP, top - BN_NIST_192_TOP, BN_NIST_192_TOP);
 
 	nist_set_192(t_d, buf, 0, 3, 3);
-	carry = bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP);
-	mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_192,BN_NIST_192_TOP);
-	mask = ~mask | (0-(size_t)carry);
-	res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
-	
+	carry = (int)bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP);
 	nist_set_192(t_d, buf, 4, 4, 0);
-	carry = bn_add_words(r_d, res, t_d, BN_NIST_192_TOP);
-	mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_192,BN_NIST_192_TOP);
-	mask = ~mask | (0-(size_t)carry);
-	res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
-
+	carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP);
 	nist_set_192(t_d, buf, 5, 5, 5)
-	carry = bn_add_words(r_d, res, t_d, BN_NIST_192_TOP);
-	mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_192,BN_NIST_192_TOP);
-	mask = ~mask | (0-(size_t)carry);
-	res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
+	carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP);
 
+	if (carry > 0)
+		carry = (int)bn_sub_words(r_d,r_d,_nist_p_192[carry-1],BN_NIST_192_TOP);
+	else
+		carry = 1;
+
+	/*
+	 * we need 'if (carry==0 || result>=modulus) result-=modulus;'
+	 * as comparison implies subtraction, we can write
+	 * 'tmp=result-modulus; if (!carry || !borrow) result=tmp;'
+	 * this is what happens below, but without explicit if:-) a.
+	 */
+	mask  = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_192[0],BN_NIST_192_TOP);
+	mask &= 0-(size_t)carry;
+	res   = (BN_ULONG *)(((size_t)c_d&~mask) | ((size_t)r_d&mask));
 	nist_cp_bn(r_d, res, BN_NIST_192_TOP);
 	r->top = BN_NIST_192_TOP;
 	bn_correct_top(r);
@@ -248,21 +415,22 @@ int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
 	return 1;
 	}
 
+typedef BN_ULONG (*bn_addsub_f)(BN_ULONG *,const BN_ULONG *,const BN_ULONG *,int);
+
 #define nist_set_224(to, from, a1, a2, a3, a4, a5, a6, a7) \
 	{ \
-	if (a7 != 0) bn_cp_32(to, 0, from, (a7) - 7) else bn_32_set_0(to, 0)\
-	if (a6 != 0) bn_cp_32(to, 1, from, (a6) - 7) else bn_32_set_0(to, 1)\
-	if (a5 != 0) bn_cp_32(to, 2, from, (a5) - 7) else bn_32_set_0(to, 2)\
-	if (a4 != 0) bn_cp_32(to, 3, from, (a4) - 7) else bn_32_set_0(to, 3)\
-	if (a3 != 0) bn_cp_32(to, 4, from, (a3) - 7) else bn_32_set_0(to, 4)\
-	if (a2 != 0) bn_cp_32(to, 5, from, (a2) - 7) else bn_32_set_0(to, 5)\
-	if (a1 != 0) bn_cp_32(to, 6, from, (a1) - 7) else bn_32_set_0(to, 6)\
+	bn_cp_32(to, 0, from, (a7) - 7) \
+	bn_cp_32(to, 1, from, (a6) - 7) \
+	bn_cp_32(to, 2, from, (a5) - 7) \
+	bn_cp_32(to, 3, from, (a4) - 7) \
+	bn_cp_32(to, 4, from, (a3) - 7) \
+	bn_cp_32(to, 5, from, (a2) - 7) \
+	bn_cp_32(to, 6, from, (a1) - 7) \
 	}
 
 int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
 	BN_CTX *ctx)
 	{
-#if BN_BITS2 == 32
 	int	top = a->top, i;
 	int	carry;
 	BN_ULONG *r_d, *a_d = a->d;
@@ -271,6 +439,18 @@ int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
 		 c_d[BN_NIST_224_TOP],
 		*res;
 	size_t   mask;
+	union { bn_addsub_f f; size_t p; } u;
+	static const BIGNUM _bignum_nist_p_224_sqr = {
+		(BN_ULONG *)_nist_p_224_sqr,
+		sizeof(_nist_p_224_sqr)/sizeof(_nist_p_224_sqr[0]),
+		sizeof(_nist_p_224_sqr)/sizeof(_nist_p_224_sqr[0]),
+		0,BN_FLG_STATIC_DATA };
+
+
+	field = &_bignum_nist_p_224; /* just to make sure */
+
+ 	if (BN_is_negative(a) || BN_ucmp(a,&_bignum_nist_p_224_sqr)>=0)
+		return BN_nnmod(r, a, field, ctx);
 
 	i = BN_ucmp(field, a);
 	if (i == 0)
@@ -281,9 +461,6 @@ int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
 	else if (i > 0)
 		return (r == a)? 1 : (BN_copy(r ,a) != NULL);
 
-	if (top == BN_NIST_224_TOP)
-		return BN_usub(r, a, field);
-
 	if (r != a)
 		{
 		if (!bn_wexpand(r, BN_NIST_224_TOP))
@@ -294,67 +471,77 @@ int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
 	else
 		r_d = a_d;
 
+#if BN_BITS2==64
+	/* copy upper 256 bits of 448 bit number ... */
+	nist_cp_bn_0(t_d, a_d + (BN_NIST_224_TOP-1), top - (BN_NIST_224_TOP-1), BN_NIST_224_TOP);
+	/* ... and right shift by 32 to obtain upper 224 bits */
+	nist_set_224(buf, t_d, 14, 13, 12, 11, 10, 9, 8);
+	/* truncate lower part to 224 bits too */
+	r_d[BN_NIST_224_TOP-1] &= BN_MASK2l;
+#else
 	nist_cp_bn_0(buf, a_d + BN_NIST_224_TOP, top - BN_NIST_224_TOP, BN_NIST_224_TOP);
-
+#endif
 	nist_set_224(t_d, buf, 10, 9, 8, 7, 0, 0, 0);
-	carry = bn_add_words(r_d, r_d, t_d, BN_NIST_224_TOP);
-	mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_224,BN_NIST_224_TOP);
-	mask = ~mask | (0-(size_t)carry);
-	res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
-	
+	carry = (int)bn_add_words(r_d, r_d, t_d, BN_NIST_224_TOP);
 	nist_set_224(t_d, buf, 0, 13, 12, 11, 0, 0, 0);
-	carry = bn_add_words(r_d, res, t_d, BN_NIST_224_TOP);
-	mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_224,BN_NIST_224_TOP);
-	mask = ~mask | (0-(size_t)carry);
-	res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
-
+	carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_224_TOP);
 	nist_set_224(t_d, buf, 13, 12, 11, 10, 9, 8, 7);
-#if BRANCH_FREE
-	carry = bn_sub_words(r_d, res, t_d, BN_NIST_224_TOP);
-	bn_add_words(c_d,r_d,_nist_p_224,BN_NIST_224_TOP);
-	mask = 0-(size_t)carry;
-	res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
-#else
-	if (bn_sub_words(r_d, res, t_d, BN_NIST_224_TOP))
-		bn_add_words(r_d,r_d,_nist_p_224,BN_NIST_224_TOP);
-#endif
+	carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_224_TOP);
 	nist_set_224(t_d, buf, 0, 0, 0, 0, 13, 12, 11);
-#if BRANCH_FREE
-	carry = bn_sub_words(r_d, res, t_d, BN_NIST_224_TOP);
-	bn_add_words(c_d,r_d,_nist_p_224,BN_NIST_224_TOP);
-	mask = 0-(size_t)carry;
-	res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
+	carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_224_TOP);
 
-	nist_cp_bn(r_d, res, BN_NIST_224_TOP);
-#else
-	if (bn_sub_words(r_d, r_d, t_d, BN_NIST_224_TOP))
-		bn_add_words(r_d,r_d,_nist_p_224,BN_NIST_224_TOP);
+#if BN_BITS2==64
+	carry = (int)(r_d[BN_NIST_224_TOP-1]>>32);
+#endif
+	u.f = bn_sub_words;
+	if (carry > 0)
+		{
+		carry = (int)bn_sub_words(r_d,r_d,_nist_p_224[carry-1],BN_NIST_224_TOP);
+#if BN_BITS2==64
+		carry=(int)(~(r_d[BN_NIST_224_TOP-1]>>32))&1;
 #endif
+		}
+	else if (carry < 0)
+		{
+		/* it's a bit more comlicated logic in this case.
+		 * if bn_add_words yields no carry, then result
+		 * has to be adjusted by unconditionally *adding*
+		 * the modulus. but if it does, then result has
+		 * to be compared to the modulus and conditionally
+		 * adjusted by *subtracting* the latter. */
+		carry = (int)bn_add_words(r_d,r_d,_nist_p_224[-carry-1],BN_NIST_224_TOP);
+		mask = 0-(size_t)carry;
+		u.p = ((size_t)bn_sub_words&mask) | ((size_t)bn_add_words&~mask);
+		}
+	else
+		carry = 1;
+
+	/* otherwise it's effectively same as in BN_nist_mod_192... */
+	mask  = 0-(size_t)(*u.f)(c_d,r_d,_nist_p_224[0],BN_NIST_224_TOP);
+	mask &= 0-(size_t)carry;
+	res   = (BN_ULONG *)(((size_t)c_d&~mask) | ((size_t)r_d&mask));
+	nist_cp_bn(r_d, res, BN_NIST_224_TOP);
 	r->top = BN_NIST_224_TOP;
 	bn_correct_top(r);
 
 	return 1;
-#else	/* BN_BITS!=32 */
-	return 0;
-#endif
 	}
 
 #define nist_set_256(to, from, a1, a2, a3, a4, a5, a6, a7, a8) \
 	{ \
-	if (a8 != 0) bn_cp_32(to, 0, from, (a8) - 8) else bn_32_set_0(to, 0)\
-	if (a7 != 0) bn_cp_32(to, 1, from, (a7) - 8) else bn_32_set_0(to, 1)\
-	if (a6 != 0) bn_cp_32(to, 2, from, (a6) - 8) else bn_32_set_0(to, 2)\
-	if (a5 != 0) bn_cp_32(to, 3, from, (a5) - 8) else bn_32_set_0(to, 3)\
-	if (a4 != 0) bn_cp_32(to, 4, from, (a4) - 8) else bn_32_set_0(to, 4)\
-	if (a3 != 0) bn_cp_32(to, 5, from, (a3) - 8) else bn_32_set_0(to, 5)\
-	if (a2 != 0) bn_cp_32(to, 6, from, (a2) - 8) else bn_32_set_0(to, 6)\
-	if (a1 != 0) bn_cp_32(to, 7, from, (a1) - 8) else bn_32_set_0(to, 7)\
+	bn_cp_32(to, 0, from, (a8) - 8) \
+	bn_cp_32(to, 1, from, (a7) - 8) \
+	bn_cp_32(to, 2, from, (a6) - 8) \
+	bn_cp_32(to, 3, from, (a5) - 8) \
+	bn_cp_32(to, 4, from, (a4) - 8) \
+	bn_cp_32(to, 5, from, (a3) - 8) \
+	bn_cp_32(to, 6, from, (a2) - 8) \
+	bn_cp_32(to, 7, from, (a1) - 8) \
 	}
 
 int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
 	BN_CTX *ctx)
 	{
-#if BN_BITS2 == 32
 	int	i, top = a->top;
 	int	carry = 0;
 	register BN_ULONG *a_d = a->d, *r_d;
@@ -363,6 +550,17 @@ int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
 		 c_d[BN_NIST_256_TOP],
 		*res;
 	size_t   mask;
+	union { bn_addsub_f f; size_t p; } u;
+	static const BIGNUM _bignum_nist_p_256_sqr = {
+		(BN_ULONG *)_nist_p_256_sqr,
+		sizeof(_nist_p_256_sqr)/sizeof(_nist_p_256_sqr[0]),
+		sizeof(_nist_p_256_sqr)/sizeof(_nist_p_256_sqr[0]),
+		0,BN_FLG_STATIC_DATA };
+
+	field = &_bignum_nist_p_256; /* just to make sure */
+
+ 	if (BN_is_negative(a) || BN_ucmp(a,&_bignum_nist_p_256_sqr)>=0)
+		return BN_nnmod(r, a, field, ctx);
 
 	i = BN_ucmp(field, a);
 	if (i == 0)
@@ -373,9 +571,6 @@ int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
 	else if (i > 0)
 		return (r == a)? 1 : (BN_copy(r ,a) != NULL);
 
-	if (top == BN_NIST_256_TOP)
-		return BN_usub(r, a, field);
-
 	if (r != a)
 		{
 		if (!bn_wexpand(r, BN_NIST_256_TOP))
@@ -391,111 +586,84 @@ int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
 	/*S1*/
 	nist_set_256(t_d, buf, 15, 14, 13, 12, 11, 0, 0, 0);
 	/*S2*/
-	nist_set_256(c_d,buf, 0, 15, 14, 13, 12, 0, 0, 0);
-	carry = bn_add_words(t_d, t_d, c_d, BN_NIST_256_TOP);
-	mask = 0-(size_t)bn_sub_words(c_d,t_d,_nist_p_256,BN_NIST_256_TOP);
-	mask = ~mask | (0-(size_t)carry);
-	res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)t_d&~mask));
-
-	carry = bn_add_words(t_d, res, res, BN_NIST_256_TOP);
-	mask = 0-(size_t)bn_sub_words(c_d,t_d,_nist_p_256,BN_NIST_256_TOP);
-	mask = ~mask | (0-(size_t)carry);
-	res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)t_d&~mask));
-
-	carry = bn_add_words(r_d, r_d, res, BN_NIST_256_TOP);
-	mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_256,BN_NIST_256_TOP);
-	mask = ~mask | (0-(size_t)carry);
-	res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
-
+	nist_set_256(c_d, buf, 0, 15, 14, 13, 12, 0, 0, 0);
+	carry = (int)bn_add_words(t_d, t_d, c_d, BN_NIST_256_TOP);
+	/* left shift */
+		{
+		register BN_ULONG *ap,t,c;
+		ap = t_d;
+		c=0;
+		for (i = BN_NIST_256_TOP; i != 0; --i)
+			{
+			t= *ap;
+			*(ap++)=((t<<1)|c)&BN_MASK2;
+			c=(t & BN_TBIT)?1:0;
+			}
+		carry <<= 1;
+		carry  |= c;
+		}
+	carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP);
 	/*S3*/
 	nist_set_256(t_d, buf, 15, 14, 0, 0, 0, 10, 9, 8);
-	carry = bn_add_words(r_d, res, t_d, BN_NIST_256_TOP);
-	mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_256,BN_NIST_256_TOP);
-	mask = ~mask | (0-(size_t)carry);
-	res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
-
+	carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP);
 	/*S4*/
 	nist_set_256(t_d, buf, 8, 13, 15, 14, 13, 11, 10, 9);
-	carry = bn_add_words(r_d, res, t_d, BN_NIST_256_TOP);
-	mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_256,BN_NIST_256_TOP);
-	mask = ~mask | (0-(size_t)carry);
-	res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
-
+	carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP);
 	/*D1*/
 	nist_set_256(t_d, buf, 10, 8, 0, 0, 0, 13, 12, 11);
-#if BRANCH_FREE
-	carry = bn_sub_words(r_d, res, t_d, BN_NIST_256_TOP);
-	bn_add_words(c_d,r_d,_nist_p_256,BN_NIST_256_TOP);
-	mask = 0-(size_t)carry;
-	res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));	
-#else
-	if (bn_sub_words(r_d, res, t_d, BN_NIST_256_TOP))
-		bn_add_words(r_d,r_d,_nist_p_256,BN_NIST_256_TOP);
-#endif
+	carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP);
 	/*D2*/
 	nist_set_256(t_d, buf, 11, 9, 0, 0, 15, 14, 13, 12);
-#if BRANCH_FREE
-	carry = bn_sub_words(r_d, res, t_d, BN_NIST_256_TOP);
-	bn_add_words(c_d,r_d,_nist_p_256,BN_NIST_256_TOP);
-	mask = 0-(size_t)carry;
-	res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));	
-#else
-	if (bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP))
-		bn_add_words(r_d,r_d,_nist_p_256,BN_NIST_256_TOP);
-#endif
+	carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP);
 	/*D3*/
 	nist_set_256(t_d, buf, 12, 0, 10, 9, 8, 15, 14, 13);
-#if BRANCH_FREE
-	carry = bn_sub_words(r_d, res, t_d, BN_NIST_256_TOP);
-	bn_add_words(c_d,r_d,_nist_p_256,BN_NIST_256_TOP);
-	mask = 0-(size_t)carry;
-	res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));	
-#else
-	if (bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP))
-		bn_add_words(r_d,r_d,_nist_p_256,BN_NIST_256_TOP);
-#endif
+	carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP);
 	/*D4*/
 	nist_set_256(t_d, buf, 13, 0, 11, 10, 9, 0, 15, 14);
-#if BRANCH_FREE
-	carry = bn_sub_words(r_d, res, t_d, BN_NIST_256_TOP);
-	bn_add_words(c_d,r_d,_nist_p_256,BN_NIST_256_TOP);
-	mask = 0-(size_t)carry;
-	res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));	
+	carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP);
 
-	nist_cp_bn(r_d, res, BN_NIST_384_TOP);
-#else
-	if (bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP))
-		bn_add_words(r_d,r_d,_nist_p_256,BN_NIST_256_TOP);
-#endif
+	/* see BN_nist_mod_224 for explanation */
+	u.f = bn_sub_words;
+	if (carry > 0)
+		carry = (int)bn_sub_words(r_d,r_d,_nist_p_256[carry-1],BN_NIST_256_TOP);
+	else if (carry < 0)
+		{
+		carry = (int)bn_add_words(r_d,r_d,_nist_p_256[-carry-1],BN_NIST_256_TOP);
+		mask = 0-(size_t)carry;
+		u.p = ((size_t)bn_sub_words&mask) | ((size_t)bn_add_words&~mask);
+		}
+	else
+		carry = 1;
+
+	mask  = 0-(size_t)(*u.f)(c_d,r_d,_nist_p_256[0],BN_NIST_256_TOP);
+	mask &= 0-(size_t)carry;
+	res   = (BN_ULONG *)(((size_t)c_d&~mask) | ((size_t)r_d&mask));
+	nist_cp_bn(r_d, res, BN_NIST_256_TOP);
 	r->top = BN_NIST_256_TOP;
 	bn_correct_top(r);
 
 	return 1;
-#else	/* BN_BITS!=32 */
-	return 0;
-#endif
 	}
 
 #define nist_set_384(to,from,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12) \
 	{ \
-	if (a12 != 0) bn_cp_32(to, 0, from,  (a12) - 12) else bn_32_set_0(to, 0)\
-	if (a11 != 0) bn_cp_32(to, 1, from,  (a11) - 12) else bn_32_set_0(to, 1)\
-	if (a10 != 0) bn_cp_32(to, 2, from,  (a10) - 12) else bn_32_set_0(to, 2)\
-	if (a9 != 0)  bn_cp_32(to, 3, from,  (a9) - 12)  else bn_32_set_0(to, 3)\
-	if (a8 != 0)  bn_cp_32(to, 4, from,  (a8) - 12)  else bn_32_set_0(to, 4)\
-	if (a7 != 0)  bn_cp_32(to, 5, from,  (a7) - 12)  else bn_32_set_0(to, 5)\
-	if (a6 != 0)  bn_cp_32(to, 6, from,  (a6) - 12)  else bn_32_set_0(to, 6)\
-	if (a5 != 0)  bn_cp_32(to, 7, from,  (a5) - 12)  else bn_32_set_0(to, 7)\
-	if (a4 != 0)  bn_cp_32(to, 8, from,  (a4) - 12)  else bn_32_set_0(to, 8)\
-	if (a3 != 0)  bn_cp_32(to, 9, from,  (a3) - 12)  else bn_32_set_0(to, 9)\
-	if (a2 != 0)  bn_cp_32(to, 10, from, (a2) - 12)  else bn_32_set_0(to, 10)\
-	if (a1 != 0)  bn_cp_32(to, 11, from, (a1) - 12)  else bn_32_set_0(to, 11)\
+	bn_cp_32(to, 0, from,  (a12) - 12) \
+	bn_cp_32(to, 1, from,  (a11) - 12) \
+	bn_cp_32(to, 2, from,  (a10) - 12) \
+	bn_cp_32(to, 3, from,  (a9) - 12)  \
+	bn_cp_32(to, 4, from,  (a8) - 12)  \
+	bn_cp_32(to, 5, from,  (a7) - 12)  \
+	bn_cp_32(to, 6, from,  (a6) - 12)  \
+	bn_cp_32(to, 7, from,  (a5) - 12)  \
+	bn_cp_32(to, 8, from,  (a4) - 12)  \
+	bn_cp_32(to, 9, from,  (a3) - 12)  \
+	bn_cp_32(to, 10, from, (a2) - 12)  \
+	bn_cp_32(to, 11, from, (a1) - 12)  \
 	}
 
 int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
 	BN_CTX *ctx)
 	{
-#if BN_BITS2 == 32
 	int	i, top = a->top;
 	int	carry = 0;
 	register BN_ULONG *r_d, *a_d = a->d;
@@ -504,6 +672,18 @@ int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
 		 c_d[BN_NIST_384_TOP],
 		*res;
 	size_t	 mask;
+	union { bn_addsub_f f; size_t p; } u;
+	static const BIGNUM _bignum_nist_p_384_sqr = {
+		(BN_ULONG *)_nist_p_384_sqr,
+		sizeof(_nist_p_384_sqr)/sizeof(_nist_p_384_sqr[0]),
+		sizeof(_nist_p_384_sqr)/sizeof(_nist_p_384_sqr[0]),
+		0,BN_FLG_STATIC_DATA };
+
+
+	field = &_bignum_nist_p_384; /* just to make sure */
+
+ 	if (BN_is_negative(a) || BN_ucmp(a,&_bignum_nist_p_384_sqr)>=0)
+		return BN_nnmod(r, a, field, ctx);
 
 	i = BN_ucmp(field, a);
 	if (i == 0)
@@ -514,9 +694,6 @@ int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
 	else if (i > 0)
 		return (r == a)? 1 : (BN_copy(r ,a) != NULL);
 
-	if (top == BN_NIST_384_TOP)
-		return BN_usub(r, a, field);
-
 	if (r != a)
 		{
 		if (!bn_wexpand(r, BN_NIST_384_TOP))
@@ -544,149 +721,116 @@ int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
 			}
 		*ap=c;
 		}
-	carry = bn_add_words(r_d+(128/BN_BITS2), r_d+(128/BN_BITS2), 
+	carry = (int)bn_add_words(r_d+(128/BN_BITS2), r_d+(128/BN_BITS2), 
 		t_d, BN_NIST_256_TOP);
-	/*
-	 * we need if (result>=modulus) subtract(result,modulus);
-	 * in n-bit space this can be expressed as
-	 * if (carry || result>=modulus) subtract(result,modulus);
-	 * the catch is that comparison implies subtraction and
-	 * therefore one can write tmp=subtract(result,modulus);
-	 * and then if(carry || !borrow) result=tmp; this's what
-	 * happens below, but without explicit if:-) a.
-	 */
-	mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_384,BN_NIST_384_TOP);
-	mask = ~mask | (0-(size_t)carry);
-	res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
-
 	/*S2 */
-	carry = bn_add_words(r_d, res, buf, BN_NIST_384_TOP);
-	mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_384,BN_NIST_384_TOP);
-	mask = ~mask | (0-(size_t)carry);
-	res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
-
+	carry += (int)bn_add_words(r_d, r_d, buf, BN_NIST_384_TOP);
 	/*S3*/
 	nist_set_384(t_d,buf,20,19,18,17,16,15,14,13,12,23,22,21);
-	carry = bn_add_words(r_d, res, t_d, BN_NIST_384_TOP);
-	mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_384,BN_NIST_384_TOP);
-	mask = ~mask | (0-(size_t)carry);
-	res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
-
+	carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP);
 	/*S4*/
 	nist_set_384(t_d,buf,19,18,17,16,15,14,13,12,20,0,23,0);
-	carry = bn_add_words(r_d, res, t_d, BN_NIST_384_TOP);
-	mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_384,BN_NIST_384_TOP);
-	mask = ~mask | (0-(size_t)carry);
-	res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
-
+	carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP);
 	/*S5*/
 	nist_set_384(t_d, buf,0,0,0,0,23,22,21,20,0,0,0,0);
-	carry = bn_add_words(r_d, res, t_d, BN_NIST_384_TOP);
-	mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_384,BN_NIST_384_TOP);
-	mask = ~mask | (0-(size_t)carry);
-	res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
-
+	carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP);
 	/*S6*/
 	nist_set_384(t_d,buf,0,0,0,0,0,0,23,22,21,0,0,20);
-	carry = bn_add_words(r_d, res, t_d, BN_NIST_384_TOP);
-	mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_384,BN_NIST_384_TOP);
-	mask = ~mask | (0-(size_t)carry);
-	res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
-
+	carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP);
 	/*D1*/
 	nist_set_384(t_d,buf,22,21,20,19,18,17,16,15,14,13,12,23);
-#if BRANCH_FREE
-	carry = bn_sub_words(r_d, res, t_d, BN_NIST_384_TOP);
-	bn_add_words(c_d,r_d,_nist_p_384,BN_NIST_384_TOP);
-	mask = 0-(size_t)carry;
-	res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
-#else
-	if (bn_sub_words(r_d, res, t_d, BN_NIST_384_TOP))
-		bn_add_words(r_d,r_d,_nist_p_384,BN_NIST_384_TOP);
-#endif
+	carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP);
 	/*D2*/
 	nist_set_384(t_d,buf,0,0,0,0,0,0,0,23,22,21,20,0);
-#if BRANCH_FREE
-	carry = bn_sub_words(r_d, res, t_d, BN_NIST_384_TOP);
-	bn_add_words(c_d,r_d,_nist_p_384,BN_NIST_384_TOP);
-	mask = 0-(size_t)carry;
-	res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
-#else
-	if (bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP))
-		bn_add_words(r_d,r_d,_nist_p_384,BN_NIST_384_TOP);
-#endif
+	carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP);
 	/*D3*/
 	nist_set_384(t_d,buf,0,0,0,0,0,0,0,23,23,0,0,0);
-#if BRANCH_FREE
-	carry = bn_sub_words(r_d, res, t_d, BN_NIST_384_TOP);
-	bn_add_words(c_d,r_d,_nist_p_384,BN_NIST_384_TOP);
-	mask = 0-(size_t)carry;
-	res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
+	carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP);
+
+	/* see BN_nist_mod_224 for explanation */
+	u.f = bn_sub_words;
+	if (carry > 0)
+		carry = (int)bn_sub_words(r_d,r_d,_nist_p_384[carry-1],BN_NIST_384_TOP);
+	else if (carry < 0)
+		{
+		carry = (int)bn_add_words(r_d,r_d,_nist_p_384[-carry-1],BN_NIST_384_TOP);
+		mask = 0-(size_t)carry;
+		u.p = ((size_t)bn_sub_words&mask) | ((size_t)bn_add_words&~mask);
+		}
+	else
+		carry = 1;
 
+	mask  = 0-(size_t)(*u.f)(c_d,r_d,_nist_p_384[0],BN_NIST_384_TOP);
+	mask &= 0-(size_t)carry;
+	res   = (BN_ULONG *)(((size_t)c_d&~mask) | ((size_t)r_d&mask));
 	nist_cp_bn(r_d, res, BN_NIST_384_TOP);
-#else
-	if (bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP))
-		bn_add_words(r_d,r_d,_nist_p_384,BN_NIST_384_TOP);
-#endif
 	r->top = BN_NIST_384_TOP;
 	bn_correct_top(r);
 
 	return 1;
-#else	/* BN_BITS!=32 */
-	return 0;
-#endif
 	}
 
+#define BN_NIST_521_RSHIFT	(521%BN_BITS2)
+#define BN_NIST_521_LSHIFT	(BN_BITS2-BN_NIST_521_RSHIFT)
+#define BN_NIST_521_TOP_MASK	((BN_ULONG)BN_MASK2>>BN_NIST_521_LSHIFT)
+
 int BN_nist_mod_521(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
 	BN_CTX *ctx)
 	{
-#if BN_BITS2 == 64
-#define BN_NIST_521_TOP_MASK	(BN_ULONG)0x1FF
-#elif BN_BITS2 == 32
-#define BN_NIST_521_TOP_MASK	(BN_ULONG)0x1FF
-#endif
-	int	top, ret = 0;
-	BN_ULONG *r_d;
-	BIGNUM	*tmp;
-
-	/* check whether a reduction is necessary */
-	top = a->top;
-	if (top < BN_NIST_521_TOP  || ( top == BN_NIST_521_TOP &&
-           (!(a->d[BN_NIST_521_TOP-1] & ~(BN_NIST_521_TOP_MASK)))))
-		return (r == a)? 1 : (BN_copy(r ,a) != NULL);
+	int	top = a->top, i;
+	BN_ULONG *r_d, *a_d = a->d,
+		 t_d[BN_NIST_521_TOP],
+		 val,tmp,*res;
+	size_t	mask;
+	static const BIGNUM _bignum_nist_p_521_sqr = {
+		(BN_ULONG *)_nist_p_521_sqr,
+		sizeof(_nist_p_521_sqr)/sizeof(_nist_p_521_sqr[0]),
+		sizeof(_nist_p_521_sqr)/sizeof(_nist_p_521_sqr[0]),
+		0,BN_FLG_STATIC_DATA };
 
-	BN_CTX_start(ctx);
-	tmp = BN_CTX_get(ctx);
-	if (!tmp)
-		goto err;
+	field = &_bignum_nist_p_521; /* just to make sure */
 
-	if (!bn_wexpand(tmp, BN_NIST_521_TOP))
-		goto err;
-	nist_cp_bn(tmp->d, a->d, BN_NIST_521_TOP);
+ 	if (BN_is_negative(a) || BN_ucmp(a,&_bignum_nist_p_521_sqr)>=0)
+		return BN_nnmod(r, a, field, ctx);
 
-	tmp->top = BN_NIST_521_TOP;
-        tmp->d[BN_NIST_521_TOP-1]  &= BN_NIST_521_TOP_MASK;
-	bn_correct_top(tmp);
+	i = BN_ucmp(field, a);
+	if (i == 0)
+		{
+		BN_zero(r);
+		return 1;
+		}
+	else if (i > 0)
+		return (r == a)? 1 : (BN_copy(r ,a) != NULL);
 
-	if (!BN_rshift(r, a, 521))
-		goto err;
+	if (r != a)
+		{
+		if (!bn_wexpand(r,BN_NIST_521_TOP))
+			return 0;
+		r_d = r->d;
+		nist_cp_bn(r_d,a_d, BN_NIST_521_TOP);
+		}
+	else
+		r_d = a_d;
 
-	if (!BN_uadd(r, tmp, r))
-		goto err;
-	top = r->top;
-	r_d = r->d;
-	if (top == BN_NIST_521_TOP  && 
-           (r_d[BN_NIST_521_TOP-1] & ~(BN_NIST_521_TOP_MASK)))
+	/* upper 521 bits, copy ... */
+	nist_cp_bn_0(t_d,a_d + (BN_NIST_521_TOP-1), top - (BN_NIST_521_TOP-1),BN_NIST_521_TOP);
+	/* ... and right shift */
+	for (val=t_d[0],i=0; i<BN_NIST_521_TOP-1; i++)
 		{
-		BN_NIST_ADD_ONE(r_d)
-		r->d[BN_NIST_521_TOP-1] &= BN_NIST_521_TOP_MASK; 
+		tmp = val>>BN_NIST_521_RSHIFT;
+		val = t_d[i+1];
+		t_d[i] = (tmp | val<<BN_NIST_521_LSHIFT) & BN_MASK2;
 		}
+	t_d[i] = val>>BN_NIST_521_RSHIFT;
+	/* lower 521 bits */
+	r_d[i] &= BN_NIST_521_TOP_MASK;
+
+	bn_add_words(r_d,r_d,t_d,BN_NIST_521_TOP);
+	mask = 0-(size_t)bn_sub_words(t_d,r_d,_nist_p_521,BN_NIST_521_TOP);
+	res  = (BN_ULONG *)(((size_t)t_d&~mask) | ((size_t)r_d&mask));
+	nist_cp_bn(r_d,res,BN_NIST_521_TOP);
+	r->top = BN_NIST_521_TOP;
 	bn_correct_top(r);
 
-	ret = 1;
-err:
-	BN_CTX_end(ctx);
-
-	bn_check_top(r);
-	return ret;
+	return 1;
 	}
diff --git a/src/lib/libcrypto/bn/bn_rand.c b/src/lib/libcrypto/bn/bn_rand.c
index f51830b12b..b376c28ff3 100644
--- a/src/lib/libcrypto/bn/bn_rand.c
+++ b/src/lib/libcrypto/bn/bn_rand.c
@@ -227,7 +227,7 @@ int     BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom)
 
 
 /* random number r:  0 <= r < range */
-static int bn_rand_range(int pseudo, BIGNUM *r, BIGNUM *range)
+static int bn_rand_range(int pseudo, BIGNUM *r, const BIGNUM *range)
 	{
 	int (*bn_rand)(BIGNUM *, int, int, int) = pseudo ? BN_pseudo_rand : BN_rand;
 	int n;
@@ -294,12 +294,12 @@ static int bn_rand_range(int pseudo, BIGNUM *r, BIGNUM *range)
 	}
 
 
-int	BN_rand_range(BIGNUM *r, BIGNUM *range)
+int	BN_rand_range(BIGNUM *r, const BIGNUM *range)
 	{
 	return bn_rand_range(0, r, range);
 	}
 
-int	BN_pseudo_rand_range(BIGNUM *r, BIGNUM *range)
+int	BN_pseudo_rand_range(BIGNUM *r, const BIGNUM *range)
 	{
 	return bn_rand_range(1, r, range);
 	}
diff --git a/src/lib/libcrypto/bn/bn_shift.c b/src/lib/libcrypto/bn/bn_shift.c
index de9312dce2..c4d301afc4 100644
--- a/src/lib/libcrypto/bn/bn_shift.c
+++ b/src/lib/libcrypto/bn/bn_shift.c
@@ -177,7 +177,7 @@ int BN_rshift(BIGNUM *r, const BIGNUM *a, int n)
 	nw=n/BN_BITS2;
 	rb=n%BN_BITS2;
 	lb=BN_BITS2-rb;
-	if (nw > a->top || a->top == 0)
+	if (nw >= a->top || a->top == 0)
 		{
 		BN_zero(r);
 		return(1);
diff --git a/src/lib/libcrypto/bn/bn_x931p.c b/src/lib/libcrypto/bn/bn_x931p.c
index c64410dd3a..04c5c874ec 100644
--- a/src/lib/libcrypto/bn/bn_x931p.c
+++ b/src/lib/libcrypto/bn/bn_x931p.c
@@ -1,5 +1,5 @@
 /* bn_x931p.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2005.
  */
 /* ====================================================================
@@ -59,18 +59,15 @@
 #include <stdio.h>
 #include <openssl/bn.h>
 
-#ifdef OPENSSL_FIPS
-
 /* X9.31 routines for prime derivation */
 
-
 /* X9.31 prime derivation. This is used to generate the primes pi
  * (p1, p2, q1, q2) from a parameter Xpi by checking successive odd
  * integers.
  */
 
 static int bn_x931_derive_pi(BIGNUM *pi, const BIGNUM *Xpi, BN_CTX *ctx,
-			void (*cb)(int, int, void *), void *cb_arg)
+			BN_GENCB *cb)
 	{
 	int i = 0;
 	if (!BN_copy(pi, Xpi))
@@ -80,16 +77,14 @@ static int bn_x931_derive_pi(BIGNUM *pi, const BIGNUM *Xpi, BN_CTX *ctx,
 	for(;;)
 		{
 		i++;
-		if (cb)
-			cb(0, i, cb_arg);
+		BN_GENCB_call(cb, 0, i);
 		/* NB 27 MR is specificed in X9.31 */
-		if (BN_is_prime_fasttest(pi, 27, cb, ctx, cb_arg, 1))
+		if (BN_is_prime_fasttest_ex(pi, 27, ctx, 1, cb))
 			break;
 		if (!BN_add_word(pi, 2))
 			return 0;
 		}
-	if (cb)
-		cb(2, i, cb_arg);
+	BN_GENCB_call(cb, 2, i);
 	return 1;
 	}
 
@@ -98,10 +93,9 @@ static int bn_x931_derive_pi(BIGNUM *pi, const BIGNUM *Xpi, BN_CTX *ctx,
  * not NULL they will be returned too: this is needed for testing.
  */
 
-int BN_X931_derive_prime(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
-			void (*cb)(int, int, void *), void *cb_arg,
+int BN_X931_derive_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
 			const BIGNUM *Xp, const BIGNUM *Xp1, const BIGNUM *Xp2,
-			const BIGNUM *e, BN_CTX *ctx)
+			const BIGNUM *e, BN_CTX *ctx, BN_GENCB *cb)
 	{
 	int ret = 0;
 
@@ -124,10 +118,10 @@ int BN_X931_derive_prime(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
 
 	pm1 = BN_CTX_get(ctx);
 
-	if (!bn_x931_derive_pi(p1, Xp1, ctx, cb, cb_arg))
+	if (!bn_x931_derive_pi(p1, Xp1, ctx, cb))
 		goto err;
 
-	if (!bn_x931_derive_pi(p2, Xp2, ctx, cb, cb_arg))
+	if (!bn_x931_derive_pi(p2, Xp2, ctx, cb))
 		goto err;
 
 	if (!BN_mul(p1p2, p1, p2, ctx))
@@ -166,8 +160,7 @@ int BN_X931_derive_prime(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
 	for (;;)
 		{
 		int i = 1;
-		if (cb)
-			cb(0, i++, cb_arg);
+		BN_GENCB_call(cb, 0, i++);
 		if (!BN_copy(pm1, p))
 			goto err;
 		if (!BN_sub_word(pm1, 1))
@@ -179,14 +172,13 @@ int BN_X931_derive_prime(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
 		 * offering similar or better guarantees 50 MR is considerably 
 		 * better.
 		 */
-			&& BN_is_prime_fasttest(p, 50, cb, ctx, cb_arg, 1))
+			&& BN_is_prime_fasttest_ex(p, 50, ctx, 1, cb))
 			break;
 		if (!BN_add(p, p, p1p2))
 			goto err;
 		}
 
-	if (cb)
-		cb(3, 0, cb_arg);
+	BN_GENCB_call(cb, 3, 0);
 
 	ret = 1;
 
@@ -248,11 +240,11 @@ int BN_X931_generate_Xpq(BIGNUM *Xp, BIGNUM *Xq, int nbits, BN_CTX *ctx)
  * are generated using the previous function and supplied as input.
  */
 
-int BN_X931_generate_prime(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
+int BN_X931_generate_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
 			BIGNUM *Xp1, BIGNUM *Xp2,
 			const BIGNUM *Xp,
 			const BIGNUM *e, BN_CTX *ctx,
-			void (*cb)(int, int, void *), void *cb_arg)
+			BN_GENCB *cb)
 	{
 	int ret = 0;
 
@@ -266,8 +258,7 @@ int BN_X931_generate_prime(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
 		goto error;
 	if (!BN_rand(Xp2, 101, 0, 0))
 		goto error;
-	if (!BN_X931_derive_prime(p, p1, p2, cb, cb_arg,
-						Xp, Xp1, Xp2, e, ctx))
+	if (!BN_X931_derive_prime_ex(p, p1, p2, Xp, Xp1, Xp2, e, ctx, cb))
 		goto error;
 
 	ret = 1;
@@ -279,4 +270,3 @@ int BN_X931_generate_prime(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
 
 	}
 
-#endif
diff --git a/src/lib/libcrypto/buffer/buf_str.c b/src/lib/libcrypto/buffer/buf_str.c
new file mode 100644
index 0000000000..28dd1e401e
--- /dev/null
+++ b/src/lib/libcrypto/buffer/buf_str.c
@@ -0,0 +1,116 @@
+/* crypto/buffer/buf_str.c */
+/* ====================================================================
+ * Copyright (c) 2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <stdio.h>
+#include "cryptlib.h"
+#include <openssl/buffer.h>
+
+char *BUF_strdup(const char *str)
+	{
+	if (str == NULL) return(NULL);
+	return BUF_strndup(str, strlen(str));
+	}
+
+char *BUF_strndup(const char *str, size_t siz)
+	{
+	char *ret;
+
+	if (str == NULL) return(NULL);
+
+	ret=OPENSSL_malloc(siz+1);
+	if (ret == NULL) 
+		{
+		BUFerr(BUF_F_BUF_STRNDUP,ERR_R_MALLOC_FAILURE);
+		return(NULL);
+		}
+	BUF_strlcpy(ret,str,siz+1);
+	return(ret);
+	}
+
+void *BUF_memdup(const void *data, size_t siz)
+	{
+	void *ret;
+
+	if (data == NULL) return(NULL);
+
+	ret=OPENSSL_malloc(siz);
+	if (ret == NULL) 
+		{
+		BUFerr(BUF_F_BUF_MEMDUP,ERR_R_MALLOC_FAILURE);
+		return(NULL);
+		}
+	return memcpy(ret, data, siz);
+	}	
+
+size_t BUF_strlcpy(char *dst, const char *src, size_t size)
+	{
+	size_t l = 0;
+	for(; size > 1 && *src; size--)
+		{
+		*dst++ = *src++;
+		l++;
+		}
+	if (size)
+		*dst = '\0';
+	return l + strlen(src);
+	}
+
+size_t BUF_strlcat(char *dst, const char *src, size_t size)
+	{
+	size_t l = 0;
+	for(; size > 0 && *dst; size--, dst++)
+		l++;
+	return l + BUF_strlcpy(dst, src, size);
+	}
diff --git a/src/lib/libcrypto/buffer/buffer.c b/src/lib/libcrypto/buffer/buffer.c
index 3bf03c7eff..b3e947771d 100644
--- a/src/lib/libcrypto/buffer/buffer.c
+++ b/src/lib/libcrypto/buffer/buffer.c
@@ -161,61 +161,3 @@ int BUF_MEM_grow_clean(BUF_MEM *str, int len)
 		}
 	return(len);
 	}
-
-char *BUF_strdup(const char *str)
-	{
-	if (str == NULL) return(NULL);
-	return BUF_strndup(str, strlen(str));
-	}
-
-char *BUF_strndup(const char *str, size_t siz)
-	{
-	char *ret;
-
-	if (str == NULL) return(NULL);
-
-	ret=OPENSSL_malloc(siz+1);
-	if (ret == NULL) 
-		{
-		BUFerr(BUF_F_BUF_STRNDUP,ERR_R_MALLOC_FAILURE);
-		return(NULL);
-		}
-	BUF_strlcpy(ret,str,siz+1);
-	return(ret);
-	}
-
-void *BUF_memdup(const void *data, size_t siz)
-	{
-	void *ret;
-
-	if (data == NULL) return(NULL);
-
-	ret=OPENSSL_malloc(siz);
-	if (ret == NULL) 
-		{
-		BUFerr(BUF_F_BUF_MEMDUP,ERR_R_MALLOC_FAILURE);
-		return(NULL);
-		}
-	return memcpy(ret, data, siz);
-	}	
-
-size_t BUF_strlcpy(char *dst, const char *src, size_t size)
-	{
-	size_t l = 0;
-	for(; size > 1 && *src; size--)
-		{
-		*dst++ = *src++;
-		l++;
-		}
-	if (size)
-		*dst = '\0';
-	return l + strlen(src);
-	}
-
-size_t BUF_strlcat(char *dst, const char *src, size_t size)
-	{
-	size_t l = 0;
-	for(; size > 0 && *dst; size--, dst++)
-		l++;
-	return l + BUF_strlcpy(dst, src, size);
-	}
diff --git a/src/lib/libcrypto/camellia/camellia.h b/src/lib/libcrypto/camellia/camellia.h
index 3c8a359543..b8a8b6e10b 100644
--- a/src/lib/libcrypto/camellia/camellia.h
+++ b/src/lib/libcrypto/camellia/camellia.h
@@ -87,6 +87,11 @@ struct camellia_key_st
 
 typedef struct camellia_key_st CAMELLIA_KEY;
 
+#ifdef OPENSSL_FIPS
+int private_Camellia_set_key(const unsigned char *userKey, const int bits,
+	CAMELLIA_KEY *key);
+#endif
+
 int Camellia_set_key(const unsigned char *userKey, const int bits,
 	CAMELLIA_KEY *key);
 
diff --git a/src/lib/libcrypto/camellia/cmll_misc.c b/src/lib/libcrypto/camellia/cmll_misc.c
index f1047b54e0..2cd7aba9bb 100644
--- a/src/lib/libcrypto/camellia/cmll_misc.c
+++ b/src/lib/libcrypto/camellia/cmll_misc.c
@@ -52,11 +52,24 @@
 #include <openssl/opensslv.h>
 #include <openssl/camellia.h>
 #include "cmll_locl.h"
+#include <openssl/crypto.h>
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
 
 const char CAMELLIA_version[]="CAMELLIA" OPENSSL_VERSION_PTEXT;
 
 int Camellia_set_key(const unsigned char *userKey, const int bits,
 	CAMELLIA_KEY *key)
+#ifdef OPENSSL_FIPS
+	{
+	if (FIPS_mode())
+		FIPS_BAD_ABORT(CAMELLIA)
+	return private_Camellia_set_key(userKey, bits, key);
+	}
+int private_Camellia_set_key(const unsigned char *userKey, const int bits,
+	CAMELLIA_KEY *key)
+#endif
 	{
 	if (!userKey || !key)
 		{
diff --git a/src/lib/libcrypto/cast/c_skey.c b/src/lib/libcrypto/cast/c_skey.c
index 76e40005c9..68e690a60c 100644
--- a/src/lib/libcrypto/cast/c_skey.c
+++ b/src/lib/libcrypto/cast/c_skey.c
@@ -57,6 +57,11 @@
  */
 
 #include <openssl/cast.h>
+#include <openssl/crypto.h>
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
+
 #include "cast_lcl.h"
 #include "cast_s.h"
 
@@ -72,7 +77,7 @@
 #define S6 CAST_S_table6
 #define S7 CAST_S_table7
 
-void CAST_set_key(CAST_KEY *key, int len, const unsigned char *data)
+FIPS_NON_FIPS_VCIPHER_Init(CAST)
 	{
 	CAST_LONG x[16];
 	CAST_LONG z[16];
diff --git a/src/lib/libcrypto/cast/cast.h b/src/lib/libcrypto/cast/cast.h
index 90b45b950a..1faf5806aa 100644
--- a/src/lib/libcrypto/cast/cast.h
+++ b/src/lib/libcrypto/cast/cast.h
@@ -83,7 +83,9 @@ typedef struct cast_key_st
 	int short_key;	/* Use reduced rounds for short key */
 	} CAST_KEY;
 
- 
+#ifdef OPENSSL_FIPS 
+void private_CAST_set_key(CAST_KEY *key, int len, const unsigned char *data);
+#endif
 void CAST_set_key(CAST_KEY *key, int len, const unsigned char *data);
 void CAST_ecb_encrypt(const unsigned char *in,unsigned char *out,CAST_KEY *key,
 		      int enc);
diff --git a/src/lib/libcrypto/cms/cms_sd.c b/src/lib/libcrypto/cms/cms_sd.c
index 591bfbec33..cdac3b870d 100644
--- a/src/lib/libcrypto/cms/cms_sd.c
+++ b/src/lib/libcrypto/cms/cms_sd.c
@@ -830,7 +830,7 @@ int CMS_SignerInfo_verify(CMS_SignerInfo *si)
 	cms_fixup_mctx(&mctx, si->pkey);
 	r = EVP_VerifyFinal(&mctx,
 			si->signature->data, si->signature->length, si->pkey);
-	if (!r)
+	if (r <= 0)
 		CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY, CMS_R_VERIFICATION_FAILURE);
 	err:
 	EVP_MD_CTX_cleanup(&mctx);
diff --git a/src/lib/libcrypto/cms/cms_smime.c b/src/lib/libcrypto/cms/cms_smime.c
index f79c504e91..b9463f9abb 100644
--- a/src/lib/libcrypto/cms/cms_smime.c
+++ b/src/lib/libcrypto/cms/cms_smime.c
@@ -68,7 +68,10 @@ static int cms_copy_content(BIO *out, BIO *in, unsigned int flags)
 	if (out == NULL)
 		tmpout = BIO_new(BIO_s_null());
 	else if (flags & CMS_TEXT)
+		{
 		tmpout = BIO_new(BIO_s_mem());
+		BIO_set_mem_eof_return(tmpout, 0);
+		}
 	else
 		tmpout = out;
 
@@ -89,11 +92,13 @@ static int cms_copy_content(BIO *out, BIO *in, unsigned int flags)
 				if (!BIO_get_cipher_status(in))
 					goto err;
 				}
+			if (i < 0)
+				goto err;
 			break;
 			}
 				
-		if (tmpout)
-			BIO_write(tmpout, buf, i);
+		if (tmpout && (BIO_write(tmpout, buf, i) != i))
+			goto err;
 	}
 
 	if(flags & CMS_TEXT)
diff --git a/src/lib/libcrypto/comp/c_zlib.c b/src/lib/libcrypto/comp/c_zlib.c
index 0f34597e70..eccfd09137 100644
--- a/src/lib/libcrypto/comp/c_zlib.c
+++ b/src/lib/libcrypto/comp/c_zlib.c
@@ -727,6 +727,7 @@ static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr)
 	case BIO_CTRL_RESET:
 		ctx->ocount = 0;
 		ctx->odone = 0;
+		ret = 1;
 		break;
 
 	case BIO_CTRL_FLUSH:
@@ -771,7 +772,7 @@ static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr)
 				}
 			ctx->obufsize = obs;
 			}
-
+		ret = 1;
 		break;
 
 	case BIO_C_DO_STATE_MACHINE:
@@ -783,7 +784,6 @@ static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr)
 	default:
 		ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
 		break;
-
 		}
 
 	return ret;
diff --git a/src/lib/libcrypto/conf/conf_mall.c b/src/lib/libcrypto/conf/conf_mall.c
index 4ba40cf44c..1cc1fd5534 100644
--- a/src/lib/libcrypto/conf/conf_mall.c
+++ b/src/lib/libcrypto/conf/conf_mall.c
@@ -1,5 +1,5 @@
 /* conf_mall.c */
-/* Written by Stephen Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Stephen Henson (steve@openssl.org) for the OpenSSL
  * project 2001.
  */
 /* ====================================================================
@@ -63,6 +63,7 @@
 #include <openssl/dso.h>
 #include <openssl/x509.h>
 #include <openssl/asn1.h>
+#include <openssl/evp.h>
 #ifndef OPENSSL_NO_ENGINE
 #include <openssl/engine.h>
 #endif
@@ -76,5 +77,6 @@ void OPENSSL_load_builtin_modules(void)
 #ifndef OPENSSL_NO_ENGINE
 	ENGINE_add_conf_module();
 #endif
+	EVP_add_alg_module();
 	}
 
diff --git a/src/lib/libcrypto/conf/conf_mod.c b/src/lib/libcrypto/conf/conf_mod.c
index 628e8333a6..ee9c677d9b 100644
--- a/src/lib/libcrypto/conf/conf_mod.c
+++ b/src/lib/libcrypto/conf/conf_mod.c
@@ -1,5 +1,5 @@
 /* conf_mod.c */
-/* Written by Stephen Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Stephen Henson (steve@openssl.org) for the OpenSSL
  * project 2001.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/conf/conf_sap.c b/src/lib/libcrypto/conf/conf_sap.c
index 9c53bac1a8..760dc2632d 100644
--- a/src/lib/libcrypto/conf/conf_sap.c
+++ b/src/lib/libcrypto/conf/conf_sap.c
@@ -1,5 +1,5 @@
 /* conf_sap.c */
-/* Written by Stephen Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Stephen Henson (steve@openssl.org) for the OpenSSL
  * project 2001.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/cryptlib.c b/src/lib/libcrypto/cryptlib.c
index 8c68623828..8f9e88e403 100644
--- a/src/lib/libcrypto/cryptlib.c
+++ b/src/lib/libcrypto/cryptlib.c
@@ -121,275 +121,17 @@
 static double SSLeay_MSVC5_hack=0.0; /* and for VC1.5 */
 #endif
 
-DECLARE_STACK_OF(CRYPTO_dynlock)
-IMPLEMENT_STACK_OF(CRYPTO_dynlock)
-
-/* real #defines in crypto.h, keep these upto date */
-static const char* const lock_names[CRYPTO_NUM_LOCKS] =
-	{
-	"<<ERROR>>",
-	"err",
-	"ex_data",
-	"x509",
-	"x509_info",
-	"x509_pkey",
-	"x509_crl",
-	"x509_req",
-	"dsa",
-	"rsa",
-	"evp_pkey",
-	"x509_store",
-	"ssl_ctx",
-	"ssl_cert",
-	"ssl_session",
-	"ssl_sess_cert",
-	"ssl",
-	"ssl_method",
-	"rand",
-	"rand2",
-	"debug_malloc",
-	"BIO",
-	"gethostbyname",
-	"getservbyname",
-	"readdir",
-	"RSA_blinding",
-	"dh",
-	"debug_malloc2",
-	"dso",
-	"dynlock",
-	"engine",
-	"ui",
-	"ecdsa",
-	"ec",
-	"ecdh",
-	"bn",
-	"ec_pre_comp",
-	"store",
-	"comp",
-#if CRYPTO_NUM_LOCKS != 39
-# error "Inconsistency between crypto.h and cryptlib.c"
-#endif
-	};
-
-/* This is for applications to allocate new type names in the non-dynamic
-   array of lock names.  These are numbered with positive numbers.  */
-static STACK *app_locks=NULL;
-
-/* For applications that want a more dynamic way of handling threads, the
-   following stack is used.  These are externally numbered with negative
-   numbers.  */
-static STACK_OF(CRYPTO_dynlock) *dyn_locks=NULL;
-
-
 static void (MS_FAR *locking_callback)(int mode,int type,
 	const char *file,int line)=NULL;
 static int (MS_FAR *add_lock_callback)(int *pointer,int amount,
 	int type,const char *file,int line)=NULL;
 static unsigned long (MS_FAR *id_callback)(void)=NULL;
-static struct CRYPTO_dynlock_value *(MS_FAR *dynlock_create_callback)
-	(const char *file,int line)=NULL;
-static void (MS_FAR *dynlock_lock_callback)(int mode,
-	struct CRYPTO_dynlock_value *l, const char *file,int line)=NULL;
-static void (MS_FAR *dynlock_destroy_callback)(struct CRYPTO_dynlock_value *l,
-	const char *file,int line)=NULL;
-
-int CRYPTO_get_new_lockid(char *name)
-	{
-	char *str;
-	int i;
-
-#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN16)
-	/* A hack to make Visual C++ 5.0 work correctly when linking as
-	 * a DLL using /MT. Without this, the application cannot use
-	 * and floating point printf's.
-	 * It also seems to be needed for Visual C 1.5 (win16) */
-	SSLeay_MSVC5_hack=(double)name[0]*(double)name[1];
-#endif
-
-	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)
-		{
-		CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_LOCKID,ERR_R_MALLOC_FAILURE);
-		return(0);
-		}
-	i=sk_push(app_locks,str);
-	if (!i)
-		OPENSSL_free(str);
-	else
-		i+=CRYPTO_NUM_LOCKS; /* gap of one :-) */
-	return(i);
-	}
 
 int CRYPTO_num_locks(void)
 	{
 	return CRYPTO_NUM_LOCKS;
 	}
 
-int CRYPTO_get_new_dynlockid(void)
-	{
-	int i = 0;
-	CRYPTO_dynlock *pointer = NULL;
-
-	if (dynlock_create_callback == NULL)
-		{
-		CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,CRYPTO_R_NO_DYNLOCK_CREATE_CALLBACK);
-		return(0);
-		}
-	CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK);
-	if ((dyn_locks == NULL)
-		&& ((dyn_locks=sk_CRYPTO_dynlock_new_null()) == NULL))
-		{
-		CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
-		CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,ERR_R_MALLOC_FAILURE);
-		return(0);
-		}
-	CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
-
-	pointer = (CRYPTO_dynlock *)OPENSSL_malloc(sizeof(CRYPTO_dynlock));
-	if (pointer == NULL)
-		{
-		CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,ERR_R_MALLOC_FAILURE);
-		return(0);
-		}
-	pointer->references = 1;
-	pointer->data = dynlock_create_callback(__FILE__,__LINE__);
-	if (pointer->data == NULL)
-		{
-		OPENSSL_free(pointer);
-		CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,ERR_R_MALLOC_FAILURE);
-		return(0);
-		}
-
-	CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK);
-	/* First, try to find an existing empty slot */
-	i=sk_CRYPTO_dynlock_find(dyn_locks,NULL);
-	/* If there was none, push, thereby creating a new one */
-	if (i == -1)
-		/* Since sk_push() returns the number of items on the
-		   stack, not the location of the pushed item, we need
-		   to transform the returned number into a position,
-		   by decreasing it.  */
-		i=sk_CRYPTO_dynlock_push(dyn_locks,pointer) - 1;
-	else
-		/* If we found a place with a NULL pointer, put our pointer
-		   in it.  */
-		(void)sk_CRYPTO_dynlock_set(dyn_locks,i,pointer);
-	CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
-
-	if (i == -1)
-		{
-		dynlock_destroy_callback(pointer->data,__FILE__,__LINE__);
-		OPENSSL_free(pointer);
-		}
-	else
-		i += 1; /* to avoid 0 */
-	return -i;
-	}
-
-void CRYPTO_destroy_dynlockid(int i)
-	{
-	CRYPTO_dynlock *pointer = NULL;
-	if (i)
-		i = -i-1;
-	if (dynlock_destroy_callback == NULL)
-		return;
-
-	CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK);
-
-	if (dyn_locks == NULL || i >= sk_CRYPTO_dynlock_num(dyn_locks))
-		{
-		CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
-		return;
-		}
-	pointer = sk_CRYPTO_dynlock_value(dyn_locks, i);
-	if (pointer != NULL)
-		{
-		--pointer->references;
-#ifdef REF_CHECK
-		if (pointer->references < 0)
-			{
-			fprintf(stderr,"CRYPTO_destroy_dynlockid, bad reference count\n");
-			abort();
-			}
-		else
-#endif
-			if (pointer->references <= 0)
-				{
-				(void)sk_CRYPTO_dynlock_set(dyn_locks, i, NULL);
-				}
-			else
-				pointer = NULL;
-		}
-	CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
-
-	if (pointer)
-		{
-		dynlock_destroy_callback(pointer->data,__FILE__,__LINE__);
-		OPENSSL_free(pointer);
-		}
-	}
-
-struct CRYPTO_dynlock_value *CRYPTO_get_dynlock_value(int i)
-	{
-	CRYPTO_dynlock *pointer = NULL;
-	if (i)
-		i = -i-1;
-
-	CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK);
-
-	if (dyn_locks != NULL && i < sk_CRYPTO_dynlock_num(dyn_locks))
-		pointer = sk_CRYPTO_dynlock_value(dyn_locks, i);
-	if (pointer)
-		pointer->references++;
-
-	CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
-
-	if (pointer)
-		return pointer->data;
-	return NULL;
-	}
-
-struct CRYPTO_dynlock_value *(*CRYPTO_get_dynlock_create_callback(void))
-	(const char *file,int line)
-	{
-	return(dynlock_create_callback);
-	}
-
-void (*CRYPTO_get_dynlock_lock_callback(void))(int mode,
-	struct CRYPTO_dynlock_value *l, const char *file,int line)
-	{
-	return(dynlock_lock_callback);
-	}
-
-void (*CRYPTO_get_dynlock_destroy_callback(void))
-	(struct CRYPTO_dynlock_value *l, const char *file,int line)
-	{
-	return(dynlock_destroy_callback);
-	}
-
-void CRYPTO_set_dynlock_create_callback(struct CRYPTO_dynlock_value *(*func)
-	(const char *file, int line))
-	{
-	dynlock_create_callback=func;
-	}
-
-void CRYPTO_set_dynlock_lock_callback(void (*func)(int mode,
-	struct CRYPTO_dynlock_value *l, const char *file, int line))
-	{
-	dynlock_lock_callback=func;
-	}
-
-void CRYPTO_set_dynlock_destroy_callback(void (*func)
-	(struct CRYPTO_dynlock_value *l, const char *file, int line))
-	{
-	dynlock_destroy_callback=func;
-	}
-
-
 void (*CRYPTO_get_locking_callback(void))(int mode,int type,const char *file,
 		int line)
 	{
@@ -445,6 +187,14 @@ unsigned long CRYPTO_thread_id(void)
 	return(ret);
 	}
 
+static void (*do_dynlock_cb)(int mode, int type, const char *file, int line);
+
+void int_CRYPTO_set_do_dynlock_callback(
+	void (*dyn_cb)(int mode, int type, const char *file, int line))
+	{
+	do_dynlock_cb = dyn_cb;
+	}
+
 void CRYPTO_lock(int mode, int type, const char *file, int line)
 	{
 #ifdef LOCK_DEBUG
@@ -472,17 +222,8 @@ void CRYPTO_lock(int mode, int type, const char *file, int line)
 #endif
 	if (type < 0)
 		{
-		if (dynlock_lock_callback != NULL)
-			{
-			struct CRYPTO_dynlock_value *pointer
-				= CRYPTO_get_dynlock_value(type);
-
-			OPENSSL_assert(pointer != NULL);
-
-			dynlock_lock_callback(mode, pointer, file, line);
-
-			CRYPTO_destroy_dynlockid(type);
-			}
+		if (do_dynlock_cb)
+			do_dynlock_cb(mode, type, file, line);
 		}
 	else
 		if (locking_callback != NULL)
@@ -527,21 +268,9 @@ int CRYPTO_add_lock(int *pointer, int amount, int type, const char *file,
 	return(ret);
 	}
 
-const char *CRYPTO_get_lock_name(int type)
-	{
-	if (type < 0)
-		return("dynamic");
-	else if (type < CRYPTO_NUM_LOCKS)
-		return(lock_names[type]);
-	else if (type-CRYPTO_NUM_LOCKS > sk_num(app_locks))
-		return("ERROR");
-	else
-		return(sk_value(app_locks,type-CRYPTO_NUM_LOCKS));
-	}
-
 #if	defined(__i386)   || defined(__i386__)   || defined(_M_IX86) || \
 	defined(__INTEL__) || \
-	defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64)
+	defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)
 
 unsigned long  OPENSSL_ia32cap_P=0;
 unsigned long *OPENSSL_ia32cap_loc(void) { return &OPENSSL_ia32cap_P; }
@@ -577,6 +306,62 @@ void OPENSSL_cpuid_setup(void) {}
 #endif
 
 #if (defined(_WIN32) || defined(__CYGWIN__)) && defined(_WINDLL)
+
+#ifdef OPENSSL_FIPS
+
+#include <tlhelp32.h>
+#if defined(__GNUC__) && __GNUC__>=2
+static int DllInit(void) __attribute__((constructor));
+#elif defined(_MSC_VER)
+static int DllInit(void);
+# ifdef _WIN64
+# pragma section(".CRT$XCU",read)
+  __declspec(allocate(".CRT$XCU"))
+# else
+# pragma data_seg(".CRT$XCU")
+# endif
+  static int (*p)(void) = DllInit;
+# pragma data_seg()
+#endif
+
+static int DllInit(void)
+{
+#if defined(_WIN32_WINNT)
+	union	{ int(*f)(void); BYTE *p; } t = { DllInit };
+        HANDLE	hModuleSnap = INVALID_HANDLE_VALUE;
+	IMAGE_DOS_HEADER *dos_header;
+	IMAGE_NT_HEADERS *nt_headers;
+	MODULEENTRY32 me32 = {sizeof(me32)};
+
+	hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,0);
+	if (hModuleSnap != INVALID_HANDLE_VALUE &&
+	    Module32First(hModuleSnap,&me32)) do
+		{
+		if (t.p >= me32.modBaseAddr &&
+		    t.p <  me32.modBaseAddr+me32.modBaseSize)
+			{
+			dos_header=(IMAGE_DOS_HEADER *)me32.modBaseAddr;
+			if (dos_header->e_magic==IMAGE_DOS_SIGNATURE)
+				{
+				nt_headers=(IMAGE_NT_HEADERS *)
+					((BYTE *)dos_header+dos_header->e_lfanew);
+				if (nt_headers->Signature==IMAGE_NT_SIGNATURE &&
+				    me32.modBaseAddr!=(BYTE*)nt_headers->OptionalHeader.ImageBase)
+					OPENSSL_NONPIC_relocated=1;
+				}
+			break;
+			}
+		} while (Module32Next(hModuleSnap,&me32));
+
+	if (hModuleSnap != INVALID_HANDLE_VALUE)
+		CloseHandle(hModuleSnap);
+#endif
+	OPENSSL_cpuid_setup();
+	return 0;
+}
+
+#else
+
 #ifdef __CYGWIN__
 /* pick DLL_[PROCESS|THREAD]_[ATTACH|DETACH] definitions */
 #include <windows.h>
@@ -620,6 +405,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason,
 	}
 #endif
 
+#endif
+
 #if defined(_WIN32) && !defined(__CYGWIN__)
 #include <tchar.h>
 
diff --git a/src/lib/libcrypto/cryptlib.h b/src/lib/libcrypto/cryptlib.h
index 5ceaa964b5..fc249c57f3 100644
--- a/src/lib/libcrypto/cryptlib.h
+++ b/src/lib/libcrypto/cryptlib.h
@@ -103,7 +103,6 @@ extern unsigned long OPENSSL_ia32cap_P;
 void OPENSSL_showfatal(const char *,...);
 void *OPENSSL_stderr(void);
 extern int OPENSSL_NONPIC_relocated;
-int OPENSSL_isservice(void);
 
 #ifdef  __cplusplus
 }
diff --git a/src/lib/libcrypto/crypto.h b/src/lib/libcrypto/crypto.h
index d2b5ffe332..0e4fb0723c 100644
--- a/src/lib/libcrypto/crypto.h
+++ b/src/lib/libcrypto/crypto.h
@@ -219,7 +219,13 @@ typedef struct openssl_item_st
 #define CRYPTO_LOCK_EC_PRE_COMP		36
 #define CRYPTO_LOCK_STORE		37
 #define CRYPTO_LOCK_COMP		38
+#ifndef OPENSSL_FIPS
 #define CRYPTO_NUM_LOCKS		39
+#else
+#define CRYPTO_LOCK_FIPS		39
+#define CRYPTO_LOCK_FIPS2		40
+#define CRYPTO_NUM_LOCKS		41
+#endif
 
 #define CRYPTO_LOCK		1
 #define CRYPTO_UNLOCK		2
@@ -341,14 +347,7 @@ DECLARE_STACK_OF(CRYPTO_EX_DATA_FUNCS)
 
 /* Set standard debugging functions (not done by default
  * unless CRYPTO_MDEBUG is defined) */
-#define CRYPTO_malloc_debug_init()	do {\
-	CRYPTO_set_mem_debug_functions(\
-		CRYPTO_dbg_malloc,\
-		CRYPTO_dbg_realloc,\
-		CRYPTO_dbg_free,\
-		CRYPTO_dbg_set_options,\
-		CRYPTO_dbg_get_options);\
-	} while(0)
+void CRYPTO_malloc_debug_init(void);
 
 int CRYPTO_mem_ctrl(int mode);
 int CRYPTO_is_mem_check_on(void);
@@ -363,6 +362,7 @@ int CRYPTO_is_mem_check_on(void);
 #define is_MemCheck_on() CRYPTO_is_mem_check_on()
 
 #define OPENSSL_malloc(num)	CRYPTO_malloc((int)num,__FILE__,__LINE__)
+#define OPENSSL_strdup(str)	CRYPTO_strdup((str),__FILE__,__LINE__)
 #define OPENSSL_realloc(addr,num) \
 	CRYPTO_realloc((char *)addr,(int)num,__FILE__,__LINE__)
 #define OPENSSL_realloc_clean(addr,old_num,num) \
@@ -427,6 +427,9 @@ const char *CRYPTO_get_lock_name(int type);
 int CRYPTO_add_lock(int *pointer,int amount,int type, const char *file,
 		    int line);
 
+void int_CRYPTO_set_do_dynlock_callback(
+	void (*do_dynlock_cb)(int mode, int type, const char *file, int line));
+
 int CRYPTO_get_new_dynlockid(void);
 void CRYPTO_destroy_dynlockid(int i);
 struct CRYPTO_dynlock_value *CRYPTO_get_dynlock_value(int i);
@@ -451,6 +454,10 @@ int CRYPTO_set_mem_debug_functions(void (*m)(void *,int,const char *,int,int),
 				   void (*f)(void *,int),
 				   void (*so)(long),
 				   long (*go)(void));
+void CRYPTO_set_mem_info_functions(
+	int  (*push_info_fn)(const char *info, const char *file, int line),
+	int  (*pop_info_fn)(void),
+	int (*remove_all_info_fn)(void));
 void CRYPTO_get_mem_functions(void *(**m)(size_t),void *(**r)(void *, size_t), void (**f)(void *));
 void CRYPTO_get_locked_mem_functions(void *(**m)(size_t), void (**f)(void *));
 void CRYPTO_get_mem_ex_functions(void *(**m)(size_t,const char *,int),
@@ -467,6 +474,7 @@ void CRYPTO_get_mem_debug_functions(void (**m)(void *,int,const char *,int,int),
 void *CRYPTO_malloc_locked(int num, const char *file, int line);
 void CRYPTO_free_locked(void *);
 void *CRYPTO_malloc(int num, const char *file, int line);
+char *CRYPTO_strdup(const char *str, const char *file, int line);
 void CRYPTO_free(void *);
 void *CRYPTO_realloc(void *addr,int num, const char *file, int line);
 void *CRYPTO_realloc_clean(void *addr,int old_num,int num,const char *file,
@@ -506,6 +514,9 @@ void CRYPTO_dbg_free(void *addr,int before_p);
 void CRYPTO_dbg_set_options(long bits);
 long CRYPTO_dbg_get_options(void);
 
+int CRYPTO_dbg_push_info(const char *info, const char *file, int line);
+int CRYPTO_dbg_pop_info(void);
+int CRYPTO_dbg_remove_all_info(void);
 
 #ifndef OPENSSL_NO_FP_API
 void CRYPTO_mem_leaks_fp(FILE *);
@@ -521,6 +532,61 @@ void OpenSSLDie(const char *file,int line,const char *assertion);
 
 unsigned long *OPENSSL_ia32cap_loc(void);
 #define OPENSSL_ia32cap (*(OPENSSL_ia32cap_loc()))
+int OPENSSL_isservice(void);
+
+#ifdef OPENSSL_FIPS
+#define FIPS_ERROR_IGNORED(alg) OpenSSLDie(__FILE__, __LINE__, \
+		alg " previous FIPS forbidden algorithm error ignored");
+
+#define FIPS_BAD_ABORT(alg) OpenSSLDie(__FILE__, __LINE__, \
+		#alg " Algorithm forbidden in FIPS mode");
+
+#ifdef OPENSSL_FIPS_STRICT
+#define FIPS_BAD_ALGORITHM(alg) FIPS_BAD_ABORT(alg)
+#else
+#define FIPS_BAD_ALGORITHM(alg) \
+	{ \
+	FIPSerr(FIPS_F_HASH_FINAL,FIPS_R_NON_FIPS_METHOD); \
+	ERR_add_error_data(2, "Algorithm=", #alg); \
+	return 0; \
+	}
+#endif
+
+/* Low level digest API blocking macro */
+
+#define FIPS_NON_FIPS_MD_Init(alg) \
+	int alg##_Init(alg##_CTX *c) \
+		{ \
+		if (FIPS_mode()) \
+			FIPS_BAD_ALGORITHM(alg) \
+		return private_##alg##_Init(c); \
+		} \
+	int private_##alg##_Init(alg##_CTX *c)
+
+/* For ciphers the API often varies from cipher to cipher and each needs to
+ * be treated as a special case. Variable key length ciphers (Blowfish, RC4,
+ * CAST) however are very similar and can use a blocking macro.
+ */
+
+#define FIPS_NON_FIPS_VCIPHER_Init(alg) \
+	void alg##_set_key(alg##_KEY *key, int len, const unsigned char *data) \
+		{ \
+		if (FIPS_mode()) \
+			FIPS_BAD_ABORT(alg) \
+		private_##alg##_set_key(key, len, data); \
+		} \
+	void private_##alg##_set_key(alg##_KEY *key, int len, \
+					const unsigned char *data)
+
+#else
+
+#define FIPS_NON_FIPS_VCIPHER_Init(alg) \
+	void alg##_set_key(alg##_KEY *key, int len, const unsigned char *data)
+
+#define FIPS_NON_FIPS_MD_Init(alg) \
+	int alg##_Init(alg##_CTX *c) 
+
+#endif /* def OPENSSL_FIPS */
 
 /* BEGIN ERROR CODES */
 /* The following lines are auto generated by the script mkerr.pl. Any changes
@@ -528,6 +594,9 @@ unsigned long *OPENSSL_ia32cap_loc(void);
  */
 void ERR_load_CRYPTO_strings(void);
 
+#define OPENSSL_HAVE_INIT	1
+void OPENSSL_init(void);
+
 /* Error codes for the CRYPTO functions. */
 
 /* Function codes. */
diff --git a/src/lib/libcrypto/des/des_enc.c b/src/lib/libcrypto/des/des_enc.c
index 1c37ab96d3..cf71965aca 100644
--- a/src/lib/libcrypto/des/des_enc.c
+++ b/src/lib/libcrypto/des/des_enc.c
@@ -289,6 +289,8 @@ void DES_decrypt3(DES_LONG *data, DES_key_schedule *ks1,
 
 #ifndef DES_DEFAULT_OPTIONS
 
+#if !defined(OPENSSL_FIPS_DES_ASM)
+
 #undef CBC_ENC_C__DONT_UPDATE_IV
 #include "ncbc_enc.c" /* DES_ncbc_encrypt */
 
@@ -404,4 +406,6 @@ void DES_ede3_cbc_encrypt(const unsigned char *input, unsigned char *output,
 	tin[0]=tin[1]=0;
 	}
 
+#endif
+
 #endif /* DES_DEFAULT_OPTIONS */
diff --git a/src/lib/libcrypto/des/ecb_enc.c b/src/lib/libcrypto/des/ecb_enc.c
index 00d5b91e8c..75ae6cf8bb 100644
--- a/src/lib/libcrypto/des/ecb_enc.c
+++ b/src/lib/libcrypto/des/ecb_enc.c
@@ -57,54 +57,7 @@
  */
 
 #include "des_locl.h"
-#include "des_ver.h"
 #include "spr.h"
-#include <openssl/opensslv.h>
-#include <openssl/bio.h>
-
-OPENSSL_GLOBAL const char libdes_version[]="libdes" OPENSSL_VERSION_PTEXT;
-OPENSSL_GLOBAL const char DES_version[]="DES" OPENSSL_VERSION_PTEXT;
-
-const char *DES_options(void)
-	{
-	static int init=1;
-	static char buf[32];
-
-	if (init)
-		{
-		const char *ptr,*unroll,*risc,*size;
-
-#ifdef DES_PTR
-		ptr="ptr";
-#else
-		ptr="idx";
-#endif
-#if defined(DES_RISC1) || defined(DES_RISC2)
-#ifdef DES_RISC1
-		risc="risc1";
-#endif
-#ifdef DES_RISC2
-		risc="risc2";
-#endif
-#else
-		risc="cisc";
-#endif
-#ifdef DES_UNROLL
-		unroll="16";
-#else
-		unroll="4";
-#endif
-		if (sizeof(DES_LONG) != sizeof(long))
-			size="int";
-		else
-			size="long";
-		BIO_snprintf(buf,sizeof buf,"des(%s,%s,%s,%s)",ptr,risc,unroll,
-			     size);
-		init=0;
-		}
-	return(buf);
-	}
-		
 
 void DES_ecb_encrypt(const_DES_cblock *input, DES_cblock *output,
 		     DES_key_schedule *ks, int enc)
diff --git a/src/lib/libcrypto/des/enc_read.c b/src/lib/libcrypto/des/enc_read.c
index c70fb686b8..e7da2ec66b 100644
--- a/src/lib/libcrypto/des/enc_read.c
+++ b/src/lib/libcrypto/des/enc_read.c
@@ -147,7 +147,11 @@ int DES_enc_read(int fd, void *buf, int len, DES_key_schedule *sched,
 	/* first - get the length */
 	while (net_num < HDRSIZE) 
 		{
+#ifndef _WIN32
 		i=read(fd,(void *)&(net[net_num]),HDRSIZE-net_num);
+#else
+		i=_read(fd,(void *)&(net[net_num]),HDRSIZE-net_num);
+#endif
 #ifdef EINTR
 		if ((i == -1) && (errno == EINTR)) continue;
 #endif
diff --git a/src/lib/libcrypto/des/enc_writ.c b/src/lib/libcrypto/des/enc_writ.c
index af5b8c2349..c2f032c9a6 100644
--- a/src/lib/libcrypto/des/enc_writ.c
+++ b/src/lib/libcrypto/des/enc_writ.c
@@ -153,7 +153,11 @@ int DES_enc_write(int fd, const void *_buf, int len,
 		{
 		/* eay 26/08/92 I was not doing writing from where we
 		 * got up to. */
+#ifndef _WIN32
 		i=write(fd,(void *)&(outbuf[j]),outnum-j);
+#else
+		i=_write(fd,(void *)&(outbuf[j]),outnum-j);
+#endif
 		if (i == -1)
 			{
 #ifdef EINTR
diff --git a/src/lib/libcrypto/des/set_key.c b/src/lib/libcrypto/des/set_key.c
index a43ef3c881..c0806d593c 100644
--- a/src/lib/libcrypto/des/set_key.c
+++ b/src/lib/libcrypto/des/set_key.c
@@ -64,6 +64,10 @@
  * 1.0 First working version
  */
 #include "des_locl.h"
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
+
 
 OPENSSL_IMPLEMENT_GLOBAL(int,DES_check_key);	/* defaults to false */
 
@@ -349,6 +353,10 @@ void DES_set_key_unchecked(const_DES_cblock *key, DES_key_schedule *schedule)
 	k = &schedule->ks->deslong[0];
 	in = &(*key)[0];
 
+#ifdef OPENSSL_FIPS
+	FIPS_selftest_check();
+#endif
+
 	c2l(in,c);
 	c2l(in,d);
 
@@ -405,3 +413,4 @@ void des_fixup_key_parity(des_cblock *key)
 	des_set_odd_parity(key);
 	}
 */
+
diff --git a/src/lib/libcrypto/dh/dh.h b/src/lib/libcrypto/dh/dh.h
index ccdf35ae1c..10475ac4b3 100644
--- a/src/lib/libcrypto/dh/dh.h
+++ b/src/lib/libcrypto/dh/dh.h
@@ -77,6 +77,8 @@
 # define OPENSSL_DH_MAX_MODULUS_BITS	10000
 #endif
 
+#define OPENSSL_DH_FIPS_MIN_MODULUS_BITS 1024
+
 #define DH_FLAG_CACHE_MONT_P     0x01
 #define DH_FLAG_NO_EXP_CONSTTIME 0x02 /* new with 0.9.7h; the built-in DH
                                        * implementation now uses constant time
@@ -167,6 +169,11 @@ struct dh_st
 
 const DH_METHOD *DH_OpenSSL(void);
 
+#ifdef OPENSSL_FIPS
+DH *	FIPS_dh_new(void);
+void	FIPS_dh_free(DH *dh);
+#endif
+
 void DH_set_default_method(const DH_METHOD *meth);
 const DH_METHOD *DH_get_default_method(void);
 int DH_set_method(DH *dh, const DH_METHOD *meth);
@@ -218,6 +225,9 @@ void ERR_load_DH_strings(void);
 #define DH_F_DHPARAMS_PRINT				 100
 #define DH_F_DHPARAMS_PRINT_FP				 101
 #define DH_F_DH_BUILTIN_GENPARAMS			 106
+#define DH_F_DH_COMPUTE_KEY				 107
+#define DH_F_DH_GENERATE_KEY				 108
+#define DH_F_DH_GENERATE_PARAMETERS			 109
 #define DH_F_DH_NEW_METHOD				 105
 #define DH_F_GENERATE_KEY				 103
 #define DH_F_GENERATE_PARAMETERS			 104
@@ -225,6 +235,7 @@ void ERR_load_DH_strings(void);
 /* Reason codes. */
 #define DH_R_BAD_GENERATOR				 101
 #define DH_R_INVALID_PUBKEY				 102
+#define DH_R_KEY_SIZE_TOO_SMALL				 104
 #define DH_R_MODULUS_TOO_LARGE				 103
 #define DH_R_NO_PRIVATE_VALUE				 100
 
diff --git a/src/lib/libcrypto/dh/dh_asn1.c b/src/lib/libcrypto/dh/dh_asn1.c
index 769b5b68c5..76740af2bd 100644
--- a/src/lib/libcrypto/dh/dh_asn1.c
+++ b/src/lib/libcrypto/dh/dh_asn1.c
@@ -1,5 +1,5 @@
 /* dh_asn1.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2000.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/dh/dh_check.c b/src/lib/libcrypto/dh/dh_check.c
index b846913004..316cb9221d 100644
--- a/src/lib/libcrypto/dh/dh_check.c
+++ b/src/lib/libcrypto/dh/dh_check.c
@@ -70,6 +70,8 @@
  * should hold.
  */
 
+#ifndef OPENSSL_FIPS
+
 int DH_check(const DH *dh, int *ret)
 	{
 	int ok=0;
@@ -140,3 +142,5 @@ err:
 	if (q != NULL) BN_free(q);
 	return(ok);
 	}
+
+#endif
diff --git a/src/lib/libcrypto/dh/dh_err.c b/src/lib/libcrypto/dh/dh_err.c
index a2d8196ecb..13263c81c1 100644
--- a/src/lib/libcrypto/dh/dh_err.c
+++ b/src/lib/libcrypto/dh/dh_err.c
@@ -1,6 +1,6 @@
 /* crypto/dh/dh_err.c */
 /* ====================================================================
- * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-2007 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -74,6 +74,9 @@ static ERR_STRING_DATA DH_str_functs[]=
 {ERR_FUNC(DH_F_DHPARAMS_PRINT),	"DHparams_print"},
 {ERR_FUNC(DH_F_DHPARAMS_PRINT_FP),	"DHparams_print_fp"},
 {ERR_FUNC(DH_F_DH_BUILTIN_GENPARAMS),	"DH_BUILTIN_GENPARAMS"},
+{ERR_FUNC(DH_F_DH_COMPUTE_KEY),	"DH_compute_key"},
+{ERR_FUNC(DH_F_DH_GENERATE_KEY),	"DH_generate_key"},
+{ERR_FUNC(DH_F_DH_GENERATE_PARAMETERS),	"DH_generate_parameters"},
 {ERR_FUNC(DH_F_DH_NEW_METHOD),	"DH_new_method"},
 {ERR_FUNC(DH_F_GENERATE_KEY),	"GENERATE_KEY"},
 {ERR_FUNC(DH_F_GENERATE_PARAMETERS),	"GENERATE_PARAMETERS"},
@@ -84,6 +87,7 @@ static ERR_STRING_DATA DH_str_reasons[]=
 	{
 {ERR_REASON(DH_R_BAD_GENERATOR)          ,"bad generator"},
 {ERR_REASON(DH_R_INVALID_PUBKEY)         ,"invalid public key"},
+{ERR_REASON(DH_R_KEY_SIZE_TOO_SMALL)     ,"key size too small"},
 {ERR_REASON(DH_R_MODULUS_TOO_LARGE)      ,"modulus too large"},
 {ERR_REASON(DH_R_NO_PRIVATE_VALUE)       ,"no private value"},
 {0,NULL}
diff --git a/src/lib/libcrypto/dh/dh_gen.c b/src/lib/libcrypto/dh/dh_gen.c
index cfd5b11868..999e1deb40 100644
--- a/src/lib/libcrypto/dh/dh_gen.c
+++ b/src/lib/libcrypto/dh/dh_gen.c
@@ -66,6 +66,8 @@
 #include <openssl/bn.h>
 #include <openssl/dh.h>
 
+#ifndef OPENSSL_FIPS
+
 static int dh_builtin_genparams(DH *ret, int prime_len, int generator, BN_GENCB *cb);
 
 int DH_generate_parameters_ex(DH *ret, int prime_len, int generator, BN_GENCB *cb)
@@ -173,3 +175,5 @@ err:
 		}
 	return ok;
 	}
+
+#endif
diff --git a/src/lib/libcrypto/dh/dh_key.c b/src/lib/libcrypto/dh/dh_key.c
index e7db440342..79dd331863 100644
--- a/src/lib/libcrypto/dh/dh_key.c
+++ b/src/lib/libcrypto/dh/dh_key.c
@@ -62,6 +62,8 @@
 #include <openssl/rand.h>
 #include <openssl/dh.h>
 
+#ifndef OPENSSL_FIPS
+
 static int generate_key(DH *dh);
 static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh);
 static int dh_bn_mod_exp(const DH *dh, BIGNUM *r,
@@ -261,3 +263,5 @@ static int dh_finish(DH *dh)
 		BN_MONT_CTX_free(dh->method_mont_p);
 	return(1);
 	}
+
+#endif
diff --git a/src/lib/libcrypto/dsa/dsa.h b/src/lib/libcrypto/dsa/dsa.h
index 3a8fe5b56b..702c50d6dc 100644
--- a/src/lib/libcrypto/dsa/dsa.h
+++ b/src/lib/libcrypto/dsa/dsa.h
@@ -88,6 +88,8 @@
 # define OPENSSL_DSA_MAX_MODULUS_BITS	10000
 #endif
 
+#define OPENSSL_DSA_FIPS_MIN_MODULUS_BITS 1024
+
 #define DSA_FLAG_CACHE_MONT_P	0x01
 #define DSA_FLAG_NO_EXP_CONSTTIME       0x02 /* new with 0.9.7h; the built-in DSA
                                               * implementation now uses constant time
@@ -97,6 +99,25 @@
                                               * be used for all exponents.
                                               */
 
+/* If this flag is set the DSA method is FIPS compliant and can be used
+ * in FIPS mode. This is set in the validated module method. If an
+ * application sets this flag in its own methods it is its reposibility
+ * to ensure the result is compliant.
+ */
+
+#define DSA_FLAG_FIPS_METHOD			0x0400
+
+/* If this flag is set the operations normally disabled in FIPS mode are
+ * permitted it is then the applications responsibility to ensure that the
+ * usage is compliant.
+ */
+
+#define DSA_FLAG_NON_FIPS_ALLOW			0x0400
+
+#ifdef OPENSSL_FIPS
+#define FIPS_DSA_SIZE_T	int
+#endif
+
 #ifdef  __cplusplus
 extern "C" {
 #endif
@@ -189,6 +210,11 @@ void	DSA_set_default_method(const DSA_METHOD *);
 const DSA_METHOD *DSA_get_default_method(void);
 int	DSA_set_method(DSA *dsa, const DSA_METHOD *);
 
+#ifdef OPENSSL_FIPS
+DSA *	FIPS_dsa_new(void);
+void	FIPS_dsa_free (DSA *r);
+#endif
+
 DSA *	DSA_new(void);
 DSA *	DSA_new_method(ENGINE *engine);
 void	DSA_free (DSA *r);
@@ -249,6 +275,11 @@ int	DSA_print_fp(FILE *bp, const DSA *x, int off);
 DH *DSA_dup_DH(const DSA *r);
 #endif
 
+#ifdef OPENSSL_FIPS
+int FIPS_dsa_sig_encode(unsigned char *out, DSA_SIG *sig);
+int FIPS_dsa_sig_decode(DSA_SIG *sig, const unsigned char *in, int inlen);
+#endif
+
 /* BEGIN ERROR CODES */
 /* The following lines are auto generated by the script mkerr.pl. Any changes
  * made after this point may be overwritten when the script is next run.
@@ -261,11 +292,16 @@ void ERR_load_DSA_strings(void);
 #define DSA_F_D2I_DSA_SIG				 110
 #define DSA_F_DSAPARAMS_PRINT				 100
 #define DSA_F_DSAPARAMS_PRINT_FP			 101
+#define DSA_F_DSA_BUILTIN_KEYGEN			 119
+#define DSA_F_DSA_BUILTIN_PARAMGEN			 118
 #define DSA_F_DSA_DO_SIGN				 112
 #define DSA_F_DSA_DO_VERIFY				 113
+#define DSA_F_DSA_GENERATE_PARAMETERS			 117
 #define DSA_F_DSA_NEW_METHOD				 103
 #define DSA_F_DSA_PRINT					 104
 #define DSA_F_DSA_PRINT_FP				 105
+#define DSA_F_DSA_SET_DEFAULT_METHOD			 115
+#define DSA_F_DSA_SET_METHOD				 116
 #define DSA_F_DSA_SIGN					 106
 #define DSA_F_DSA_SIGN_SETUP				 107
 #define DSA_F_DSA_SIG_NEW				 109
@@ -276,8 +312,11 @@ void ERR_load_DSA_strings(void);
 /* Reason codes. */
 #define DSA_R_BAD_Q_VALUE				 102
 #define DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE		 100
+#define DSA_R_KEY_SIZE_TOO_SMALL			 106
 #define DSA_R_MISSING_PARAMETERS			 101
 #define DSA_R_MODULUS_TOO_LARGE				 103
+#define DSA_R_NON_FIPS_METHOD				 104
+#define DSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE	 105
 
 #ifdef  __cplusplus
 }
diff --git a/src/lib/libcrypto/dsa/dsa_asn1.c b/src/lib/libcrypto/dsa/dsa_asn1.c
index 23fce555aa..0645facb4b 100644
--- a/src/lib/libcrypto/dsa/dsa_asn1.c
+++ b/src/lib/libcrypto/dsa/dsa_asn1.c
@@ -1,5 +1,5 @@
 /* dsa_asn1.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2000.
  */
 /* ====================================================================
@@ -61,6 +61,11 @@
 #include <openssl/dsa.h>
 #include <openssl/asn1.h>
 #include <openssl/asn1t.h>
+#include <openssl/bn.h>
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
+
 
 /* Override the default new methods */
 static int sig_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it)
@@ -83,7 +88,7 @@ ASN1_SEQUENCE_cb(DSA_SIG, sig_cb) = {
 	ASN1_SIMPLE(DSA_SIG, s, CBIGNUM)
 } ASN1_SEQUENCE_END_cb(DSA_SIG, DSA_SIG)
 
-IMPLEMENT_ASN1_FUNCTIONS_const(DSA_SIG)
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA_SIG,DSA_SIG,DSA_SIG)
 
 /* Override the default free and new methods */
 static int dsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it)
@@ -138,3 +143,76 @@ ASN1_CHOICE_cb(DSAPublicKey, dsa_cb) = {
 } ASN1_CHOICE_END_cb(DSA, DSAPublicKey, write_params)
 
 IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA, DSAPublicKey, DSAPublicKey)
+
+int DSA_sign(int type, const unsigned char *dgst, int dlen, unsigned char *sig,
+	     unsigned int *siglen, DSA *dsa)
+	{
+	DSA_SIG *s;
+#ifdef OPENSSL_FIPS
+	if(FIPS_mode() && !(dsa->flags & DSA_FLAG_NON_FIPS_ALLOW))
+		{
+		DSAerr(DSA_F_DSA_SIGN, DSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE);
+		return 0;
+		}
+#endif
+	s=DSA_do_sign(dgst,dlen,dsa);
+	if (s == NULL)
+		{
+		*siglen=0;
+		return(0);
+		}
+	*siglen=i2d_DSA_SIG(s,&sig);
+	DSA_SIG_free(s);
+	return(1);
+	}
+
+int DSA_size(const DSA *r)
+	{
+	int ret,i;
+	ASN1_INTEGER bs;
+	unsigned char buf[4];	/* 4 bytes looks really small.
+				   However, i2d_ASN1_INTEGER() will not look
+				   beyond the first byte, as long as the second
+				   parameter is NULL. */
+
+	i=BN_num_bits(r->q);
+	bs.length=(i+7)/8;
+	bs.data=buf;
+	bs.type=V_ASN1_INTEGER;
+	/* If the top bit is set the asn1 encoding is 1 larger. */
+	buf[0]=0xff;	
+
+	i=i2d_ASN1_INTEGER(&bs,NULL);
+	i+=i; /* r and s */
+	ret=ASN1_object_size(1,i,V_ASN1_SEQUENCE);
+	return(ret);
+	}
+
+/* data has already been hashed (probably with SHA or SHA-1). */
+/* returns
+ *      1: correct signature
+ *      0: incorrect signature
+ *     -1: error
+ */
+int DSA_verify(int type, const unsigned char *dgst, int dgst_len,
+	     const unsigned char *sigbuf, int siglen, DSA *dsa)
+	{
+	DSA_SIG *s;
+	int ret=-1;
+#ifdef OPENSSL_FIPS
+	if(FIPS_mode() && !(dsa->flags & DSA_FLAG_NON_FIPS_ALLOW))
+		{
+		DSAerr(DSA_F_DSA_VERIFY, DSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE);
+		return 0;
+		}
+#endif
+
+	s = DSA_SIG_new();
+	if (s == NULL) return(ret);
+	if (d2i_DSA_SIG(&s,&sigbuf,siglen) == NULL) goto err;
+	ret=DSA_do_verify(dgst,dgst_len,s,dsa);
+err:
+	DSA_SIG_free(s);
+	return(ret);
+	}
+
diff --git a/src/lib/libcrypto/dsa/dsa_err.c b/src/lib/libcrypto/dsa/dsa_err.c
index 768711994b..872839af94 100644
--- a/src/lib/libcrypto/dsa/dsa_err.c
+++ b/src/lib/libcrypto/dsa/dsa_err.c
@@ -1,6 +1,6 @@
 /* crypto/dsa/dsa_err.c */
 /* ====================================================================
- * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-2007 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -73,11 +73,16 @@ static ERR_STRING_DATA DSA_str_functs[]=
 {ERR_FUNC(DSA_F_D2I_DSA_SIG),	"d2i_DSA_SIG"},
 {ERR_FUNC(DSA_F_DSAPARAMS_PRINT),	"DSAparams_print"},
 {ERR_FUNC(DSA_F_DSAPARAMS_PRINT_FP),	"DSAparams_print_fp"},
+{ERR_FUNC(DSA_F_DSA_BUILTIN_KEYGEN),	"DSA_BUILTIN_KEYGEN"},
+{ERR_FUNC(DSA_F_DSA_BUILTIN_PARAMGEN),	"DSA_BUILTIN_PARAMGEN"},
 {ERR_FUNC(DSA_F_DSA_DO_SIGN),	"DSA_do_sign"},
 {ERR_FUNC(DSA_F_DSA_DO_VERIFY),	"DSA_do_verify"},
+{ERR_FUNC(DSA_F_DSA_GENERATE_PARAMETERS),	"DSA_generate_parameters"},
 {ERR_FUNC(DSA_F_DSA_NEW_METHOD),	"DSA_new_method"},
 {ERR_FUNC(DSA_F_DSA_PRINT),	"DSA_print"},
 {ERR_FUNC(DSA_F_DSA_PRINT_FP),	"DSA_print_fp"},
+{ERR_FUNC(DSA_F_DSA_SET_DEFAULT_METHOD),	"DSA_set_default_method"},
+{ERR_FUNC(DSA_F_DSA_SET_METHOD),	"DSA_set_method"},
 {ERR_FUNC(DSA_F_DSA_SIGN),	"DSA_sign"},
 {ERR_FUNC(DSA_F_DSA_SIGN_SETUP),	"DSA_sign_setup"},
 {ERR_FUNC(DSA_F_DSA_SIG_NEW),	"DSA_SIG_new"},
@@ -91,8 +96,11 @@ static ERR_STRING_DATA DSA_str_reasons[]=
 	{
 {ERR_REASON(DSA_R_BAD_Q_VALUE)           ,"bad q value"},
 {ERR_REASON(DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE),"data too large for key size"},
+{ERR_REASON(DSA_R_KEY_SIZE_TOO_SMALL)    ,"key size too small"},
 {ERR_REASON(DSA_R_MISSING_PARAMETERS)    ,"missing parameters"},
 {ERR_REASON(DSA_R_MODULUS_TOO_LARGE)     ,"modulus too large"},
+{ERR_REASON(DSA_R_NON_FIPS_METHOD)       ,"non fips method"},
+{ERR_REASON(DSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE),"operation not allowed in fips mode"},
 {0,NULL}
 	};
 
diff --git a/src/lib/libcrypto/dsa/dsa_gen.c b/src/lib/libcrypto/dsa/dsa_gen.c
index ca0b86a6cf..6f1728e3cf 100644
--- a/src/lib/libcrypto/dsa/dsa_gen.c
+++ b/src/lib/libcrypto/dsa/dsa_gen.c
@@ -82,6 +82,8 @@
 #include <openssl/rand.h>
 #include <openssl/sha.h>
 
+#ifndef OPENSSL_FIPS
+
 static int dsa_builtin_paramgen(DSA *ret, int bits,
 		unsigned char *seed_in, int seed_len,
 		int *counter_ret, unsigned long *h_ret, BN_GENCB *cb);
@@ -320,3 +322,4 @@ err:
 	return ok;
 	}
 #endif
+#endif
diff --git a/src/lib/libcrypto/dsa/dsa_key.c b/src/lib/libcrypto/dsa/dsa_key.c
index c4aa86bc6d..5e39124230 100644
--- a/src/lib/libcrypto/dsa/dsa_key.c
+++ b/src/lib/libcrypto/dsa/dsa_key.c
@@ -64,6 +64,8 @@
 #include <openssl/dsa.h>
 #include <openssl/rand.h>
 
+#ifndef OPENSSL_FIPS
+
 static int dsa_builtin_keygen(DSA *dsa);
 
 int DSA_generate_key(DSA *dsa)
@@ -126,3 +128,5 @@ err:
 	return(ok);
 	}
 #endif
+
+#endif
diff --git a/src/lib/libcrypto/dsa/dsa_lib.c b/src/lib/libcrypto/dsa/dsa_lib.c
index e9b75902db..7ac9dc8c89 100644
--- a/src/lib/libcrypto/dsa/dsa_lib.c
+++ b/src/lib/libcrypto/dsa/dsa_lib.c
@@ -76,6 +76,14 @@ static const DSA_METHOD *default_DSA_method = NULL;
 
 void DSA_set_default_method(const DSA_METHOD *meth)
 	{
+#ifdef OPENSSL_FIPS
+	if (FIPS_mode() && !(meth->flags & DSA_FLAG_FIPS_METHOD))
+		{
+		DSAerr(DSA_F_DSA_SET_DEFAULT_METHOD, DSA_R_NON_FIPS_METHOD);
+		return;
+		}
+#endif
+		
 	default_DSA_method = meth;
 	}
 
@@ -96,6 +104,13 @@ int DSA_set_method(DSA *dsa, const DSA_METHOD *meth)
 	/* NB: The caller is specifically setting a method, so it's not up to us
 	 * to deal with which ENGINE it comes from. */
         const DSA_METHOD *mtmp;
+#ifdef OPENSSL_FIPS
+	if (FIPS_mode() && !(meth->flags & DSA_FLAG_FIPS_METHOD))
+		{
+		DSAerr(DSA_F_DSA_SET_METHOD, DSA_R_NON_FIPS_METHOD);
+		return 0;
+		}
+#endif
         mtmp = dsa->meth;
         if (mtmp->finish) mtmp->finish(dsa);
 #ifndef OPENSSL_NO_ENGINE
@@ -147,6 +162,18 @@ DSA *DSA_new_method(ENGINE *engine)
 			}
 		}
 #endif
+#ifdef OPENSSL_FIPS
+	if (FIPS_mode() && !(ret->meth->flags & DSA_FLAG_FIPS_METHOD))
+		{
+		DSAerr(DSA_F_DSA_NEW_METHOD, DSA_R_NON_FIPS_METHOD);
+#ifndef OPENSSL_NO_ENGINE
+		if (ret->engine)
+			ENGINE_finish(ret->engine);
+#endif
+		OPENSSL_free(ret);
+		return NULL;
+		}
+#endif
 
 	ret->pad=0;
 	ret->version=0;
@@ -233,28 +260,6 @@ int DSA_up_ref(DSA *r)
 	return ((i > 1) ? 1 : 0);
 	}
 
-int DSA_size(const DSA *r)
-	{
-	int ret,i;
-	ASN1_INTEGER bs;
-	unsigned char buf[4];	/* 4 bytes looks really small.
-				   However, i2d_ASN1_INTEGER() will not look
-				   beyond the first byte, as long as the second
-				   parameter is NULL. */
-
-	i=BN_num_bits(r->q);
-	bs.length=(i+7)/8;
-	bs.data=buf;
-	bs.type=V_ASN1_INTEGER;
-	/* If the top bit is set the asn1 encoding is 1 larger. */
-	buf[0]=0xff;	
-
-	i=i2d_ASN1_INTEGER(&bs,NULL);
-	i+=i; /* r and s */
-	ret=ASN1_object_size(1,i,V_ASN1_SEQUENCE);
-	return(ret);
-	}
-
 int DSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
 	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
         {
diff --git a/src/lib/libcrypto/dsa/dsa_ossl.c b/src/lib/libcrypto/dsa/dsa_ossl.c
index 75ff7cc4af..412cf1d88b 100644
--- a/src/lib/libcrypto/dsa/dsa_ossl.c
+++ b/src/lib/libcrypto/dsa/dsa_ossl.c
@@ -65,6 +65,8 @@
 #include <openssl/rand.h>
 #include <openssl/asn1.h>
 
+#ifndef OPENSSL_FIPS
+
 static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa);
 static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp);
 static int dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig,
@@ -391,3 +393,4 @@ static int dsa_finish(DSA *dsa)
 	return(1);
 }
 
+#endif
diff --git a/src/lib/libcrypto/dsa/dsa_sign.c b/src/lib/libcrypto/dsa/dsa_sign.c
index 89205026f0..4cfbbe57a8 100644
--- a/src/lib/libcrypto/dsa/dsa_sign.c
+++ b/src/lib/libcrypto/dsa/dsa_sign.c
@@ -64,29 +64,32 @@
 #include <openssl/dsa.h>
 #include <openssl/rand.h>
 #include <openssl/asn1.h>
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
 
-DSA_SIG * DSA_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
-	{
-	return dsa->meth->dsa_do_sign(dgst, dlen, dsa);
-	}
 
-int DSA_sign(int type, const unsigned char *dgst, int dlen, unsigned char *sig,
-	     unsigned int *siglen, DSA *dsa)
+DSA_SIG * DSA_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
 	{
-	DSA_SIG *s;
-	s=DSA_do_sign(dgst,dlen,dsa);
-	if (s == NULL)
+#ifdef OPENSSL_FIPS
+	if(FIPS_mode() && !(dsa->flags & DSA_FLAG_NON_FIPS_ALLOW))
 		{
-		*siglen=0;
-		return(0);
+		DSAerr(DSA_F_DSA_DO_SIGN, DSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE);
+		return NULL;
 		}
-	*siglen=i2d_DSA_SIG(s,&sig);
-	DSA_SIG_free(s);
-	return(1);
+#endif
+	return dsa->meth->dsa_do_sign(dgst, dlen, dsa);
 	}
 
 int DSA_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)
 	{
+#ifdef OPENSSL_FIPS
+	if(FIPS_mode() && !(dsa->flags & DSA_FLAG_NON_FIPS_ALLOW))
+		{
+		DSAerr(DSA_F_DSA_SIGN_SETUP, DSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE);
+		return 0;
+		}
+#endif
 	return dsa->meth->dsa_sign_setup(dsa, ctx_in, kinvp, rp);
 	}
 
diff --git a/src/lib/libcrypto/dsa/dsa_vrf.c b/src/lib/libcrypto/dsa/dsa_vrf.c
index c4aeddd056..c75e423048 100644
--- a/src/lib/libcrypto/dsa/dsa_vrf.c
+++ b/src/lib/libcrypto/dsa/dsa_vrf.c
@@ -64,31 +64,21 @@
 #include <openssl/dsa.h>
 #include <openssl/rand.h>
 #include <openssl/asn1.h>
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
+
 #include <openssl/asn1_mac.h>
 
 int DSA_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig,
 		  DSA *dsa)
 	{
+#ifdef OPENSSL_FIPS
+	if(FIPS_mode() && !(dsa->flags & DSA_FLAG_NON_FIPS_ALLOW))
+		{
+		DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE);
+		return 0;
+		}
+#endif
 	return dsa->meth->dsa_do_verify(dgst, dgst_len, sig, dsa);
 	}
-
-/* data has already been hashed (probably with SHA or SHA-1). */
-/* returns
- *      1: correct signature
- *      0: incorrect signature
- *     -1: error
- */
-int DSA_verify(int type, const unsigned char *dgst, int dgst_len,
-	     const unsigned char *sigbuf, int siglen, DSA *dsa)
-	{
-	DSA_SIG *s;
-	int ret=-1;
-
-	s = DSA_SIG_new();
-	if (s == NULL) return(ret);
-	if (d2i_DSA_SIG(&s,&sigbuf,siglen) == NULL) goto err;
-	ret=DSA_do_verify(dgst,dgst_len,s,dsa);
-err:
-	DSA_SIG_free(s);
-	return(ret);
-	}
diff --git a/src/lib/libcrypto/ec/ec_key.c b/src/lib/libcrypto/ec/ec_key.c
index 3d6c900b95..12fb0e6d6d 100644
--- a/src/lib/libcrypto/ec/ec_key.c
+++ b/src/lib/libcrypto/ec/ec_key.c
@@ -296,7 +296,7 @@ int EC_KEY_check_key(const EC_KEY *eckey)
 	{
 	int	ok   = 0;
 	BN_CTX	*ctx = NULL;
-	BIGNUM	*order  = NULL;
+	const BIGNUM	*order  = NULL;
 	EC_POINT *point = NULL;
 
 	if (!eckey || !eckey->group || !eckey->pub_key)
@@ -307,8 +307,6 @@ int EC_KEY_check_key(const EC_KEY *eckey)
 	
 	if ((ctx = BN_CTX_new()) == NULL)
 		goto err;
-	if ((order = BN_new()) == NULL)
-		goto err;
 	if ((point = EC_POINT_new(eckey->group)) == NULL)
 		goto err;
 
@@ -319,17 +317,13 @@ int EC_KEY_check_key(const EC_KEY *eckey)
 		goto err;
 		}
 	/* testing whether pub_key * order is the point at infinity */
-	if (!EC_GROUP_get_order(eckey->group, order, ctx))
+	order = &eckey->group->order;
+	if (BN_is_zero(order))
 		{
 		ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_GROUP_ORDER);
 		goto err;
 		}
-	if (!EC_POINT_copy(point, eckey->pub_key))
-		{
-		ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB);
-		goto err;
-		}
-	if (!EC_POINT_mul(eckey->group, point, order, NULL, NULL, ctx))
+	if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx))
 		{
 		ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB);
 		goto err;
@@ -366,8 +360,6 @@ int EC_KEY_check_key(const EC_KEY *eckey)
 err:
 	if (ctx   != NULL)
 		BN_CTX_free(ctx);
-	if (order != NULL)
-		BN_free(order);
 	if (point != NULL)
 		EC_POINT_free(point);
 	return(ok);
diff --git a/src/lib/libcrypto/engine/eng_all.c b/src/lib/libcrypto/engine/eng_all.c
index 8599046717..d29cd57dc2 100644
--- a/src/lib/libcrypto/engine/eng_all.c
+++ b/src/lib/libcrypto/engine/eng_all.c
@@ -107,6 +107,9 @@ void ENGINE_load_builtin_engines(void)
 #if defined(__OpenBSD__) || defined(__FreeBSD__)
 	ENGINE_load_cryptodev();
 #endif
+#if defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_NO_CAPIENG)
+	ENGINE_load_capi();
+#endif
 #endif
 	}
 
diff --git a/src/lib/libcrypto/engine/eng_cnf.c b/src/lib/libcrypto/engine/eng_cnf.c
index a97e01e619..08066cea59 100644
--- a/src/lib/libcrypto/engine/eng_cnf.c
+++ b/src/lib/libcrypto/engine/eng_cnf.c
@@ -1,5 +1,5 @@
 /* eng_cnf.c */
-/* Written by Stephen Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Stephen Henson (steve@openssl.org) for the OpenSSL
  * project 2001.
  */
 /* ====================================================================
@@ -98,6 +98,8 @@ static int int_engine_configure(char *name, char *value, const CONF *cnf)
 	CONF_VALUE *ecmd;
 	char *ctrlname, *ctrlvalue;
 	ENGINE *e = NULL;
+	int soft = 0;
+
 	name = skip_dot(name);
 #ifdef ENGINE_CONF_DEBUG
 	fprintf(stderr, "Configuring engine %s\n", name);
@@ -125,6 +127,8 @@ static int int_engine_configure(char *name, char *value, const CONF *cnf)
 		/* Override engine name to use */
 		if (!strcmp(ctrlname, "engine_id"))
 			name = ctrlvalue;
+		else if (!strcmp(ctrlname, "soft_load"))
+			soft = 1;
 		/* Load a dynamic ENGINE */
 		else if (!strcmp(ctrlname, "dynamic_path"))
 			{
@@ -147,6 +151,11 @@ static int int_engine_configure(char *name, char *value, const CONF *cnf)
 			if (!e)
 				{
 				e = ENGINE_by_id(name);
+				if (!e && soft)
+					{
+					ERR_clear_error();
+					return 1;
+					}
 				if (!e)
 					return 0;
 				}
diff --git a/src/lib/libcrypto/engine/eng_err.c b/src/lib/libcrypto/engine/eng_err.c
index 369f2e22d3..574ffbb5c0 100644
--- a/src/lib/libcrypto/engine/eng_err.c
+++ b/src/lib/libcrypto/engine/eng_err.c
@@ -1,6 +1,6 @@
 /* crypto/engine/eng_err.c */
 /* ====================================================================
- * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-2008 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -92,6 +92,7 @@ static ERR_STRING_DATA ENGINE_str_functs[]=
 {ERR_FUNC(ENGINE_F_ENGINE_LIST_REMOVE),	"ENGINE_LIST_REMOVE"},
 {ERR_FUNC(ENGINE_F_ENGINE_LOAD_PRIVATE_KEY),	"ENGINE_load_private_key"},
 {ERR_FUNC(ENGINE_F_ENGINE_LOAD_PUBLIC_KEY),	"ENGINE_load_public_key"},
+{ERR_FUNC(ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT),	"ENGINE_load_ssl_client_cert"},
 {ERR_FUNC(ENGINE_F_ENGINE_NEW),	"ENGINE_new"},
 {ERR_FUNC(ENGINE_F_ENGINE_REMOVE),	"ENGINE_remove"},
 {ERR_FUNC(ENGINE_F_ENGINE_SET_DEFAULT_STRING),	"ENGINE_set_default_string"},
diff --git a/src/lib/libcrypto/engine/eng_int.h b/src/lib/libcrypto/engine/eng_int.h
index a5b1edebf4..a66f107a44 100644
--- a/src/lib/libcrypto/engine/eng_int.h
+++ b/src/lib/libcrypto/engine/eng_int.h
@@ -170,6 +170,8 @@ struct engine_st
 	ENGINE_LOAD_KEY_PTR load_privkey;
 	ENGINE_LOAD_KEY_PTR load_pubkey;
 
+	ENGINE_SSL_CLIENT_CERT_PTR load_ssl_client_cert;
+
 	const ENGINE_CMD_DEFN *cmd_defns;
 	int flags;
 	/* reference count on the structure itself */
diff --git a/src/lib/libcrypto/engine/eng_padlock.c b/src/lib/libcrypto/engine/eng_padlock.c
index 1ba9d85db4..743558ab33 100644
--- a/src/lib/libcrypto/engine/eng_padlock.c
+++ b/src/lib/libcrypto/engine/eng_padlock.c
@@ -234,8 +234,8 @@ padlock_bind_fn(ENGINE *e, const char *id)
 	return 1;
 }
 
-IMPLEMENT_DYNAMIC_CHECK_FN ();
-IMPLEMENT_DYNAMIC_BIND_FN (padlock_bind_fn);
+IMPLEMENT_DYNAMIC_CHECK_FN ()
+IMPLEMENT_DYNAMIC_BIND_FN (padlock_bind_fn)
 #endif /* DYNAMIC_ENGINE */
 
 /* ===== Here comes the "real" engine ===== */
diff --git a/src/lib/libcrypto/engine/eng_pkey.c b/src/lib/libcrypto/engine/eng_pkey.c
index bc8b21abec..1dfa2e3664 100644
--- a/src/lib/libcrypto/engine/eng_pkey.c
+++ b/src/lib/libcrypto/engine/eng_pkey.c
@@ -69,6 +69,13 @@ int ENGINE_set_load_pubkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpub_f)
 	return 1;
 	}
 
+int ENGINE_set_load_ssl_client_cert_function(ENGINE *e,
+				ENGINE_SSL_CLIENT_CERT_PTR loadssl_f)
+	{
+	e->load_ssl_client_cert = loadssl_f;
+	return 1;
+	}
+
 ENGINE_LOAD_KEY_PTR ENGINE_get_load_privkey_function(const ENGINE *e)
 	{
 	return e->load_privkey;
@@ -79,6 +86,11 @@ ENGINE_LOAD_KEY_PTR ENGINE_get_load_pubkey_function(const ENGINE *e)
 	return e->load_pubkey;
 	}
 
+ENGINE_SSL_CLIENT_CERT_PTR ENGINE_get_ssl_client_cert_function(const ENGINE *e)
+	{
+	return e->load_ssl_client_cert;
+	}
+
 /* API functions to load public/private keys */
 
 EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id,
@@ -152,3 +164,33 @@ EVP_PKEY *ENGINE_load_public_key(ENGINE *e, const char *key_id,
 		}
 	return pkey;
 	}
+
+int ENGINE_load_ssl_client_cert(ENGINE *e, SSL *s,
+	STACK_OF(X509_NAME) *ca_dn, X509 **pcert, EVP_PKEY **ppkey,
+	STACK_OF(X509) **pother, UI_METHOD *ui_method, void *callback_data)
+	{
+
+	if(e == NULL)
+		{
+		ENGINEerr(ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT,
+			ERR_R_PASSED_NULL_PARAMETER);
+		return 0;
+		}
+	CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+	if(e->funct_ref == 0)
+		{
+		CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+		ENGINEerr(ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT,
+			ENGINE_R_NOT_INITIALISED);
+		return 0;
+		}
+	CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+	if (!e->load_ssl_client_cert)
+		{
+		ENGINEerr(ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT,
+			ENGINE_R_NO_LOAD_FUNCTION);
+		return 0;
+		}
+	return e->load_ssl_client_cert(e, s, ca_dn, pcert, ppkey, pother,
+					ui_method, callback_data);
+	}
diff --git a/src/lib/libcrypto/engine/engine.h b/src/lib/libcrypto/engine/engine.h
index 3ec59338ff..f503595ece 100644
--- a/src/lib/libcrypto/engine/engine.h
+++ b/src/lib/libcrypto/engine/engine.h
@@ -93,6 +93,8 @@
 #include <openssl/err.h>
 #endif
 
+#include <openssl/x509.h>
+
 #include <openssl/ossl_typ.h>
 #include <openssl/symhacks.h>
 
@@ -278,6 +280,9 @@ typedef int (*ENGINE_CTRL_FUNC_PTR)(ENGINE *, int, long, void *, void (*f)(void)
 /* Generic load_key function pointer */
 typedef EVP_PKEY * (*ENGINE_LOAD_KEY_PTR)(ENGINE *, const char *,
 	UI_METHOD *ui_method, void *callback_data);
+typedef int (*ENGINE_SSL_CLIENT_CERT_PTR)(ENGINE *, SSL *ssl,
+	STACK_OF(X509_NAME) *ca_dn, X509 **pcert, EVP_PKEY **pkey,
+	STACK_OF(X509) **pother, UI_METHOD *ui_method, void *callback_data);
 /* These callback types are for an ENGINE's handler for cipher and digest logic.
  * These handlers have these prototypes;
  *   int foo(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid);
@@ -334,6 +339,9 @@ void ENGINE_load_ubsec(void);
 void ENGINE_load_cryptodev(void);
 void ENGINE_load_padlock(void);
 void ENGINE_load_builtin_engines(void);
+#ifndef OPENSSL_NO_CAPIENG
+void ENGINE_load_capi(void);
+#endif
 
 /* Get and set global flags (ENGINE_TABLE_FLAG_***) for the implementation
  * "registry" handling. */
@@ -459,6 +467,8 @@ int ENGINE_set_finish_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR finish_f);
 int ENGINE_set_ctrl_function(ENGINE *e, ENGINE_CTRL_FUNC_PTR ctrl_f);
 int ENGINE_set_load_privkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpriv_f);
 int ENGINE_set_load_pubkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpub_f);
+int ENGINE_set_load_ssl_client_cert_function(ENGINE *e,
+				ENGINE_SSL_CLIENT_CERT_PTR loadssl_f);
 int ENGINE_set_ciphers(ENGINE *e, ENGINE_CIPHERS_PTR f);
 int ENGINE_set_digests(ENGINE *e, ENGINE_DIGESTS_PTR f);
 int ENGINE_set_flags(ENGINE *e, int flags);
@@ -494,6 +504,7 @@ ENGINE_GEN_INT_FUNC_PTR ENGINE_get_finish_function(const ENGINE *e);
 ENGINE_CTRL_FUNC_PTR ENGINE_get_ctrl_function(const ENGINE *e);
 ENGINE_LOAD_KEY_PTR ENGINE_get_load_privkey_function(const ENGINE *e);
 ENGINE_LOAD_KEY_PTR ENGINE_get_load_pubkey_function(const ENGINE *e);
+ENGINE_SSL_CLIENT_CERT_PTR ENGINE_get_ssl_client_cert_function(const ENGINE *e);
 ENGINE_CIPHERS_PTR ENGINE_get_ciphers(const ENGINE *e);
 ENGINE_DIGESTS_PTR ENGINE_get_digests(const ENGINE *e);
 const EVP_CIPHER *ENGINE_get_cipher(ENGINE *e, int nid);
@@ -529,6 +540,10 @@ EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id,
 	UI_METHOD *ui_method, void *callback_data);
 EVP_PKEY *ENGINE_load_public_key(ENGINE *e, const char *key_id,
 	UI_METHOD *ui_method, void *callback_data);
+int ENGINE_load_ssl_client_cert(ENGINE *e, SSL *s,
+	STACK_OF(X509_NAME) *ca_dn, X509 **pcert, EVP_PKEY **ppkey,
+	STACK_OF(X509) **pother,
+	UI_METHOD *ui_method, void *callback_data);
 
 /* This returns a pointer for the current ENGINE structure that
  * is (by default) performing any RSA operations. The value returned
@@ -723,6 +738,7 @@ void ERR_load_ENGINE_strings(void);
 #define ENGINE_F_ENGINE_LIST_REMOVE			 121
 #define ENGINE_F_ENGINE_LOAD_PRIVATE_KEY		 150
 #define ENGINE_F_ENGINE_LOAD_PUBLIC_KEY			 151
+#define ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT		 192
 #define ENGINE_F_ENGINE_NEW				 122
 #define ENGINE_F_ENGINE_REMOVE				 123
 #define ENGINE_F_ENGINE_SET_DEFAULT_STRING		 189
diff --git a/src/lib/libcrypto/err/err.c b/src/lib/libcrypto/err/err.c
index b6ff070e8f..292404a2fb 100644
--- a/src/lib/libcrypto/err/err.c
+++ b/src/lib/libcrypto/err/err.c
@@ -119,479 +119,9 @@
 #include <openssl/bio.h>
 #include <openssl/err.h>
 
-static void err_load_strings(int lib, ERR_STRING_DATA *str);
-
-static void ERR_STATE_free(ERR_STATE *s);
-#ifndef OPENSSL_NO_ERR
-static ERR_STRING_DATA ERR_str_libraries[]=
-	{
-{ERR_PACK(ERR_LIB_NONE,0,0)		,"unknown library"},
-{ERR_PACK(ERR_LIB_SYS,0,0)		,"system library"},
-{ERR_PACK(ERR_LIB_BN,0,0)		,"bignum routines"},
-{ERR_PACK(ERR_LIB_RSA,0,0)		,"rsa routines"},
-{ERR_PACK(ERR_LIB_DH,0,0)		,"Diffie-Hellman routines"},
-{ERR_PACK(ERR_LIB_EVP,0,0)		,"digital envelope routines"},
-{ERR_PACK(ERR_LIB_BUF,0,0)		,"memory buffer routines"},
-{ERR_PACK(ERR_LIB_OBJ,0,0)		,"object identifier routines"},
-{ERR_PACK(ERR_LIB_PEM,0,0)		,"PEM routines"},
-{ERR_PACK(ERR_LIB_DSA,0,0)		,"dsa routines"},
-{ERR_PACK(ERR_LIB_X509,0,0)		,"x509 certificate routines"},
-{ERR_PACK(ERR_LIB_ASN1,0,0)		,"asn1 encoding routines"},
-{ERR_PACK(ERR_LIB_CONF,0,0)		,"configuration file routines"},
-{ERR_PACK(ERR_LIB_CRYPTO,0,0)		,"common libcrypto routines"},
-{ERR_PACK(ERR_LIB_EC,0,0)		,"elliptic curve routines"},
-{ERR_PACK(ERR_LIB_SSL,0,0)		,"SSL routines"},
-{ERR_PACK(ERR_LIB_BIO,0,0)		,"BIO routines"},
-{ERR_PACK(ERR_LIB_PKCS7,0,0)		,"PKCS7 routines"},
-{ERR_PACK(ERR_LIB_X509V3,0,0)		,"X509 V3 routines"},
-{ERR_PACK(ERR_LIB_PKCS12,0,0)		,"PKCS12 routines"},
-{ERR_PACK(ERR_LIB_RAND,0,0)		,"random number generator"},
-{ERR_PACK(ERR_LIB_DSO,0,0)		,"DSO support routines"},
-{ERR_PACK(ERR_LIB_ENGINE,0,0)		,"engine routines"},
-{ERR_PACK(ERR_LIB_OCSP,0,0)		,"OCSP routines"},
-{ERR_PACK(ERR_LIB_CMS,0,0)		,"CMS routines"},
-{0,NULL},
-	};
-
-static ERR_STRING_DATA ERR_str_functs[]=
-	{
-	{ERR_PACK(0,SYS_F_FOPEN,0),     	"fopen"},
-	{ERR_PACK(0,SYS_F_CONNECT,0),		"connect"},
-	{ERR_PACK(0,SYS_F_GETSERVBYNAME,0),	"getservbyname"},
-	{ERR_PACK(0,SYS_F_SOCKET,0),		"socket"}, 
-	{ERR_PACK(0,SYS_F_IOCTLSOCKET,0),	"ioctlsocket"},
-	{ERR_PACK(0,SYS_F_BIND,0),		"bind"},
-	{ERR_PACK(0,SYS_F_LISTEN,0),		"listen"},
-	{ERR_PACK(0,SYS_F_ACCEPT,0),		"accept"},
-#ifdef OPENSSL_SYS_WINDOWS
-	{ERR_PACK(0,SYS_F_WSASTARTUP,0),	"WSAstartup"},
-#endif
-	{ERR_PACK(0,SYS_F_OPENDIR,0),		"opendir"},
-	{ERR_PACK(0,SYS_F_FREAD,0),		"fread"},
-	{0,NULL},
-	};
-
-static ERR_STRING_DATA ERR_str_reasons[]=
-	{
-{ERR_R_SYS_LIB				,"system lib"},
-{ERR_R_BN_LIB				,"BN lib"},
-{ERR_R_RSA_LIB				,"RSA lib"},
-{ERR_R_DH_LIB				,"DH lib"},
-{ERR_R_EVP_LIB				,"EVP lib"},
-{ERR_R_BUF_LIB				,"BUF lib"},
-{ERR_R_OBJ_LIB				,"OBJ lib"},
-{ERR_R_PEM_LIB				,"PEM lib"},
-{ERR_R_DSA_LIB				,"DSA lib"},
-{ERR_R_X509_LIB				,"X509 lib"},
-{ERR_R_ASN1_LIB				,"ASN1 lib"},
-{ERR_R_CONF_LIB				,"CONF lib"},
-{ERR_R_CRYPTO_LIB			,"CRYPTO lib"},
-{ERR_R_EC_LIB				,"EC lib"},
-{ERR_R_SSL_LIB				,"SSL lib"},
-{ERR_R_BIO_LIB				,"BIO lib"},
-{ERR_R_PKCS7_LIB			,"PKCS7 lib"},
-{ERR_R_X509V3_LIB			,"X509V3 lib"},
-{ERR_R_PKCS12_LIB			,"PKCS12 lib"},
-{ERR_R_RAND_LIB				,"RAND lib"},
-{ERR_R_DSO_LIB				,"DSO lib"},
-{ERR_R_ENGINE_LIB			,"ENGINE lib"},
-{ERR_R_OCSP_LIB				,"OCSP lib"},
-
-{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"},
-
-{ERR_R_FATAL                            ,"fatal"},
-{ERR_R_MALLOC_FAILURE			,"malloc failure"},
-{ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED	,"called a function you should not call"},
-{ERR_R_PASSED_NULL_PARAMETER		,"passed a null parameter"},
-{ERR_R_INTERNAL_ERROR			,"internal error"},
-{ERR_R_DISABLED				,"called a function that was disabled at compile-time"},
-
-{0,NULL},
-	};
-#endif
-
-
-/* Define the predeclared (but externally opaque) "ERR_FNS" type */
-struct st_ERR_FNS
-	{
-	/* Works on the "error_hash" string table */
-	LHASH *(*cb_err_get)(int create);
-	void (*cb_err_del)(void);
-	ERR_STRING_DATA *(*cb_err_get_item)(const ERR_STRING_DATA *);
-	ERR_STRING_DATA *(*cb_err_set_item)(ERR_STRING_DATA *);
-	ERR_STRING_DATA *(*cb_err_del_item)(ERR_STRING_DATA *);
-	/* Works on the "thread_hash" error-state table */
-	LHASH *(*cb_thread_get)(int create);
-	void (*cb_thread_release)(LHASH **hash);
-	ERR_STATE *(*cb_thread_get_item)(const ERR_STATE *);
-	ERR_STATE *(*cb_thread_set_item)(ERR_STATE *);
-	void (*cb_thread_del_item)(const ERR_STATE *);
-	/* Returns the next available error "library" numbers */
-	int (*cb_get_next_lib)(void);
-	};
-
-/* Predeclarations of the "err_defaults" functions */
-static LHASH *int_err_get(int create);
-static void int_err_del(void);
-static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *);
-static ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *);
-static ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *);
-static LHASH *int_thread_get(int create);
-static void int_thread_release(LHASH **hash);
-static ERR_STATE *int_thread_get_item(const ERR_STATE *);
-static ERR_STATE *int_thread_set_item(ERR_STATE *);
-static void int_thread_del_item(const ERR_STATE *);
-static int int_err_get_next_lib(void);
-/* The static ERR_FNS table using these defaults functions */
-static const ERR_FNS err_defaults =
-	{
-	int_err_get,
-	int_err_del,
-	int_err_get_item,
-	int_err_set_item,
-	int_err_del_item,
-	int_thread_get,
-	int_thread_release,
-	int_thread_get_item,
-	int_thread_set_item,
-	int_thread_del_item,
-	int_err_get_next_lib
-	};
-
-/* The replacable table of ERR_FNS functions we use at run-time */
-static const ERR_FNS *err_fns = NULL;
-
-/* Eg. rather than using "err_get()", use "ERRFN(err_get)()". */
-#define ERRFN(a) err_fns->cb_##a
-
-/* The internal state used by "err_defaults" - as such, the setting, reading,
- * creating, and deleting of this data should only be permitted via the
- * "err_defaults" functions. This way, a linked module can completely defer all
- * ERR state operation (together with requisite locking) to the implementations
- * and state in the loading application. */
-static LHASH *int_error_hash = NULL;
-static LHASH *int_thread_hash = NULL;
-static int int_thread_hash_references = 0;
-static int int_err_library_number= ERR_LIB_USER;
-
-/* Internal function that checks whether "err_fns" is set and if not, sets it to
- * the defaults. */
-static void err_fns_check(void)
-	{
-	if (err_fns) return;
-	
-	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
-	if (!err_fns)
-		err_fns = &err_defaults;
-	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
-	}
-
-/* API functions to get or set the underlying ERR functions. */
-
-const ERR_FNS *ERR_get_implementation(void)
-	{
-	err_fns_check();
-	return err_fns;
-	}
-
-int ERR_set_implementation(const ERR_FNS *fns)
-	{
-	int ret = 0;
-
-	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
-	/* It's too late if 'err_fns' is non-NULL. BTW: not much point setting
-	 * an error is there?! */
-	if (!err_fns)
-		{
-		err_fns = fns;
-		ret = 1;
-		}
-	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
-	return ret;
-	}
-
-/* These are the callbacks provided to "lh_new()" when creating the LHASH tables
- * internal to the "err_defaults" implementation. */
-
-/* static unsigned long err_hash(ERR_STRING_DATA *a); */
-static unsigned long err_hash(const void *a_void);
-/* static int err_cmp(ERR_STRING_DATA *a, ERR_STRING_DATA *b); */
-static int err_cmp(const void *a_void, const void *b_void);
-/* static unsigned long pid_hash(ERR_STATE *pid); */
-static unsigned long pid_hash(const void *pid_void);
-/* static int pid_cmp(ERR_STATE *a,ERR_STATE *pid); */
-static int pid_cmp(const void *a_void,const void *pid_void);
-static unsigned long get_error_values(int inc,int top,const char **file,int *line,
-				      const char **data,int *flags);
-
-/* The internal functions used in the "err_defaults" implementation */
-
-static LHASH *int_err_get(int create)
-	{
-	LHASH *ret = NULL;
-
-	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
-	if (!int_error_hash && create)
-		{
-		CRYPTO_push_info("int_err_get (err.c)");
-		int_error_hash = lh_new(err_hash, err_cmp);
-		CRYPTO_pop_info();
-		}
-	if (int_error_hash)
-		ret = int_error_hash;
-	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
-
-	return ret;
-	}
-
-static void int_err_del(void)
-	{
-	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
-	if (int_error_hash)
-		{
-		lh_free(int_error_hash);
-		int_error_hash = NULL;
-		}
-	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
-	}
-
-static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *d)
-	{
-	ERR_STRING_DATA *p;
-	LHASH *hash;
-
-	err_fns_check();
-	hash = ERRFN(err_get)(0);
-	if (!hash)
-		return NULL;
-
-	CRYPTO_r_lock(CRYPTO_LOCK_ERR);
-	p = (ERR_STRING_DATA *)lh_retrieve(hash, d);
-	CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
-
-	return p;
-	}
-
-static ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *d)
-	{
-	ERR_STRING_DATA *p;
-	LHASH *hash;
-
-	err_fns_check();
-	hash = ERRFN(err_get)(1);
-	if (!hash)
-		return NULL;
-
-	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
-	p = (ERR_STRING_DATA *)lh_insert(hash, d);
-	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
-
-	return p;
-	}
-
-static ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *d)
-	{
-	ERR_STRING_DATA *p;
-	LHASH *hash;
-
-	err_fns_check();
-	hash = ERRFN(err_get)(0);
-	if (!hash)
-		return NULL;
-
-	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
-	p = (ERR_STRING_DATA *)lh_delete(hash, d);
-	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
-
-	return p;
-	}
-
-static LHASH *int_thread_get(int create)
-	{
-	LHASH *ret = NULL;
-
-	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
-	if (!int_thread_hash && create)
-		{
-		CRYPTO_push_info("int_thread_get (err.c)");
-		int_thread_hash = lh_new(pid_hash, pid_cmp);
-		CRYPTO_pop_info();
-		}
-	if (int_thread_hash)
-		{
-		int_thread_hash_references++;
-		ret = int_thread_hash;
-		}
-	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
-	return ret;
-	}
-
-static void int_thread_release(LHASH **hash)
-	{
-	int i;
-
-	if (hash == NULL || *hash == NULL)
-		return;
-
-	i = CRYPTO_add(&int_thread_hash_references, -1, CRYPTO_LOCK_ERR);
-
-#ifdef REF_PRINT
-	fprintf(stderr,"%4d:%s\n",int_thread_hash_references,"ERR");
-#endif
-	if (i > 0) return;
-#ifdef REF_CHECK
-	if (i < 0)
-		{
-		fprintf(stderr,"int_thread_release, bad reference count\n");
-		abort(); /* ok */
-		}
-#endif
-	*hash = NULL;
-	}
-
-static ERR_STATE *int_thread_get_item(const ERR_STATE *d)
-	{
-	ERR_STATE *p;
-	LHASH *hash;
-
-	err_fns_check();
-	hash = ERRFN(thread_get)(0);
-	if (!hash)
-		return NULL;
-
-	CRYPTO_r_lock(CRYPTO_LOCK_ERR);
-	p = (ERR_STATE *)lh_retrieve(hash, d);
-	CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
-
-	ERRFN(thread_release)(&hash);
-	return p;
-	}
-
-static ERR_STATE *int_thread_set_item(ERR_STATE *d)
-	{
-	ERR_STATE *p;
-	LHASH *hash;
-
-	err_fns_check();
-	hash = ERRFN(thread_get)(1);
-	if (!hash)
-		return NULL;
-
-	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
-	p = (ERR_STATE *)lh_insert(hash, d);
-	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
-
-	ERRFN(thread_release)(&hash);
-	return p;
-	}
-
-static void int_thread_del_item(const ERR_STATE *d)
-	{
-	ERR_STATE *p;
-	LHASH *hash;
-
-	err_fns_check();
-	hash = ERRFN(thread_get)(0);
-	if (!hash)
-		return;
-
-	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
-	p = (ERR_STATE *)lh_delete(hash, d);
-	/* make sure we don't leak memory */
-	if (int_thread_hash_references == 1
-		&& int_thread_hash && (lh_num_items(int_thread_hash) == 0))
-		{
-		lh_free(int_thread_hash);
-		int_thread_hash = NULL;
-		}
-	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
-
-	ERRFN(thread_release)(&hash);
-	if (p)
-		ERR_STATE_free(p);
-	}
-
-static int int_err_get_next_lib(void)
-	{
-	int ret;
-
-	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
-	ret = int_err_library_number++;
-	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
-
-	return ret;
-	}
-
-
-#ifndef OPENSSL_NO_ERR
-#define NUM_SYS_STR_REASONS 127
-#define LEN_SYS_STR_REASON 32
-
-static ERR_STRING_DATA SYS_str_reasons[NUM_SYS_STR_REASONS + 1];
-/* SYS_str_reasons is filled with copies of strerror() results at
- * initialization.
- * 'errno' values up to 127 should cover all usual errors,
- * others will be displayed numerically by ERR_error_string.
- * It is crucial that we have something for each reason code
- * that occurs in ERR_str_reasons, or bogus reason strings
- * will be returned for SYSerr(), which always gets an errno
- * value and never one of those 'standard' reason codes. */
-
-static void build_SYS_str_reasons(void)
-	{
-	/* OPENSSL_malloc cannot be used here, use static storage instead */
-	static char strerror_tab[NUM_SYS_STR_REASONS][LEN_SYS_STR_REASON];
-	int i;
-	static int init = 1;
-
-	CRYPTO_r_lock(CRYPTO_LOCK_ERR);
-	if (!init)
-		{
-		CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
-		return;
-		}
-	
-	CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
-	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
-	if (!init)
-		{
-		CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
-		return;
-		}
-
-	for (i = 1; i <= NUM_SYS_STR_REASONS; i++)
-		{
-		ERR_STRING_DATA *str = &SYS_str_reasons[i - 1];
-
-		str->error = (unsigned long)i;
-		if (str->string == NULL)
-			{
-			char (*dest)[LEN_SYS_STR_REASON] = &(strerror_tab[i - 1]);
-			char *src = strerror(i);
-			if (src != NULL)
-				{
-				strncpy(*dest, src, sizeof *dest);
-				(*dest)[sizeof *dest - 1] = '\0';
-				str->string = *dest;
-				}
-			}
-		if (str->string == NULL)
-			str->string = "unknown";
-		}
-
-	/* Now we still have SYS_str_reasons[NUM_SYS_STR_REASONS] = {0, NULL},
-	 * as required by ERR_load_strings. */
-
-	init = 0;
-	
-	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
-	}
-#endif
+static unsigned long get_error_values(int inc,int top,
+					const char **file,int *line,
+					const char **data,int *flags);
 
 #define err_clear_data(p,i) \
 	do { \
@@ -613,68 +143,6 @@ static void build_SYS_str_reasons(void)
 	(p)->err_line[i]= -1; \
 	} while(0)
 
-static void ERR_STATE_free(ERR_STATE *s)
-	{
-	int i;
-
-	if (s == NULL)
-	    return;
-
-	for (i=0; i<ERR_NUM_ERRORS; i++)
-		{
-		err_clear_data(s,i);
-		}
-	OPENSSL_free(s);
-	}
-
-void ERR_load_ERR_strings(void)
-	{
-	err_fns_check();
-#ifndef OPENSSL_NO_ERR
-	err_load_strings(0,ERR_str_libraries);
-	err_load_strings(0,ERR_str_reasons);
-	err_load_strings(ERR_LIB_SYS,ERR_str_functs);
-	build_SYS_str_reasons();
-	err_load_strings(ERR_LIB_SYS,SYS_str_reasons);
-#endif
-	}
-
-static void err_load_strings(int lib, ERR_STRING_DATA *str)
-	{
-	while (str->error)
-		{
-		if (lib)
-			str->error|=ERR_PACK(lib,0,0);
-		ERRFN(err_set_item)(str);
-		str++;
-		}
-	}
-
-void ERR_load_strings(int lib, ERR_STRING_DATA *str)
-	{
-	ERR_load_ERR_strings();
-	err_load_strings(lib, str);
-	}
-
-void ERR_unload_strings(int lib, ERR_STRING_DATA *str)
-	{
-	while (str->error)
-		{
-		if (lib)
-			str->error|=ERR_PACK(lib,0,0);
-		ERRFN(err_del_item)(str);
-		str++;
-		}
-	}
-
-void ERR_free_strings(void)
-	{
-	err_fns_check();
-	ERRFN(err_del)();
-	}
-
-/********************************************************/
-
 void ERR_put_error(int lib, int func, int reason, const char *file,
 	     int line)
 	{
@@ -829,218 +297,6 @@ static unsigned long get_error_values(int inc, int top, const char **file, int *
 	return ret;
 	}
 
-void ERR_error_string_n(unsigned long e, char *buf, size_t len)
-	{
-	char lsbuf[64], fsbuf[64], rsbuf[64];
-	const char *ls,*fs,*rs;
-	unsigned long l,f,r;
-
-	l=ERR_GET_LIB(e);
-	f=ERR_GET_FUNC(e);
-	r=ERR_GET_REASON(e);
-
-	ls=ERR_lib_error_string(e);
-	fs=ERR_func_error_string(e);
-	rs=ERR_reason_error_string(e);
-
-	if (ls == NULL) 
-		BIO_snprintf(lsbuf, sizeof(lsbuf), "lib(%lu)", l);
-	if (fs == NULL)
-		BIO_snprintf(fsbuf, sizeof(fsbuf), "func(%lu)", f);
-	if (rs == NULL)
-		BIO_snprintf(rsbuf, sizeof(rsbuf), "reason(%lu)", r);
-
-	BIO_snprintf(buf, len,"error:%08lX:%s:%s:%s", e, ls?ls:lsbuf, 
-		fs?fs:fsbuf, rs?rs:rsbuf);
-	if (strlen(buf) == len-1)
-		{
-		/* output may be truncated; make sure we always have 5 
-		 * colon-separated fields, i.e. 4 colons ... */
-#define NUM_COLONS 4
-		if (len > NUM_COLONS) /* ... if possible */
-			{
-			int i;
-			char *s = buf;
-			
-			for (i = 0; i < NUM_COLONS; i++)
-				{
-				char *colon = strchr(s, ':');
-				if (colon == NULL || colon > &buf[len-1] - NUM_COLONS + i)
-					{
-					/* set colon no. i at last possible position
-					 * (buf[len-1] is the terminating 0)*/
-					colon = &buf[len-1] - NUM_COLONS + i;
-					*colon = ':';
-					}
-				s = colon + 1;
-				}
-			}
-		}
-	}
-
-/* BAD for multi-threading: uses a local buffer if ret == NULL */
-/* ERR_error_string_n should be used instead for ret != NULL
- * as ERR_error_string cannot know how large the buffer is */
-char *ERR_error_string(unsigned long e, char *ret)
-	{
-	static char buf[256];
-
-	if (ret == NULL) ret=buf;
-	ERR_error_string_n(e, ret, 256);
-
-	return ret;
-	}
-
-LHASH *ERR_get_string_table(void)
-	{
-	err_fns_check();
-	return ERRFN(err_get)(0);
-	}
-
-LHASH *ERR_get_err_state_table(void)
-	{
-	err_fns_check();
-	return ERRFN(thread_get)(0);
-	}
-
-void ERR_release_err_state_table(LHASH **hash)
-	{
-	err_fns_check();
-	ERRFN(thread_release)(hash);
-	}
-
-const char *ERR_lib_error_string(unsigned long e)
-	{
-	ERR_STRING_DATA d,*p;
-	unsigned long l;
-
-	err_fns_check();
-	l=ERR_GET_LIB(e);
-	d.error=ERR_PACK(l,0,0);
-	p=ERRFN(err_get_item)(&d);
-	return((p == NULL)?NULL:p->string);
-	}
-
-const char *ERR_func_error_string(unsigned long e)
-	{
-	ERR_STRING_DATA d,*p;
-	unsigned long l,f;
-
-	err_fns_check();
-	l=ERR_GET_LIB(e);
-	f=ERR_GET_FUNC(e);
-	d.error=ERR_PACK(l,f,0);
-	p=ERRFN(err_get_item)(&d);
-	return((p == NULL)?NULL:p->string);
-	}
-
-const char *ERR_reason_error_string(unsigned long e)
-	{
-	ERR_STRING_DATA d,*p=NULL;
-	unsigned long l,r;
-
-	err_fns_check();
-	l=ERR_GET_LIB(e);
-	r=ERR_GET_REASON(e);
-	d.error=ERR_PACK(l,0,r);
-	p=ERRFN(err_get_item)(&d);
-	if (!p)
-		{
-		d.error=ERR_PACK(0,0,r);
-		p=ERRFN(err_get_item)(&d);
-		}
-	return((p == NULL)?NULL:p->string);
-	}
-
-/* static unsigned long err_hash(ERR_STRING_DATA *a) */
-static unsigned long err_hash(const void *a_void)
-	{
-	unsigned long ret,l;
-
-	l=((const ERR_STRING_DATA *)a_void)->error;
-	ret=l^ERR_GET_LIB(l)^ERR_GET_FUNC(l);
-	return(ret^ret%19*13);
-	}
-
-/* static int err_cmp(ERR_STRING_DATA *a, ERR_STRING_DATA *b) */
-static int err_cmp(const void *a_void, const void *b_void)
-	{
-	return((int)(((const ERR_STRING_DATA *)a_void)->error -
-			((const ERR_STRING_DATA *)b_void)->error));
-	}
-
-/* static unsigned long pid_hash(ERR_STATE *a) */
-static unsigned long pid_hash(const void *a_void)
-	{
-	return(((const ERR_STATE *)a_void)->pid*13);
-	}
-
-/* static int pid_cmp(ERR_STATE *a, ERR_STATE *b) */
-static int pid_cmp(const void *a_void, const void *b_void)
-	{
-	return((int)((long)((const ERR_STATE *)a_void)->pid -
-			(long)((const ERR_STATE *)b_void)->pid));
-	}
-
-void ERR_remove_state(unsigned long pid)
-	{
-	ERR_STATE tmp;
-
-	err_fns_check();
-	if (pid == 0)
-		pid=(unsigned long)CRYPTO_thread_id();
-	tmp.pid=pid;
-	/* thread_del_item automatically destroys the LHASH if the number of
-	 * items reaches zero. */
-	ERRFN(thread_del_item)(&tmp);
-	}
-
-ERR_STATE *ERR_get_state(void)
-	{
-	static ERR_STATE fallback;
-	ERR_STATE *ret,tmp,*tmpp=NULL;
-	int i;
-	unsigned long pid;
-
-	err_fns_check();
-	pid=(unsigned long)CRYPTO_thread_id();
-	tmp.pid=pid;
-	ret=ERRFN(thread_get_item)(&tmp);
-
-	/* ret == the error state, if NULL, make a new one */
-	if (ret == NULL)
-		{
-		ret=(ERR_STATE *)OPENSSL_malloc(sizeof(ERR_STATE));
-		if (ret == NULL) return(&fallback);
-		ret->pid=pid;
-		ret->top=0;
-		ret->bottom=0;
-		for (i=0; i<ERR_NUM_ERRORS; i++)
-			{
-			ret->err_data[i]=NULL;
-			ret->err_data_flags[i]=0;
-			}
-		tmpp = ERRFN(thread_set_item)(ret);
-		/* To check if insertion failed, do a get. */
-		if (ERRFN(thread_get_item)(ret) != ret)
-			{
-			ERR_STATE_free(ret); /* could not insert it */
-			return(&fallback);
-			}
-		/* If a race occured in this function and we came second, tmpp
-		 * is the first one that we just replaced. */
-		if (tmpp)
-			ERR_STATE_free(tmpp);
-		}
-	return ret;
-	}
-
-int ERR_get_next_error_library(void)
-	{
-	err_fns_check();
-	return ERRFN(get_next_lib)();
-	}
-
 void ERR_set_error_data(char *data, int flags)
 	{
 	ERR_STATE *es;
@@ -1127,3 +383,34 @@ int ERR_pop_to_mark(void)
 	es->err_flags[es->top]&=~ERR_FLAG_MARK;
 	return 1;
 	}
+
+#ifdef OPENSSL_FIPS
+
+static ERR_STATE *fget_state(void)
+	{
+	static ERR_STATE fstate;
+	return &fstate;
+	}
+
+ERR_STATE *(*get_state_func)(void) = fget_state;
+void (*remove_state_func)(unsigned long pid);
+
+ERR_STATE *ERR_get_state(void)
+	{
+	return get_state_func();
+	}
+
+void int_ERR_set_state_func(ERR_STATE *(*get_func)(void),
+				void (*remove_func)(unsigned long pid))
+	{
+	get_state_func = get_func;
+	remove_state_func = remove_func;
+	}
+
+void ERR_remove_state(unsigned long pid)
+	{
+	if (remove_state_func)
+		remove_state_func(pid);
+	}
+
+#endif
diff --git a/src/lib/libcrypto/err/err.h b/src/lib/libcrypto/err/err.h
index bf28fce492..dcac415231 100644
--- a/src/lib/libcrypto/err/err.h
+++ b/src/lib/libcrypto/err/err.h
@@ -140,7 +140,9 @@ typedef struct err_state_st
 #define ERR_LIB_ECDSA		42
 #define ERR_LIB_ECDH		43
 #define ERR_LIB_STORE           44
-#define ERR_LIB_CMS		45
+#define ERR_LIB_FIPS		45
+#define ERR_LIB_CMS		46
+#define ERR_LIB_JPAKE		47
 
 #define ERR_LIB_USER		128
 
@@ -172,7 +174,9 @@ typedef struct err_state_st
 #define ECDSAerr(f,r)  ERR_PUT_error(ERR_LIB_ECDSA,(f),(r),__FILE__,__LINE__)
 #define ECDHerr(f,r)  ERR_PUT_error(ERR_LIB_ECDH,(f),(r),__FILE__,__LINE__)
 #define STOREerr(f,r) ERR_PUT_error(ERR_LIB_STORE,(f),(r),__FILE__,__LINE__)
+#define FIPSerr(f,r) ERR_PUT_error(ERR_LIB_FIPS,(f),(r),__FILE__,__LINE__)
 #define CMSerr(f,r) ERR_PUT_error(ERR_LIB_CMS,(f),(r),__FILE__,__LINE__)
+#define JPAKEerr(f,r) ERR_PUT_error(ERR_LIB_JPAKE,(f),(r),__FILE__,__LINE__)
 
 /* Borland C seems too stupid to be able to shift and do longs in
  * the pre-processor :-( */
@@ -304,6 +308,12 @@ int ERR_get_next_error_library(void);
 int ERR_set_mark(void);
 int ERR_pop_to_mark(void);
 
+#ifdef OPENSSL_FIPS
+void int_ERR_set_state_func(ERR_STATE *(*get_func)(void),
+				void (*remove_func)(unsigned long pid));
+void int_ERR_lib_init(void);
+#endif
+
 /* Already defined in ossl_typ.h */
 /* typedef struct st_ERR_FNS ERR_FNS; */
 /* An application can use this function and provide the return value to loaded
diff --git a/src/lib/libcrypto/err/err_all.c b/src/lib/libcrypto/err/err_all.c
index 5813060ce2..f21a5276ed 100644
--- a/src/lib/libcrypto/err/err_all.c
+++ b/src/lib/libcrypto/err/err_all.c
@@ -94,9 +94,16 @@
 #include <openssl/ui.h>
 #include <openssl/ocsp.h>
 #include <openssl/err.h>
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
+
 #ifndef OPENSSL_NO_CMS
 #include <openssl/cms.h>
 #endif
+#ifndef OPENSSL_NO_JPAKE
+#include <openssl/jpake.h>
+#endif
 
 void ERR_load_crypto_strings(void)
 	{
@@ -141,8 +148,14 @@ void ERR_load_crypto_strings(void)
 #endif
 	ERR_load_OCSP_strings();
 	ERR_load_UI_strings();
+#ifdef OPENSSL_FIPS
+	ERR_load_FIPS_strings();
+#endif
 #ifndef OPENSSL_NO_CMS
 	ERR_load_CMS_strings();
 #endif
+#ifndef OPENSSL_NO_JPAKE
+	ERR_load_JPAKE_strings();
+#endif
 #endif
 	}
diff --git a/src/lib/libcrypto/err/err_prn.c b/src/lib/libcrypto/err/err_prn.c
index 2224a901e5..4cdf342fa6 100644
--- a/src/lib/libcrypto/err/err_prn.c
+++ b/src/lib/libcrypto/err/err_prn.c
@@ -86,12 +86,7 @@ void ERR_print_errors_cb(int (*cb)(const char *str, size_t len, void *u),
 #ifndef OPENSSL_NO_FP_API
 static int print_fp(const char *str, size_t len, void *fp)
 	{
-	BIO bio;
-
-	BIO_set(&bio,BIO_s_file());
-	BIO_set_fp(&bio,fp,BIO_NOCLOSE);
-
-	return BIO_printf(&bio, "%s", str);
+	return fwrite(str, 1, len, fp);
 	}
 void ERR_print_errors_fp(FILE *fp)
 	{
@@ -99,13 +94,64 @@ void ERR_print_errors_fp(FILE *fp)
 	}
 #endif
 
-static int print_bio(const char *str, size_t len, void *bp)
+void ERR_error_string_n(unsigned long e, char *buf, size_t len)
 	{
-	return BIO_write((BIO *)bp, str, len);
+	char lsbuf[64], fsbuf[64], rsbuf[64];
+	const char *ls,*fs,*rs;
+	unsigned long l,f,r;
+
+	l=ERR_GET_LIB(e);
+	f=ERR_GET_FUNC(e);
+	r=ERR_GET_REASON(e);
+
+	ls=ERR_lib_error_string(e);
+	fs=ERR_func_error_string(e);
+	rs=ERR_reason_error_string(e);
+
+	if (ls == NULL) 
+		BIO_snprintf(lsbuf, sizeof(lsbuf), "lib(%lu)", l);
+	if (fs == NULL)
+		BIO_snprintf(fsbuf, sizeof(fsbuf), "func(%lu)", f);
+	if (rs == NULL)
+		BIO_snprintf(rsbuf, sizeof(rsbuf), "reason(%lu)", r);
+
+	BIO_snprintf(buf, len,"error:%08lX:%s:%s:%s", e, ls?ls:lsbuf, 
+		fs?fs:fsbuf, rs?rs:rsbuf);
+	if (strlen(buf) == len-1)
+		{
+		/* output may be truncated; make sure we always have 5 
+		 * colon-separated fields, i.e. 4 colons ... */
+#define NUM_COLONS 4
+		if (len > NUM_COLONS) /* ... if possible */
+			{
+			int i;
+			char *s = buf;
+			
+			for (i = 0; i < NUM_COLONS; i++)
+				{
+				char *colon = strchr(s, ':');
+				if (colon == NULL || colon > &buf[len-1] - NUM_COLONS + i)
+					{
+					/* set colon no. i at last possible position
+					 * (buf[len-1] is the terminating 0)*/
+					colon = &buf[len-1] - NUM_COLONS + i;
+					*colon = ':';
+					}
+				s = colon + 1;
+				}
+			}
+		}
 	}
-void ERR_print_errors(BIO *bp)
+
+/* BAD for multi-threading: uses a local buffer if ret == NULL */
+/* ERR_error_string_n should be used instead for ret != NULL
+ * as ERR_error_string cannot know how large the buffer is */
+char *ERR_error_string(unsigned long e, char *ret)
 	{
-	ERR_print_errors_cb(print_bio, bp);
-	}
+	static char buf[256];
+
+	if (ret == NULL) ret=buf;
+	ERR_error_string_n(e, ret, 256);
 
-	
+	return ret;
+	}
diff --git a/src/lib/libcrypto/err/openssl.ec b/src/lib/libcrypto/err/openssl.ec
index 1938f081ac..868826624d 100644
--- a/src/lib/libcrypto/err/openssl.ec
+++ b/src/lib/libcrypto/err/openssl.ec
@@ -31,7 +31,9 @@ L COMP		crypto/comp/comp.h		crypto/comp/comp_err.c
 L ECDSA		crypto/ecdsa/ecdsa.h		crypto/ecdsa/ecs_err.c
 L ECDH		crypto/ecdh/ecdh.h		crypto/ecdh/ech_err.c
 L STORE		crypto/store/store.h		crypto/store/str_err.c
+L FIPS		fips/fips.h			crypto/fips_err.h
 L CMS		crypto/cms/cms.h		crypto/cms/cms_err.c
+L JPAKE		crypto/jpake/jpake.h		crypto/jpake/jpake_err.c
 
 # additional header files to be scanned for function names
 L NONE		crypto/x509/x509_vfy.h		NONE
diff --git a/src/lib/libcrypto/evp/bio_md.c b/src/lib/libcrypto/evp/bio_md.c
index d648ac6da6..ed5c1135fd 100644
--- a/src/lib/libcrypto/evp/bio_md.c
+++ b/src/lib/libcrypto/evp/bio_md.c
@@ -192,13 +192,8 @@ static long md_ctrl(BIO *b, int cmd, long num, void *ptr)
 			ret=0;
 		break;
 	case BIO_C_GET_MD_CTX:
-		if (b->init)
-			{
-			pctx=ptr;
-			*pctx=ctx;
-			}
-		else
-			ret=0;
+		pctx=ptr;
+		*pctx=ctx;
 		break;
 	case BIO_C_SET_MD_CTX:
 		if (b->init)
diff --git a/src/lib/libcrypto/evp/digest.c b/src/lib/libcrypto/evp/digest.c
index 762e6d3450..3bc2d1295c 100644
--- a/src/lib/libcrypto/evp/digest.c
+++ b/src/lib/libcrypto/evp/digest.c
@@ -116,6 +116,7 @@
 #ifndef OPENSSL_NO_ENGINE
 #include <openssl/engine.h>
 #endif
+#include "evp_locl.h"
 
 void EVP_MD_CTX_init(EVP_MD_CTX *ctx)
 	{
@@ -137,18 +138,77 @@ int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type)
 	return EVP_DigestInit_ex(ctx, type, NULL);
 	}
 
-int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
+#ifdef OPENSSL_FIPS
+
+/* The purpose of these is to trap programs that attempt to use non FIPS
+ * algorithms in FIPS mode and ignore the errors.
+ */
+
+static int bad_init(EVP_MD_CTX *ctx)
+	{ FIPS_ERROR_IGNORED("Digest init"); return 0;}
+
+static int bad_update(EVP_MD_CTX *ctx,const void *data,size_t count)
+	{ FIPS_ERROR_IGNORED("Digest update"); return 0;}
+
+static int bad_final(EVP_MD_CTX *ctx,unsigned char *md)
+	{ FIPS_ERROR_IGNORED("Digest Final"); return 0;}
+
+static const EVP_MD bad_md =
 	{
-	EVP_MD_CTX_clear_flags(ctx,EVP_MD_CTX_FLAG_CLEANED);
+	0,
+	0,
+	0,
+	0,
+	bad_init,
+	bad_update,
+	bad_final,
+	NULL,
+	NULL,
+	NULL,
+	0,
+	{0,0,0,0},
+	};
+
+#endif
+
 #ifndef OPENSSL_NO_ENGINE
-	/* Whether it's nice or not, "Inits" can be used on "Final"'d contexts
-	 * so this context may already have an ENGINE! Try to avoid releasing
-	 * the previous handle, re-querying for an ENGINE, and having a
-	 * reinitialisation, when it may all be unecessary. */
-	if (ctx->engine && ctx->digest && (!type ||
-			(type && (type->type == ctx->digest->type))))
-		goto skip_to_init;
-	if (type)
+
+#ifdef OPENSSL_FIPS
+
+static int do_engine_null(ENGINE *impl) { return 0;}
+static int do_evp_md_engine_null(EVP_MD_CTX *ctx,
+				const EVP_MD **ptype, ENGINE *impl)
+	{ return 1; }
+
+static int (*do_engine_init)(ENGINE *impl)
+		= do_engine_null;
+
+static int (*do_engine_finish)(ENGINE *impl)
+		= do_engine_null;
+
+static int (*do_evp_md_engine)
+	(EVP_MD_CTX *ctx, const EVP_MD **ptype, ENGINE *impl)
+		= do_evp_md_engine_null;
+
+void int_EVP_MD_set_engine_callbacks(
+	int (*eng_md_init)(ENGINE *impl),
+	int (*eng_md_fin)(ENGINE *impl),
+	int (*eng_md_evp)
+		(EVP_MD_CTX *ctx, const EVP_MD **ptype, ENGINE *impl))
+	{
+	do_engine_init = eng_md_init;
+	do_engine_finish = eng_md_fin;
+	do_evp_md_engine = eng_md_evp;
+	}
+
+#else
+
+#define do_engine_init	ENGINE_init
+#define do_engine_finish ENGINE_finish
+
+static int do_evp_md_engine(EVP_MD_CTX *ctx, const EVP_MD **ptype, ENGINE *impl)
+	{
+	if (*ptype)
 		{
 		/* Ensure an ENGINE left lying around from last time is cleared
 		 * (the previous check attempted to avoid this if the same
@@ -159,25 +219,25 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
 			{
 			if (!ENGINE_init(impl))
 				{
-				EVPerr(EVP_F_EVP_DIGESTINIT_EX,EVP_R_INITIALIZATION_ERROR);
+				EVPerr(EVP_F_DO_EVP_MD_ENGINE,EVP_R_INITIALIZATION_ERROR);
 				return 0;
 				}
 			}
 		else
 			/* Ask if an ENGINE is reserved for this job */
-			impl = ENGINE_get_digest_engine(type->type);
+			impl = ENGINE_get_digest_engine((*ptype)->type);
 		if(impl)
 			{
 			/* There's an ENGINE for this job ... (apparently) */
-			const EVP_MD *d = ENGINE_get_digest(impl, type->type);
+			const EVP_MD *d = ENGINE_get_digest(impl, (*ptype)->type);
 			if(!d)
 				{
 				/* Same comment from evp_enc.c */
-				EVPerr(EVP_F_EVP_DIGESTINIT_EX,EVP_R_INITIALIZATION_ERROR);
+				EVPerr(EVP_F_DO_EVP_MD_ENGINE,EVP_R_INITIALIZATION_ERROR);
 				return 0;
 				}
 			/* We'll use the ENGINE's private digest definition */
-			type = d;
+			*ptype = d;
 			/* Store the ENGINE functional reference so we know
 			 * 'type' came from an ENGINE and we need to release
 			 * it when done. */
@@ -189,12 +249,52 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
 	else
 	if(!ctx->digest)
 		{
-		EVPerr(EVP_F_EVP_DIGESTINIT_EX,EVP_R_NO_DIGEST_SET);
+		EVPerr(EVP_F_DO_EVP_MD_ENGINE,EVP_R_NO_DIGEST_SET);
 		return 0;
 		}
+	return 1;
+	}
+
+#endif
+
+#endif
+
+int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
+	{
+	M_EVP_MD_CTX_clear_flags(ctx,EVP_MD_CTX_FLAG_CLEANED);
+#ifdef OPENSSL_FIPS
+	if(FIPS_selftest_failed())
+		{
+		FIPSerr(FIPS_F_EVP_DIGESTINIT_EX,FIPS_R_FIPS_SELFTEST_FAILED);
+		ctx->digest = &bad_md;
+		return 0;
+		}
+#endif
+#ifndef OPENSSL_NO_ENGINE
+	/* Whether it's nice or not, "Inits" can be used on "Final"'d contexts
+	 * so this context may already have an ENGINE! Try to avoid releasing
+	 * the previous handle, re-querying for an ENGINE, and having a
+	 * reinitialisation, when it may all be unecessary. */
+	if (ctx->engine && ctx->digest && (!type ||
+			(type && (type->type == ctx->digest->type))))
+		goto skip_to_init;
+	if (!do_evp_md_engine(ctx, &type, impl))
+		return 0;
 #endif
 	if (ctx->digest != type)
 		{
+#ifdef OPENSSL_FIPS
+		if (FIPS_mode())
+			{
+			if (!(type->flags & EVP_MD_FLAG_FIPS) 
+			 && !(ctx->flags & EVP_MD_CTX_FLAG_NON_FIPS_ALLOW))
+				{
+				EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_DISABLED_FOR_FIPS);
+				ctx->digest = &bad_md;
+				return 0;
+				}
+			}
+#endif
 		if (ctx->digest && ctx->digest->ctx_size)
 			OPENSSL_free(ctx->md_data);
 		ctx->digest=type;
@@ -202,7 +302,7 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
 			ctx->md_data=OPENSSL_malloc(type->ctx_size);
 		}
 #ifndef OPENSSL_NO_ENGINE
-skip_to_init:
+	skip_to_init:
 #endif
 	return ctx->digest->init(ctx);
 	}
@@ -210,6 +310,9 @@ skip_to_init:
 int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data,
 	     size_t count)
 	{
+#ifdef OPENSSL_FIPS
+	FIPS_selftest_check();
+#endif
 	return ctx->digest->update(ctx,data,count);
 	}
 
@@ -226,6 +329,9 @@ int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
 int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
 	{
 	int ret;
+#ifdef OPENSSL_FIPS
+	FIPS_selftest_check();
+#endif
 
 	OPENSSL_assert(ctx->digest->md_size <= EVP_MAX_MD_SIZE);
 	ret=ctx->digest->final(ctx,md);
@@ -234,7 +340,7 @@ int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
 	if (ctx->digest->cleanup)
 		{
 		ctx->digest->cleanup(ctx);
-		EVP_MD_CTX_set_flags(ctx,EVP_MD_CTX_FLAG_CLEANED);
+		M_EVP_MD_CTX_set_flags(ctx,EVP_MD_CTX_FLAG_CLEANED);
 		}
 	memset(ctx->md_data,0,ctx->digest->ctx_size);
 	return ret;
@@ -256,7 +362,7 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
 		}
 #ifndef OPENSSL_NO_ENGINE
 	/* Make sure it's safe to copy a digest context using an ENGINE */
-	if (in->engine && !ENGINE_init(in->engine))
+	if (in->engine && !do_engine_init(in->engine))
 		{
 		EVPerr(EVP_F_EVP_MD_CTX_COPY_EX,ERR_R_ENGINE_LIB);
 		return 0;
@@ -266,7 +372,7 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
 	if (out->digest == in->digest)
 		{
 		tmp_buf = out->md_data;
-	    	EVP_MD_CTX_set_flags(out,EVP_MD_CTX_FLAG_REUSE);
+	    	M_EVP_MD_CTX_set_flags(out,EVP_MD_CTX_FLAG_REUSE);
 		}
 	else tmp_buf = NULL;
 	EVP_MD_CTX_cleanup(out);
@@ -292,7 +398,7 @@ int EVP_Digest(const void *data, size_t count,
 	int ret;
 
 	EVP_MD_CTX_init(&ctx);
-	EVP_MD_CTX_set_flags(&ctx,EVP_MD_CTX_FLAG_ONESHOT);
+	M_EVP_MD_CTX_set_flags(&ctx,EVP_MD_CTX_FLAG_ONESHOT);
 	ret=EVP_DigestInit_ex(&ctx, type, impl)
 	  && EVP_DigestUpdate(&ctx, data, count)
 	  && EVP_DigestFinal_ex(&ctx, md, size);
@@ -314,10 +420,10 @@ int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx)
 	 * because sometimes only copies of the context are ever finalised.
 	 */
 	if (ctx->digest && ctx->digest->cleanup
-	    && !EVP_MD_CTX_test_flags(ctx,EVP_MD_CTX_FLAG_CLEANED))
+	    && !M_EVP_MD_CTX_test_flags(ctx,EVP_MD_CTX_FLAG_CLEANED))
 		ctx->digest->cleanup(ctx);
 	if (ctx->digest && ctx->digest->ctx_size && ctx->md_data
-	    && !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_REUSE))
+	    && !M_EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_REUSE))
 		{
 		OPENSSL_cleanse(ctx->md_data,ctx->digest->ctx_size);
 		OPENSSL_free(ctx->md_data);
@@ -326,7 +432,7 @@ int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx)
 	if(ctx->engine)
 		/* The EVP_MD we used belongs to an ENGINE, release the
 		 * functional reference we held for this reason. */
-		ENGINE_finish(ctx->engine);
+		do_engine_finish(ctx->engine);
 #endif
 	memset(ctx,'\0',sizeof *ctx);
 
diff --git a/src/lib/libcrypto/evp/e_aes.c b/src/lib/libcrypto/evp/e_aes.c
index bd6c0a3a62..c9a5ee8d75 100644
--- a/src/lib/libcrypto/evp/e_aes.c
+++ b/src/lib/libcrypto/evp/e_aes.c
@@ -69,32 +69,29 @@ typedef struct
 
 IMPLEMENT_BLOCK_CIPHER(aes_128, ks, AES, EVP_AES_KEY,
 		       NID_aes_128, 16, 16, 16, 128,
-		       0, aes_init_key, NULL, 
-		       EVP_CIPHER_set_asn1_iv,
-		       EVP_CIPHER_get_asn1_iv,
-		       NULL)
+		       EVP_CIPH_FLAG_FIPS|EVP_CIPH_FLAG_DEFAULT_ASN1,
+		       aes_init_key,
+		       NULL, NULL, NULL, NULL)
 IMPLEMENT_BLOCK_CIPHER(aes_192, ks, AES, EVP_AES_KEY,
 		       NID_aes_192, 16, 24, 16, 128,
-		       0, aes_init_key, NULL, 
-		       EVP_CIPHER_set_asn1_iv,
-		       EVP_CIPHER_get_asn1_iv,
-		       NULL)
+		       EVP_CIPH_FLAG_FIPS|EVP_CIPH_FLAG_DEFAULT_ASN1,
+		       aes_init_key,
+		       NULL, NULL, NULL, NULL)
 IMPLEMENT_BLOCK_CIPHER(aes_256, ks, AES, EVP_AES_KEY,
 		       NID_aes_256, 16, 32, 16, 128,
-		       0, aes_init_key, NULL, 
-		       EVP_CIPHER_set_asn1_iv,
-		       EVP_CIPHER_get_asn1_iv,
-		       NULL)
+		       EVP_CIPH_FLAG_FIPS|EVP_CIPH_FLAG_DEFAULT_ASN1,
+		       aes_init_key,
+		       NULL, NULL, NULL, NULL)
 
-#define IMPLEMENT_AES_CFBR(ksize,cbits)	IMPLEMENT_CFBR(aes,AES,EVP_AES_KEY,ks,ksize,cbits,16)
+#define IMPLEMENT_AES_CFBR(ksize,cbits,flags)	IMPLEMENT_CFBR(aes,AES,EVP_AES_KEY,ks,ksize,cbits,16,flags)
 
-IMPLEMENT_AES_CFBR(128,1)
-IMPLEMENT_AES_CFBR(192,1)
-IMPLEMENT_AES_CFBR(256,1)
+IMPLEMENT_AES_CFBR(128,1,EVP_CIPH_FLAG_FIPS)
+IMPLEMENT_AES_CFBR(192,1,EVP_CIPH_FLAG_FIPS)
+IMPLEMENT_AES_CFBR(256,1,EVP_CIPH_FLAG_FIPS)
 
-IMPLEMENT_AES_CFBR(128,8)
-IMPLEMENT_AES_CFBR(192,8)
-IMPLEMENT_AES_CFBR(256,8)
+IMPLEMENT_AES_CFBR(128,8,EVP_CIPH_FLAG_FIPS)
+IMPLEMENT_AES_CFBR(192,8,EVP_CIPH_FLAG_FIPS)
+IMPLEMENT_AES_CFBR(256,8,EVP_CIPH_FLAG_FIPS)
 
 static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
 		   const unsigned char *iv, int enc)
diff --git a/src/lib/libcrypto/evp/e_camellia.c b/src/lib/libcrypto/evp/e_camellia.c
index a7b40d1c60..365d397164 100644
--- a/src/lib/libcrypto/evp/e_camellia.c
+++ b/src/lib/libcrypto/evp/e_camellia.c
@@ -93,7 +93,7 @@ IMPLEMENT_BLOCK_CIPHER(camellia_256, ks, Camellia, EVP_CAMELLIA_KEY,
 	EVP_CIPHER_get_asn1_iv,
 	NULL)
 
-#define IMPLEMENT_CAMELLIA_CFBR(ksize,cbits)	IMPLEMENT_CFBR(camellia,Camellia,EVP_CAMELLIA_KEY,ks,ksize,cbits,16)
+#define IMPLEMENT_CAMELLIA_CFBR(ksize,cbits)	IMPLEMENT_CFBR(camellia,Camellia,EVP_CAMELLIA_KEY,ks,ksize,cbits,16,0)
 
 IMPLEMENT_CAMELLIA_CFBR(128,1)
 IMPLEMENT_CAMELLIA_CFBR(192,1)
diff --git a/src/lib/libcrypto/evp/e_des.c b/src/lib/libcrypto/evp/e_des.c
index 856323648c..04376df232 100644
--- a/src/lib/libcrypto/evp/e_des.c
+++ b/src/lib/libcrypto/evp/e_des.c
@@ -129,18 +129,21 @@ static int des_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
     }
 
 BLOCK_CIPHER_defs(des, DES_key_schedule, NID_des, 8, 8, 8, 64,
-			EVP_CIPH_RAND_KEY, des_init_key, NULL,
+			EVP_CIPH_RAND_KEY,
+			des_init_key, NULL,
 			EVP_CIPHER_set_asn1_iv,
 			EVP_CIPHER_get_asn1_iv,
 			des_ctrl)
 
 BLOCK_CIPHER_def_cfb(des,DES_key_schedule,NID_des,8,8,1,
-		     EVP_CIPH_RAND_KEY, des_init_key,NULL,
+		     EVP_CIPH_RAND_KEY,
+		     des_init_key, NULL,
 		     EVP_CIPHER_set_asn1_iv,
 		     EVP_CIPHER_get_asn1_iv,des_ctrl)
 
 BLOCK_CIPHER_def_cfb(des,DES_key_schedule,NID_des,8,8,8,
-		     EVP_CIPH_RAND_KEY,des_init_key,NULL,
+		     EVP_CIPH_RAND_KEY,
+		     des_init_key,NULL,
 		     EVP_CIPHER_set_asn1_iv,
 		     EVP_CIPHER_get_asn1_iv,des_ctrl)
 
diff --git a/src/lib/libcrypto/evp/e_des3.c b/src/lib/libcrypto/evp/e_des3.c
index ac148efab2..f910af19b1 100644
--- a/src/lib/libcrypto/evp/e_des3.c
+++ b/src/lib/libcrypto/evp/e_des3.c
@@ -111,8 +111,7 @@ static int des_ede_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
 #ifdef KSSL_DEBUG
 	{
         int i;
-        char *cp;
-	printf("des_ede_cbc_cipher(ctx=%lx, buflen=%d)\n", ctx, ctx->buf_len);
+	printf("des_ede_cbc_cipher(ctx=%lx, buflen=%d)\n", (unsigned long)ctx, ctx->buf_len);
 	printf("\t iv= ");
         for(i=0;i<8;i++)
                 printf("%02X",ctx->iv[i]);
@@ -164,9 +163,9 @@ static int des_ede3_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
     }
 
 BLOCK_CIPHER_defs(des_ede, DES_EDE_KEY, NID_des_ede, 8, 16, 8, 64,
-			EVP_CIPH_RAND_KEY, des_ede_init_key, NULL, 
-			EVP_CIPHER_set_asn1_iv,
-			EVP_CIPHER_get_asn1_iv,
+		EVP_CIPH_RAND_KEY|EVP_CIPH_FLAG_FIPS|EVP_CIPH_FLAG_DEFAULT_ASN1,
+			des_ede_init_key,
+			NULL, NULL, NULL,
 			des3_ctrl)
 
 #define des_ede3_cfb64_cipher des_ede_cfb64_cipher
@@ -175,21 +174,21 @@ BLOCK_CIPHER_defs(des_ede, DES_EDE_KEY, NID_des_ede, 8, 16, 8, 64,
 #define des_ede3_ecb_cipher des_ede_ecb_cipher
 
 BLOCK_CIPHER_defs(des_ede3, DES_EDE_KEY, NID_des_ede3, 8, 24, 8, 64,
-			EVP_CIPH_RAND_KEY, des_ede3_init_key, NULL, 
-			EVP_CIPHER_set_asn1_iv,
-			EVP_CIPHER_get_asn1_iv,
+		EVP_CIPH_RAND_KEY|EVP_CIPH_FLAG_FIPS|EVP_CIPH_FLAG_DEFAULT_ASN1,
+			des_ede3_init_key,
+			NULL, NULL, NULL,
 			des3_ctrl)
 
 BLOCK_CIPHER_def_cfb(des_ede3,DES_EDE_KEY,NID_des_ede3,24,8,1,
-		     EVP_CIPH_RAND_KEY, des_ede3_init_key,NULL,
-		     EVP_CIPHER_set_asn1_iv,
-		     EVP_CIPHER_get_asn1_iv,
+		EVP_CIPH_RAND_KEY|EVP_CIPH_FLAG_FIPS|EVP_CIPH_FLAG_DEFAULT_ASN1,
+		     des_ede3_init_key,
+		     NULL, NULL, NULL,
 		     des3_ctrl)
 
 BLOCK_CIPHER_def_cfb(des_ede3,DES_EDE_KEY,NID_des_ede3,24,8,8,
-		     EVP_CIPH_RAND_KEY, des_ede3_init_key,NULL,
-		     EVP_CIPHER_set_asn1_iv,
-		     EVP_CIPHER_get_asn1_iv,
+		EVP_CIPH_RAND_KEY|EVP_CIPH_FLAG_FIPS|EVP_CIPH_FLAG_DEFAULT_ASN1,
+		     des_ede3_init_key,
+		     NULL, NULL, NULL,
 		     des3_ctrl)
 
 static int des_ede_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
@@ -216,7 +215,7 @@ static int des_ede3_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
 #ifdef KSSL_DEBUG
 	{
         int i;
-        printf("des_ede3_init_key(ctx=%lx)\n", ctx);
+        printf("des_ede3_init_key(ctx=%lx)\n", (unsigned long)ctx);
 	printf("\tKEY= ");
         for(i=0;i<24;i++) printf("%02X",key[i]); printf("\n");
 	printf("\t IV= ");
diff --git a/src/lib/libcrypto/evp/e_null.c b/src/lib/libcrypto/evp/e_null.c
index 5205259f18..0872d733e4 100644
--- a/src/lib/libcrypto/evp/e_null.c
+++ b/src/lib/libcrypto/evp/e_null.c
@@ -69,7 +69,7 @@ static const EVP_CIPHER n_cipher=
 	{
 	NID_undef,
 	1,0,0,
-	0,
+	EVP_CIPH_FLAG_FIPS,
 	null_init_key,
 	null_cipher,
 	NULL,
diff --git a/src/lib/libcrypto/evp/e_rc4.c b/src/lib/libcrypto/evp/e_rc4.c
index 67af850bea..55baad7446 100644
--- a/src/lib/libcrypto/evp/e_rc4.c
+++ b/src/lib/libcrypto/evp/e_rc4.c
@@ -64,6 +64,7 @@
 #include <openssl/evp.h>
 #include <openssl/objects.h>
 #include <openssl/rc4.h>
+#include "evp_locl.h"
 
 /* FIXME: surely this is available elsewhere? */
 #define EVP_RC4_KEY_SIZE		16
diff --git a/src/lib/libcrypto/evp/evp.h b/src/lib/libcrypto/evp/evp.h
index bdd3b7ecaa..79c097181f 100644
--- a/src/lib/libcrypto/evp/evp.h
+++ b/src/lib/libcrypto/evp/evp.h
@@ -75,6 +75,10 @@
 #include <openssl/bio.h>
 #endif
 
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
+
 /*
 #define EVP_RC2_KEY_SIZE		16
 #define EVP_RC4_KEY_SIZE		16
@@ -250,9 +254,19 @@ typedef int evp_verify_method(int type,const unsigned char *m,
 			    unsigned int m_length,const unsigned char *sigbuf,
 			    unsigned int siglen, void *key);
 
+typedef struct
+	{
+	EVP_MD_CTX *mctx;
+	void *key;
+	} EVP_MD_SVCTX;
+
 #define EVP_MD_FLAG_ONESHOT	0x0001 /* digest can only handle a single
 					* block */
 
+#define EVP_MD_FLAG_FIPS	0x0400 /* Note if suitable for use in FIPS mode */
+
+#define EVP_MD_FLAG_SVCTX	0x0800 /* pass EVP_MD_SVCTX to sign/verify */
+
 #define EVP_PKEY_NULL_method	NULL,NULL,{0,0,0,0}
 
 #ifndef OPENSSL_NO_DSA
@@ -303,6 +317,17 @@ struct env_md_ctx_st
 						* cleaned */
 #define EVP_MD_CTX_FLAG_REUSE		0x0004 /* Don't free up ctx->md_data
 						* in EVP_MD_CTX_cleanup */
+#define EVP_MD_CTX_FLAG_NON_FIPS_ALLOW	0x0008	/* Allow use of non FIPS digest
+						 * in FIPS mode */
+
+#define EVP_MD_CTX_FLAG_PAD_MASK	0xF0	/* RSA mode to use */
+#define EVP_MD_CTX_FLAG_PAD_PKCS1	0x00	/* PKCS#1 v1.5 mode */
+#define EVP_MD_CTX_FLAG_PAD_X931	0x10	/* X9.31 mode */
+#define EVP_MD_CTX_FLAG_PAD_PSS		0x20	/* PSS mode */
+#define M_EVP_MD_CTX_FLAG_PSS_SALT(ctx) \
+		((ctx->flags>>16) &0xFFFF) /* seed length */
+#define EVP_MD_CTX_FLAG_PSS_MDLEN	0xFFFF	/* salt len same as digest */
+#define EVP_MD_CTX_FLAG_PSS_MREC	0xFFFE	/* salt max or auto recovered */
 
 struct evp_cipher_st
 	{
@@ -347,6 +372,14 @@ struct evp_cipher_st
 #define 	EVP_CIPH_NO_PADDING		0x100
 /* cipher handles random key generation */
 #define 	EVP_CIPH_RAND_KEY		0x200
+/* Note if suitable for use in FIPS mode */
+#define		EVP_CIPH_FLAG_FIPS		0x400
+/* Allow non FIPS cipher in FIPS mode */
+#define		EVP_CIPH_FLAG_NON_FIPS_ALLOW	0x800
+/* Allow use default ASN1 get/set iv */
+#define		EVP_CIPH_FLAG_DEFAULT_ASN1	0x1000
+/* Buffer length in bits not bytes: CFB1 mode only */
+#define		EVP_CIPH_FLAG_LENGTH_BITS	0x2000
 
 /* ctrl() values */
 
@@ -429,6 +462,18 @@ typedef int (EVP_PBE_KEYGEN)(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
 #define EVP_get_cipherbynid(a) EVP_get_cipherbyname(OBJ_nid2sn(a))
 #define EVP_get_cipherbyobj(a) EVP_get_cipherbynid(OBJ_obj2nid(a))
 
+/* Macros to reduce FIPS dependencies: do NOT use in applications */
+#define M_EVP_MD_size(e)		((e)->md_size)
+#define M_EVP_MD_block_size(e)		((e)->block_size)
+#define M_EVP_MD_CTX_set_flags(ctx,flgs) ((ctx)->flags|=(flgs))
+#define M_EVP_MD_CTX_clear_flags(ctx,flgs) ((ctx)->flags&=~(flgs))
+#define M_EVP_MD_CTX_test_flags(ctx,flgs) ((ctx)->flags&(flgs))
+#define M_EVP_MD_type(e)			((e)->type)
+#define M_EVP_MD_CTX_type(e)		M_EVP_MD_type(M_EVP_MD_CTX_md(e))
+#define M_EVP_MD_CTX_md(e)			((e)->digest)
+
+#define M_EVP_CIPHER_CTX_set_flags(ctx,flgs) ((ctx)->flags|=(flgs))
+
 int EVP_MD_type(const EVP_MD *md);
 #define EVP_MD_nid(e)			EVP_MD_type(e)
 #define EVP_MD_name(e)			OBJ_nid2sn(EVP_MD_nid(e))
@@ -524,6 +569,10 @@ int	EVP_BytesToKey(const EVP_CIPHER *type,const EVP_MD *md,
 		const unsigned char *salt, const unsigned char *data,
 		int datal, int count, unsigned char *key,unsigned char *iv);
 
+void	EVP_CIPHER_CTX_set_flags(EVP_CIPHER_CTX *ctx, int flags);
+void	EVP_CIPHER_CTX_clear_flags(EVP_CIPHER_CTX *ctx, int flags);
+int 	EVP_CIPHER_CTX_test_flags(const EVP_CIPHER_CTX *ctx,int flags);
+
 int	EVP_EncryptInit(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher,
 		const unsigned char *key, const unsigned char *iv);
 int	EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher, ENGINE *impl,
@@ -879,6 +928,24 @@ int EVP_PBE_alg_add(int nid, const EVP_CIPHER *cipher, const EVP_MD *md,
 		    EVP_PBE_KEYGEN *keygen);
 void EVP_PBE_cleanup(void);
 
+#ifdef OPENSSL_FIPS
+#ifndef OPENSSL_NO_ENGINE
+void int_EVP_MD_set_engine_callbacks(
+	int (*eng_md_init)(ENGINE *impl),
+	int (*eng_md_fin)(ENGINE *impl),
+	int (*eng_md_evp)
+		(EVP_MD_CTX *ctx, const EVP_MD **ptype, ENGINE *impl));
+void int_EVP_MD_init_engine_callbacks(void);
+void int_EVP_CIPHER_set_engine_callbacks(
+	int (*eng_ciph_fin)(ENGINE *impl),
+	int (*eng_ciph_evp)
+		(EVP_CIPHER_CTX *ctx, const EVP_CIPHER **pciph, ENGINE *impl));
+void int_EVP_CIPHER_init_engine_callbacks(void);
+#endif
+#endif
+
+void EVP_add_alg_module(void);
+
 /* BEGIN ERROR CODES */
 /* The following lines are auto generated by the script mkerr.pl. Any changes
  * made after this point may be overwritten when the script is next run.
@@ -889,16 +956,23 @@ void ERR_load_EVP_strings(void);
 
 /* Function codes. */
 #define EVP_F_AES_INIT_KEY				 133
+#define EVP_F_ALG_MODULE_INIT				 138
 #define EVP_F_CAMELLIA_INIT_KEY				 159
 #define EVP_F_D2I_PKEY					 100
+#define EVP_F_DO_EVP_ENC_ENGINE				 140
+#define EVP_F_DO_EVP_ENC_ENGINE_FULL			 141
+#define EVP_F_DO_EVP_MD_ENGINE				 139
+#define EVP_F_DO_EVP_MD_ENGINE_FULL			 142
 #define EVP_F_DSAPKEY2PKCS8				 134
 #define EVP_F_DSA_PKEY2PKCS8				 135
 #define EVP_F_ECDSA_PKEY2PKCS8				 129
 #define EVP_F_ECKEY_PKEY2PKCS8				 132
+#define EVP_F_EVP_CIPHERINIT				 137
 #define EVP_F_EVP_CIPHERINIT_EX				 123
 #define EVP_F_EVP_CIPHER_CTX_CTRL			 124
 #define EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH		 122
 #define EVP_F_EVP_DECRYPTFINAL_EX			 101
+#define EVP_F_EVP_DIGESTINIT				 136
 #define EVP_F_EVP_DIGESTINIT_EX				 128
 #define EVP_F_EVP_ENCRYPTFINAL_EX			 127
 #define EVP_F_EVP_MD_CTX_COPY_EX			 110
@@ -940,15 +1014,20 @@ void ERR_load_EVP_strings(void);
 #define EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH		 138
 #define EVP_R_DECODE_ERROR				 114
 #define EVP_R_DIFFERENT_KEY_TYPES			 101
+#define EVP_R_DISABLED_FOR_FIPS				 144
 #define EVP_R_ENCODE_ERROR				 115
+#define EVP_R_ERROR_LOADING_SECTION			 145
+#define EVP_R_ERROR_SETTING_FIPS_MODE			 146
 #define EVP_R_EVP_PBE_CIPHERINIT_ERROR			 119
 #define EVP_R_EXPECTING_AN_RSA_KEY			 127
 #define EVP_R_EXPECTING_A_DH_KEY			 128
 #define EVP_R_EXPECTING_A_DSA_KEY			 129
 #define EVP_R_EXPECTING_A_ECDSA_KEY			 141
 #define EVP_R_EXPECTING_A_EC_KEY			 142
+#define EVP_R_FIPS_MODE_NOT_SUPPORTED			 147
 #define EVP_R_INITIALIZATION_ERROR			 134
 #define EVP_R_INPUT_NOT_INITIALIZED			 111
+#define EVP_R_INVALID_FIPS_MODE				 148
 #define EVP_R_INVALID_KEY_LENGTH			 130
 #define EVP_R_IV_TOO_LARGE				 102
 #define EVP_R_KEYGEN_FAILURE				 120
@@ -960,6 +1039,7 @@ void ERR_load_EVP_strings(void);
 #define EVP_R_NO_VERIFY_FUNCTION_CONFIGURED		 105
 #define EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE			 117
 #define EVP_R_PUBLIC_KEY_NOT_RSA			 106
+#define EVP_R_UNKNOWN_OPTION				 149
 #define EVP_R_UNKNOWN_PBE_ALGORITHM			 121
 #define EVP_R_UNSUPORTED_NUMBER_OF_ROUNDS		 135
 #define EVP_R_UNSUPPORTED_CIPHER			 107
diff --git a/src/lib/libcrypto/evp/evp_enc.c b/src/lib/libcrypto/evp/evp_enc.c
index a1904993bf..30e0ca4d9f 100644
--- a/src/lib/libcrypto/evp/evp_enc.c
+++ b/src/lib/libcrypto/evp/evp_enc.c
@@ -66,13 +66,15 @@
 #endif
 #include "evp_locl.h"
 
-const char EVP_version[]="EVP" OPENSSL_VERSION_PTEXT;
+#ifdef OPENSSL_FIPS
+	#define M_do_cipher(ctx, out, in, inl) \
+		EVP_Cipher(ctx,out,in,inl)
+#else
+	#define M_do_cipher(ctx, out, in, inl) \
+		ctx->cipher->do_cipher(ctx,out,in,inl)
+#endif
 
-void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *ctx)
-	{
-	memset(ctx,0,sizeof(EVP_CIPHER_CTX));
-	/* ctx->cipher=NULL; */
-	}
+const char EVP_version[]="EVP" OPENSSL_VERSION_PTEXT;
 
 EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void)
 	{
@@ -90,144 +92,6 @@ int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
 	return EVP_CipherInit_ex(ctx,cipher,NULL,key,iv,enc);
 	}
 
-int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *impl,
-	     const unsigned char *key, const unsigned char *iv, int enc)
-	{
-	if (enc == -1)
-		enc = ctx->encrypt;
-	else
-		{
-		if (enc)
-			enc = 1;
-		ctx->encrypt = enc;
-		}
-#ifndef OPENSSL_NO_ENGINE
-	/* Whether it's nice or not, "Inits" can be used on "Final"'d contexts
-	 * so this context may already have an ENGINE! Try to avoid releasing
-	 * the previous handle, re-querying for an ENGINE, and having a
-	 * reinitialisation, when it may all be unecessary. */
-	if (ctx->engine && ctx->cipher && (!cipher ||
-			(cipher && (cipher->nid == ctx->cipher->nid))))
-		goto skip_to_init;
-#endif
-	if (cipher)
-		{
-		/* Ensure a context left lying around from last time is cleared
-		 * (the previous check attempted to avoid this if the same
-		 * ENGINE and EVP_CIPHER could be used). */
-		EVP_CIPHER_CTX_cleanup(ctx);
-
-		/* Restore encrypt field: it is zeroed by cleanup */
-		ctx->encrypt = enc;
-#ifndef OPENSSL_NO_ENGINE
-		if(impl)
-			{
-			if (!ENGINE_init(impl))
-				{
-				EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
-				return 0;
-				}
-			}
-		else
-			/* Ask if an ENGINE is reserved for this job */
-			impl = ENGINE_get_cipher_engine(cipher->nid);
-		if(impl)
-			{
-			/* There's an ENGINE for this job ... (apparently) */
-			const EVP_CIPHER *c = ENGINE_get_cipher(impl, cipher->nid);
-			if(!c)
-				{
-				/* One positive side-effect of US's export
-				 * control history, is that we should at least
-				 * be able to avoid using US mispellings of
-				 * "initialisation"? */
-				EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
-				return 0;
-				}
-			/* We'll use the ENGINE's private cipher definition */
-			cipher = c;
-			/* Store the ENGINE functional reference so we know
-			 * 'cipher' came from an ENGINE and we need to release
-			 * it when done. */
-			ctx->engine = impl;
-			}
-		else
-			ctx->engine = NULL;
-#endif
-
-		ctx->cipher=cipher;
-		if (ctx->cipher->ctx_size)
-			{
-			ctx->cipher_data=OPENSSL_malloc(ctx->cipher->ctx_size);
-			if (!ctx->cipher_data)
-				{
-				EVPerr(EVP_F_EVP_CIPHERINIT_EX, ERR_R_MALLOC_FAILURE);
-				return 0;
-				}
-			}
-		else
-			{
-			ctx->cipher_data = NULL;
-			}
-		ctx->key_len = cipher->key_len;
-		ctx->flags = 0;
-		if(ctx->cipher->flags & EVP_CIPH_CTRL_INIT)
-			{
-			if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_INIT, 0, NULL))
-				{
-				EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
-				return 0;
-				}
-			}
-		}
-	else if(!ctx->cipher)
-		{
-		EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_NO_CIPHER_SET);
-		return 0;
-		}
-#ifndef OPENSSL_NO_ENGINE
-skip_to_init:
-#endif
-	/* we assume block size is a power of 2 in *cryptUpdate */
-	OPENSSL_assert(ctx->cipher->block_size == 1
-	    || ctx->cipher->block_size == 8
-	    || ctx->cipher->block_size == 16);
-
-	if(!(EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_CUSTOM_IV)) {
-		switch(EVP_CIPHER_CTX_mode(ctx)) {
-
-			case EVP_CIPH_STREAM_CIPHER:
-			case EVP_CIPH_ECB_MODE:
-			break;
-
-			case EVP_CIPH_CFB_MODE:
-			case EVP_CIPH_OFB_MODE:
-
-			ctx->num = 0;
-
-			case EVP_CIPH_CBC_MODE:
-
-			OPENSSL_assert(EVP_CIPHER_CTX_iv_length(ctx) <=
-					(int)sizeof(ctx->iv));
-			if(iv) memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx));
-			memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx));
-			break;
-
-			default:
-			return 0;
-			break;
-		}
-	}
-
-	if(key || (ctx->cipher->flags & EVP_CIPH_ALWAYS_CALL_INIT)) {
-		if(!ctx->cipher->init(ctx,key,iv,enc)) return 0;
-	}
-	ctx->buf_len=0;
-	ctx->final_used=0;
-	ctx->block_mask=ctx->cipher->block_size-1;
-	return 1;
-	}
-
 int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
 	     const unsigned char *in, int inl)
 	{
@@ -279,10 +143,15 @@ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
 	{
 	int i,j,bl;
 
-	OPENSSL_assert(inl > 0);
+	if (inl <= 0)
+		{
+		*outl = 0;
+		return inl == 0;
+		}
+
 	if(ctx->buf_len == 0 && (inl&(ctx->block_mask)) == 0)
 		{
-		if(ctx->cipher->do_cipher(ctx,out,in,inl))
+		if(M_do_cipher(ctx,out,in,inl))
 			{
 			*outl=inl;
 			return 1;
@@ -309,7 +178,7 @@ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
 			{
 			j=bl-i;
 			memcpy(&(ctx->buf[i]),in,j);
-			if(!ctx->cipher->do_cipher(ctx,out,ctx->buf,bl)) return 0;
+			if(!M_do_cipher(ctx,out,ctx->buf,bl)) return 0;
 			inl-=j;
 			in+=j;
 			out+=bl;
@@ -322,7 +191,7 @@ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
 	inl-=i;
 	if (inl > 0)
 		{
-		if(!ctx->cipher->do_cipher(ctx,out,in,inl)) return 0;
+		if(!M_do_cipher(ctx,out,in,inl)) return 0;
 		*outl+=inl;
 		}
 
@@ -366,7 +235,7 @@ int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
 	n=b-bl;
 	for (i=bl; i<b; i++)
 		ctx->buf[i]=n;
-	ret=ctx->cipher->do_cipher(ctx,out,ctx->buf,b);
+	ret=M_do_cipher(ctx,out,ctx->buf,b);
 
 
 	if(ret)
@@ -381,10 +250,10 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
 	int fix_len;
 	unsigned int b;
 
-	if (inl == 0)
+	if (inl <= 0)
 		{
-		*outl=0;
-		return 1;
+		*outl = 0;
+		return inl == 0;
 		}
 
 	if (ctx->flags & EVP_CIPH_NO_PADDING)
@@ -488,28 +357,6 @@ void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx)
 		}
 	}
 
-int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *c)
-	{
-	if (c->cipher != NULL)
-		{
-		if(c->cipher->cleanup && !c->cipher->cleanup(c))
-			return 0;
-		/* Cleanse cipher context data */
-		if (c->cipher_data)
-			OPENSSL_cleanse(c->cipher_data, c->cipher->ctx_size);
-		}
-	if (c->cipher_data)
-		OPENSSL_free(c->cipher_data);
-#ifndef OPENSSL_NO_ENGINE
-	if (c->engine)
-		/* The EVP_CIPHER we used belongs to an ENGINE, release the
-		 * functional reference we held for this reason. */
-		ENGINE_finish(c->engine);
-#endif
-	memset(c,0,sizeof(EVP_CIPHER_CTX));
-	return 1;
-	}
-
 int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, int keylen)
 	{
 	if(c->cipher->flags & EVP_CIPH_CUSTOM_KEY_LENGTH) 
@@ -531,27 +378,6 @@ int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int pad)
 	return 1;
 	}
 
-int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
-{
-	int ret;
-	if(!ctx->cipher) {
-		EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_NO_CIPHER_SET);
-		return 0;
-	}
-
-	if(!ctx->cipher->ctrl) {
-		EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_CTRL_NOT_IMPLEMENTED);
-		return 0;
-	}
-
-	ret = ctx->cipher->ctrl(ctx, type, arg, ptr);
-	if(ret == -1) {
-		EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED);
-		return 0;
-	}
-	return ret;
-}
-
 int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key)
 	{
 	if (ctx->cipher->flags & EVP_CIPH_RAND_KEY)
@@ -561,3 +387,54 @@ int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key)
 	return 1;
 	}
 
+#ifndef OPENSSL_NO_ENGINE
+
+#ifdef OPENSSL_FIPS
+
+static int do_evp_enc_engine_full(EVP_CIPHER_CTX *ctx, const EVP_CIPHER **pcipher, ENGINE *impl)
+	{
+	if(impl)
+		{
+		if (!ENGINE_init(impl))
+			{
+			EVPerr(EVP_F_DO_EVP_ENC_ENGINE_FULL, EVP_R_INITIALIZATION_ERROR);
+			return 0;
+			}
+		}
+	else
+		/* Ask if an ENGINE is reserved for this job */
+		impl = ENGINE_get_cipher_engine((*pcipher)->nid);
+	if(impl)
+		{
+		/* There's an ENGINE for this job ... (apparently) */
+		const EVP_CIPHER *c = ENGINE_get_cipher(impl, (*pcipher)->nid);
+		if(!c)
+			{
+			/* One positive side-effect of US's export
+			 * control history, is that we should at least
+			 * be able to avoid using US mispellings of
+			 * "initialisation"? */
+			EVPerr(EVP_F_DO_EVP_ENC_ENGINE_FULL, EVP_R_INITIALIZATION_ERROR);
+			return 0;
+			}
+		/* We'll use the ENGINE's private cipher definition */
+		*pcipher = c;
+		/* Store the ENGINE functional reference so we know
+		 * 'cipher' came from an ENGINE and we need to release
+		 * it when done. */
+		ctx->engine = impl;
+		}
+	else
+		ctx->engine = NULL;
+	return 1;
+	}
+
+void int_EVP_CIPHER_init_engine_callbacks(void)
+	{
+	int_EVP_CIPHER_set_engine_callbacks(
+		ENGINE_finish, do_evp_enc_engine_full);
+	}
+
+#endif
+
+#endif
diff --git a/src/lib/libcrypto/evp/evp_err.c b/src/lib/libcrypto/evp/evp_err.c
index e8c9e8de9c..b5b900d4fe 100644
--- a/src/lib/libcrypto/evp/evp_err.c
+++ b/src/lib/libcrypto/evp/evp_err.c
@@ -1,6 +1,6 @@
 /* crypto/evp/evp_err.c */
 /* ====================================================================
- * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-2007 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -71,16 +71,23 @@
 static ERR_STRING_DATA EVP_str_functs[]=
 	{
 {ERR_FUNC(EVP_F_AES_INIT_KEY),	"AES_INIT_KEY"},
+{ERR_FUNC(EVP_F_ALG_MODULE_INIT),	"ALG_MODULE_INIT"},
 {ERR_FUNC(EVP_F_CAMELLIA_INIT_KEY),	"CAMELLIA_INIT_KEY"},
 {ERR_FUNC(EVP_F_D2I_PKEY),	"D2I_PKEY"},
+{ERR_FUNC(EVP_F_DO_EVP_ENC_ENGINE),	"DO_EVP_ENC_ENGINE"},
+{ERR_FUNC(EVP_F_DO_EVP_ENC_ENGINE_FULL),	"DO_EVP_ENC_ENGINE_FULL"},
+{ERR_FUNC(EVP_F_DO_EVP_MD_ENGINE),	"DO_EVP_MD_ENGINE"},
+{ERR_FUNC(EVP_F_DO_EVP_MD_ENGINE_FULL),	"DO_EVP_MD_ENGINE_FULL"},
 {ERR_FUNC(EVP_F_DSAPKEY2PKCS8),	"DSAPKEY2PKCS8"},
 {ERR_FUNC(EVP_F_DSA_PKEY2PKCS8),	"DSA_PKEY2PKCS8"},
 {ERR_FUNC(EVP_F_ECDSA_PKEY2PKCS8),	"ECDSA_PKEY2PKCS8"},
 {ERR_FUNC(EVP_F_ECKEY_PKEY2PKCS8),	"ECKEY_PKEY2PKCS8"},
+{ERR_FUNC(EVP_F_EVP_CIPHERINIT),	"EVP_CipherInit"},
 {ERR_FUNC(EVP_F_EVP_CIPHERINIT_EX),	"EVP_CipherInit_ex"},
 {ERR_FUNC(EVP_F_EVP_CIPHER_CTX_CTRL),	"EVP_CIPHER_CTX_ctrl"},
 {ERR_FUNC(EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH),	"EVP_CIPHER_CTX_set_key_length"},
 {ERR_FUNC(EVP_F_EVP_DECRYPTFINAL_EX),	"EVP_DecryptFinal_ex"},
+{ERR_FUNC(EVP_F_EVP_DIGESTINIT),	"EVP_DigestInit"},
 {ERR_FUNC(EVP_F_EVP_DIGESTINIT_EX),	"EVP_DigestInit_ex"},
 {ERR_FUNC(EVP_F_EVP_ENCRYPTFINAL_EX),	"EVP_EncryptFinal_ex"},
 {ERR_FUNC(EVP_F_EVP_MD_CTX_COPY_EX),	"EVP_MD_CTX_copy_ex"},
@@ -125,15 +132,20 @@ static ERR_STRING_DATA EVP_str_reasons[]=
 {ERR_REASON(EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH),"data not multiple of block length"},
 {ERR_REASON(EVP_R_DECODE_ERROR)          ,"decode error"},
 {ERR_REASON(EVP_R_DIFFERENT_KEY_TYPES)   ,"different key types"},
+{ERR_REASON(EVP_R_DISABLED_FOR_FIPS)     ,"disabled for fips"},
 {ERR_REASON(EVP_R_ENCODE_ERROR)          ,"encode error"},
+{ERR_REASON(EVP_R_ERROR_LOADING_SECTION) ,"error loading section"},
+{ERR_REASON(EVP_R_ERROR_SETTING_FIPS_MODE),"error setting fips mode"},
 {ERR_REASON(EVP_R_EVP_PBE_CIPHERINIT_ERROR),"evp pbe cipherinit error"},
 {ERR_REASON(EVP_R_EXPECTING_AN_RSA_KEY)  ,"expecting an rsa key"},
 {ERR_REASON(EVP_R_EXPECTING_A_DH_KEY)    ,"expecting a dh key"},
 {ERR_REASON(EVP_R_EXPECTING_A_DSA_KEY)   ,"expecting a dsa key"},
 {ERR_REASON(EVP_R_EXPECTING_A_ECDSA_KEY) ,"expecting a ecdsa key"},
 {ERR_REASON(EVP_R_EXPECTING_A_EC_KEY)    ,"expecting a ec key"},
+{ERR_REASON(EVP_R_FIPS_MODE_NOT_SUPPORTED),"fips mode not supported"},
 {ERR_REASON(EVP_R_INITIALIZATION_ERROR)  ,"initialization error"},
 {ERR_REASON(EVP_R_INPUT_NOT_INITIALIZED) ,"input not initialized"},
+{ERR_REASON(EVP_R_INVALID_FIPS_MODE)     ,"invalid fips mode"},
 {ERR_REASON(EVP_R_INVALID_KEY_LENGTH)    ,"invalid key length"},
 {ERR_REASON(EVP_R_IV_TOO_LARGE)          ,"iv too large"},
 {ERR_REASON(EVP_R_KEYGEN_FAILURE)        ,"keygen failure"},
@@ -145,6 +157,8 @@ static ERR_STRING_DATA EVP_str_reasons[]=
 {ERR_REASON(EVP_R_NO_VERIFY_FUNCTION_CONFIGURED),"no verify function configured"},
 {ERR_REASON(EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE),"pkcs8 unknown broken type"},
 {ERR_REASON(EVP_R_PUBLIC_KEY_NOT_RSA)    ,"public key not rsa"},
+{ERR_REASON(EVP_R_SEED_KEY_SETUP_FAILED) ,"seed key setup failed"},
+{ERR_REASON(EVP_R_UNKNOWN_OPTION)        ,"unknown option"},
 {ERR_REASON(EVP_R_UNKNOWN_PBE_ALGORITHM) ,"unknown pbe algorithm"},
 {ERR_REASON(EVP_R_UNSUPORTED_NUMBER_OF_ROUNDS),"unsuported number of rounds"},
 {ERR_REASON(EVP_R_UNSUPPORTED_CIPHER)    ,"unsupported cipher"},
diff --git a/src/lib/libcrypto/evp/evp_lib.c b/src/lib/libcrypto/evp/evp_lib.c
index edb28ef38e..174cf6c594 100644
--- a/src/lib/libcrypto/evp/evp_lib.c
+++ b/src/lib/libcrypto/evp/evp_lib.c
@@ -67,6 +67,8 @@ int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
 
 	if (c->cipher->set_asn1_parameters != NULL)
 		ret=c->cipher->set_asn1_parameters(c,type);
+	else if (c->cipher->flags & EVP_CIPH_FLAG_DEFAULT_ASN1)
+		ret=EVP_CIPHER_set_asn1_iv(c, type);
 	else
 		ret=-1;
 	return(ret);
@@ -78,6 +80,8 @@ int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
 
 	if (c->cipher->get_asn1_parameters != NULL)
 		ret=c->cipher->get_asn1_parameters(c,type);
+	else if (c->cipher->flags & EVP_CIPH_FLAG_DEFAULT_ASN1)
+		ret=EVP_CIPHER_get_asn1_iv(c, type);
 	else
 		ret=-1;
 	return(ret);
@@ -178,11 +182,6 @@ int EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx)
 	return ctx->cipher->block_size;
 	}
 
-int EVP_Cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl)
-	{
-	return ctx->cipher->do_cipher(ctx,out,in,inl);
-	}
-
 const EVP_CIPHER *EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx)
 	{
 	return ctx->cipher;
@@ -193,11 +192,6 @@ unsigned long EVP_CIPHER_flags(const EVP_CIPHER *cipher)
 	return cipher->flags;
 	}
 
-unsigned long EVP_CIPHER_CTX_flags(const EVP_CIPHER_CTX *ctx)
-	{
-	return ctx->cipher->flags;
-	}
-
 void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx)
 	{
 	return ctx->app_data;
@@ -213,11 +207,6 @@ int EVP_CIPHER_iv_length(const EVP_CIPHER *cipher)
 	return cipher->iv_len;
 	}
 
-int EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx)
-	{
-	return ctx->cipher->iv_len;
-	}
-
 int EVP_CIPHER_key_length(const EVP_CIPHER *cipher)
 	{
 	return cipher->key_len;
@@ -228,11 +217,6 @@ int EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx)
 	return ctx->key_len;
 	}
 
-int EVP_CIPHER_nid(const EVP_CIPHER *cipher)
-	{
-	return cipher->nid;
-	}
-
 int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx)
 	{
 	return ctx->cipher->nid;
@@ -277,3 +261,18 @@ int EVP_MD_CTX_test_flags(const EVP_MD_CTX *ctx, int flags)
 	{
 	return (ctx->flags & flags);
 	}
+
+void EVP_CIPHER_CTX_set_flags(EVP_CIPHER_CTX *ctx, int flags)
+	{
+	ctx->flags |= flags;
+	}
+
+void EVP_CIPHER_CTX_clear_flags(EVP_CIPHER_CTX *ctx, int flags)
+	{
+	ctx->flags &= ~flags;
+	}
+
+int EVP_CIPHER_CTX_test_flags(const EVP_CIPHER_CTX *ctx, int flags)
+	{
+	return (ctx->flags & flags);
+	}
diff --git a/src/lib/libcrypto/evp/evp_locl.h b/src/lib/libcrypto/evp/evp_locl.h
index 073b0adcff..eabcc96f30 100644
--- a/src/lib/libcrypto/evp/evp_locl.h
+++ b/src/lib/libcrypto/evp/evp_locl.h
@@ -1,5 +1,5 @@
 /* evp_locl.h */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2000.
  */
 /* ====================================================================
@@ -92,7 +92,7 @@ static int cname##_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const uns
 #define BLOCK_CIPHER_func_cfb(cname, cprefix, cbits, kstruct, ksched) \
 static int cname##_cfb##cbits##_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl) \
 {\
-	cprefix##_cfb##cbits##_encrypt(in, out, (long)(cbits==1?inl*8:inl), &((kstruct *)ctx->cipher_data)->ksched, ctx->iv, &ctx->num, ctx->encrypt);\
+	cprefix##_cfb##cbits##_encrypt(in, out, (long)((cbits==1) && !(ctx->flags & EVP_CIPH_FLAG_LENGTH_BITS) ?inl*8:inl), &((kstruct *)ctx->cipher_data)->ksched, ctx->iv, &ctx->num, ctx->encrypt);\
 	return 1;\
 }
 
@@ -226,11 +226,27 @@ const EVP_CIPHER *EVP_##cname##_ecb(void) { return &cname##_ecb; }
 
 #define EVP_C_DATA(kstruct, ctx)	((kstruct *)(ctx)->cipher_data)
 
-#define IMPLEMENT_CFBR(cipher,cprefix,kstruct,ksched,keysize,cbits,iv_len) \
+#define IMPLEMENT_CFBR(cipher,cprefix,kstruct,ksched,keysize,cbits,iv_len,fl) \
 	BLOCK_CIPHER_func_cfb(cipher##_##keysize,cprefix,cbits,kstruct,ksched) \
 	BLOCK_CIPHER_def_cfb(cipher##_##keysize,kstruct, \
 			     NID_##cipher##_##keysize, keysize/8, iv_len, cbits, \
-			     0, cipher##_init_key, NULL, \
-			     EVP_CIPHER_set_asn1_iv, \
-			     EVP_CIPHER_get_asn1_iv, \
-			     NULL)
+			     (fl)|EVP_CIPH_FLAG_DEFAULT_ASN1, \
+			     cipher##_init_key, NULL, NULL, NULL, NULL)
+
+#ifdef OPENSSL_FIPS
+#define RC2_set_key	private_RC2_set_key
+#define RC4_set_key	private_RC4_set_key
+#define CAST_set_key	private_CAST_set_key
+#define RC5_32_set_key	private_RC5_32_set_key
+#define BF_set_key	private_BF_set_key
+#define Camellia_set_key private_Camellia_set_key
+#define idea_set_encrypt_key private_idea_set_encrypt_key
+
+#define MD5_Init	private_MD5_Init
+#define MD4_Init	private_MD4_Init
+#define MD2_Init	private_MD2_Init
+#define MDC2_Init	private_MDC2_Init
+#define SHA_Init	private_SHA_Init
+
+#endif
+
diff --git a/src/lib/libcrypto/evp/evp_pbe.c b/src/lib/libcrypto/evp/evp_pbe.c
index c26d2de0f3..5e830be65f 100644
--- a/src/lib/libcrypto/evp/evp_pbe.c
+++ b/src/lib/libcrypto/evp/evp_pbe.c
@@ -1,5 +1,5 @@
 /* evp_pbe.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/evp/evp_pkey.c b/src/lib/libcrypto/evp/evp_pkey.c
index 0147f3e02a..10d9e9e772 100644
--- a/src/lib/libcrypto/evp/evp_pkey.c
+++ b/src/lib/libcrypto/evp/evp_pkey.c
@@ -1,5 +1,5 @@
 /* evp_pkey.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/evp/m_dss.c b/src/lib/libcrypto/evp/m_dss.c
index a948c77fa4..6b0c0aa7a3 100644
--- a/src/lib/libcrypto/evp/m_dss.c
+++ b/src/lib/libcrypto/evp/m_dss.c
@@ -81,7 +81,7 @@ static const EVP_MD dsa_md=
 	NID_dsaWithSHA,
 	NID_dsaWithSHA,
 	SHA_DIGEST_LENGTH,
-	0,
+	EVP_MD_FLAG_FIPS,
 	init,
 	update,
 	final,
diff --git a/src/lib/libcrypto/evp/m_dss1.c b/src/lib/libcrypto/evp/m_dss1.c
index c12e13972b..da8babc147 100644
--- a/src/lib/libcrypto/evp/m_dss1.c
+++ b/src/lib/libcrypto/evp/m_dss1.c
@@ -68,6 +68,8 @@
 #include <openssl/dsa.h>
 #endif
 
+#ifndef OPENSSL_FIPS
+
 static int init(EVP_MD_CTX *ctx)
 	{ return SHA1_Init(ctx->md_data); }
 
@@ -98,3 +100,4 @@ const EVP_MD *EVP_dss1(void)
 	return(&dss1_md);
 	}
 #endif
+#endif
diff --git a/src/lib/libcrypto/evp/m_md4.c b/src/lib/libcrypto/evp/m_md4.c
index 1e0b7c5b42..5cd2ab5ade 100644
--- a/src/lib/libcrypto/evp/m_md4.c
+++ b/src/lib/libcrypto/evp/m_md4.c
@@ -58,6 +58,7 @@
 
 #include <stdio.h>
 #include "cryptlib.h"
+#include "evp_locl.h"
 
 #ifndef OPENSSL_NO_MD4
 
diff --git a/src/lib/libcrypto/evp/m_md5.c b/src/lib/libcrypto/evp/m_md5.c
index 63c142119e..6455829671 100644
--- a/src/lib/libcrypto/evp/m_md5.c
+++ b/src/lib/libcrypto/evp/m_md5.c
@@ -62,6 +62,7 @@
 #ifndef OPENSSL_NO_MD5
 
 #include <openssl/evp.h>
+#include "evp_locl.h"
 #include <openssl/objects.h>
 #include <openssl/x509.h>
 #include <openssl/md5.h>
diff --git a/src/lib/libcrypto/evp/m_sha1.c b/src/lib/libcrypto/evp/m_sha1.c
index 4679b1c463..471ec30be0 100644
--- a/src/lib/libcrypto/evp/m_sha1.c
+++ b/src/lib/libcrypto/evp/m_sha1.c
@@ -68,6 +68,8 @@
 #include <openssl/rsa.h>
 #endif
 
+#ifndef OPENSSL_FIPS
+
 static int init(EVP_MD_CTX *ctx)
 	{ return SHA1_Init(ctx->md_data); }
 
@@ -97,7 +99,6 @@ const EVP_MD *EVP_sha1(void)
 	{
 	return(&sha1_md);
 	}
-#endif
 
 #ifndef OPENSSL_NO_SHA256
 static int init224(EVP_MD_CTX *ctx)
@@ -202,3 +203,7 @@ static const EVP_MD sha512_md=
 const EVP_MD *EVP_sha512(void)
 	{ return(&sha512_md); }
 #endif	/* ifndef OPENSSL_NO_SHA512 */
+
+#endif
+
+#endif
diff --git a/src/lib/libcrypto/evp/names.c b/src/lib/libcrypto/evp/names.c
index 88c1e780dd..e2e04c3570 100644
--- a/src/lib/libcrypto/evp/names.c
+++ b/src/lib/libcrypto/evp/names.c
@@ -66,6 +66,10 @@ int EVP_add_cipher(const EVP_CIPHER *c)
 	{
 	int r;
 
+#ifdef OPENSSL_FIPS
+	OPENSSL_init();
+#endif
+
 	r=OBJ_NAME_add(OBJ_nid2sn(c->nid),OBJ_NAME_TYPE_CIPHER_METH,(const char *)c);
 	if (r == 0) return(0);
 	r=OBJ_NAME_add(OBJ_nid2ln(c->nid),OBJ_NAME_TYPE_CIPHER_METH,(const char *)c);
@@ -77,6 +81,9 @@ int EVP_add_digest(const EVP_MD *md)
 	int r;
 	const char *name;
 
+#ifdef OPENSSL_FIPS
+	OPENSSL_init();
+#endif
 	name=OBJ_nid2sn(md->type);
 	r=OBJ_NAME_add(name,OBJ_NAME_TYPE_MD_METH,(const char *)md);
 	if (r == 0) return(0);
diff --git a/src/lib/libcrypto/evp/p5_crpt.c b/src/lib/libcrypto/evp/p5_crpt.c
index 48d50014a0..2a265fdee2 100644
--- a/src/lib/libcrypto/evp/p5_crpt.c
+++ b/src/lib/libcrypto/evp/p5_crpt.c
@@ -1,5 +1,5 @@
 /* p5_crpt.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/evp/p5_crpt2.c b/src/lib/libcrypto/evp/p5_crpt2.c
index c969d5a206..6bec77baf9 100644
--- a/src/lib/libcrypto/evp/p5_crpt2.c
+++ b/src/lib/libcrypto/evp/p5_crpt2.c
@@ -1,5 +1,5 @@
 /* p5_crpt2.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/evp/p_sign.c b/src/lib/libcrypto/evp/p_sign.c
index e4ae5906f5..bf41a0db68 100644
--- a/src/lib/libcrypto/evp/p_sign.c
+++ b/src/lib/libcrypto/evp/p_sign.c
@@ -84,10 +84,6 @@ int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, unsigned int *siglen,
 	MS_STATIC EVP_MD_CTX tmp_ctx;
 
 	*siglen=0;
-	EVP_MD_CTX_init(&tmp_ctx);
-	EVP_MD_CTX_copy_ex(&tmp_ctx,ctx);   
-	EVP_DigestFinal_ex(&tmp_ctx,&(m[0]),&m_len);
-	EVP_MD_CTX_cleanup(&tmp_ctx);
 	for (i=0; i<4; i++)
 		{
 		v=ctx->digest->required_pkey_type[i];
@@ -108,7 +104,23 @@ int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, unsigned int *siglen,
 		EVPerr(EVP_F_EVP_SIGNFINAL,EVP_R_NO_SIGN_FUNCTION_CONFIGURED);
 		return(0);
 		}
-	return(ctx->digest->sign(ctx->digest->type,m,m_len,sigret,siglen,
-		pkey->pkey.ptr));
+	EVP_MD_CTX_init(&tmp_ctx);
+	EVP_MD_CTX_copy_ex(&tmp_ctx,ctx);
+	if (ctx->digest->flags & EVP_MD_FLAG_SVCTX)
+		{
+		EVP_MD_SVCTX sctmp;
+		sctmp.mctx = &tmp_ctx;
+		sctmp.key = pkey->pkey.ptr;
+		i = ctx->digest->sign(ctx->digest->type,
+			NULL, -1, sigret, siglen, &sctmp);
+		}
+	else
+		{
+		EVP_DigestFinal_ex(&tmp_ctx,&(m[0]),&m_len);
+		i = ctx->digest->sign(ctx->digest->type,m,m_len,sigret,siglen,
+					pkey->pkey.ptr);
+		}
+	EVP_MD_CTX_cleanup(&tmp_ctx);
+	return i;
 	}
 
diff --git a/src/lib/libcrypto/evp/p_verify.c b/src/lib/libcrypto/evp/p_verify.c
index 21a40a375e..2d46dffe7e 100644
--- a/src/lib/libcrypto/evp/p_verify.c
+++ b/src/lib/libcrypto/evp/p_verify.c
@@ -85,17 +85,29 @@ int EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf,
 		EVPerr(EVP_F_EVP_VERIFYFINAL,EVP_R_WRONG_PUBLIC_KEY_TYPE);
 		return(-1);
 		}
-	EVP_MD_CTX_init(&tmp_ctx);
-	EVP_MD_CTX_copy_ex(&tmp_ctx,ctx);     
-	EVP_DigestFinal_ex(&tmp_ctx,&(m[0]),&m_len);
-	EVP_MD_CTX_cleanup(&tmp_ctx);
-        if (ctx->digest->verify == NULL)
+	if (ctx->digest->verify == NULL)
                 {
 		EVPerr(EVP_F_EVP_VERIFYFINAL,EVP_R_NO_VERIFY_FUNCTION_CONFIGURED);
 		return(0);
 		}
 
-	return(ctx->digest->verify(ctx->digest->type,m,m_len,
-		sigbuf,siglen,pkey->pkey.ptr));
+	EVP_MD_CTX_init(&tmp_ctx);
+	EVP_MD_CTX_copy_ex(&tmp_ctx,ctx);     
+	if (ctx->digest->flags & EVP_MD_FLAG_SVCTX)
+		{
+		EVP_MD_SVCTX sctmp;
+		sctmp.mctx = &tmp_ctx;
+		sctmp.key = pkey->pkey.ptr;
+		i = ctx->digest->verify(ctx->digest->type,
+			NULL, -1, sigbuf, siglen, &sctmp);
+		}
+	else
+		{
+		EVP_DigestFinal_ex(&tmp_ctx,&(m[0]),&m_len);
+		i = ctx->digest->verify(ctx->digest->type,m,m_len,
+					sigbuf,siglen,pkey->pkey.ptr);
+		}
+	EVP_MD_CTX_cleanup(&tmp_ctx);
+	return i;
 	}
 
diff --git a/src/lib/libcrypto/hmac/hmac.c b/src/lib/libcrypto/hmac/hmac.c
index c45e001492..cbc1c76a57 100644
--- a/src/lib/libcrypto/hmac/hmac.c
+++ b/src/lib/libcrypto/hmac/hmac.c
@@ -61,6 +61,8 @@
 #include "cryptlib.h"
 #include <openssl/hmac.h>
 
+#ifndef OPENSSL_FIPS
+
 void HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
 		  const EVP_MD *md, ENGINE *impl)
 	{
@@ -171,3 +173,11 @@ unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len,
 	return(md);
 	}
 
+void HMAC_CTX_set_flags(HMAC_CTX *ctx, unsigned long flags)
+	{
+	EVP_MD_CTX_set_flags(&ctx->i_ctx, flags);
+	EVP_MD_CTX_set_flags(&ctx->o_ctx, flags);
+	EVP_MD_CTX_set_flags(&ctx->md_ctx, flags);
+	}
+
+#endif
diff --git a/src/lib/libcrypto/hmac/hmac.h b/src/lib/libcrypto/hmac/hmac.h
index 719fc408ac..fc38ffb52b 100644
--- a/src/lib/libcrypto/hmac/hmac.h
+++ b/src/lib/libcrypto/hmac/hmac.h
@@ -100,6 +100,7 @@ unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len,
 		    const unsigned char *d, size_t n, unsigned char *md,
 		    unsigned int *md_len);
 
+void HMAC_CTX_set_flags(HMAC_CTX *ctx, unsigned long flags);
 
 #ifdef  __cplusplus
 }
diff --git a/src/lib/libcrypto/idea/idea.h b/src/lib/libcrypto/idea/idea.h
index bf97a37e39..a137d4cbce 100644
--- a/src/lib/libcrypto/idea/idea.h
+++ b/src/lib/libcrypto/idea/idea.h
@@ -83,6 +83,9 @@ typedef struct idea_key_st
 const char *idea_options(void);
 void idea_ecb_encrypt(const unsigned char *in, unsigned char *out,
 	IDEA_KEY_SCHEDULE *ks);
+#ifdef OPENSSL_FIPS
+void private_idea_set_encrypt_key(const unsigned char *key, IDEA_KEY_SCHEDULE *ks);
+#endif
 void idea_set_encrypt_key(const unsigned char *key, IDEA_KEY_SCHEDULE *ks);
 void idea_set_decrypt_key(const IDEA_KEY_SCHEDULE *ek, IDEA_KEY_SCHEDULE *dk);
 void idea_cbc_encrypt(const unsigned char *in, unsigned char *out,
diff --git a/src/lib/libcrypto/md32_common.h b/src/lib/libcrypto/md32_common.h
index 089c450290..61bcd9786f 100644
--- a/src/lib/libcrypto/md32_common.h
+++ b/src/lib/libcrypto/md32_common.h
@@ -301,7 +301,7 @@ int HASH_UPDATE (HASH_CTX *c, const void *data_, size_t len)
 		{
 		p=(unsigned char *)c->data;
 
-		if ((n+len) >= HASH_CBLOCK)
+		if (len >= HASH_CBLOCK || len+n >= HASH_CBLOCK)
 			{
 			memcpy (p+n,data,HASH_CBLOCK-n);
 			HASH_BLOCK_DATA_ORDER (c,p,1);
diff --git a/src/lib/libcrypto/md4/md4.h b/src/lib/libcrypto/md4/md4.h
index 5598c93a4f..ba1fe4a6ee 100644
--- a/src/lib/libcrypto/md4/md4.h
+++ b/src/lib/libcrypto/md4/md4.h
@@ -105,6 +105,9 @@ typedef struct MD4state_st
 	unsigned int num;
 	} MD4_CTX;
 
+#ifdef OPENSSL_FIPS
+int private_MD4_Init(MD4_CTX *c);
+#endif
 int MD4_Init(MD4_CTX *c);
 int MD4_Update(MD4_CTX *c, const void *data, size_t len);
 int MD4_Final(unsigned char *md, MD4_CTX *c);
diff --git a/src/lib/libcrypto/md4/md4_dgst.c b/src/lib/libcrypto/md4/md4_dgst.c
index cfef94af39..0f5448601d 100644
--- a/src/lib/libcrypto/md4/md4_dgst.c
+++ b/src/lib/libcrypto/md4/md4_dgst.c
@@ -59,6 +59,11 @@
 #include <stdio.h>
 #include "md4_locl.h"
 #include <openssl/opensslv.h>
+#include <openssl/err.h>
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
+
 
 const char MD4_version[]="MD4" OPENSSL_VERSION_PTEXT;
 
@@ -70,7 +75,7 @@ const char MD4_version[]="MD4" OPENSSL_VERSION_PTEXT;
 #define INIT_DATA_C (unsigned long)0x98badcfeL
 #define INIT_DATA_D (unsigned long)0x10325476L
 
-int MD4_Init(MD4_CTX *c)
+FIPS_NON_FIPS_MD_Init(MD4)
 	{
 	c->A=INIT_DATA_A;
 	c->B=INIT_DATA_B;
diff --git a/src/lib/libcrypto/md5/md5.h b/src/lib/libcrypto/md5/md5.h
index dbdc0e1abc..0761f84a27 100644
--- a/src/lib/libcrypto/md5/md5.h
+++ b/src/lib/libcrypto/md5/md5.h
@@ -105,6 +105,9 @@ typedef struct MD5state_st
 	unsigned int num;
 	} MD5_CTX;
 
+#ifdef OPENSSL_FIPS
+int private_MD5_Init(MD5_CTX *c);
+#endif
 int MD5_Init(MD5_CTX *c);
 int MD5_Update(MD5_CTX *c, const void *data, size_t len);
 int MD5_Final(unsigned char *md, MD5_CTX *c);
diff --git a/src/lib/libcrypto/md5/md5_dgst.c b/src/lib/libcrypto/md5/md5_dgst.c
index b96e332ba4..47bb9020ee 100644
--- a/src/lib/libcrypto/md5/md5_dgst.c
+++ b/src/lib/libcrypto/md5/md5_dgst.c
@@ -59,6 +59,11 @@
 #include <stdio.h>
 #include "md5_locl.h"
 #include <openssl/opensslv.h>
+#include <openssl/err.h>
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
+
 
 const char MD5_version[]="MD5" OPENSSL_VERSION_PTEXT;
 
@@ -70,7 +75,7 @@ const char MD5_version[]="MD5" OPENSSL_VERSION_PTEXT;
 #define INIT_DATA_C (unsigned long)0x98badcfeL
 #define INIT_DATA_D (unsigned long)0x10325476L
 
-int MD5_Init(MD5_CTX *c)
+FIPS_NON_FIPS_MD_Init(MD5)
 	{
 	c->A=INIT_DATA_A;
 	c->B=INIT_DATA_B;
diff --git a/src/lib/libcrypto/mem_dbg.c b/src/lib/libcrypto/mem_dbg.c
index 8316485217..dfeb084799 100644
--- a/src/lib/libcrypto/mem_dbg.c
+++ b/src/lib/libcrypto/mem_dbg.c
@@ -330,7 +330,7 @@ static APP_INFO *pop_info(void)
 	return(ret);
 	}
 
-int CRYPTO_push_info_(const char *info, const char *file, int line)
+int CRYPTO_dbg_push_info(const char *info, const char *file, int line)
 	{
 	APP_INFO *ami, *amim;
 	int ret=0;
@@ -380,7 +380,7 @@ int CRYPTO_push_info_(const char *info, const char *file, int line)
 	return(ret);
 	}
 
-int CRYPTO_pop_info(void)
+int CRYPTO_dbg_pop_info(void)
 	{
 	int ret=0;
 
@@ -395,7 +395,7 @@ int CRYPTO_pop_info(void)
 	return(ret);
 	}
 
-int CRYPTO_remove_all_info(void)
+int CRYPTO_dbg_remove_all_info(void)
 	{
 	int ret=0;
 
@@ -793,3 +793,25 @@ void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb)
 	lh_doall_arg(mh, LHASH_DOALL_ARG_FN(cb_leak), &cb);
 	CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
 	}
+
+void CRYPTO_malloc_debug_init(void)
+	{
+	CRYPTO_set_mem_debug_functions(
+		CRYPTO_dbg_malloc,
+		CRYPTO_dbg_realloc,
+		CRYPTO_dbg_free,
+		CRYPTO_dbg_set_options,
+		CRYPTO_dbg_get_options);
+	CRYPTO_set_mem_info_functions(
+		CRYPTO_dbg_push_info,
+		CRYPTO_dbg_pop_info,
+		CRYPTO_dbg_remove_all_info);
+	}
+
+char *CRYPTO_strdup(const char *str, const char *file, int line)
+	{
+	char *ret = CRYPTO_malloc(strlen(str)+1, file, line);
+
+	strcpy(ret, str);
+	return ret;
+	}
diff --git a/src/lib/libcrypto/o_init.c b/src/lib/libcrypto/o_init.c
new file mode 100644
index 0000000000..00ed65a6cf
--- /dev/null
+++ b/src/lib/libcrypto/o_init.c
@@ -0,0 +1,86 @@
+/* o_init.c */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <e_os.h>
+#include <openssl/err.h>
+
+/* Perform any essential OpenSSL initialization operations.
+ * Currently only sets FIPS callbacks
+ */
+
+void OPENSSL_init(void)
+	{
+#ifdef OPENSSL_FIPS
+	static int done = 0;
+	if (!done)
+		{
+		int_ERR_lib_init();
+#ifdef CRYPTO_MDEBUG
+		CRYPTO_malloc_debug_init();
+#endif
+#ifdef OPENSSL_ENGINE
+		int_EVP_MD_init_engine_callbacks();
+		int_EVP_CIPHER_init_engine_callbacks();
+		int_RAND_init_engine_callbacks();
+#endif
+		done = 1;
+		}
+#endif
+	}
+		
+
diff --git a/src/lib/libcrypto/objects/obj_dat.pl b/src/lib/libcrypto/objects/obj_dat.pl
index 8a09a46ee6..7de2f77afd 100644
--- a/src/lib/libcrypto/objects/obj_dat.pl
+++ b/src/lib/libcrypto/objects/obj_dat.pl
@@ -2,7 +2,9 @@
 
 # fixes bug in floating point emulation on sparc64 when
 # this script produces off-by-one output on sparc64
-use integer;
+eval 'use integer;';
+
+print STDERR "Warning: perl module integer not found.\n" if ($@);
 
 sub obj_cmp
 	{
diff --git a/src/lib/libcrypto/objects/obj_mac.num b/src/lib/libcrypto/objects/obj_mac.num
index 47815b1e4e..e3f56bc52c 100644
--- a/src/lib/libcrypto/objects/obj_mac.num
+++ b/src/lib/libcrypto/objects/obj_mac.num
@@ -788,3 +788,71 @@ id_ct_asciiTextWithCRLF		787
 id_aes128_wrap		788
 id_aes192_wrap		789
 id_aes256_wrap		790
+ecdsa_with_Recommended		791
+ecdsa_with_Specified		792
+ecdsa_with_SHA224		793
+ecdsa_with_SHA256		794
+ecdsa_with_SHA384		795
+ecdsa_with_SHA512		796
+hmacWithMD5		797
+hmacWithSHA224		798
+hmacWithSHA256		799
+hmacWithSHA384		800
+hmacWithSHA512		801
+dsa_with_SHA224		802
+dsa_with_SHA256		803
+whirlpool		804
+cryptopro		805
+cryptocom		806
+id_GostR3411_94_with_GostR3410_2001		807
+id_GostR3411_94_with_GostR3410_94		808
+id_GostR3411_94		809
+id_HMACGostR3411_94		810
+id_GostR3410_2001		811
+id_GostR3410_94		812
+id_Gost28147_89		813
+gost89_cnt		814
+id_Gost28147_89_MAC		815
+id_GostR3411_94_prf		816
+id_GostR3410_2001DH		817
+id_GostR3410_94DH		818
+id_Gost28147_89_CryptoPro_KeyMeshing		819
+id_Gost28147_89_None_KeyMeshing		820
+id_GostR3411_94_TestParamSet		821
+id_GostR3411_94_CryptoProParamSet		822
+id_Gost28147_89_TestParamSet		823
+id_Gost28147_89_CryptoPro_A_ParamSet		824
+id_Gost28147_89_CryptoPro_B_ParamSet		825
+id_Gost28147_89_CryptoPro_C_ParamSet		826
+id_Gost28147_89_CryptoPro_D_ParamSet		827
+id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet		828
+id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet		829
+id_Gost28147_89_CryptoPro_RIC_1_ParamSet		830
+id_GostR3410_94_TestParamSet		831
+id_GostR3410_94_CryptoPro_A_ParamSet		832
+id_GostR3410_94_CryptoPro_B_ParamSet		833
+id_GostR3410_94_CryptoPro_C_ParamSet		834
+id_GostR3410_94_CryptoPro_D_ParamSet		835
+id_GostR3410_94_CryptoPro_XchA_ParamSet		836
+id_GostR3410_94_CryptoPro_XchB_ParamSet		837
+id_GostR3410_94_CryptoPro_XchC_ParamSet		838
+id_GostR3410_2001_TestParamSet		839
+id_GostR3410_2001_CryptoPro_A_ParamSet		840
+id_GostR3410_2001_CryptoPro_B_ParamSet		841
+id_GostR3410_2001_CryptoPro_C_ParamSet		842
+id_GostR3410_2001_CryptoPro_XchA_ParamSet		843
+id_GostR3410_2001_CryptoPro_XchB_ParamSet		844
+id_GostR3410_94_a		845
+id_GostR3410_94_aBis		846
+id_GostR3410_94_b		847
+id_GostR3410_94_bBis		848
+id_Gost28147_89_cc		849
+id_GostR3410_94_cc		850
+id_GostR3410_2001_cc		851
+id_GostR3411_94_with_GostR3410_94_cc		852
+id_GostR3411_94_with_GostR3410_2001_cc		853
+id_GostR3410_2001_ParamSet_cc		854
+hmac		855
+LocalKeySet		856
+freshest_crl		857
+id_on_permanentIdentifier		858
diff --git a/src/lib/libcrypto/objects/objects.txt b/src/lib/libcrypto/objects/objects.txt
index 34c8d1d647..a6a811b8e7 100644
--- a/src/lib/libcrypto/objects/objects.txt
+++ b/src/lib/libcrypto/objects/objects.txt
@@ -79,6 +79,12 @@ X9-62_primeCurve 7	 	: prime256v1
 !Alias id-ecSigType ansi-X9-62 4
 !global
 X9-62_id-ecSigType 1		: ecdsa-with-SHA1
+X9-62_id-ecSigType 2		: ecdsa-with-Recommended
+X9-62_id-ecSigType 3		: ecdsa-with-Specified
+ecdsa-with-Specified 1		: ecdsa-with-SHA224
+ecdsa-with-Specified 2		: ecdsa-with-SHA256
+ecdsa-with-Specified 3		: ecdsa-with-SHA384
+ecdsa-with-Specified 4		: ecdsa-with-SHA512
 
 # SECG curve OIDs from "SEC 2: Recommended Elliptic Curve Domain Parameters"
 # (http://www.secg.org/)
@@ -313,6 +319,7 @@ pkcs9 20		:			: friendlyName
 pkcs9 21		:			: localKeyID
 !Cname ms-csp-name
 1 3 6 1 4 1 311 17 1	: CSPName		: Microsoft CSP Name
+1 3 6 1 4 1 311 17 2	: LocalKeySet		: Microsoft Local Key set
 !Alias certTypes pkcs9 22
 certTypes 1		:			: x509Certificate
 certTypes 2		:			: sdsiCertificate
@@ -348,7 +355,15 @@ rsadsi 2 2		: MD2			: md2
 rsadsi 2 4		: MD4			: md4
 rsadsi 2 5		: MD5			: md5
 			: MD5-SHA1		: md5-sha1
+rsadsi 2 6		:			: hmacWithMD5
 rsadsi 2 7		:			: hmacWithSHA1
+
+# From RFC4231
+rsadsi 2 8		:			: hmacWithSHA224
+rsadsi 2 9		:			: hmacWithSHA256
+rsadsi 2 10		:			: hmacWithSHA384
+rsadsi 2 11		:			: hmacWithSHA512
+
 rsadsi 3 2		: RC2-CBC		: rc2-cbc
 			: RC2-ECB		: rc2-ecb
 !Cname rc2-cfb64
@@ -542,6 +557,7 @@ id-cmc 24		: id-cmc-confirmCertAcceptance
 
 # other names
 id-on 1			: id-on-personalData
+id-on 3			: id-on-permanentIdentifier : Permanent Identifier
 
 # personal data attributes
 id-pda 1		: id-pda-dateOfBirth
@@ -711,6 +727,8 @@ id-ce 35		: authorityKeyIdentifier : X509v3 Authority Key Identifier
 id-ce 36		: policyConstraints	: X509v3 Policy Constraints
 !Cname ext-key-usage
 id-ce 37		: extendedKeyUsage	: X509v3 Extended Key Usage
+!Cname freshest-crl
+id-ce 46		: freshestCRL		: X509v3 Freshest CRL
 !Cname inhibit-any-policy
 id-ce 54		: inhibitAnyPolicy	: X509v3 Inhibit Any Policy
 !Cname target-information
@@ -833,6 +851,11 @@ nist_hashalgs 2		: SHA384		: sha384
 nist_hashalgs 3		: SHA512		: sha512
 nist_hashalgs 4		: SHA224		: sha224
 
+# OIDs for dsa-with-sha224 and dsa-with-sha256
+!Alias dsa_with_sha2 nistAlgorithms 3
+dsa_with_sha2 1		: dsa_with_SHA224
+dsa_with_sha2 2		: dsa_with_SHA256
+
 # Hold instruction CRL entry extension
 !Cname hold-instruction-code
 id-ce 23		: holdInstructionCode	: Hold Instruction Code
@@ -1070,13 +1093,93 @@ rsadsi 1 1 6		: rsaOAEPEncryptionSET
 			: Oakley-EC2N-3		: ipsec3
 			: Oakley-EC2N-4		: ipsec4
 
+iso 0 10118 3 0 55	: whirlpool
+
+# GOST OIDs
+
+member-body 643 2 2	: cryptopro
+member-body 643 2 9	: cryptocom
+
+cryptopro 3		: id-GostR3411-94-with-GostR3410-2001 : GOST R 34.11-94 with GOST R 34.10-2001
+cryptopro 4		: id-GostR3411-94-with-GostR3410-94 : GOST R 34.11-94 with GOST R 34.10-94
+!Cname id-GostR3411-94
+cryptopro 9		: md_gost94		: GOST R 34.11-94
+cryptopro 10		: id-HMACGostR3411-94	: HMAC GOST 34.11-94
+!Cname id-GostR3410-2001
+cryptopro 19		: gost2001	: GOST R 34.10-2001
+!Cname id-GostR3410-94
+cryptopro 20		: gost94	: GOST R 34.10-94
+!Cname id-Gost28147-89
+cryptopro 21		: gost89 		: GOST 28147-89
+			: gost89-cnt
+!Cname id-Gost28147-89-MAC
+cryptopro 22		: gost-mac	: GOST 28147-89 MAC
+!Cname id-GostR3411-94-prf
+cryptopro 23		: prf-gostr3411-94	: GOST R 34.11-94 PRF
+cryptopro 98		: id-GostR3410-2001DH	: GOST R 34.10-2001 DH
+cryptopro 99		: id-GostR3410-94DH	: GOST R 34.10-94 DH
+
+cryptopro 14 1		: id-Gost28147-89-CryptoPro-KeyMeshing
+cryptopro 14 0		: id-Gost28147-89-None-KeyMeshing
+
+# GOST parameter set OIDs
+
+cryptopro 30 0		: id-GostR3411-94-TestParamSet
+cryptopro 30 1		: id-GostR3411-94-CryptoProParamSet
+
+cryptopro 31 0		: id-Gost28147-89-TestParamSet
+cryptopro 31 1		: id-Gost28147-89-CryptoPro-A-ParamSet
+cryptopro 31 2		: id-Gost28147-89-CryptoPro-B-ParamSet
+cryptopro 31 3		: id-Gost28147-89-CryptoPro-C-ParamSet
+cryptopro 31 4		: id-Gost28147-89-CryptoPro-D-ParamSet
+cryptopro 31 5		: id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet
+cryptopro 31 6		: id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet
+cryptopro 31 7		: id-Gost28147-89-CryptoPro-RIC-1-ParamSet
+
+cryptopro 32 0		: id-GostR3410-94-TestParamSet
+cryptopro 32 2		: id-GostR3410-94-CryptoPro-A-ParamSet
+cryptopro 32 3		: id-GostR3410-94-CryptoPro-B-ParamSet
+cryptopro 32 4		: id-GostR3410-94-CryptoPro-C-ParamSet
+cryptopro 32 5		: id-GostR3410-94-CryptoPro-D-ParamSet
+
+cryptopro 33 1		: id-GostR3410-94-CryptoPro-XchA-ParamSet
+cryptopro 33 2		: id-GostR3410-94-CryptoPro-XchB-ParamSet
+cryptopro 33 3		: id-GostR3410-94-CryptoPro-XchC-ParamSet
+
+cryptopro 35 0		: id-GostR3410-2001-TestParamSet
+cryptopro 35 1		: id-GostR3410-2001-CryptoPro-A-ParamSet
+cryptopro 35 2		: id-GostR3410-2001-CryptoPro-B-ParamSet
+cryptopro 35 3		: id-GostR3410-2001-CryptoPro-C-ParamSet
+
+cryptopro 36 0		: id-GostR3410-2001-CryptoPro-XchA-ParamSet
+cryptopro 36 1		: id-GostR3410-2001-CryptoPro-XchB-ParamSet
+
+id-GostR3410-94 1	: id-GostR3410-94-a
+id-GostR3410-94 2	: id-GostR3410-94-aBis
+id-GostR3410-94 3	: id-GostR3410-94-b
+id-GostR3410-94 4	: id-GostR3410-94-bBis
+
+# Cryptocom LTD GOST OIDs
+
+cryptocom 1 6 1		: id-Gost28147-89-cc	: GOST 28147-89 Cryptocom ParamSet
+!Cname id-GostR3410-94-cc
+cryptocom 1 5 3		: gost94cc	: GOST 34.10-94 Cryptocom
+!Cname id-GostR3410-2001-cc
+cryptocom 1 5 4		: gost2001cc	: GOST 34.10-2001 Cryptocom
+
+cryptocom 1 3 3		: id-GostR3411-94-with-GostR3410-94-cc : GOST R 34.11-94 with GOST R 34.10-94 Cryptocom
+cryptocom 1 3 4		: id-GostR3411-94-with-GostR3410-2001-cc : GOST R 34.11-94 with GOST R 34.10-2001 Cryptocom
+
+cryptocom 1 8 1		: id-GostR3410-2001-ParamSet-cc : GOST R 3410-2001 Parameter Set Cryptocom
 
 # Definitions for Camellia cipher - CBC MODE
+
 1 2 392 200011 61 1 1 1 2 : CAMELLIA-128-CBC		: camellia-128-cbc
 1 2 392 200011 61 1 1 1 3 : CAMELLIA-192-CBC		: camellia-192-cbc
 1 2 392 200011 61 1 1 1 4 : CAMELLIA-256-CBC		: camellia-256-cbc
 
 # Definitions for Camellia cipher - ECB, CFB, OFB MODE
+
 !Alias ntt-ds 0 3 4401 5
 !Alias camellia ntt-ds 3 1 9 
 
@@ -1107,7 +1210,6 @@ camellia 44		: CAMELLIA-256-CFB		: camellia-256-cfb
 			: CAMELLIA-192-CFB8		: camellia-192-cfb8
 			: CAMELLIA-256-CFB8		: camellia-256-cfb8
 
-
 # Definitions for SEED cipher - ECB, CBC, OFB mode
 
 member-body 410 200004  : KISA          : kisa
@@ -1117,3 +1219,7 @@ kisa 1 4                : SEED-CBC      : seed-cbc
 kisa 1 5                : SEED-CFB      : seed-cfb
 !Cname seed-ofb128
 kisa 1 6                : SEED-OFB      : seed-ofb
+
+# There is no OID that just denotes "HMAC" oddly enough...
+
+			: HMAC				: hmac
diff --git a/src/lib/libcrypto/ocsp/ocsp_asn.c b/src/lib/libcrypto/ocsp/ocsp_asn.c
index 39b7a1c568..bfe892ac70 100644
--- a/src/lib/libcrypto/ocsp/ocsp_asn.c
+++ b/src/lib/libcrypto/ocsp/ocsp_asn.c
@@ -1,5 +1,5 @@
 /* ocsp_asn.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2000.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/ocsp/ocsp_ht.c b/src/lib/libcrypto/ocsp/ocsp_ht.c
index a8e569b74a..6abb30b2c0 100644
--- a/src/lib/libcrypto/ocsp/ocsp_ht.c
+++ b/src/lib/libcrypto/ocsp/ocsp_ht.c
@@ -1,5 +1,5 @@
 /* ocsp_ht.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2006.
  */
 /* ====================================================================
@@ -56,11 +56,12 @@
  *
  */
 
-#include <openssl/asn1.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
 #include <string.h>
+#include "e_os.h"
+#include <openssl/asn1.h>
 #include <openssl/ocsp.h>
 #include <openssl/err.h>
 #include <openssl/buffer.h>
diff --git a/src/lib/libcrypto/ocsp/ocsp_srv.c b/src/lib/libcrypto/ocsp/ocsp_srv.c
index fffa134e75..1c606dd0b6 100644
--- a/src/lib/libcrypto/ocsp/ocsp_srv.c
+++ b/src/lib/libcrypto/ocsp/ocsp_srv.c
@@ -1,5 +1,5 @@
 /* ocsp_srv.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2001.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/ocsp/ocsp_vfy.c b/src/lib/libcrypto/ocsp/ocsp_vfy.c
index 23ea41c847..4a0c3870d8 100644
--- a/src/lib/libcrypto/ocsp/ocsp_vfy.c
+++ b/src/lib/libcrypto/ocsp/ocsp_vfy.c
@@ -1,5 +1,5 @@
 /* ocsp_vfy.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2000.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/opensslv.h b/src/lib/libcrypto/opensslv.h
index b308894f18..09687b5136 100644
--- a/src/lib/libcrypto/opensslv.h
+++ b/src/lib/libcrypto/opensslv.h
@@ -25,11 +25,11 @@
  * (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for
  *  major minor fix final patch/beta)
  */
-#define OPENSSL_VERSION_NUMBER	0x0090808fL
+#define OPENSSL_VERSION_NUMBER	0x009080afL
 #ifdef OPENSSL_FIPS
-#define OPENSSL_VERSION_TEXT	"OpenSSL 0.9.8h-fips 28 May 2008"
+#define OPENSSL_VERSION_TEXT	"OpenSSL 0.9.8j-fips 07 Jan 2009"
 #else
-#define OPENSSL_VERSION_TEXT	"OpenSSL 0.9.8h 28 May 2008"
+#define OPENSSL_VERSION_TEXT	"OpenSSL 0.9.8j 07 Jan 2009"
 #endif
 #define OPENSSL_VERSION_PTEXT	" part of " OPENSSL_VERSION_TEXT
 
diff --git a/src/lib/libcrypto/ossl_typ.h b/src/lib/libcrypto/ossl_typ.h
index 345fb1dc4d..0e7a380880 100644
--- a/src/lib/libcrypto/ossl_typ.h
+++ b/src/lib/libcrypto/ossl_typ.h
@@ -100,6 +100,8 @@ typedef int ASN1_NULL;
 #undef X509_EXTENSIONS
 #undef X509_CERT_PAIR
 #undef PKCS7_ISSUER_AND_SERIAL
+#undef OCSP_REQUEST
+#undef OCSP_RESPONSE
 #endif
 
 #ifdef BIGNUM
@@ -140,6 +142,8 @@ typedef struct X509_crl_st X509_CRL;
 typedef struct X509_name_st X509_NAME;
 typedef struct x509_store_st X509_STORE;
 typedef struct x509_store_ctx_st X509_STORE_CTX;
+typedef struct ssl_st SSL;
+typedef struct ssl_ctx_st SSL_CTX;
 
 typedef struct v3_ext_ctx X509V3_CTX;
 typedef struct conf_st CONF;
diff --git a/src/lib/libcrypto/pem/pem.h b/src/lib/libcrypto/pem/pem.h
index 670afa670b..6f8e01544b 100644
--- a/src/lib/libcrypto/pem/pem.h
+++ b/src/lib/libcrypto/pem/pem.h
@@ -125,6 +125,7 @@ extern "C" {
 #define PEM_STRING_DSA		"DSA PRIVATE KEY"
 #define PEM_STRING_DSA_PUBLIC	"DSA PUBLIC KEY"
 #define PEM_STRING_PKCS7	"PKCS7"
+#define PEM_STRING_PKCS7_SIGNED	"PKCS #7 SIGNED DATA"
 #define PEM_STRING_PKCS8	"ENCRYPTED PRIVATE KEY"
 #define PEM_STRING_PKCS8INF	"PRIVATE KEY"
 #define PEM_STRING_DHPARAMS	"DH PARAMETERS"
diff --git a/src/lib/libcrypto/pem/pem_all.c b/src/lib/libcrypto/pem/pem_all.c
index 66cbc7eb82..69dd19bf2e 100644
--- a/src/lib/libcrypto/pem/pem_all.c
+++ b/src/lib/libcrypto/pem/pem_all.c
@@ -194,7 +194,49 @@ RSA *PEM_read_RSAPrivateKey(FILE *fp, RSA **rsa, pem_password_cb *cb,
 
 #endif
 
+#ifdef OPENSSL_FIPS
+
+int PEM_write_bio_RSAPrivateKey(BIO *bp, RSA *x, const EVP_CIPHER *enc,
+                                               unsigned char *kstr, int klen,
+                                               pem_password_cb *cb, void *u)
+{
+	EVP_PKEY *k;
+	int ret;
+	k = EVP_PKEY_new();
+	if (!k)
+		return 0;
+	EVP_PKEY_set1_RSA(k, x);
+
+	ret = PEM_write_bio_PrivateKey(bp, k, enc, kstr, klen, cb, u);
+	EVP_PKEY_free(k);
+	return ret;
+}
+
+#ifndef OPENSSL_NO_FP_API
+int PEM_write_RSAPrivateKey(FILE *fp, RSA *x, const EVP_CIPHER *enc,
+                                               unsigned char *kstr, int klen,
+                                               pem_password_cb *cb, void *u)
+{
+	EVP_PKEY *k;
+	int ret;
+	k = EVP_PKEY_new();
+	if (!k)
+		return 0;
+
+	EVP_PKEY_set1_RSA(k, x);
+
+	ret = PEM_write_PrivateKey(fp, k, enc, kstr, klen, cb, u);
+	EVP_PKEY_free(k);
+	return ret;
+}
+#endif
+
+#else
+
 IMPLEMENT_PEM_write_cb_const(RSAPrivateKey, RSA, PEM_STRING_RSA, RSAPrivateKey)
+
+#endif
+
 IMPLEMENT_PEM_rw_const(RSAPublicKey, RSA, PEM_STRING_RSA_PUBLIC, RSAPublicKey)
 IMPLEMENT_PEM_rw(RSA_PUBKEY, RSA, PEM_STRING_PUBLIC, RSA_PUBKEY)
 
@@ -224,7 +266,47 @@ DSA *PEM_read_bio_DSAPrivateKey(BIO *bp, DSA **dsa, pem_password_cb *cb,
 	return pkey_get_dsa(pktmp, dsa);
 }
 
+#ifdef OPENSSL_FIPS
+
+int PEM_write_bio_DSAPrivateKey(BIO *bp, DSA *x, const EVP_CIPHER *enc,
+                                               unsigned char *kstr, int klen,
+                                               pem_password_cb *cb, void *u)
+{
+	EVP_PKEY *k;
+	int ret;
+	k = EVP_PKEY_new();
+	if (!k)
+		return 0;
+	EVP_PKEY_set1_DSA(k, x);
+
+	ret = PEM_write_bio_PrivateKey(bp, k, enc, kstr, klen, cb, u);
+	EVP_PKEY_free(k);
+	return ret;
+}
+
+#ifndef OPENSSL_NO_FP_API
+int PEM_write_DSAPrivateKey(FILE *fp, DSA *x, const EVP_CIPHER *enc,
+                                               unsigned char *kstr, int klen,
+                                               pem_password_cb *cb, void *u)
+{
+	EVP_PKEY *k;
+	int ret;
+	k = EVP_PKEY_new();
+	if (!k)
+		return 0;
+	EVP_PKEY_set1_DSA(k, x);
+	ret = PEM_write_PrivateKey(fp, k, enc, kstr, klen, cb, u);
+	EVP_PKEY_free(k);
+	return ret;
+}
+#endif
+
+#else
+
 IMPLEMENT_PEM_write_cb_const(DSAPrivateKey, DSA, PEM_STRING_DSA, DSAPrivateKey)
+
+#endif
+
 IMPLEMENT_PEM_rw(DSA_PUBKEY, DSA, PEM_STRING_PUBLIC, DSA_PUBKEY)
 
 #ifndef OPENSSL_NO_FP_API
@@ -270,8 +352,49 @@ EC_KEY *PEM_read_bio_ECPrivateKey(BIO *bp, EC_KEY **key, pem_password_cb *cb,
 
 IMPLEMENT_PEM_rw_const(ECPKParameters, EC_GROUP, PEM_STRING_ECPARAMETERS, ECPKParameters)
 
+
+
+#ifdef OPENSSL_FIPS
+
+int PEM_write_bio_ECPrivateKey(BIO *bp, EC_KEY *x, const EVP_CIPHER *enc,
+                                               unsigned char *kstr, int klen,
+                                               pem_password_cb *cb, void *u)
+{
+	EVP_PKEY *k;
+	int ret;
+	k = EVP_PKEY_new();
+	if (!k)
+		return 0;
+	EVP_PKEY_set1_EC_KEY(k, x);
+
+	ret = PEM_write_bio_PrivateKey(bp, k, enc, kstr, klen, cb, u);
+	EVP_PKEY_free(k);
+	return ret;
+}
+
+#ifndef OPENSSL_NO_FP_API
+int PEM_write_ECPrivateKey(FILE *fp, EC_KEY *x, const EVP_CIPHER *enc,
+                                               unsigned char *kstr, int klen,
+                                               pem_password_cb *cb, void *u)
+{
+	EVP_PKEY *k;
+	int ret;
+	k = EVP_PKEY_new();
+	if (!k)
+		return 0;
+	EVP_PKEY_set1_EC_KEY(k, x);
+	ret = PEM_write_PrivateKey(fp, k, enc, kstr, klen, cb, u);
+	EVP_PKEY_free(k);
+	return ret;
+}
+#endif
+
+#else
+
 IMPLEMENT_PEM_write_cb(ECPrivateKey, EC_KEY, PEM_STRING_ECPRIVATEKEY, ECPrivateKey)
 
+#endif
+
 IMPLEMENT_PEM_rw(EC_PUBKEY, EC_KEY, PEM_STRING_PUBLIC, EC_PUBKEY)
 
 #ifndef OPENSSL_NO_FP_API
@@ -301,8 +424,59 @@ IMPLEMENT_PEM_rw_const(DHparams, DH, PEM_STRING_DHPARAMS, DHparams)
  * (When reading, parameter PEM_STRING_EVP_PKEY is a wildcard for anything
  * appropriate.)
  */
+
+#ifdef OPENSSL_FIPS
+
+static const char *pkey_str(EVP_PKEY *x)
+	{
+	switch (x->type)
+		{
+		case EVP_PKEY_RSA:
+		return PEM_STRING_RSA;
+
+		case EVP_PKEY_DSA:
+		return PEM_STRING_DSA;
+
+		case EVP_PKEY_EC:
+		return PEM_STRING_ECPRIVATEKEY;
+
+		default:
+		return NULL;
+		}
+	}
+
+
+int PEM_write_bio_PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
+                                               unsigned char *kstr, int klen,
+                                               pem_password_cb *cb, void *u)
+	{
+		if (FIPS_mode())
+			return PEM_write_bio_PKCS8PrivateKey(bp, x, enc,
+						(char *)kstr, klen, cb, u);
+		else
+                	return PEM_ASN1_write_bio((i2d_of_void *)i2d_PrivateKey,
+			pkey_str(x), bp,(char *)x,enc,kstr,klen,cb,u);
+	}
+
+#ifndef OPENSSL_NO_FP_API
+int PEM_write_PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
+                                               unsigned char *kstr, int klen,
+                                               pem_password_cb *cb, void *u)
+	{
+		if (FIPS_mode())
+			return PEM_write_PKCS8PrivateKey(fp, x, enc,
+						(char *)kstr, klen, cb, u);
+		else
+                	return PEM_ASN1_write((i2d_of_void *)i2d_PrivateKey,
+			pkey_str(x), fp,(char *)x,enc,kstr,klen,cb,u);
+	}
+#endif
+
+#else
 IMPLEMENT_PEM_write_cb(PrivateKey, EVP_PKEY, ((x->type == EVP_PKEY_DSA)?PEM_STRING_DSA:\
 			(x->type == EVP_PKEY_RSA)?PEM_STRING_RSA:PEM_STRING_ECPRIVATEKEY), PrivateKey)
 
+#endif
+
 IMPLEMENT_PEM_rw(PUBKEY, EVP_PKEY, PEM_STRING_PUBLIC, PUBKEY)
 
diff --git a/src/lib/libcrypto/pem/pem_lib.c b/src/lib/libcrypto/pem/pem_lib.c
index 9bae4c8850..cbafefe416 100644
--- a/src/lib/libcrypto/pem/pem_lib.c
+++ b/src/lib/libcrypto/pem/pem_lib.c
@@ -216,6 +216,9 @@ static int check_pem(const char *nm, const char *name)
 	if(!strcmp(nm, PEM_STRING_X509) &&
 		!strcmp(name, PEM_STRING_PKCS7)) return 1;
 
+	if(!strcmp(nm, PEM_STRING_PKCS7_SIGNED) &&
+		!strcmp(name, PEM_STRING_PKCS7)) return 1;
+
 	return 0;
 }
 
diff --git a/src/lib/libcrypto/pem/pem_x509.c b/src/lib/libcrypto/pem/pem_x509.c
index 19f88d8d3a..3f709f13e6 100644
--- a/src/lib/libcrypto/pem/pem_x509.c
+++ b/src/lib/libcrypto/pem/pem_x509.c
@@ -1,5 +1,5 @@
 /* pem_x509.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2001.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/pem/pem_xaux.c b/src/lib/libcrypto/pem/pem_xaux.c
index 63ce660cf1..7cc7491009 100644
--- a/src/lib/libcrypto/pem/pem_xaux.c
+++ b/src/lib/libcrypto/pem/pem_xaux.c
@@ -1,5 +1,5 @@
 /* pem_xaux.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2001.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/pkcs12/p12_add.c b/src/lib/libcrypto/pkcs12/p12_add.c
index 41bdc00551..1f3e378f5c 100644
--- a/src/lib/libcrypto/pkcs12/p12_add.c
+++ b/src/lib/libcrypto/pkcs12/p12_add.c
@@ -1,5 +1,5 @@
 /* p12_add.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/pkcs12/p12_asn.c b/src/lib/libcrypto/pkcs12/p12_asn.c
index a3739fee1a..6e27633817 100644
--- a/src/lib/libcrypto/pkcs12/p12_asn.c
+++ b/src/lib/libcrypto/pkcs12/p12_asn.c
@@ -1,5 +1,5 @@
 /* p12_asn.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/pkcs12/p12_attr.c b/src/lib/libcrypto/pkcs12/p12_attr.c
index 026cf3826a..68d6c5ad15 100644
--- a/src/lib/libcrypto/pkcs12/p12_attr.c
+++ b/src/lib/libcrypto/pkcs12/p12_attr.c
@@ -1,5 +1,5 @@
 /* p12_attr.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/pkcs12/p12_crpt.c b/src/lib/libcrypto/pkcs12/p12_crpt.c
index 3ad33c49d8..f8b952e27e 100644
--- a/src/lib/libcrypto/pkcs12/p12_crpt.c
+++ b/src/lib/libcrypto/pkcs12/p12_crpt.c
@@ -1,5 +1,5 @@
 /* p12_crpt.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/pkcs12/p12_crt.c b/src/lib/libcrypto/pkcs12/p12_crt.c
index dbafda17b6..e863de52ce 100644
--- a/src/lib/libcrypto/pkcs12/p12_crt.c
+++ b/src/lib/libcrypto/pkcs12/p12_crt.c
@@ -1,5 +1,5 @@
 /* p12_crt.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project.
  */
 /* ====================================================================
@@ -59,10 +59,27 @@
 #include <stdio.h>
 #include "cryptlib.h"
 #include <openssl/pkcs12.h>
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
+
 
 
 static int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags, PKCS12_SAFEBAG *bag);
 
+static int copy_bag_attr(PKCS12_SAFEBAG *bag, EVP_PKEY *pkey, int nid)
+	{
+	int idx;
+	X509_ATTRIBUTE *attr;
+	idx = EVP_PKEY_get_attr_by_NID(pkey, nid, -1);
+	if (idx < 0)
+		return 1;
+	attr = EVP_PKEY_get_attr(pkey, idx);
+	if (!X509at_add1_attr(&bag->attrib, attr))
+		return 0;
+	return 1;
+	}
+
 PKCS12 *PKCS12_create(char *pass, char *name, EVP_PKEY *pkey, X509 *cert,
 	     STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter, int mac_iter,
 	     int keytype)
@@ -77,7 +94,14 @@ PKCS12 *PKCS12_create(char *pass, char *name, EVP_PKEY *pkey, X509 *cert,
 
 	/* Set defaults */
 	if (!nid_cert)
+		{
+#ifdef OPENSSL_FIPS
+		if (FIPS_mode())
+			nid_cert = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
+		else
+#endif
 		nid_cert = NID_pbe_WithSHA1And40BitRC2_CBC;
+		}
 	if (!nid_key)
 		nid_key = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
 	if (!iter)
@@ -122,20 +146,15 @@ PKCS12 *PKCS12_create(char *pass, char *name, EVP_PKEY *pkey, X509 *cert,
 
 	if (pkey)
 		{
-		int cspidx;
 		bag = PKCS12_add_key(&bags, pkey, keytype, iter, nid_key, pass);
 
 		if (!bag)
 			goto err;
 
-		cspidx = EVP_PKEY_get_attr_by_NID(pkey, NID_ms_csp_name, -1);
-		if (cspidx >= 0)
-			{
-			X509_ATTRIBUTE *cspattr;
-			cspattr = EVP_PKEY_get_attr(pkey, cspidx);
-			if (!X509at_add1_attr(&bag->attrib, cspattr))
-				goto err;
-			}
+		if (!copy_bag_attr(bag, pkey, NID_ms_csp_name))
+			goto err;
+		if (!copy_bag_attr(bag, pkey, NID_LocalKeySet))
+			goto err;
 
 		if(name && !PKCS12_add_friendlyname(bag, name, -1))
 			goto err;
diff --git a/src/lib/libcrypto/pkcs12/p12_decr.c b/src/lib/libcrypto/pkcs12/p12_decr.c
index 74c961a92b..ba77dbbe32 100644
--- a/src/lib/libcrypto/pkcs12/p12_decr.c
+++ b/src/lib/libcrypto/pkcs12/p12_decr.c
@@ -1,5 +1,5 @@
 /* p12_decr.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/pkcs12/p12_init.c b/src/lib/libcrypto/pkcs12/p12_init.c
index 6bdc132631..d4d84b056a 100644
--- a/src/lib/libcrypto/pkcs12/p12_init.c
+++ b/src/lib/libcrypto/pkcs12/p12_init.c
@@ -1,5 +1,5 @@
 /* p12_init.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/pkcs12/p12_key.c b/src/lib/libcrypto/pkcs12/p12_key.c
index 18e72d0a1b..9e57eee4a4 100644
--- a/src/lib/libcrypto/pkcs12/p12_key.c
+++ b/src/lib/libcrypto/pkcs12/p12_key.c
@@ -1,5 +1,5 @@
 /* p12_key.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/pkcs12/p12_kiss.c b/src/lib/libcrypto/pkcs12/p12_kiss.c
index c2ee2cc6f3..5c4c6ec988 100644
--- a/src/lib/libcrypto/pkcs12/p12_kiss.c
+++ b/src/lib/libcrypto/pkcs12/p12_kiss.c
@@ -1,5 +1,5 @@
 /* p12_kiss.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/pkcs12/p12_mutl.c b/src/lib/libcrypto/pkcs12/p12_mutl.c
index c408cc8ab8..70bfef6e5d 100644
--- a/src/lib/libcrypto/pkcs12/p12_mutl.c
+++ b/src/lib/libcrypto/pkcs12/p12_mutl.c
@@ -1,5 +1,5 @@
 /* p12_mutl.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/pkcs12/p12_npas.c b/src/lib/libcrypto/pkcs12/p12_npas.c
index 48eacc5c49..47e5e9c377 100644
--- a/src/lib/libcrypto/pkcs12/p12_npas.c
+++ b/src/lib/libcrypto/pkcs12/p12_npas.c
@@ -1,5 +1,5 @@
 /* p12_npas.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/pkcs12/p12_p8d.c b/src/lib/libcrypto/pkcs12/p12_p8d.c
index 3c6f377933..deba81e4a9 100644
--- a/src/lib/libcrypto/pkcs12/p12_p8d.c
+++ b/src/lib/libcrypto/pkcs12/p12_p8d.c
@@ -1,5 +1,5 @@
 /* p12_p8d.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2001.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/pkcs12/p12_p8e.c b/src/lib/libcrypto/pkcs12/p12_p8e.c
index 3d47956652..bf20a77b4c 100644
--- a/src/lib/libcrypto/pkcs12/p12_p8e.c
+++ b/src/lib/libcrypto/pkcs12/p12_p8e.c
@@ -1,5 +1,5 @@
 /* p12_p8e.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2001.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/pkcs12/p12_utl.c b/src/lib/libcrypto/pkcs12/p12_utl.c
index 243ec76be9..ca30ac4f6d 100644
--- a/src/lib/libcrypto/pkcs12/p12_utl.c
+++ b/src/lib/libcrypto/pkcs12/p12_utl.c
@@ -1,5 +1,5 @@
 /* p12_utl.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/pkcs12/pkcs12.h b/src/lib/libcrypto/pkcs12/pkcs12.h
index a2d7e359a0..4bee605dc0 100644
--- a/src/lib/libcrypto/pkcs12/pkcs12.h
+++ b/src/lib/libcrypto/pkcs12/pkcs12.h
@@ -1,5 +1,5 @@
 /* pkcs12.h */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/pkcs7/pk7_asn1.c b/src/lib/libcrypto/pkcs7/pk7_asn1.c
index 77931feeb4..1f70d31386 100644
--- a/src/lib/libcrypto/pkcs7/pk7_asn1.c
+++ b/src/lib/libcrypto/pkcs7/pk7_asn1.c
@@ -1,5 +1,5 @@
 /* pk7_asn.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2000.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/pkcs7/pk7_attr.c b/src/lib/libcrypto/pkcs7/pk7_attr.c
index 735c8800e1..d549717169 100644
--- a/src/lib/libcrypto/pkcs7/pk7_attr.c
+++ b/src/lib/libcrypto/pkcs7/pk7_attr.c
@@ -1,5 +1,5 @@
 /* pk7_attr.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2001.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/pkcs7/pk7_mime.c b/src/lib/libcrypto/pkcs7/pk7_mime.c
index 17b68992f7..bf190360d7 100644
--- a/src/lib/libcrypto/pkcs7/pk7_mime.c
+++ b/src/lib/libcrypto/pkcs7/pk7_mime.c
@@ -1,5 +1,5 @@
 /* pk7_mime.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/pkcs7/pk7_smime.c b/src/lib/libcrypto/pkcs7/pk7_smime.c
index 5c6b0fe24b..c34db1d6fe 100644
--- a/src/lib/libcrypto/pkcs7/pk7_smime.c
+++ b/src/lib/libcrypto/pkcs7/pk7_smime.c
@@ -1,5 +1,5 @@
 /* pk7_smime.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project.
  */
 /* ====================================================================
@@ -282,6 +282,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
 			PKCS7err(PKCS7_F_PKCS7_VERIFY,ERR_R_MALLOC_FAILURE);
 			goto err;
 		}
+		BIO_set_mem_eof_return(tmpout, 0);
 	} else tmpout = out;
 
 	/* We now have to 'read' from p7bio to calculate digests etc. */
diff --git a/src/lib/libcrypto/rand/rand.h b/src/lib/libcrypto/rand/rand.h
index ac6c021763..ea89153cba 100644
--- a/src/lib/libcrypto/rand/rand.h
+++ b/src/lib/libcrypto/rand/rand.h
@@ -72,7 +72,7 @@ extern "C" {
 #endif
 
 #if defined(OPENSSL_FIPS)
-#define FIPS_RAND_SIZE_T size_t
+#define FIPS_RAND_SIZE_T int
 #endif
 
 /* Already defined in ossl_typ.h */
@@ -111,6 +111,15 @@ int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes);
 int RAND_egd(const char *path);
 int RAND_egd_bytes(const char *path,int bytes);
 int RAND_poll(void);
+#ifndef OPENSSL_NO_ENGINE
+#ifdef OPENSSL_FIPS
+void int_RAND_init_engine_callbacks(void);
+void int_RAND_set_callbacks(
+	int (*set_rand_func)(const RAND_METHOD *meth,
+						const RAND_METHOD **pmeth),
+	const RAND_METHOD *(*get_rand_func)(const RAND_METHOD **pmeth));
+#endif
+#endif
 
 #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
 
@@ -128,11 +137,29 @@ void ERR_load_RAND_strings(void);
 /* Error codes for the RAND functions. */
 
 /* Function codes. */
+#define RAND_F_ENG_RAND_GET_RAND_METHOD			 108
+#define RAND_F_FIPS_RAND				 103
+#define RAND_F_FIPS_RAND_BYTES				 102
+#define RAND_F_FIPS_RAND_GET_RAND_METHOD		 109
+#define RAND_F_FIPS_RAND_SET_DT				 106
+#define RAND_F_FIPS_SET_DT				 104
+#define RAND_F_FIPS_SET_PRNG_SEED			 107
+#define RAND_F_FIPS_SET_TEST_MODE			 105
 #define RAND_F_RAND_GET_RAND_METHOD			 101
 #define RAND_F_SSLEAY_RAND_BYTES			 100
 
 /* Reason codes. */
+#define RAND_R_NON_FIPS_METHOD				 105
+#define RAND_R_NOT_IN_TEST_MODE				 106
+#define RAND_R_NO_KEY_SET				 107
+#define RAND_R_PRNG_ASKING_FOR_TOO_MUCH			 101
+#define RAND_R_PRNG_ERROR				 108
+#define RAND_R_PRNG_KEYED				 109
+#define RAND_R_PRNG_NOT_REKEYED				 102
+#define RAND_R_PRNG_NOT_RESEEDED			 103
 #define RAND_R_PRNG_NOT_SEEDED				 100
+#define RAND_R_PRNG_SEED_MUST_NOT_MATCH_KEY		 110
+#define RAND_R_PRNG_STUCK				 104
 
 #ifdef  __cplusplus
 }
diff --git a/src/lib/libcrypto/rand/rand_err.c b/src/lib/libcrypto/rand/rand_err.c
index 386934dcd1..829fb44d77 100644
--- a/src/lib/libcrypto/rand/rand_err.c
+++ b/src/lib/libcrypto/rand/rand_err.c
@@ -1,6 +1,6 @@
 /* crypto/rand/rand_err.c */
 /* ====================================================================
- * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-2007 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -70,6 +70,14 @@
 
 static ERR_STRING_DATA RAND_str_functs[]=
 	{
+{ERR_FUNC(RAND_F_ENG_RAND_GET_RAND_METHOD),	"ENG_RAND_GET_RAND_METHOD"},
+{ERR_FUNC(RAND_F_FIPS_RAND),	"FIPS_RAND"},
+{ERR_FUNC(RAND_F_FIPS_RAND_BYTES),	"FIPS_RAND_BYTES"},
+{ERR_FUNC(RAND_F_FIPS_RAND_GET_RAND_METHOD),	"FIPS_RAND_GET_RAND_METHOD"},
+{ERR_FUNC(RAND_F_FIPS_RAND_SET_DT),	"FIPS_RAND_SET_DT"},
+{ERR_FUNC(RAND_F_FIPS_SET_DT),	"FIPS_SET_DT"},
+{ERR_FUNC(RAND_F_FIPS_SET_PRNG_SEED),	"FIPS_SET_PRNG_SEED"},
+{ERR_FUNC(RAND_F_FIPS_SET_TEST_MODE),	"FIPS_SET_TEST_MODE"},
 {ERR_FUNC(RAND_F_RAND_GET_RAND_METHOD),	"RAND_get_rand_method"},
 {ERR_FUNC(RAND_F_SSLEAY_RAND_BYTES),	"SSLEAY_RAND_BYTES"},
 {0,NULL}
@@ -77,7 +85,17 @@ static ERR_STRING_DATA RAND_str_functs[]=
 
 static ERR_STRING_DATA RAND_str_reasons[]=
 	{
+{ERR_REASON(RAND_R_NON_FIPS_METHOD)      ,"non fips method"},
+{ERR_REASON(RAND_R_NOT_IN_TEST_MODE)     ,"not in test mode"},
+{ERR_REASON(RAND_R_NO_KEY_SET)           ,"no key set"},
+{ERR_REASON(RAND_R_PRNG_ASKING_FOR_TOO_MUCH),"prng asking for too much"},
+{ERR_REASON(RAND_R_PRNG_ERROR)           ,"prng error"},
+{ERR_REASON(RAND_R_PRNG_KEYED)           ,"prng keyed"},
+{ERR_REASON(RAND_R_PRNG_NOT_REKEYED)     ,"prng not rekeyed"},
+{ERR_REASON(RAND_R_PRNG_NOT_RESEEDED)    ,"prng not reseeded"},
 {ERR_REASON(RAND_R_PRNG_NOT_SEEDED)      ,"PRNG not seeded"},
+{ERR_REASON(RAND_R_PRNG_SEED_MUST_NOT_MATCH_KEY),"prng seed must not match key"},
+{ERR_REASON(RAND_R_PRNG_STUCK)           ,"prng stuck"},
 {0,NULL}
 	};
 
diff --git a/src/lib/libcrypto/rand/rand_lib.c b/src/lib/libcrypto/rand/rand_lib.c
index 513e338985..da6b4e0e86 100644
--- a/src/lib/libcrypto/rand/rand_lib.c
+++ b/src/lib/libcrypto/rand/rand_lib.c
@@ -60,15 +60,82 @@
 #include <time.h>
 #include "cryptlib.h"
 #include <openssl/rand.h>
+#include "rand_lcl.h"
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#include <openssl/fips_rand.h>
+#endif
+
 #ifndef OPENSSL_NO_ENGINE
 #include <openssl/engine.h>
 #endif
 
+static const RAND_METHOD *default_RAND_meth = NULL;
+
+#ifdef OPENSSL_FIPS
+
+static int fips_RAND_set_rand_method(const RAND_METHOD *meth,
+					const RAND_METHOD **pmeth)
+	{
+	*pmeth = meth;
+	return 1;
+	}
+
+static const RAND_METHOD *fips_RAND_get_rand_method(const RAND_METHOD **pmeth)
+	{
+	if (!*pmeth)
+		{
+		if(FIPS_mode())
+			*pmeth=FIPS_rand_method();
+		else
+			*pmeth = RAND_SSLeay();
+		}
+
+	if(FIPS_mode()
+		&& *pmeth != FIPS_rand_check())
+	    {
+	    RANDerr(RAND_F_FIPS_RAND_GET_RAND_METHOD,RAND_R_NON_FIPS_METHOD);
+	    return 0;
+	    }
+
+	return *pmeth;
+	}
+
+static int (*RAND_set_rand_method_func)(const RAND_METHOD *meth,
+						const RAND_METHOD **pmeth)
+	= fips_RAND_set_rand_method;
+static const RAND_METHOD *(*RAND_get_rand_method_func)
+						(const RAND_METHOD **pmeth)
+	= fips_RAND_get_rand_method;
+
+#ifndef OPENSSL_NO_ENGINE
+void int_RAND_set_callbacks(
+	int (*set_rand_func)(const RAND_METHOD *meth,
+						const RAND_METHOD **pmeth),
+	const RAND_METHOD *(*get_rand_func)
+						(const RAND_METHOD **pmeth))
+	{
+	RAND_set_rand_method_func = set_rand_func;
+	RAND_get_rand_method_func = get_rand_func;
+	}
+#endif
+
+int RAND_set_rand_method(const RAND_METHOD *meth)
+	{
+	return RAND_set_rand_method_func(meth, &default_RAND_meth);
+	}
+
+const RAND_METHOD *RAND_get_rand_method(void)
+	{
+	return RAND_get_rand_method_func(&default_RAND_meth);
+	}
+
+#else
+
 #ifndef OPENSSL_NO_ENGINE
 /* non-NULL if default_RAND_meth is ENGINE-provided */
 static ENGINE *funct_ref =NULL;
 #endif
-static const RAND_METHOD *default_RAND_meth = NULL;
 
 int RAND_set_rand_method(const RAND_METHOD *meth)
 	{
@@ -129,6 +196,8 @@ int RAND_set_rand_engine(ENGINE *engine)
 	}
 #endif
 
+#endif
+
 void RAND_cleanup(void)
 	{
 	const RAND_METHOD *meth = RAND_get_rand_method();
diff --git a/src/lib/libcrypto/rand/randfile.c b/src/lib/libcrypto/rand/randfile.c
index 6c0ec9a41c..d108353bbc 100644
--- a/src/lib/libcrypto/rand/randfile.c
+++ b/src/lib/libcrypto/rand/randfile.c
@@ -81,10 +81,25 @@
 # include <sys/stat.h>
 #endif
 
+#ifdef _WIN32
+#define stat	_stat
+#define chmod	_chmod
+#define open	_open
+#define fdopen	_fdopen
+#endif
+
 #undef BUFSIZE
 #define BUFSIZE	1024
 #define RAND_DATA 1024
 
+#ifdef OPENSSL_SYS_VMS
+/* This declaration is a nasty hack to get around vms' extension to fopen
+ * for passing in sharing options being disabled by our /STANDARD=ANSI89 */
+static FILE *(*const vms_fopen)(const char *, const char *, ...) =
+    (FILE *(*)(const char *, const char *, ...))fopen;
+#define VMS_OPEN_ATTRS "shr=get,put,upd,del","ctx=bin,stm","rfm=stm","rat=none","mrs=0"
+#endif
+
 /* #define RFILE ".rnd" - defined in ../../e_os.h */
 
 /* Note that these functions are intended for seed files only.
@@ -106,7 +121,11 @@ int RAND_load_file(const char *file, long bytes)
 	RAND_add(&sb,sizeof(sb),0.0);
 	if (bytes == 0) return(ret);
 
+#ifdef OPENSSL_SYS_VMS
+	in=vms_fopen(file,"rb",VMS_OPEN_ATTRS);
+#else
 	in=fopen(file,"rb");
+#endif
 	if (in == NULL) goto err;
 #if defined(S_IFBLK) && defined(S_IFCHR)
 	if (sb.st_mode & (S_IFBLK | S_IFCHR)) {
@@ -167,7 +186,7 @@ int RAND_write_file(const char *file)
 #endif
 	}
 
-#if defined(O_CREAT) && !defined(OPENSSL_SYS_WIN32)
+#if defined(O_CREAT) && !defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_SYS_VMS)
 	{
 	/* For some reason Win32 can't write to files created this way */
 	
@@ -178,8 +197,34 @@ int RAND_write_file(const char *file)
 		out = fdopen(fd, "wb");
 	}
 #endif
+
+#ifdef OPENSSL_SYS_VMS
+	/* VMS NOTE: Prior versions of this routine created a _new_
+	 * version of the rand file for each call into this routine, then
+	 * deleted all existing versions named ;-1, and finally renamed
+	 * the current version as ';1'. Under concurrent usage, this
+	 * resulted in an RMS race condition in rename() which could
+	 * orphan files (see vms message help for RMS$_REENT). With the
+	 * fopen() calls below, openssl/VMS now shares the top-level
+	 * version of the rand file. Note that there may still be
+	 * conditions where the top-level rand file is locked. If so, this
+	 * code will then create a new version of the rand file. Without
+	 * the delete and rename code, this can result in ascending file
+	 * versions that stop at version 32767, and this routine will then
+	 * return an error. The remedy for this is to recode the calling
+	 * application to avoid concurrent use of the rand file, or
+	 * synchronize usage at the application level. Also consider
+	 * whether or not you NEED a persistent rand file in a concurrent
+	 * use situation. 
+	 */
+
+	out = vms_fopen(file,"rb+",VMS_OPEN_ATTRS);
+	if (out == NULL)
+		out = vms_fopen(file,"wb",VMS_OPEN_ATTRS);
+#else
 	if (out == NULL)
 		out = fopen(file,"wb");
+#endif
 	if (out == NULL) goto err;
 
 #ifndef NO_CHMOD
@@ -201,25 +246,6 @@ int RAND_write_file(const char *file)
 		ret+=i;
 		if (n <= 0) break;
                 }
-#ifdef OPENSSL_SYS_VMS
-	/* Try to delete older versions of the file, until there aren't
-	   any */
-	{
-	char *tmpf;
-
-	tmpf = OPENSSL_malloc(strlen(file) + 4);  /* to add ";-1" and a nul */
-	if (tmpf)
-		{
-		strcpy(tmpf, file);
-		strcat(tmpf, ";-1");
-		while(delete(tmpf) == 0)
-			;
-		rename(file,";1"); /* Make sure it's version 1, or we
-				      will reach the limit (32767) at
-				      some point... */
-		}
-	}
-#endif /* OPENSSL_SYS_VMS */
 
 	fclose(out);
 	OPENSSL_cleanse(buf,BUFSIZE);
diff --git a/src/lib/libcrypto/rc2/rc2.h b/src/lib/libcrypto/rc2/rc2.h
index 34c8362317..e542ec94ff 100644
--- a/src/lib/libcrypto/rc2/rc2.h
+++ b/src/lib/libcrypto/rc2/rc2.h
@@ -79,7 +79,9 @@ typedef struct rc2_key_st
 	RC2_INT data[64];
 	} RC2_KEY;
 
- 
+#ifdef OPENSSL_FIPS 
+void private_RC2_set_key(RC2_KEY *key, int len, const unsigned char *data,int bits);
+#endif
 void RC2_set_key(RC2_KEY *key, int len, const unsigned char *data,int bits);
 void RC2_ecb_encrypt(const unsigned char *in,unsigned char *out,RC2_KEY *key,
 		     int enc);
diff --git a/src/lib/libcrypto/rc2/rc2_skey.c b/src/lib/libcrypto/rc2/rc2_skey.c
index 4953642056..4e000e5b99 100644
--- a/src/lib/libcrypto/rc2/rc2_skey.c
+++ b/src/lib/libcrypto/rc2/rc2_skey.c
@@ -57,6 +57,11 @@
  */
 
 #include <openssl/rc2.h>
+#include <openssl/crypto.h>
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
+
 #include "rc2_locl.h"
 
 static unsigned char key_table[256]={
@@ -94,7 +99,19 @@ static unsigned char key_table[256]={
  * BSAFE uses the 'retarded' version.  What I previously shipped is
  * the same as specifying 1024 for the 'bits' parameter.  Bsafe uses
  * a version where the bits parameter is the same as len*8 */
+
+#ifdef OPENSSL_FIPS
 void RC2_set_key(RC2_KEY *key, int len, const unsigned char *data, int bits)
+	{
+	if (FIPS_mode())
+		FIPS_BAD_ABORT(RC2)
+	private_RC2_set_key(key, len, data, bits);
+	}
+void private_RC2_set_key(RC2_KEY *key, int len, const unsigned char *data,
+								int bits)
+#else
+void RC2_set_key(RC2_KEY *key, int len, const unsigned char *data, int bits)
+#endif
 	{
 	int i,j;
 	unsigned char *k;
diff --git a/src/lib/libcrypto/rc4/asm/rc4-x86_64.pl b/src/lib/libcrypto/rc4/asm/rc4-x86_64.pl
index 2d47320485..00c6fa28aa 100755
--- a/src/lib/libcrypto/rc4/asm/rc4-x86_64.pl
+++ b/src/lib/libcrypto/rc4/asm/rc4-x86_64.pl
@@ -359,6 +359,8 @@ ___
 
 $code =~ s/#([bwd])/$1/gm;
 
+$code =~ s/RC4_set_key/private_RC4_set_key/g if ($ENV{FIPSCANLIB} ne "");
+
 print $code;
 
 close STDOUT;
diff --git a/src/lib/libcrypto/rc4/rc4.h b/src/lib/libcrypto/rc4/rc4.h
index 7aec04fe93..2d8620d33b 100644
--- a/src/lib/libcrypto/rc4/rc4.h
+++ b/src/lib/libcrypto/rc4/rc4.h
@@ -76,6 +76,9 @@ typedef struct rc4_key_st
 
  
 const char *RC4_options(void);
+#ifdef OPENSSL_FIPS
+void private_RC4_set_key(RC4_KEY *key, int len, const unsigned char *data);
+#endif
 void RC4_set_key(RC4_KEY *key, int len, const unsigned char *data);
 void RC4(RC4_KEY *key, unsigned long len, const unsigned char *indata,
 		unsigned char *outdata);
diff --git a/src/lib/libcrypto/rc4/rc4_skey.c b/src/lib/libcrypto/rc4/rc4_skey.c
index 46b77ec321..4478d1a4b3 100644
--- a/src/lib/libcrypto/rc4/rc4_skey.c
+++ b/src/lib/libcrypto/rc4/rc4_skey.c
@@ -59,6 +59,11 @@
 #include <openssl/rc4.h>
 #include "rc4_locl.h"
 #include <openssl/opensslv.h>
+#include <openssl/crypto.h>
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
+
 
 const char RC4_version[]="RC4" OPENSSL_VERSION_PTEXT;
 
@@ -85,7 +90,11 @@ const char *RC4_options(void)
  * Date: Wed, 14 Sep 1994 06:35:31 GMT
  */
 
+#ifdef OPENSSL_FIPS
+void private_RC4_set_key(RC4_KEY *key, int len, const unsigned char *data)
+#else
 void RC4_set_key(RC4_KEY *key, int len, const unsigned char *data)
+#endif
 	{
         register RC4_INT tmp;
         register int id1,id2;
@@ -127,7 +136,12 @@ void RC4_set_key(RC4_KEY *key, int len, const unsigned char *data)
 		 *
 		 *				<appro@fy.chalmers.se>
 		 */
-		if (OPENSSL_ia32cap_P & (1<<20)) {
+#ifdef OPENSSL_FIPS
+		unsigned long *ia32cap_ptr = OPENSSL_ia32cap_loc();
+		if (ia32cap_ptr && (*ia32cap_ptr & (1<<28))) {
+#else
+		if (OPENSSL_ia32cap_P & (1<<28)) {
+#endif
 			unsigned char *cp=(unsigned char *)d;
 
 			for (i=0;i<256;i++) cp[i]=i;
diff --git a/src/lib/libcrypto/ripemd/ripemd.h b/src/lib/libcrypto/ripemd/ripemd.h
index 033a5965b5..3b6d04386d 100644
--- a/src/lib/libcrypto/ripemd/ripemd.h
+++ b/src/lib/libcrypto/ripemd/ripemd.h
@@ -90,7 +90,9 @@ typedef struct RIPEMD160state_st
 	RIPEMD160_LONG data[RIPEMD160_LBLOCK];
 	unsigned int   num;
 	} RIPEMD160_CTX;
-
+#ifdef OPENSSL_FIPS
+int private_RIPEMD160_Init(RIPEMD160_CTX *c);
+#endif
 int RIPEMD160_Init(RIPEMD160_CTX *c);
 int RIPEMD160_Update(RIPEMD160_CTX *c, const void *data, size_t len);
 int RIPEMD160_Final(unsigned char *md, RIPEMD160_CTX *c);
diff --git a/src/lib/libcrypto/ripemd/rmd_dgst.c b/src/lib/libcrypto/ripemd/rmd_dgst.c
index 61626284b8..ead11d075a 100644
--- a/src/lib/libcrypto/ripemd/rmd_dgst.c
+++ b/src/lib/libcrypto/ripemd/rmd_dgst.c
@@ -59,6 +59,11 @@
 #include <stdio.h>
 #include "rmd_locl.h"
 #include <openssl/opensslv.h>
+#include <openssl/err.h>
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
+
 
 const char RMD160_version[]="RIPE-MD160" OPENSSL_VERSION_PTEXT;
 
@@ -69,7 +74,7 @@ const char RMD160_version[]="RIPE-MD160" OPENSSL_VERSION_PTEXT;
      void ripemd160_block(RIPEMD160_CTX *c, unsigned long *p,size_t num);
 #  endif
 
-int RIPEMD160_Init(RIPEMD160_CTX *c)
+FIPS_NON_FIPS_MD_Init(RIPEMD160)
 	{
 	c->A=RIPEMD160_A;
 	c->B=RIPEMD160_B;
diff --git a/src/lib/libcrypto/ripemd/rmd_locl.h b/src/lib/libcrypto/ripemd/rmd_locl.h
index f14b346e66..ce12a8000e 100644
--- a/src/lib/libcrypto/ripemd/rmd_locl.h
+++ b/src/lib/libcrypto/ripemd/rmd_locl.h
@@ -72,7 +72,7 @@
  */
 #ifdef RMD160_ASM
 # if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__INTEL__)
-#  define ripemd160_block_data_order ripemd160_block_asm_data_order
+#  define ripemd160_block_host_order ripemd160_block_asm_data_order
 # endif
 #endif
 
diff --git a/src/lib/libcrypto/rsa/rsa.h b/src/lib/libcrypto/rsa/rsa.h
index 6b5e4f8a9a..5bb932ae15 100644
--- a/src/lib/libcrypto/rsa/rsa.h
+++ b/src/lib/libcrypto/rsa/rsa.h
@@ -74,6 +74,25 @@
 #error RSA is disabled.
 #endif
 
+/* If this flag is set the RSA method is FIPS compliant and can be used
+ * in FIPS mode. This is set in the validated module method. If an
+ * application sets this flag in its own methods it is its reposibility
+ * to ensure the result is compliant.
+ */
+
+#define RSA_FLAG_FIPS_METHOD			0x0400
+
+/* If this flag is set the operations normally disabled in FIPS mode are
+ * permitted it is then the applications responsibility to ensure that the
+ * usage is compliant.
+ */
+
+#define RSA_FLAG_NON_FIPS_ALLOW			0x0400
+
+#ifdef OPENSSL_FIPS
+#define FIPS_RSA_SIZE_T	int
+#endif
+
 #ifdef  __cplusplus
 extern "C" {
 #endif
@@ -163,6 +182,8 @@ struct rsa_st
 # define OPENSSL_RSA_MAX_MODULUS_BITS	16384
 #endif
 
+#define OPENSSL_RSA_FIPS_MIN_MODULUS_BITS 1024
+
 #ifndef OPENSSL_RSA_SMALL_MODULUS_BITS
 # define OPENSSL_RSA_SMALL_MODULUS_BITS	3072
 #endif
@@ -240,6 +261,11 @@ RSA *	RSA_generate_key(int bits, unsigned long e,void
 
 /* New version */
 int	RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
+int RSA_X931_derive_ex(RSA *rsa, BIGNUM *p1, BIGNUM *p2, BIGNUM *q1, BIGNUM *q2,
+			const BIGNUM *Xp1, const BIGNUM *Xp2, const BIGNUM *Xp,
+			const BIGNUM *Xq1, const BIGNUM *Xq2, const BIGNUM *Xq,
+			const BIGNUM *e, BN_GENCB *cb);
+int RSA_X931_generate_key_ex(RSA *rsa, int bits, const BIGNUM *e, BN_GENCB *cb);
 
 int	RSA_check_key(const RSA *);
 	/* next 4 return -1 on error */
@@ -257,6 +283,11 @@ int	RSA_up_ref(RSA *r);
 
 int	RSA_flags(const RSA *r);
 
+#ifdef OPENSSL_FIPS
+RSA *FIPS_rsa_new(void);
+void FIPS_rsa_free(RSA *r);
+#endif
+
 void RSA_set_default_method(const RSA_METHOD *meth);
 const RSA_METHOD *RSA_get_default_method(void);
 const RSA_METHOD *RSA_get_method(const RSA *rsa);
@@ -281,6 +312,7 @@ int	RSA_print_fp(FILE *fp, const RSA *r,int offset);
 int	RSA_print(BIO *bp, const RSA *r,int offset);
 #endif
 
+#ifndef OPENSSL_NO_RC4
 int i2d_RSA_NET(const RSA *a, unsigned char **pp,
 		int (*cb)(char *buf, int len, const char *prompt, int verify),
 		int sgckey);
@@ -294,6 +326,7 @@ int i2d_Netscape_RSA(const RSA *a, unsigned char **pp,
 RSA *d2i_Netscape_RSA(RSA **a, const unsigned char **pp, long length,
 		      int (*cb)(char *buf, int len, const char *prompt,
 				int verify));
+#endif
 
 /* The following 2 functions sign and verify a X509_SIG ASN1 object
  * inside PKCS#1 padded RSA encryption */
@@ -368,6 +401,8 @@ void ERR_load_RSA_strings(void);
 /* Error codes for the RSA functions. */
 
 /* Function codes. */
+#define RSA_F_FIPS_RSA_SIGN				 140
+#define RSA_F_FIPS_RSA_VERIFY				 141
 #define RSA_F_MEMORY_LOCK				 100
 #define RSA_F_RSA_BUILTIN_KEYGEN			 129
 #define RSA_F_RSA_CHECK_KEY				 123
@@ -399,7 +434,11 @@ void ERR_load_RSA_strings(void);
 #define RSA_F_RSA_PADDING_CHECK_X931			 128
 #define RSA_F_RSA_PRINT					 115
 #define RSA_F_RSA_PRINT_FP				 116
+#define RSA_F_RSA_PRIVATE_ENCRYPT			 137
+#define RSA_F_RSA_PUBLIC_DECRYPT			 138
 #define RSA_F_RSA_SETUP_BLINDING			 136
+#define RSA_F_RSA_SET_DEFAULT_METHOD			 139
+#define RSA_F_RSA_SET_METHOD				 142
 #define RSA_F_RSA_SIGN					 117
 #define RSA_F_RSA_SIGN_ASN1_OCTET_STRING		 118
 #define RSA_F_RSA_VERIFY				 119
@@ -433,10 +472,12 @@ void ERR_load_RSA_strings(void);
 #define RSA_R_KEY_SIZE_TOO_SMALL			 120
 #define RSA_R_LAST_OCTET_INVALID			 134
 #define RSA_R_MODULUS_TOO_LARGE				 105
+#define RSA_R_NON_FIPS_METHOD				 141
 #define RSA_R_NO_PUBLIC_EXPONENT			 140
 #define RSA_R_NULL_BEFORE_BLOCK_MISSING			 113
 #define RSA_R_N_DOES_NOT_EQUAL_P_Q			 127
 #define RSA_R_OAEP_DECODING_ERROR			 121
+#define RSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE	 142
 #define RSA_R_PADDING_CHECK_FAILED			 114
 #define RSA_R_P_NOT_PRIME				 128
 #define RSA_R_Q_NOT_PRIME				 129
diff --git a/src/lib/libcrypto/rsa/rsa_asn1.c b/src/lib/libcrypto/rsa/rsa_asn1.c
index bbbf26d50e..6e8a803e81 100644
--- a/src/lib/libcrypto/rsa/rsa_asn1.c
+++ b/src/lib/libcrypto/rsa/rsa_asn1.c
@@ -1,5 +1,5 @@
 /* rsa_asn1.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2000.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/rsa/rsa_eay.c b/src/lib/libcrypto/rsa/rsa_eay.c
index ffadaab9a4..0ac6418449 100644
--- a/src/lib/libcrypto/rsa/rsa_eay.c
+++ b/src/lib/libcrypto/rsa/rsa_eay.c
@@ -115,7 +115,7 @@
 #include <openssl/rsa.h>
 #include <openssl/rand.h>
 
-#ifndef RSA_NULL
+#if !defined(RSA_NULL) && !defined(OPENSSL_FIPS)
 
 static int RSA_eay_public_encrypt(int flen, const unsigned char *from,
 		unsigned char *to, RSA *rsa,int padding);
@@ -150,16 +150,6 @@ const RSA_METHOD *RSA_PKCS1_SSLeay(void)
 	return(&rsa_pkcs1_eay_meth);
 	}
 
-/* Usage example;
- *    MONT_HELPER(rsa->_method_mod_p, bn_ctx, rsa->p, rsa->flags & RSA_FLAG_CACHE_PRIVATE, goto err);
- */
-#define MONT_HELPER(method_mod, ctx, m, pre_cond, err_instr) \
-	if ((pre_cond) && ((method_mod) == NULL) && \
-			!BN_MONT_CTX_set_locked(&(method_mod), \
-				CRYPTO_LOCK_RSA, \
-				(m), (ctx))) \
-		err_instr
-
 static int RSA_eay_public_encrypt(int flen, const unsigned char *from,
 	     unsigned char *to, RSA *rsa, int padding)
 	{
@@ -233,7 +223,9 @@ static int RSA_eay_public_encrypt(int flen, const unsigned char *from,
 		goto err;
 		}
 
-	MONT_HELPER(rsa->_method_mod_n, ctx, rsa->n, rsa->flags & RSA_FLAG_CACHE_PUBLIC, goto err);
+	if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
+		if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n, ctx))
+			goto err;
 
 	if (!rsa->meth->bn_mod_exp(ret,f,rsa->e,rsa->n,ctx,
 		rsa->_method_mod_n)) goto err;
@@ -438,7 +430,9 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
 		else
 			d= rsa->d;
 
-		MONT_HELPER(rsa->_method_mod_n, ctx, rsa->n, rsa->flags & RSA_FLAG_CACHE_PUBLIC, goto err);
+		if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
+			if(!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n, ctx))
+				goto err;
 
 		if (!rsa->meth->bn_mod_exp(ret,f,d,rsa->n,ctx,
 				rsa->_method_mod_n)) goto err;
@@ -559,7 +553,9 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
 		else
 			d = rsa->d;
 
-		MONT_HELPER(rsa->_method_mod_n, ctx, rsa->n, rsa->flags & RSA_FLAG_CACHE_PUBLIC, goto err);
+		if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
+			if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n, ctx))
+				goto err;
 		if (!rsa->meth->bn_mod_exp(ret,f,d,rsa->n,ctx,
 				rsa->_method_mod_n))
 		  goto err;
@@ -669,7 +665,9 @@ static int RSA_eay_public_decrypt(int flen, const unsigned char *from,
 		goto err;
 		}
 
-	MONT_HELPER(rsa->_method_mod_n, ctx, rsa->n, rsa->flags & RSA_FLAG_CACHE_PUBLIC, goto err);
+	if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
+		if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n, ctx))
+			goto err;
 
 	if (!rsa->meth->bn_mod_exp(ret,f,rsa->e,rsa->n,ctx,
 		rsa->_method_mod_n)) goto err;
@@ -747,11 +745,18 @@ static int RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
 			q = rsa->q;
 			}
 
-		MONT_HELPER(rsa->_method_mod_p, ctx, p, rsa->flags & RSA_FLAG_CACHE_PRIVATE, goto err);
-		MONT_HELPER(rsa->_method_mod_q, ctx, q, rsa->flags & RSA_FLAG_CACHE_PRIVATE, goto err);
+		if (rsa->flags & RSA_FLAG_CACHE_PRIVATE)
+			{
+			if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_p, CRYPTO_LOCK_RSA, p, ctx))
+				goto err;
+			if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_q, CRYPTO_LOCK_RSA, q, ctx))
+				goto err;
+			}
 	}
 
-	MONT_HELPER(rsa->_method_mod_n, ctx, rsa->n, rsa->flags & RSA_FLAG_CACHE_PUBLIC, goto err);
+	if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
+		if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n, ctx))
+			goto err;
 
 	/* compute I mod q */
 	if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
diff --git a/src/lib/libcrypto/rsa/rsa_err.c b/src/lib/libcrypto/rsa/rsa_err.c
index fe3ba1b44b..501f5ea389 100644
--- a/src/lib/libcrypto/rsa/rsa_err.c
+++ b/src/lib/libcrypto/rsa/rsa_err.c
@@ -1,6 +1,6 @@
 /* crypto/rsa/rsa_err.c */
 /* ====================================================================
- * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-2007 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -70,6 +70,8 @@
 
 static ERR_STRING_DATA RSA_str_functs[]=
 	{
+{ERR_FUNC(RSA_F_FIPS_RSA_SIGN),	"FIPS_RSA_SIGN"},
+{ERR_FUNC(RSA_F_FIPS_RSA_VERIFY),	"FIPS_RSA_VERIFY"},
 {ERR_FUNC(RSA_F_MEMORY_LOCK),	"MEMORY_LOCK"},
 {ERR_FUNC(RSA_F_RSA_BUILTIN_KEYGEN),	"RSA_BUILTIN_KEYGEN"},
 {ERR_FUNC(RSA_F_RSA_CHECK_KEY),	"RSA_check_key"},
@@ -101,7 +103,11 @@ static ERR_STRING_DATA RSA_str_functs[]=
 {ERR_FUNC(RSA_F_RSA_PADDING_CHECK_X931),	"RSA_padding_check_X931"},
 {ERR_FUNC(RSA_F_RSA_PRINT),	"RSA_print"},
 {ERR_FUNC(RSA_F_RSA_PRINT_FP),	"RSA_print_fp"},
+{ERR_FUNC(RSA_F_RSA_PRIVATE_ENCRYPT),	"RSA_private_encrypt"},
+{ERR_FUNC(RSA_F_RSA_PUBLIC_DECRYPT),	"RSA_public_decrypt"},
 {ERR_FUNC(RSA_F_RSA_SETUP_BLINDING),	"RSA_setup_blinding"},
+{ERR_FUNC(RSA_F_RSA_SET_DEFAULT_METHOD),	"RSA_set_default_method"},
+{ERR_FUNC(RSA_F_RSA_SET_METHOD),	"RSA_set_method"},
 {ERR_FUNC(RSA_F_RSA_SIGN),	"RSA_sign"},
 {ERR_FUNC(RSA_F_RSA_SIGN_ASN1_OCTET_STRING),	"RSA_sign_ASN1_OCTET_STRING"},
 {ERR_FUNC(RSA_F_RSA_VERIFY),	"RSA_verify"},
@@ -138,10 +144,12 @@ static ERR_STRING_DATA RSA_str_reasons[]=
 {ERR_REASON(RSA_R_KEY_SIZE_TOO_SMALL)    ,"key size too small"},
 {ERR_REASON(RSA_R_LAST_OCTET_INVALID)    ,"last octet invalid"},
 {ERR_REASON(RSA_R_MODULUS_TOO_LARGE)     ,"modulus too large"},
+{ERR_REASON(RSA_R_NON_FIPS_METHOD)       ,"non fips method"},
 {ERR_REASON(RSA_R_NO_PUBLIC_EXPONENT)    ,"no public exponent"},
 {ERR_REASON(RSA_R_NULL_BEFORE_BLOCK_MISSING),"null before block missing"},
 {ERR_REASON(RSA_R_N_DOES_NOT_EQUAL_P_Q)  ,"n does not equal p q"},
 {ERR_REASON(RSA_R_OAEP_DECODING_ERROR)   ,"oaep decoding error"},
+{ERR_REASON(RSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE),"operation not allowed in fips mode"},
 {ERR_REASON(RSA_R_PADDING_CHECK_FAILED)  ,"padding check failed"},
 {ERR_REASON(RSA_R_P_NOT_PRIME)           ,"p not prime"},
 {ERR_REASON(RSA_R_Q_NOT_PRIME)           ,"q not prime"},
diff --git a/src/lib/libcrypto/rsa/rsa_gen.c b/src/lib/libcrypto/rsa/rsa_gen.c
index 767f7ab682..41278f83c6 100644
--- a/src/lib/libcrypto/rsa/rsa_gen.c
+++ b/src/lib/libcrypto/rsa/rsa_gen.c
@@ -68,6 +68,8 @@
 #include <openssl/bn.h>
 #include <openssl/rsa.h>
 
+#ifndef OPENSSL_FIPS
+
 static int rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb);
 
 /* NB: this wrapper would normally be placed in rsa_lib.c and the static
@@ -217,3 +219,4 @@ err:
 	return ok;
 	}
 
+#endif
diff --git a/src/lib/libcrypto/rsa/rsa_lib.c b/src/lib/libcrypto/rsa/rsa_lib.c
index 104aa4c1f2..5714841f4c 100644
--- a/src/lib/libcrypto/rsa/rsa_lib.c
+++ b/src/lib/libcrypto/rsa/rsa_lib.c
@@ -67,215 +67,6 @@
 #include <openssl/engine.h>
 #endif
 
-const char RSA_version[]="RSA" OPENSSL_VERSION_PTEXT;
-
-static const RSA_METHOD *default_RSA_meth=NULL;
-
-RSA *RSA_new(void)
-	{
-	RSA *r=RSA_new_method(NULL);
-
-	return r;
-	}
-
-void RSA_set_default_method(const RSA_METHOD *meth)
-	{
-	default_RSA_meth = meth;
-	}
-
-const RSA_METHOD *RSA_get_default_method(void)
-	{
-	if (default_RSA_meth == NULL)
-		{
-#ifdef RSA_NULL
-		default_RSA_meth=RSA_null_method();
-#else
-#if 0 /* was: #ifdef RSAref */
-		default_RSA_meth=RSA_PKCS1_RSAref();
-#else
-		default_RSA_meth=RSA_PKCS1_SSLeay();
-#endif
-#endif
-		}
-
-	return default_RSA_meth;
-	}
-
-const RSA_METHOD *RSA_get_method(const RSA *rsa)
-	{
-	return rsa->meth;
-	}
-
-int RSA_set_method(RSA *rsa, const RSA_METHOD *meth)
-	{
-	/* NB: The caller is specifically setting a method, so it's not up to us
-	 * to deal with which ENGINE it comes from. */
-	const RSA_METHOD *mtmp;
-	mtmp = rsa->meth;
-	if (mtmp->finish) mtmp->finish(rsa);
-#ifndef OPENSSL_NO_ENGINE
-	if (rsa->engine)
-		{
-		ENGINE_finish(rsa->engine);
-		rsa->engine = NULL;
-		}
-#endif
-	rsa->meth = meth;
-	if (meth->init) meth->init(rsa);
-	return 1;
-	}
-
-RSA *RSA_new_method(ENGINE *engine)
-	{
-	RSA *ret;
-
-	ret=(RSA *)OPENSSL_malloc(sizeof(RSA));
-	if (ret == NULL)
-		{
-		RSAerr(RSA_F_RSA_NEW_METHOD,ERR_R_MALLOC_FAILURE);
-		return NULL;
-		}
-
-	ret->meth = RSA_get_default_method();
-#ifndef OPENSSL_NO_ENGINE
-	if (engine)
-		{
-		if (!ENGINE_init(engine))
-			{
-			RSAerr(RSA_F_RSA_NEW_METHOD, ERR_R_ENGINE_LIB);
-			OPENSSL_free(ret);
-			return NULL;
-			}
-		ret->engine = engine;
-		}
-	else
-		ret->engine = ENGINE_get_default_RSA();
-	if(ret->engine)
-		{
-		ret->meth = ENGINE_get_RSA(ret->engine);
-		if(!ret->meth)
-			{
-			RSAerr(RSA_F_RSA_NEW_METHOD,
-				ERR_R_ENGINE_LIB);
-			ENGINE_finish(ret->engine);
-			OPENSSL_free(ret);
-			return NULL;
-			}
-		}
-#endif
-
-	ret->pad=0;
-	ret->version=0;
-	ret->n=NULL;
-	ret->e=NULL;
-	ret->d=NULL;
-	ret->p=NULL;
-	ret->q=NULL;
-	ret->dmp1=NULL;
-	ret->dmq1=NULL;
-	ret->iqmp=NULL;
-	ret->references=1;
-	ret->_method_mod_n=NULL;
-	ret->_method_mod_p=NULL;
-	ret->_method_mod_q=NULL;
-	ret->blinding=NULL;
-	ret->mt_blinding=NULL;
-	ret->bignum_data=NULL;
-	ret->flags=ret->meth->flags;
-	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_RSA, ret, &ret->ex_data);
-	if ((ret->meth->init != NULL) && !ret->meth->init(ret))
-		{
-#ifndef OPENSSL_NO_ENGINE
-		if (ret->engine)
-			ENGINE_finish(ret->engine);
-#endif
-		CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, ret, &ret->ex_data);
-		OPENSSL_free(ret);
-		ret=NULL;
-		}
-	return(ret);
-	}
-
-void RSA_free(RSA *r)
-	{
-	int i;
-
-	if (r == NULL) return;
-
-	i=CRYPTO_add(&r->references,-1,CRYPTO_LOCK_RSA);
-#ifdef REF_PRINT
-	REF_PRINT("RSA",r);
-#endif
-	if (i > 0) return;
-#ifdef REF_CHECK
-	if (i < 0)
-		{
-		fprintf(stderr,"RSA_free, bad reference count\n");
-		abort();
-		}
-#endif
-
-	if (r->meth->finish)
-		r->meth->finish(r);
-#ifndef OPENSSL_NO_ENGINE
-	if (r->engine)
-		ENGINE_finish(r->engine);
-#endif
-
-	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, r, &r->ex_data);
-
-	if (r->n != NULL) BN_clear_free(r->n);
-	if (r->e != NULL) BN_clear_free(r->e);
-	if (r->d != NULL) BN_clear_free(r->d);
-	if (r->p != NULL) BN_clear_free(r->p);
-	if (r->q != NULL) BN_clear_free(r->q);
-	if (r->dmp1 != NULL) BN_clear_free(r->dmp1);
-	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->mt_blinding != NULL) BN_BLINDING_free(r->mt_blinding);
-	if (r->bignum_data != NULL) OPENSSL_free_locked(r->bignum_data);
-	OPENSSL_free(r);
-	}
-
-int RSA_up_ref(RSA *r)
-	{
-	int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_RSA);
-#ifdef REF_PRINT
-	REF_PRINT("RSA",r);
-#endif
-#ifdef REF_CHECK
-	if (i < 2)
-		{
-		fprintf(stderr, "RSA_up_ref, bad reference count\n");
-		abort();
-		}
-#endif
-	return ((i > 1) ? 1 : 0);
-	}
-
-int RSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
-	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
-        {
-	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_RSA, argl, argp,
-				new_func, dup_func, free_func);
-        }
-
-int RSA_set_ex_data(RSA *r, int idx, void *arg)
-	{
-	return(CRYPTO_set_ex_data(&r->ex_data,idx,arg));
-	}
-
-void *RSA_get_ex_data(const RSA *r, int idx)
-	{
-	return(CRYPTO_get_ex_data(&r->ex_data,idx));
-	}
-
-int RSA_size(const RSA *r)
-	{
-	return(BN_num_bytes(r->n));
-	}
-
 int RSA_public_encrypt(int flen, const unsigned char *from, unsigned char *to,
 	     RSA *rsa, int padding)
 	{
@@ -285,6 +76,13 @@ int RSA_public_encrypt(int flen, const unsigned char *from, unsigned char *to,
 int RSA_private_encrypt(int flen, const unsigned char *from, unsigned char *to,
 	     RSA *rsa, int padding)
 	{
+#ifdef OPENSSL_FIPS
+	if(FIPS_mode() && !(rsa->flags & RSA_FLAG_NON_FIPS_ALLOW))
+		{
+		RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, RSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE);
+		return 0;
+		}
+#endif
 	return(rsa->meth->rsa_priv_enc(flen, from, to, rsa, padding));
 	}
 
@@ -297,12 +95,19 @@ int RSA_private_decrypt(int flen, const unsigned char *from, unsigned char *to,
 int RSA_public_decrypt(int flen, const unsigned char *from, unsigned char *to,
 	     RSA *rsa, int padding)
 	{
+#ifdef OPENSSL_FIPS
+	if(FIPS_mode() && !(rsa->flags & RSA_FLAG_NON_FIPS_ALLOW))
+		{
+		RSAerr(RSA_F_RSA_PUBLIC_DECRYPT, RSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE);
+		return 0;
+		}
+#endif
 	return(rsa->meth->rsa_pub_dec(flen, from, to, rsa, padding));
 	}
 
-int RSA_flags(const RSA *r)
+int RSA_size(const RSA *r)
 	{
-	return((r == NULL)?0:r->meth->flags);
+	return(BN_num_bytes(r->n));
 	}
 
 void RSA_blinding_off(RSA *rsa)
@@ -427,48 +232,3 @@ err:
 
 	return ret;
 }
-
-int RSA_memory_lock(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=OPENSSL_malloc_locked((off+j)*sizeof(BN_ULONG))) == NULL)
-		{
-		RSAerr(RSA_F_RSA_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/src/lib/libcrypto/rsa/rsa_oaep.c b/src/lib/libcrypto/rsa/rsa_oaep.c
index 3652677a99..4d30c9d2d3 100644
--- a/src/lib/libcrypto/rsa/rsa_oaep.c
+++ b/src/lib/libcrypto/rsa/rsa_oaep.c
@@ -187,7 +187,7 @@ int PKCS1_MGF1(unsigned char *mask, long len,
 	int mdlen;
 
 	EVP_MD_CTX_init(&c);
-	mdlen = EVP_MD_size(dgst);
+	mdlen = M_EVP_MD_size(dgst);
 	for (i = 0; outlen < len; i++)
 		{
 		cnt[0] = (unsigned char)((i >> 24) & 255);
diff --git a/src/lib/libcrypto/rsa/rsa_pss.c b/src/lib/libcrypto/rsa/rsa_pss.c
index e19d18c5b9..9b993aca49 100644
--- a/src/lib/libcrypto/rsa/rsa_pss.c
+++ b/src/lib/libcrypto/rsa/rsa_pss.c
@@ -1,5 +1,5 @@
 /* rsa_pss.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2005.
  */
 /* ====================================================================
@@ -81,7 +81,7 @@ int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash,
 	EVP_MD_CTX ctx;
 	unsigned char H_[EVP_MAX_MD_SIZE];
 
-	hLen = EVP_MD_size(Hash);
+	hLen = M_EVP_MD_size(Hash);
 	/*
 	 * Negative sLen has special meanings:
 	 *	-1	sLen == hLen
@@ -176,7 +176,7 @@ int RSA_padding_add_PKCS1_PSS(RSA *rsa, unsigned char *EM,
 	unsigned char *H, *salt = NULL, *p;
 	EVP_MD_CTX ctx;
 
-	hLen = EVP_MD_size(Hash);
+	hLen = M_EVP_MD_size(Hash);
 	/*
 	 * Negative sLen has special meanings:
 	 *	-1	sLen == hLen
diff --git a/src/lib/libcrypto/rsa/rsa_sign.c b/src/lib/libcrypto/rsa/rsa_sign.c
index 71aabeea1b..5488c06f6d 100644
--- a/src/lib/libcrypto/rsa/rsa_sign.c
+++ b/src/lib/libcrypto/rsa/rsa_sign.c
@@ -90,6 +90,14 @@ int RSA_sign(int type, const unsigned char *m, unsigned int m_len,
 		i = SSL_SIG_LENGTH;
 		s = m;
 	} else {
+	/* NB: in FIPS mode block anything that isn't a TLS signature */
+#ifdef OPENSSL_FIPS
+		if(FIPS_mode() && !(rsa->flags & RSA_FLAG_NON_FIPS_ALLOW))
+			{
+			RSAerr(RSA_F_RSA_SIGN, RSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE);
+			return 0;
+			}
+#endif
 		sig.algor= &algor;
 		sig.algor->algorithm=OBJ_nid2obj(type);
 		if (sig.algor->algorithm == NULL)
@@ -167,10 +175,22 @@ int RSA_verify(int dtype, const unsigned char *m, unsigned int m_len,
 		RSAerr(RSA_F_RSA_VERIFY,ERR_R_MALLOC_FAILURE);
 		goto err;
 		}
-	if((dtype == NID_md5_sha1) && (m_len != SSL_SIG_LENGTH) ) {
+	if(dtype == NID_md5_sha1)
+		{
+		if (m_len != SSL_SIG_LENGTH)
+			{
 			RSAerr(RSA_F_RSA_VERIFY,RSA_R_INVALID_MESSAGE_LENGTH);
 			goto err;
-	}
+			}
+		}
+	/* NB: in FIPS mode block anything that isn't a TLS signature */
+#ifdef OPENSSL_FIPS
+	else if(FIPS_mode() && !(rsa->flags & RSA_FLAG_NON_FIPS_ALLOW))
+		{
+		RSAerr(RSA_F_RSA_VERIFY, RSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE);
+		return 0;
+		}
+#endif
 	i=RSA_public_decrypt((int)siglen,sigbuf,s,rsa,RSA_PKCS1_PADDING);
 
 	if (i <= 0) goto err;
diff --git a/src/lib/libcrypto/rsa/rsa_ssl.c b/src/lib/libcrypto/rsa/rsa_ssl.c
index ea72629494..cfeff15bc9 100644
--- a/src/lib/libcrypto/rsa/rsa_ssl.c
+++ b/src/lib/libcrypto/rsa/rsa_ssl.c
@@ -130,7 +130,7 @@ int RSA_padding_check_SSLv23(unsigned char *to, int tlen,
 		RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23,RSA_R_NULL_BEFORE_BLOCK_MISSING);
 		return(-1);
 		}
-	for (k= -8; k<0; k++)
+	for (k = -9; k<-1; k++)
 		{
 		if (p[k] !=  0x03) break;
 		}
diff --git a/src/lib/libcrypto/rsa/rsa_x931.c b/src/lib/libcrypto/rsa/rsa_x931.c
index e918654176..21548e37ed 100644
--- a/src/lib/libcrypto/rsa/rsa_x931.c
+++ b/src/lib/libcrypto/rsa/rsa_x931.c
@@ -1,5 +1,5 @@
 /* rsa_x931.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2005.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/sha/asm/sha1-586.pl b/src/lib/libcrypto/sha/asm/sha1-586.pl
index 0b4dab2bd5..a787dd37da 100644
--- a/src/lib/libcrypto/sha/asm/sha1-586.pl
+++ b/src/lib/libcrypto/sha/asm/sha1-586.pl
@@ -149,7 +149,7 @@ sub BODY_40_59
 	&add($f,$e);			# f+=ROTATE(a,5)
 	}
 
-&function_begin("sha1_block_data_order",16);
+&function_begin("sha1_block_data_order");
 	&mov($tmp1,&wparam(0));	# SHA_CTX *c
 	&mov($T,&wparam(1));	# const void *input
 	&mov($A,&wparam(2));	# size_t num
diff --git a/src/lib/libcrypto/sha/sha.h b/src/lib/libcrypto/sha/sha.h
index eed44d7f94..47a2c29f66 100644
--- a/src/lib/libcrypto/sha/sha.h
+++ b/src/lib/libcrypto/sha/sha.h
@@ -106,6 +106,9 @@ typedef struct SHAstate_st
 	} SHA_CTX;
 
 #ifndef OPENSSL_NO_SHA0
+#ifdef OPENSSL_FIPS
+int private_SHA_Init(SHA_CTX *c);
+#endif
 int SHA_Init(SHA_CTX *c);
 int SHA_Update(SHA_CTX *c, const void *data, size_t len);
 int SHA_Final(unsigned char *md, SHA_CTX *c);
diff --git a/src/lib/libcrypto/sha/sha1_one.c b/src/lib/libcrypto/sha/sha1_one.c
index 7c65b60276..4831174198 100644
--- a/src/lib/libcrypto/sha/sha1_one.c
+++ b/src/lib/libcrypto/sha/sha1_one.c
@@ -61,7 +61,7 @@
 #include <openssl/sha.h>
 #include <openssl/crypto.h>
 
-#ifndef OPENSSL_NO_SHA1
+#if !defined(OPENSSL_NO_SHA1)
 unsigned char *SHA1(const unsigned char *d, size_t n, unsigned char *md)
 	{
 	SHA_CTX c;
diff --git a/src/lib/libcrypto/sha/sha1dgst.c b/src/lib/libcrypto/sha/sha1dgst.c
index 50d1925cde..d31f0781a0 100644
--- a/src/lib/libcrypto/sha/sha1dgst.c
+++ b/src/lib/libcrypto/sha/sha1dgst.c
@@ -63,6 +63,10 @@
 #define SHA_1
 
 #include <openssl/opensslv.h>
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
+
 
 const char SHA1_version[]="SHA1" OPENSSL_VERSION_PTEXT;
 
diff --git a/src/lib/libcrypto/sha/sha256.c b/src/lib/libcrypto/sha/sha256.c
index 867f90cc97..3256a83e98 100644
--- a/src/lib/libcrypto/sha/sha256.c
+++ b/src/lib/libcrypto/sha/sha256.c
@@ -12,12 +12,19 @@
 
 #include <openssl/crypto.h>
 #include <openssl/sha.h>
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
+
 #include <openssl/opensslv.h>
 
 const char SHA256_version[]="SHA-256" OPENSSL_VERSION_PTEXT;
 
 int SHA224_Init (SHA256_CTX *c)
 	{
+#ifdef OPENSSL_FIPS
+	FIPS_selftest_check();
+#endif
 	c->h[0]=0xc1059ed8UL;	c->h[1]=0x367cd507UL;
 	c->h[2]=0x3070dd17UL;	c->h[3]=0xf70e5939UL;
 	c->h[4]=0xffc00b31UL;	c->h[5]=0x68581511UL;
@@ -29,6 +36,9 @@ int SHA224_Init (SHA256_CTX *c)
 
 int SHA256_Init (SHA256_CTX *c)
 	{
+#ifdef OPENSSL_FIPS
+	FIPS_selftest_check();
+#endif
 	c->h[0]=0x6a09e667UL;	c->h[1]=0xbb67ae85UL;
 	c->h[2]=0x3c6ef372UL;	c->h[3]=0xa54ff53aUL;
 	c->h[4]=0x510e527fUL;	c->h[5]=0x9b05688cUL;
diff --git a/src/lib/libcrypto/sha/sha512.c b/src/lib/libcrypto/sha/sha512.c
index 987fc07c99..f5ed468b85 100644
--- a/src/lib/libcrypto/sha/sha512.c
+++ b/src/lib/libcrypto/sha/sha512.c
@@ -5,6 +5,10 @@
  * ====================================================================
  */
 #include <openssl/opensslconf.h>
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
+
 #if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA512)
 /*
  * IMPLEMENTATION NOTES.
@@ -61,6 +65,9 @@ const char SHA512_version[]="SHA-512" OPENSSL_VERSION_PTEXT;
 
 int SHA384_Init (SHA512_CTX *c)
 	{
+#ifdef OPENSSL_FIPS
+	FIPS_selftest_check();
+#endif
 	c->h[0]=U64(0xcbbb9d5dc1059ed8);
 	c->h[1]=U64(0x629a292a367cd507);
 	c->h[2]=U64(0x9159015a3070dd17);
@@ -76,6 +83,9 @@ int SHA384_Init (SHA512_CTX *c)
 
 int SHA512_Init (SHA512_CTX *c)
 	{
+#ifdef OPENSSL_FIPS
+	FIPS_selftest_check();
+#endif
 	c->h[0]=U64(0x6a09e667f3bcc908);
 	c->h[1]=U64(0xbb67ae8584caa73b);
 	c->h[2]=U64(0x3c6ef372fe94f82b);
@@ -327,7 +337,7 @@ static const SHA_LONG64 K512[80] = {
 				((SHA_LONG64)hi)<<32|lo;	})
 #   else
 #    define PULL64(x) ({ const unsigned int *p=(const unsigned int *)(&(x));\
-			 unsigned int hi=p[0],lo=p[1];		\
+			 unsigned int hi=p[0],lo=p[1];			\
 				asm ("bswapl %0; bswapl %1;"	\
 				: "=r"(lo),"=r"(hi)		\
 				: "0"(lo),"1"(hi));		\
diff --git a/src/lib/libcrypto/sha/sha_locl.h b/src/lib/libcrypto/sha/sha_locl.h
index e37e5726e3..da46ddfe79 100644
--- a/src/lib/libcrypto/sha/sha_locl.h
+++ b/src/lib/libcrypto/sha/sha_locl.h
@@ -122,8 +122,15 @@ void sha1_block_data_order (SHA_CTX *c, const void *p,size_t num);
 #define INIT_DATA_h3 0x10325476UL
 #define INIT_DATA_h4 0xc3d2e1f0UL
 
+#if defined(SHA_0) && defined(OPENSSL_FIPS)
+FIPS_NON_FIPS_MD_Init(SHA)
+#else
 int HASH_INIT (SHA_CTX *c)
+#endif
 	{
+#if defined(SHA_1) && defined(OPENSSL_FIPS)
+	FIPS_selftest_check();
+#endif
 	c->h0=INIT_DATA_h0;
 	c->h1=INIT_DATA_h1;
 	c->h2=INIT_DATA_h2;
diff --git a/src/lib/libcrypto/stack/safestack.h b/src/lib/libcrypto/stack/safestack.h
index 78cc485e6d..40b17902e0 100644
--- a/src/lib/libcrypto/stack/safestack.h
+++ b/src/lib/libcrypto/stack/safestack.h
@@ -986,6 +986,50 @@ STACK_OF(type) \
 #define sk_MIME_HEADER_sort(st) SKM_sk_sort(MIME_HEADER, (st))
 #define sk_MIME_HEADER_is_sorted(st) SKM_sk_is_sorted(MIME_HEADER, (st))
 
+#define sk_MIME_HEADER_new(st) SKM_sk_new(MIME_HEADER, (st))
+#define sk_MIME_HEADER_new_null() SKM_sk_new_null(MIME_HEADER)
+#define sk_MIME_HEADER_free(st) SKM_sk_free(MIME_HEADER, (st))
+#define sk_MIME_HEADER_num(st) SKM_sk_num(MIME_HEADER, (st))
+#define sk_MIME_HEADER_value(st, i) SKM_sk_value(MIME_HEADER, (st), (i))
+#define sk_MIME_HEADER_set(st, i, val) SKM_sk_set(MIME_HEADER, (st), (i), (val))
+#define sk_MIME_HEADER_zero(st) SKM_sk_zero(MIME_HEADER, (st))
+#define sk_MIME_HEADER_push(st, val) SKM_sk_push(MIME_HEADER, (st), (val))
+#define sk_MIME_HEADER_unshift(st, val) SKM_sk_unshift(MIME_HEADER, (st), (val))
+#define sk_MIME_HEADER_find(st, val) SKM_sk_find(MIME_HEADER, (st), (val))
+#define sk_MIME_HEADER_find_ex(st, val) SKM_sk_find_ex(MIME_HEADER, (st), (val))
+#define sk_MIME_HEADER_delete(st, i) SKM_sk_delete(MIME_HEADER, (st), (i))
+#define sk_MIME_HEADER_delete_ptr(st, ptr) SKM_sk_delete_ptr(MIME_HEADER, (st), (ptr))
+#define sk_MIME_HEADER_insert(st, val, i) SKM_sk_insert(MIME_HEADER, (st), (val), (i))
+#define sk_MIME_HEADER_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(MIME_HEADER, (st), (cmp))
+#define sk_MIME_HEADER_dup(st) SKM_sk_dup(MIME_HEADER, st)
+#define sk_MIME_HEADER_pop_free(st, free_func) SKM_sk_pop_free(MIME_HEADER, (st), (free_func))
+#define sk_MIME_HEADER_shift(st) SKM_sk_shift(MIME_HEADER, (st))
+#define sk_MIME_HEADER_pop(st) SKM_sk_pop(MIME_HEADER, (st))
+#define sk_MIME_HEADER_sort(st) SKM_sk_sort(MIME_HEADER, (st))
+#define sk_MIME_HEADER_is_sorted(st) SKM_sk_is_sorted(MIME_HEADER, (st))
+
+#define sk_MIME_PARAM_new(st) SKM_sk_new(MIME_PARAM, (st))
+#define sk_MIME_PARAM_new_null() SKM_sk_new_null(MIME_PARAM)
+#define sk_MIME_PARAM_free(st) SKM_sk_free(MIME_PARAM, (st))
+#define sk_MIME_PARAM_num(st) SKM_sk_num(MIME_PARAM, (st))
+#define sk_MIME_PARAM_value(st, i) SKM_sk_value(MIME_PARAM, (st), (i))
+#define sk_MIME_PARAM_set(st, i, val) SKM_sk_set(MIME_PARAM, (st), (i), (val))
+#define sk_MIME_PARAM_zero(st) SKM_sk_zero(MIME_PARAM, (st))
+#define sk_MIME_PARAM_push(st, val) SKM_sk_push(MIME_PARAM, (st), (val))
+#define sk_MIME_PARAM_unshift(st, val) SKM_sk_unshift(MIME_PARAM, (st), (val))
+#define sk_MIME_PARAM_find(st, val) SKM_sk_find(MIME_PARAM, (st), (val))
+#define sk_MIME_PARAM_find_ex(st, val) SKM_sk_find_ex(MIME_PARAM, (st), (val))
+#define sk_MIME_PARAM_delete(st, i) SKM_sk_delete(MIME_PARAM, (st), (i))
+#define sk_MIME_PARAM_delete_ptr(st, ptr) SKM_sk_delete_ptr(MIME_PARAM, (st), (ptr))
+#define sk_MIME_PARAM_insert(st, val, i) SKM_sk_insert(MIME_PARAM, (st), (val), (i))
+#define sk_MIME_PARAM_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(MIME_PARAM, (st), (cmp))
+#define sk_MIME_PARAM_dup(st) SKM_sk_dup(MIME_PARAM, st)
+#define sk_MIME_PARAM_pop_free(st, free_func) SKM_sk_pop_free(MIME_PARAM, (st), (free_func))
+#define sk_MIME_PARAM_shift(st) SKM_sk_shift(MIME_PARAM, (st))
+#define sk_MIME_PARAM_pop(st) SKM_sk_pop(MIME_PARAM, (st))
+#define sk_MIME_PARAM_sort(st) SKM_sk_sort(MIME_PARAM, (st))
+#define sk_MIME_PARAM_is_sorted(st) SKM_sk_is_sorted(MIME_PARAM, (st))
+
 #define sk_MIME_PARAM_new(st) SKM_sk_new(MIME_PARAM, (st))
 #define sk_MIME_PARAM_new_null() SKM_sk_new_null(MIME_PARAM)
 #define sk_MIME_PARAM_free(st) SKM_sk_free(MIME_PARAM, (st))
diff --git a/src/lib/libcrypto/ui/ui_openssl.c b/src/lib/libcrypto/ui/ui_openssl.c
index 1f23a45a33..ef930bf247 100644
--- a/src/lib/libcrypto/ui/ui_openssl.c
+++ b/src/lib/libcrypto/ui/ui_openssl.c
@@ -677,6 +677,8 @@ static int noecho_fgets(char *buf, int size, FILE *tty)
 		size--;
 #ifdef WIN16TTY
 		i=_inchar();
+#elif defined(_WIN32)
+		i=_getch();
 #else
 		i=getch();
 #endif
diff --git a/src/lib/libcrypto/util/mkerr.pl b/src/lib/libcrypto/util/mkerr.pl
index 53e14ab4df..554bebb159 100644
--- a/src/lib/libcrypto/util/mkerr.pl
+++ b/src/lib/libcrypto/util/mkerr.pl
@@ -44,7 +44,8 @@ while (@ARGV) {
 }
 
 if($recurse) {
-	@source = (<crypto/*.c>, <crypto/*/*.c>, <ssl/*.c>);
+	@source = ( <crypto/*.c>, <crypto/*/*.c>, <ssl/*.c>,
+			<fips/*.c>, <fips/*/*.c>);
 } else {
 	@source = @ARGV;
 }
diff --git a/src/lib/libcrypto/x509/by_dir.c b/src/lib/libcrypto/x509/by_dir.c
index 37f9a48206..341e0ba6a4 100644
--- a/src/lib/libcrypto/x509/by_dir.c
+++ b/src/lib/libcrypto/x509/by_dir.c
@@ -74,6 +74,10 @@
 #include <openssl/lhash.h>
 #include <openssl/x509.h>
 
+#ifdef _WIN32
+#define stat	_stat
+#endif
+
 typedef struct lookup_dir_st
 	{
 	BUF_MEM *buffer;
diff --git a/src/lib/libcrypto/x509/x509_att.c b/src/lib/libcrypto/x509/x509_att.c
index 511b49d589..98460e8921 100644
--- a/src/lib/libcrypto/x509/x509_att.c
+++ b/src/lib/libcrypto/x509/x509_att.c
@@ -245,7 +245,7 @@ X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr,
 		goto err;
 	if (!X509_ATTRIBUTE_set1_data(ret,atrtype,data,len))
 		goto err;
-	
+
 	if ((attr != NULL) && (*attr == NULL)) *attr=ret;
 	return(ret);
 err:
@@ -302,8 +302,15 @@ int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, const void *dat
 		atype = attrtype;
 	}
 	if(!(attr->value.set = sk_ASN1_TYPE_new_null())) goto err;
+	attr->single = 0;
+	/* This is a bit naughty because the attribute should really have
+	 * at least one value but some types use and zero length SET and
+	 * require this.
+	 */
+	if (attrtype == 0)
+		return 1;
 	if(!(ttmp = ASN1_TYPE_new())) goto err;
-	if (len == -1)
+	if ((len == -1) && !(attrtype & MBSTRING_FLAG))
 		{
 		if (!ASN1_TYPE_set1(ttmp, attrtype, data))
 			goto err;
@@ -311,7 +318,6 @@ int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, const void *dat
 	else
 		ASN1_TYPE_set(ttmp, atype, stmp);
 	if(!sk_ASN1_TYPE_push(attr->value.set, ttmp)) goto err;
-	attr->single = 0;
 	return 1;
 	err:
 	X509err(X509_F_X509_ATTRIBUTE_SET1_DATA, ERR_R_MALLOC_FAILURE);
diff --git a/src/lib/libcrypto/x509/x509_cmp.c b/src/lib/libcrypto/x509/x509_cmp.c
index 0d6bc653b2..e4c682fc44 100644
--- a/src/lib/libcrypto/x509/x509_cmp.c
+++ b/src/lib/libcrypto/x509/x509_cmp.c
@@ -322,10 +322,16 @@ unsigned long X509_NAME_hash(X509_NAME *x)
 	{
 	unsigned long ret=0;
 	unsigned char md[16];
+	EVP_MD_CTX md_ctx;
 
 	/* Make sure X509_NAME structure contains valid cached encoding */
 	i2d_X509_NAME(x,NULL);
-	EVP_Digest(x->bytes->data, x->bytes->length, md, NULL, EVP_md5(), NULL);
+	EVP_MD_CTX_init(&md_ctx);
+	EVP_MD_CTX_set_flags(&md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
+	EVP_DigestInit_ex(&md_ctx, EVP_md5(), NULL);
+	EVP_DigestUpdate(&md_ctx, x->bytes->data, x->bytes->length);
+	EVP_DigestFinal_ex(&md_ctx,md,NULL);
+	EVP_MD_CTX_cleanup(&md_ctx);
 
 	ret=(	((unsigned long)md[0]     )|((unsigned long)md[1]<<8L)|
 		((unsigned long)md[2]<<16L)|((unsigned long)md[3]<<24L)
diff --git a/src/lib/libcrypto/x509/x509_trs.c b/src/lib/libcrypto/x509/x509_trs.c
index 9c84a59d52..ed18700585 100644
--- a/src/lib/libcrypto/x509/x509_trs.c
+++ b/src/lib/libcrypto/x509/x509_trs.c
@@ -1,5 +1,5 @@
 /* x509_trs.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509/x509_vfy.c b/src/lib/libcrypto/x509/x509_vfy.c
index 9a62ebcf67..336c40ddd7 100644
--- a/src/lib/libcrypto/x509/x509_vfy.c
+++ b/src/lib/libcrypto/x509/x509_vfy.c
@@ -394,7 +394,7 @@ static int check_chain_extensions(X509_STORE_CTX *ctx)
 #ifdef OPENSSL_NO_CHAIN_VERIFY
 	return 1;
 #else
-	int i, ok=0, must_be_ca;
+	int i, ok=0, must_be_ca, plen = 0;
 	X509 *x;
 	int (*cb)(int xok,X509_STORE_CTX *xctx);
 	int proxy_path_length = 0;
@@ -495,9 +495,10 @@ static int check_chain_extensions(X509_STORE_CTX *ctx)
 				if (!ok) goto end;
 				}
 			}
-		/* Check pathlen */
-		if ((i > 1) && (x->ex_pathlen != -1)
-			   && (i > (x->ex_pathlen + proxy_path_length + 1)))
+		/* Check pathlen if not self issued */
+		if ((i > 1) && !(x->ex_flags & EXFLAG_SI)
+			   && (x->ex_pathlen != -1)
+			   && (plen > (x->ex_pathlen + proxy_path_length + 1)))
 			{
 			ctx->error = X509_V_ERR_PATH_LENGTH_EXCEEDED;
 			ctx->error_depth = i;
@@ -505,6 +506,9 @@ static int check_chain_extensions(X509_STORE_CTX *ctx)
 			ok=cb(0,ctx);
 			if (!ok) goto end;
 			}
+		/* Increment path length if not self issued */
+		if (!(x->ex_flags & EXFLAG_SI))
+			plen++;
 		/* If this certificate is a proxy certificate, the next
 		   certificate must be another proxy certificate or a EE
 		   certificate.  If not, the next certificate must be a
diff --git a/src/lib/libcrypto/x509/x509_vpm.c b/src/lib/libcrypto/x509/x509_vpm.c
index e9db6d62a7..c92e65936f 100644
--- a/src/lib/libcrypto/x509/x509_vpm.c
+++ b/src/lib/libcrypto/x509/x509_vpm.c
@@ -1,5 +1,5 @@
 /* x509_vpm.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2004.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509/x509cset.c b/src/lib/libcrypto/x509/x509cset.c
index 9d1646d5c8..7f4004b291 100644
--- a/src/lib/libcrypto/x509/x509cset.c
+++ b/src/lib/libcrypto/x509/x509cset.c
@@ -1,5 +1,5 @@
 /* crypto/x509/x509cset.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2001.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509/x509spki.c b/src/lib/libcrypto/x509/x509spki.c
index ed868b838e..02a203d72c 100644
--- a/src/lib/libcrypto/x509/x509spki.c
+++ b/src/lib/libcrypto/x509/x509spki.c
@@ -1,5 +1,5 @@
 /* x509spki.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509v3/ext_dat.h b/src/lib/libcrypto/x509v3/ext_dat.h
index 5c063ac65d..3eaec46f8a 100644
--- a/src/lib/libcrypto/x509v3/ext_dat.h
+++ b/src/lib/libcrypto/x509v3/ext_dat.h
@@ -1,5 +1,5 @@
 /* ext_dat.h */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509v3/pcy_cache.c b/src/lib/libcrypto/x509v3/pcy_cache.c
index c18beb89f5..1030931b71 100644
--- a/src/lib/libcrypto/x509v3/pcy_cache.c
+++ b/src/lib/libcrypto/x509v3/pcy_cache.c
@@ -1,5 +1,5 @@
 /* pcy_cache.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2004.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509v3/pcy_data.c b/src/lib/libcrypto/x509v3/pcy_data.c
index 614d2b4935..fb392b901f 100644
--- a/src/lib/libcrypto/x509v3/pcy_data.c
+++ b/src/lib/libcrypto/x509v3/pcy_data.c
@@ -1,5 +1,5 @@
 /* pcy_data.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2004.
  */
 /* ====================================================================
@@ -87,6 +87,12 @@ X509_POLICY_DATA *policy_data_new(POLICYINFO *policy, ASN1_OBJECT *id, int crit)
 	X509_POLICY_DATA *ret;
 	if (!policy && !id)
 		return NULL;
+	if (id)
+		{
+		id = OBJ_dup(id);
+		if (!id)
+			return NULL;
+		}
 	ret = OPENSSL_malloc(sizeof(X509_POLICY_DATA));
 	if (!ret)
 		return NULL;
@@ -94,6 +100,8 @@ X509_POLICY_DATA *policy_data_new(POLICYINFO *policy, ASN1_OBJECT *id, int crit)
 	if (!ret->expected_policy_set)
 		{
 		OPENSSL_free(ret);
+		if (id)
+			ASN1_OBJECT_free(id);
 		return NULL;
 		}
 
diff --git a/src/lib/libcrypto/x509v3/pcy_int.h b/src/lib/libcrypto/x509v3/pcy_int.h
index ba62a209da..3780de4fcd 100644
--- a/src/lib/libcrypto/x509v3/pcy_int.h
+++ b/src/lib/libcrypto/x509v3/pcy_int.h
@@ -1,5 +1,5 @@
 /* pcy_int.h */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2004.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509v3/pcy_lib.c b/src/lib/libcrypto/x509v3/pcy_lib.c
index dae4840bc5..93bfd92703 100644
--- a/src/lib/libcrypto/x509v3/pcy_lib.c
+++ b/src/lib/libcrypto/x509v3/pcy_lib.c
@@ -1,5 +1,5 @@
 /* pcy_lib.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2004.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509v3/pcy_map.c b/src/lib/libcrypto/x509v3/pcy_map.c
index 35221e8ba8..f28796e6d4 100644
--- a/src/lib/libcrypto/x509v3/pcy_map.c
+++ b/src/lib/libcrypto/x509v3/pcy_map.c
@@ -1,5 +1,5 @@
 /* pcy_map.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2004.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509v3/pcy_node.c b/src/lib/libcrypto/x509v3/pcy_node.c
index dcc1554e29..6587cb05ab 100644
--- a/src/lib/libcrypto/x509v3/pcy_node.c
+++ b/src/lib/libcrypto/x509v3/pcy_node.c
@@ -1,5 +1,5 @@
 /* pcy_node.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2004.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509v3/pcy_tree.c b/src/lib/libcrypto/x509v3/pcy_tree.c
index 4fda1d419a..6c87a7f506 100644
--- a/src/lib/libcrypto/x509v3/pcy_tree.c
+++ b/src/lib/libcrypto/x509v3/pcy_tree.c
@@ -1,5 +1,5 @@
 /* pcy_tree.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2004.
  */
 /* ====================================================================
@@ -130,9 +130,9 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
 			ret = 2;
 		if (explicit_policy > 0)
 			{
-			explicit_policy--;
-			if (!(x->ex_flags & EXFLAG_SS)
-				&& (cache->explicit_skip != -1)
+			if (!(x->ex_flags & EXFLAG_SI))
+				explicit_policy--;
+			if ((cache->explicit_skip != -1)
 				&& (cache->explicit_skip < explicit_policy))
 				explicit_policy = cache->explicit_skip;
 			}
@@ -197,13 +197,14 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
 			/* Any matching allowed if certificate is self
 			 * issued and not the last in the chain.
 			 */
-			if (!(x->ex_flags & EXFLAG_SS) || (i == 0))
+			if (!(x->ex_flags & EXFLAG_SI) || (i == 0))
 				level->flags |= X509_V_FLAG_INHIBIT_ANY;
 			}
 		else
 			{
-			any_skip--;
-			if ((cache->any_skip > 0)
+			if (!(x->ex_flags & EXFLAG_SI))
+				any_skip--;
+			if ((cache->any_skip >= 0)
 				&& (cache->any_skip < any_skip))
 				any_skip = cache->any_skip;
 			}
@@ -213,7 +214,7 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
 		else
 			{
 			map_skip--;
-			if ((cache->map_skip > 0)
+			if ((cache->map_skip >= 0)
 				&& (cache->map_skip < map_skip))
 				map_skip = cache->map_skip;
 			}
@@ -310,7 +311,8 @@ static int tree_link_any(X509_POLICY_LEVEL *curr,
 
 		if (data == NULL)
 			return 0;
-		data->qualifier_set = curr->anyPolicy->data->qualifier_set;
+		/* Curr may not have anyPolicy */
+		data->qualifier_set = cache->anyPolicy->qualifier_set;
 		data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
 		if (!level_add_node(curr, data, node, tree))
 			{
diff --git a/src/lib/libcrypto/x509v3/v3_akey.c b/src/lib/libcrypto/x509v3/v3_akey.c
index ac0548b775..c6b68ee221 100644
--- a/src/lib/libcrypto/x509v3/v3_akey.c
+++ b/src/lib/libcrypto/x509v3/v3_akey.c
@@ -1,5 +1,5 @@
 /* v3_akey.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509v3/v3_akeya.c b/src/lib/libcrypto/x509v3/v3_akeya.c
index 2aafa26ba7..2c50f7360e 100644
--- a/src/lib/libcrypto/x509v3/v3_akeya.c
+++ b/src/lib/libcrypto/x509v3/v3_akeya.c
@@ -1,5 +1,5 @@
 /* v3_akey_asn1.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509v3/v3_alt.c b/src/lib/libcrypto/x509v3/v3_alt.c
index bb2f5bc54e..58b2952478 100644
--- a/src/lib/libcrypto/x509v3/v3_alt.c
+++ b/src/lib/libcrypto/x509v3/v3_alt.c
@@ -1,5 +1,5 @@
 /* v3_alt.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project.
  */
 /* ====================================================================
@@ -527,7 +527,8 @@ GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out,
 	return gen;
 
 	err:
-	GENERAL_NAME_free(gen);
+	if (!out)
+		GENERAL_NAME_free(gen);
 	return NULL;
 	}
 
diff --git a/src/lib/libcrypto/x509v3/v3_bcons.c b/src/lib/libcrypto/x509v3/v3_bcons.c
index 74b1233071..82aa488f75 100644
--- a/src/lib/libcrypto/x509v3/v3_bcons.c
+++ b/src/lib/libcrypto/x509v3/v3_bcons.c
@@ -1,5 +1,5 @@
 /* v3_bcons.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509v3/v3_bitst.c b/src/lib/libcrypto/x509v3/v3_bitst.c
index cf31f0816e..058d0d4dce 100644
--- a/src/lib/libcrypto/x509v3/v3_bitst.c
+++ b/src/lib/libcrypto/x509v3/v3_bitst.c
@@ -1,5 +1,5 @@
 /* v3_bitst.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509v3/v3_conf.c b/src/lib/libcrypto/x509v3/v3_conf.c
index 2b867305fb..11eb6b7fd5 100644
--- a/src/lib/libcrypto/x509v3/v3_conf.c
+++ b/src/lib/libcrypto/x509v3/v3_conf.c
@@ -1,5 +1,5 @@
 /* v3_conf.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509v3/v3_cpols.c b/src/lib/libcrypto/x509v3/v3_cpols.c
index a40f490aa9..95596055ab 100644
--- a/src/lib/libcrypto/x509v3/v3_cpols.c
+++ b/src/lib/libcrypto/x509v3/v3_cpols.c
@@ -1,5 +1,5 @@
 /* v3_cpols.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509v3/v3_crld.c b/src/lib/libcrypto/x509v3/v3_crld.c
index c6e3ebae7b..181a8977b1 100644
--- a/src/lib/libcrypto/x509v3/v3_crld.c
+++ b/src/lib/libcrypto/x509v3/v3_crld.c
@@ -1,5 +1,5 @@
 /* v3_crld.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509v3/v3_enum.c b/src/lib/libcrypto/x509v3/v3_enum.c
index a236cb22e1..36576eaa4d 100644
--- a/src/lib/libcrypto/x509v3/v3_enum.c
+++ b/src/lib/libcrypto/x509v3/v3_enum.c
@@ -1,5 +1,5 @@
 /* v3_enum.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509v3/v3_extku.c b/src/lib/libcrypto/x509v3/v3_extku.c
index a4efe0031e..c0d14500ed 100644
--- a/src/lib/libcrypto/x509v3/v3_extku.c
+++ b/src/lib/libcrypto/x509v3/v3_extku.c
@@ -1,5 +1,5 @@
 /* v3_extku.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509v3/v3_genn.c b/src/lib/libcrypto/x509v3/v3_genn.c
index 650b510980..84b4b1c881 100644
--- a/src/lib/libcrypto/x509v3/v3_genn.c
+++ b/src/lib/libcrypto/x509v3/v3_genn.c
@@ -1,5 +1,5 @@
 /* v3_genn.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509v3/v3_ia5.c b/src/lib/libcrypto/x509v3/v3_ia5.c
index b739ccd036..4ff12b52b5 100644
--- a/src/lib/libcrypto/x509v3/v3_ia5.c
+++ b/src/lib/libcrypto/x509v3/v3_ia5.c
@@ -1,5 +1,5 @@
 /* v3_ia5.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509v3/v3_info.c b/src/lib/libcrypto/x509v3/v3_info.c
index e0ef69de42..e1b8699f92 100644
--- a/src/lib/libcrypto/x509v3/v3_info.c
+++ b/src/lib/libcrypto/x509v3/v3_info.c
@@ -1,5 +1,5 @@
 /* v3_info.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509v3/v3_int.c b/src/lib/libcrypto/x509v3/v3_int.c
index 9a48dc1508..4bfd14cf46 100644
--- a/src/lib/libcrypto/x509v3/v3_int.c
+++ b/src/lib/libcrypto/x509v3/v3_int.c
@@ -1,5 +1,5 @@
 /* v3_int.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509v3/v3_lib.c b/src/lib/libcrypto/x509v3/v3_lib.c
index f3015ea610..df3a48f43e 100644
--- a/src/lib/libcrypto/x509v3/v3_lib.c
+++ b/src/lib/libcrypto/x509v3/v3_lib.c
@@ -1,5 +1,5 @@
 /* v3_lib.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509v3/v3_ncons.c b/src/lib/libcrypto/x509v3/v3_ncons.c
index 42e7f5a879..4e706be3e1 100644
--- a/src/lib/libcrypto/x509v3/v3_ncons.c
+++ b/src/lib/libcrypto/x509v3/v3_ncons.c
@@ -1,5 +1,5 @@
 /* v3_ncons.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509v3/v3_ocsp.c b/src/lib/libcrypto/x509v3/v3_ocsp.c
index 62aac06335..e426ea930c 100644
--- a/src/lib/libcrypto/x509v3/v3_ocsp.c
+++ b/src/lib/libcrypto/x509v3/v3_ocsp.c
@@ -1,5 +1,5 @@
 /* v3_ocsp.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509v3/v3_pcons.c b/src/lib/libcrypto/x509v3/v3_pcons.c
index 13248c2ada..86c0ff70e6 100644
--- a/src/lib/libcrypto/x509v3/v3_pcons.c
+++ b/src/lib/libcrypto/x509v3/v3_pcons.c
@@ -1,5 +1,5 @@
 /* v3_pcons.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509v3/v3_pku.c b/src/lib/libcrypto/x509v3/v3_pku.c
index 5c4626e89b..076f3ff48e 100644
--- a/src/lib/libcrypto/x509v3/v3_pku.c
+++ b/src/lib/libcrypto/x509v3/v3_pku.c
@@ -1,5 +1,5 @@
 /* v3_pku.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509v3/v3_pmaps.c b/src/lib/libcrypto/x509v3/v3_pmaps.c
index 626303264f..da03bbc35d 100644
--- a/src/lib/libcrypto/x509v3/v3_pmaps.c
+++ b/src/lib/libcrypto/x509v3/v3_pmaps.c
@@ -1,5 +1,5 @@
 /* v3_pmaps.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509v3/v3_prn.c b/src/lib/libcrypto/x509v3/v3_prn.c
index 20bd9bda19..c1bb17f105 100644
--- a/src/lib/libcrypto/x509v3/v3_prn.c
+++ b/src/lib/libcrypto/x509v3/v3_prn.c
@@ -1,5 +1,5 @@
 /* v3_prn.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509v3/v3_purp.c b/src/lib/libcrypto/x509v3/v3_purp.c
index b2f5cdfa05..e18751e01c 100644
--- a/src/lib/libcrypto/x509v3/v3_purp.c
+++ b/src/lib/libcrypto/x509v3/v3_purp.c
@@ -1,5 +1,5 @@
 /* v3_purp.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2001.
  */
 /* ====================================================================
@@ -291,7 +291,9 @@ int X509_supported_extension(X509_EXTENSION *ex)
 		NID_sbgp_ipAddrBlock,	/* 290 */
 		NID_sbgp_autonomousSysNum, /* 291 */
 #endif
-		NID_proxyCertInfo	/* 661 */
+		NID_policy_constraints,	/* 401 */
+		NID_proxyCertInfo,	/* 661 */
+		NID_inhibit_any_policy	/* 748 */
 	};
 
 	int ex_nid;
@@ -325,7 +327,7 @@ static void x509v3_cache_extensions(X509 *x)
 #endif
 	/* Does subject name match issuer ? */
 	if(!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x)))
-			 x->ex_flags |= EXFLAG_SS;
+			 x->ex_flags |= EXFLAG_SI;
 	/* V1 should mean no extensions ... */
 	if(!X509_get_version(x)) x->ex_flags |= EXFLAG_V1;
 	/* Handle basic constraints */
diff --git a/src/lib/libcrypto/x509v3/v3_skey.c b/src/lib/libcrypto/x509v3/v3_skey.c
index da0a3558f6..202c9e4896 100644
--- a/src/lib/libcrypto/x509v3/v3_skey.c
+++ b/src/lib/libcrypto/x509v3/v3_skey.c
@@ -1,5 +1,5 @@
 /* v3_skey.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509v3/v3_sxnet.c b/src/lib/libcrypto/x509v3/v3_sxnet.c
index eaea9ea01b..2a6bf11b65 100644
--- a/src/lib/libcrypto/x509v3/v3_sxnet.c
+++ b/src/lib/libcrypto/x509v3/v3_sxnet.c
@@ -1,5 +1,5 @@
 /* v3_sxnet.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
diff --git a/src/lib/libcrypto/x509v3/v3_utl.c b/src/lib/libcrypto/x509v3/v3_utl.c
index ac171ca940..a4236bbb6d 100644
--- a/src/lib/libcrypto/x509v3/v3_utl.c
+++ b/src/lib/libcrypto/x509v3/v3_utl.c
@@ -1,5 +1,5 @@
 /* v3_utl.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project.
  */
 /* ====================================================================
@@ -736,17 +736,20 @@ static int ipv6_from_asc(unsigned char *v6, const char *in)
 
 	/* Format result */
 
-	/* Copy initial part */
-	if (v6stat.zero_pos > 0)
+	if (v6stat.zero_pos >= 0)
+		{
+		/* Copy initial part */
 		memcpy(v6, v6stat.tmp, v6stat.zero_pos);
-	/* Zero middle */
-	if (v6stat.total != 16)
+		/* Zero middle */
 		memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total);
-	/* Copy final part */
-	if (v6stat.total != v6stat.zero_pos)
-		memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total,
-			v6stat.tmp + v6stat.zero_pos,
-			v6stat.total - v6stat.zero_pos);
+		/* Copy final part */
+		if (v6stat.total != v6stat.zero_pos)
+			memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total,
+				v6stat.tmp + v6stat.zero_pos,
+				v6stat.total - v6stat.zero_pos);
+		}
+	else
+		memcpy(v6, v6stat.tmp, 16);
 
 	return 1;
 	}
diff --git a/src/lib/libcrypto/x509v3/x509v3.h b/src/lib/libcrypto/x509v3/x509v3.h
index db2b0482c1..9ef83da755 100644
--- a/src/lib/libcrypto/x509v3/x509v3.h
+++ b/src/lib/libcrypto/x509v3/x509v3.h
@@ -1,5 +1,5 @@
 /* x509v3.h */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
@@ -363,6 +363,8 @@ DECLARE_ASN1_FUNCTIONS(PROXY_CERT_INFO_EXTENSION)
 #define EXFLAG_NSCERT		0x8
 
 #define EXFLAG_CA		0x10
+/* Really self issued not necessarily self signed */
+#define EXFLAG_SI		0x20
 #define EXFLAG_SS		0x20
 #define EXFLAG_V1		0x40
 #define EXFLAG_INVALID		0x80
@@ -370,7 +372,7 @@ DECLARE_ASN1_FUNCTIONS(PROXY_CERT_INFO_EXTENSION)
 #define EXFLAG_CRITICAL		0x200
 #define EXFLAG_PROXY		0x400
 
-#define EXFLAG_INVALID_POLICY	0x400
+#define EXFLAG_INVALID_POLICY	0x800
 
 #define KU_DIGITAL_SIGNATURE	0x0080
 #define KU_NON_REPUDIATION	0x0040
diff --git a/src/lib/libssl/d1_clnt.c b/src/lib/libssl/d1_clnt.c
index 5e59dc845a..49c6760d19 100644
--- a/src/lib/libssl/d1_clnt.c
+++ b/src/lib/libssl/d1_clnt.c
@@ -1095,8 +1095,7 @@ int dtls1_send_client_certificate(SSL *s)
 		 * ssl->rwstate=SSL_X509_LOOKUP; return(-1);
 		 * We then get retied later */
 		i=0;
-		if (s->ctx->client_cert_cb != NULL)
-			i=s->ctx->client_cert_cb(s,&(x509),&(pkey));
+		i = ssl_do_client_cert_cb(s, &x509, &pkey);
 		if (i < 0)
 			{
 			s->rwstate=SSL_X509_LOOKUP;
diff --git a/src/lib/libssl/d1_enc.c b/src/lib/libssl/d1_enc.c
index cbff7495c5..cf3332e4e4 100644
--- a/src/lib/libssl/d1_enc.c
+++ b/src/lib/libssl/d1_enc.c
@@ -115,12 +115,16 @@
 
 #include <stdio.h>
 #include "ssl_locl.h"
+#ifndef OPENSSL_NO_COMP
 #include <openssl/comp.h>
+#endif
 #include <openssl/evp.h>
 #include <openssl/hmac.h>
 #include <openssl/md5.h>
 #include <openssl/rand.h>
-
+#ifdef KSSL_DEBUG
+#include <openssl/des.h>
+#endif
 
 int dtls1_enc(SSL *s, int send)
 	{
@@ -202,10 +206,11 @@ int dtls1_enc(SSL *s, int send)
 		{
                 unsigned long ui;
 		printf("EVP_Cipher(ds=%p,rec->data=%p,rec->input=%p,l=%ld) ==>\n",
-                        ds,rec->data,rec->input,l);
-		printf("\tEVP_CIPHER_CTX: %d buf_len, %d key_len [%d %d], %d iv_len\n",
+                        (void *)ds,rec->data,rec->input,l);
+		printf("\tEVP_CIPHER_CTX: %d buf_len, %d key_len [%ld %ld], %d iv_len\n",
                         ds->buf_len, ds->cipher->key_len,
-                        DES_KEY_SZ, DES_SCHEDULE_SZ,
+                        (unsigned long)DES_KEY_SZ,
+			(unsigned long)DES_SCHEDULE_SZ,
                         ds->cipher->iv_len);
 		printf("\t\tIV: ");
 		for (i=0; i<ds->cipher->iv_len; i++) printf("%02X", ds->iv[i]);
@@ -230,10 +235,10 @@ int dtls1_enc(SSL *s, int send)
 
 #ifdef KSSL_DEBUG
 		{
-                unsigned long i;
+                unsigned long ki;
                 printf("\trec->data=");
-		for (i=0; i<l; i++)
-                        printf(" %02x", rec->data[i]);  printf("\n");
+		for (ki=0; ki<l; ki++)
+                        printf(" %02x", rec->data[ki]);  printf("\n");
                 }
 #endif	/* KSSL_DEBUG */
 
diff --git a/src/lib/libssl/d1_lib.c b/src/lib/libssl/d1_lib.c
index fc088b4148..3568e97a87 100644
--- a/src/lib/libssl/d1_lib.c
+++ b/src/lib/libssl/d1_lib.c
@@ -106,6 +106,7 @@ int dtls1_new(SSL *s)
 	pq_64bit_init(&(d1->bitmap.map));
 	pq_64bit_init(&(d1->bitmap.max_seq_num));
 	
+	d1->next_bitmap.length = d1->bitmap.length;
 	pq_64bit_init(&(d1->next_bitmap.map));
 	pq_64bit_init(&(d1->next_bitmap.max_seq_num));
 
diff --git a/src/lib/libssl/d1_pkt.c b/src/lib/libssl/d1_pkt.c
index 377696deac..eb56cf987b 100644
--- a/src/lib/libssl/d1_pkt.c
+++ b/src/lib/libssl/d1_pkt.c
@@ -597,6 +597,7 @@ again:
 	/* check whether this is a repeat, or aged record */
 	if ( ! dtls1_record_replay_check(s, bitmap, &(rr->seq_num)))
 		{
+		rr->length = 0;
 		s->packet_length=0; /* dump this record */
 		goto again;     /* get another record */
 		}
@@ -811,6 +812,14 @@ start:
              *  may be fragmented--don't always expect dest_maxlen bytes */
 			if ( rr->length < dest_maxlen)
 				{
+#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
+				/*
+				 * for normal alerts rr->length is 2, while
+				 * dest_maxlen is 7 if we were to handle this
+				 * non-existing alert...
+				 */
+				FIX ME
+#endif
 				s->rstate=SSL_ST_READ_HEADER;
 				rr->length = 0;
 				goto start;
@@ -1251,7 +1260,7 @@ int dtls1_write_bytes(SSL *s, int type, const void *buf_, int len)
 	else 
 		s->s3->wnum += i;
 
-	return tot + i;
+	return i;
 	}
 
 int do_dtls1_write(SSL *s, int type, const unsigned char *buf, unsigned int len, int create_empty_fragment)
@@ -1576,7 +1585,7 @@ int dtls1_dispatch_alert(SSL *s)
 	{
 	int i,j;
 	void (*cb)(const SSL *ssl,int type,int val)=NULL;
-	unsigned char buf[2 + 2 + 3]; /* alert level + alert desc + message seq +frag_off */
+	unsigned char buf[DTLS1_AL_HEADER_LENGTH];
 	unsigned char *ptr = &buf[0];
 
 	s->s3->alert_dispatch=0;
@@ -1585,6 +1594,7 @@ int dtls1_dispatch_alert(SSL *s)
 	*ptr++ = s->s3->send_alert[0];
 	*ptr++ = s->s3->send_alert[1];
 
+#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
 	if (s->s3->send_alert[1] == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE)
 		{	
 		s2n(s->d1->handshake_read_seq, ptr);
@@ -1600,6 +1610,7 @@ int dtls1_dispatch_alert(SSL *s)
 #endif
 		l2n3(s->d1->r_msg_hdr.frag_off, ptr);
 		}
+#endif
 
 	i = do_dtls1_write(s, SSL3_RT_ALERT, &buf[0], sizeof(buf), 0);
 	if (i <= 0)
@@ -1609,8 +1620,11 @@ int dtls1_dispatch_alert(SSL *s)
 		}
 	else
 		{
-		if ( s->s3->send_alert[0] == SSL3_AL_FATAL ||
-			s->s3->send_alert[1] == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE)
+		if (s->s3->send_alert[0] == SSL3_AL_FATAL
+#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
+		    || s->s3->send_alert[1] == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
+#endif
+		   )
 			(void)BIO_flush(s->wbio);
 
 		if (s->msg_callback)
diff --git a/src/lib/libssl/d1_srvr.c b/src/lib/libssl/d1_srvr.c
index 927b01f3c4..0bbf8ae7f3 100644
--- a/src/lib/libssl/d1_srvr.c
+++ b/src/lib/libssl/d1_srvr.c
@@ -732,7 +732,7 @@ int dtls1_send_server_hello(SSL *s)
 
 		d = dtls1_set_message_header(s, d, SSL3_MT_SERVER_HELLO, l, 0, l);
 
-		s->state=SSL3_ST_CW_CLNT_HELLO_B;
+		s->state=SSL3_ST_SW_SRVR_HELLO_B;
 		/* number of bytes to write */
 		s->init_num=p-buf;
 		s->init_off=0;
@@ -741,7 +741,7 @@ int dtls1_send_server_hello(SSL *s)
 		dtls1_buffer_message(s, 0);
 		}
 
-	/* SSL3_ST_CW_CLNT_HELLO_B */
+	/* SSL3_ST_SW_SRVR_HELLO_B */
 	return(dtls1_do_write(s,SSL3_RT_HANDSHAKE));
 	}
 
@@ -765,7 +765,7 @@ int dtls1_send_server_done(SSL *s)
 		dtls1_buffer_message(s, 0);
 		}
 
-	/* SSL3_ST_CW_CLNT_HELLO_B */
+	/* SSL3_ST_SW_SRVR_DONE_B */
 	return(dtls1_do_write(s,SSL3_RT_HANDSHAKE));
 	}
 
diff --git a/src/lib/libssl/dtls1.h b/src/lib/libssl/dtls1.h
index a663cf85f2..f159d37110 100644
--- a/src/lib/libssl/dtls1.h
+++ b/src/lib/libssl/dtls1.h
@@ -70,7 +70,10 @@ extern "C" {
 #define DTLS1_VERSION			0xFEFF
 #define DTLS1_BAD_VER			0x0100
 
+#if 0
+/* this alert description is not specified anywhere... */
 #define DTLS1_AD_MISSING_HANDSHAKE_MESSAGE    110
+#endif
 
 /* lengths of messages */
 #define DTLS1_COOKIE_LENGTH                     32
@@ -84,7 +87,11 @@ extern "C" {
 
 #define DTLS1_CCS_HEADER_LENGTH                  1
 
+#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
 #define DTLS1_AL_HEADER_LENGTH                   7
+#else
+#define DTLS1_AL_HEADER_LENGTH                   2
+#endif
 
 
 typedef struct dtls1_bitmap_st
diff --git a/src/lib/libssl/s23_clnt.c b/src/lib/libssl/s23_clnt.c
index c45a8e0a04..bc918170e1 100644
--- a/src/lib/libssl/s23_clnt.c
+++ b/src/lib/libssl/s23_clnt.c
@@ -257,6 +257,14 @@ static int ssl23_client_hello(SSL *s)
 			version_major = TLS1_VERSION_MAJOR;
 			version_minor = TLS1_VERSION_MINOR;
 			}
+#ifdef OPENSSL_FIPS
+		else if(FIPS_mode())
+			{
+			SSLerr(SSL_F_SSL23_CLIENT_HELLO,
+					SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE);
+			return -1;
+			}
+#endif
 		else if (version == SSL3_VERSION)
 			{
 			version_major = SSL3_VERSION_MAJOR;
@@ -536,6 +544,14 @@ static int ssl23_get_server_hello(SSL *s)
 		if ((p[2] == SSL3_VERSION_MINOR) &&
 			!(s->options & SSL_OP_NO_SSLv3))
 			{
+#ifdef OPENSSL_FIPS
+			if(FIPS_mode())
+				{
+				SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,
+					SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE);
+				goto err;
+				}
+#endif
 			s->version=SSL3_VERSION;
 			s->method=SSLv3_client_method();
 			}
diff --git a/src/lib/libssl/s23_srvr.c b/src/lib/libssl/s23_srvr.c
index 6637bb9549..ba06e7ae2e 100644
--- a/src/lib/libssl/s23_srvr.c
+++ b/src/lib/libssl/s23_srvr.c
@@ -386,6 +386,15 @@ int ssl23_get_client_hello(SSL *s)
 			}
 		}
 
+#ifdef OPENSSL_FIPS
+	if (FIPS_mode() && (s->version < TLS1_VERSION))
+		{
+		SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,
+					SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE);
+		goto err;
+		}
+#endif
+
 	if (s->state == SSL23_ST_SR_CLNT_HELLO_B)
 		{
 		/* we have SSLv3/TLSv1 in an SSLv2 header
diff --git a/src/lib/libssl/s3_clnt.c b/src/lib/libssl/s3_clnt.c
index f6864cdc50..5fd3520caf 100644
--- a/src/lib/libssl/s3_clnt.c
+++ b/src/lib/libssl/s3_clnt.c
@@ -130,10 +130,17 @@
 #include <openssl/objects.h>
 #include <openssl/evp.h>
 #include <openssl/md5.h>
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
+
 #ifndef OPENSSL_NO_DH
 #include <openssl/dh.h>
 #endif
 #include <openssl/bn.h>
+#ifndef OPENSSL_NO_ENGINE
+#include <openssl/engine.h>
+#endif
 
 static SSL_METHOD *ssl3_get_client_method(int ver);
 static int ca_dn_cmp(const X509_NAME * const *a,const X509_NAME * const *b);
@@ -965,7 +972,7 @@ int ssl3_get_server_certificate(SSL *s)
 		}
 
 	i=ssl_verify_cert_chain(s,sk);
-	if ((s->verify_mode != SSL_VERIFY_NONE) && (!i)
+	if ((s->verify_mode != SSL_VERIFY_NONE) && (i <= 0)
 #ifndef OPENSSL_NO_KRB5
 	        && (s->s3->tmp.new_cipher->algorithms & (SSL_MKEY_MASK|SSL_AUTH_MASK))
 	        != (SSL_aKRB5|SSL_kKRB5)
@@ -999,7 +1006,7 @@ int ssl3_get_server_certificate(SSL *s)
 	                 == (SSL_aKRB5|SSL_kKRB5))? 0: 1;
 
 #ifdef KSSL_DEBUG
-	printf("pkey,x = %p, %p\n", pkey,x);
+	printf("pkey,x = %p, %p\n", (void *)pkey,(void *)x);
 	printf("ssl_cert_type(x,pkey) = %d\n", ssl_cert_type(x,pkey));
 	printf("cipher, alg, nc = %s, %lx, %d\n", s->s3->tmp.new_cipher->name,
 	        s->s3->tmp.new_cipher->algorithms, need_cert);
@@ -1415,6 +1422,8 @@ int ssl3_get_key_exchange(SSL *s)
 			q=md_buf;
 			for (num=2; num > 0; num--)
 				{
+				EVP_MD_CTX_set_flags(&md_ctx,
+					EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
 				EVP_DigestInit_ex(&md_ctx,(num == 2)
 					?s->ctx->md5:s->ctx->sha1, NULL);
 				EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
@@ -1450,7 +1459,7 @@ int ssl3_get_key_exchange(SSL *s)
 			EVP_VerifyUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
 			EVP_VerifyUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
 			EVP_VerifyUpdate(&md_ctx,param,param_len);
-			if (!EVP_VerifyFinal(&md_ctx,p,(int)n,pkey))
+			if (EVP_VerifyFinal(&md_ctx,p,(int)n,pkey) <= 0)
 				{
 				/* bad signature */
 				al=SSL_AD_DECRYPT_ERROR;
@@ -1468,7 +1477,7 @@ int ssl3_get_key_exchange(SSL *s)
 			EVP_VerifyUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
 			EVP_VerifyUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
 			EVP_VerifyUpdate(&md_ctx,param,param_len);
-			if (!EVP_VerifyFinal(&md_ctx,p,(int)n,pkey))
+			if (EVP_VerifyFinal(&md_ctx,p,(int)n,pkey) <= 0)
 				{
 				/* bad signature */
 				al=SSL_AD_DECRYPT_ERROR;
@@ -1768,7 +1777,7 @@ int ssl3_get_cert_status(SSL *s)
 		goto f_err;
 		}
 	n2l3(p, resplen);
-	if (resplen + 4 != n)
+	if (resplen + 4 != (unsigned long)n)
 		{
 		al = SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_LENGTH_MISMATCH);
@@ -2061,12 +2070,12 @@ int ssl3_send_client_key_exchange(SSL *s)
 			{
 			DH *dh_srvr,*dh_clnt;
 
-                        if (s->session->sess_cert == NULL) 
-                                {
-                                ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
-                                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
-                                goto err;
-                                }
+			if (s->session->sess_cert == NULL) 
+				{
+				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
+				goto err;
+			        }
 
 			if (s->session->sess_cert->peer_dh_tmp != NULL)
 				dh_srvr=s->session->sess_cert->peer_dh_tmp;
@@ -2448,8 +2457,7 @@ int ssl3_send_client_certificate(SSL *s)
 		 * ssl->rwstate=SSL_X509_LOOKUP; return(-1);
 		 * We then get retied later */
 		i=0;
-		if (s->ctx->client_cert_cb != NULL)
-			i=s->ctx->client_cert_cb(s,&(x509),&(pkey));
+		i = ssl_do_client_cert_cb(s, &x509, &pkey);
 		if (i < 0)
 			{
 			s->rwstate=SSL_X509_LOOKUP;
@@ -2716,3 +2724,21 @@ static int ssl3_check_finished(SSL *s)
 	return 1;
 	}
 #endif
+
+int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey)
+	{
+	int i = 0;
+#ifndef OPENSSL_NO_ENGINE
+	if (s->ctx->client_cert_engine)
+		{
+		i = ENGINE_load_ssl_client_cert(s->ctx->client_cert_engine, s,
+						SSL_get_client_CA_list(s),
+						px509, ppkey, NULL, NULL, NULL);
+		if (i != 0)
+			return i;
+		}
+#endif
+	if (s->ctx->client_cert_cb)
+		i = s->ctx->client_cert_cb(s,px509,ppkey);
+	return i;
+	}
diff --git a/src/lib/libssl/s3_lib.c b/src/lib/libssl/s3_lib.c
index bdbcd44f27..8916a0b1b3 100644
--- a/src/lib/libssl/s3_lib.c
+++ b/src/lib/libssl/s3_lib.c
@@ -158,7 +158,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
 	SSL3_TXT_RSA_NULL_SHA,
 	SSL3_CK_RSA_NULL_SHA,
 	SSL_kRSA|SSL_aRSA|SSL_eNULL |SSL_SHA1|SSL_SSLV3,
-	SSL_NOT_EXP|SSL_STRONG_NONE,
+	SSL_NOT_EXP|SSL_STRONG_NONE|SSL_FIPS,
 	0,
 	0,
 	0,
@@ -264,7 +264,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
 	SSL3_TXT_RSA_DES_192_CBC3_SHA,
 	SSL3_CK_RSA_DES_192_CBC3_SHA,
 	SSL_kRSA|SSL_aRSA|SSL_3DES |SSL_SHA1|SSL_SSLV3,
-	SSL_NOT_EXP|SSL_HIGH,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
 	0,
 	168,
 	168,
@@ -304,7 +304,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
 	SSL3_TXT_DH_DSS_DES_192_CBC3_SHA,
 	SSL3_CK_DH_DSS_DES_192_CBC3_SHA,
 	SSL_kDHd |SSL_aDH|SSL_3DES |SSL_SHA1|SSL_SSLV3,
-	SSL_NOT_EXP|SSL_HIGH,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
 	0,
 	168,
 	168,
@@ -343,7 +343,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
 	SSL3_TXT_DH_RSA_DES_192_CBC3_SHA,
 	SSL3_CK_DH_RSA_DES_192_CBC3_SHA,
 	SSL_kDHr |SSL_aDH|SSL_3DES |SSL_SHA1|SSL_SSLV3,
-	SSL_NOT_EXP|SSL_HIGH,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
 	0,
 	168,
 	168,
@@ -384,7 +384,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
 	SSL3_TXT_EDH_DSS_DES_192_CBC3_SHA,
 	SSL3_CK_EDH_DSS_DES_192_CBC3_SHA,
 	SSL_kEDH|SSL_aDSS|SSL_3DES |SSL_SHA1|SSL_SSLV3,
-	SSL_NOT_EXP|SSL_HIGH,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
 	0,
 	168,
 	168,
@@ -423,7 +423,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
 	SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA,
 	SSL3_CK_EDH_RSA_DES_192_CBC3_SHA,
 	SSL_kEDH|SSL_aRSA|SSL_3DES |SSL_SHA1|SSL_SSLV3,
-	SSL_NOT_EXP|SSL_HIGH,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
 	0,
 	168,
 	168,
@@ -488,7 +488,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
 	SSL3_TXT_ADH_DES_192_CBC_SHA,
 	SSL3_CK_ADH_DES_192_CBC_SHA,
 	SSL_kEDH |SSL_aNULL|SSL_3DES |SSL_SHA1|SSL_SSLV3,
-	SSL_NOT_EXP|SSL_HIGH,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
 	0,
 	168,
 	168,
@@ -563,7 +563,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
 	SSL3_TXT_KRB5_DES_192_CBC3_SHA,
 	SSL3_CK_KRB5_DES_192_CBC3_SHA,
 	SSL_kKRB5|SSL_aKRB5|  SSL_3DES|SSL_SHA1  |SSL_SSLV3,
-	SSL_NOT_EXP|SSL_HIGH,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
 	0,
 	168,
 	168,
@@ -747,7 +747,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
 	TLS1_TXT_RSA_WITH_AES_128_SHA,
 	TLS1_CK_RSA_WITH_AES_128_SHA,
 	SSL_kRSA|SSL_aRSA|SSL_AES|SSL_SHA |SSL_TLSV1,
-	SSL_NOT_EXP|SSL_HIGH,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
 	0,
 	128,
 	128,
@@ -760,7 +760,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
 	TLS1_TXT_DH_DSS_WITH_AES_128_SHA,
 	TLS1_CK_DH_DSS_WITH_AES_128_SHA,
 	SSL_kDHd|SSL_aDH|SSL_AES|SSL_SHA|SSL_TLSV1,
-	SSL_NOT_EXP|SSL_HIGH,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
 	0,
 	128,
 	128,
@@ -773,7 +773,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
 	TLS1_TXT_DH_RSA_WITH_AES_128_SHA,
 	TLS1_CK_DH_RSA_WITH_AES_128_SHA,
 	SSL_kDHr|SSL_aDH|SSL_AES|SSL_SHA|SSL_TLSV1,
-	SSL_NOT_EXP|SSL_HIGH,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
 	0,
 	128,
 	128,
@@ -786,7 +786,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
 	TLS1_TXT_DHE_DSS_WITH_AES_128_SHA,
 	TLS1_CK_DHE_DSS_WITH_AES_128_SHA,
 	SSL_kEDH|SSL_aDSS|SSL_AES|SSL_SHA|SSL_TLSV1,
-	SSL_NOT_EXP|SSL_HIGH,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
 	0,
 	128,
 	128,
@@ -799,7 +799,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
 	TLS1_TXT_DHE_RSA_WITH_AES_128_SHA,
 	TLS1_CK_DHE_RSA_WITH_AES_128_SHA,
 	SSL_kEDH|SSL_aRSA|SSL_AES|SSL_SHA|SSL_TLSV1,
-	SSL_NOT_EXP|SSL_HIGH,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
 	0,
 	128,
 	128,
@@ -812,7 +812,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
 	TLS1_TXT_ADH_WITH_AES_128_SHA,
 	TLS1_CK_ADH_WITH_AES_128_SHA,
 	SSL_kEDH|SSL_aNULL|SSL_AES|SSL_SHA|SSL_TLSV1,
-	SSL_NOT_EXP|SSL_HIGH,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
 	0,
 	128,
 	128,
@@ -826,7 +826,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
 	TLS1_TXT_RSA_WITH_AES_256_SHA,
 	TLS1_CK_RSA_WITH_AES_256_SHA,
 	SSL_kRSA|SSL_aRSA|SSL_AES|SSL_SHA |SSL_TLSV1,
-	SSL_NOT_EXP|SSL_HIGH,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
 	0,
 	256,
 	256,
@@ -839,7 +839,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
 	TLS1_TXT_DH_DSS_WITH_AES_256_SHA,
 	TLS1_CK_DH_DSS_WITH_AES_256_SHA,
 	SSL_kDHd|SSL_aDH|SSL_AES|SSL_SHA|SSL_TLSV1,
-	SSL_NOT_EXP|SSL_HIGH,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
 	0,
 	256,
 	256,
@@ -852,7 +852,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
 	TLS1_TXT_DH_RSA_WITH_AES_256_SHA,
 	TLS1_CK_DH_RSA_WITH_AES_256_SHA,
 	SSL_kDHr|SSL_aDH|SSL_AES|SSL_SHA|SSL_TLSV1,
-	SSL_NOT_EXP|SSL_HIGH,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
 	0,
 	256,
 	256,
@@ -865,7 +865,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
 	TLS1_TXT_DHE_DSS_WITH_AES_256_SHA,
 	TLS1_CK_DHE_DSS_WITH_AES_256_SHA,
 	SSL_kEDH|SSL_aDSS|SSL_AES|SSL_SHA|SSL_TLSV1,
-	SSL_NOT_EXP|SSL_HIGH,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
 	0,
 	256,
 	256,
@@ -878,7 +878,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
 	TLS1_TXT_DHE_RSA_WITH_AES_256_SHA,
 	TLS1_CK_DHE_RSA_WITH_AES_256_SHA,
 	SSL_kEDH|SSL_aRSA|SSL_AES|SSL_SHA|SSL_TLSV1,
-	SSL_NOT_EXP|SSL_HIGH,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
 	0,
 	256,
 	256,
@@ -891,7 +891,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
 	TLS1_TXT_ADH_WITH_AES_256_SHA,
 	TLS1_CK_ADH_WITH_AES_256_SHA,
 	SSL_kEDH|SSL_aNULL|SSL_AES|SSL_SHA|SSL_TLSV1,
-	SSL_NOT_EXP|SSL_HIGH,
+	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
 	0,
 	256,
 	256,
diff --git a/src/lib/libssl/s3_pkt.c b/src/lib/libssl/s3_pkt.c
index 44c7c143fe..9476dcddf6 100644
--- a/src/lib/libssl/s3_pkt.c
+++ b/src/lib/libssl/s3_pkt.c
@@ -753,8 +753,15 @@ int ssl3_write_pending(SSL *s, int type, const unsigned char *buf,
 			s->rwstate=SSL_NOTHING;
 			return(s->s3->wpend_ret);
 			}
-		else if (i <= 0)
+		else if (i <= 0) {
+			if (s->version == DTLS1_VERSION ||
+			    s->version == DTLS1_BAD_VER) {
+				/* For DTLS, just drop it. That's kind of the whole
+				   point in using a datagram service */
+				s->s3->wbuf.left = 0;
+			}
 			return(i);
+		}
 		s->s3->wbuf.offset+=i;
 		s->s3->wbuf.left-=i;
 		}
@@ -1225,6 +1232,13 @@ int ssl3_do_change_cipher_spec(SSL *s)
 
 	if (s->s3->tmp.key_block == NULL)
 		{
+		if (s->session == NULL) 
+			{
+			/* might happen if dtls1_read_bytes() calls this */
+			SSLerr(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC,SSL_R_CCS_RECEIVED_EARLY);
+			return (0);
+			}
+
 		s->session->cipher=s->s3->tmp.new_cipher;
 		if (!s->method->ssl3_enc->setup_key_block(s)) return(0);
 		}
diff --git a/src/lib/libssl/s3_srvr.c b/src/lib/libssl/s3_srvr.c
index 903522ab59..80b45eb86f 100644
--- a/src/lib/libssl/s3_srvr.c
+++ b/src/lib/libssl/s3_srvr.c
@@ -902,22 +902,28 @@ int ssl3_get_client_hello(SSL *s)
 				break;
 				}
 			}
-		if (j == 0)
-			{
-			if ((s->options & SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) && (sk_SSL_CIPHER_num(ciphers) == 1))
-				{
-				/* Very bad for multi-threading.... */
-				s->session->cipher=sk_SSL_CIPHER_value(ciphers, 0);
-				}
-			else
+		if (j == 0 && (s->options & SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) && (sk_SSL_CIPHER_num(ciphers) == 1))
+			{
+			/* Special case as client bug workaround: the previously used cipher may
+			 * not be in the current list, the client instead might be trying to
+			 * continue using a cipher that before wasn't chosen due to server
+			 * preferences.  We'll have to reject the connection if the cipher is not
+			 * enabled, though. */
+			c = sk_SSL_CIPHER_value(ciphers, 0);
+			if (sk_SSL_CIPHER_find(SSL_get_ciphers(s), c) >= 0)
 				{
-				/* we need to have the cipher in the cipher
-				 * list if we are asked to reuse it */
-				al=SSL_AD_ILLEGAL_PARAMETER;
-				SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_REQUIRED_CIPHER_MISSING);
-				goto f_err;
+				s->session->cipher = c;
+				j = 1;
 				}
 			}
+		if (j == 0)
+			{
+			/* we need to have the cipher in the cipher
+			 * list if we are asked to reuse it */
+			al=SSL_AD_ILLEGAL_PARAMETER;
+			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_REQUIRED_CIPHER_MISSING);
+			goto f_err;
+			}
 		}
 
 	/* compression */
@@ -1172,13 +1178,13 @@ int ssl3_send_server_hello(SSL *s)
 		*(d++)=SSL3_MT_SERVER_HELLO;
 		l2n3(l,d);
 
-		s->state=SSL3_ST_CW_CLNT_HELLO_B;
+		s->state=SSL3_ST_SW_SRVR_HELLO_B;
 		/* number of bytes to write */
 		s->init_num=p-buf;
 		s->init_off=0;
 		}
 
-	/* SSL3_ST_CW_CLNT_HELLO_B */
+	/* SSL3_ST_SW_SRVR_HELLO_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 	}
 
@@ -1202,7 +1208,7 @@ int ssl3_send_server_done(SSL *s)
 		s->init_off=0;
 		}
 
-	/* SSL3_ST_CW_CLNT_HELLO_B */
+	/* SSL3_ST_SW_SRVR_DONE_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 	}
 
@@ -1540,6 +1546,8 @@ int ssl3_send_server_key_exchange(SSL *s)
 				j=0;
 				for (num=2; num > 0; num--)
 					{
+					EVP_MD_CTX_set_flags(&md_ctx,
+						EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
 					EVP_DigestInit_ex(&md_ctx,(num == 2)
 						?s->ctx->md5:s->ctx->sha1, NULL);
 					EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
@@ -2558,7 +2566,7 @@ int ssl3_get_client_certificate(SSL *s)
 	else
 		{
 		i=ssl_verify_cert_chain(s,sk);
-		if (!i)
+		if (i <= 0)
 			{
 			al=ssl_verify_alarm_type(s->verify_result);
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_NO_CERTIFICATE_RETURNED);
diff --git a/src/lib/libssl/ssl.h b/src/lib/libssl/ssl.h
index 6df921f3c1..ff8a128d3c 100644
--- a/src/lib/libssl/ssl.h
+++ b/src/lib/libssl/ssl.h
@@ -252,6 +252,7 @@ extern "C" {
 #define SSL_TXT_LOW		"LOW"
 #define SSL_TXT_MEDIUM		"MEDIUM"
 #define SSL_TXT_HIGH		"HIGH"
+#define SSL_TXT_FIPS		"FIPS"
 #define SSL_TXT_kFZA		"kFZA"
 #define	SSL_TXT_aFZA		"aFZA"
 #define SSL_TXT_eFZA		"eFZA"
@@ -361,9 +362,6 @@ typedef struct ssl_cipher_st
 
 DECLARE_STACK_OF(SSL_CIPHER)
 
-typedef struct ssl_st SSL;
-typedef struct ssl_ctx_st SSL_CTX;
-
 /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
 typedef struct ssl_method_st
 	{
@@ -760,6 +758,12 @@ struct ssl_ctx_st
 
 	int quiet_shutdown;
 
+#ifndef OPENSSL_ENGINE
+	/* Engine to pass requests for client certs to
+	 */
+	ENGINE *client_cert_engine;
+#endif
+
 #ifndef OPENSSL_NO_TLSEXT
 	/* TLS extensions servername callback */
 	int (*tlsext_servername_callback)(SSL*, int *, void *);
@@ -829,6 +833,9 @@ void SSL_CTX_set_info_callback(SSL_CTX *ctx, void (*cb)(const SSL *ssl,int type,
 void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl,int type,int val);
 void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, int (*client_cert_cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey));
 int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL *ssl, X509 **x509, EVP_PKEY **pkey);
+#ifndef OPENSSL_NO_ENGINE
+int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e);
+#endif
 void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx, int (*app_gen_cookie_cb)(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len));
 void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx, int (*app_verify_cookie_cb)(SSL *ssl, unsigned char *cookie, unsigned int cookie_len));
 
@@ -1702,6 +1709,7 @@ void ERR_load_SSL_strings(void);
 #define SSL_F_SSL3_CONNECT				 132
 #define SSL_F_SSL3_CTRL					 213
 #define SSL_F_SSL3_CTX_CTRL				 133
+#define SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC		 279
 #define SSL_F_SSL3_ENC					 134
 #define SSL_F_SSL3_GENERATE_KEY_BLOCK			 238
 #define SSL_F_SSL3_GET_CERTIFICATE_REQUEST		 135
@@ -1755,6 +1763,7 @@ void ERR_load_SSL_strings(void);
 #define SSL_F_SSL_CTX_CHECK_PRIVATE_KEY			 168
 #define SSL_F_SSL_CTX_NEW				 169
 #define SSL_F_SSL_CTX_SET_CIPHER_LIST			 269
+#define SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE		 278
 #define SSL_F_SSL_CTX_SET_PURPOSE			 226
 #define SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT		 219
 #define SSL_F_SSL_CTX_SET_SSL_VERSION			 170
@@ -1935,6 +1944,7 @@ void ERR_load_SSL_strings(void);
 #define SSL_R_NO_CIPHERS_SPECIFIED			 183
 #define SSL_R_NO_CIPHER_LIST				 184
 #define SSL_R_NO_CIPHER_MATCH				 185
+#define SSL_R_NO_CLIENT_CERT_METHOD			 317
 #define SSL_R_NO_CLIENT_CERT_RECEIVED			 186
 #define SSL_R_NO_COMPRESSION_SPECIFIED			 187
 #define SSL_R_NO_METHOD_SPECIFIED			 188
diff --git a/src/lib/libssl/ssl_asn1.c b/src/lib/libssl/ssl_asn1.c
index 6e14f4d834..0f9a3489dd 100644
--- a/src/lib/libssl/ssl_asn1.c
+++ b/src/lib/libssl/ssl_asn1.c
@@ -353,7 +353,7 @@ SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
 	memcpy(ret->session_id,os.data,os.length);
 
 	M_ASN1_D2I_get_x(ASN1_OCTET_STRING,osp,d2i_ASN1_OCTET_STRING);
-	if (ret->master_key_length > SSL_MAX_MASTER_KEY_LENGTH)
+	if (os.length > SSL_MAX_MASTER_KEY_LENGTH)
 		ret->master_key_length=SSL_MAX_MASTER_KEY_LENGTH;
 	else
 		ret->master_key_length=os.length;
diff --git a/src/lib/libssl/ssl_ciph.c b/src/lib/libssl/ssl_ciph.c
index 725f7f3c1f..0c2aa249b4 100644
--- a/src/lib/libssl/ssl_ciph.c
+++ b/src/lib/libssl/ssl_ciph.c
@@ -115,7 +115,10 @@
  */
 #include <stdio.h>
 #include <openssl/objects.h>
+#ifndef OPENSSL_NO_COMP
 #include <openssl/comp.h>
+#endif
+
 #include "ssl_locl.h"
 
 #define SSL_ENC_DES_IDX		0
@@ -222,6 +225,7 @@ static const SSL_CIPHER cipher_aliases[]={
 	{0,SSL_TXT_LOW,   0, 0,   SSL_LOW, 0,0,0,0,SSL_STRONG_MASK},
 	{0,SSL_TXT_MEDIUM,0, 0,SSL_MEDIUM, 0,0,0,0,SSL_STRONG_MASK},
 	{0,SSL_TXT_HIGH,  0, 0,  SSL_HIGH, 0,0,0,0,SSL_STRONG_MASK},
+	{0,SSL_TXT_FIPS,  0, 0,  SSL_FIPS, 0,0,0,0,SSL_FIPS|SSL_STRONG_NONE},
 	};
 
 void ssl_load_ciphers(void)
@@ -515,7 +519,12 @@ static void ssl_cipher_collect_ciphers(const SSL_METHOD *ssl_method,
 		c = ssl_method->get_cipher(i);
 #define IS_MASKED(c) ((c)->algorithms & (((c)->alg_bits == 256) ? m256 : mask))
 		/* drop those that use any of that is not available */
+#ifdef OPENSSL_FIPS
+		if ((c != NULL) && c->valid && !IS_MASKED(c)
+			&& (!FIPS_mode() || (c->algo_strength & SSL_FIPS)))
+#else
 		if ((c != NULL) && c->valid && !IS_MASKED(c))
+#endif
 			{
 			co_list[co_list_num].cipher = c;
 			co_list[co_list_num].next = NULL;
@@ -1054,7 +1063,11 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
 	 */
 	for (curr = head; curr != NULL; curr = curr->next)
 		{
+#ifdef OPENSSL_FIPS
+		if (curr->active && (!FIPS_mode() || curr->cipher->algo_strength & SSL_FIPS))
+#else
 		if (curr->active)
+#endif
 			{
 			sk_SSL_CIPHER_push(cipherstack, curr->cipher);
 #ifdef CIPHER_DEBUG
diff --git a/src/lib/libssl/ssl_err.c b/src/lib/libssl/ssl_err.c
index 50779c1632..24a994fe01 100644
--- a/src/lib/libssl/ssl_err.c
+++ b/src/lib/libssl/ssl_err.c
@@ -1,6 +1,6 @@
 /* ssl/ssl_err.c */
 /* ====================================================================
- * Copyright (c) 1999-2007 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-2008 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -138,6 +138,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
 {ERR_FUNC(SSL_F_SSL3_CONNECT),	"SSL3_CONNECT"},
 {ERR_FUNC(SSL_F_SSL3_CTRL),	"SSL3_CTRL"},
 {ERR_FUNC(SSL_F_SSL3_CTX_CTRL),	"SSL3_CTX_CTRL"},
+{ERR_FUNC(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC),	"SSL3_DO_CHANGE_CIPHER_SPEC"},
 {ERR_FUNC(SSL_F_SSL3_ENC),	"SSL3_ENC"},
 {ERR_FUNC(SSL_F_SSL3_GENERATE_KEY_BLOCK),	"SSL3_GENERATE_KEY_BLOCK"},
 {ERR_FUNC(SSL_F_SSL3_GET_CERTIFICATE_REQUEST),	"SSL3_GET_CERTIFICATE_REQUEST"},
@@ -191,6 +192,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
 {ERR_FUNC(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY),	"SSL_CTX_check_private_key"},
 {ERR_FUNC(SSL_F_SSL_CTX_NEW),	"SSL_CTX_new"},
 {ERR_FUNC(SSL_F_SSL_CTX_SET_CIPHER_LIST),	"SSL_CTX_set_cipher_list"},
+{ERR_FUNC(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE),	"SSL_CTX_set_client_cert_engine"},
 {ERR_FUNC(SSL_F_SSL_CTX_SET_PURPOSE),	"SSL_CTX_set_purpose"},
 {ERR_FUNC(SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT),	"SSL_CTX_set_session_id_context"},
 {ERR_FUNC(SSL_F_SSL_CTX_SET_SSL_VERSION),	"SSL_CTX_set_ssl_version"},
@@ -374,6 +376,7 @@ static ERR_STRING_DATA SSL_str_reasons[]=
 {ERR_REASON(SSL_R_NO_CIPHERS_SPECIFIED)  ,"no ciphers specified"},
 {ERR_REASON(SSL_R_NO_CIPHER_LIST)        ,"no cipher list"},
 {ERR_REASON(SSL_R_NO_CIPHER_MATCH)       ,"no cipher match"},
+{ERR_REASON(SSL_R_NO_CLIENT_CERT_METHOD) ,"no client cert method"},
 {ERR_REASON(SSL_R_NO_CLIENT_CERT_RECEIVED),"no client cert received"},
 {ERR_REASON(SSL_R_NO_COMPRESSION_SPECIFIED),"no compression specified"},
 {ERR_REASON(SSL_R_NO_METHOD_SPECIFIED)   ,"no method specified"},
diff --git a/src/lib/libssl/ssl_lib.c b/src/lib/libssl/ssl_lib.c
index 065411aea8..68eee77e6f 100644
--- a/src/lib/libssl/ssl_lib.c
+++ b/src/lib/libssl/ssl_lib.c
@@ -130,6 +130,9 @@
 #ifndef OPENSSL_NO_DH
 #include <openssl/dh.h>
 #endif
+#ifndef OPENSSL_NO_ENGINE
+#include <openssl/engine.h>
+#endif
 
 const char *SSL_version_str=OPENSSL_VERSION_TEXT;
 
@@ -1393,6 +1396,14 @@ SSL_CTX *SSL_CTX_new(SSL_METHOD *meth)
 		return(NULL);
 		}
 
+#ifdef OPENSSL_FIPS
+	if (FIPS_mode() && (meth->version < TLS1_VERSION))	
+		{
+		SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE);
+		return NULL;
+		}
+#endif
+
 	if (SSL_get_ex_data_X509_STORE_CTX_idx() < 0)
 		{
 		SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_X509_VERIFICATION_SETUP_PROBLEMS);
@@ -1511,6 +1522,27 @@ SSL_CTX *SSL_CTX_new(SSL_METHOD *meth)
 	ret->tlsext_status_cb = 0;
 	ret->tlsext_status_arg = NULL;
 
+#endif
+
+#ifndef OPENSSL_NO_ENGINE
+	ret->client_cert_engine = NULL;
+#ifdef OPENSSL_SSL_CLIENT_ENGINE_AUTO
+#define eng_strx(x)	#x
+#define eng_str(x)	eng_strx(x)
+	/* Use specific client engine automatically... ignore errors */
+	{
+	ENGINE *eng;
+	eng = ENGINE_by_id(eng_str(OPENSSL_SSL_CLIENT_ENGINE_AUTO));
+	if (!eng)
+		{
+		ERR_clear_error();
+		ENGINE_load_builtin_engines();
+		eng = ENGINE_by_id(eng_str(OPENSSL_SSL_CLIENT_ENGINE_AUTO));
+		}
+	if (!eng || !SSL_CTX_set_client_cert_engine(ret, eng))
+		ERR_clear_error();
+	}
+#endif
 #endif
 
 	return(ret);
@@ -1582,6 +1614,10 @@ void SSL_CTX_free(SSL_CTX *a)
 		sk_SSL_COMP_pop_free(a->comp_methods,SSL_COMP_free);
 #else
 	a->comp_methods = NULL;
+#endif
+#ifndef OPENSSL_NO_ENGINE
+	if (a->client_cert_engine)
+		ENGINE_finish(a->client_cert_engine);
 #endif
 	OPENSSL_free(a);
 	}
diff --git a/src/lib/libssl/ssl_locl.h b/src/lib/libssl/ssl_locl.h
index de94c0d0c7..ed4ddbbae6 100644
--- a/src/lib/libssl/ssl_locl.h
+++ b/src/lib/libssl/ssl_locl.h
@@ -124,7 +124,9 @@
 #include "e_os.h"
 
 #include <openssl/buffer.h>
+#ifndef OPENSSL_NO_COMP
 #include <openssl/comp.h>
+#endif
 #include <openssl/bio.h>
 #include <openssl/stack.h>
 #ifndef OPENSSL_NO_RSA
@@ -330,8 +332,9 @@
 #define SSL_LOW			0x00000020L
 #define SSL_MEDIUM		0x00000040L
 #define SSL_HIGH		0x00000080L
+#define SSL_FIPS		0x00000100L
 
-/* we have used 000000ff - 24 bits left to go */
+/* we have used 000001ff - 23 bits left to go */
 
 /*
  * Macros to check the export status and cipher strength for export ciphers.
@@ -499,6 +502,7 @@ typedef struct ssl3_enc_method
 	int (*alert_value)(int);
 	} SSL3_ENC_METHOD;
 
+#ifndef OPENSSL_NO_COMP
 /* Used for holding the relevant compression methods loaded into SSL_CTX */
 typedef struct ssl3_comp_st
 	{
@@ -506,6 +510,7 @@ typedef struct ssl3_comp_st
 	char *name;	/* Text name used for the compression type */
 	COMP_METHOD *method; /* The method :-) */
 	} SSL3_COMP;
+#endif
 
 extern SSL3_ENC_METHOD ssl3_undef_enc_method;
 OPENSSL_EXTERN SSL_CIPHER ssl2_ciphers[];
@@ -874,6 +879,7 @@ int ssl3_get_new_session_ticket(SSL *s);
 int ssl3_get_cert_status(SSL *s);
 int ssl3_get_server_done(SSL *s);
 int ssl3_send_client_verify(SSL *s);
+int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey);
 int ssl3_send_client_certificate(SSL *s);
 int ssl3_send_client_key_exchange(SSL *s);
 int ssl3_get_key_exchange(SSL *s);
diff --git a/src/lib/libssl/ssl_sess.c b/src/lib/libssl/ssl_sess.c
index ee88be2b88..8391d62212 100644
--- a/src/lib/libssl/ssl_sess.c
+++ b/src/lib/libssl/ssl_sess.c
@@ -59,6 +59,9 @@
 #include <stdio.h>
 #include <openssl/lhash.h>
 #include <openssl/rand.h>
+#ifndef OPENSSL_NO_ENGINE
+#include <openssl/engine.h>
+#endif
 #include "ssl_locl.h"
 
 static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s);
@@ -870,6 +873,25 @@ int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL * ssl, X509 ** x509 , EVP_PK
 	return ctx->client_cert_cb;
 	}
 
+#ifndef OPENSSL_NO_ENGINE
+int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e)
+	{
+	if (!ENGINE_init(e))
+		{
+		SSLerr(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE, ERR_R_ENGINE_LIB);
+		return 0;
+		}
+	if(!ENGINE_get_ssl_client_cert_function(e))
+		{
+		SSLerr(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE, SSL_R_NO_CLIENT_CERT_METHOD);
+		ENGINE_finish(e);
+		return 0;
+		}
+	ctx->client_cert_engine = e;
+	return 1;
+	}
+#endif
+
 void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx,
 	int (*cb)(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len))
 	{
diff --git a/src/lib/libssl/t1_enc.c b/src/lib/libssl/t1_enc.c
index ed5a4a7255..7cb3e29a41 100644
--- a/src/lib/libssl/t1_enc.c
+++ b/src/lib/libssl/t1_enc.c
@@ -111,10 +111,15 @@
 
 #include <stdio.h>
 #include "ssl_locl.h"
+#ifndef OPENSSL_NO_COMP
 #include <openssl/comp.h>
+#endif
 #include <openssl/evp.h>
 #include <openssl/hmac.h>
 #include <openssl/md5.h>
+#ifdef KSSL_DEBUG
+#include <openssl/des.h>
+#endif
 
 static void tls1_P_hash(const EVP_MD *md, const unsigned char *sec,
 			int sec_len, unsigned char *seed, int seed_len,
@@ -131,6 +136,8 @@ static void tls1_P_hash(const EVP_MD *md, const unsigned char *sec,
 
 	HMAC_CTX_init(&ctx);
 	HMAC_CTX_init(&ctx_tmp);
+	HMAC_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
+	HMAC_CTX_set_flags(&ctx_tmp, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
 	HMAC_Init_ex(&ctx,sec,sec_len,md, NULL);
 	HMAC_Init_ex(&ctx_tmp,sec,sec_len,md, NULL);
 	HMAC_Update(&ctx,seed,seed_len);
@@ -249,15 +256,15 @@ int tls1_change_cipher_state(SSL *s, int which)
 #ifdef KSSL_DEBUG
 	printf("tls1_change_cipher_state(which= %d) w/\n", which);
 	printf("\talg= %ld, comp= %p\n", s->s3->tmp.new_cipher->algorithms,
-                comp);
-	printf("\tevp_cipher == %p ==? &d_cbc_ede_cipher3\n", c);
+                (void *)comp);
+	printf("\tevp_cipher == %p ==? &d_cbc_ede_cipher3\n", (void *)c);
 	printf("\tevp_cipher: nid, blksz= %d, %d, keylen=%d, ivlen=%d\n",
                 c->nid,c->block_size,c->key_len,c->iv_len);
 	printf("\tkey_block: len= %d, data= ", s->s3->tmp.key_block_length);
 	{
-        int i;
-        for (i=0; i<s->s3->tmp.key_block_length; i++)
-		printf("%02x", key_block[i]);  printf("\n");
+        int ki;
+        for (ki=0; ki<s->s3->tmp.key_block_length; ki++)
+		printf("%02x", key_block[ki]);  printf("\n");
         }
 #endif	/* KSSL_DEBUG */
 
@@ -413,11 +420,13 @@ printf("which = %04X\nmac key=",which);
 	s->session->key_arg_length=0;
 #ifdef KSSL_DEBUG
 	{
-        int i;
+        int ki;
 	printf("EVP_CipherInit_ex(dd,c,key=,iv=,which)\n");
-	printf("\tkey= "); for (i=0; i<c->key_len; i++) printf("%02x", key[i]);
+	printf("\tkey= ");
+	for (ki=0; ki<c->key_len; ki++) printf("%02x", key[ki]);
 	printf("\n");
-	printf("\t iv= "); for (i=0; i<c->iv_len; i++) printf("%02x", iv[i]);
+	printf("\t iv= ");
+	for (ki=0; ki<c->iv_len; ki++) printf("%02x", iv[ki]);
 	printf("\n");
 	}
 #endif	/* KSSL_DEBUG */
@@ -590,10 +599,11 @@ int tls1_enc(SSL *s, int send)
 		{
                 unsigned long ui;
 		printf("EVP_Cipher(ds=%p,rec->data=%p,rec->input=%p,l=%ld) ==>\n",
-                        ds,rec->data,rec->input,l);
-		printf("\tEVP_CIPHER_CTX: %d buf_len, %d key_len [%d %d], %d iv_len\n",
+                        (void *)ds,rec->data,rec->input,l);
+		printf("\tEVP_CIPHER_CTX: %d buf_len, %d key_len [%ld %ld], %d iv_len\n",
                         ds->buf_len, ds->cipher->key_len,
-                        DES_KEY_SZ, DES_SCHEDULE_SZ,
+                        (unsigned long)DES_KEY_SZ,
+			(unsigned long)DES_SCHEDULE_SZ,
                         ds->cipher->iv_len);
 		printf("\t\tIV: ");
 		for (i=0; i<ds->cipher->iv_len; i++) printf("%02X", ds->iv[i]);
@@ -618,10 +628,10 @@ int tls1_enc(SSL *s, int send)
 
 #ifdef KSSL_DEBUG
 		{
-                unsigned long i;
+                unsigned long ki;
                 printf("\trec->data=");
-		for (i=0; i<l; i++)
-                        printf(" %02x", rec->data[i]);  printf("\n");
+		for (ki=0; ki<l; i++)
+                        printf(" %02x", rec->data[ki]);  printf("\n");
                 }
 #endif	/* KSSL_DEBUG */
 
@@ -805,7 +815,7 @@ int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
 	unsigned char buff[SSL_MAX_MASTER_KEY_LENGTH];
 
 #ifdef KSSL_DEBUG
-	printf ("tls1_generate_master_secret(%p,%p, %p, %d)\n", s,out, p,len);
+	printf ("tls1_generate_master_secret(%p,%p, %p, %d)\n", (void *)s,out, p,len);
 #endif	/* KSSL_DEBUG */
 
 	/* Setup the stuff to munge */
@@ -852,8 +862,10 @@ int tls1_alert_code(int code)
 	case SSL_AD_INTERNAL_ERROR:	return(TLS1_AD_INTERNAL_ERROR);
 	case SSL_AD_USER_CANCELLED:	return(TLS1_AD_USER_CANCELLED);
 	case SSL_AD_NO_RENEGOTIATION:	return(TLS1_AD_NO_RENEGOTIATION);
+#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
 	case DTLS1_AD_MISSING_HANDSHAKE_MESSAGE: return 
 					  (DTLS1_AD_MISSING_HANDSHAKE_MESSAGE);
+#endif
 	default:			return(-1);
 		}
 	}
diff --git a/src/lib/libssl/t1_lib.c b/src/lib/libssl/t1_lib.c
index 35f04afa4a..9ce726996d 100644
--- a/src/lib/libssl/t1_lib.c
+++ b/src/lib/libssl/t1_lib.c
@@ -734,6 +734,13 @@ int tls1_process_ticket(SSL *s, unsigned char *session_id, int len,
 	/* Point after session ID in client hello */
 	const unsigned char *p = session_id + len;
 	unsigned short i;
+
+	/* If tickets disabled behave as if no ticket present
+ 	 * to permit stateful resumption.
+ 	 */
+	if (SSL_get_options(s) & SSL_OP_NO_TICKET)
+		return 1;
+
 	if ((s->version <= SSL3_VERSION) || !limit)
 		return 1;
 	if (p >= limit)
@@ -761,12 +768,7 @@ int tls1_process_ticket(SSL *s, unsigned char *session_id, int len,
 			return 1;
 		if (type == TLSEXT_TYPE_session_ticket)
 			{
-			/* If tickets disabled indicate cache miss which will
- 			 * trigger a full handshake
- 			 */
-			if (SSL_get_options(s) & SSL_OP_NO_TICKET)
-				return 0;
-			/* If zero length not client will accept a ticket
+			/* If zero length note client will accept a ticket
  			 * and indicate cache miss to trigger full handshake
  			 */
 			if (size == 0)
diff --git a/src/lib/libssl/test/CAss.cnf b/src/lib/libssl/test/CAss.cnf
index 20f8f05e3d..546e660626 100644
--- a/src/lib/libssl/test/CAss.cnf
+++ b/src/lib/libssl/test/CAss.cnf
@@ -7,7 +7,7 @@ RANDFILE		= ./.rnd
 
 ####################################################################
 [ req ]
-default_bits		= 512
+default_bits		= 1024
 default_keyfile 	= keySS.pem
 distinguished_name	= req_distinguished_name
 encrypt_rsa_key		= no
diff --git a/src/lib/libssl/test/Uss.cnf b/src/lib/libssl/test/Uss.cnf
index 0c0ebb5f67..98b2e054b7 100644
--- a/src/lib/libssl/test/Uss.cnf
+++ b/src/lib/libssl/test/Uss.cnf
@@ -7,7 +7,7 @@ RANDFILE		= ./.rnd
 
 ####################################################################
 [ req ]
-default_bits		= 512
+default_bits		= 1024
 default_keyfile 	= keySS.pem
 distinguished_name	= req_distinguished_name
 encrypt_rsa_key		= no
-- 
cgit v1.2.3-55-g6feb