[Pkg-openssl-changes] r372 - in openssl/branches/upstream/current: . apps crypto crypto/aes crypto/aes/asm crypto/asn1 crypto/bio crypto/bn crypto/des crypto/des/asm crypto/dh crypto/dsa crypto/engine crypto/evp crypto/md2 crypto/md4 crypto/md5 crypto/ocsp crypto/pem crypto/perlasm crypto/pkcs7 crypto/rand crypto/ripemd crypto/rsa crypto/sha crypto/x509v3 engines ssl

Kurt Roeckx kroeckx at alioth.debian.org
Sat May 16 15:25:35 UTC 2009


Author: kroeckx
Date: 2009-05-16 15:25:35 +0000 (Sat, 16 May 2009)
New Revision: 372

Added:
   openssl/branches/upstream/current/apps/CA.sh
   openssl/branches/upstream/current/apps/s_time.c
   openssl/branches/upstream/current/apps/speed.c
   openssl/branches/upstream/current/apps/spkac.c
   openssl/branches/upstream/current/apps/verify.c
   openssl/branches/upstream/current/apps/x509.c
   openssl/branches/upstream/current/crypto/aes/
   openssl/branches/upstream/current/crypto/aes/asm/
   openssl/branches/upstream/current/crypto/aes/asm/aes-586.pl
   openssl/branches/upstream/current/crypto/asn1/asn1_err.c
   openssl/branches/upstream/current/crypto/des/
   openssl/branches/upstream/current/crypto/des/asm/
   openssl/branches/upstream/current/crypto/des/asm/desboth.pl
   openssl/branches/upstream/current/crypto/engine/
   openssl/branches/upstream/current/crypto/engine/eng_table.c
   openssl/branches/upstream/current/crypto/perlasm/
   openssl/branches/upstream/current/crypto/perlasm/cbc.pl
   openssl/branches/upstream/current/crypto/perlasm/x86unix.pl
   openssl/branches/upstream/current/crypto/x509v3/v3_utl.c
   openssl/branches/upstream/current/crypto/x86cpuid.pl
   openssl/branches/upstream/current/ssl/s2_srvr.c
   openssl/branches/upstream/current/ssl/s3_clnt.c
   openssl/branches/upstream/current/ssl/ssltest.c
   openssl/branches/upstream/current/ssl/t1_lib.c
Removed:
   openssl/branches/upstream/current/crypto/md5/asm/
Modified:
   openssl/branches/upstream/current/Configure
   openssl/branches/upstream/current/Makefile.org
   openssl/branches/upstream/current/Makefile.shared
   openssl/branches/upstream/current/config
   openssl/branches/upstream/current/crypto/Makefile
   openssl/branches/upstream/current/crypto/asn1/asn1.h
   openssl/branches/upstream/current/crypto/asn1/tasn_dec.c
   openssl/branches/upstream/current/crypto/bio/bio.h
   openssl/branches/upstream/current/crypto/bn/bn_mont.c
   openssl/branches/upstream/current/crypto/dh/dh.h
   openssl/branches/upstream/current/crypto/dh/dh_err.c
   openssl/branches/upstream/current/crypto/dh/dh_key.c
   openssl/branches/upstream/current/crypto/dsa/dsa.h
   openssl/branches/upstream/current/crypto/dsa/dsa_err.c
   openssl/branches/upstream/current/crypto/dsa/dsa_ossl.c
   openssl/branches/upstream/current/crypto/evp/evp.h
   openssl/branches/upstream/current/crypto/evp/evp_lib.c
   openssl/branches/upstream/current/crypto/md2/md2.h
   openssl/branches/upstream/current/crypto/md4/md4.h
   openssl/branches/upstream/current/crypto/md5/md5.h
   openssl/branches/upstream/current/crypto/ocsp/ocsp.h
   openssl/branches/upstream/current/crypto/pem/pem.h
   openssl/branches/upstream/current/crypto/pkcs7/pk7_mime.c
   openssl/branches/upstream/current/crypto/rand/md_rand.c
   openssl/branches/upstream/current/crypto/ripemd/ripemd.h
   openssl/branches/upstream/current/crypto/rsa/rsa.h
   openssl/branches/upstream/current/crypto/rsa/rsa_eay.c
   openssl/branches/upstream/current/crypto/rsa/rsa_err.c
   openssl/branches/upstream/current/crypto/rsa/rsa_sign.c
   openssl/branches/upstream/current/crypto/sha/sha.h
   openssl/branches/upstream/current/crypto/x509v3/pcy_tree.c
   openssl/branches/upstream/current/crypto/x86_64cpuid.pl
   openssl/branches/upstream/current/engines/Makefile
   openssl/branches/upstream/current/ssl/s2_clnt.c
   openssl/branches/upstream/current/ssl/s3_srvr.c
   openssl/branches/upstream/current/ssl/ssl.h
   openssl/branches/upstream/current/ssl/ssl_lib.c
   openssl/branches/upstream/current/ssl/t1_enc.c
Log:
[svn-upgrade] Integrating new upstream version, openssl (0.9.8k)

Modified: openssl/branches/upstream/current/Configure
===================================================================
--- openssl/branches/upstream/current/Configure	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/Configure	2009-05-16 15:25:35 UTC (rev 372)
@@ -6,11 +6,13 @@
 ##
 
 require 5.000;
-use strict;
+eval 'use strict;';
 
+print STDERR "Warning: perl module strict not found.\n" if ($@);
+
 # see INSTALL for instructions.
 
-my $usage="Usage: Configure [no-<cipher> ...] [enable-<cipher> ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-dso] [no-krb5] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]\n";
+my $usage="Usage: Configure [no-<cipher> ...] [enable-<cipher> ...] [experimental-<cipher> ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [enable-montasm] [no-asm] [no-dso] [no-krb5] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]\n";
 
 # Options:
 #
@@ -54,6 +56,8 @@
 # [no-]zlib     [don't] compile support for zlib compression.
 # zlib-dynamic	Like "zlib", but the zlib library is expected to be a shared
 #		library and will be loaded in run-time by the OpenSSL library.
+# enable-montasm 0.9.8 branch only: enable Montgomery x86 assembler backport
+#               from 0.9.9
 # 386           generate 80386 code
 # no-sse2	disables IA-32 SSE2 code, above option implies no-sse2
 # no-<cipher>   build without specified algorithm (rsa, idea, rc5, ...)
@@ -97,6 +101,11 @@
 # SHA512_ASM	sha512_block is implemented in assembler
 # AES_ASM	ASE_[en|de]crypt is implemented in assembler
 
+# Minimum warning options... any contributions to OpenSSL should at least get
+# past these. 
+
+my $gcc_devteam_warn = "-Wall -pedantic -DPEDANTIC -Wno-long-long -Wsign-compare -Wmissing-prototypes -Wshadow -Wformat -Werror -DCRYPTO_MDEBUG_ALL -DCRYPTO_MDEBUG_ABORT -DREF_CHECK -DOPENSSL_NO_DEPRECATED";
+
 my $x86_gcc_des="DES_PTR DES_RISC1 DES_UNROLL";
 
 # MD2_CHAR slags pentium pros
@@ -114,12 +123,12 @@
 my $bits1="THIRTY_TWO_BIT ";
 my $bits2="SIXTY_FOUR_BIT ";
 
-my $x86_elf_asm="x86cpuid-elf.o:bn86-elf.o co86-elf.o:dx86-elf.o yx86-elf.o:ax86-elf.o:bx86-elf.o:mx86-elf.o:sx86-elf.o s512sse2-elf.o:cx86-elf.o:rx86-elf.o:rm86-elf.o:r586-elf.o";
-my $x86_coff_asm="x86cpuid-cof.o:bn86-cof.o co86-cof.o:dx86-cof.o yx86-cof.o:ax86-cof.o:bx86-cof.o:mx86-cof.o:sx86-cof.o s512sse2-cof.o:cx86-cof.o:rx86-cof.o:rm86-cof.o:r586-cof.o";
-my $x86_out_asm="x86cpuid-out.o:bn86-out.o co86-out.o:dx86-out.o yx86-out.o:ax86-out.o:bx86-out.o:mx86-out.o:sx86-out.o s512sse2-out.o:cx86-out.o:rx86-out.o:rm86-out.o:r586-out.o";
+my $x86_elf_asm="x86cpuid-elf.o:bn86-elf.o co86-elf.o MAYBE-MO86-elf.o:dx86-elf.o yx86-elf.o:ax86-elf.o:bx86-elf.o:mx86-elf.o:sx86-elf.o s512sse2-elf.o:cx86-elf.o:rx86-elf.o rc4_skey.o:rm86-elf.o:r586-elf.o";
+my $x86_coff_asm="x86cpuid-cof.o:bn86-cof.o co86-cof.o MAYBE-MO86-cof.o:dx86-cof.o yx86-cof.o:ax86-cof.o:bx86-cof.o:mx86-cof.o:sx86-cof.o s512sse2-cof.o:cx86-cof.o:rx86-cof.o rc4_skey.o:rm86-cof.o:r586-cof.o";
+my $x86_out_asm="x86cpuid-out.o:bn86-out.o co86-out.o MAYBE-MO86-out.o:dx86-out.o yx86-out.o:ax86-out.o:bx86-out.o:mx86-out.o:sx86-out.o s512sse2-out.o:cx86-out.o:rx86-out.o rc4_skey.o:rm86-out.o:r586-out.o";
 
-my $x86_64_asm="x86_64cpuid.o:x86_64-gcc.o::::md5-x86_64.o:::rc4-x86_64.o::";
-my $ia64_asm=":bn-ia64.o::aes_core.o aes_cbc.o aes-ia64.o:::sha1-ia64.o sha256-ia64.o sha512-ia64.o::rc4-ia64.o::";
+my $x86_64_asm="x86_64cpuid.o:x86_64-gcc.o x86_64-mont.o::aes-x86_64.o::md5-x86_64.o:sha1-x86_64.o sha256-x86_64.o sha512-x86_64.o::rc4-x86_64.o::";
+my $ia64_asm=":bn-ia64.o::aes_core.o aes_cbc.o aes-ia64.o:::sha1-ia64.o sha256-ia64.o sha512-ia64.o::rc4-ia64.o rc4_skey.o::";
 
 my $no_asm="::::::::::";
 
@@ -150,11 +159,14 @@
 "debug-ben",	"gcc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_CTX_DEBUG -DCRYPTO_MDEBUG -DPEDANTIC -DDEBUG_SAFESTACK -O2 -pedantic -Wall -Wshadow -Werror -pipe::(unknown):::::bn86-elf.o co86-elf.o",
 "debug-ben-openbsd","gcc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_CTX_DEBUG -DCRYPTO_MDEBUG -DPEDANTIC -DDEBUG_SAFESTACK -DOPENSSL_OPENBSD_DEV_CRYPTO -DOPENSSL_NO_ASM -O2 -pedantic -Wall -Wshadow -Werror -pipe::(unknown)::::",
 "debug-ben-openbsd-debug","gcc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_CTX_DEBUG -DCRYPTO_MDEBUG -DPEDANTIC -DDEBUG_SAFESTACK -DOPENSSL_OPENBSD_DEV_CRYPTO -DOPENSSL_NO_ASM -g3 -O2 -pedantic -Wall -Wshadow -Werror -pipe::(unknown)::::",
-"debug-ben-debug",	"gcc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_CTX_DEBUG -DCRYPTO_MDEBUG -DPEDANTIC -DDEBUG_SAFESTACK -g3 -O2 -pedantic -Wall -Wshadow -Werror -pipe::(unknown)::::::",
+"debug-ben-debug",	"gcc:$gcc_devteam_warn -DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_CTX_DEBUG  -DDEBUG_SAFESTACK -g3 -O2 -pipe::(unknown)::::::",
 "debug-ben-strict",	"gcc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_CTX_DEBUG -DCRYPTO_MDEBUG -DCONST_STRICT -O2 -Wall -Wshadow -Werror -Wpointer-arith -Wcast-qual -Wwrite-strings -pipe::(unknown)::::::",
 "debug-rse","cc:-DTERMIOS -DL_ENDIAN -pipe -O -g -ggdb3 -Wall::(unknown):::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}",
-"debug-bodo",	"gcc:-DL_ENDIAN -DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DBIO_PAIR_DEBUG -DPEDANTIC -g -march=i486 -pedantic -Wshadow -Wall::-D_REENTRANT:::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}",
+"debug-bodo",	"gcc:-DL_ENDIAN -DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DBIO_PAIR_DEBUG -DPEDANTIC -g -march=i486 -pedantic -Wshadow -Wall -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wno-long-long -Wundef -Wconversion -pipe::-D_REENTRANT:::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}",
 "debug-ulf", "gcc:-DTERMIOS -DL_ENDIAN -march=i486 -Wall -DBN_DEBUG -DBN_DEBUG_RAND -DREF_CHECK -DCONF_DEBUG -DBN_CTX_DEBUG -DCRYPTO_MDEBUG -DOPENSSL_NO_ASM -g -Wformat -Wshadow -Wmissing-prototypes -Wmissing-declarations:::CYGWIN32:::${no_asm}:win32:cygwin-shared:::.dll",
+"debug-steve64", "gcc:$gcc_devteam_warn -m64 -DL_ENDIAN -DTERMIO -DCONF_DEBUG -DDEBUG_SAFESTACK -g -DMD32_REG_T=int::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK BF_PTR2 DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"debug-steve32", "gcc:$gcc_devteam_warn -m32 -DL_ENDIAN -DCONF_DEBUG -DDEBUG_SAFESTACK -g -pipe::-D_REENTRANT::-rdynamic -ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC:-m32:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"debug-steve-opt", "gcc:$gcc_devteam_warn -m64 -O3 -DL_ENDIAN -DTERMIO -DCONF_DEBUG -DDEBUG_SAFESTACK -g -DMD32_REG_T=int::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK BF_PTR2 DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
 "debug-steve",	"gcc:-DL_ENDIAN -DREF_CHECK -DCONF_DEBUG -DDEBUG_SAFESTACK -DCRYPTO_MDEBUG_ALL -DPEDANTIC -m32 -g -pedantic -Wno-long-long -Wall -Werror -Wshadow -pipe::-D_REENTRANT::-rdynamic -ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared",
 "debug-steve-linux-pseudo64",	"gcc:-DL_ENDIAN -DREF_CHECK -DCONF_DEBUG -DBN_CTX_DEBUG -DDEBUG_SAFESTACK -DCRYPTO_MDEBUG_ALL -DOPENSSL_NO_ASM -g -mcpu=i486 -Wall -Werror -Wshadow -pipe::-D_REENTRANT::-rdynamic -ldl:SIXTY_FOUR_BIT:${no_asm}:dlfcn:linux-shared",
 "debug-levitte-linux-elf","gcc:-DLEVITTE_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_DEBUG -DBN_DEBUG_RAND -DCRYPTO_MDEBUG -DENGINE_CONF_DEBUG -DL_ENDIAN -DTERMIO -D_POSIX_SOURCE -DPEDANTIC -ggdb -g3 -mcpu=i486 -pedantic -ansi -Wall -Wshadow -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wno-long-long -Wundef -Wconversion -pipe::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
@@ -201,11 +213,11 @@
 "solaris-sparcv7-gcc","gcc:-O3 -fomit-frame-pointer -Wall -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT::-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR:${no_asm}:dlfcn:solaris-shared:-fPIC:-shared:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
 "solaris-sparcv8-gcc","gcc:-mv8 -O3 -fomit-frame-pointer -Wall -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT::-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR::sparcv8.o:des_enc-sparc.o fcrypt_b.o:::::::::dlfcn:solaris-shared:-fPIC:-shared:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
 # -m32 should be safe to add as long as driver recognizes -mcpu=ultrasparc
-"solaris-sparcv9-gcc","gcc:-m32 -mcpu=ultrasparc -O3 -fomit-frame-pointer -Wall -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR::sparcv8plus.o:des_enc-sparc.o fcrypt_b.o:::md5-sparcv8plus.o::::::dlfcn:solaris-shared:-fPIC:-shared:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
-"solaris64-sparcv9-gcc","gcc:-m64 -mcpu=ultrasparc -O3 -Wall -DB_ENDIAN::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_PTR DES_RISC1 DES_UNROLL BF_PTR:::des_enc-sparc.o fcrypt_b.o:::md5-sparcv9.o::::::dlfcn:solaris-shared:-fPIC:-m64 -shared:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"solaris-sparcv9-gcc","gcc:-m32 -mcpu=ultrasparc -O3 -fomit-frame-pointer -Wall -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR::sparcv8plus.o:des_enc-sparc.o fcrypt_b.o:::::::::dlfcn:solaris-shared:-fPIC:-shared:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"solaris64-sparcv9-gcc","gcc:-m64 -mcpu=ultrasparc -O3 -Wall -DB_ENDIAN::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_PTR DES_RISC1 DES_UNROLL BF_PTR:::des_enc-sparc.o fcrypt_b.o:::::::::dlfcn:solaris-shared:-fPIC:-m64 -shared:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
 ####
 "debug-solaris-sparcv8-gcc","gcc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG_ALL -O -g -mv8 -Wall -DB_ENDIAN::-D_REENTRANT::-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR::sparcv8.o::::::::::dlfcn:solaris-shared:-fPIC:-shared:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
-"debug-solaris-sparcv9-gcc","gcc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG_ALL -DPEDANTIC -O -g -mcpu=ultrasparc -pedantic -ansi -Wall -Wshadow -Wno-long-long -D__EXTENSIONS__ -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR::sparcv8plus.o:des_enc-sparc.o fcrypt_b.o:::md5-sparcv8plus.o::::::dlfcn:solaris-shared:-fPIC:-shared:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"debug-solaris-sparcv9-gcc","gcc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG_ALL -DPEDANTIC -O -g -mcpu=ultrasparc -pedantic -ansi -Wall -Wshadow -Wno-long-long -D__EXTENSIONS__ -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR::sparcv8plus.o:des_enc-sparc.o fcrypt_b.o:::::::::dlfcn:solaris-shared:-fPIC:-shared:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
 
 #### SPARC Solaris with Sun C setups
 # SC4.0 doesn't pass 'make test', upgrade to SC5.0 or SC4.2.
@@ -213,11 +225,11 @@
 # SC5.0 note: Compiler common patch 107357-01 or later is required!
 "solaris-sparcv7-cc","cc:-xO5 -xstrconst -xdepend -Xa -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT::-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_PTR DES_RISC1 DES_UNROLL BF_PTR:${no_asm}:dlfcn:solaris-shared:-KPIC:-G -dy -z text:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
 "solaris-sparcv8-cc","cc:-xarch=v8 -xO5 -xstrconst -xdepend -Xa -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT::-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_PTR DES_RISC1 DES_UNROLL BF_PTR::sparcv8.o:des_enc-sparc.o fcrypt_b.o:::::::::dlfcn:solaris-shared:-KPIC:-G -dy -z text:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
-"solaris-sparcv9-cc","cc:-xtarget=ultra -xarch=v8plus -xO5 -xstrconst -xdepend -Xa -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK_LL DES_PTR DES_RISC1 DES_UNROLL BF_PTR::sparcv8plus.o:des_enc-sparc.o fcrypt_b.o:::md5-sparcv8plus.o::::::dlfcn:solaris-shared:-KPIC:-G -dy -z text:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
-"solaris64-sparcv9-cc","cc:-xtarget=ultra -xarch=v9 -xO5 -xstrconst -xdepend -Xa -DB_ENDIAN::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_PTR DES_RISC1 DES_UNROLL BF_PTR:::des_enc-sparc.o fcrypt_b.o:::md5-sparcv9.o::::::dlfcn:solaris-shared:-KPIC:-xarch=v9 -G -dy -z text:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):/usr/ccs/bin/ar rs",
+"solaris-sparcv9-cc","cc:-xtarget=ultra -xarch=v8plus -xO5 -xstrconst -xdepend -Xa -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK_LL DES_PTR DES_RISC1 DES_UNROLL BF_PTR::sparcv8plus.o:des_enc-sparc.o fcrypt_b.o:::::::::dlfcn:solaris-shared:-KPIC:-G -dy -z text:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"solaris64-sparcv9-cc","cc:-xtarget=ultra -xarch=v9 -xO5 -xstrconst -xdepend -Xa -DB_ENDIAN::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_PTR DES_RISC1 DES_UNROLL BF_PTR:::des_enc-sparc.o fcrypt_b.o:::::::::dlfcn:solaris-shared:-KPIC:-xarch=v9 -G -dy -z text:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):/usr/ccs/bin/ar rs",
 ####
 "debug-solaris-sparcv8-cc","cc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG_ALL -xarch=v8 -g -O -xstrconst -Xa -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT::-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_PTR DES_RISC1 DES_UNROLL BF_PTR::sparcv8.o::::::::::dlfcn:solaris-shared:-KPIC:-G -dy -z text:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
-"debug-solaris-sparcv9-cc","cc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG_ALL -xtarget=ultra -xarch=v8plus -g -O -xstrconst -Xa -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK_LL DES_PTR DES_RISC1 DES_UNROLL BF_PTR::sparcv8plus.o::::md5-sparcv8plus.o::::::dlfcn:solaris-shared:-KPIC:-G -dy -z text:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", 
+"debug-solaris-sparcv9-cc","cc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG_ALL -xtarget=ultra -xarch=v8plus -g -O -xstrconst -Xa -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK_LL DES_PTR DES_RISC1 DES_UNROLL BF_PTR::sparcv8plus.o::::::::::dlfcn:solaris-shared:-KPIC:-G -dy -z text:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", 
 
 #### SunOS configs, assuming sparc for the gcc one.
 #"sunos-cc", "cc:-O4 -DNOPROTO -DNOCONST::(unknown):SUNOS::DES_UNROLL:${no_asm}::",
@@ -332,9 +344,9 @@
 "linux-sparcv8","gcc:-mv8 -DB_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -Wall -DBN_DIV2W::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR::sparcv8.o:des_enc-sparc.o fcrypt_b.o:::::::::dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
 # it's a real mess with -mcpu=ultrasparc option under Linux, but
 # -Wa,-Av8plus should do the trick no matter what.
-"linux-sparcv9","gcc:-m32 -mcpu=ultrasparc -DB_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -Wall -Wa,-Av8plus -DBN_DIV2W::-D_REENTRANT:ULTRASPARC:-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR::sparcv8plus.o:des_enc-sparc.o fcrypt_b.o:::md5-sparcv8plus.o::::::dlfcn:linux-shared:-fPIC:-m32:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"linux-sparcv9","gcc:-m32 -mcpu=ultrasparc -DB_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -Wall -Wa,-Av8plus -DBN_DIV2W::-D_REENTRANT:ULTRASPARC:-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR::sparcv8plus.o:des_enc-sparc.o fcrypt_b.o:::::::::dlfcn:linux-shared:-fPIC:-m32:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
 # GCC 3.1 is a requirement
-"linux64-sparcv9","gcc:-m64 -mcpu=ultrasparc -DB_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -Wall::-D_REENTRANT:ULTRASPARC:-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR::::::md5-sparcv9.o::::::dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"linux64-sparcv9","gcc:-m64 -mcpu=ultrasparc -DB_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -Wall::-D_REENTRANT:ULTRASPARC:-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR::::::::::::dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
 #### Alpha Linux with GNU C and Compaq C setups
 # Special notes:
 # - linux-alpha+bwx-gcc is ment to be used from ./config only. If you
@@ -364,7 +376,7 @@
 # -DMD32_REG_T=int doesn't actually belong in sparc64 target, it
 # simply *happens* to work around a compiler bug in gcc 3.3.3,
 # triggered by RIPEMD160 code.
-"BSD-sparc64",	"gcc:-DB_ENDIAN -DTERMIOS -O3 -DMD32_REG_T=int -Wall::${BSDthreads}:::SIXTY_FOUR_BIT_LONG RC2_CHAR RC4_CHUNK DES_INT DES_PTR DES_RISC2 BF_PTR:::des_enc-sparc.o fcrypt_b.o:::md5-sparcv9.o::::::dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"BSD-sparc64",	"gcc:-DB_ENDIAN -DTERMIOS -O3 -DMD32_REG_T=int -Wall::${BSDthreads}:::SIXTY_FOUR_BIT_LONG RC2_CHAR RC4_CHUNK DES_INT DES_PTR DES_RISC2 BF_PTR:::des_enc-sparc.o fcrypt_b.o:::::::::dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
 "BSD-ia64",	"gcc:-DL_ENDIAN -DTERMIOS -O3 -Wall::${BSDthreads}:::SIXTY_FOUR_BIT_LONG RC4_CHUNK:${ia64_asm}:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
 "BSD-x86_64",	"gcc:-DL_ENDIAN -DTERMIOS -O3 -DMD32_REG_T=int -Wall::${BSDthreads}:::SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
 
@@ -402,12 +414,12 @@
 
 #### IBM's AIX.
 "aix3-cc",  "cc:-O -DB_ENDIAN -qmaxmem=16384::(unknown):AIX::BN_LLONG RC4_CHAR:::",
-"aix-gcc",  "gcc:-O -DB_ENDIAN::-D_THREAD_SAFE:AIX::BN_LLONG RC4_CHAR::aix_ppc32.o::::::::::dlfcn:aix-shared:::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)::-X 32",
-"aix64-gcc","gcc:-maix64 -O -DB_ENDIAN::-D_THREAD_SAFE:AIX::SIXTY_FOUR_BIT_LONG RC4_CHAR::aix_ppc64.o::::::::::dlfcn:aix-shared::-maix64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)::-X64",
+"aix-gcc",  "gcc:-O -DB_ENDIAN::-pthread:AIX::BN_LLONG RC4_CHAR::aix_ppc32.o::::::::::dlfcn:aix-shared::-shared -Wl,-G:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)::-X 32",
+"aix64-gcc","gcc:-maix64 -O -DB_ENDIAN::-pthread:AIX::SIXTY_FOUR_BIT_LONG RC4_CHAR::aix_ppc64.o::::::::::dlfcn:aix-shared::-maix64 -shared -Wl,-G:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)::-X64",
 # Below targets assume AIX 5. Idea is to effectively disregard $OBJECT_MODE
 # at build time. $OBJECT_MODE is respected at ./config stage!
-"aix-cc",   "cc:-q32 -O -DB_ENDIAN -qmaxmem=16384 -qro -qroconst::-qthreaded:AIX::BN_LLONG RC4_CHAR::aix_ppc32.o::::::::::dlfcn:aix-shared::-q32:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)::-X 32",
-"aix64-cc", "cc:-q64 -O -DB_ENDIAN -qmaxmem=16384 -qro -qroconst::-qthreaded:AIX::SIXTY_FOUR_BIT_LONG RC4_CHAR::aix_ppc64.o::::::::::dlfcn:aix-shared::-q64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)::-X 64",
+"aix-cc",   "cc:-q32 -O -DB_ENDIAN -qmaxmem=16384 -qro -qroconst::-qthreaded:AIX::BN_LLONG RC4_CHAR::aix_ppc32.o::::::::::dlfcn:aix-shared::-q32 -G:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)::-X 32",
+"aix64-cc", "cc:-q64 -O -DB_ENDIAN -qmaxmem=16384 -qro -qroconst::-qthreaded:AIX::SIXTY_FOUR_BIT_LONG RC4_CHAR::aix_ppc64.o::::::::::dlfcn:aix-shared::-q64 -G:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)::-X 64",
 
 #
 # Cray T90 and similar (SDSC)
@@ -478,15 +490,20 @@
 "Cygwin", "gcc:-DTERMIOS -DL_ENDIAN -fomit-frame-pointer -O3 -march=i486 -Wall:::CYGWIN32::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_coff_asm}:dlfcn:cygwin-shared:-D_WINDLL:-shared:.dll.a",
 "debug-Cygwin", "gcc:-DTERMIOS -DL_ENDIAN -march=i486 -Wall -DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG -DOPENSSL_NO_ASM -g -Wformat -Wshadow -Wmissing-prototypes -Wmissing-declarations -Werror:::CYGWIN32:::${no_asm}:dlfcn:cygwin-shared:-D_WINDLL:-shared:.dll.a",
 
-# NetWare from David Ward (dsward at novell.com) - requires MetroWerks NLM development tools
+# NetWare from David Ward (dsward at novell.com)
+# requires either MetroWerks NLM development tools, or gcc / nlmconv
+# NetWare defaults socket bio to WinSock sockets. However,
+# the builds can be configured to use BSD sockets instead.
 # netware-clib => legacy CLib c-runtime support
-"netware-clib", "mwccnlm::::::BN_LLONG ${x86_gcc_opts}::",
+"netware-clib", "mwccnlm::::::${x86_gcc_opts}::",
+"netware-clib-bsdsock", "mwccnlm::::::${x86_gcc_opts}::",
+"netware-clib-gcc", "i586-netware-gcc:-nostdinc -I/ndk/nwsdk/include/nlm -I/ndk/ws295sdk/include -DL_ENDIAN -DNETWARE_CLIB -DOPENSSL_SYSNAME_NETWARE -O2 -Wall:::::${x86_gcc_opts}::",
+"netware-clib-bsdsock-gcc", "i586-netware-gcc:-nostdinc -I/ndk/nwsdk/include/nlm -DNETWARE_BSDSOCK -DNETDB_USE_INTERNET -DL_ENDIAN -DNETWARE_CLIB -DOPENSSL_SYSNAME_NETWARE -O2 -Wall:::::${x86_gcc_opts}::",
 # netware-libc => LibC/NKS support
-# NetWare defaults socket bio to WinSock sockets. However, the LibC build can be
-# configured to use BSD sockets instead.
 "netware-libc", "mwccnlm::::::BN_LLONG ${x86_gcc_opts}::",
 "netware-libc-bsdsock", "mwccnlm::::::BN_LLONG ${x86_gcc_opts}::",
 "netware-libc-gcc", "i586-netware-gcc:-nostdinc -I/ndk/libc/include -I/ndk/libc/include/winsock -DL_ENDIAN -DNETWARE_LIBC -DOPENSSL_SYSNAME_NETWARE -DTERMIO -O2 -Wall:::::BN_LLONG ${x86_gcc_opts}::",
+"netware-libc-bsdsock-gcc", "i586-netware-gcc:-nostdinc -I/ndk/libc/include -DNETWARE_BSDSOCK -DL_ENDIAN -DNETWARE_LIBC -DOPENSSL_SYSNAME_NETWARE -DTERMIO -O2 -Wall:::::BN_LLONG ${x86_gcc_opts}::",
 
 # DJGPP
 "DJGPP", "gcc:-I/dev/env/WATT_ROOT/inc -DTERMIOS -DL_ENDIAN -fomit-frame-pointer -O2 -Wall:::MSDOS:-L/dev/env/WATT_ROOT/lib -lwatt:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_out_asm}:",
@@ -500,8 +517,9 @@
 ##### MacOS X (a.k.a. Rhapsody or Darwin) setup
 "rhapsody-ppc-cc","cc:-O3 -DB_ENDIAN::(unknown):MACOSX_RHAPSODY::BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR:${no_asm}::",
 "darwin-ppc-cc","cc:-arch ppc -O3 -DB_ENDIAN::-D_REENTRANT:MACOSX:-Wl,-search_paths_first%:BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR::osx_ppc32.o::::::::::dlfcn:darwin-shared:-fPIC -fno-common:-arch ppc -dynamiclib:.\$(SHLIB_MAJOR).\$(SHLIB_MINOR).dylib",
-"darwin64-ppc-cc","cc:-arch ppc64 -O3 -DB_ENDIAN::-D_REENTRANT:MACOSX:-Wl,-search_paths_first%:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR:ppccpuid_osx64.o:osx_ppc64.o osx_ppc64-mont.o:::::sha1-ppc_osx64.o sha256-ppc_osx64.o sha512-ppc_osx64.o:::::::dlfcn:darwin-shared:-fPIC -fno-common:-arch ppc64 -dynamiclib:.\$(SHLIB_MAJOR).\$(SHLIB_MINOR).dylib",
-"darwin-i386-cc","cc:-arch i386 -O3 -fomit-frame-pointer -fno-common::-D_REENTRANT:MACOSX:-Wl,-search_paths_first%:BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR:${no_asm}:dlfcn:darwin-shared:-fPIC -fno-common:-arch i386 -dynamiclib:.\$(SHLIB_MAJOR).\$(SHLIB_MINOR).dylib",
+"darwin64-ppc-cc","cc:-arch ppc64 -O3 -DB_ENDIAN::-D_REENTRANT:MACOSX:-Wl,-search_paths_first%:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR::osx_ppc64.o::::::::::dlfcn:darwin-shared:-fPIC -fno-common:-arch ppc64 -dynamiclib:.\$(SHLIB_MAJOR).\$(SHLIB_MINOR).dylib",
+"darwin-i386-cc","cc:-arch i386 -O3 -fomit-frame-pointer -DL_ENDIAN::-D_REENTRANT:MACOSX:-Wl,-search_paths_first%:BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR:${no_asm}:dlfcn:darwin-shared:-fPIC -fno-common:-arch i386 -dynamiclib:.\$(SHLIB_MAJOR).\$(SHLIB_MINOR).dylib",
+"debug-darwin-i386-cc","cc:-arch i386 -g3 -DL_ENDIAN::-D_REENTRANT:MACOSX:-Wl,-search_paths_first%:BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR:${no_asm}:dlfcn:darwin-shared:-fPIC -fno-common:-arch i386 -dynamiclib:.\$(SHLIB_MAJOR).\$(SHLIB_MINOR).dylib",
 "darwin64-x86_64-cc","cc:-arch x86_64 -O3 -fomit-frame-pointer -DL_ENDIAN -DMD32_REG_T=int -Wall::-D_REENTRANT:MACOSX:-Wl,-search_paths_first%:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK BF_PTR2 DES_INT DES_UNROLL:${no_asm}:dlfcn:darwin-shared:-fPIC -fno-common:-arch x86_64 -dynamiclib:.\$(SHLIB_MAJOR).\$(SHLIB_MINOR).dylib",
 "debug-darwin-ppc-cc","cc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG -DB_ENDIAN -g -Wall -O::-D_REENTRANT:MACOSX::BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR::osx_ppc32.o::::::::::dlfcn:darwin-shared:-fPIC -fno-common:-dynamiclib:.\$(SHLIB_MAJOR).\$(SHLIB_MINOR).dylib",
 
@@ -531,7 +549,9 @@
 
 my @MK1MF_Builds=qw(VC-WIN64I VC-WIN64A
 		    VC-NT VC-CE VC-WIN32
-		    BC-32 OS2-EMX netware-clib netware-libc netware-libc-bsdsock);
+		    BC-32 OS2-EMX
+		    netware-clib netware-clib-bsdsock
+		    netware-libc netware-libc-bsdsock);
 
 my $idx = 0;
 my $idx_cc = $idx++;
@@ -564,12 +584,18 @@
 my $openssldir="";
 my $exe_ext="";
 my $install_prefix="";
+my $fipslibdir="/usr/local/ssl/fips-1.0/lib/";
+my $nofipscanistercheck=0;
+my $fipsdso=0;
+my $fipscanisterinternal="n";
+my $baseaddr="0xFB00000";
 my $no_threads=0;
 my $threads=0;
 my $no_shared=0; # but "no-shared" is default
 my $zlib=1;      # but "no-zlib" is default
 my $no_krb5=0;   # but "no-krb5" is implied unless "--with-krb5-..." is used
 my $no_rfc3779=1; # but "no-rfc3779" is default
+my $montasm=1;   # but "no-montasm" is default
 my $no_asm=0;
 my $no_dso=0;
 my $no_gmp=0;
@@ -586,10 +612,11 @@
 my $bf	="crypto/bf/bf_locl.h";
 my $bn_asm	="bn_asm.o";
 my $des_enc="des_enc.o fcrypt_b.o";
+my $fips_des_enc="fips_des_enc.o";
 my $aes_enc="aes_core.o aes_cbc.o";
 my $bf_enc	="bf_enc.o";
 my $cast_enc="c_enc.o";
-my $rc4_enc="rc4_enc.o";
+my $rc4_enc="rc4_enc.o rc4_skey.o";
 my $rc5_enc="rc5_enc.o";
 my $md5_obj="";
 my $sha1_obj="";
@@ -597,37 +624,49 @@
 my $processor="";
 my $default_ranlib;
 my $perl;
+my $fips=0;
 
 
 # All of the following is disabled by default (RC5 was enabled before 0.9.8):
 
-my %disabled = ( # "what"         => "comment"
+my %disabled = ( # "what"         => "comment" [or special keyword "experimental"]
                  "camellia"       => "default",
+                 "capieng"        => "default",
+                 "cms"            => "default",
                  "gmp"            => "default",
+                 "jpake"          => "experimental",
                  "mdc2"           => "default",
+                 "montasm"        => "default", # explicit option in 0.9.8 only (implicitly enabled in 0.9.9)
                  "rc5"            => "default",
                  "rfc3779"        => "default",
                  "seed"           => "default",
                  "shared"         => "default",
-                 "tlsext"         => "default",
                  "zlib"           => "default",
                  "zlib-dynamic"   => "default"
                );
+my @experimental = ();
 
-# Additional "no-..." options will be collected in %disabled.
-# To remove something from %disabled, use e.g. "enable-rc5".
-# For symmetry, "disable-..." is a synonym for "no-...".
+# This is what $depflags will look like with the above defaults
+# (we need this to see if we should advise the user to run "make depend"):
+my $default_depflags = " -DOPENSSL_NO_CAMELLIA -DOPENSSL_NO_CAPIENG -DOPENSSL_NO_CMS -DOPENSSL_NO_GMP -DOPENSSL_NO_JPAKE -DOPENSSL_NO_MDC2 -DOPENSSL_NO_RC5 -DOPENSSL_NO_RFC3779 -DOPENSSL_NO_SEED";
 
-# This is what $depflags will look like with the above default:
-my $default_depflags = "-DOPENSSL_NO_CAMELLIA -DOPENSSL_NO_GMP -DOPENSSL_NO_MDC2 -DOPENSSL_NO_RC5 -DOPENSSL_NO_RFC3779 -DOPENSSL_NO_SEED -DOPENSSL_NO_TLSEXT ";
 
+# Explicit "no-..." options will be collected in %disabled along with the defaults.
+# To remove something from %disabled, use "enable-foo" (unless it's experimental).
+# For symmetry, "disable-foo" is a synonym for "no-foo".
 
+# For features called "experimental" here, a more explicit "experimental-foo" is needed to enable.
+# We will collect such requests in @experimental.
+# To avoid accidental use of experimental features, applications will have to use -DOPENSSL_EXPERIMENTAL_FOO.
+
+
 my $no_sse2=0;
 
 &usage if ($#ARGV < 0);
 
 my $flags;
 my $depflags;
+my $openssl_experimental_defines;
 my $openssl_algorithm_defines;
 my $openssl_thread_defines;
 my $openssl_sys_defines="";
@@ -648,6 +687,7 @@
 	{
 	$flags="";
 	$depflags="";
+	$openssl_experimental_defines="";
 	$openssl_algorithm_defines="";
 	$openssl_thread_defines="";
 	$openssl_sys_defines="";
@@ -673,25 +713,35 @@
 
 		if (/^no-(.+)$/ || /^disable-(.+)$/)
 			{
-			if ($1 eq "ssl")
+			if (!($disabled{$1} eq "experimental"))
 				{
-				$disabled{"ssl2"} = "option(ssl)";
-				$disabled{"ssl3"} = "option(ssl)";
+				if ($1 eq "ssl")
+					{
+					$disabled{"ssl2"} = "option(ssl)";
+					$disabled{"ssl3"} = "option(ssl)";
+					}
+				elsif ($1 eq "tls")
+					{
+					$disabled{"tls1"} = "option(tls)"
+					}
+				else
+					{
+					$disabled{$1} = "option";
+					}
 				}
-			elsif ($1 eq "tls")
+			}			
+		elsif (/^enable-(.+)$/ || /^experimental-(.+)$/)
+			{
+			my $algo = $1;
+			if ($disabled{$algo} eq "experimental")
 				{
-				$disabled{"tls1"} = "option(tls)"
+				die "You are requesting an experimental feature; please say 'experimental-$algo' if you are sure\n"
+					unless (/^experimental-/);
+				push @experimental, $algo;
 				}
-			else
-				{
-				$disabled{$1} = "option";
-				}
-			}			
-		elsif (/^enable-(.+)$/)
-			{
-			delete $disabled{$1};
+			delete $disabled{$algo};
 
-			$threads = 1 if ($1 eq "threads");
+			$threads = 1 if ($algo eq "threads");
 			}
 		elsif (/^--test-sanity$/)
 			{
@@ -722,12 +772,36 @@
 			}
 		elsif (/^386$/)
 			{ $processor=386; }
+		elsif (/^fips$/)
+			{
+			$fips=1;
+		        }
 		elsif (/^rsaref$/)
 			{
 			# No RSAref support any more since it's not needed.
 			# The check for the option is there so scripts aren't
 			# broken
 			}
+		elsif (/^nofipscanistercheck$/)
+			{
+			$fips = 1;
+			$nofipscanistercheck = 1;
+			}
+		elsif (/^fipscanisterbuild$/)
+			{
+			$fips = 1;
+			$nofipscanistercheck = 1;
+			$fipslibdir="";
+			$fipscanisterinternal="y";
+			}
+		elsif (/^fipsdso$/)
+			{
+			$fips = 1;
+			$nofipscanistercheck = 1;
+			$fipslibdir="";
+			$fipscanisterinternal="y";
+			$fipsdso = 1;
+			}
 		elsif (/^[-+]/)
 			{
 			if (/^-[lL](.*)$/)
@@ -762,6 +836,14 @@
 				{
 				$withargs{"zlib-include"}="-I$1";
 				}
+			elsif (/^--with-fipslibdir=(.*)$/)
+				{
+				$fipslibdir="$1/";
+				}
+			elsif (/^--with-baseaddr=(.*)$/)
+				{
+				$baseaddr="$1";
+				}
 			else
 				{
 				print STDERR $usage;
@@ -869,7 +951,55 @@
 
 &usage if (!defined($table{$target}));
 
+my @fields = split(/\s*:\s*/,$table{$target} . ":" x 30 , -1);
+my $cc = $fields[$idx_cc];
+# Allow environment CC to override compiler...
+if($ENV{CC}) {
+    $cc = $ENV{CC};
+}
+my $cflags = $fields[$idx_cflags];
+my $unistd = $fields[$idx_unistd];
+my $thread_cflag = $fields[$idx_thread_cflag];
+my $sys_id = $fields[$idx_sys_id];
+my $lflags = $fields[$idx_lflags];
+my $bn_ops = $fields[$idx_bn_ops];
+my $cpuid_obj = $fields[$idx_cpuid_obj];
+my $bn_obj = $fields[$idx_bn_obj];
+my $des_obj = $fields[$idx_des_obj];
+my $aes_obj = $fields[$idx_aes_obj];
+my $bf_obj = $fields[$idx_bf_obj];
+my $md5_obj = $fields[$idx_md5_obj];
+my $sha1_obj = $fields[$idx_sha1_obj];
+my $cast_obj = $fields[$idx_cast_obj];
+my $rc4_obj = $fields[$idx_rc4_obj];
+my $rmd160_obj = $fields[$idx_rmd160_obj];
+my $rc5_obj = $fields[$idx_rc5_obj];
+my $dso_scheme = $fields[$idx_dso_scheme];
+my $shared_target = $fields[$idx_shared_target];
+my $shared_cflag = $fields[$idx_shared_cflag];
+my $shared_ldflag = $fields[$idx_shared_ldflag];
+my $shared_extension = $fields[$idx_shared_extension];
+my $ranlib = $fields[$idx_ranlib];
+my $arflags = $fields[$idx_arflags];
 
+if ($fips)
+	{
+	delete $disabled{"shared"} if ($disabled{"shared"} eq "default");
+	$disabled{"asm"}="forced"
+		if ($target !~ "VC\-.*" &&
+		    "$cpuid_obj:$bn_obj:$aes_obj:$des_obj:$sha1_obj" eq "::::");
+	}
+
+foreach (sort @experimental)
+	{
+	my $ALGO;
+	($ALGO = $_) =~ tr/[a-z]/[A-Z]/;
+
+	# opensslconf.h will set OPENSSL_NO_... unless OPENSSL_EXPERIMENTAL_... is defined
+	$openssl_experimental_defines .= "#define OPENSSL_NO_$ALGO\n";
+	$cflags .= " -DOPENSSL_EXPERIMENTAL_$ALGO";
+	}
+
 foreach (sort (keys %disabled))
 	{
 	$options .= " no-$_";
@@ -884,6 +1014,8 @@
 		{ $no_shared = 1; }
 	elsif (/^zlib$/)
 		{ $zlib = 0; }
+	elsif (/^montasm$/)
+		{ $montasm = 0; }
 	elsif (/^static-engine$/)
 		{ }
 	elsif (/^zlib-dynamic$/)
@@ -917,7 +1049,7 @@
 				push @skip, $algo;
 				print " (skip dir)";
 
-				$depflags .="-DOPENSSL_NO_$ALGO ";
+				$depflags .= " -DOPENSSL_NO_$ALGO";
 				}
 			}
 		}
@@ -925,14 +1057,26 @@
 	print "\n";
 	}
 
-
 my $IsMK1MF=scalar grep /^$target$/, at MK1MF_Builds;
 
 $IsMK1MF=1 if ($target eq "mingw" && $^O ne "cygwin" && !is_msys());
 
+$no_shared = 0 if ($fipsdso && !$IsMK1MF);
+
 $exe_ext=".exe" if ($target eq "Cygwin" || $target eq "DJGPP" || $target eq "mingw");
+$exe_ext=".nlm" if ($target =~ /netware/);
 $exe_ext=".pm"  if ($target =~ /vos/);
-$openssldir="/usr/local/ssl" if ($openssldir eq "" and $prefix eq "");
+if ($openssldir eq "" and $prefix eq "")
+	{
+	if ($fips)
+		{
+		$openssldir="/usr/local/ssl/fips";
+		}
+	else
+		{
+		$openssldir="/usr/local/ssl";
+		}
+	}
 $prefix=$openssldir if $prefix eq "";
 
 $default_ranlib= &which("ranlib") or $default_ranlib="true";
@@ -940,7 +1084,7 @@
   or $perl="perl";
 
 chop $openssldir if $openssldir =~ /\/$/;
-chop $prefix if $prefix =~ /\/$/;
+chop $prefix if $prefix =~ /.\/$/;
 
 $openssldir=$prefix . "/ssl" if $openssldir eq "";
 $openssldir=$prefix . "/" . $openssldir if $openssldir !~ /(^\/|^[a-zA-Z]:[\\\/])/;
@@ -948,33 +1092,6 @@
 
 print "IsMK1MF=$IsMK1MF\n";
 
-my @fields = split(/\s*:\s*/,$table{$target} . ":" x 30 , -1);
-my $cc = $fields[$idx_cc];
-my $cflags = $fields[$idx_cflags];
-my $unistd = $fields[$idx_unistd];
-my $thread_cflag = $fields[$idx_thread_cflag];
-my $sys_id = $fields[$idx_sys_id];
-my $lflags = $fields[$idx_lflags];
-my $bn_ops = $fields[$idx_bn_ops];
-my $cpuid_obj = $fields[$idx_cpuid_obj];
-my $bn_obj = $fields[$idx_bn_obj];
-my $des_obj = $fields[$idx_des_obj];
-my $aes_obj = $fields[$idx_aes_obj];
-my $bf_obj = $fields[$idx_bf_obj];
-my $md5_obj = $fields[$idx_md5_obj];
-my $sha1_obj = $fields[$idx_sha1_obj];
-my $cast_obj = $fields[$idx_cast_obj];
-my $rc4_obj = $fields[$idx_rc4_obj];
-my $rmd160_obj = $fields[$idx_rmd160_obj];
-my $rc5_obj = $fields[$idx_rc5_obj];
-my $dso_scheme = $fields[$idx_dso_scheme];
-my $shared_target = $fields[$idx_shared_target];
-my $shared_cflag = $fields[$idx_shared_cflag];
-my $shared_ldflag = $fields[$idx_shared_ldflag];
-my $shared_extension = $fields[$idx_shared_extension];
-my $ranlib = $fields[$idx_ranlib];
-my $arflags = $fields[$idx_arflags];
-
 # '%' in $lflags is used to split flags to "pre-" and post-flags
 my ($prelflags,$postlflags)=split('%',$lflags);
 if (defined($postlflags))	{ $lflags=$postlflags;  }
@@ -1108,7 +1225,17 @@
 	{
 	$cpuid_obj=$bn_obj=$des_obj=$aes_obj=$bf_obj=$cast_obj=$rc4_obj=$rc5_obj="";
 	$sha1_obj=$md5_obj=$rmd160_obj="";
+	$cflags=~s/\-D[BL]_ENDIAN//		if ($fips);
+	$thread_cflags=~s/\-D[BL]_ENDIAN//	if ($fips);
 	}
+if ($montasm)
+	{
+	$bn_obj =~ s/MAYBE-MO86-/mo86-/;
+	}
+else
+	{
+	$bn_obj =~ s/MAYBE-MO86-[a-z.]*//;
+	}
 
 if (!$no_shared)
 	{
@@ -1138,7 +1265,7 @@
 my $shared_mark = "";
 if ($shared_target eq "")
 	{
-	$no_shared_warn = 1 if !$no_shared;
+	$no_shared_warn = 1 if !$no_shared && !$fips;
 	$no_shared = 1;
 	}
 if (!$no_shared)
@@ -1228,6 +1355,13 @@
 $cflags.=" -DOPENSSL_BN_ASM_PART_WORDS" if ($bn_obj =~ /bn86/);
 $cflags.=" -DOPENSSL_IA32_SSE2" if (!$no_sse2 && $bn_obj =~ /bn86/);
 
+$cflags.=" -DOPENSSL_BN_ASM_MONT" if ($bn_obj =~ /\-mont|mo86\-/);
+
+if ($fips)
+	{
+	$openssl_other_defines.="#define OPENSSL_FIPS\n";
+	}
+
 $des_obj=$des_enc	unless ($des_obj =~ /\.o$/);
 $bf_obj=$bf_enc		unless ($bf_obj =~ /\.o$/);
 $cast_obj=$cast_enc	unless ($cast_obj =~ /\.o$/);
@@ -1312,10 +1446,13 @@
 	if ($sdirs) {
 		my $dir;
 		foreach $dir (@skip) {
-			s/([ 	])$dir /\1/;
+			s/(\s)$dir\s/$1/;
+			s/\s$dir$//;
 			}
 		}
 	$sdirs = 0 unless /\\$/;
+        s/fips // if (/^DIRS=/ && !$fips);
+        s/engines // if (/^DIRS=/ && $disabled{"engine"});
 	s/^VERSION=.*/VERSION=$version/;
 	s/^MAJOR=.*/MAJOR=$major/;
 	s/^MINOR=.*/MINOR=$minor/;
@@ -1333,7 +1470,7 @@
 	s/^CC=.*$/CC= $cc/;
 	s/^MAKEDEPPROG=.*$/MAKEDEPPROG= $cc/ if $cc eq "gcc";
 	s/^CFLAG=.*$/CFLAG= $cflags/;
-	s/^DEPFLAG=.*$/DEPFLAG= $depflags/;
+	s/^DEPFLAG=.*$/DEPFLAG=$depflags/;
 	s/^PEX_LIBS=.*$/PEX_LIBS= $prelflags/;
 	s/^EX_LIBS=.*$/EX_LIBS= $lflags/;
 	s/^EXE_EXT=.*$/EXE_EXT= $exe_ext/;
@@ -1356,9 +1493,24 @@
 	s/^LIBKRB5=.*/LIBKRB5=$withargs{"krb5-lib"}/;
 	s/^LIBZLIB=.*/LIBZLIB=$withargs{"zlib-lib"}/;
 	s/^ZLIB_INCLUDE=.*/ZLIB_INCLUDE=$withargs{"zlib-include"}/;
+	s/^FIPSLIBDIR=.*/FIPSLIBDIR=$fipslibdir/;
+	if ($fipsdso)
+		{
+		s/^FIPSCANLIB=.*/FIPSCANLIB=libfips/;
+		s/^SHARED_FIPS=.*/SHARED_FIPS=libfips\$(SHLIB_EXT)/;
+		s/^SHLIBDIRS=.*/SHLIBDIRS= crypto ssl fips/;
+		}
+	else
+		{
+		s/^FIPSCANLIB=.*/FIPSCANLIB=libcrypto/ if $fips;
+		s/^SHARED_FIPS=.*/SHARED_FIPS=/;
+		s/^SHLIBDIRS=.*/SHLIBDIRS= crypto ssl/;
+		}
+	s/^FIPSCANISTERINTERNAL=.*/FIPSCANISTERINTERNAL=$fipscanisterinternal/;
+	s/^BASEADDR=.*/BASEADDR=$baseaddr/;
 	s/^SHLIB_TARGET=.*/SHLIB_TARGET=$shared_target/;
 	s/^SHLIB_MARK=.*/SHLIB_MARK=$shared_mark/;
-	s/^SHARED_LIBS=.*/SHARED_LIBS=\$(SHARED_CRYPTO) \$(SHARED_SSL)/ if (!$no_shared);
+	s/^SHARED_LIBS=.*/SHARED_LIBS=\$(SHARED_FIPS) \$(SHARED_CRYPTO) \$(SHARED_SSL)/ if (!$no_shared);
 	if ($shared_extension ne "" && $shared_extension =~ /^\.s([ol])\.[^\.]*$/)
 		{
 		my $sotmp = $1;
@@ -1462,6 +1614,7 @@
 
 print OUT "/* OpenSSL was configured with the following options: */\n";
 my $openssl_algorithm_defines_trans = $openssl_algorithm_defines;
+$openssl_experimental_defines =~ s/^\s*#\s*define\s+OPENSSL_NO_(.*)/#ifndef OPENSSL_EXPERIMENTAL_$1\n# ifndef OPENSSL_NO_$1\n#  define OPENSSL_NO_$1\n# endif\n#endif/mg;
 $openssl_algorithm_defines_trans =~ s/^\s*#\s*define\s+OPENSSL_(.*)/# if defined(OPENSSL_$1) \&\& !defined($1)\n#  define $1\n# endif/mg;
 $openssl_algorithm_defines =~ s/^\s*#\s*define\s+(.*)/#ifndef $1\n# define $1\n#endif/mg;
 $openssl_algorithm_defines = "   /* no ciphers excluded */\n" if $openssl_algorithm_defines eq "";
@@ -1470,8 +1623,10 @@
 $openssl_other_defines =~ s/^\s*#\s*define\s+(.*)/#ifndef $1\n# define $1\n#endif/mg;
 print OUT $openssl_sys_defines;
 print OUT "#ifndef OPENSSL_DOING_MAKEDEPEND\n\n";
+print OUT $openssl_experimental_defines;
+print OUT "\n";
 print OUT $openssl_algorithm_defines;
-print OUT "\n#endif /* OPENSSL_DOING_MAKEDEPEND */\n";
+print OUT "\n#endif /* OPENSSL_DOING_MAKEDEPEND */\n\n";
 print OUT $openssl_thread_defines;
 print OUT $openssl_other_defines,"\n";
 
@@ -1622,7 +1777,7 @@
 }
 
 # create the ms/version32.rc file if needed
-if ($IsMK1MF) {
+if ($IsMK1MF && ($target !~ /^netware/)) {
 	my ($v1, $v2, $v3, $v4);
 	if ($version_num =~ /(^[0-9a-f]{1})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/i) {
 		$v1=hex $1;
@@ -1653,9 +1808,16 @@
     BEGIN
 	BLOCK "040904b0"
 	BEGIN
+#if defined(FIPS)
+	    VALUE "Comments", "WARNING: TEST VERSION ONLY ***NOT*** FIPS 140-2 VALIDATED.\\0"
+#endif
 	    // Required:	    
 	    VALUE "CompanyName", "The OpenSSL Project, http://www.openssl.org/\\0"
+#if defined(FIPS)
+	    VALUE "FileDescription", "TEST UNVALIDATED FIPS140-2 DLL\\0"
+#else
 	    VALUE "FileDescription", "OpenSSL Shared Library\\0"
+#endif
 	    VALUE "FileVersion", "$version\\0"
 #if defined(CRYPTO)
 	    VALUE "InternalName", "libeay32\\0"
@@ -1663,12 +1825,15 @@
 #elif defined(SSL)
 	    VALUE "InternalName", "ssleay32\\0"
 	    VALUE "OriginalFilename", "ssleay32.dll\\0"
+#elif defined(FIPS)
+	    VALUE "InternalName", "libosslfips\\0"
+	    VALUE "OriginalFilename", "libosslfips.dll\\0"
 #endif
 	    VALUE "ProductName", "The OpenSSL Toolkit\\0"
 	    VALUE "ProductVersion", "$version\\0"
 	    // Optional:
 	    //VALUE "Comments", "\\0"
-	    VALUE "LegalCopyright", "Copyright © 1998-2005 The OpenSSL Project. Copyright © 1995-1998 Eric A. Young, Tim J. Hudson. All rights reserved.\\0"
+	    VALUE "LegalCopyright", "Copyright © 1998-2007 The OpenSSL Project. Copyright © 1995-1998 Eric A. Young, Tim J. Hudson. All rights reserved.\\0"
 	    //VALUE "LegalTrademarks", "\\0"
 	    //VALUE "PrivateBuild", "\\0"
 	    //VALUE "SpecialBuild", "\\0"
@@ -1705,6 +1870,21 @@
 (but please first make sure you have tried with a current version of OpenSSL).
 EOF
 
+print <<\EOF if ($fipscanisterinternal eq "y");
+
+WARNING: OpenSSL has been configured using unsupported option(s) to internally
+generate a fipscanister.o object module for TESTING PURPOSES ONLY; that
+compiled module is NOT FIPS 140-2 validated and CANNOT be used to replace the
+OpenSSL FIPS Object Module as identified by the CMVP
+(http://csrc.nist.gov/cryptval/) in any application requiring the use of FIPS
+140-2 validated software. 
+
+This is an OpenSSL 0.9.8 test version.
+
+See the file README.FIPS for details of how to build a test library.
+
+EOF
+
 exit(0);
 
 sub usage

Modified: openssl/branches/upstream/current/Makefile.org
===================================================================
--- openssl/branches/upstream/current/Makefile.org	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/Makefile.org	2009-05-16 15:25:35 UTC (rev 372)
@@ -65,6 +65,7 @@
 EXE_EXT= 
 ARFLAGS=
 AR=ar $(ARFLAGS) r
+ARD=ar $(ARFLAGS) d
 RANLIB= ranlib
 PERL= perl
 TAR= tar
@@ -104,9 +105,35 @@
 ZLIB_INCLUDE=
 LIBZLIB=
 
-DIRS=   crypto ssl engines apps test tools
-SHLIBDIRS= crypto ssl
+# This is the location of fipscanister.o and friends.
+# The FIPS module build will place it $(INSTALLTOP)/lib
+# but since $(INSTALLTOP) can only take the default value
+# when the module is built it will be in /usr/local/ssl/lib
+# $(INSTALLTOP) for this build make be different so hard
+# code the path.
 
+FIPSLIBDIR=/usr/local/ssl/lib/
+
+# This is set to "y" if fipscanister.o is compiled internally as
+# opposed to coming from an external validated location.
+
+FIPSCANISTERINTERNAL=n
+
+# The location of the library which contains fipscanister.o
+# normally it will be libcrypto unless fipsdso is set in which
+# case it will be libfips. If not compiling in FIPS mode at all
+# this is empty making it a useful test for a FIPS compile.
+
+FIPSCANLIB=
+
+# Shared library base address. Currently only used on Windows.
+#
+
+BASEADDR=
+
+DIRS=   crypto fips ssl engines apps test tools
+SHLIBDIRS= crypto ssl fips
+
 # dirs in crypto to build
 SDIRS=  \
 	objects \
@@ -115,7 +142,7 @@
 	bn ec rsa dsa ecdsa dh ecdh dso engine \
 	buffer bio stack lhash rand err \
 	evp asn1 pem x509 x509v3 conf txt_db pkcs7 pkcs12 comp ocsp ui krb5 \
-	store pqueue
+	store cms pqueue jpake
 # keep in mind that the above list is adjusted by ./Configure
 # according to no-xxx arguments...
 
@@ -138,6 +165,7 @@
 LIBS=   libcrypto.a libssl.a
 SHARED_CRYPTO=libcrypto$(SHLIB_EXT)
 SHARED_SSL=libssl$(SHLIB_EXT)
+SHARED_FIPS=
 SHARED_LIBS=
 SHARED_LIBS_LINK_EXTS=
 SHARED_LDFLAGS=
@@ -191,6 +219,10 @@
 		SHA1_ASM_OBJ='${SHA1_ASM_OBJ}'			\
 		MD5_ASM_OBJ='${MD5_ASM_OBJ}'			\
 		RMD160_ASM_OBJ='${RMD160_ASM_OBJ}'		\
+		FIPSLIBDIR='${FIPSLIBDIR}'			\
+		FIPSCANLIB="$${FIPSCANLIB:-$(FIPSCANLIB)}"	\
+		FIPSCANISTERINTERNAL='${FIPSCANISTERINTERNAL}'	\
+		FIPS_EX_OBJ='${FIPS_EX_OBJ}'	\
 		THIS=$${THIS:-$@} MAKEFILE=Makefile MAKEOVERRIDES=
 # MAKEOVERRIDES= effectively "equalizes" GNU-ish and SysV-ish make flavors,
 # which in turn eliminates ambiguities in variable treatment with -e.
@@ -209,7 +241,8 @@
 # subdirectories defined in $(DIRS).  It requires that the target
 # is given through the shell variable `target'.
 BUILD_CMD=  if [ -d "$$dir" ]; then \
-	    (	cd $$dir && echo "making $$target in $$dir..." && \
+	    (	[ $$target != all -a -z "$(FIPSCANLIB)" ] && FIPSCANLIB=/dev/null; \
+		cd $$dir && echo "making $$target in $$dir..." && \
 		$(CLEARENV) && $(MAKE) -e $(BUILDENV) TOP=.. DIR=$$dir $$target \
 	    ) || exit 1; \
 	    fi
@@ -222,13 +255,84 @@
 reflect:
 	@[ -n "$(THIS)" ] && $(CLEARENV) && $(MAKE) $(THIS) -e $(BUILDENV)
 
+FIPS_EX_OBJ= ../crypto/aes/aes_cfb.o \
+	../crypto/aes/aes_ecb.o \
+	../crypto/aes/aes_ofb.o \
+	../crypto/bn/bn_add.o \
+	../crypto/bn/bn_blind.o \
+	../crypto/bn/bn_ctx.o \
+	../crypto/bn/bn_div.o \
+	../crypto/bn/bn_exp2.o \
+	../crypto/bn/bn_exp.o \
+	../crypto/bn/bn_gcd.o \
+	../crypto/bn/bn_lib.o \
+	../crypto/bn/bn_mod.o \
+	../crypto/bn/bn_mont.o \
+	../crypto/bn/bn_mul.o \
+	../crypto/bn/bn_prime.o \
+	../crypto/bn/bn_rand.o \
+	../crypto/bn/bn_recp.o \
+	../crypto/bn/bn_shift.o \
+	../crypto/bn/bn_sqr.o \
+	../crypto/bn/bn_word.o \
+	../crypto/bn/bn_x931p.o \
+	../crypto/buffer/buf_str.o \
+	../crypto/cryptlib.o \
+	../crypto/des/cfb64ede.o \
+	../crypto/des/cfb64enc.o \
+	../crypto/des/cfb_enc.o \
+	../crypto/des/ecb3_enc.o \
+	../crypto/des/ecb_enc.o \
+	../crypto/des/ofb64ede.o \
+	../crypto/des/ofb64enc.o \
+	../crypto/des/fcrypt.o \
+	../crypto/des/set_key.o \
+	../crypto/dsa/dsa_utl.o \
+	../crypto/dsa/dsa_sign.o \
+	../crypto/dsa/dsa_vrf.o \
+	../crypto/err/err.o \
+	../crypto/evp/digest.o \
+	../crypto/evp/enc_min.o \
+	../crypto/evp/e_aes.o \
+	../crypto/evp/e_des3.o \
+	../crypto/evp/p_sign.o \
+	../crypto/evp/p_verify.o \
+	../crypto/mem_clr.o \
+	../crypto/mem.o \
+	../crypto/rand/md_rand.o \
+	../crypto/rand/rand_egd.o \
+	../crypto/rand/randfile.o \
+	../crypto/rand/rand_lib.o \
+	../crypto/rand/rand_os2.o \
+	../crypto/rand/rand_unix.o \
+	../crypto/rand/rand_win.o \
+	../crypto/rsa/rsa_lib.o \
+	../crypto/rsa/rsa_none.o \
+	../crypto/rsa/rsa_oaep.o \
+	../crypto/rsa/rsa_pk1.o \
+	../crypto/rsa/rsa_pss.o \
+	../crypto/rsa/rsa_ssl.o \
+	../crypto/rsa/rsa_x931.o \
+	../crypto/sha/sha1dgst.o \
+	../crypto/sha/sha256.o \
+	../crypto/sha/sha512.o \
+	../crypto/uid.o
+
 sub_all: build_all
 build_all: build_libs build_apps build_tests build_tools
 
-build_libs: build_crypto build_ssl build_engines
+build_libs: build_crypto build_fips build_ssl build_shared build_engines
 
 build_crypto:
-	@dir=crypto; target=all; $(BUILD_ONE_CMD)
+	if [ -n "$(FIPSCANLIB)" ]; then \
+		EXCL_OBJ='$(AES_ASM_OBJ) $(BN_ASM) $(DES_ENC) $(CPUID_OBJ) $(SHA1_ASM_OBJ) $(FIPS_EX_OBJ)' ; export EXCL_OBJ ; \
+		ARX='$(PERL) $${TOP}/util/arx.pl $(AR)' ; \
+	else \
+		ARX='${AR}' ; \
+	fi ; export ARX ; \
+		dir=crypto; target=all; $(BUILD_ONE_CMD)
+build_fips:
+	@dir=fips; target=all; [ -z "$(FIPSCANLIB)" ] || $(BUILD_ONE_CMD)
 build_ssl:
 	@dir=ssl; target=all; $(BUILD_ONE_CMD)
 build_engines:
@@ -244,9 +348,20 @@
 build_testapps:
 	@dir=crypto; target=testapps; $(BUILD_ONE_CMD)
 
-libcrypto$(SHLIB_EXT): libcrypto.a
+build_shared:	$(SHARED_LIBS)
+libcrypto$(SHLIB_EXT): libcrypto.a $(SHARED_FIPS)
 	@if [ "$(SHLIB_TARGET)" != "" ]; then \
-		$(MAKE) SHLIBDIRS=crypto build-shared; \
+		if [ "$(FIPSCANLIB)" = "libfips" ]; then \
+			$(ARD) libcrypto.a fipscanister.o ; \
+			$(MAKE) SHLIBDIRS='crypto' SHLIBDEPS='-lfips' build-shared; \
+			$(AR) libcrypto.a fips/fipscanister.o ; \
+		else \
+			if [ "$(FIPSCANLIB)" = "libcrypto" ]; then \
+				FIPSLD_CC=$(CC); CC=fips/fipsld; \
+				export CC FIPSLD_CC; \
+			fi; \
+			$(MAKE) -e SHLIBDIRS='crypto' build-shared; \
+		fi \
 	else \
 		echo "There's no support for shared libraries on this platform" >&2; \
 		exit 1; \
@@ -254,12 +369,32 @@
 
 libssl$(SHLIB_EXT): libcrypto$(SHLIB_EXT) libssl.a
 	@if [ "$(SHLIB_TARGET)" != "" ]; then \
-		$(MAKE) SHLIBDIRS=ssl SHLIBDEPS='-lcrypto' build-shared; \
+		shlibdeps=-lcrypto; \
+		[ "$(FIPSCANLIB)" = "libfips" ] && shlibdeps="$$shlibdeps -lfips"; \
+		$(MAKE) SHLIBDIRS=ssl SHLIBDEPS="$$shlibdeps" build-shared; \
 	else \
+		echo "There's no support for shared libraries on this platform" >&2 ; \
+		exit 1; \
+	fi
+
+fips/fipscanister.o:	build_fips
+libfips$(SHLIB_EXT):		fips/fipscanister.o
+	@if [ "$(SHLIB_TARGET)" != "" ]; then \
+		FIPSLD_CC=$(CC); CC=fips/fipsld; export CC FIPSLD_CC; \
+		$(MAKE) -f Makefile.shared -e $(BUILDENV) \
+			CC=$${CC} LIBNAME=fips THIS=$@ \
+			LIBEXTRAS=fips/fipscanister.o \
+			LIBDEPS="$(EX_LIBS)" \
+			LIBVERSION=${SHLIB_MAJOR}.${SHLIB_MINOR} \
+			link_o.$(SHLIB_TARGET) || { rm -f $@; exit 1; } \
+	else \
 		echo "There's no support for shared libraries on this platform" >&2; \
 		exit 1; \
 	fi
 
+libfips.a:
+	dir=fips; target=all; $(BUILD_ONE_CMD)
+
 clean-shared:
 	@set -e; for i in $(SHLIBDIRS); do \
 		if [ -n "$(SHARED_LIBS_LINK_EXTS)" ]; then \
@@ -369,6 +504,9 @@
 	@$(PERL) $(TOP)/util/mkdir-p.pl include/openssl
 	@$(PERL) $(TOP)/util/mklink.pl include/openssl $(EXHEADER)
 	@set -e; target=links; $(RECURSIVE_BUILD_CMD)
+	@if [ -z "$(FIPSCANLIB)" ]; then \
+		set -e; target=links; dir=fips ; $(BUILD_CMD) ; \
+	fi
 
 gentests:
 	@(cd test && echo "generating dummy tests (if needed)..." && \

Modified: openssl/branches/upstream/current/Makefile.shared
===================================================================
--- openssl/branches/upstream/current/Makefile.shared	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/Makefile.shared	2009-05-16 15:25:35 UTC (rev 372)
@@ -101,15 +101,13 @@
     LIBDEPS="$${LIBDEPS:-$(LIBDEPS)}"; \
     SHAREDCMD="$${SHAREDCMD:-$(CC)}"; \
     SHAREDFLAGS="$${SHAREDFLAGS:-$(CFLAGS) $(SHARED_LDFLAGS)}"; \
-    nm -Pg $$SHOBJECTS | grep ' [BDT] ' | cut -f1 -d' ' > lib$(LIBNAME).exp; \
     LIBPATH=`for x in $$LIBDEPS; do if echo $$x | grep '^ *-L' > /dev/null 2>&1; then echo $$x | sed -e 's/^ *-L//'; fi; done | uniq`; \
     LIBPATH=`echo $$LIBPATH | sed -e 's/ /:/g'`; \
     LD_LIBRARY_PATH=$$LIBPATH:$$LD_LIBRARY_PATH \
     $${SHAREDCMD} $${SHAREDFLAGS} \
 	-o $$SHLIB$$SHLIB_SOVER$$SHLIB_SUFFIX \
 	$$ALLSYMSFLAGS $$SHOBJECTS $$NOALLSYMSFLAGS $$LIBDEPS \
-  ) && $(SYMLINK_SO); \
-  ( $(SET_X); rm -f lib$(LIBNAME).exp )
+  ) && $(SYMLINK_SO)
 
 SYMLINK_SO=	\
 	if [ -n "$$INHIBIT_SYMLINKS" ]; then :; else \
@@ -202,8 +200,10 @@
 # to use native NSModule(3) API and refers to dlfcn as termporary hack.
 link_o.darwin:
 	@ $(CALC_VERSIONS); \
-	SHLIB=lib$(LIBNAME); \
-	SHLIB_SUFFIX=.so; \
+	SHLIB=`expr "$$THIS" : '.*/\([^/\.]*\)\.'`; \
+	SHLIB=$${SHLIB:-lib$(LIBNAME)}; \
+	SHLIB_SUFFIX=`expr "$$THIS" : '.*\(\.[^\.]*\)$$'`; \
+	SHLIB_SUFFIX=$${SHLIB_SUFFIX:-.so}; \
 	ALLSYMSFLAGS='-all_load'; \
 	NOALLSYMSFLAGS=''; \
 	SHAREDFLAGS="$(CFLAGS) $(SHARED_LDFLAGS)"; \
@@ -491,23 +491,23 @@
 
 link_o.aix:
 	@ $(CALC_VERSIONS); \
-	OBJECT_MODE=`expr x$(SHARED_LDFLAGS) : 'x\-[a-z]*\(64\)'` || :; \
+	OBJECT_MODE=`expr "x$(SHARED_LDFLAGS)" : 'x\-[a-z]*\(64\)'` || :; \
 	OBJECT_MODE=$${OBJECT_MODE:-32}; export OBJECT_MODE; \
 	SHLIB=lib$(LIBNAME).so; \
 	SHLIB_SUFFIX=; \
 	ALLSYMSFLAGS=''; \
 	NOALLSYMSFLAGS=''; \
-	SHAREDFLAGS='$(CFLAGS) $(SHARED_LDFLAGS) -Wl,-G,-bexpall,-bnolibpath,-bM:SRE'; \
+	SHAREDFLAGS='$(CFLAGS) $(SHARED_LDFLAGS) -Wl,-bexpall,-bnolibpath,-bM:SRE'; \
 	$(LINK_SO_O);
 link_a.aix:
 	@ $(CALC_VERSIONS); \
-	OBJECT_MODE=`expr x$(SHARED_LDFLAGS) : 'x\-[a-z]*\(64\)'` || : ; \
+	OBJECT_MODE=`expr "x$(SHARED_LDFLAGS)" : 'x\-[a-z]*\(64\)'` || : ; \
 	OBJECT_MODE=$${OBJECT_MODE:-32}; export OBJECT_MODE; \
 	SHLIB=lib$(LIBNAME).so; \
 	SHLIB_SUFFIX=; \
 	ALLSYMSFLAGS='-bnogc'; \
 	NOALLSYMSFLAGS=''; \
-	SHAREDFLAGS='$(CFLAGS) $(SHARED_LDFLAGS) -Wl,-G,-bexpall,-bnolibpath,-bM:SRE'; \
+	SHAREDFLAGS='$(CFLAGS) $(SHARED_LDFLAGS) -Wl,-bexpall,-bnolibpath,-bM:SRE'; \
 	$(LINK_SO_A_VIA_O)
 link_app.aix:
 	LDFLAGS="$(CFLAGS) -Wl,-brtl,-blibpath:$(LIBRPATH):$${LIBPATH:-/usr/lib:/lib}"; \

Added: openssl/branches/upstream/current/apps/CA.sh
===================================================================
--- openssl/branches/upstream/current/apps/CA.sh	                        (rev 0)
+++ openssl/branches/upstream/current/apps/CA.sh	2009-05-16 15:25:35 UTC (rev 372)
@@ -0,0 +1,139 @@
+#!/bin/sh
+#
+# CA - wrapper around ca to make it easier to use ... basically ca requires
+#      some setup stuff to be done before you can use it and this makes
+#      things easier between now and when Eric is convinced to fix it :-)
+#
+# CA -newca ... will setup the right stuff
+# CA -newreq ... will generate a certificate request 
+# CA -sign ... will sign the generated request and output 
+#
+# At the end of that grab newreq.pem and newcert.pem (one has the key 
+# and the other the certificate) and cat them together and that is what
+# you want/need ... I'll make even this a little cleaner later.
+#
+#
+# 12-Jan-96 tjh    Added more things ... including CA -signcert which
+#                  converts a certificate to a request and then signs it.
+# 10-Jan-96 eay    Fixed a few more bugs and added the SSLEAY_CONFIG
+#		   environment variable so this can be driven from
+#		   a script.
+# 25-Jul-96 eay    Cleaned up filenames some more.
+# 11-Jun-96 eay    Fixed a few filename missmatches.
+# 03-May-96 eay    Modified to use 'ssleay cmd' instead of 'cmd'.
+# 18-Apr-96 tjh    Original hacking
+#
+# Tim Hudson
+# tjh at cryptsoft.com
+#
+
+# default openssl.cnf file has setup as per the following
+# demoCA ... where everything is stored
+
+if [ -z "$OPENSSL" ]; then OPENSSL=openssl; fi
+
+DAYS="-days 365"	# 1 year
+CADAYS="-days 1095"	# 3 years
+REQ="$OPENSSL req $SSLEAY_CONFIG"
+CA="$OPENSSL ca $SSLEAY_CONFIG"
+VERIFY="$OPENSSL verify"
+X509="$OPENSSL x509"
+
+CATOP=./demoCA
+CAKEY=./cakey.pem
+CAREQ=./careq.pem
+CACERT=./cacert.pem
+
+for i
+do
+case $i in
+-\?|-h|-help)
+    echo "usage: CA -newcert|-newreq|-newca|-sign|-verify" >&2
+    exit 0
+    ;;
+-newcert) 
+    # create a certificate
+    $REQ -new -x509 -keyout newkey.pem -out newcert.pem $DAYS
+    RET=$?
+    echo "Certificate is in newcert.pem, private key is in newkey.pem"
+    ;;
+-newreq) 
+    # create a certificate request
+    $REQ -new -keyout newkey.pem -out newreq.pem $DAYS
+    RET=$?
+    echo "Request is in newreq.pem, private key is in newkey.pem"
+    ;;
+-newca)     
+    # if explicitly asked for or it doesn't exist then setup the directory
+    # structure that Eric likes to manage things 
+    NEW="1"
+    if [ "$NEW" -o ! -f ${CATOP}/serial ]; then
+	# create the directory hierarchy
+	mkdir ${CATOP} 
+	mkdir ${CATOP}/certs 
+	mkdir ${CATOP}/crl 
+	mkdir ${CATOP}/newcerts
+	mkdir ${CATOP}/private
+	echo "00" > ${CATOP}/serial
+	touch ${CATOP}/index.txt
+    fi
+    if [ ! -f ${CATOP}/private/$CAKEY ]; then
+	echo "CA certificate filename (or enter to create)"
+	read FILE
+
+	# ask user for existing CA certificate
+	if [ "$FILE" ]; then
+	    cp $FILE ${CATOP}/private/$CAKEY
+	    RET=$?
+	else
+	    echo "Making CA certificate ..."
+	    $REQ -new -keyout ${CATOP}/private/$CAKEY \
+			   -out ${CATOP}/$CAREQ
+	    $CA -out ${CATOP}/$CACERT $CADAYS -batch \
+			   -keyfile ${CATOP}/private/$CAKEY -selfsign \
+			   -infiles ${CATOP}/$CAREQ 
+	    RET=$?
+	fi
+    fi
+    ;;
+-xsign)
+    $CA -policy policy_anything -infiles newreq.pem 
+    RET=$?
+    ;;
+-sign|-signreq) 
+    $CA -policy policy_anything -out newcert.pem -infiles newreq.pem
+    RET=$?
+    cat newcert.pem
+    echo "Signed certificate is in newcert.pem"
+    ;;
+-signcert) 
+    echo "Cert passphrase will be requested twice - bug?"
+    $X509 -x509toreq -in newreq.pem -signkey newreq.pem -out tmp.pem
+    $CA -policy policy_anything -out newcert.pem -infiles tmp.pem
+    cat newcert.pem
+    echo "Signed certificate is in newcert.pem"
+    ;;
+-verify) 
+    shift
+    if [ -z "$1" ]; then
+	    $VERIFY -CAfile $CATOP/$CACERT newcert.pem
+	    RET=$?
+    else
+	for j
+	do
+	    $VERIFY -CAfile $CATOP/$CACERT $j
+	    if [ $? != 0 ]; then
+		    RET=$?
+	    fi
+	done
+    fi
+    exit 0
+    ;;
+*)
+    echo "Unknown arg $i";
+    exit 1
+    ;;
+esac
+done
+exit $RET
+

Added: openssl/branches/upstream/current/apps/s_time.c
===================================================================
--- openssl/branches/upstream/current/apps/s_time.c	                        (rev 0)
+++ openssl/branches/upstream/current/apps/s_time.c	2009-05-16 15:25:35 UTC (rev 372)
@@ -0,0 +1,735 @@
+/* apps/s_time.c */
+/* Copyright (C) 1995-1998 Eric Young (eay at cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay at cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh at cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay at cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh at cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#define NO_SHUTDOWN
+
+/*-----------------------------------------
+   s_time - SSL client connection timer program
+   Written and donated by Larry Streepy <streepy at healthcare.com>
+  -----------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define USE_SOCKETS
+#include "apps.h"
+#ifdef OPENSSL_NO_STDIO
+#define APPS_WIN16
+#endif
+#include <openssl/x509.h>
+#include <openssl/ssl.h>
+#include <openssl/pem.h>
+#include "s_apps.h"
+#include <openssl/err.h>
+#ifdef WIN32_STUFF
+#include "winmain.h"
+#include "wintext.h"
+#endif
+#if !defined(OPENSSL_SYS_MSDOS)
+#include OPENSSL_UNISTD
+#endif
+
+#if !defined(OPENSSL_SYS_NETWARE) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VXWORKS) && (!defined(OPENSSL_SYS_VMS) || defined(__DECC))
+#define TIMES
+#endif
+
+#ifndef _IRIX
+#include <time.h>
+#endif
+#ifdef TIMES
+#include <sys/types.h>
+#include <sys/times.h>
+#endif
+
+/* Depending on the VMS version, the tms structure is perhaps defined.
+   The __TMS macro will show if it was.  If it wasn't defined, we should
+   undefine TIMES, since that tells the rest of the program how things
+   should be handled.				-- Richard Levitte */
+#if defined(OPENSSL_SYS_VMS_DECC) && !defined(__TMS)
+#undef TIMES
+#endif
+
+#if !defined(TIMES) && !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_NETWARE)
+#include <sys/timeb.h>
+#endif
+
+#if defined(sun) || defined(__ultrix)
+#define _POSIX_SOURCE
+#include <limits.h>
+#include <sys/param.h>
+#endif
+
+/* The following if from times(3) man page.  It may need to be changed
+*/
+#ifndef HZ
+# ifdef _SC_CLK_TCK
+#  define HZ ((double)sysconf(_SC_CLK_TCK))
+# else
+#  ifndef CLK_TCK
+#   ifndef _BSD_CLK_TCK_ /* FreeBSD hack */
+#    define HZ	100.0
+#   else /* _BSD_CLK_TCK_ */
+#    define HZ ((double)_BSD_CLK_TCK_)
+#   endif
+#  else /* CLK_TCK */
+#   define HZ ((double)CLK_TCK)
+#  endif
+# endif
+#endif
+
+#undef PROG
+#define PROG s_time_main
+
+#undef ioctl
+#define ioctl ioctlsocket
+
+#define SSL_CONNECT_NAME	"localhost:4433"
+
+/*#define TEST_CERT "client.pem" */ /* no default cert. */
+
+#undef BUFSIZZ
+#define BUFSIZZ 1024*10
+
+#define MYBUFSIZ 1024*8
+
+#undef min
+#undef max
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+
+#undef SECONDS
+#define SECONDS	30
+extern int verify_depth;
+extern int verify_error;
+
+static void s_time_usage(void);
+static int parseArgs( int argc, char **argv );
+static SSL *doConnection( SSL *scon );
+static void s_time_init(void);
+
+/***********************************************************************
+ * Static data declarations
+ */
+
+/* static char *port=PORT_STR;*/
+static char *host=SSL_CONNECT_NAME;
+static char *t_cert_file=NULL;
+static char *t_key_file=NULL;
+static char *CApath=NULL;
+static char *CAfile=NULL;
+static char *tm_cipher=NULL;
+static int tm_verify = SSL_VERIFY_NONE;
+static int maxTime = SECONDS;
+static SSL_CTX *tm_ctx=NULL;
+static SSL_METHOD *s_time_meth=NULL;
+static char *s_www_path=NULL;
+static long bytes_read=0; 
+static int st_bugs=0;
+static int perform=0;
+#ifdef FIONBIO
+static int t_nbio=0;
+#endif
+#ifdef OPENSSL_SYS_WIN32
+static int exitNow = 0;		/* Set when it's time to exit main */
+#endif
+
+static void s_time_init(void)
+	{
+	host=SSL_CONNECT_NAME;
+	t_cert_file=NULL;
+	t_key_file=NULL;
+	CApath=NULL;
+	CAfile=NULL;
+	tm_cipher=NULL;
+	tm_verify = SSL_VERIFY_NONE;
+	maxTime = SECONDS;
+	tm_ctx=NULL;
+	s_time_meth=NULL;
+	s_www_path=NULL;
+	bytes_read=0; 
+	st_bugs=0;
+	perform=0;
+
+#ifdef FIONBIO
+	t_nbio=0;
+#endif
+#ifdef OPENSSL_SYS_WIN32
+	exitNow = 0;		/* Set when it's time to exit main */
+#endif
+	}
+
+/***********************************************************************
+ * usage - display usage message
+ */
+static void s_time_usage(void)
+{
+	static char umsg[] = "\
+-time arg     - max number of seconds to collect data, default %d\n\
+-verify arg   - turn on peer certificate verification, arg == depth\n\
+-cert arg     - certificate file to use, PEM format assumed\n\
+-key arg      - RSA file to use, PEM format assumed, key is in cert file\n\
+                file if not specified by this option\n\
+-CApath arg   - PEM format directory of CA's\n\
+-CAfile arg   - PEM format file of CA's\n\
+-cipher       - preferred cipher to use, play with 'openssl ciphers'\n\n";
+
+	printf( "usage: s_time <args>\n\n" );
+
+	printf("-connect host:port - host:port to connect to (default is %s)\n",SSL_CONNECT_NAME);
+#ifdef FIONBIO
+	printf("-nbio         - Run with non-blocking IO\n");
+	printf("-ssl2         - Just use SSLv2\n");
+	printf("-ssl3         - Just use SSLv3\n");
+	printf("-bugs         - Turn on SSL bug compatibility\n");
+	printf("-new          - Just time new connections\n");
+	printf("-reuse        - Just time connection reuse\n");
+	printf("-www page     - Retrieve 'page' from the site\n");
+#endif
+	printf( umsg,SECONDS );
+}
+
+/***********************************************************************
+ * parseArgs - Parse command line arguments and initialize data
+ *
+ * Returns 0 if ok, -1 on bad args
+ */
+static int parseArgs(int argc, char **argv)
+{
+    int badop = 0;
+
+    verify_depth=0;
+    verify_error=X509_V_OK;
+
+    argc--;
+    argv++;
+
+    while (argc >= 1) {
+	if (strcmp(*argv,"-connect") == 0)
+		{
+		if (--argc < 1) goto bad;
+		host= *(++argv);
+		}
+#if 0
+	else if( strcmp(*argv,"-host") == 0)
+		{
+		if (--argc < 1) goto bad;
+		host= *(++argv);
+		}
+	else if( strcmp(*argv,"-port") == 0)
+		{
+		if (--argc < 1) goto bad;
+		port= *(++argv);
+		}
+#endif
+	else if (strcmp(*argv,"-reuse") == 0)
+		perform=2;
+	else if (strcmp(*argv,"-new") == 0)
+		perform=1;
+	else if( strcmp(*argv,"-verify") == 0) {
+
+	    tm_verify=SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE;
+	    if (--argc < 1) goto bad;
+	    verify_depth=atoi(*(++argv));
+	    BIO_printf(bio_err,"verify depth is %d\n",verify_depth);
+
+	} else if( strcmp(*argv,"-cert") == 0) {
+
+	    if (--argc < 1) goto bad;
+	    t_cert_file= *(++argv);
+
+	} else if( strcmp(*argv,"-key") == 0) {
+
+	    if (--argc < 1) goto bad;
+	    t_key_file= *(++argv);
+
+	} else if( strcmp(*argv,"-CApath") == 0) {
+
+	    if (--argc < 1) goto bad;
+	    CApath= *(++argv);
+
+	} else if( strcmp(*argv,"-CAfile") == 0) {
+
+	    if (--argc < 1) goto bad;
+	    CAfile= *(++argv);
+
+	} else if( strcmp(*argv,"-cipher") == 0) {
+
+	    if (--argc < 1) goto bad;
+	    tm_cipher= *(++argv);
+	}
+#ifdef FIONBIO
+	else if(strcmp(*argv,"-nbio") == 0) {
+	    t_nbio=1;
+	}
+#endif
+	else if(strcmp(*argv,"-www") == 0)
+		{
+		if (--argc < 1) goto bad;
+		s_www_path= *(++argv);
+		if(strlen(s_www_path) > MYBUFSIZ-100)
+			{
+			BIO_printf(bio_err,"-www option too long\n");
+			badop=1;
+			}
+		}
+	else if(strcmp(*argv,"-bugs") == 0)
+	    st_bugs=1;
+#ifndef OPENSSL_NO_SSL2
+	else if(strcmp(*argv,"-ssl2") == 0)
+	    s_time_meth=SSLv2_client_method();
+#endif
+#ifndef OPENSSL_NO_SSL3
+	else if(strcmp(*argv,"-ssl3") == 0)
+	    s_time_meth=SSLv3_client_method();
+#endif
+	else if( strcmp(*argv,"-time") == 0) {
+
+	    if (--argc < 1) goto bad;
+	    maxTime= atoi(*(++argv));
+	}
+	else {
+	    BIO_printf(bio_err,"unknown option %s\n",*argv);
+	    badop=1;
+	    break;
+	}
+
+	argc--;
+	argv++;
+    }
+
+    if (perform == 0) perform=3;
+
+    if(badop) {
+bad:
+		s_time_usage();
+		return -1;
+    }
+
+	return 0;			/* Valid args */
+}
+
+/***********************************************************************
+ * TIME - time functions
+ */
+#define START	0
+#define STOP	1
+
+static double tm_Time_F(int s)
+	{
+	static double ret;
+#ifdef TIMES
+	static struct tms tstart,tend;
+
+	if(s == START) {
+		times(&tstart);
+		return(0);
+	} else {
+		times(&tend);
+		ret=((double)(tend.tms_utime-tstart.tms_utime))/HZ;
+		return((ret == 0.0)?1e-6:ret);
+	}
+#elif defined(OPENSSL_SYS_NETWARE)
+    static clock_t tstart,tend;
+
+    if (s == START)
+    {
+        tstart=clock();
+        return(0);
+    }
+    else
+    {
+        tend=clock();
+        ret=(double)((double)(tend)-(double)(tstart));
+        return((ret < 0.001)?0.001:ret);
+    }
+#elif defined(OPENSSL_SYS_VXWORKS)
+        {
+	static unsigned long tick_start, tick_end;
+
+	if( s == START )
+		{
+		tick_start = tickGet();
+		return 0;
+		}
+	else
+		{
+		tick_end = tickGet();
+		ret = (double)(tick_end - tick_start) / (double)sysClkRateGet();
+		return((ret == 0.0)?1e-6:ret);
+		}
+        }
+#else /* !times() */
+	static struct timeb tstart,tend;
+	long i;
+
+	if(s == START) {
+		ftime(&tstart);
+		return(0);
+	} else {
+		ftime(&tend);
+		i=(long)tend.millitm-(long)tstart.millitm;
+		ret=((double)(tend.time-tstart.time))+((double)i)/1000.0;
+		return((ret == 0.0)?1e-6:ret);
+	}
+#endif
+}
+
+/***********************************************************************
+ * MAIN - main processing area for client
+ *			real name depends on MONOLITH
+ */
+int MAIN(int, char **);
+
+int MAIN(int argc, char **argv)
+	{
+	double totalTime = 0.0;
+	int nConn = 0;
+	SSL *scon=NULL;
+	long finishtime=0;
+	int ret=1,i;
+	MS_STATIC char buf[1024*8];
+	int ver;
+
+	apps_startup();
+	s_time_init();
+
+	if (bio_err == NULL)
+		bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
+
+#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
+	s_time_meth=SSLv23_client_method();
+#elif !defined(OPENSSL_NO_SSL3)
+	s_time_meth=SSLv3_client_method();
+#elif !defined(OPENSSL_NO_SSL2)
+	s_time_meth=SSLv2_client_method();
+#endif
+
+	/* parse the command line arguments */
+	if( parseArgs( argc, argv ) < 0 )
+		goto end;
+
+	OpenSSL_add_ssl_algorithms();
+	if ((tm_ctx=SSL_CTX_new(s_time_meth)) == NULL) return(1);
+
+	SSL_CTX_set_quiet_shutdown(tm_ctx,1);
+
+	if (st_bugs) SSL_CTX_set_options(tm_ctx,SSL_OP_ALL);
+	SSL_CTX_set_cipher_list(tm_ctx,tm_cipher);
+	if(!set_cert_stuff(tm_ctx,t_cert_file,t_key_file)) 
+		goto end;
+
+	SSL_load_error_strings();
+
+	if ((!SSL_CTX_load_verify_locations(tm_ctx,CAfile,CApath)) ||
+		(!SSL_CTX_set_default_verify_paths(tm_ctx)))
+		{
+		/* BIO_printf(bio_err,"error setting default verify locations\n"); */
+		ERR_print_errors(bio_err);
+		/* goto end; */
+		}
+
+	if (tm_cipher == NULL)
+		tm_cipher = getenv("SSL_CIPHER");
+
+	if (tm_cipher == NULL ) {
+		fprintf( stderr, "No CIPHER specified\n" );
+	}
+
+	if (!(perform & 1)) goto next;
+	printf( "Collecting connection statistics for %d seconds\n", maxTime );
+
+	/* Loop and time how long it takes to make connections */
+
+	bytes_read=0;
+	finishtime=(long)time(NULL)+maxTime;
+	tm_Time_F(START);
+	for (;;)
+		{
+		if (finishtime < (long)time(NULL)) break;
+#ifdef WIN32_STUFF
+
+		if( flushWinMsgs(0) == -1 )
+			goto end;
+
+		if( waitingToDie || exitNow )		/* we're dead */
+			goto end;
+#endif
+
+		if( (scon = doConnection( NULL )) == NULL )
+			goto end;
+
+		if (s_www_path != NULL)
+			{
+			BIO_snprintf(buf,sizeof buf,"GET %s HTTP/1.0\r\n\r\n",s_www_path);
+			SSL_write(scon,buf,strlen(buf));
+			while ((i=SSL_read(scon,buf,sizeof(buf))) > 0)
+				bytes_read+=i;
+			}
+
+#ifdef NO_SHUTDOWN
+		SSL_set_shutdown(scon,SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
+#else
+		SSL_shutdown(scon);
+#endif
+		SHUTDOWN2(SSL_get_fd(scon));
+
+		nConn += 1;
+		if (SSL_session_reused(scon))
+			ver='r';
+		else
+			{
+			ver=SSL_version(scon);
+			if (ver == TLS1_VERSION)
+				ver='t';
+			else if (ver == SSL3_VERSION)
+				ver='3';
+			else if (ver == SSL2_VERSION)
+				ver='2';
+			else
+				ver='*';
+			}
+		fputc(ver,stdout);
+		fflush(stdout);
+
+		SSL_free( scon );
+		scon=NULL;
+		}
+	totalTime += tm_Time_F(STOP); /* Add the time for this iteration */
+
+	i=(int)((long)time(NULL)-finishtime+maxTime);
+	printf( "\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n", nConn, totalTime, ((double)nConn/totalTime),bytes_read);
+	printf( "%d connections in %ld real seconds, %ld bytes read per connection\n",nConn,(long)time(NULL)-finishtime+maxTime,bytes_read/nConn);
+
+	/* Now loop and time connections using the same session id over and over */
+
+next:
+	if (!(perform & 2)) goto end;
+	printf( "\n\nNow timing with session id reuse.\n" );
+
+	/* Get an SSL object so we can reuse the session id */
+	if( (scon = doConnection( NULL )) == NULL )
+		{
+		fprintf( stderr, "Unable to get connection\n" );
+		goto end;
+		}
+
+	if (s_www_path != NULL)
+		{
+		BIO_snprintf(buf,sizeof buf,"GET %s HTTP/1.0\r\n\r\n",s_www_path);
+		SSL_write(scon,buf,strlen(buf));
+		while (SSL_read(scon,buf,sizeof(buf)) > 0)
+			;
+		}
+#ifdef NO_SHUTDOWN
+	SSL_set_shutdown(scon,SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
+#else
+	SSL_shutdown(scon);
+#endif
+	SHUTDOWN2(SSL_get_fd(scon));
+
+	nConn = 0;
+	totalTime = 0.0;
+
+	finishtime=(long)time(NULL)+maxTime;
+
+	printf( "starting\n" );
+	bytes_read=0;
+	tm_Time_F(START);
+		
+	for (;;)
+		{
+		if (finishtime < (long)time(NULL)) break;
+
+#ifdef WIN32_STUFF
+		if( flushWinMsgs(0) == -1 )
+			goto end;
+
+		if( waitingToDie || exitNow )	/* we're dead */
+			goto end;
+#endif
+
+	 	if( (doConnection( scon )) == NULL )
+			goto end;
+
+		if (s_www_path)
+			{
+			BIO_snprintf(buf,sizeof buf,"GET %s HTTP/1.0\r\n\r\n",s_www_path);
+			SSL_write(scon,buf,strlen(buf));
+			while ((i=SSL_read(scon,buf,sizeof(buf))) > 0)
+				bytes_read+=i;
+			}
+
+#ifdef NO_SHUTDOWN
+		SSL_set_shutdown(scon,SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
+#else
+		SSL_shutdown(scon);
+#endif
+		SHUTDOWN2(SSL_get_fd(scon));
+	
+		nConn += 1;
+		if (SSL_session_reused(scon))
+			ver='r';
+		else
+			{
+			ver=SSL_version(scon);
+			if (ver == TLS1_VERSION)
+				ver='t';
+			else if (ver == SSL3_VERSION)
+				ver='3';
+			else if (ver == SSL2_VERSION)
+				ver='2';
+			else
+				ver='*';
+			}
+		fputc(ver,stdout);
+		fflush(stdout);
+		}
+	totalTime += tm_Time_F(STOP); /* Add the time for this iteration*/
+
+
+	printf( "\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n", nConn, totalTime, ((double)nConn/totalTime),bytes_read);
+	printf( "%d connections in %ld real seconds, %ld bytes read per connection\n",nConn,(long)time(NULL)-finishtime+maxTime,bytes_read/nConn);
+
+	ret=0;
+end:
+	if (scon != NULL) SSL_free(scon);
+
+	if (tm_ctx != NULL)
+		{
+		SSL_CTX_free(tm_ctx);
+		tm_ctx=NULL;
+		}
+	apps_shutdown();
+	OPENSSL_EXIT(ret);
+	}
+
+/***********************************************************************
+ * doConnection - make a connection
+ * Args:
+ *		scon	= earlier ssl connection for session id, or NULL
+ * Returns:
+ *		SSL *	= the connection pointer.
+ */
+static SSL *doConnection(SSL *scon)
+	{
+	BIO *conn;
+	SSL *serverCon;
+	int width, i;
+	fd_set readfds;
+
+	if ((conn=BIO_new(BIO_s_connect())) == NULL)
+		return(NULL);
+
+/*	BIO_set_conn_port(conn,port);*/
+	BIO_set_conn_hostname(conn,host);
+
+	if (scon == NULL)
+		serverCon=SSL_new(tm_ctx);
+	else
+		{
+		serverCon=scon;
+		SSL_set_connect_state(serverCon);
+		}
+
+	SSL_set_bio(serverCon,conn,conn);
+
+#if 0
+	if( scon != NULL )
+		SSL_set_session(serverCon,SSL_get_session(scon));
+#endif
+
+	/* ok, lets connect */
+	for(;;) {
+		i=SSL_connect(serverCon);
+		if (BIO_sock_should_retry(i))
+			{
+			BIO_printf(bio_err,"DELAY\n");
+
+			i=SSL_get_fd(serverCon);
+			width=i+1;
+			FD_ZERO(&readfds);
+			FD_SET(i,&readfds);
+			/* Note: under VMS with SOCKETSHR the 2nd parameter
+			 * is currently of type (int *) whereas under other
+			 * systems it is (void *) if you don't have a cast it
+			 * will choke the compiler: if you do have a cast then
+			 * you can either go for (int *) or (void *).
+			 */
+			select(width,(void *)&readfds,NULL,NULL,NULL);
+			continue;
+			}
+		break;
+		}
+	if(i <= 0)
+		{
+		BIO_printf(bio_err,"ERROR\n");
+		if (verify_error != X509_V_OK)
+			BIO_printf(bio_err,"verify error:%s\n",
+				X509_verify_cert_error_string(verify_error));
+		else
+			ERR_print_errors(bio_err);
+		if (scon == NULL)
+			SSL_free(serverCon);
+		return NULL;
+		}
+
+	return serverCon;
+	}
+
+

Added: openssl/branches/upstream/current/apps/speed.c
===================================================================
--- openssl/branches/upstream/current/apps/speed.c	                        (rev 0)
+++ openssl/branches/upstream/current/apps/speed.c	2009-05-16 15:25:35 UTC (rev 372)
@@ -0,0 +1,2930 @@
+/* apps/speed.c -*- mode:C; c-file-style: "eay" -*- */
+/* Copyright (C) 1995-1998 Eric Young (eay at cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay at cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh at cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay at cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh at cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * Portions of the attached software ("Contribution") are developed by 
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the OpenSSL open source
+ * license provided above.
+ *
+ * The ECDH and ECDSA speed test software is originally written by 
+ * Sumit Gupta of Sun Microsystems Laboratories.
+ *
+ */
+
+/* most of this code has been pilfered from my libdes speed.c program */
+
+#ifndef OPENSSL_NO_SPEED
+
+#undef SECONDS
+#define SECONDS		3	
+#define RSA_SECONDS	10
+#define DSA_SECONDS	10
+#define ECDSA_SECONDS   10
+#define ECDH_SECONDS    10
+
+/* 11-Sep-92 Andrew Daviel   Support for Silicon Graphics IRIX added */
+/* 06-Apr-92 Luke Brennan    Support for VMS and add extra signal calls */
+
+#undef PROG
+#define PROG speed_main
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <string.h>
+#include <math.h>
+#include "apps.h"
+#ifdef OPENSSL_NO_STDIO
+#define APPS_WIN16
+#endif
+#include <openssl/crypto.h>
+#include <openssl/rand.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/objects.h>
+#if !defined(OPENSSL_SYS_MSDOS)
+#include OPENSSL_UNISTD
+#endif
+
+#ifndef OPENSSL_SYS_NETWARE
+#include <signal.h>
+#endif
+
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(OPENSSL_SYS_MACOSX)
+# define USE_TOD
+#elif !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VXWORKS) && (!defined(OPENSSL_SYS_VMS) || defined(__DECC))
+# define TIMES
+#endif
+#if !defined(_UNICOS) && !defined(__OpenBSD__) && !defined(sgi) && !defined(__FreeBSD__) && !(defined(__bsdi) || defined(__bsdi__)) && !defined(_AIX) && !defined(OPENSSL_SYS_MPE) && !defined(__NetBSD__) && !defined(OPENSSL_SYS_VXWORKS) /* FIXME */
+# define TIMEB
+#endif
+
+#if defined(OPENSSL_SYS_NETWARE)
+#undef TIMES
+#undef TIMEB
+#include <time.h>
+#endif
+
+#ifndef _IRIX
+# include <time.h>
+#endif
+#ifdef TIMES
+# include <sys/types.h>
+# include <sys/times.h>
+#endif
+#ifdef USE_TOD
+# include <sys/time.h>
+# include <sys/resource.h>
+#endif
+
+/* Depending on the VMS version, the tms structure is perhaps defined.
+   The __TMS macro will show if it was.  If it wasn't defined, we should
+   undefine TIMES, since that tells the rest of the program how things
+   should be handled.				-- Richard Levitte */
+#if defined(OPENSSL_SYS_VMS_DECC) && !defined(__TMS)
+#undef TIMES
+#endif
+
+#ifdef TIMEB
+#include <sys/timeb.h>
+#endif
+
+#if !defined(TIMES) && !defined(TIMEB) && !defined(USE_TOD) && !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_NETWARE)
+#error "It seems neither struct tms nor struct timeb is supported in this platform!"
+#endif
+
+#if defined(sun) || defined(__ultrix)
+#define _POSIX_SOURCE
+#include <limits.h>
+#include <sys/param.h>
+#endif
+
+#include <openssl/bn.h>
+#ifndef OPENSSL_NO_DES
+#include <openssl/des.h>
+#endif
+#ifndef OPENSSL_NO_AES
+#include <openssl/aes.h>
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+#include <openssl/camellia.h>
+#endif
+#ifndef OPENSSL_NO_MD2
+#include <openssl/md2.h>
+#endif
+#ifndef OPENSSL_NO_MDC2
+#include <openssl/mdc2.h>
+#endif
+#ifndef OPENSSL_NO_MD4
+#include <openssl/md4.h>
+#endif
+#ifndef OPENSSL_NO_MD5
+#include <openssl/md5.h>
+#endif
+#ifndef OPENSSL_NO_HMAC
+#include <openssl/hmac.h>
+#endif
+#include <openssl/evp.h>
+#ifndef OPENSSL_NO_SHA
+#include <openssl/sha.h>
+#endif
+#ifndef OPENSSL_NO_RIPEMD
+#include <openssl/ripemd.h>
+#endif
+#ifndef OPENSSL_NO_RC4
+#include <openssl/rc4.h>
+#endif
+#ifndef OPENSSL_NO_RC5
+#include <openssl/rc5.h>
+#endif
+#ifndef OPENSSL_NO_RC2
+#include <openssl/rc2.h>
+#endif
+#ifndef OPENSSL_NO_IDEA
+#include <openssl/idea.h>
+#endif
+#ifndef OPENSSL_NO_SEED
+#include <openssl/seed.h>
+#endif
+#ifndef OPENSSL_NO_BF
+#include <openssl/blowfish.h>
+#endif
+#ifndef OPENSSL_NO_CAST
+#include <openssl/cast.h>
+#endif
+#ifndef OPENSSL_NO_RSA
+#include <openssl/rsa.h>
+#include "./testrsa.h"
+#endif
+#include <openssl/x509.h>
+#ifndef OPENSSL_NO_DSA
+#include <openssl/dsa.h>
+#include "./testdsa.h"
+#endif
+#ifndef OPENSSL_NO_ECDSA
+#include <openssl/ecdsa.h>
+#endif
+#ifndef OPENSSL_NO_ECDH
+#include <openssl/ecdh.h>
+#endif
+
+/*
+ * The following "HZ" timing stuff should be sync'd up with the code in
+ * crypto/tmdiff.[ch]. That appears to try to do the same job, though I think
+ * this code is more up to date than libcrypto's so there may be features to
+ * migrate over first. This is used in two places further down AFAICS. 
+ * The point is that nothing in openssl actually *uses* that tmdiff stuff, so
+ * either speed.c should be using it or it should go because it's obviously not
+ * useful enough. Anyone want to do a janitorial job on this?
+ */
+
+/* The following if from times(3) man page.  It may need to be changed */
+#ifndef HZ
+# if defined(_SC_CLK_TCK) \
+     && (!defined(OPENSSL_SYS_VMS) || __CTRL_VER >= 70000000)
+#  define HZ sysconf(_SC_CLK_TCK)
+# else
+#  ifndef CLK_TCK
+#   ifndef _BSD_CLK_TCK_ /* FreeBSD hack */
+#    define HZ	100.0
+#   else /* _BSD_CLK_TCK_ */
+#    define HZ ((double)_BSD_CLK_TCK_)
+#   endif
+#  else /* CLK_TCK */
+#   define HZ ((double)CLK_TCK)
+#  endif
+# endif
+#endif
+
+#if !defined(OPENSSL_SYS_VMS) && !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MACINTOSH_CLASSIC) && !defined(OPENSSL_SYS_OS2) && !defined(OPENSSL_SYS_NETWARE)
+# define HAVE_FORK 1
+#endif
+
+#undef BUFSIZE
+#define BUFSIZE	((long)1024*8+1)
+int run=0;
+
+static char ftime_used = 0, times_used = 0, gettimeofday_used = 0, getrusage_used = 0;
+static int mr=0;
+static int usertime=1;
+
+static double Time_F(int s);
+static void print_message(const char *s,long num,int length);
+static void pkey_print_message(const char *str, const char *str2,
+	long num, int bits, int sec);
+static void print_result(int alg,int run_no,int count,double time_used);
+#ifdef HAVE_FORK
+static int do_multi(int multi);
+#endif
+
+#define ALGOR_NUM	28
+#define SIZE_NUM	5
+#define RSA_NUM		4
+#define DSA_NUM		3
+
+#define EC_NUM       16
+#define MAX_ECDH_SIZE 256
+
+static const char *names[ALGOR_NUM]={
+  "md2","mdc2","md4","md5","hmac(md5)","sha1","rmd160","rc4",
+  "des cbc","des ede3","idea cbc","seed cbc",
+  "rc2 cbc","rc5-32/12 cbc","blowfish cbc","cast cbc",
+  "aes-128 cbc","aes-192 cbc","aes-256 cbc",
+  "camellia-128 cbc","camellia-192 cbc","camellia-256 cbc",
+  "evp","sha256","sha512",
+  "aes-128 ige","aes-192 ige","aes-256 ige"};
+static double results[ALGOR_NUM][SIZE_NUM];
+static int lengths[SIZE_NUM]={16,64,256,1024,8*1024};
+static double rsa_results[RSA_NUM][2];
+static double dsa_results[DSA_NUM][2];
+#ifndef OPENSSL_NO_ECDSA
+static double ecdsa_results[EC_NUM][2];
+#endif
+#ifndef OPENSSL_NO_ECDH
+static double ecdh_results[EC_NUM][1];
+#endif
+
+#if defined(OPENSSL_NO_DSA) && !(defined(OPENSSL_NO_ECDSA) && defined(OPENSSL_NO_ECDH))
+static const char rnd_seed[] = "string to make the random number generator think it has entropy";
+static int rnd_fake = 0;
+#endif
+
+#ifdef SIGALRM
+#if defined(__STDC__) || defined(sgi) || defined(_AIX)
+#define SIGRETTYPE void
+#else
+#define SIGRETTYPE int
+#endif 
+
+static SIGRETTYPE sig_done(int sig);
+static SIGRETTYPE sig_done(int sig)
+	{
+	signal(SIGALRM,sig_done);
+	run=0;
+#ifdef LINT
+	sig=sig;
+#endif
+	}
+#endif
+
+#define START	0
+#define STOP	1
+
+#if defined(OPENSSL_SYS_NETWARE)
+
+   /* for NetWare the best we can do is use clock() which returns the
+    * time, in hundredths of a second, since the NLM began executing
+   */
+static double Time_F(int s)
+	{
+	double ret;
+
+   static clock_t tstart,tend;
+
+   if (s == START)
+   {
+      tstart=clock();
+      return(0);
+   }
+   else
+   {
+      tend=clock();
+      ret=(double)((double)(tend)-(double)(tstart));
+      return((ret < 0.001)?0.001:ret);
+   }
+   }
+
+#else
+
+static double Time_F(int s)
+	{
+	double ret;
+
+#ifdef USE_TOD
+	if(usertime)
+		{
+		static struct rusage tstart,tend;
+
+		getrusage_used = 1;
+		if (s == START)
+			{
+			getrusage(RUSAGE_SELF,&tstart);
+			return(0);
+			}
+		else
+			{
+			long i;
+
+			getrusage(RUSAGE_SELF,&tend);
+			i=(long)tend.ru_utime.tv_usec-(long)tstart.ru_utime.tv_usec;
+			ret=((double)(tend.ru_utime.tv_sec-tstart.ru_utime.tv_sec))
+			  +((double)i)/1000000.0;
+			return((ret < 0.001)?0.001:ret);
+			}
+		}
+	else
+		{
+		static struct timeval tstart,tend;
+		long i;
+
+		gettimeofday_used = 1;
+		if (s == START)
+			{
+			gettimeofday(&tstart,NULL);
+			return(0);
+			}
+		else
+			{
+			gettimeofday(&tend,NULL);
+			i=(long)tend.tv_usec-(long)tstart.tv_usec;
+			ret=((double)(tend.tv_sec-tstart.tv_sec))+((double)i)/1000000.0;
+			return((ret < 0.001)?0.001:ret);
+			}
+		}
+#else  /* ndef USE_TOD */
+		
+# ifdef TIMES
+	if (usertime)
+		{
+		static struct tms tstart,tend;
+
+		times_used = 1;
+		if (s == START)
+			{
+			times(&tstart);
+			return(0);
+			}
+		else
+			{
+			times(&tend);
+			ret = HZ;
+			ret=(double)(tend.tms_utime-tstart.tms_utime) / ret;
+			return((ret < 1e-3)?1e-3:ret);
+			}
+		}
+# endif /* times() */
+# if defined(TIMES) && defined(TIMEB)
+	else
+# endif
+# ifdef OPENSSL_SYS_VXWORKS
+                {
+		static unsigned long tick_start, tick_end;
+
+		if( s == START )
+			{
+			tick_start = tickGet();
+			return 0;
+			}
+		else
+			{
+			tick_end = tickGet();
+			ret = (double)(tick_end - tick_start) / (double)sysClkRateGet();
+			return((ret < 0.001)?0.001:ret);
+			}
+                }
+# elif defined(TIMEB)
+		{
+		static struct timeb tstart,tend;
+		long i;
+
+		ftime_used = 1;
+		if (s == START)
+			{
+			ftime(&tstart);
+			return(0);
+			}
+		else
+			{
+			ftime(&tend);
+			i=(long)tend.millitm-(long)tstart.millitm;
+			ret=((double)(tend.time-tstart.time))+((double)i)/1000.0;
+			return((ret < 0.001)?0.001:ret);
+			}
+		}
+# endif
+#endif
+	}
+#endif /* if defined(OPENSSL_SYS_NETWARE) */
+
+
+#ifndef OPENSSL_NO_ECDH
+static const int KDF1_SHA1_len = 20;
+static void *KDF1_SHA1(const void *in, size_t inlen, void *out, size_t *outlen)
+	{
+#ifndef OPENSSL_NO_SHA
+	if (*outlen < SHA_DIGEST_LENGTH)
+		return NULL;
+	else
+		*outlen = SHA_DIGEST_LENGTH;
+	return SHA1(in, inlen, out);
+#else
+	return NULL;
+#endif	/* OPENSSL_NO_SHA */
+	}
+#endif	/* OPENSSL_NO_ECDH */
+
+
+int MAIN(int, char **);
+
+int MAIN(int argc, char **argv)
+	{
+#ifndef OPENSSL_NO_ENGINE
+	ENGINE *e = NULL;
+#endif
+	unsigned char *buf=NULL,*buf2=NULL;
+	int mret=1;
+	long count=0,save_count=0;
+	int i,j,k;
+#if !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_DSA)
+	long rsa_count;
+#endif
+#ifndef OPENSSL_NO_RSA
+	unsigned rsa_num;
+#endif
+	unsigned char md[EVP_MAX_MD_SIZE];
+#ifndef OPENSSL_NO_MD2
+	unsigned char md2[MD2_DIGEST_LENGTH];
+#endif
+#ifndef OPENSSL_NO_MDC2
+	unsigned char mdc2[MDC2_DIGEST_LENGTH];
+#endif
+#ifndef OPENSSL_NO_MD4
+	unsigned char md4[MD4_DIGEST_LENGTH];
+#endif
+#ifndef OPENSSL_NO_MD5
+	unsigned char md5[MD5_DIGEST_LENGTH];
+	unsigned char hmac[MD5_DIGEST_LENGTH];
+#endif
+#ifndef OPENSSL_NO_SHA
+	unsigned char sha[SHA_DIGEST_LENGTH];
+#ifndef OPENSSL_NO_SHA256
+	unsigned char sha256[SHA256_DIGEST_LENGTH];
+#endif
+#ifndef OPENSSL_NO_SHA512
+	unsigned char sha512[SHA512_DIGEST_LENGTH];
+#endif
+#endif
+#ifndef OPENSSL_NO_RIPEMD
+	unsigned char rmd160[RIPEMD160_DIGEST_LENGTH];
+#endif
+#ifndef OPENSSL_NO_RC4
+	RC4_KEY rc4_ks;
+#endif
+#ifndef OPENSSL_NO_RC5
+	RC5_32_KEY rc5_ks;
+#endif
+#ifndef OPENSSL_NO_RC2
+	RC2_KEY rc2_ks;
+#endif
+#ifndef OPENSSL_NO_IDEA
+	IDEA_KEY_SCHEDULE idea_ks;
+#endif
+#ifndef OPENSSL_NO_SEED
+	SEED_KEY_SCHEDULE seed_ks;
+#endif
+#ifndef OPENSSL_NO_BF
+	BF_KEY bf_ks;
+#endif
+#ifndef OPENSSL_NO_CAST
+	CAST_KEY cast_ks;
+#endif
+	static const unsigned char key16[16]=
+		{0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,
+		 0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12};
+#ifndef OPENSSL_NO_AES
+	static const unsigned char key24[24]=
+		{0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,
+		 0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,
+		 0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,0x34};
+	static const unsigned char key32[32]=
+		{0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,
+		 0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,
+		 0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,0x34,
+		 0x78,0x9a,0xbc,0xde,0xf0,0x12,0x34,0x56};
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+	static const unsigned char ckey24[24]=
+		{0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,
+		 0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,
+		 0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,0x34};
+	static const unsigned char ckey32[32]=
+		{0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,
+		 0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,
+		 0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,0x34,
+		 0x78,0x9a,0xbc,0xde,0xf0,0x12,0x34,0x56};
+#endif
+#ifndef OPENSSL_NO_AES
+#define MAX_BLOCK_SIZE 128
+#else
+#define MAX_BLOCK_SIZE 64
+#endif
+	unsigned char DES_iv[8];
+	unsigned char iv[2*MAX_BLOCK_SIZE/8];
+#ifndef OPENSSL_NO_DES
+	DES_cblock *buf_as_des_cblock = NULL;
+	static DES_cblock key ={0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0};
+	static DES_cblock key2={0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12};
+	static DES_cblock key3={0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,0x34};
+	DES_key_schedule sch;
+	DES_key_schedule sch2;
+	DES_key_schedule sch3;
+#endif
+#ifndef OPENSSL_NO_AES
+	AES_KEY aes_ks1, aes_ks2, aes_ks3;
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+	CAMELLIA_KEY camellia_ks1, camellia_ks2, camellia_ks3;
+#endif
+#define	D_MD2		0
+#define	D_MDC2		1
+#define	D_MD4		2
+#define	D_MD5		3
+#define	D_HMAC		4
+#define	D_SHA1		5
+#define D_RMD160	6
+#define	D_RC4		7
+#define	D_CBC_DES	8
+#define	D_EDE3_DES	9
+#define	D_CBC_IDEA	10
+#define	D_CBC_SEED	11
+#define	D_CBC_RC2	12
+#define	D_CBC_RC5	13
+#define	D_CBC_BF	14
+#define	D_CBC_CAST	15
+#define D_CBC_128_AES	16
+#define D_CBC_192_AES	17
+#define D_CBC_256_AES	18
+#define D_CBC_128_CML   19 
+#define D_CBC_192_CML   20
+#define D_CBC_256_CML   21 
+#define D_EVP		22
+#define D_SHA256	23	
+#define D_SHA512	24
+#define D_IGE_128_AES   25
+#define D_IGE_192_AES   26
+#define D_IGE_256_AES   27
+	double d=0.0;
+	long c[ALGOR_NUM][SIZE_NUM];
+#define	R_DSA_512	0
+#define	R_DSA_1024	1
+#define	R_DSA_2048	2
+#define	R_RSA_512	0
+#define	R_RSA_1024	1
+#define	R_RSA_2048	2
+#define	R_RSA_4096	3
+
+#define R_EC_P160    0
+#define R_EC_P192    1	
+#define R_EC_P224    2
+#define R_EC_P256    3
+#define R_EC_P384    4
+#define R_EC_P521    5
+#define R_EC_K163    6
+#define R_EC_K233    7
+#define R_EC_K283    8
+#define R_EC_K409    9
+#define R_EC_K571    10
+#define R_EC_B163    11
+#define R_EC_B233    12
+#define R_EC_B283    13
+#define R_EC_B409    14
+#define R_EC_B571    15
+
+#ifndef OPENSSL_NO_RSA
+	RSA *rsa_key[RSA_NUM];
+	long rsa_c[RSA_NUM][2];
+	static unsigned int rsa_bits[RSA_NUM]={512,1024,2048,4096};
+	static unsigned char *rsa_data[RSA_NUM]=
+		{test512,test1024,test2048,test4096};
+	static int rsa_data_length[RSA_NUM]={
+		sizeof(test512),sizeof(test1024),
+		sizeof(test2048),sizeof(test4096)};
+#endif
+#ifndef OPENSSL_NO_DSA
+	DSA *dsa_key[DSA_NUM];
+	long dsa_c[DSA_NUM][2];
+	static unsigned int dsa_bits[DSA_NUM]={512,1024,2048};
+#endif
+#ifndef OPENSSL_NO_EC
+	/* We only test over the following curves as they are representative, 
+	 * To add tests over more curves, simply add the curve NID
+	 * and curve name to the following arrays and increase the 
+	 * EC_NUM value accordingly. 
+	 */
+	static unsigned int test_curves[EC_NUM] = 
+	{	
+	/* Prime Curves */
+	NID_secp160r1,
+	NID_X9_62_prime192v1,
+	NID_secp224r1,
+	NID_X9_62_prime256v1,
+	NID_secp384r1,
+	NID_secp521r1,
+	/* Binary Curves */
+	NID_sect163k1,
+	NID_sect233k1,
+	NID_sect283k1,
+	NID_sect409k1,
+	NID_sect571k1,
+	NID_sect163r2,
+	NID_sect233r1,
+	NID_sect283r1,
+	NID_sect409r1,
+	NID_sect571r1
+	}; 
+	static const char * test_curves_names[EC_NUM] = 
+	{
+	/* Prime Curves */
+	"secp160r1",
+	"nistp192",
+	"nistp224",
+	"nistp256",
+	"nistp384",
+	"nistp521",
+	/* Binary Curves */
+	"nistk163",
+	"nistk233",
+	"nistk283",
+	"nistk409",
+	"nistk571",
+	"nistb163",
+	"nistb233",
+	"nistb283",
+	"nistb409",
+	"nistb571"
+	};
+	static int test_curves_bits[EC_NUM] =
+        {
+        160, 192, 224, 256, 384, 521,
+        163, 233, 283, 409, 571,
+        163, 233, 283, 409, 571
+        };
+
+#endif
+
+#ifndef OPENSSL_NO_ECDSA
+	unsigned char ecdsasig[256];
+	unsigned int ecdsasiglen;
+	EC_KEY *ecdsa[EC_NUM];
+	long ecdsa_c[EC_NUM][2];
+#endif
+
+#ifndef OPENSSL_NO_ECDH
+	EC_KEY *ecdh_a[EC_NUM], *ecdh_b[EC_NUM];
+	unsigned char secret_a[MAX_ECDH_SIZE], secret_b[MAX_ECDH_SIZE];
+	int secret_size_a, secret_size_b;
+	int ecdh_checks = 0;
+	int secret_idx = 0;
+	long ecdh_c[EC_NUM][2];
+#endif
+
+	int rsa_doit[RSA_NUM];
+	int dsa_doit[DSA_NUM];
+#ifndef OPENSSL_NO_ECDSA
+	int ecdsa_doit[EC_NUM];
+#endif
+#ifndef OPENSSL_NO_ECDH
+        int ecdh_doit[EC_NUM];
+#endif
+	int doit[ALGOR_NUM];
+	int pr_header=0;
+	const EVP_CIPHER *evp_cipher=NULL;
+	const EVP_MD *evp_md=NULL;
+	int decrypt=0;
+#ifdef HAVE_FORK
+	int multi=0;
+#endif
+
+#ifndef TIMES
+	usertime=-1;
+#endif
+
+	apps_startup();
+	memset(results, 0, sizeof(results));
+#ifndef OPENSSL_NO_DSA
+	memset(dsa_key,0,sizeof(dsa_key));
+#endif
+#ifndef OPENSSL_NO_ECDSA
+	for (i=0; i<EC_NUM; i++) ecdsa[i] = NULL;
+#endif
+#ifndef OPENSSL_NO_ECDH
+	for (i=0; i<EC_NUM; i++)
+		{
+		ecdh_a[i] = NULL;
+		ecdh_b[i] = NULL;
+		}
+#endif
+
+
+	if (bio_err == NULL)
+		if ((bio_err=BIO_new(BIO_s_file())) != NULL)
+			BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
+
+	if (!load_config(bio_err, NULL))
+		goto end;
+
+#ifndef OPENSSL_NO_RSA
+	memset(rsa_key,0,sizeof(rsa_key));
+	for (i=0; i<RSA_NUM; i++)
+		rsa_key[i]=NULL;
+#endif
+
+	if ((buf=(unsigned char *)OPENSSL_malloc((int)BUFSIZE)) == NULL)
+		{
+		BIO_printf(bio_err,"out of memory\n");
+		goto end;
+		}
+#ifndef OPENSSL_NO_DES
+	buf_as_des_cblock = (DES_cblock *)buf;
+#endif
+	if ((buf2=(unsigned char *)OPENSSL_malloc((int)BUFSIZE)) == NULL)
+		{
+		BIO_printf(bio_err,"out of memory\n");
+		goto end;
+		}
+
+	memset(c,0,sizeof(c));
+	memset(DES_iv,0,sizeof(DES_iv));
+	memset(iv,0,sizeof(iv));
+
+	for (i=0; i<ALGOR_NUM; i++)
+		doit[i]=0;
+	for (i=0; i<RSA_NUM; i++)
+		rsa_doit[i]=0;
+	for (i=0; i<DSA_NUM; i++)
+		dsa_doit[i]=0;
+#ifndef OPENSSL_NO_ECDSA
+	for (i=0; i<EC_NUM; i++)
+		ecdsa_doit[i]=0;
+#endif
+#ifndef OPENSSL_NO_ECDH
+	for (i=0; i<EC_NUM; i++)
+		ecdh_doit[i]=0;
+#endif
+
+	
+	j=0;
+	argc--;
+	argv++;
+	while (argc)
+		{
+		if	((argc > 0) && (strcmp(*argv,"-elapsed") == 0))
+			{
+			usertime = 0;
+			j--;	/* Otherwise, -elapsed gets confused with
+				   an algorithm. */
+			}
+		else if	((argc > 0) && (strcmp(*argv,"-evp") == 0))
+			{
+			argc--;
+			argv++;
+			if(argc == 0)
+				{
+				BIO_printf(bio_err,"no EVP given\n");
+				goto end;
+				}
+			evp_cipher=EVP_get_cipherbyname(*argv);
+			if(!evp_cipher)
+				{
+				evp_md=EVP_get_digestbyname(*argv);
+				}
+			if(!evp_cipher && !evp_md)
+				{
+				BIO_printf(bio_err,"%s is an unknown cipher or digest\n",*argv);
+				goto end;
+				}
+			doit[D_EVP]=1;
+			}
+		else if (argc > 0 && !strcmp(*argv,"-decrypt"))
+			{
+			decrypt=1;
+			j--;	/* Otherwise, -elapsed gets confused with
+				   an algorithm. */
+			}
+#ifndef OPENSSL_NO_ENGINE
+		else if	((argc > 0) && (strcmp(*argv,"-engine") == 0))
+			{
+			argc--;
+			argv++;
+			if(argc == 0)
+				{
+				BIO_printf(bio_err,"no engine given\n");
+				goto end;
+				}
+                        e = setup_engine(bio_err, *argv, 0);
+			/* j will be increased again further down.  We just
+			   don't want speed to confuse an engine with an
+			   algorithm, especially when none is given (which
+			   means all of them should be run) */
+			j--;
+			}
+#endif
+#ifdef HAVE_FORK
+		else if	((argc > 0) && (strcmp(*argv,"-multi") == 0))
+			{
+			argc--;
+			argv++;
+			if(argc == 0)
+				{
+				BIO_printf(bio_err,"no multi count given\n");
+				goto end;
+				}
+			multi=atoi(argv[0]);
+			if(multi <= 0)
+			    {
+				BIO_printf(bio_err,"bad multi count\n");
+				goto end;
+				}				
+			j--;	/* Otherwise, -mr gets confused with
+				   an algorithm. */
+			}
+#endif
+		else if (argc > 0 && !strcmp(*argv,"-mr"))
+			{
+			mr=1;
+			j--;	/* Otherwise, -mr gets confused with
+				   an algorithm. */
+			}
+		else
+#ifndef OPENSSL_NO_MD2
+		if	(strcmp(*argv,"md2") == 0) doit[D_MD2]=1;
+		else
+#endif
+#ifndef OPENSSL_NO_MDC2
+			if (strcmp(*argv,"mdc2") == 0) doit[D_MDC2]=1;
+		else
+#endif
+#ifndef OPENSSL_NO_MD4
+			if (strcmp(*argv,"md4") == 0) doit[D_MD4]=1;
+		else
+#endif
+#ifndef OPENSSL_NO_MD5
+			if (strcmp(*argv,"md5") == 0) doit[D_MD5]=1;
+		else
+#endif
+#ifndef OPENSSL_NO_MD5
+			if (strcmp(*argv,"hmac") == 0) doit[D_HMAC]=1;
+		else
+#endif
+#ifndef OPENSSL_NO_SHA
+			if (strcmp(*argv,"sha1") == 0) doit[D_SHA1]=1;
+		else
+			if (strcmp(*argv,"sha") == 0)	doit[D_SHA1]=1,
+							doit[D_SHA256]=1,
+							doit[D_SHA512]=1;
+		else
+#ifndef OPENSSL_NO_SHA256
+			if (strcmp(*argv,"sha256") == 0) doit[D_SHA256]=1;
+		else
+#endif
+#ifndef OPENSSL_NO_SHA512
+			if (strcmp(*argv,"sha512") == 0) doit[D_SHA512]=1;
+		else
+#endif
+#endif
+#ifndef OPENSSL_NO_RIPEMD
+			if (strcmp(*argv,"ripemd") == 0) doit[D_RMD160]=1;
+		else
+			if (strcmp(*argv,"rmd160") == 0) doit[D_RMD160]=1;
+		else
+			if (strcmp(*argv,"ripemd160") == 0) doit[D_RMD160]=1;
+		else
+#endif
+#ifndef OPENSSL_NO_RC4
+			if (strcmp(*argv,"rc4") == 0) doit[D_RC4]=1;
+		else 
+#endif
+#ifndef OPENSSL_NO_DES
+			if (strcmp(*argv,"des-cbc") == 0) doit[D_CBC_DES]=1;
+		else	if (strcmp(*argv,"des-ede3") == 0) doit[D_EDE3_DES]=1;
+		else
+#endif
+#ifndef OPENSSL_NO_AES
+			if (strcmp(*argv,"aes-128-cbc") == 0) doit[D_CBC_128_AES]=1;
+		else	if (strcmp(*argv,"aes-192-cbc") == 0) doit[D_CBC_192_AES]=1;
+		else	if (strcmp(*argv,"aes-256-cbc") == 0) doit[D_CBC_256_AES]=1;
+		else    if (strcmp(*argv,"aes-128-ige") == 0) doit[D_IGE_128_AES]=1;
+		else	if (strcmp(*argv,"aes-192-ige") == 0) doit[D_IGE_192_AES]=1;
+		else	if (strcmp(*argv,"aes-256-ige") == 0) doit[D_IGE_256_AES]=1;
+                else
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+			if (strcmp(*argv,"camellia-128-cbc") == 0) doit[D_CBC_128_CML]=1;
+		else    if (strcmp(*argv,"camellia-192-cbc") == 0) doit[D_CBC_192_CML]=1;
+		else    if (strcmp(*argv,"camellia-256-cbc") == 0) doit[D_CBC_256_CML]=1;
+		else
+#endif
+#ifndef OPENSSL_NO_RSA
+#if 0 /* was: #ifdef RSAref */
+			if (strcmp(*argv,"rsaref") == 0) 
+			{
+			RSA_set_default_openssl_method(RSA_PKCS1_RSAref());
+			j--;
+			}
+		else
+#endif
+#ifndef RSA_NULL
+			if (strcmp(*argv,"openssl") == 0) 
+			{
+			RSA_set_default_method(RSA_PKCS1_SSLeay());
+			j--;
+			}
+		else
+#endif
+#endif /* !OPENSSL_NO_RSA */
+		     if (strcmp(*argv,"dsa512") == 0) dsa_doit[R_DSA_512]=2;
+		else if (strcmp(*argv,"dsa1024") == 0) dsa_doit[R_DSA_1024]=2;
+		else if (strcmp(*argv,"dsa2048") == 0) dsa_doit[R_DSA_2048]=2;
+		else if (strcmp(*argv,"rsa512") == 0) rsa_doit[R_RSA_512]=2;
+		else if (strcmp(*argv,"rsa1024") == 0) rsa_doit[R_RSA_1024]=2;
+		else if (strcmp(*argv,"rsa2048") == 0) rsa_doit[R_RSA_2048]=2;
+		else if (strcmp(*argv,"rsa4096") == 0) rsa_doit[R_RSA_4096]=2;
+		else
+#ifndef OPENSSL_NO_RC2
+		     if (strcmp(*argv,"rc2-cbc") == 0) doit[D_CBC_RC2]=1;
+		else if (strcmp(*argv,"rc2") == 0) doit[D_CBC_RC2]=1;
+		else
+#endif
+#ifndef OPENSSL_NO_RC5
+		     if (strcmp(*argv,"rc5-cbc") == 0) doit[D_CBC_RC5]=1;
+		else if (strcmp(*argv,"rc5") == 0) doit[D_CBC_RC5]=1;
+		else
+#endif
+#ifndef OPENSSL_NO_IDEA
+		     if (strcmp(*argv,"idea-cbc") == 0) doit[D_CBC_IDEA]=1;
+		else if (strcmp(*argv,"idea") == 0) doit[D_CBC_IDEA]=1;
+		else
+#endif
+#ifndef OPENSSL_NO_SEED
+		     if (strcmp(*argv,"seed-cbc") == 0) doit[D_CBC_SEED]=1;
+		else if (strcmp(*argv,"seed") == 0) doit[D_CBC_SEED]=1;
+		else
+#endif
+#ifndef OPENSSL_NO_BF
+		     if (strcmp(*argv,"bf-cbc") == 0) doit[D_CBC_BF]=1;
+		else if (strcmp(*argv,"blowfish") == 0) doit[D_CBC_BF]=1;
+		else if (strcmp(*argv,"bf") == 0) doit[D_CBC_BF]=1;
+		else
+#endif
+#ifndef OPENSSL_NO_CAST
+		     if (strcmp(*argv,"cast-cbc") == 0) doit[D_CBC_CAST]=1;
+		else if (strcmp(*argv,"cast") == 0) doit[D_CBC_CAST]=1;
+		else if (strcmp(*argv,"cast5") == 0) doit[D_CBC_CAST]=1;
+		else
+#endif
+#ifndef OPENSSL_NO_DES
+			if (strcmp(*argv,"des") == 0)
+			{
+			doit[D_CBC_DES]=1;
+			doit[D_EDE3_DES]=1;
+			}
+		else
+#endif
+#ifndef OPENSSL_NO_AES
+			if (strcmp(*argv,"aes") == 0)
+			{
+			doit[D_CBC_128_AES]=1;
+			doit[D_CBC_192_AES]=1;
+			doit[D_CBC_256_AES]=1;
+			}
+		else
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+			if (strcmp(*argv,"camellia") == 0)
+			{
+			doit[D_CBC_128_CML]=1;
+			doit[D_CBC_192_CML]=1;
+			doit[D_CBC_256_CML]=1;
+			}
+		else
+#endif
+#ifndef OPENSSL_NO_RSA
+			if (strcmp(*argv,"rsa") == 0)
+			{
+			rsa_doit[R_RSA_512]=1;
+			rsa_doit[R_RSA_1024]=1;
+			rsa_doit[R_RSA_2048]=1;
+			rsa_doit[R_RSA_4096]=1;
+			}
+		else
+#endif
+#ifndef OPENSSL_NO_DSA
+			if (strcmp(*argv,"dsa") == 0)
+			{
+			dsa_doit[R_DSA_512]=1;
+			dsa_doit[R_DSA_1024]=1;
+			dsa_doit[R_DSA_2048]=1;
+			}
+		else
+#endif
+#ifndef OPENSSL_NO_ECDSA
+		     if (strcmp(*argv,"ecdsap160") == 0) ecdsa_doit[R_EC_P160]=2;
+		else if (strcmp(*argv,"ecdsap192") == 0) ecdsa_doit[R_EC_P192]=2;
+		else if (strcmp(*argv,"ecdsap224") == 0) ecdsa_doit[R_EC_P224]=2;
+		else if (strcmp(*argv,"ecdsap256") == 0) ecdsa_doit[R_EC_P256]=2;
+		else if (strcmp(*argv,"ecdsap384") == 0) ecdsa_doit[R_EC_P384]=2;
+		else if (strcmp(*argv,"ecdsap521") == 0) ecdsa_doit[R_EC_P521]=2;
+		else if (strcmp(*argv,"ecdsak163") == 0) ecdsa_doit[R_EC_K163]=2;
+		else if (strcmp(*argv,"ecdsak233") == 0) ecdsa_doit[R_EC_K233]=2;
+		else if (strcmp(*argv,"ecdsak283") == 0) ecdsa_doit[R_EC_K283]=2;
+		else if (strcmp(*argv,"ecdsak409") == 0) ecdsa_doit[R_EC_K409]=2;
+		else if (strcmp(*argv,"ecdsak571") == 0) ecdsa_doit[R_EC_K571]=2;
+		else if (strcmp(*argv,"ecdsab163") == 0) ecdsa_doit[R_EC_B163]=2;
+		else if (strcmp(*argv,"ecdsab233") == 0) ecdsa_doit[R_EC_B233]=2;
+		else if (strcmp(*argv,"ecdsab283") == 0) ecdsa_doit[R_EC_B283]=2;
+		else if (strcmp(*argv,"ecdsab409") == 0) ecdsa_doit[R_EC_B409]=2;
+		else if (strcmp(*argv,"ecdsab571") == 0) ecdsa_doit[R_EC_B571]=2;
+		else if (strcmp(*argv,"ecdsa") == 0)
+			{
+			for (i=0; i < EC_NUM; i++)
+				ecdsa_doit[i]=1;
+			}
+		else
+#endif
+#ifndef OPENSSL_NO_ECDH
+		     if (strcmp(*argv,"ecdhp160") == 0) ecdh_doit[R_EC_P160]=2;
+		else if (strcmp(*argv,"ecdhp192") == 0) ecdh_doit[R_EC_P192]=2;
+		else if (strcmp(*argv,"ecdhp224") == 0) ecdh_doit[R_EC_P224]=2;
+		else if (strcmp(*argv,"ecdhp256") == 0) ecdh_doit[R_EC_P256]=2;
+		else if (strcmp(*argv,"ecdhp384") == 0) ecdh_doit[R_EC_P384]=2;
+		else if (strcmp(*argv,"ecdhp521") == 0) ecdh_doit[R_EC_P521]=2;
+		else if (strcmp(*argv,"ecdhk163") == 0) ecdh_doit[R_EC_K163]=2;
+		else if (strcmp(*argv,"ecdhk233") == 0) ecdh_doit[R_EC_K233]=2;
+		else if (strcmp(*argv,"ecdhk283") == 0) ecdh_doit[R_EC_K283]=2;
+		else if (strcmp(*argv,"ecdhk409") == 0) ecdh_doit[R_EC_K409]=2;
+		else if (strcmp(*argv,"ecdhk571") == 0) ecdh_doit[R_EC_K571]=2;
+		else if (strcmp(*argv,"ecdhb163") == 0) ecdh_doit[R_EC_B163]=2;
+		else if (strcmp(*argv,"ecdhb233") == 0) ecdh_doit[R_EC_B233]=2;
+		else if (strcmp(*argv,"ecdhb283") == 0) ecdh_doit[R_EC_B283]=2;
+		else if (strcmp(*argv,"ecdhb409") == 0) ecdh_doit[R_EC_B409]=2;
+		else if (strcmp(*argv,"ecdhb571") == 0) ecdh_doit[R_EC_B571]=2;
+		else if (strcmp(*argv,"ecdh") == 0)
+			{
+			for (i=0; i < EC_NUM; i++)
+				ecdh_doit[i]=1;
+			}
+		else
+#endif
+			{
+			BIO_printf(bio_err,"Error: bad option or value\n");
+			BIO_printf(bio_err,"\n");
+			BIO_printf(bio_err,"Available values:\n");
+#ifndef OPENSSL_NO_MD2
+			BIO_printf(bio_err,"md2      ");
+#endif
+#ifndef OPENSSL_NO_MDC2
+			BIO_printf(bio_err,"mdc2     ");
+#endif
+#ifndef OPENSSL_NO_MD4
+			BIO_printf(bio_err,"md4      ");
+#endif
+#ifndef OPENSSL_NO_MD5
+			BIO_printf(bio_err,"md5      ");
+#ifndef OPENSSL_NO_HMAC
+			BIO_printf(bio_err,"hmac     ");
+#endif
+#endif
+#ifndef OPENSSL_NO_SHA1
+			BIO_printf(bio_err,"sha1     ");
+#endif
+#ifndef OPENSSL_NO_SHA256
+			BIO_printf(bio_err,"sha256   ");
+#endif
+#ifndef OPENSSL_NO_SHA512
+			BIO_printf(bio_err,"sha512   ");
+#endif
+#ifndef OPENSSL_NO_RIPEMD160
+			BIO_printf(bio_err,"rmd160");
+#endif
+#if !defined(OPENSSL_NO_MD2) || !defined(OPENSSL_NO_MDC2) || \
+    !defined(OPENSSL_NO_MD4) || !defined(OPENSSL_NO_MD5) || \
+    !defined(OPENSSL_NO_SHA1) || !defined(OPENSSL_NO_RIPEMD160)
+			BIO_printf(bio_err,"\n");
+#endif
+
+#ifndef OPENSSL_NO_IDEA
+			BIO_printf(bio_err,"idea-cbc ");
+#endif
+#ifndef OPENSSL_NO_SEED
+			BIO_printf(bio_err,"seed-cbc ");
+#endif
+#ifndef OPENSSL_NO_RC2
+			BIO_printf(bio_err,"rc2-cbc  ");
+#endif
+#ifndef OPENSSL_NO_RC5
+			BIO_printf(bio_err,"rc5-cbc  ");
+#endif
+#ifndef OPENSSL_NO_BF
+			BIO_printf(bio_err,"bf-cbc");
+#endif
+#if !defined(OPENSSL_NO_IDEA) || !defined(OPENSSL_NO_SEED) || !defined(OPENSSL_NO_RC2) || \
+    !defined(OPENSSL_NO_BF) || !defined(OPENSSL_NO_RC5)
+			BIO_printf(bio_err,"\n");
+#endif
+#ifndef OPENSSL_NO_DES
+			BIO_printf(bio_err,"des-cbc  des-ede3 ");
+#endif
+#ifndef OPENSSL_NO_AES
+			BIO_printf(bio_err,"aes-128-cbc aes-192-cbc aes-256-cbc ");
+			BIO_printf(bio_err,"aes-128-ige aes-192-ige aes-256-ige ");
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+			BIO_printf(bio_err,"\n");
+			BIO_printf(bio_err,"camellia-128-cbc camellia-192-cbc camellia-256-cbc ");
+#endif
+#ifndef OPENSSL_NO_RC4
+			BIO_printf(bio_err,"rc4");
+#endif
+			BIO_printf(bio_err,"\n");
+
+#ifndef OPENSSL_NO_RSA
+			BIO_printf(bio_err,"rsa512   rsa1024  rsa2048  rsa4096\n");
+#endif
+
+#ifndef OPENSSL_NO_DSA
+			BIO_printf(bio_err,"dsa512   dsa1024  dsa2048\n");
+#endif
+#ifndef OPENSSL_NO_ECDSA
+			BIO_printf(bio_err,"ecdsap160 ecdsap192 ecdsap224 ecdsap256 ecdsap384 ecdsap521\n");
+			BIO_printf(bio_err,"ecdsak163 ecdsak233 ecdsak283 ecdsak409 ecdsak571\n");
+			BIO_printf(bio_err,"ecdsab163 ecdsab233 ecdsab283 ecdsab409 ecdsab571\n");
+			BIO_printf(bio_err,"ecdsa\n");
+#endif
+#ifndef OPENSSL_NO_ECDH
+			BIO_printf(bio_err,"ecdhp160  ecdhp192  ecdhp224  ecdhp256  ecdhp384  ecdhp521\n");
+			BIO_printf(bio_err,"ecdhk163  ecdhk233  ecdhk283  ecdhk409  ecdhk571\n");
+			BIO_printf(bio_err,"ecdhb163  ecdhb233  ecdhb283  ecdhb409  ecdhb571\n");
+			BIO_printf(bio_err,"ecdh\n");
+#endif
+
+#ifndef OPENSSL_NO_IDEA
+			BIO_printf(bio_err,"idea     ");
+#endif
+#ifndef OPENSSL_NO_SEED
+			BIO_printf(bio_err,"seed     ");
+#endif
+#ifndef OPENSSL_NO_RC2
+			BIO_printf(bio_err,"rc2      ");
+#endif
+#ifndef OPENSSL_NO_DES
+			BIO_printf(bio_err,"des      ");
+#endif
+#ifndef OPENSSL_NO_AES
+			BIO_printf(bio_err,"aes      ");
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+			BIO_printf(bio_err,"camellia ");
+#endif
+#ifndef OPENSSL_NO_RSA
+			BIO_printf(bio_err,"rsa      ");
+#endif
+#ifndef OPENSSL_NO_BF
+			BIO_printf(bio_err,"blowfish");
+#endif
+#if !defined(OPENSSL_NO_IDEA) || !defined(OPENSSL_NO_SEED) || \
+    !defined(OPENSSL_NO_RC2) || !defined(OPENSSL_NO_DES) || \
+    !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_BF) || \
+    !defined(OPENSSL_NO_AES) || !defined(OPENSSL_NO_CAMELLIA)
+			BIO_printf(bio_err,"\n");
+#endif
+
+			BIO_printf(bio_err,"\n");
+			BIO_printf(bio_err,"Available options:\n");
+#if defined(TIMES) || defined(USE_TOD)
+			BIO_printf(bio_err,"-elapsed        measure time in real time instead of CPU user time.\n");
+#endif
+#ifndef OPENSSL_NO_ENGINE
+			BIO_printf(bio_err,"-engine e       use engine e, possibly a hardware device.\n");
+#endif
+			BIO_printf(bio_err,"-evp e          use EVP e.\n");
+			BIO_printf(bio_err,"-decrypt        time decryption instead of encryption (only EVP).\n");
+			BIO_printf(bio_err,"-mr             produce machine readable output.\n");
+#ifdef HAVE_FORK
+			BIO_printf(bio_err,"-multi n        run n benchmarks in parallel.\n");
+#endif
+			goto end;
+			}
+		argc--;
+		argv++;
+		j++;
+		}
+
+#ifdef HAVE_FORK
+	if(multi && do_multi(multi))
+		goto show_res;
+#endif
+
+	if (j == 0)
+		{
+		for (i=0; i<ALGOR_NUM; i++)
+			{
+			if (i != D_EVP)
+				doit[i]=1;
+			}
+		for (i=0; i<RSA_NUM; i++)
+			rsa_doit[i]=1;
+		for (i=0; i<DSA_NUM; i++)
+			dsa_doit[i]=1;
+		}
+	for (i=0; i<ALGOR_NUM; i++)
+		if (doit[i]) pr_header++;
+
+	if (usertime == 0 && !mr)
+		BIO_printf(bio_err,"You have chosen to measure elapsed time instead of user CPU time.\n");
+	if (usertime <= 0 && !mr)
+		{
+		BIO_printf(bio_err,"To get the most accurate results, try to run this\n");
+		BIO_printf(bio_err,"program when this computer is idle.\n");
+		}
+
+#ifndef OPENSSL_NO_RSA
+	for (i=0; i<RSA_NUM; i++)
+		{
+		const unsigned char *p;
+
+		p=rsa_data[i];
+		rsa_key[i]=d2i_RSAPrivateKey(NULL,&p,rsa_data_length[i]);
+		if (rsa_key[i] == NULL)
+			{
+			BIO_printf(bio_err,"internal error loading RSA key number %d\n",i);
+			goto end;
+			}
+#if 0
+		else
+			{
+			BIO_printf(bio_err,mr ? "+RK:%d:"
+				   : "Loaded RSA key, %d bit modulus and e= 0x",
+				   BN_num_bits(rsa_key[i]->n));
+			BN_print(bio_err,rsa_key[i]->e);
+			BIO_printf(bio_err,"\n");
+			}
+#endif
+		}
+#endif
+
+#ifndef OPENSSL_NO_DSA
+	dsa_key[0]=get_dsa512();
+	dsa_key[1]=get_dsa1024();
+	dsa_key[2]=get_dsa2048();
+#endif
+
+#ifndef OPENSSL_NO_DES
+	DES_set_key_unchecked(&key,&sch);
+	DES_set_key_unchecked(&key2,&sch2);
+	DES_set_key_unchecked(&key3,&sch3);
+#endif
+#ifndef OPENSSL_NO_AES
+	AES_set_encrypt_key(key16,128,&aes_ks1);
+	AES_set_encrypt_key(key24,192,&aes_ks2);
+	AES_set_encrypt_key(key32,256,&aes_ks3);
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+	Camellia_set_key(key16,128,&camellia_ks1);
+	Camellia_set_key(ckey24,192,&camellia_ks2);
+	Camellia_set_key(ckey32,256,&camellia_ks3);
+#endif
+#ifndef OPENSSL_NO_IDEA
+	idea_set_encrypt_key(key16,&idea_ks);
+#endif
+#ifndef OPENSSL_NO_SEED
+	SEED_set_key(key16,&seed_ks);
+#endif
+#ifndef OPENSSL_NO_RC4
+	RC4_set_key(&rc4_ks,16,key16);
+#endif
+#ifndef OPENSSL_NO_RC2
+	RC2_set_key(&rc2_ks,16,key16,128);
+#endif
+#ifndef OPENSSL_NO_RC5
+	RC5_32_set_key(&rc5_ks,16,key16,12);
+#endif
+#ifndef OPENSSL_NO_BF
+	BF_set_key(&bf_ks,16,key16);
+#endif
+#ifndef OPENSSL_NO_CAST
+	CAST_set_key(&cast_ks,16,key16);
+#endif
+#ifndef OPENSSL_NO_RSA
+	memset(rsa_c,0,sizeof(rsa_c));
+#endif
+#ifndef SIGALRM
+#ifndef OPENSSL_NO_DES
+	BIO_printf(bio_err,"First we calculate the approximate speed ...\n");
+	count=10;
+	do	{
+		long it;
+		count*=2;
+		Time_F(START);
+		for (it=count; it; it--)
+			DES_ecb_encrypt(buf_as_des_cblock,buf_as_des_cblock,
+				&sch,DES_ENCRYPT);
+		d=Time_F(STOP);
+		} while (d <3);
+	save_count=count;
+	c[D_MD2][0]=count/10;
+	c[D_MDC2][0]=count/10;
+	c[D_MD4][0]=count;
+	c[D_MD5][0]=count;
+	c[D_HMAC][0]=count;
+	c[D_SHA1][0]=count;
+	c[D_RMD160][0]=count;
+	c[D_RC4][0]=count*5;
+	c[D_CBC_DES][0]=count;
+	c[D_EDE3_DES][0]=count/3;
+	c[D_CBC_IDEA][0]=count;
+	c[D_CBC_SEED][0]=count;
+	c[D_CBC_RC2][0]=count;
+	c[D_CBC_RC5][0]=count;
+	c[D_CBC_BF][0]=count;
+	c[D_CBC_CAST][0]=count;
+	c[D_CBC_128_AES][0]=count;
+	c[D_CBC_192_AES][0]=count;
+	c[D_CBC_256_AES][0]=count;
+	c[D_CBC_128_CML][0]=count;
+	c[D_CBC_192_CML][0]=count;
+	c[D_CBC_256_CML][0]=count;
+	c[D_SHA256][0]=count;
+	c[D_SHA512][0]=count;
+	c[D_IGE_128_AES][0]=count;
+	c[D_IGE_192_AES][0]=count;
+	c[D_IGE_256_AES][0]=count;
+
+	for (i=1; i<SIZE_NUM; i++)
+		{
+		c[D_MD2][i]=c[D_MD2][0]*4*lengths[0]/lengths[i];
+		c[D_MDC2][i]=c[D_MDC2][0]*4*lengths[0]/lengths[i];
+		c[D_MD4][i]=c[D_MD4][0]*4*lengths[0]/lengths[i];
+		c[D_MD5][i]=c[D_MD5][0]*4*lengths[0]/lengths[i];
+		c[D_HMAC][i]=c[D_HMAC][0]*4*lengths[0]/lengths[i];
+		c[D_SHA1][i]=c[D_SHA1][0]*4*lengths[0]/lengths[i];
+		c[D_RMD160][i]=c[D_RMD160][0]*4*lengths[0]/lengths[i];
+		c[D_SHA256][i]=c[D_SHA256][0]*4*lengths[0]/lengths[i];
+		c[D_SHA512][i]=c[D_SHA512][0]*4*lengths[0]/lengths[i];
+		}
+	for (i=1; i<SIZE_NUM; i++)
+		{
+		long l0,l1;
+
+		l0=(long)lengths[i-1];
+		l1=(long)lengths[i];
+		c[D_RC4][i]=c[D_RC4][i-1]*l0/l1;
+		c[D_CBC_DES][i]=c[D_CBC_DES][i-1]*l0/l1;
+		c[D_EDE3_DES][i]=c[D_EDE3_DES][i-1]*l0/l1;
+		c[D_CBC_IDEA][i]=c[D_CBC_IDEA][i-1]*l0/l1;
+		c[D_CBC_SEED][i]=c[D_CBC_SEED][i-1]*l0/l1;
+		c[D_CBC_RC2][i]=c[D_CBC_RC2][i-1]*l0/l1;
+		c[D_CBC_RC5][i]=c[D_CBC_RC5][i-1]*l0/l1;
+		c[D_CBC_BF][i]=c[D_CBC_BF][i-1]*l0/l1;
+		c[D_CBC_CAST][i]=c[D_CBC_CAST][i-1]*l0/l1;
+		c[D_CBC_128_AES][i]=c[D_CBC_128_AES][i-1]*l0/l1;
+		c[D_CBC_192_AES][i]=c[D_CBC_192_AES][i-1]*l0/l1;
+		c[D_CBC_256_AES][i]=c[D_CBC_256_AES][i-1]*l0/l1;
+ 		c[D_CBC_128_CML][i]=c[D_CBC_128_CML][i-1]*l0/l1;
+		c[D_CBC_192_CML][i]=c[D_CBC_192_CML][i-1]*l0/l1;
+		c[D_CBC_256_CML][i]=c[D_CBC_256_CML][i-1]*l0/l1;
+		c[D_IGE_128_AES][i]=c[D_IGE_128_AES][i-1]*l0/l1;
+		c[D_IGE_192_AES][i]=c[D_IGE_192_AES][i-1]*l0/l1;
+		c[D_IGE_256_AES][i]=c[D_IGE_256_AES][i-1]*l0/l1;
+		}
+#ifndef OPENSSL_NO_RSA
+	rsa_c[R_RSA_512][0]=count/2000;
+	rsa_c[R_RSA_512][1]=count/400;
+	for (i=1; i<RSA_NUM; i++)
+		{
+		rsa_c[i][0]=rsa_c[i-1][0]/8;
+		rsa_c[i][1]=rsa_c[i-1][1]/4;
+		if ((rsa_doit[i] <= 1) && (rsa_c[i][0] == 0))
+			rsa_doit[i]=0;
+		else
+			{
+			if (rsa_c[i][0] == 0)
+				{
+				rsa_c[i][0]=1;
+				rsa_c[i][1]=20;
+				}
+			}				
+		}
+#endif
+
+#ifndef OPENSSL_NO_DSA
+	dsa_c[R_DSA_512][0]=count/1000;
+	dsa_c[R_DSA_512][1]=count/1000/2;
+	for (i=1; i<DSA_NUM; i++)
+		{
+		dsa_c[i][0]=dsa_c[i-1][0]/4;
+		dsa_c[i][1]=dsa_c[i-1][1]/4;
+		if ((dsa_doit[i] <= 1) && (dsa_c[i][0] == 0))
+			dsa_doit[i]=0;
+		else
+			{
+			if (dsa_c[i] == 0)
+				{
+				dsa_c[i][0]=1;
+				dsa_c[i][1]=1;
+				}
+			}				
+		}
+#endif
+
+#ifndef OPENSSL_NO_ECDSA
+	ecdsa_c[R_EC_P160][0]=count/1000;
+	ecdsa_c[R_EC_P160][1]=count/1000/2;
+	for (i=R_EC_P192; i<=R_EC_P521; i++)
+		{
+		ecdsa_c[i][0]=ecdsa_c[i-1][0]/2;
+		ecdsa_c[i][1]=ecdsa_c[i-1][1]/2;
+		if ((ecdsa_doit[i] <= 1) && (ecdsa_c[i][0] == 0))
+			ecdsa_doit[i]=0;
+		else
+			{
+			if (ecdsa_c[i] == 0)
+				{
+				ecdsa_c[i][0]=1;
+				ecdsa_c[i][1]=1;
+				}
+			}
+		}
+	ecdsa_c[R_EC_K163][0]=count/1000;
+	ecdsa_c[R_EC_K163][1]=count/1000/2;
+	for (i=R_EC_K233; i<=R_EC_K571; i++)
+		{
+		ecdsa_c[i][0]=ecdsa_c[i-1][0]/2;
+		ecdsa_c[i][1]=ecdsa_c[i-1][1]/2;
+		if ((ecdsa_doit[i] <= 1) && (ecdsa_c[i][0] == 0))
+			ecdsa_doit[i]=0;
+		else
+			{
+			if (ecdsa_c[i] == 0)
+				{
+				ecdsa_c[i][0]=1;
+				ecdsa_c[i][1]=1;
+				}
+			}
+		}
+	ecdsa_c[R_EC_B163][0]=count/1000;
+	ecdsa_c[R_EC_B163][1]=count/1000/2;
+	for (i=R_EC_B233; i<=R_EC_B571; i++)
+		{
+		ecdsa_c[i][0]=ecdsa_c[i-1][0]/2;
+		ecdsa_c[i][1]=ecdsa_c[i-1][1]/2;
+		if ((ecdsa_doit[i] <= 1) && (ecdsa_c[i][0] == 0))
+			ecdsa_doit[i]=0;
+		else
+			{
+			if (ecdsa_c[i] == 0)
+				{
+				ecdsa_c[i][0]=1;
+				ecdsa_c[i][1]=1;
+				}
+			}
+		}
+#endif
+
+#ifndef OPENSSL_NO_ECDH
+	ecdh_c[R_EC_P160][0]=count/1000;
+	ecdh_c[R_EC_P160][1]=count/1000;
+	for (i=R_EC_P192; i<=R_EC_P521; i++)
+		{
+		ecdh_c[i][0]=ecdh_c[i-1][0]/2;
+		ecdh_c[i][1]=ecdh_c[i-1][1]/2;
+		if ((ecdh_doit[i] <= 1) && (ecdh_c[i][0] == 0))
+			ecdh_doit[i]=0;
+		else
+			{
+			if (ecdh_c[i] == 0)
+				{
+				ecdh_c[i][0]=1;
+				ecdh_c[i][1]=1;
+				}
+			}
+		}
+	ecdh_c[R_EC_K163][0]=count/1000;
+	ecdh_c[R_EC_K163][1]=count/1000;
+	for (i=R_EC_K233; i<=R_EC_K571; i++)
+		{
+		ecdh_c[i][0]=ecdh_c[i-1][0]/2;
+		ecdh_c[i][1]=ecdh_c[i-1][1]/2;
+		if ((ecdh_doit[i] <= 1) && (ecdh_c[i][0] == 0))
+			ecdh_doit[i]=0;
+		else
+			{
+			if (ecdh_c[i] == 0)
+				{
+				ecdh_c[i][0]=1;
+				ecdh_c[i][1]=1;
+				}
+			}
+		}
+	ecdh_c[R_EC_B163][0]=count/1000;
+	ecdh_c[R_EC_B163][1]=count/1000;
+	for (i=R_EC_B233; i<=R_EC_B571; i++)
+		{
+		ecdh_c[i][0]=ecdh_c[i-1][0]/2;
+		ecdh_c[i][1]=ecdh_c[i-1][1]/2;
+		if ((ecdh_doit[i] <= 1) && (ecdh_c[i][0] == 0))
+			ecdh_doit[i]=0;
+		else
+			{
+			if (ecdh_c[i] == 0)
+				{
+				ecdh_c[i][0]=1;
+				ecdh_c[i][1]=1;
+				}
+			}
+		}
+#endif
+
+#define COND(d)	(count < (d))
+#define COUNT(d) (d)
+#else
+/* not worth fixing */
+# error "You cannot disable DES on systems without SIGALRM."
+#endif /* OPENSSL_NO_DES */
+#else
+#define COND(c)	(run)
+#define COUNT(d) (count)
+	signal(SIGALRM,sig_done);
+#endif /* SIGALRM */
+
+#ifndef OPENSSL_NO_MD2
+	if (doit[D_MD2])
+		{
+		for (j=0; j<SIZE_NUM; j++)
+			{
+			print_message(names[D_MD2],c[D_MD2][j],lengths[j]);
+			Time_F(START);
+			for (count=0,run=1; COND(c[D_MD2][j]); count++)
+				EVP_Digest(buf,(unsigned long)lengths[j],&(md2[0]),NULL,EVP_md2(),NULL);
+			d=Time_F(STOP);
+			print_result(D_MD2,j,count,d);
+			}
+		}
+#endif
+#ifndef OPENSSL_NO_MDC2
+	if (doit[D_MDC2])
+		{
+		for (j=0; j<SIZE_NUM; j++)
+			{
+			print_message(names[D_MDC2],c[D_MDC2][j],lengths[j]);
+			Time_F(START);
+			for (count=0,run=1; COND(c[D_MDC2][j]); count++)
+				EVP_Digest(buf,(unsigned long)lengths[j],&(mdc2[0]),NULL,EVP_mdc2(),NULL);
+			d=Time_F(STOP);
+			print_result(D_MDC2,j,count,d);
+			}
+		}
+#endif
+
+#ifndef OPENSSL_NO_MD4
+	if (doit[D_MD4])
+		{
+		for (j=0; j<SIZE_NUM; j++)
+			{
+			print_message(names[D_MD4],c[D_MD4][j],lengths[j]);
+			Time_F(START);
+			for (count=0,run=1; COND(c[D_MD4][j]); count++)
+				EVP_Digest(&(buf[0]),(unsigned long)lengths[j],&(md4[0]),NULL,EVP_md4(),NULL);
+			d=Time_F(STOP);
+			print_result(D_MD4,j,count,d);
+			}
+		}
+#endif
+
+#ifndef OPENSSL_NO_MD5
+	if (doit[D_MD5])
+		{
+		for (j=0; j<SIZE_NUM; j++)
+			{
+			print_message(names[D_MD5],c[D_MD5][j],lengths[j]);
+			Time_F(START);
+			for (count=0,run=1; COND(c[D_MD5][j]); count++)
+				EVP_Digest(&(buf[0]),(unsigned long)lengths[j],&(md5[0]),NULL,EVP_get_digestbyname("md5"),NULL);
+			d=Time_F(STOP);
+			print_result(D_MD5,j,count,d);
+			}
+		}
+#endif
+
+#if !defined(OPENSSL_NO_MD5) && !defined(OPENSSL_NO_HMAC)
+	if (doit[D_HMAC])
+		{
+		HMAC_CTX hctx;
+
+		HMAC_CTX_init(&hctx);
+		HMAC_Init_ex(&hctx,(unsigned char *)"This is a key...",
+			16,EVP_md5(), NULL);
+
+		for (j=0; j<SIZE_NUM; j++)
+			{
+			print_message(names[D_HMAC],c[D_HMAC][j],lengths[j]);
+			Time_F(START);
+			for (count=0,run=1; COND(c[D_HMAC][j]); count++)
+				{
+				HMAC_Init_ex(&hctx,NULL,0,NULL,NULL);
+				HMAC_Update(&hctx,buf,lengths[j]);
+				HMAC_Final(&hctx,&(hmac[0]),NULL);
+				}
+			d=Time_F(STOP);
+			print_result(D_HMAC,j,count,d);
+			}
+		HMAC_CTX_cleanup(&hctx);
+		}
+#endif
+#ifndef OPENSSL_NO_SHA
+	if (doit[D_SHA1])
+		{
+		for (j=0; j<SIZE_NUM; j++)
+			{
+			print_message(names[D_SHA1],c[D_SHA1][j],lengths[j]);
+			Time_F(START);
+			for (count=0,run=1; COND(c[D_SHA1][j]); count++)
+				EVP_Digest(buf,(unsigned long)lengths[j],&(sha[0]),NULL,EVP_sha1(),NULL);
+			d=Time_F(STOP);
+			print_result(D_SHA1,j,count,d);
+			}
+		}
+
+#ifndef OPENSSL_NO_SHA256
+	if (doit[D_SHA256])
+		{
+		for (j=0; j<SIZE_NUM; j++)
+			{
+			print_message(names[D_SHA256],c[D_SHA256][j],lengths[j]);
+			Time_F(START);
+			for (count=0,run=1; COND(c[D_SHA256][j]); count++)
+				SHA256(buf,lengths[j],sha256);
+			d=Time_F(STOP);
+			print_result(D_SHA256,j,count,d);
+			}
+		}
+#endif
+
+#ifndef OPENSSL_NO_SHA512
+	if (doit[D_SHA512])
+		{
+		for (j=0; j<SIZE_NUM; j++)
+			{
+			print_message(names[D_SHA512],c[D_SHA512][j],lengths[j]);
+			Time_F(START);
+			for (count=0,run=1; COND(c[D_SHA512][j]); count++)
+				SHA512(buf,lengths[j],sha512);
+			d=Time_F(STOP);
+			print_result(D_SHA512,j,count,d);
+			}
+		}
+#endif
+
+#endif
+#ifndef OPENSSL_NO_RIPEMD
+	if (doit[D_RMD160])
+		{
+		for (j=0; j<SIZE_NUM; j++)
+			{
+			print_message(names[D_RMD160],c[D_RMD160][j],lengths[j]);
+			Time_F(START);
+			for (count=0,run=1; COND(c[D_RMD160][j]); count++)
+				EVP_Digest(buf,(unsigned long)lengths[j],&(rmd160[0]),NULL,EVP_ripemd160(),NULL);
+			d=Time_F(STOP);
+			print_result(D_RMD160,j,count,d);
+			}
+		}
+#endif
+#ifndef OPENSSL_NO_RC4
+	if (doit[D_RC4])
+		{
+		for (j=0; j<SIZE_NUM; j++)
+			{
+			print_message(names[D_RC4],c[D_RC4][j],lengths[j]);
+			Time_F(START);
+			for (count=0,run=1; COND(c[D_RC4][j]); count++)
+				RC4(&rc4_ks,(unsigned int)lengths[j],
+					buf,buf);
+			d=Time_F(STOP);
+			print_result(D_RC4,j,count,d);
+			}
+		}
+#endif
+#ifndef OPENSSL_NO_DES
+	if (doit[D_CBC_DES])
+		{
+		for (j=0; j<SIZE_NUM; j++)
+			{
+			print_message(names[D_CBC_DES],c[D_CBC_DES][j],lengths[j]);
+			Time_F(START);
+			for (count=0,run=1; COND(c[D_CBC_DES][j]); count++)
+				DES_ncbc_encrypt(buf,buf,lengths[j],&sch,
+						 &DES_iv,DES_ENCRYPT);
+			d=Time_F(STOP);
+			print_result(D_CBC_DES,j,count,d);
+			}
+		}
+
+	if (doit[D_EDE3_DES])
+		{
+		for (j=0; j<SIZE_NUM; j++)
+			{
+			print_message(names[D_EDE3_DES],c[D_EDE3_DES][j],lengths[j]);
+			Time_F(START);
+			for (count=0,run=1; COND(c[D_EDE3_DES][j]); count++)
+				DES_ede3_cbc_encrypt(buf,buf,lengths[j],
+						     &sch,&sch2,&sch3,
+						     &DES_iv,DES_ENCRYPT);
+			d=Time_F(STOP);
+			print_result(D_EDE3_DES,j,count,d);
+			}
+		}
+#endif
+#ifndef OPENSSL_NO_AES
+	if (doit[D_CBC_128_AES])
+		{
+		for (j=0; j<SIZE_NUM; j++)
+			{
+			print_message(names[D_CBC_128_AES],c[D_CBC_128_AES][j],lengths[j]);
+			Time_F(START);
+			for (count=0,run=1; COND(c[D_CBC_128_AES][j]); count++)
+				AES_cbc_encrypt(buf,buf,
+					(unsigned long)lengths[j],&aes_ks1,
+					iv,AES_ENCRYPT);
+			d=Time_F(STOP);
+			print_result(D_CBC_128_AES,j,count,d);
+			}
+		}
+	if (doit[D_CBC_192_AES])
+		{
+		for (j=0; j<SIZE_NUM; j++)
+			{
+			print_message(names[D_CBC_192_AES],c[D_CBC_192_AES][j],lengths[j]);
+			Time_F(START);
+			for (count=0,run=1; COND(c[D_CBC_192_AES][j]); count++)
+				AES_cbc_encrypt(buf,buf,
+					(unsigned long)lengths[j],&aes_ks2,
+					iv,AES_ENCRYPT);
+			d=Time_F(STOP);
+			print_result(D_CBC_192_AES,j,count,d);
+			}
+		}
+	if (doit[D_CBC_256_AES])
+		{
+		for (j=0; j<SIZE_NUM; j++)
+			{
+			print_message(names[D_CBC_256_AES],c[D_CBC_256_AES][j],lengths[j]);
+			Time_F(START);
+			for (count=0,run=1; COND(c[D_CBC_256_AES][j]); count++)
+				AES_cbc_encrypt(buf,buf,
+					(unsigned long)lengths[j],&aes_ks3,
+					iv,AES_ENCRYPT);
+			d=Time_F(STOP);
+			print_result(D_CBC_256_AES,j,count,d);
+			}
+		}
+
+	if (doit[D_IGE_128_AES])
+		{
+		for (j=0; j<SIZE_NUM; j++)
+			{
+			print_message(names[D_IGE_128_AES],c[D_IGE_128_AES][j],lengths[j]);
+			Time_F(START);
+			for (count=0,run=1; COND(c[D_IGE_128_AES][j]); count++)
+				AES_ige_encrypt(buf,buf2,
+					(unsigned long)lengths[j],&aes_ks1,
+					iv,AES_ENCRYPT);
+			d=Time_F(STOP);
+			print_result(D_IGE_128_AES,j,count,d);
+			}
+		}
+	if (doit[D_IGE_192_AES])
+		{
+		for (j=0; j<SIZE_NUM; j++)
+			{
+			print_message(names[D_IGE_192_AES],c[D_IGE_192_AES][j],lengths[j]);
+			Time_F(START);
+			for (count=0,run=1; COND(c[D_IGE_192_AES][j]); count++)
+				AES_ige_encrypt(buf,buf2,
+					(unsigned long)lengths[j],&aes_ks2,
+					iv,AES_ENCRYPT);
+			d=Time_F(STOP);
+			print_result(D_IGE_192_AES,j,count,d);
+			}
+		}
+	if (doit[D_IGE_256_AES])
+		{
+		for (j=0; j<SIZE_NUM; j++)
+			{
+			print_message(names[D_IGE_256_AES],c[D_IGE_256_AES][j],lengths[j]);
+			Time_F(START);
+			for (count=0,run=1; COND(c[D_IGE_256_AES][j]); count++)
+				AES_ige_encrypt(buf,buf2,
+					(unsigned long)lengths[j],&aes_ks3,
+					iv,AES_ENCRYPT);
+			d=Time_F(STOP);
+			print_result(D_IGE_256_AES,j,count,d);
+			}
+		}
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+	if (doit[D_CBC_128_CML])
+		{
+		for (j=0; j<SIZE_NUM; j++)
+			{
+			print_message(names[D_CBC_128_CML],c[D_CBC_128_CML][j],lengths[j]);
+			Time_F(START);
+			for (count=0,run=1; COND(c[D_CBC_128_CML][j]); count++)
+				Camellia_cbc_encrypt(buf,buf,
+				        (unsigned long)lengths[j],&camellia_ks1,
+				        iv,CAMELLIA_ENCRYPT);
+			d=Time_F(STOP);
+			print_result(D_CBC_128_CML,j,count,d);
+			}
+		}
+	if (doit[D_CBC_192_CML])
+		{
+		for (j=0; j<SIZE_NUM; j++)
+			{
+			print_message(names[D_CBC_192_CML],c[D_CBC_192_CML][j],lengths[j]);
+			Time_F(START);
+			for (count=0,run=1; COND(c[D_CBC_192_CML][j]); count++)
+				Camellia_cbc_encrypt(buf,buf,
+				        (unsigned long)lengths[j],&camellia_ks2,
+				        iv,CAMELLIA_ENCRYPT);
+			d=Time_F(STOP);
+			print_result(D_CBC_192_CML,j,count,d);
+			}
+		}
+	if (doit[D_CBC_256_CML])
+		{
+		for (j=0; j<SIZE_NUM; j++)
+			{
+			print_message(names[D_CBC_256_CML],c[D_CBC_256_CML][j],lengths[j]);
+			Time_F(START);
+			for (count=0,run=1; COND(c[D_CBC_256_CML][j]); count++)
+				Camellia_cbc_encrypt(buf,buf,
+				        (unsigned long)lengths[j],&camellia_ks3,
+				        iv,CAMELLIA_ENCRYPT);
+			d=Time_F(STOP);
+			print_result(D_CBC_256_CML,j,count,d);
+			}
+		}
+
+#endif
+#ifndef OPENSSL_NO_IDEA
+	if (doit[D_CBC_IDEA])
+		{
+		for (j=0; j<SIZE_NUM; j++)
+			{
+			print_message(names[D_CBC_IDEA],c[D_CBC_IDEA][j],lengths[j]);
+			Time_F(START);
+			for (count=0,run=1; COND(c[D_CBC_IDEA][j]); count++)
+				idea_cbc_encrypt(buf,buf,
+					(unsigned long)lengths[j],&idea_ks,
+					iv,IDEA_ENCRYPT);
+			d=Time_F(STOP);
+			print_result(D_CBC_IDEA,j,count,d);
+			}
+		}
+#endif
+#ifndef OPENSSL_NO_SEED
+	if (doit[D_CBC_SEED])
+		{
+		for (j=0; j<SIZE_NUM; j++)
+			{
+			print_message(names[D_CBC_SEED],c[D_CBC_SEED][j],lengths[j]);
+			Time_F(START);
+			for (count=0,run=1; COND(c[D_CBC_SEED][j]); count++)
+				SEED_cbc_encrypt(buf,buf,
+					(unsigned long)lengths[j],&seed_ks,iv,1);
+			d=Time_F(STOP);
+			print_result(D_CBC_SEED,j,count,d);
+			}
+		}
+#endif
+#ifndef OPENSSL_NO_RC2
+	if (doit[D_CBC_RC2])
+		{
+		for (j=0; j<SIZE_NUM; j++)
+			{
+			print_message(names[D_CBC_RC2],c[D_CBC_RC2][j],lengths[j]);
+			Time_F(START);
+			for (count=0,run=1; COND(c[D_CBC_RC2][j]); count++)
+				RC2_cbc_encrypt(buf,buf,
+					(unsigned long)lengths[j],&rc2_ks,
+					iv,RC2_ENCRYPT);
+			d=Time_F(STOP);
+			print_result(D_CBC_RC2,j,count,d);
+			}
+		}
+#endif
+#ifndef OPENSSL_NO_RC5
+	if (doit[D_CBC_RC5])
+		{
+		for (j=0; j<SIZE_NUM; j++)
+			{
+			print_message(names[D_CBC_RC5],c[D_CBC_RC5][j],lengths[j]);
+			Time_F(START);
+			for (count=0,run=1; COND(c[D_CBC_RC5][j]); count++)
+				RC5_32_cbc_encrypt(buf,buf,
+					(unsigned long)lengths[j],&rc5_ks,
+					iv,RC5_ENCRYPT);
+			d=Time_F(STOP);
+			print_result(D_CBC_RC5,j,count,d);
+			}
+		}
+#endif
+#ifndef OPENSSL_NO_BF
+	if (doit[D_CBC_BF])
+		{
+		for (j=0; j<SIZE_NUM; j++)
+			{
+			print_message(names[D_CBC_BF],c[D_CBC_BF][j],lengths[j]);
+			Time_F(START);
+			for (count=0,run=1; COND(c[D_CBC_BF][j]); count++)
+				BF_cbc_encrypt(buf,buf,
+					(unsigned long)lengths[j],&bf_ks,
+					iv,BF_ENCRYPT);
+			d=Time_F(STOP);
+			print_result(D_CBC_BF,j,count,d);
+			}
+		}
+#endif
+#ifndef OPENSSL_NO_CAST
+	if (doit[D_CBC_CAST])
+		{
+		for (j=0; j<SIZE_NUM; j++)
+			{
+			print_message(names[D_CBC_CAST],c[D_CBC_CAST][j],lengths[j]);
+			Time_F(START);
+			for (count=0,run=1; COND(c[D_CBC_CAST][j]); count++)
+				CAST_cbc_encrypt(buf,buf,
+					(unsigned long)lengths[j],&cast_ks,
+					iv,CAST_ENCRYPT);
+			d=Time_F(STOP);
+			print_result(D_CBC_CAST,j,count,d);
+			}
+		}
+#endif
+
+	if (doit[D_EVP])
+		{
+		for (j=0; j<SIZE_NUM; j++)
+			{
+			if (evp_cipher)
+				{
+				EVP_CIPHER_CTX ctx;
+				int outl;
+
+				names[D_EVP]=OBJ_nid2ln(evp_cipher->nid);
+				/* -O3 -fschedule-insns messes up an
+				 * optimization here!  names[D_EVP]
+				 * somehow becomes NULL */
+				print_message(names[D_EVP],save_count,
+					lengths[j]);
+
+				EVP_CIPHER_CTX_init(&ctx);
+				if(decrypt)
+					EVP_DecryptInit_ex(&ctx,evp_cipher,NULL,key16,iv);
+				else
+					EVP_EncryptInit_ex(&ctx,evp_cipher,NULL,key16,iv);
+				EVP_CIPHER_CTX_set_padding(&ctx, 0);
+
+				Time_F(START);
+				if(decrypt)
+					for (count=0,run=1; COND(save_count*4*lengths[0]/lengths[j]); count++)
+						EVP_DecryptUpdate(&ctx,buf,&outl,buf,lengths[j]);
+				else
+					for (count=0,run=1; COND(save_count*4*lengths[0]/lengths[j]); count++)
+						EVP_EncryptUpdate(&ctx,buf,&outl,buf,lengths[j]);
+				if(decrypt)
+					EVP_DecryptFinal_ex(&ctx,buf,&outl);
+				else
+					EVP_EncryptFinal_ex(&ctx,buf,&outl);
+				d=Time_F(STOP);
+				EVP_CIPHER_CTX_cleanup(&ctx);
+				}
+			if (evp_md)
+				{
+				names[D_EVP]=OBJ_nid2ln(evp_md->type);
+				print_message(names[D_EVP],save_count,
+					lengths[j]);
+
+				Time_F(START);
+				for (count=0,run=1; COND(save_count*4*lengths[0]/lengths[j]); count++)
+					EVP_Digest(buf,lengths[j],&(md[0]),NULL,evp_md,NULL);
+
+				d=Time_F(STOP);
+				}
+			print_result(D_EVP,j,count,d);
+			}
+		}
+
+	RAND_pseudo_bytes(buf,36);
+#ifndef OPENSSL_NO_RSA
+	for (j=0; j<RSA_NUM; j++)
+		{
+		int ret;
+		if (!rsa_doit[j]) continue;
+		ret=RSA_sign(NID_md5_sha1, buf,36, buf2, &rsa_num, rsa_key[j]);
+		if (ret == 0)
+			{
+			BIO_printf(bio_err,"RSA sign failure.  No RSA sign will be done.\n");
+			ERR_print_errors(bio_err);
+			rsa_count=1;
+			}
+		else
+			{
+			pkey_print_message("private","rsa",
+				rsa_c[j][0],rsa_bits[j],
+				RSA_SECONDS);
+/*			RSA_blinding_on(rsa_key[j],NULL); */
+			Time_F(START);
+			for (count=0,run=1; COND(rsa_c[j][0]); count++)
+				{
+				ret=RSA_sign(NID_md5_sha1, buf,36, buf2,
+					&rsa_num, rsa_key[j]);
+				if (ret == 0)
+					{
+					BIO_printf(bio_err,
+						"RSA sign failure\n");
+					ERR_print_errors(bio_err);
+					count=1;
+					break;
+					}
+				}
+			d=Time_F(STOP);
+			BIO_printf(bio_err,mr ? "+R1:%ld:%d:%.2f\n"
+				   : "%ld %d bit private RSA's in %.2fs\n",
+				   count,rsa_bits[j],d);
+			rsa_results[j][0]=d/(double)count;
+			rsa_count=count;
+			}
+
+#if 1
+		ret=RSA_verify(NID_md5_sha1, buf,36, buf2, rsa_num, rsa_key[j]);
+		if (ret <= 0)
+			{
+			BIO_printf(bio_err,"RSA verify failure.  No RSA verify will be done.\n");
+			ERR_print_errors(bio_err);
+			rsa_doit[j] = 0;
+			}
+		else
+			{
+			pkey_print_message("public","rsa",
+				rsa_c[j][1],rsa_bits[j],
+				RSA_SECONDS);
+			Time_F(START);
+			for (count=0,run=1; COND(rsa_c[j][1]); count++)
+				{
+				ret=RSA_verify(NID_md5_sha1, buf,36, buf2,
+					rsa_num, rsa_key[j]);
+				if (ret <= 0)
+					{
+					BIO_printf(bio_err,
+						"RSA verify failure\n");
+					ERR_print_errors(bio_err);
+					count=1;
+					break;
+					}
+				}
+			d=Time_F(STOP);
+			BIO_printf(bio_err,mr ? "+R2:%ld:%d:%.2f\n"
+				   : "%ld %d bit public RSA's in %.2fs\n",
+				   count,rsa_bits[j],d);
+			rsa_results[j][1]=d/(double)count;
+			}
+#endif
+
+		if (rsa_count <= 1)
+			{
+			/* if longer than 10s, don't do any more */
+			for (j++; j<RSA_NUM; j++)
+				rsa_doit[j]=0;
+			}
+		}
+#endif
+
+	RAND_pseudo_bytes(buf,20);
+#ifndef OPENSSL_NO_DSA
+	if (RAND_status() != 1)
+		{
+		RAND_seed(rnd_seed, sizeof rnd_seed);
+		rnd_fake = 1;
+		}
+	for (j=0; j<DSA_NUM; j++)
+		{
+		unsigned int kk;
+		int ret;
+
+		if (!dsa_doit[j]) continue;
+/*		DSA_generate_key(dsa_key[j]); */
+/*		DSA_sign_setup(dsa_key[j],NULL); */
+		ret=DSA_sign(EVP_PKEY_DSA,buf,20,buf2,
+			&kk,dsa_key[j]);
+		if (ret == 0)
+			{
+			BIO_printf(bio_err,"DSA sign failure.  No DSA sign will be done.\n");
+			ERR_print_errors(bio_err);
+			rsa_count=1;
+			}
+		else
+			{
+			pkey_print_message("sign","dsa",
+				dsa_c[j][0],dsa_bits[j],
+				DSA_SECONDS);
+			Time_F(START);
+			for (count=0,run=1; COND(dsa_c[j][0]); count++)
+				{
+				ret=DSA_sign(EVP_PKEY_DSA,buf,20,buf2,
+					&kk,dsa_key[j]);
+				if (ret == 0)
+					{
+					BIO_printf(bio_err,
+						"DSA sign failure\n");
+					ERR_print_errors(bio_err);
+					count=1;
+					break;
+					}
+				}
+			d=Time_F(STOP);
+			BIO_printf(bio_err,mr ? "+R3:%ld:%d:%.2f\n"
+				   : "%ld %d bit DSA signs in %.2fs\n",
+				   count,dsa_bits[j],d);
+			dsa_results[j][0]=d/(double)count;
+			rsa_count=count;
+			}
+
+		ret=DSA_verify(EVP_PKEY_DSA,buf,20,buf2,
+			kk,dsa_key[j]);
+		if (ret <= 0)
+			{
+			BIO_printf(bio_err,"DSA verify failure.  No DSA verify will be done.\n");
+			ERR_print_errors(bio_err);
+			dsa_doit[j] = 0;
+			}
+		else
+			{
+			pkey_print_message("verify","dsa",
+				dsa_c[j][1],dsa_bits[j],
+				DSA_SECONDS);
+			Time_F(START);
+			for (count=0,run=1; COND(dsa_c[j][1]); count++)
+				{
+				ret=DSA_verify(EVP_PKEY_DSA,buf,20,buf2,
+					kk,dsa_key[j]);
+				if (ret <= 0)
+					{
+					BIO_printf(bio_err,
+						"DSA verify failure\n");
+					ERR_print_errors(bio_err);
+					count=1;
+					break;
+					}
+				}
+			d=Time_F(STOP);
+			BIO_printf(bio_err,mr ? "+R4:%ld:%d:%.2f\n"
+				   : "%ld %d bit DSA verify in %.2fs\n",
+				   count,dsa_bits[j],d);
+			dsa_results[j][1]=d/(double)count;
+			}
+
+		if (rsa_count <= 1)
+			{
+			/* if longer than 10s, don't do any more */
+			for (j++; j<DSA_NUM; j++)
+				dsa_doit[j]=0;
+			}
+		}
+	if (rnd_fake) RAND_cleanup();
+#endif
+
+#ifndef OPENSSL_NO_ECDSA
+	if (RAND_status() != 1) 
+		{
+		RAND_seed(rnd_seed, sizeof rnd_seed);
+		rnd_fake = 1;
+		}
+	for (j=0; j<EC_NUM; j++) 
+		{
+		int ret;
+
+		if (!ecdsa_doit[j]) continue; /* Ignore Curve */ 
+		ecdsa[j] = EC_KEY_new_by_curve_name(test_curves[j]);
+		if (ecdsa[j] == NULL) 
+			{
+			BIO_printf(bio_err,"ECDSA failure.\n");
+			ERR_print_errors(bio_err);
+			rsa_count=1;
+			} 
+		else 
+			{
+#if 1
+			EC_KEY_precompute_mult(ecdsa[j], NULL);
+#endif
+			/* Perform ECDSA signature test */
+			EC_KEY_generate_key(ecdsa[j]);
+			ret = ECDSA_sign(0, buf, 20, ecdsasig, 
+				&ecdsasiglen, ecdsa[j]);
+			if (ret == 0) 
+				{
+				BIO_printf(bio_err,"ECDSA sign failure.  No ECDSA sign will be done.\n");
+				ERR_print_errors(bio_err);
+				rsa_count=1;
+				} 
+			else 
+				{
+				pkey_print_message("sign","ecdsa",
+					ecdsa_c[j][0], 
+					test_curves_bits[j],
+					ECDSA_SECONDS);
+
+				Time_F(START);
+				for (count=0,run=1; COND(ecdsa_c[j][0]);
+					count++) 
+					{
+					ret=ECDSA_sign(0, buf, 20, 
+						ecdsasig, &ecdsasiglen,
+						ecdsa[j]);
+					if (ret == 0) 
+						{
+						BIO_printf(bio_err, "ECDSA sign failure\n");
+						ERR_print_errors(bio_err);
+						count=1;
+						break;
+						}
+					}
+				d=Time_F(STOP);
+
+				BIO_printf(bio_err, mr ? "+R5:%ld:%d:%.2f\n" :
+					"%ld %d bit ECDSA signs in %.2fs \n", 
+					count, test_curves_bits[j], d);
+				ecdsa_results[j][0]=d/(double)count;
+				rsa_count=count;
+				}
+
+			/* Perform ECDSA verification test */
+			ret=ECDSA_verify(0, buf, 20, ecdsasig, 
+				ecdsasiglen, ecdsa[j]);
+			if (ret != 1) 
+				{
+				BIO_printf(bio_err,"ECDSA verify failure.  No ECDSA verify will be done.\n");
+				ERR_print_errors(bio_err);
+				ecdsa_doit[j] = 0;
+				} 
+			else 
+				{
+				pkey_print_message("verify","ecdsa",
+				ecdsa_c[j][1],
+				test_curves_bits[j],
+				ECDSA_SECONDS);
+				Time_F(START);
+				for (count=0,run=1; COND(ecdsa_c[j][1]); count++) 
+					{
+					ret=ECDSA_verify(0, buf, 20, ecdsasig, ecdsasiglen, ecdsa[j]);
+					if (ret != 1) 
+						{
+						BIO_printf(bio_err, "ECDSA verify failure\n");
+						ERR_print_errors(bio_err);
+						count=1;
+						break;
+						}
+					}
+				d=Time_F(STOP);
+				BIO_printf(bio_err, mr? "+R6:%ld:%d:%.2f\n"
+						: "%ld %d bit ECDSA verify in %.2fs\n",
+				count, test_curves_bits[j], d);
+				ecdsa_results[j][1]=d/(double)count;
+				}
+
+			if (rsa_count <= 1) 
+				{
+				/* if longer than 10s, don't do any more */
+				for (j++; j<EC_NUM; j++)
+				ecdsa_doit[j]=0;
+				}
+			}
+		}
+	if (rnd_fake) RAND_cleanup();
+#endif
+
+#ifndef OPENSSL_NO_ECDH
+	if (RAND_status() != 1)
+		{
+		RAND_seed(rnd_seed, sizeof rnd_seed);
+		rnd_fake = 1;
+		}
+	for (j=0; j<EC_NUM; j++)
+		{
+		if (!ecdh_doit[j]) continue;
+		ecdh_a[j] = EC_KEY_new_by_curve_name(test_curves[j]);
+		ecdh_b[j] = EC_KEY_new_by_curve_name(test_curves[j]);
+		if ((ecdh_a[j] == NULL) || (ecdh_b[j] == NULL))
+			{
+			BIO_printf(bio_err,"ECDH failure.\n");
+			ERR_print_errors(bio_err);
+			rsa_count=1;
+			}
+		else
+			{
+			/* generate two ECDH key pairs */
+			if (!EC_KEY_generate_key(ecdh_a[j]) ||
+				!EC_KEY_generate_key(ecdh_b[j]))
+				{
+				BIO_printf(bio_err,"ECDH key generation failure.\n");
+				ERR_print_errors(bio_err);
+				rsa_count=1;		
+				}
+			else
+				{
+				/* If field size is not more than 24 octets, then use SHA-1 hash of result;
+				 * otherwise, use result (see section 4.8 of draft-ietf-tls-ecc-03.txt).
+				 */
+				int field_size, outlen;
+				void *(*kdf)(const void *in, size_t inlen, void *out, size_t *xoutlen);
+				field_size = EC_GROUP_get_degree(EC_KEY_get0_group(ecdh_a[j]));
+				if (field_size <= 24 * 8)
+					{
+					outlen = KDF1_SHA1_len;
+					kdf = KDF1_SHA1;
+					}
+				else
+					{
+					outlen = (field_size+7)/8;
+					kdf = NULL;
+					}
+				secret_size_a = ECDH_compute_key(secret_a, outlen,
+					EC_KEY_get0_public_key(ecdh_b[j]),
+					ecdh_a[j], kdf);
+				secret_size_b = ECDH_compute_key(secret_b, outlen,
+					EC_KEY_get0_public_key(ecdh_a[j]),
+					ecdh_b[j], kdf);
+				if (secret_size_a != secret_size_b) 
+					ecdh_checks = 0;
+				else
+					ecdh_checks = 1;
+
+				for (secret_idx = 0; 
+				    (secret_idx < secret_size_a)
+					&& (ecdh_checks == 1);
+				    secret_idx++)
+					{
+					if (secret_a[secret_idx] != secret_b[secret_idx])
+					ecdh_checks = 0;
+					}
+
+				if (ecdh_checks == 0)
+					{
+					BIO_printf(bio_err,"ECDH computations don't match.\n");
+					ERR_print_errors(bio_err);
+					rsa_count=1;		
+					}
+
+				pkey_print_message("","ecdh",
+				ecdh_c[j][0], 
+				test_curves_bits[j],
+				ECDH_SECONDS);
+				Time_F(START);
+				for (count=0,run=1; COND(ecdh_c[j][0]); count++)
+					{
+					ECDH_compute_key(secret_a, outlen,
+					EC_KEY_get0_public_key(ecdh_b[j]),
+					ecdh_a[j], kdf);
+					}
+				d=Time_F(STOP);
+				BIO_printf(bio_err, mr ? "+R7:%ld:%d:%.2f\n" :"%ld %d-bit ECDH ops in %.2fs\n",
+				count, test_curves_bits[j], d);
+				ecdh_results[j][0]=d/(double)count;
+				rsa_count=count;
+				}
+			}
+
+
+		if (rsa_count <= 1)
+			{
+			/* if longer than 10s, don't do any more */
+			for (j++; j<EC_NUM; j++)
+			ecdh_doit[j]=0;
+			}
+		}
+	if (rnd_fake) RAND_cleanup();
+#endif
+#ifdef HAVE_FORK
+show_res:
+#endif
+	if(!mr)
+		{
+		fprintf(stdout,"%s\n",SSLeay_version(SSLEAY_VERSION));
+        fprintf(stdout,"%s\n",SSLeay_version(SSLEAY_BUILT_ON));
+		printf("options:");
+		printf("%s ",BN_options());
+#ifndef OPENSSL_NO_MD2
+		printf("%s ",MD2_options());
+#endif
+#ifndef OPENSSL_NO_RC4
+		printf("%s ",RC4_options());
+#endif
+#ifndef OPENSSL_NO_DES
+		printf("%s ",DES_options());
+#endif
+#ifndef OPENSSL_NO_AES
+		printf("%s ",AES_options());
+#endif
+#ifndef OPENSSL_NO_IDEA
+		printf("%s ",idea_options());
+#endif
+#ifndef OPENSSL_NO_BF
+		printf("%s ",BF_options());
+#endif
+		fprintf(stdout,"\n%s\n",SSLeay_version(SSLEAY_CFLAGS));
+		printf("available timing options: ");
+#ifdef TIMES
+		printf("TIMES ");
+#endif
+#ifdef TIMEB
+		printf("TIMEB ");
+#endif
+#ifdef USE_TOD
+		printf("USE_TOD ");
+#endif
+#ifdef HZ
+#define as_string(s) (#s)
+		{
+		double dbl = HZ;
+		printf("HZ=%g", dbl);
+		}
+# ifdef _SC_CLK_TCK
+		printf(" [sysconf value]");
+# endif
+#endif
+		printf("\n");
+		printf("timing function used: %s%s%s%s%s%s%s\n",
+		       (ftime_used ? "ftime" : ""),
+		       (ftime_used + times_used > 1 ? "," : ""),
+		       (times_used ? "times" : ""),
+		       (ftime_used + times_used + gettimeofday_used > 1 ? "," : ""),
+		       (gettimeofday_used ? "gettimeofday" : ""),
+		       (ftime_used + times_used + gettimeofday_used + getrusage_used > 1 ? "," : ""),
+		       (getrusage_used ? "getrusage" : ""));
+		}
+
+	if (pr_header)
+		{
+		if(mr)
+			fprintf(stdout,"+H");
+		else
+			{
+			fprintf(stdout,"The 'numbers' are in 1000s of bytes per second processed.\n"); 
+			fprintf(stdout,"type        ");
+			}
+		for (j=0;  j<SIZE_NUM; j++)
+			fprintf(stdout,mr ? ":%d" : "%7d bytes",lengths[j]);
+		fprintf(stdout,"\n");
+		}
+
+	for (k=0; k<ALGOR_NUM; k++)
+		{
+		if (!doit[k]) continue;
+		if(mr)
+			fprintf(stdout,"+F:%d:%s",k,names[k]);
+		else
+			fprintf(stdout,"%-13s",names[k]);
+		for (j=0; j<SIZE_NUM; j++)
+			{
+			if (results[k][j] > 10000 && !mr)
+				fprintf(stdout," %11.2fk",results[k][j]/1e3);
+			else
+				fprintf(stdout,mr ? ":%.2f" : " %11.2f ",results[k][j]);
+			}
+		fprintf(stdout,"\n");
+		}
+#ifndef OPENSSL_NO_RSA
+	j=1;
+	for (k=0; k<RSA_NUM; k++)
+		{
+		if (!rsa_doit[k]) continue;
+		if (j && !mr)
+			{
+			printf("%18ssign    verify    sign/s verify/s\n"," ");
+			j=0;
+			}
+		if(mr)
+			fprintf(stdout,"+F2:%u:%u:%f:%f\n",
+				k,rsa_bits[k],rsa_results[k][0],
+				rsa_results[k][1]);
+		else
+			fprintf(stdout,"rsa %4u bits %8.6fs %8.6fs %8.1f %8.1f\n",
+				rsa_bits[k],rsa_results[k][0],rsa_results[k][1],
+				1.0/rsa_results[k][0],1.0/rsa_results[k][1]);
+		}
+#endif
+#ifndef OPENSSL_NO_DSA
+	j=1;
+	for (k=0; k<DSA_NUM; k++)
+		{
+		if (!dsa_doit[k]) continue;
+		if (j && !mr)
+			{
+			printf("%18ssign    verify    sign/s verify/s\n"," ");
+			j=0;
+			}
+		if(mr)
+			fprintf(stdout,"+F3:%u:%u:%f:%f\n",
+				k,dsa_bits[k],dsa_results[k][0],dsa_results[k][1]);
+		else
+			fprintf(stdout,"dsa %4u bits %8.6fs %8.6fs %8.1f %8.1f\n",
+				dsa_bits[k],dsa_results[k][0],dsa_results[k][1],
+				1.0/dsa_results[k][0],1.0/dsa_results[k][1]);
+		}
+#endif
+#ifndef OPENSSL_NO_ECDSA
+	j=1;
+	for (k=0; k<EC_NUM; k++)
+		{
+		if (!ecdsa_doit[k]) continue;
+		if (j && !mr)
+			{
+			printf("%30ssign    verify    sign/s verify/s\n"," ");
+			j=0;
+			}
+
+		if (mr)
+			fprintf(stdout,"+F4:%u:%u:%f:%f\n", 
+				k, test_curves_bits[k],
+				ecdsa_results[k][0],ecdsa_results[k][1]);
+		else
+			fprintf(stdout,
+				"%4u bit ecdsa (%s) %8.4fs %8.4fs %8.1f %8.1f\n", 
+				test_curves_bits[k],
+				test_curves_names[k],
+				ecdsa_results[k][0],ecdsa_results[k][1], 
+				1.0/ecdsa_results[k][0],1.0/ecdsa_results[k][1]);
+		}
+#endif
+
+
+#ifndef OPENSSL_NO_ECDH
+	j=1;
+	for (k=0; k<EC_NUM; k++)
+		{
+		if (!ecdh_doit[k]) continue;
+		if (j && !mr)
+			{
+			printf("%30sop      op/s\n"," ");
+			j=0;
+			}
+		if (mr)
+			fprintf(stdout,"+F5:%u:%u:%f:%f\n",
+				k, test_curves_bits[k],
+				ecdh_results[k][0], 1.0/ecdh_results[k][0]);
+
+		else
+			fprintf(stdout,"%4u bit ecdh (%s) %8.4fs %8.1f\n",
+				test_curves_bits[k],
+				test_curves_names[k],
+				ecdh_results[k][0], 1.0/ecdh_results[k][0]);
+		}
+#endif
+
+	mret=0;
+
+end:
+	ERR_print_errors(bio_err);
+	if (buf != NULL) OPENSSL_free(buf);
+	if (buf2 != NULL) OPENSSL_free(buf2);
+#ifndef OPENSSL_NO_RSA
+	for (i=0; i<RSA_NUM; i++)
+		if (rsa_key[i] != NULL)
+			RSA_free(rsa_key[i]);
+#endif
+#ifndef OPENSSL_NO_DSA
+	for (i=0; i<DSA_NUM; i++)
+		if (dsa_key[i] != NULL)
+			DSA_free(dsa_key[i]);
+#endif
+
+#ifndef OPENSSL_NO_ECDSA
+	for (i=0; i<EC_NUM; i++)
+		if (ecdsa[i] != NULL)
+			EC_KEY_free(ecdsa[i]);
+#endif
+#ifndef OPENSSL_NO_ECDH
+	for (i=0; i<EC_NUM; i++)
+	{
+		if (ecdh_a[i] != NULL)
+			EC_KEY_free(ecdh_a[i]);
+		if (ecdh_b[i] != NULL)
+			EC_KEY_free(ecdh_b[i]);
+	}
+#endif
+
+	apps_shutdown();
+	OPENSSL_EXIT(mret);
+	}
+
+static void print_message(const char *s, long num, int length)
+	{
+#ifdef SIGALRM
+	BIO_printf(bio_err,mr ? "+DT:%s:%d:%d\n"
+		   : "Doing %s for %ds on %d size blocks: ",s,SECONDS,length);
+	(void)BIO_flush(bio_err);
+	alarm(SECONDS);
+#else
+	BIO_printf(bio_err,mr ? "+DN:%s:%ld:%d\n"
+		   : "Doing %s %ld times on %d size blocks: ",s,num,length);
+	(void)BIO_flush(bio_err);
+#endif
+#ifdef LINT
+	num=num;
+#endif
+	}
+
+static void pkey_print_message(const char *str, const char *str2, long num,
+	int bits, int tm)
+	{
+#ifdef SIGALRM
+	BIO_printf(bio_err,mr ? "+DTP:%d:%s:%s:%d\n"
+			   : "Doing %d bit %s %s's for %ds: ",bits,str,str2,tm);
+	(void)BIO_flush(bio_err);
+	alarm(RSA_SECONDS);
+#else
+	BIO_printf(bio_err,mr ? "+DNP:%ld:%d:%s:%s\n"
+			   : "Doing %ld %d bit %s %s's: ",num,bits,str,str2);
+	(void)BIO_flush(bio_err);
+#endif
+#ifdef LINT
+	num=num;
+#endif
+	}
+
+static void print_result(int alg,int run_no,int count,double time_used)
+	{
+	BIO_printf(bio_err,mr ? "+R:%d:%s:%f\n"
+		   : "%d %s's in %.2fs\n",count,names[alg],time_used);
+	results[alg][run_no]=((double)count)/time_used*lengths[run_no];
+	}
+
+#ifdef HAVE_FORK
+static char *sstrsep(char **string, const char *delim)
+    {
+    char isdelim[256];
+    char *token = *string;
+
+    if (**string == 0)
+        return NULL;
+
+    memset(isdelim, 0, sizeof isdelim);
+    isdelim[0] = 1;
+
+    while (*delim)
+        {
+        isdelim[(unsigned char)(*delim)] = 1;
+        delim++;
+        }
+
+    while (!isdelim[(unsigned char)(**string)])
+        {
+        (*string)++;
+        }
+
+    if (**string)
+        {
+        **string = 0;
+        (*string)++;
+        }
+
+    return token;
+    }
+
+static int do_multi(int multi)
+	{
+	int n;
+	int fd[2];
+	int *fds;
+	static char sep[]=":";
+
+	fds=malloc(multi*sizeof *fds);
+	for(n=0 ; n < multi ; ++n)
+		{
+		pipe(fd);
+		fflush(stdout);
+		fflush(stderr);
+		if(fork())
+			{
+			close(fd[1]);
+			fds[n]=fd[0];
+			}
+		else
+			{
+			close(fd[0]);
+			close(1);
+			dup(fd[1]);
+			close(fd[1]);
+			mr=1;
+			usertime=0;
+			return 0;
+			}
+		printf("Forked child %d\n",n);
+		}
+
+	/* for now, assume the pipe is long enough to take all the output */
+	for(n=0 ; n < multi ; ++n)
+		{
+		FILE *f;
+		char buf[1024];
+		char *p;
+
+		f=fdopen(fds[n],"r");
+		while(fgets(buf,sizeof buf,f))
+			{
+			p=strchr(buf,'\n');
+			if(p)
+				*p='\0';
+			if(buf[0] != '+')
+				{
+				fprintf(stderr,"Don't understand line '%s' from child %d\n",
+						buf,n);
+				continue;
+				}
+			printf("Got: %s from %d\n",buf,n);
+			if(!strncmp(buf,"+F:",3))
+				{
+				int alg;
+				int j;
+
+				p=buf+3;
+				alg=atoi(sstrsep(&p,sep));
+				sstrsep(&p,sep);
+				for(j=0 ; j < SIZE_NUM ; ++j)
+					results[alg][j]+=atof(sstrsep(&p,sep));
+				}
+			else if(!strncmp(buf,"+F2:",4))
+				{
+				int k;
+				double d;
+				
+				p=buf+4;
+				k=atoi(sstrsep(&p,sep));
+				sstrsep(&p,sep);
+
+				d=atof(sstrsep(&p,sep));
+				if(n)
+					rsa_results[k][0]=1/(1/rsa_results[k][0]+1/d);
+				else
+					rsa_results[k][0]=d;
+
+				d=atof(sstrsep(&p,sep));
+				if(n)
+					rsa_results[k][1]=1/(1/rsa_results[k][1]+1/d);
+				else
+					rsa_results[k][1]=d;
+				}
+			else if(!strncmp(buf,"+F2:",4))
+				{
+				int k;
+				double d;
+				
+				p=buf+4;
+				k=atoi(sstrsep(&p,sep));
+				sstrsep(&p,sep);
+
+				d=atof(sstrsep(&p,sep));
+				if(n)
+					rsa_results[k][0]=1/(1/rsa_results[k][0]+1/d);
+				else
+					rsa_results[k][0]=d;
+
+				d=atof(sstrsep(&p,sep));
+				if(n)
+					rsa_results[k][1]=1/(1/rsa_results[k][1]+1/d);
+				else
+					rsa_results[k][1]=d;
+				}
+			else if(!strncmp(buf,"+F3:",4))
+				{
+				int k;
+				double d;
+				
+				p=buf+4;
+				k=atoi(sstrsep(&p,sep));
+				sstrsep(&p,sep);
+
+				d=atof(sstrsep(&p,sep));
+				if(n)
+					dsa_results[k][0]=1/(1/dsa_results[k][0]+1/d);
+				else
+					dsa_results[k][0]=d;
+
+				d=atof(sstrsep(&p,sep));
+				if(n)
+					dsa_results[k][1]=1/(1/dsa_results[k][1]+1/d);
+				else
+					dsa_results[k][1]=d;
+				}
+#ifndef OPENSSL_NO_ECDSA
+			else if(!strncmp(buf,"+F4:",4))
+				{
+				int k;
+				double d;
+				
+				p=buf+4;
+				k=atoi(sstrsep(&p,sep));
+				sstrsep(&p,sep);
+
+				d=atof(sstrsep(&p,sep));
+				if(n)
+					ecdsa_results[k][0]=1/(1/ecdsa_results[k][0]+1/d);
+				else
+					ecdsa_results[k][0]=d;
+
+				d=atof(sstrsep(&p,sep));
+				if(n)
+					ecdsa_results[k][1]=1/(1/ecdsa_results[k][1]+1/d);
+				else
+					ecdsa_results[k][1]=d;
+				}
+#endif 
+
+#ifndef OPENSSL_NO_ECDH
+			else if(!strncmp(buf,"+F5:",4))
+				{
+				int k;
+				double d;
+				
+				p=buf+4;
+				k=atoi(sstrsep(&p,sep));
+				sstrsep(&p,sep);
+
+				d=atof(sstrsep(&p,sep));
+				if(n)
+					ecdh_results[k][0]=1/(1/ecdh_results[k][0]+1/d);
+				else
+					ecdh_results[k][0]=d;
+
+				}
+#endif
+
+			else if(!strncmp(buf,"+H:",3))
+				{
+				}
+			else
+				fprintf(stderr,"Unknown type '%s' from child %d\n",buf,n);
+			}
+		}
+	return 1;
+	}
+#endif
+#endif

Added: openssl/branches/upstream/current/apps/spkac.c
===================================================================
--- openssl/branches/upstream/current/apps/spkac.c	                        (rev 0)
+++ openssl/branches/upstream/current/apps/spkac.c	2009-05-16 15:25:35 UTC (rev 372)
@@ -0,0 +1,308 @@
+/* apps/spkac.c */
+
+/* Written by Dr Stephen N Henson (steve at openssl.org) for the OpenSSL
+ * project 1999. Based on an original idea by Massimiliano Pala
+ * (madwolf at openca.org).
+ */
+/* ====================================================================
+ * Copyright (c) 1999 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 at 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 at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "apps.h"
+#include <openssl/bio.h>
+#include <openssl/conf.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/lhash.h>
+#include <openssl/x509.h>
+#include <openssl/pem.h>
+
+#undef PROG
+#define PROG	spkac_main
+
+/* -in arg	- input file - default stdin
+ * -out arg	- output file - default stdout
+ */
+
+int MAIN(int, char **);
+
+int MAIN(int argc, char **argv)
+	{
+	ENGINE *e = NULL;
+	int i,badops=0, ret = 1;
+	BIO *in = NULL,*out = NULL;
+	int verify=0,noout=0,pubkey=0;
+	char *infile = NULL,*outfile = NULL,*prog;
+	char *passargin = NULL, *passin = NULL;
+	const char *spkac = "SPKAC", *spksect = "default";
+	char *spkstr = NULL;
+	char *challenge = NULL, *keyfile = NULL;
+	CONF *conf = NULL;
+	NETSCAPE_SPKI *spki = NULL;
+	EVP_PKEY *pkey = NULL;
+#ifndef OPENSSL_NO_ENGINE
+	char *engine=NULL;
+#endif
+
+	apps_startup();
+
+	if (!bio_err) bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
+
+	if (!load_config(bio_err, NULL))
+		goto end;
+
+	prog=argv[0];
+	argc--;
+	argv++;
+	while (argc >= 1)
+		{
+		if (strcmp(*argv,"-in") == 0)
+			{
+			if (--argc < 1) goto bad;
+			infile= *(++argv);
+			}
+		else if (strcmp(*argv,"-out") == 0)
+			{
+			if (--argc < 1) goto bad;
+			outfile= *(++argv);
+			}
+		else if (strcmp(*argv,"-passin") == 0)
+			{
+			if (--argc < 1) goto bad;
+			passargin= *(++argv);
+			}
+		else if (strcmp(*argv,"-key") == 0)
+			{
+			if (--argc < 1) goto bad;
+			keyfile= *(++argv);
+			}
+		else if (strcmp(*argv,"-challenge") == 0)
+			{
+			if (--argc < 1) goto bad;
+			challenge= *(++argv);
+			}
+		else if (strcmp(*argv,"-spkac") == 0)
+			{
+			if (--argc < 1) goto bad;
+			spkac= *(++argv);
+			}
+		else if (strcmp(*argv,"-spksect") == 0)
+			{
+			if (--argc < 1) goto bad;
+			spksect= *(++argv);
+			}
+#ifndef OPENSSL_NO_ENGINE
+		else if (strcmp(*argv,"-engine") == 0)
+			{
+			if (--argc < 1) goto bad;
+			engine= *(++argv);
+			}
+#endif
+		else if (strcmp(*argv,"-noout") == 0)
+			noout=1;
+		else if (strcmp(*argv,"-pubkey") == 0)
+			pubkey=1;
+		else if (strcmp(*argv,"-verify") == 0)
+			verify=1;
+		else badops = 1;
+		argc--;
+		argv++;
+		}
+
+	if (badops)
+		{
+bad:
+		BIO_printf(bio_err,"%s [options]\n",prog);
+		BIO_printf(bio_err,"where options are\n");
+		BIO_printf(bio_err," -in arg        input file\n");
+		BIO_printf(bio_err," -out arg       output file\n");
+		BIO_printf(bio_err," -key arg       create SPKAC using private key\n");
+		BIO_printf(bio_err," -passin arg    input file pass phrase source\n");
+		BIO_printf(bio_err," -challenge arg challenge string\n");
+		BIO_printf(bio_err," -spkac arg     alternative SPKAC name\n");
+		BIO_printf(bio_err," -noout         don't print SPKAC\n");
+		BIO_printf(bio_err," -pubkey        output public key\n");
+		BIO_printf(bio_err," -verify        verify SPKAC signature\n");
+#ifndef OPENSSL_NO_ENGINE
+		BIO_printf(bio_err," -engine e      use engine e, possibly a hardware device.\n");
+#endif
+		goto end;
+		}
+
+	ERR_load_crypto_strings();
+	if(!app_passwd(bio_err, passargin, NULL, &passin, NULL)) {
+		BIO_printf(bio_err, "Error getting password\n");
+		goto end;
+	}
+
+#ifndef OPENSSL_NO_ENGINE
+        e = setup_engine(bio_err, engine, 0);
+#endif
+
+	if(keyfile) {
+		pkey = load_key(bio_err,
+				strcmp(keyfile, "-") ? keyfile : NULL,
+				FORMAT_PEM, 1, passin, e, "private key");
+		if(!pkey) {
+			goto end;
+		}
+		spki = NETSCAPE_SPKI_new();
+		if(challenge) ASN1_STRING_set(spki->spkac->challenge,
+						 challenge, (int)strlen(challenge));
+		NETSCAPE_SPKI_set_pubkey(spki, pkey);
+		NETSCAPE_SPKI_sign(spki, pkey, EVP_md5());
+		spkstr = NETSCAPE_SPKI_b64_encode(spki);
+
+		if (outfile) out = BIO_new_file(outfile, "w");
+		else {
+			out = BIO_new_fp(stdout, BIO_NOCLOSE);
+#ifdef OPENSSL_SYS_VMS
+			{
+			    BIO *tmpbio = BIO_new(BIO_f_linebuffer());
+			    out = BIO_push(tmpbio, out);
+			}
+#endif
+		}
+
+		if(!out) {
+			BIO_printf(bio_err, "Error opening output file\n");
+			ERR_print_errors(bio_err);
+			goto end;
+		}
+		BIO_printf(out, "SPKAC=%s\n", spkstr);
+		OPENSSL_free(spkstr);
+		ret = 0;
+		goto end;
+	}
+
+	
+
+	if (infile) in = BIO_new_file(infile, "r");
+	else in = BIO_new_fp(stdin, BIO_NOCLOSE);
+
+	if(!in) {
+		BIO_printf(bio_err, "Error opening input file\n");
+		ERR_print_errors(bio_err);
+		goto end;
+	}
+
+	conf = NCONF_new(NULL);
+	i = NCONF_load_bio(conf, in, NULL);
+
+	if(!i) {
+		BIO_printf(bio_err, "Error parsing config file\n");
+		ERR_print_errors(bio_err);
+		goto end;
+	}
+
+	spkstr = NCONF_get_string(conf, spksect, spkac);
+		
+	if(!spkstr) {
+		BIO_printf(bio_err, "Can't find SPKAC called \"%s\"\n", spkac);
+		ERR_print_errors(bio_err);
+		goto end;
+	}
+
+	spki = NETSCAPE_SPKI_b64_decode(spkstr, -1);
+	
+	if(!spki) {
+		BIO_printf(bio_err, "Error loading SPKAC\n");
+		ERR_print_errors(bio_err);
+		goto end;
+	}
+
+	if (outfile) out = BIO_new_file(outfile, "w");
+	else {
+		out = BIO_new_fp(stdout, BIO_NOCLOSE);
+#ifdef OPENSSL_SYS_VMS
+		{
+		    BIO *tmpbio = BIO_new(BIO_f_linebuffer());
+		    out = BIO_push(tmpbio, out);
+		}
+#endif
+	}
+
+	if(!out) {
+		BIO_printf(bio_err, "Error opening output file\n");
+		ERR_print_errors(bio_err);
+		goto end;
+	}
+
+	if(!noout) NETSCAPE_SPKI_print(out, spki);
+	pkey = NETSCAPE_SPKI_get_pubkey(spki);
+	if(verify) {
+		i = NETSCAPE_SPKI_verify(spki, pkey);
+		if (i > 0) BIO_printf(bio_err, "Signature OK\n");
+		else {
+			BIO_printf(bio_err, "Signature Failure\n");
+			ERR_print_errors(bio_err);
+			goto end;
+		}
+	}
+	if(pubkey) PEM_write_bio_PUBKEY(out, pkey);
+
+	ret = 0;
+
+end:
+	NCONF_free(conf);
+	NETSCAPE_SPKI_free(spki);
+	BIO_free(in);
+	BIO_free_all(out);
+	EVP_PKEY_free(pkey);
+	if(passin) OPENSSL_free(passin);
+	apps_shutdown();
+	OPENSSL_EXIT(ret);
+	}

Added: openssl/branches/upstream/current/apps/verify.c
===================================================================
--- openssl/branches/upstream/current/apps/verify.c	                        (rev 0)
+++ openssl/branches/upstream/current/apps/verify.c	2009-05-16 15:25:35 UTC (rev 372)
@@ -0,0 +1,369 @@
+/* apps/verify.c */
+/* Copyright (C) 1995-1998 Eric Young (eay at cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay at cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh at cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay at cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh at cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "apps.h"
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/pem.h>
+
+#undef PROG
+#define PROG	verify_main
+
+static int MS_CALLBACK cb(int ok, X509_STORE_CTX *ctx);
+static int check(X509_STORE *ctx, char *file, STACK_OF(X509) *uchain, STACK_OF(X509) *tchain, int purpose, ENGINE *e);
+static STACK_OF(X509) *load_untrusted(char *file);
+static int v_verbose=0, vflags = 0;
+
+int MAIN(int, char **);
+
+int MAIN(int argc, char **argv)
+	{
+	ENGINE *e = NULL;
+	int i,ret=1, badarg = 0;
+	int purpose = -1;
+	char *CApath=NULL,*CAfile=NULL;
+	char *untfile = NULL, *trustfile = NULL;
+	STACK_OF(X509) *untrusted = NULL, *trusted = NULL;
+	X509_STORE *cert_ctx=NULL;
+	X509_LOOKUP *lookup=NULL;
+	X509_VERIFY_PARAM *vpm = NULL;
+#ifndef OPENSSL_NO_ENGINE
+	char *engine=NULL;
+#endif
+
+	cert_ctx=X509_STORE_new();
+	if (cert_ctx == NULL) goto end;
+	X509_STORE_set_verify_cb_func(cert_ctx,cb);
+
+	ERR_load_crypto_strings();
+
+	apps_startup();
+
+	if (bio_err == NULL)
+		if ((bio_err=BIO_new(BIO_s_file())) != NULL)
+			BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
+
+	if (!load_config(bio_err, NULL))
+		goto end;
+
+	argc--;
+	argv++;
+	for (;;)
+		{
+		if (argc >= 1)
+			{
+			if (strcmp(*argv,"-CApath") == 0)
+				{
+				if (argc-- < 1) goto end;
+				CApath= *(++argv);
+				}
+			else if (strcmp(*argv,"-CAfile") == 0)
+				{
+				if (argc-- < 1) goto end;
+				CAfile= *(++argv);
+				}
+			else if (args_verify(&argv, &argc, &badarg, bio_err,
+									&vpm))
+				{
+				if (badarg)
+					goto end;
+				continue;
+				}
+			else if (strcmp(*argv,"-untrusted") == 0)
+				{
+				if (argc-- < 1) goto end;
+				untfile= *(++argv);
+				}
+			else if (strcmp(*argv,"-trusted") == 0)
+				{
+				if (argc-- < 1) goto end;
+				trustfile= *(++argv);
+				}
+#ifndef OPENSSL_NO_ENGINE
+			else if (strcmp(*argv,"-engine") == 0)
+				{
+				if (--argc < 1) goto end;
+				engine= *(++argv);
+				}
+#endif
+			else if (strcmp(*argv,"-help") == 0)
+				goto end;
+			else if (strcmp(*argv,"-verbose") == 0)
+				v_verbose=1;
+			else if (argv[0][0] == '-')
+				goto end;
+			else
+				break;
+			argc--;
+			argv++;
+			}
+		else
+			break;
+		}
+
+#ifndef OPENSSL_NO_ENGINE
+        e = setup_engine(bio_err, engine, 0);
+#endif
+
+	if (vpm)
+		X509_STORE_set1_param(cert_ctx, vpm);
+
+	lookup=X509_STORE_add_lookup(cert_ctx,X509_LOOKUP_file());
+	if (lookup == NULL) abort();
+	if (CAfile) {
+		i=X509_LOOKUP_load_file(lookup,CAfile,X509_FILETYPE_PEM);
+		if(!i) {
+			BIO_printf(bio_err, "Error loading file %s\n", CAfile);
+			ERR_print_errors(bio_err);
+			goto end;
+		}
+	} else X509_LOOKUP_load_file(lookup,NULL,X509_FILETYPE_DEFAULT);
+		
+	lookup=X509_STORE_add_lookup(cert_ctx,X509_LOOKUP_hash_dir());
+	if (lookup == NULL) abort();
+	if (CApath) {
+		i=X509_LOOKUP_add_dir(lookup,CApath,X509_FILETYPE_PEM);
+		if(!i) {
+			BIO_printf(bio_err, "Error loading directory %s\n", CApath);
+			ERR_print_errors(bio_err);
+			goto end;
+		}
+	} else X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT);
+
+	ERR_clear_error();
+
+	if(untfile) {
+		if(!(untrusted = load_untrusted(untfile))) {
+			BIO_printf(bio_err, "Error loading untrusted file %s\n", untfile);
+			ERR_print_errors(bio_err);
+			goto end;
+		}
+	}
+
+	if(trustfile) {
+		if(!(trusted = load_untrusted(trustfile))) {
+			BIO_printf(bio_err, "Error loading untrusted file %s\n", trustfile);
+			ERR_print_errors(bio_err);
+			goto end;
+		}
+	}
+
+	if (argc < 1) check(cert_ctx, NULL, untrusted, trusted, purpose, e);
+	else
+		for (i=0; i<argc; i++)
+			check(cert_ctx,argv[i], untrusted, trusted, purpose, e);
+	ret=0;
+end:
+	if (ret == 1) {
+		BIO_printf(bio_err,"usage: verify [-verbose] [-CApath path] [-CAfile file] [-purpose purpose] [-crl_check]");
+#ifndef OPENSSL_NO_ENGINE
+		BIO_printf(bio_err," [-engine e]");
+#endif
+		BIO_printf(bio_err," cert1 cert2 ...\n");
+		BIO_printf(bio_err,"recognized usages:\n");
+		for(i = 0; i < X509_PURPOSE_get_count(); i++) {
+			X509_PURPOSE *ptmp;
+			ptmp = X509_PURPOSE_get0(i);
+			BIO_printf(bio_err, "\t%-10s\t%s\n", X509_PURPOSE_get0_sname(ptmp),
+								X509_PURPOSE_get0_name(ptmp));
+		}
+	}
+	if (vpm) X509_VERIFY_PARAM_free(vpm);
+	if (cert_ctx != NULL) X509_STORE_free(cert_ctx);
+	sk_X509_pop_free(untrusted, X509_free);
+	sk_X509_pop_free(trusted, X509_free);
+	apps_shutdown();
+	OPENSSL_EXIT(ret);
+	}
+
+static int check(X509_STORE *ctx, char *file, STACK_OF(X509) *uchain, STACK_OF(X509) *tchain, int purpose, ENGINE *e)
+	{
+	X509 *x=NULL;
+	int i=0,ret=0;
+	X509_STORE_CTX *csc;
+
+	x = load_cert(bio_err, file, FORMAT_PEM, NULL, e, "certificate file");
+	if (x == NULL)
+		goto end;
+	fprintf(stdout,"%s: ",(file == NULL)?"stdin":file);
+
+	csc = X509_STORE_CTX_new();
+	if (csc == NULL)
+		{
+		ERR_print_errors(bio_err);
+		goto end;
+		}
+	X509_STORE_set_flags(ctx, vflags);
+	if(!X509_STORE_CTX_init(csc,ctx,x,uchain))
+		{
+		ERR_print_errors(bio_err);
+		goto end;
+		}
+	if(tchain) X509_STORE_CTX_trusted_stack(csc, tchain);
+	if(purpose >= 0) X509_STORE_CTX_set_purpose(csc, purpose);
+	i=X509_verify_cert(csc);
+	X509_STORE_CTX_free(csc);
+
+	ret=0;
+end:
+	if (i > 0)
+		{
+		fprintf(stdout,"OK\n");
+		ret=1;
+		}
+	else
+		ERR_print_errors(bio_err);
+	if (x != NULL) X509_free(x);
+
+	return(ret);
+	}
+
+static STACK_OF(X509) *load_untrusted(char *certfile)
+{
+	STACK_OF(X509_INFO) *sk=NULL;
+	STACK_OF(X509) *stack=NULL, *ret=NULL;
+	BIO *in=NULL;
+	X509_INFO *xi;
+
+	if(!(stack = sk_X509_new_null())) {
+		BIO_printf(bio_err,"memory allocation failure\n");
+		goto end;
+	}
+
+	if(!(in=BIO_new_file(certfile, "r"))) {
+		BIO_printf(bio_err,"error opening the file, %s\n",certfile);
+		goto end;
+	}
+
+	/* This loads from a file, a stack of x509/crl/pkey sets */
+	if(!(sk=PEM_X509_INFO_read_bio(in,NULL,NULL,NULL))) {
+		BIO_printf(bio_err,"error reading the file, %s\n",certfile);
+		goto end;
+	}
+
+	/* scan over it and pull out the certs */
+	while (sk_X509_INFO_num(sk))
+		{
+		xi=sk_X509_INFO_shift(sk);
+		if (xi->x509 != NULL)
+			{
+			sk_X509_push(stack,xi->x509);
+			xi->x509=NULL;
+			}
+		X509_INFO_free(xi);
+		}
+	if(!sk_X509_num(stack)) {
+		BIO_printf(bio_err,"no certificates in file, %s\n",certfile);
+		sk_X509_free(stack);
+		goto end;
+	}
+	ret=stack;
+end:
+	BIO_free(in);
+	sk_X509_INFO_free(sk);
+	return(ret);
+	}
+
+static int MS_CALLBACK cb(int ok, X509_STORE_CTX *ctx)
+	{
+	char buf[256];
+
+	if (!ok)
+		{
+		if (ctx->current_cert)
+			{
+			X509_NAME_oneline(
+				X509_get_subject_name(ctx->current_cert),buf,
+				sizeof buf);
+			printf("%s\n",buf);
+			}
+		printf("error %d at %d depth lookup:%s\n",ctx->error,
+			ctx->error_depth,
+			X509_verify_cert_error_string(ctx->error));
+		if (ctx->error == X509_V_ERR_CERT_HAS_EXPIRED) ok=1;
+		/* since we are just checking the certificates, it is
+		 * ok if they are self signed. But we should still warn
+		 * the user.
+ 		 */
+		if (ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) ok=1;
+		/* Continue after extension errors too */
+		if (ctx->error == X509_V_ERR_INVALID_CA) ok=1;
+		if (ctx->error == X509_V_ERR_INVALID_NON_CA) ok=1;
+		if (ctx->error == X509_V_ERR_PATH_LENGTH_EXCEEDED) ok=1;
+		if (ctx->error == X509_V_ERR_INVALID_PURPOSE) ok=1;
+		if (ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) ok=1;
+		if (ctx->error == X509_V_ERR_CRL_HAS_EXPIRED) ok=1;
+		if (ctx->error == X509_V_ERR_CRL_NOT_YET_VALID) ok=1;
+		if (ctx->error == X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION) ok=1;
+
+		if (ctx->error == X509_V_ERR_NO_EXPLICIT_POLICY)
+			policies_print(NULL, ctx);
+		return ok;
+
+		}
+	if ((ctx->error == X509_V_OK) && (ok == 2))
+		policies_print(NULL, ctx);
+	if (!v_verbose)
+		ERR_clear_error();
+	return(ok);
+	}

Added: openssl/branches/upstream/current/apps/x509.c
===================================================================
--- openssl/branches/upstream/current/apps/x509.c	                        (rev 0)
+++ openssl/branches/upstream/current/apps/x509.c	2009-05-16 15:25:35 UTC (rev 372)
@@ -0,0 +1,1285 @@
+/* apps/x509.c */
+/* Copyright (C) 1995-1998 Eric Young (eay at cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay at cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh at cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay at cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh at cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef OPENSSL_NO_STDIO
+#define APPS_WIN16
+#endif
+#include "apps.h"
+#include <openssl/bio.h>
+#include <openssl/asn1.h>
+#include <openssl/err.h>
+#include <openssl/bn.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/objects.h>
+#include <openssl/pem.h>
+#ifndef OPENSSL_NO_RSA
+#include <openssl/rsa.h>
+#endif
+#ifndef OPENSSL_NO_DSA
+#include <openssl/dsa.h>
+#endif
+
+#undef PROG
+#define PROG x509_main
+
+#undef POSTFIX
+#define	POSTFIX	".srl"
+#define DEF_DAYS	30
+
+static const char *x509_usage[]={
+"usage: x509 args\n",
+" -inform arg     - input format - default PEM (one of DER, NET or PEM)\n",
+" -outform arg    - output format - default PEM (one of DER, NET or PEM)\n",
+" -keyform arg    - private key format - default PEM\n",
+" -CAform arg     - CA format - default PEM\n",
+" -CAkeyform arg  - CA key format - default PEM\n",
+" -in arg         - input file - default stdin\n",
+" -out arg        - output file - default stdout\n",
+" -passin arg     - private key password source\n",
+" -serial         - print serial number value\n",
+" -subject_hash   - print subject hash value\n",
+" -issuer_hash    - print issuer hash value\n",
+" -hash           - synonym for -subject_hash\n",
+" -subject        - print subject DN\n",
+" -issuer         - print issuer DN\n",
+" -email          - print email address(es)\n",
+" -startdate      - notBefore field\n",
+" -enddate        - notAfter field\n",
+" -purpose        - print out certificate purposes\n",
+" -dates          - both Before and After dates\n",
+" -modulus        - print the RSA key modulus\n",
+" -pubkey         - output the public key\n",
+" -fingerprint    - print the certificate fingerprint\n",
+" -alias          - output certificate alias\n",
+" -noout          - no certificate output\n",
+" -ocspid         - print OCSP hash values for the subject name and public key\n",
+" -ocsp_uri       - print OCSP Responder URL(s)\n",
+" -trustout       - output a \"trusted\" certificate\n",
+" -clrtrust       - clear all trusted purposes\n",
+" -clrreject      - clear all rejected purposes\n",
+" -addtrust arg   - trust certificate for a given purpose\n",
+" -addreject arg  - reject certificate for a given purpose\n",
+" -setalias arg   - set certificate alias\n",
+" -days arg       - How long till expiry of a signed certificate - def 30 days\n",
+" -checkend arg   - check whether the cert expires in the next arg seconds\n",
+"                   exit 1 if so, 0 if not\n",
+" -signkey arg    - self sign cert with arg\n",
+" -x509toreq      - output a certification request object\n",
+" -req            - input is a certificate request, sign and output.\n",
+" -CA arg         - set the CA certificate, must be PEM format.\n",
+" -CAkey arg      - set the CA key, must be PEM format\n",
+"                   missing, it is assumed to be in the CA file.\n",
+" -CAcreateserial - create serial number file if it does not exist\n",
+" -CAserial arg   - serial file\n",
+" -set_serial     - serial number to use\n",
+" -text           - print the certificate in text form\n",
+" -C              - print out C code forms\n",
+" -md2/-md5/-sha1/-mdc2 - digest to use\n",
+" -extfile        - configuration file with X509V3 extensions to add\n",
+" -extensions     - section from config file with X509V3 extensions to add\n",
+" -clrext         - delete extensions before signing and input certificate\n",
+" -nameopt arg    - various certificate name options\n",
+#ifndef OPENSSL_NO_ENGINE
+" -engine e       - use engine e, possibly a hardware device.\n",
+#endif
+" -certopt arg    - various certificate text options\n",
+NULL
+};
+
+static int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx);
+static int sign (X509 *x, EVP_PKEY *pkey,int days,int clrext, const EVP_MD *digest,
+						CONF *conf, char *section);
+static int x509_certify (X509_STORE *ctx,char *CAfile,const EVP_MD *digest,
+			 X509 *x,X509 *xca,EVP_PKEY *pkey,char *serial,
+			 int create,int days, int clrext, CONF *conf, char *section,
+						ASN1_INTEGER *sno);
+static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt);
+static int reqfile=0;
+
+int MAIN(int, char **);
+
+int MAIN(int argc, char **argv)
+	{
+	ENGINE *e = NULL;
+	int ret=1;
+	X509_REQ *req=NULL;
+	X509 *x=NULL,*xca=NULL;
+	ASN1_OBJECT *objtmp;
+	EVP_PKEY *Upkey=NULL,*CApkey=NULL;
+	ASN1_INTEGER *sno = NULL;
+	int i,num,badops=0;
+	BIO *out=NULL;
+	BIO *STDout=NULL;
+	STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL;
+	int informat,outformat,keyformat,CAformat,CAkeyformat;
+	char *infile=NULL,*outfile=NULL,*keyfile=NULL,*CAfile=NULL;
+	char *CAkeyfile=NULL,*CAserial=NULL;
+	char *alias=NULL;
+	int text=0,serial=0,subject=0,issuer=0,startdate=0,enddate=0;
+	int next_serial=0;
+	int subject_hash=0,issuer_hash=0,ocspid=0;
+	int noout=0,sign_flag=0,CA_flag=0,CA_createserial=0,email=0;
+	int ocsp_uri=0;
+	int trustout=0,clrtrust=0,clrreject=0,aliasout=0,clrext=0;
+	int C=0;
+	int x509req=0,days=DEF_DAYS,modulus=0,pubkey=0;
+	int pprint = 0;
+	const char **pp;
+	X509_STORE *ctx=NULL;
+	X509_REQ *rq=NULL;
+	int fingerprint=0;
+	char buf[256];
+	const EVP_MD *md_alg,*digest=EVP_sha1();
+	CONF *extconf = NULL;
+	char *extsect = NULL, *extfile = NULL, *passin = NULL, *passargin = NULL;
+	int need_rand = 0;
+	int checkend=0,checkoffset=0;
+	unsigned long nmflag = 0, certflag = 0;
+#ifndef OPENSSL_NO_ENGINE
+	char *engine=NULL;
+#endif
+
+	reqfile=0;
+
+	apps_startup();
+
+	if (bio_err == NULL)
+		bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
+
+	if (!load_config(bio_err, NULL))
+		goto end;
+	STDout=BIO_new_fp(stdout,BIO_NOCLOSE);
+#ifdef OPENSSL_SYS_VMS
+	{
+	BIO *tmpbio = BIO_new(BIO_f_linebuffer());
+	STDout = BIO_push(tmpbio, STDout);
+	}
+#endif
+
+	informat=FORMAT_PEM;
+	outformat=FORMAT_PEM;
+	keyformat=FORMAT_PEM;
+	CAformat=FORMAT_PEM;
+	CAkeyformat=FORMAT_PEM;
+
+	ctx=X509_STORE_new();
+	if (ctx == NULL) goto end;
+	X509_STORE_set_verify_cb_func(ctx,callb);
+
+	argc--;
+	argv++;
+	num=0;
+	while (argc >= 1)
+		{
+		if 	(strcmp(*argv,"-inform") == 0)
+			{
+			if (--argc < 1) goto bad;
+			informat=str2fmt(*(++argv));
+			}
+		else if (strcmp(*argv,"-outform") == 0)
+			{
+			if (--argc < 1) goto bad;
+			outformat=str2fmt(*(++argv));
+			}
+		else if (strcmp(*argv,"-keyform") == 0)
+			{
+			if (--argc < 1) goto bad;
+			keyformat=str2fmt(*(++argv));
+			}
+		else if (strcmp(*argv,"-req") == 0)
+			{
+			reqfile=1;
+			need_rand = 1;
+			}
+		else if (strcmp(*argv,"-CAform") == 0)
+			{
+			if (--argc < 1) goto bad;
+			CAformat=str2fmt(*(++argv));
+			}
+		else if (strcmp(*argv,"-CAkeyform") == 0)
+			{
+			if (--argc < 1) goto bad;
+			CAkeyformat=str2fmt(*(++argv));
+			}
+		else if (strcmp(*argv,"-days") == 0)
+			{
+			if (--argc < 1) goto bad;
+			days=atoi(*(++argv));
+			if (days == 0)
+				{
+				BIO_printf(STDout,"bad number of days\n");
+				goto bad;
+				}
+			}
+		else if (strcmp(*argv,"-passin") == 0)
+			{
+			if (--argc < 1) goto bad;
+			passargin= *(++argv);
+			}
+		else if (strcmp(*argv,"-extfile") == 0)
+			{
+			if (--argc < 1) goto bad;
+			extfile= *(++argv);
+			}
+		else if (strcmp(*argv,"-extensions") == 0)
+			{
+			if (--argc < 1) goto bad;
+			extsect= *(++argv);
+			}
+		else if (strcmp(*argv,"-in") == 0)
+			{
+			if (--argc < 1) goto bad;
+			infile= *(++argv);
+			}
+		else if (strcmp(*argv,"-out") == 0)
+			{
+			if (--argc < 1) goto bad;
+			outfile= *(++argv);
+			}
+		else if (strcmp(*argv,"-signkey") == 0)
+			{
+			if (--argc < 1) goto bad;
+			keyfile= *(++argv);
+			sign_flag= ++num;
+			need_rand = 1;
+			}
+		else if (strcmp(*argv,"-CA") == 0)
+			{
+			if (--argc < 1) goto bad;
+			CAfile= *(++argv);
+			CA_flag= ++num;
+			need_rand = 1;
+			}
+		else if (strcmp(*argv,"-CAkey") == 0)
+			{
+			if (--argc < 1) goto bad;
+			CAkeyfile= *(++argv);
+			}
+		else if (strcmp(*argv,"-CAserial") == 0)
+			{
+			if (--argc < 1) goto bad;
+			CAserial= *(++argv);
+			}
+		else if (strcmp(*argv,"-set_serial") == 0)
+			{
+			if (--argc < 1) goto bad;
+			if (!(sno = s2i_ASN1_INTEGER(NULL, *(++argv))))
+				goto bad;
+			}
+		else if (strcmp(*argv,"-addtrust") == 0)
+			{
+			if (--argc < 1) goto bad;
+			if (!(objtmp = OBJ_txt2obj(*(++argv), 0)))
+				{
+				BIO_printf(bio_err,
+					"Invalid trust object value %s\n", *argv);
+				goto bad;
+				}
+			if (!trust) trust = sk_ASN1_OBJECT_new_null();
+			sk_ASN1_OBJECT_push(trust, objtmp);
+			trustout = 1;
+			}
+		else if (strcmp(*argv,"-addreject") == 0)
+			{
+			if (--argc < 1) goto bad;
+			if (!(objtmp = OBJ_txt2obj(*(++argv), 0)))
+				{
+				BIO_printf(bio_err,
+					"Invalid reject object value %s\n", *argv);
+				goto bad;
+				}
+			if (!reject) reject = sk_ASN1_OBJECT_new_null();
+			sk_ASN1_OBJECT_push(reject, objtmp);
+			trustout = 1;
+			}
+		else if (strcmp(*argv,"-setalias") == 0)
+			{
+			if (--argc < 1) goto bad;
+			alias= *(++argv);
+			trustout = 1;
+			}
+		else if (strcmp(*argv,"-certopt") == 0)
+			{
+			if (--argc < 1) goto bad;
+			if (!set_cert_ex(&certflag, *(++argv))) goto bad;
+			}
+		else if (strcmp(*argv,"-nameopt") == 0)
+			{
+			if (--argc < 1) goto bad;
+			if (!set_name_ex(&nmflag, *(++argv))) goto bad;
+			}
+#ifndef OPENSSL_NO_ENGINE
+		else if (strcmp(*argv,"-engine") == 0)
+			{
+			if (--argc < 1) goto bad;
+			engine= *(++argv);
+			}
+#endif
+		else if (strcmp(*argv,"-C") == 0)
+			C= ++num;
+		else if (strcmp(*argv,"-email") == 0)
+			email= ++num;
+		else if (strcmp(*argv,"-ocsp_uri") == 0)
+			ocsp_uri= ++num;
+		else if (strcmp(*argv,"-serial") == 0)
+			serial= ++num;
+		else if (strcmp(*argv,"-next_serial") == 0)
+			next_serial= ++num;
+		else if (strcmp(*argv,"-modulus") == 0)
+			modulus= ++num;
+		else if (strcmp(*argv,"-pubkey") == 0)
+			pubkey= ++num;
+		else if (strcmp(*argv,"-x509toreq") == 0)
+			x509req= ++num;
+		else if (strcmp(*argv,"-text") == 0)
+			text= ++num;
+		else if (strcmp(*argv,"-hash") == 0
+			|| strcmp(*argv,"-subject_hash") == 0)
+			subject_hash= ++num;
+		else if (strcmp(*argv,"-issuer_hash") == 0)
+			issuer_hash= ++num;
+		else if (strcmp(*argv,"-subject") == 0)
+			subject= ++num;
+		else if (strcmp(*argv,"-issuer") == 0)
+			issuer= ++num;
+		else if (strcmp(*argv,"-fingerprint") == 0)
+			fingerprint= ++num;
+		else if (strcmp(*argv,"-dates") == 0)
+			{
+			startdate= ++num;
+			enddate= ++num;
+			}
+		else if (strcmp(*argv,"-purpose") == 0)
+			pprint= ++num;
+		else if (strcmp(*argv,"-startdate") == 0)
+			startdate= ++num;
+		else if (strcmp(*argv,"-enddate") == 0)
+			enddate= ++num;
+		else if (strcmp(*argv,"-checkend") == 0)
+			{
+			if (--argc < 1) goto bad;
+			checkoffset=atoi(*(++argv));
+			checkend=1;
+			}
+		else if (strcmp(*argv,"-noout") == 0)
+			noout= ++num;
+		else if (strcmp(*argv,"-trustout") == 0)
+			trustout= 1;
+		else if (strcmp(*argv,"-clrtrust") == 0)
+			clrtrust= ++num;
+		else if (strcmp(*argv,"-clrreject") == 0)
+			clrreject= ++num;
+		else if (strcmp(*argv,"-alias") == 0)
+			aliasout= ++num;
+		else if (strcmp(*argv,"-CAcreateserial") == 0)
+			CA_createserial= ++num;
+		else if (strcmp(*argv,"-clrext") == 0)
+			clrext = 1;
+#if 1 /* stay backwards-compatible with 0.9.5; this should go away soon */
+		else if (strcmp(*argv,"-crlext") == 0)
+			{
+			BIO_printf(bio_err,"use -clrext instead of -crlext\n");
+			clrext = 1;
+			}
+#endif
+		else if (strcmp(*argv,"-ocspid") == 0)
+			ocspid= ++num;
+		else if ((md_alg=EVP_get_digestbyname(*argv + 1)))
+			{
+			/* ok */
+			digest=md_alg;
+			}
+		else
+			{
+			BIO_printf(bio_err,"unknown option %s\n",*argv);
+			badops=1;
+			break;
+			}
+		argc--;
+		argv++;
+		}
+
+	if (badops)
+		{
+bad:
+		for (pp=x509_usage; (*pp != NULL); pp++)
+			BIO_printf(bio_err,"%s",*pp);
+		goto end;
+		}
+
+#ifndef OPENSSL_NO_ENGINE
+        e = setup_engine(bio_err, engine, 0);
+#endif
+
+	if (need_rand)
+		app_RAND_load_file(NULL, bio_err, 0);
+
+	ERR_load_crypto_strings();
+
+	if (!app_passwd(bio_err, passargin, NULL, &passin, NULL))
+		{
+		BIO_printf(bio_err, "Error getting password\n");
+		goto end;
+		}
+
+	if (!X509_STORE_set_default_paths(ctx))
+		{
+		ERR_print_errors(bio_err);
+		goto end;
+		}
+
+	if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM))
+		{ CAkeyfile=CAfile; }
+	else if ((CA_flag) && (CAkeyfile == NULL))
+		{
+		BIO_printf(bio_err,"need to specify a CAkey if using the CA command\n");
+		goto end;
+		}
+
+	if (extfile)
+		{
+		long errorline = -1;
+		X509V3_CTX ctx2;
+		extconf = NCONF_new(NULL);
+		if (!NCONF_load(extconf, extfile,&errorline))
+			{
+			if (errorline <= 0)
+				BIO_printf(bio_err,
+					"error loading the config file '%s'\n",
+								extfile);
+                	else
+                        	BIO_printf(bio_err,
+				       "error on line %ld of config file '%s'\n"
+							,errorline,extfile);
+			goto end;
+			}
+		if (!extsect)
+			{
+			extsect = NCONF_get_string(extconf, "default", "extensions");
+			if (!extsect)
+				{
+				ERR_clear_error();
+				extsect = "default";
+				}
+			}
+		X509V3_set_ctx_test(&ctx2);
+		X509V3_set_nconf(&ctx2, extconf);
+		if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL))
+			{
+			BIO_printf(bio_err,
+				"Error Loading extension section %s\n",
+								 extsect);
+			ERR_print_errors(bio_err);
+			goto end;
+			}
+		}
+
+
+	if (reqfile)
+		{
+		EVP_PKEY *pkey;
+		X509_CINF *ci;
+		BIO *in;
+
+		if (!sign_flag && !CA_flag)
+			{
+			BIO_printf(bio_err,"We need a private key to sign with\n");
+			goto end;
+			}
+		in=BIO_new(BIO_s_file());
+		if (in == NULL)
+			{
+			ERR_print_errors(bio_err);
+			goto end;
+			}
+
+		if (infile == NULL)
+			BIO_set_fp(in,stdin,BIO_NOCLOSE|BIO_FP_TEXT);
+		else
+			{
+			if (BIO_read_filename(in,infile) <= 0)
+				{
+				perror(infile);
+				BIO_free(in);
+				goto end;
+				}
+			}
+		req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL);
+		BIO_free(in);
+
+		if (req == NULL)
+			{
+			ERR_print_errors(bio_err);
+			goto end;
+			}
+
+		if (	(req->req_info == NULL) ||
+			(req->req_info->pubkey == NULL) ||
+			(req->req_info->pubkey->public_key == NULL) ||
+			(req->req_info->pubkey->public_key->data == NULL))
+			{
+			BIO_printf(bio_err,"The certificate request appears to corrupted\n");
+			BIO_printf(bio_err,"It does not contain a public key\n");
+			goto end;
+			}
+		if ((pkey=X509_REQ_get_pubkey(req)) == NULL)
+	                {
+	                BIO_printf(bio_err,"error unpacking public key\n");
+	                goto end;
+	                }
+		i=X509_REQ_verify(req,pkey);
+		EVP_PKEY_free(pkey);
+		if (i < 0)
+			{
+			BIO_printf(bio_err,"Signature verification error\n");
+			ERR_print_errors(bio_err);
+			goto end;
+			}
+	        if (i == 0)
+			{
+			BIO_printf(bio_err,"Signature did not match the certificate request\n");
+			goto end;
+			}
+		else
+			BIO_printf(bio_err,"Signature ok\n");
+
+		print_name(bio_err, "subject=", X509_REQ_get_subject_name(req), nmflag);
+
+		if ((x=X509_new()) == NULL) goto end;
+		ci=x->cert_info;
+
+		if (sno == NULL)
+			{
+			sno = ASN1_INTEGER_new();
+			if (!sno || !rand_serial(NULL, sno))
+				goto end;
+			if (!X509_set_serialNumber(x, sno)) 
+				goto end;
+			ASN1_INTEGER_free(sno);
+			sno = NULL;
+			}
+		else if (!X509_set_serialNumber(x, sno)) 
+			goto end;
+
+		if (!X509_set_issuer_name(x,req->req_info->subject)) goto end;
+		if (!X509_set_subject_name(x,req->req_info->subject)) goto end;
+
+		X509_gmtime_adj(X509_get_notBefore(x),0);
+	        X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days);
+
+		pkey = X509_REQ_get_pubkey(req);
+		X509_set_pubkey(x,pkey);
+		EVP_PKEY_free(pkey);
+		}
+	else
+		x=load_cert(bio_err,infile,informat,NULL,e,"Certificate");
+
+	if (x == NULL) goto end;
+	if (CA_flag)
+		{
+		xca=load_cert(bio_err,CAfile,CAformat,NULL,e,"CA Certificate");
+		if (xca == NULL) goto end;
+		}
+
+	if (!noout || text || next_serial)
+		{
+		OBJ_create("2.99999.3",
+			"SET.ex3","SET x509v3 extension 3");
+
+		out=BIO_new(BIO_s_file());
+		if (out == NULL)
+			{
+			ERR_print_errors(bio_err);
+			goto end;
+			}
+		if (outfile == NULL)
+			{
+			BIO_set_fp(out,stdout,BIO_NOCLOSE);
+#ifdef OPENSSL_SYS_VMS
+			{
+			BIO *tmpbio = BIO_new(BIO_f_linebuffer());
+			out = BIO_push(tmpbio, out);
+			}
+#endif
+			}
+		else
+			{
+			if (BIO_write_filename(out,outfile) <= 0)
+				{
+				perror(outfile);
+				goto end;
+				}
+			}
+		}
+
+	if (alias) X509_alias_set1(x, (unsigned char *)alias, -1);
+
+	if (clrtrust) X509_trust_clear(x);
+	if (clrreject) X509_reject_clear(x);
+
+	if (trust)
+		{
+		for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++)
+			{
+			objtmp = sk_ASN1_OBJECT_value(trust, i);
+			X509_add1_trust_object(x, objtmp);
+			}
+		}
+
+	if (reject)
+		{
+		for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++)
+			{
+			objtmp = sk_ASN1_OBJECT_value(reject, i);
+			X509_add1_reject_object(x, objtmp);
+			}
+		}
+
+	if (num)
+		{
+		for (i=1; i<=num; i++)
+			{
+			if (issuer == i)
+				{
+				print_name(STDout, "issuer= ",
+					X509_get_issuer_name(x), nmflag);
+				}
+			else if (subject == i) 
+				{
+				print_name(STDout, "subject= ",
+					X509_get_subject_name(x), nmflag);
+				}
+			else if (serial == i)
+				{
+				BIO_printf(STDout,"serial=");
+				i2a_ASN1_INTEGER(STDout,
+					X509_get_serialNumber(x));
+				BIO_printf(STDout,"\n");
+				}
+			else if (next_serial == i)
+				{
+				BIGNUM *bnser;
+				ASN1_INTEGER *ser;
+				ser = X509_get_serialNumber(x);
+				bnser = ASN1_INTEGER_to_BN(ser, NULL);
+				if (!bnser)
+					goto end;
+				if (!BN_add_word(bnser, 1))
+					goto end;
+				ser = BN_to_ASN1_INTEGER(bnser, NULL);
+				if (!ser)
+					goto end;
+				BN_free(bnser);
+				i2a_ASN1_INTEGER(out, ser);
+				ASN1_INTEGER_free(ser);
+				BIO_puts(out, "\n");
+				}
+			else if ((email == i) || (ocsp_uri == i))
+				{
+				int j;
+				STACK *emlst;
+				if (email == i)
+					emlst = X509_get1_email(x);
+				else
+					emlst = X509_get1_ocsp(x);
+				for (j = 0; j < sk_num(emlst); j++)
+					BIO_printf(STDout, "%s\n", sk_value(emlst, j));
+				X509_email_free(emlst);
+				}
+			else if (aliasout == i)
+				{
+				unsigned char *alstr;
+				alstr = X509_alias_get0(x, NULL);
+				if (alstr) BIO_printf(STDout,"%s\n", alstr);
+				else BIO_puts(STDout,"<No Alias>\n");
+				}
+			else if (subject_hash == i)
+				{
+				BIO_printf(STDout,"%08lx\n",X509_subject_name_hash(x));
+				}
+			else if (issuer_hash == i)
+				{
+				BIO_printf(STDout,"%08lx\n",X509_issuer_name_hash(x));
+				}
+			else if (pprint == i)
+				{
+				X509_PURPOSE *ptmp;
+				int j;
+				BIO_printf(STDout, "Certificate purposes:\n");
+				for (j = 0; j < X509_PURPOSE_get_count(); j++)
+					{
+					ptmp = X509_PURPOSE_get0(j);
+					purpose_print(STDout, x, ptmp);
+					}
+				}
+			else
+				if (modulus == i)
+				{
+				EVP_PKEY *pkey;
+
+				pkey=X509_get_pubkey(x);
+				if (pkey == NULL)
+					{
+					BIO_printf(bio_err,"Modulus=unavailable\n");
+					ERR_print_errors(bio_err);
+					goto end;
+					}
+				BIO_printf(STDout,"Modulus=");
+#ifndef OPENSSL_NO_RSA
+				if (pkey->type == EVP_PKEY_RSA)
+					BN_print(STDout,pkey->pkey.rsa->n);
+				else
+#endif
+#ifndef OPENSSL_NO_DSA
+				if (pkey->type == EVP_PKEY_DSA)
+					BN_print(STDout,pkey->pkey.dsa->pub_key);
+				else
+#endif
+					BIO_printf(STDout,"Wrong Algorithm type");
+				BIO_printf(STDout,"\n");
+				EVP_PKEY_free(pkey);
+				}
+			else
+				if (pubkey == i)
+				{
+				EVP_PKEY *pkey;
+
+				pkey=X509_get_pubkey(x);
+				if (pkey == NULL)
+					{
+					BIO_printf(bio_err,"Error getting public key\n");
+					ERR_print_errors(bio_err);
+					goto end;
+					}
+				PEM_write_bio_PUBKEY(STDout, pkey);
+				EVP_PKEY_free(pkey);
+				}
+			else
+				if (C == i)
+				{
+				unsigned char *d;
+				char *m;
+				int y,z;
+
+				X509_NAME_oneline(X509_get_subject_name(x),
+					buf,sizeof buf);
+				BIO_printf(STDout,"/* subject:%s */\n",buf);
+				m=X509_NAME_oneline(
+					X509_get_issuer_name(x),buf,
+					sizeof buf);
+				BIO_printf(STDout,"/* issuer :%s */\n",buf);
+
+				z=i2d_X509(x,NULL);
+				m=OPENSSL_malloc(z);
+
+				d=(unsigned char *)m;
+				z=i2d_X509_NAME(X509_get_subject_name(x),&d);
+				BIO_printf(STDout,"unsigned char XXX_subject_name[%d]={\n",z);
+				d=(unsigned char *)m;
+				for (y=0; y<z; y++)
+					{
+					BIO_printf(STDout,"0x%02X,",d[y]);
+					if ((y & 0x0f) == 0x0f) BIO_printf(STDout,"\n");
+					}
+				if (y%16 != 0) BIO_printf(STDout,"\n");
+				BIO_printf(STDout,"};\n");
+
+				z=i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x),&d);
+				BIO_printf(STDout,"unsigned char XXX_public_key[%d]={\n",z);
+				d=(unsigned char *)m;
+				for (y=0; y<z; y++)
+					{
+					BIO_printf(STDout,"0x%02X,",d[y]);
+					if ((y & 0x0f) == 0x0f)
+						BIO_printf(STDout,"\n");
+					}
+				if (y%16 != 0) BIO_printf(STDout,"\n");
+				BIO_printf(STDout,"};\n");
+
+				z=i2d_X509(x,&d);
+				BIO_printf(STDout,"unsigned char XXX_certificate[%d]={\n",z);
+				d=(unsigned char *)m;
+				for (y=0; y<z; y++)
+					{
+					BIO_printf(STDout,"0x%02X,",d[y]);
+					if ((y & 0x0f) == 0x0f)
+						BIO_printf(STDout,"\n");
+					}
+				if (y%16 != 0) BIO_printf(STDout,"\n");
+				BIO_printf(STDout,"};\n");
+
+				OPENSSL_free(m);
+				}
+			else if (text == i)
+				{
+				X509_print_ex(out,x,nmflag, certflag);
+				}
+			else if (startdate == i)
+				{
+				BIO_puts(STDout,"notBefore=");
+				ASN1_TIME_print(STDout,X509_get_notBefore(x));
+				BIO_puts(STDout,"\n");
+				}
+			else if (enddate == i)
+				{
+				BIO_puts(STDout,"notAfter=");
+				ASN1_TIME_print(STDout,X509_get_notAfter(x));
+				BIO_puts(STDout,"\n");
+				}
+			else if (fingerprint == i)
+				{
+				int j;
+				unsigned int n;
+				unsigned char md[EVP_MAX_MD_SIZE];
+
+				if (!X509_digest(x,digest,md,&n))
+					{
+					BIO_printf(bio_err,"out of memory\n");
+					goto end;
+					}
+				BIO_printf(STDout,"%s Fingerprint=",
+						OBJ_nid2sn(EVP_MD_type(digest)));
+				for (j=0; j<(int)n; j++)
+					{
+					BIO_printf(STDout,"%02X%c",md[j],
+						(j+1 == (int)n)
+						?'\n':':');
+					}
+				}
+
+			/* should be in the library */
+			else if ((sign_flag == i) && (x509req == 0))
+				{
+				BIO_printf(bio_err,"Getting Private key\n");
+				if (Upkey == NULL)
+					{
+					Upkey=load_key(bio_err,
+						keyfile, keyformat, 0,
+						passin, e, "Private key");
+					if (Upkey == NULL) goto end;
+					}
+#ifndef OPENSSL_NO_DSA
+		                if (Upkey->type == EVP_PKEY_DSA)
+		                        digest=EVP_dss1();
+#endif
+#ifndef OPENSSL_NO_ECDSA
+				if (Upkey->type == EVP_PKEY_EC)
+					digest=EVP_ecdsa();
+#endif
+
+				assert(need_rand);
+				if (!sign(x,Upkey,days,clrext,digest,
+						 extconf, extsect)) goto end;
+				}
+			else if (CA_flag == i)
+				{
+				BIO_printf(bio_err,"Getting CA Private Key\n");
+				if (CAkeyfile != NULL)
+					{
+					CApkey=load_key(bio_err,
+						CAkeyfile, CAkeyformat,
+						0, passin, e,
+						"CA Private Key");
+					if (CApkey == NULL) goto end;
+					}
+#ifndef OPENSSL_NO_DSA
+		                if (CApkey->type == EVP_PKEY_DSA)
+		                        digest=EVP_dss1();
+#endif
+#ifndef OPENSSL_NO_ECDSA
+				if (CApkey->type == EVP_PKEY_EC)
+					digest = EVP_ecdsa();
+#endif
+				
+				assert(need_rand);
+				if (!x509_certify(ctx,CAfile,digest,x,xca,
+					CApkey, CAserial,CA_createserial,days, clrext,
+					extconf, extsect, sno))
+					goto end;
+				}
+			else if (x509req == i)
+				{
+				EVP_PKEY *pk;
+
+				BIO_printf(bio_err,"Getting request Private Key\n");
+				if (keyfile == NULL)
+					{
+					BIO_printf(bio_err,"no request key file specified\n");
+					goto end;
+					}
+				else
+					{
+					pk=load_key(bio_err,
+						keyfile, FORMAT_PEM, 0,
+						passin, e, "request key");
+					if (pk == NULL) goto end;
+					}
+
+				BIO_printf(bio_err,"Generating certificate request\n");
+
+#ifndef OPENSSL_NO_DSA
+		                if (pk->type == EVP_PKEY_DSA)
+		                        digest=EVP_dss1();
+#endif
+#ifndef OPENSSL_NO_ECDSA
+				if (pk->type == EVP_PKEY_EC)
+					digest=EVP_ecdsa();
+#endif
+
+				rq=X509_to_X509_REQ(x,pk,digest);
+				EVP_PKEY_free(pk);
+				if (rq == NULL)
+					{
+					ERR_print_errors(bio_err);
+					goto end;
+					}
+				if (!noout)
+					{
+					X509_REQ_print(out,rq);
+					PEM_write_bio_X509_REQ(out,rq);
+					}
+				noout=1;
+				}
+			else if (ocspid == i)
+				{
+				X509_ocspid_print(out, x);
+				}
+			}
+		}
+
+	if (checkend)
+		{
+		time_t tcheck=time(NULL) + checkoffset;
+
+		if (X509_cmp_time(X509_get_notAfter(x), &tcheck) < 0)
+			{
+			BIO_printf(out,"Certificate will expire\n");
+			ret=1;
+			}
+		else
+			{
+			BIO_printf(out,"Certificate will not expire\n");
+			ret=0;
+			}
+		goto end;
+		}
+
+	if (noout)
+		{
+		ret=0;
+		goto end;
+		}
+
+	if 	(outformat == FORMAT_ASN1)
+		i=i2d_X509_bio(out,x);
+	else if (outformat == FORMAT_PEM)
+		{
+		if (trustout) i=PEM_write_bio_X509_AUX(out,x);
+		else i=PEM_write_bio_X509(out,x);
+		}
+	else if (outformat == FORMAT_NETSCAPE)
+		{
+		ASN1_HEADER ah;
+		ASN1_OCTET_STRING os;
+
+		os.data=(unsigned char *)NETSCAPE_CERT_HDR;
+		os.length=strlen(NETSCAPE_CERT_HDR);
+		ah.header= &os;
+		ah.data=(char *)x;
+		ah.meth=X509_asn1_meth();
+
+		i=ASN1_i2d_bio_of(ASN1_HEADER,i2d_ASN1_HEADER,out,&ah);
+		}
+	else	{
+		BIO_printf(bio_err,"bad output format specified for outfile\n");
+		goto end;
+		}
+	if (!i)
+		{
+		BIO_printf(bio_err,"unable to write certificate\n");
+		ERR_print_errors(bio_err);
+		goto end;
+		}
+	ret=0;
+end:
+	if (need_rand)
+		app_RAND_write_file(NULL, bio_err);
+	OBJ_cleanup();
+	NCONF_free(extconf);
+	BIO_free_all(out);
+	BIO_free_all(STDout);
+	X509_STORE_free(ctx);
+	X509_REQ_free(req);
+	X509_free(x);
+	X509_free(xca);
+	EVP_PKEY_free(Upkey);
+	EVP_PKEY_free(CApkey);
+	X509_REQ_free(rq);
+	ASN1_INTEGER_free(sno);
+	sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free);
+	sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free);
+	if (passin) OPENSSL_free(passin);
+	apps_shutdown();
+	OPENSSL_EXIT(ret);
+	}
+
+static ASN1_INTEGER *x509_load_serial(char *CAfile, char *serialfile, int create)
+	{
+	char *buf = NULL, *p;
+	ASN1_INTEGER *bs = NULL;
+	BIGNUM *serial = NULL;
+	size_t len;
+
+	len = ((serialfile == NULL)
+		?(strlen(CAfile)+strlen(POSTFIX)+1)
+		:(strlen(serialfile)))+1;
+	buf=OPENSSL_malloc(len);
+	if (buf == NULL) { BIO_printf(bio_err,"out of mem\n"); goto end; }
+	if (serialfile == NULL)
+		{
+		BUF_strlcpy(buf,CAfile,len);
+		for (p=buf; *p; p++)
+			if (*p == '.')
+				{
+				*p='\0';
+				break;
+				}
+		BUF_strlcat(buf,POSTFIX,len);
+		}
+	else
+		BUF_strlcpy(buf,serialfile,len);
+
+	serial = load_serial(buf, create, NULL);
+	if (serial == NULL) goto end;
+
+	if (!BN_add_word(serial,1))
+		{ BIO_printf(bio_err,"add_word failure\n"); goto end; }
+
+	if (!save_serial(buf, NULL, serial, &bs)) goto end;
+
+ end:
+	if (buf) OPENSSL_free(buf);
+	BN_free(serial);
+	return bs;
+	}
+
+static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
+	     X509 *x, X509 *xca, EVP_PKEY *pkey, char *serialfile, int create,
+	     int days, int clrext, CONF *conf, char *section, ASN1_INTEGER *sno)
+	{
+	int ret=0;
+	ASN1_INTEGER *bs=NULL;
+	X509_STORE_CTX xsc;
+	EVP_PKEY *upkey;
+
+	upkey = X509_get_pubkey(xca);
+	EVP_PKEY_copy_parameters(upkey,pkey);
+	EVP_PKEY_free(upkey);
+
+	if(!X509_STORE_CTX_init(&xsc,ctx,x,NULL))
+		{
+		BIO_printf(bio_err,"Error initialising X509 store\n");
+		goto end;
+		}
+	if (sno) bs = sno;
+	else if (!(bs = x509_load_serial(CAfile, serialfile, create)))
+		goto end;
+
+/*	if (!X509_STORE_add_cert(ctx,x)) goto end;*/
+
+	/* NOTE: this certificate can/should be self signed, unless it was
+	 * a certificate request in which case it is not. */
+	X509_STORE_CTX_set_cert(&xsc,x);
+	if (!reqfile && X509_verify_cert(&xsc) <= 0)
+		goto end;
+
+	if (!X509_check_private_key(xca,pkey))
+		{
+		BIO_printf(bio_err,"CA certificate and CA private key do not match\n");
+		goto end;
+		}
+
+	if (!X509_set_issuer_name(x,X509_get_subject_name(xca))) goto end;
+	if (!X509_set_serialNumber(x,bs)) goto end;
+
+	if (X509_gmtime_adj(X509_get_notBefore(x),0L) == NULL)
+		goto end;
+
+	/* hardwired expired */
+	if (X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days) == NULL)
+		goto end;
+
+	if (clrext)
+		{
+		while (X509_get_ext_count(x) > 0) X509_delete_ext(x, 0);
+		}
+
+	if (conf)
+		{
+		X509V3_CTX ctx2;
+		X509_set_version(x,2); /* version 3 certificate */
+                X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0);
+                X509V3_set_nconf(&ctx2, conf);
+                if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x)) goto end;
+		}
+
+	if (!X509_sign(x,pkey,digest)) goto end;
+	ret=1;
+end:
+	X509_STORE_CTX_cleanup(&xsc);
+	if (!ret)
+		ERR_print_errors(bio_err);
+	if (!sno) ASN1_INTEGER_free(bs);
+	return ret;
+	}
+
+static int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx)
+	{
+	int err;
+	X509 *err_cert;
+
+	/* it is ok to use a self signed certificate
+	 * This case will catch both the initial ok == 0 and the
+	 * final ok == 1 calls to this function */
+	err=X509_STORE_CTX_get_error(ctx);
+	if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)
+		return 1;
+
+	/* BAD we should have gotten an error.  Normally if everything
+	 * worked X509_STORE_CTX_get_error(ctx) will still be set to
+	 * DEPTH_ZERO_SELF_.... */
+	if (ok)
+		{
+		BIO_printf(bio_err,"error with certificate to be certified - should be self signed\n");
+		return 0;
+		}
+	else
+		{
+		err_cert=X509_STORE_CTX_get_current_cert(ctx);
+		print_name(bio_err, NULL, X509_get_subject_name(err_cert),0);
+		BIO_printf(bio_err,"error with certificate - error %d at depth %d\n%s\n",
+			err,X509_STORE_CTX_get_error_depth(ctx),
+			X509_verify_cert_error_string(err));
+		return 1;
+		}
+	}
+
+/* self sign */
+static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, const EVP_MD *digest, 
+						CONF *conf, char *section)
+	{
+
+	EVP_PKEY *pktmp;
+
+	pktmp = X509_get_pubkey(x);
+	EVP_PKEY_copy_parameters(pktmp,pkey);
+	EVP_PKEY_save_parameters(pktmp,1);
+	EVP_PKEY_free(pktmp);
+
+	if (!X509_set_issuer_name(x,X509_get_subject_name(x))) goto err;
+	if (X509_gmtime_adj(X509_get_notBefore(x),0) == NULL) goto err;
+
+	/* Lets just make it 12:00am GMT, Jan 1 1970 */
+	/* memcpy(x->cert_info->validity->notBefore,"700101120000Z",13); */
+	/* 28 days to be certified */
+
+	if (X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days) == NULL)
+		goto err;
+
+	if (!X509_set_pubkey(x,pkey)) goto err;
+	if (clrext)
+		{
+		while (X509_get_ext_count(x) > 0) X509_delete_ext(x, 0);
+		}
+	if (conf)
+		{
+		X509V3_CTX ctx;
+		X509_set_version(x,2); /* version 3 certificate */
+                X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0);
+                X509V3_set_nconf(&ctx, conf);
+                if (!X509V3_EXT_add_nconf(conf, &ctx, section, x)) goto err;
+		}
+	if (!X509_sign(x,pkey,digest)) goto err;
+	return 1;
+err:
+	ERR_print_errors(bio_err);
+	return 0;
+	}
+
+static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt)
+{
+	int id, i, idret;
+	char *pname;
+	id = X509_PURPOSE_get_id(pt);
+	pname = X509_PURPOSE_get0_name(pt);
+	for (i = 0; i < 2; i++)
+		{
+		idret = X509_check_purpose(cert, id, i);
+		BIO_printf(bio, "%s%s : ", pname, i ? " CA" : ""); 
+		if (idret == 1) BIO_printf(bio, "Yes\n");
+		else if (idret == 0) BIO_printf(bio, "No\n");
+		else BIO_printf(bio, "Yes (WARNING code=%d)\n", idret);
+		}
+	return 1;
+}

Modified: openssl/branches/upstream/current/config
===================================================================
--- openssl/branches/upstream/current/config	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/config	2009-05-16 15:25:35 UTC (rev 372)
@@ -29,7 +29,7 @@
 for i
 do
 case "$i" in 
--d*) PREFIX="debug-";;
+-d) PREFIX="debug-";;
 -t*) TEST="true";;
 -h*) TEST="true"; cat <<EOF
 Usage: config [options]
@@ -399,11 +399,8 @@
 # this is where the translation occurs into SSLeay terms
 # ---------------------------------------------------------------------------
 
-# figure out if gcc is available and if so we use it otherwise
-# we fallback to whatever cc does on the system
 GCCVER=`(gcc -dumpversion) 2>/dev/null`
 if [ "$GCCVER" != "" ]; then
-  CC=gcc
   # then strip off whatever prefix egcs prepends the number with...
   # Hopefully, this will work for any future prefixes as well.
   GCCVER=`echo $GCCVER | LC_ALL=C sed 's/^[a-zA-Z]*\-//'`
@@ -412,9 +409,18 @@
   # major and minor version numbers.
   # peak single digit before and after first dot, e.g. 2.95.1 gives 29
   GCCVER=`echo $GCCVER | sed 's/\([0-9]\)\.\([0-9]\).*/\1\2/'`
-else
-  CC=cc
 fi
+
+# Only set CC if not supplied already
+if [ -z "$CC" ]; then
+# figure out if gcc is available and if so we use it otherwise
+# we fallback to whatever cc does on the system
+  if [ "$GCCVER" != "" ]; then
+    CC=gcc
+  else
+    CC=cc
+  fi
+fi
 GCCVER=${GCCVER:-0}
 if [ "$SYSTEM" = "HP-UX" ];then
   # By default gcc is a ILP32 compiler (with long long == 64).

Modified: openssl/branches/upstream/current/crypto/Makefile
===================================================================
--- openssl/branches/upstream/current/crypto/Makefile	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/crypto/Makefile	2009-05-16 15:25:35 UTC (rev 372)
@@ -33,8 +33,8 @@
 
 LIB= $(TOP)/libcrypto.a
 SHARED_LIB= libcrypto$(SHLIB_EXT)
-LIBSRC=	cryptlib.c mem.c mem_clr.c mem_dbg.c cversion.c ex_data.c tmdiff.c cpt_err.c ebcdic.c uid.c o_time.c o_str.c o_dir.c
-LIBOBJ= cryptlib.o mem.o mem_clr.o mem_dbg.o cversion.o ex_data.o tmdiff.o cpt_err.o ebcdic.o uid.o o_time.o o_str.o o_dir.o $(CPUID_OBJ)
+LIBSRC=	cryptlib.c dyn_lck.c mem.c mem_clr.c mem_dbg.c cversion.c ex_data.c tmdiff.c cpt_err.c ebcdic.c uid.c o_time.c o_str.c o_dir.c o_init.c fips_err.c
+LIBOBJ= cryptlib.o dyn_lck.o mem.o mem_clr.o mem_dbg.o cversion.o ex_data.o tmdiff.o cpt_err.o ebcdic.o uid.o o_time.o o_str.o o_dir.o o_init.o fips_err.o $(CPUID_OBJ)
 
 SRC= $(LIBSRC)
 
@@ -47,7 +47,7 @@
 top:
 	@(cd ..; $(MAKE) DIRS=$(DIR) all)
 
-all: shared
+all: lib
 
 buildinf.h: ../Makefile
 	( echo "#ifndef MK1MF_BUILD"; \
@@ -95,10 +95,10 @@
 	@target=links; $(RECURSIVE_MAKE)
 
 # lib: and $(LIB): are splitted to avoid end-less loop
-lib:	$(LIB)
+lib:	buildinf.h $(LIB) subdirs
 	@touch lib
 $(LIB):	$(LIBOBJ)
-	$(AR) $(LIB) $(LIBOBJ)
+	$(ARX) $(LIB) $(LIBOBJ)
 	$(RANLIB) $(LIB) || echo Never mind.
 
 shared: buildinf.h lib subdirs
@@ -159,6 +159,13 @@
 cversion.o: ../include/openssl/ossl_typ.h ../include/openssl/safestack.h
 cversion.o: ../include/openssl/stack.h ../include/openssl/symhacks.h buildinf.h
 cversion.o: cryptlib.h cversion.c
+dyn_lck.o: ../e_os.h ../include/openssl/bio.h ../include/openssl/buffer.h
+dyn_lck.o: ../include/openssl/crypto.h ../include/openssl/e_os2.h
+dyn_lck.o: ../include/openssl/err.h ../include/openssl/lhash.h
+dyn_lck.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+dyn_lck.o: ../include/openssl/ossl_typ.h ../include/openssl/safestack.h
+dyn_lck.o: ../include/openssl/stack.h ../include/openssl/symhacks.h cryptlib.h
+dyn_lck.o: dyn_lck.c
 ebcdic.o: ../include/openssl/e_os2.h ../include/openssl/opensslconf.h ebcdic.c
 ex_data.o: ../e_os.h ../include/openssl/bio.h ../include/openssl/buffer.h
 ex_data.o: ../include/openssl/crypto.h ../include/openssl/e_os2.h
@@ -167,6 +174,13 @@
 ex_data.o: ../include/openssl/ossl_typ.h ../include/openssl/safestack.h
 ex_data.o: ../include/openssl/stack.h ../include/openssl/symhacks.h cryptlib.h
 ex_data.o: ex_data.c
+fips_err.o: ../include/openssl/bio.h ../include/openssl/crypto.h
+fips_err.o: ../include/openssl/e_os2.h ../include/openssl/err.h
+fips_err.o: ../include/openssl/fips.h ../include/openssl/lhash.h
+fips_err.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+fips_err.o: ../include/openssl/ossl_typ.h ../include/openssl/safestack.h
+fips_err.o: ../include/openssl/stack.h ../include/openssl/symhacks.h fips_err.c
+fips_err.o: fips_err.h
 mem.o: ../e_os.h ../include/openssl/bio.h ../include/openssl/buffer.h
 mem.o: ../include/openssl/crypto.h ../include/openssl/e_os2.h
 mem.o: ../include/openssl/err.h ../include/openssl/lhash.h
@@ -187,6 +201,12 @@
 mem_dbg.o: mem_dbg.c
 o_dir.o: ../e_os.h ../include/openssl/e_os2.h ../include/openssl/opensslconf.h
 o_dir.o: LPdir_unix.c o_dir.c o_dir.h
+o_init.o: ../e_os.h ../include/openssl/bio.h ../include/openssl/crypto.h
+o_init.o: ../include/openssl/e_os2.h ../include/openssl/err.h
+o_init.o: ../include/openssl/lhash.h ../include/openssl/opensslconf.h
+o_init.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
+o_init.o: ../include/openssl/safestack.h ../include/openssl/stack.h
+o_init.o: ../include/openssl/symhacks.h o_init.c
 o_str.o: ../e_os.h ../include/openssl/e_os2.h ../include/openssl/opensslconf.h
 o_str.o: o_str.c o_str.h
 o_time.o: ../include/openssl/e_os2.h ../include/openssl/opensslconf.h o_time.c

Added: openssl/branches/upstream/current/crypto/aes/asm/aes-586.pl
===================================================================
--- openssl/branches/upstream/current/crypto/aes/asm/aes-586.pl	                        (rev 0)
+++ openssl/branches/upstream/current/crypto/aes/asm/aes-586.pl	2009-05-16 15:25:35 UTC (rev 372)
@@ -0,0 +1,1533 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro at fy.chalmers.se> for the OpenSSL
+# project. Rights for redistribution and usage in source and binary
+# forms are granted according to the OpenSSL license.
+# ====================================================================
+#
+# Version 3.6.
+#
+# You might fail to appreciate this module performance from the first
+# try. If compared to "vanilla" linux-ia32-icc target, i.e. considered
+# to be *the* best Intel C compiler without -KPIC, performance appears
+# to be virtually identical... But try to re-configure with shared
+# library support... Aha! Intel compiler "suddenly" lags behind by 30%
+# [on P4, more on others]:-) And if compared to position-independent
+# code generated by GNU C, this code performs *more* than *twice* as
+# fast! Yes, all this buzz about PIC means that unlike other hand-
+# coded implementations, this one was explicitly designed to be safe
+# to use even in shared library context... This also means that this
+# code isn't necessarily absolutely fastest "ever," because in order
+# to achieve position independence an extra register has to be
+# off-loaded to stack, which affects the benchmark result.
+#
+# Special note about instruction choice. Do you recall RC4_INT code
+# performing poorly on P4? It might be the time to figure out why.
+# RC4_INT code implies effective address calculations in base+offset*4
+# form. Trouble is that it seems that offset scaling turned to be
+# critical path... At least eliminating scaling resulted in 2.8x RC4
+# performance improvement [as you might recall]. As AES code is hungry
+# for scaling too, I [try to] avoid the latter by favoring off-by-2
+# shifts and masking the result with 0xFF<<2 instead of "boring" 0xFF.
+#
+# As was shown by Dean Gaudet <dean at arctic.org>, the above note turned
+# void. Performance improvement with off-by-2 shifts was observed on
+# intermediate implementation, which was spilling yet another register
+# to stack... Final offset*4 code below runs just a tad faster on P4,
+# but exhibits up to 10% improvement on other cores.
+#
+# Second version is "monolithic" replacement for aes_core.c, which in
+# addition to AES_[de|en]crypt implements AES_set_[de|en]cryption_key.
+# This made it possible to implement little-endian variant of the
+# algorithm without modifying the base C code. Motivating factor for
+# the undertaken effort was that it appeared that in tight IA-32
+# register window little-endian flavor could achieve slightly higher
+# Instruction Level Parallelism, and it indeed resulted in up to 15%
+# better performance on most recent µ-archs...
+#
+# Third version adds AES_cbc_encrypt implementation, which resulted in
+# up to 40% performance imrovement of CBC benchmark results. 40% was
+# observed on P4 core, where "overall" imrovement coefficient, i.e. if
+# compared to PIC generated by GCC and in CBC mode, was observed to be
+# as large as 4x:-) CBC performance is virtually identical to ECB now
+# and on some platforms even better, e.g. 17.6 "small" cycles/byte on
+# Opteron, because certain function prologues and epilogues are
+# effectively taken out of the loop...
+#
+# Version 3.2 implements compressed tables and prefetch of these tables
+# in CBC[!] mode. Former means that 3/4 of table references are now
+# misaligned, which unfortunately has negative impact on elder IA-32
+# implementations, Pentium suffered 30% penalty, PIII - 10%.
+#
+# Version 3.3 avoids L1 cache aliasing between stack frame and
+# S-boxes, and 3.4 - L1 cache aliasing even between key schedule. The
+# latter is achieved by copying the key schedule to controlled place in
+# stack. This unfortunately has rather strong impact on small block CBC
+# performance, ~2x deterioration on 16-byte block if compared to 3.3.
+#
+# Version 3.5 checks if there is L1 cache aliasing between user-supplied
+# key schedule and S-boxes and abstains from copying the former if
+# there is no. This allows end-user to consciously retain small block
+# performance by aligning key schedule in specific manner.
+#
+# Version 3.6 compresses Td4 to 256 bytes and prefetches it in ECB.
+#
+# Current ECB performance numbers for 128-bit key in CPU cycles per
+# processed byte [measure commonly used by AES benchmarkers] are:
+#
+#		small footprint		fully unrolled
+# P4		24			22
+# AMD K8	20			19
+# PIII		25			23
+# Pentium	81			78
+
+push(@INC,"perlasm","../../perlasm");
+require "x86asm.pl";
+
+&asm_init($ARGV[0],"aes-586.pl",$ARGV[$#ARGV] eq "386");
+
+$s0="eax";
+$s1="ebx";
+$s2="ecx";
+$s3="edx";
+$key="edi";
+$acc="esi";
+
+$compromise=0;		# $compromise=128 abstains from copying key
+			# schedule to stack when encrypting inputs
+			# shorter than 128 bytes at the cost of
+			# risksing aliasing with S-boxes. In return
+			# you get way better, up to +70%, small block
+			# performance.
+$small_footprint=1;	# $small_footprint=1 code is ~5% slower [on
+			# recent µ-archs], but ~5 times smaller!
+			# I favor compact code to minimize cache
+			# contention and in hope to "collect" 5% back
+			# in real-life applications...
+$vertical_spin=0;	# shift "verticaly" defaults to 0, because of
+			# its proof-of-concept status...
+
+# Note that there is no decvert(), as well as last encryption round is
+# performed with "horizontal" shifts. This is because this "vertical"
+# implementation [one which groups shifts on a given $s[i] to form a
+# "column," unlike "horizontal" one, which groups shifts on different
+# $s[i] to form a "row"] is work in progress. It was observed to run
+# few percents faster on Intel cores, but not AMD. On AMD K8 core it's
+# whole 12% slower:-( So we face a trade-off... Shall it be resolved
+# some day? Till then the code is considered experimental and by
+# default remains dormant...
+
+sub encvert()
+{ my ($te, at s) = @_;
+  my $v0 = $acc, $v1 = $key;
+
+	&mov	($v0,$s[3]);				# copy s3
+	&mov	(&DWP(4,"esp"),$s[2]);			# save s2
+	&mov	($v1,$s[0]);				# copy s0
+	&mov	(&DWP(8,"esp"),$s[1]);			# save s1
+
+	&movz	($s[2],&HB($s[0]));
+	&and	($s[0],0xFF);
+	&mov	($s[0],&DWP(0,$te,$s[0],8));		# s0>>0
+	&shr	($v1,16);
+	&mov	($s[3],&DWP(3,$te,$s[2],8));		# s0>>8
+	&movz	($s[1],&HB($v1));
+	&and	($v1,0xFF);
+	&mov	($s[2],&DWP(2,$te,$v1,8));		# s0>>16
+	 &mov	($v1,$v0);
+	&mov	($s[1],&DWP(1,$te,$s[1],8));		# s0>>24
+
+	&and	($v0,0xFF);
+	&xor	($s[3],&DWP(0,$te,$v0,8));		# s3>>0
+	&movz	($v0,&HB($v1));
+	&shr	($v1,16);
+	&xor	($s[2],&DWP(3,$te,$v0,8));		# s3>>8
+	&movz	($v0,&HB($v1));
+	&and	($v1,0xFF);
+	&xor	($s[1],&DWP(2,$te,$v1,8));		# s3>>16
+	 &mov	($v1,&DWP(4,"esp"));			# restore s2
+	&xor	($s[0],&DWP(1,$te,$v0,8));		# s3>>24
+
+	&mov	($v0,$v1);
+	&and	($v1,0xFF);
+	&xor	($s[2],&DWP(0,$te,$v1,8));		# s2>>0
+	&movz	($v1,&HB($v0));
+	&shr	($v0,16);
+	&xor	($s[1],&DWP(3,$te,$v1,8));		# s2>>8
+	&movz	($v1,&HB($v0));
+	&and	($v0,0xFF);
+	&xor	($s[0],&DWP(2,$te,$v0,8));		# s2>>16
+	 &mov	($v0,&DWP(8,"esp"));			# restore s1
+	&xor	($s[3],&DWP(1,$te,$v1,8));		# s2>>24
+
+	&mov	($v1,$v0);
+	&and	($v0,0xFF);
+	&xor	($s[1],&DWP(0,$te,$v0,8));		# s1>>0
+	&movz	($v0,&HB($v1));
+	&shr	($v1,16);
+	&xor	($s[0],&DWP(3,$te,$v0,8));		# s1>>8
+	&movz	($v0,&HB($v1));
+	&and	($v1,0xFF);
+	&xor	($s[3],&DWP(2,$te,$v1,8));		# s1>>16
+	 &mov	($key,&DWP(12,"esp"));			# reincarnate v1 as key
+	&xor	($s[2],&DWP(1,$te,$v0,8));		# s1>>24
+}
+
+sub encstep()
+{ my ($i,$te, at s) = @_;
+  my $tmp = $key;
+  my $out = $i==3?$s[0]:$acc;
+
+	# lines marked with #%e?x[i] denote "reordered" instructions...
+	if ($i==3)  {	&mov	($key,&DWP(12,"esp"));		}##%edx
+	else        {	&mov	($out,$s[0]);
+			&and	($out,0xFF);			}
+	if ($i==1)  {	&shr	($s[0],16);			}#%ebx[1]
+	if ($i==2)  {	&shr	($s[0],24);			}#%ecx[2]
+			&mov	($out,&DWP(0,$te,$out,8));
+
+	if ($i==3)  {	$tmp=$s[1];				}##%eax
+			&movz	($tmp,&HB($s[1]));
+			&xor	($out,&DWP(3,$te,$tmp,8));
+
+	if ($i==3)  {	$tmp=$s[2]; &mov ($s[1],&DWP(4,"esp"));	}##%ebx
+	else        {	&mov	($tmp,$s[2]);
+			&shr	($tmp,16);			}
+	if ($i==2)  {	&and	($s[1],0xFF);			}#%edx[2]
+			&and	($tmp,0xFF);
+			&xor	($out,&DWP(2,$te,$tmp,8));
+
+	if ($i==3)  {	$tmp=$s[3]; &mov ($s[2],&DWP(8,"esp"));	}##%ecx
+	elsif($i==2){	&movz	($tmp,&HB($s[3]));		}#%ebx[2]
+	else        {	&mov	($tmp,$s[3]); 
+			&shr	($tmp,24)			}
+			&xor	($out,&DWP(1,$te,$tmp,8));
+	if ($i<2)   {	&mov	(&DWP(4+4*$i,"esp"),$out);	}
+	if ($i==3)  {	&mov	($s[3],$acc);			}
+			&comment();
+}
+
+sub enclast()
+{ my ($i,$te, at s)=@_;
+  my $tmp = $key;
+  my $out = $i==3?$s[0]:$acc;
+
+	if ($i==3)  {	&mov	($key,&DWP(12,"esp"));		}##%edx
+	else        {	&mov	($out,$s[0]);			}
+			&and	($out,0xFF);
+	if ($i==1)  {	&shr	($s[0],16);			}#%ebx[1]
+	if ($i==2)  {	&shr	($s[0],24);			}#%ecx[2]
+			&mov	($out,&DWP(2,$te,$out,8));
+			&and	($out,0x000000ff);
+
+	if ($i==3)  {	$tmp=$s[1];				}##%eax
+			&movz	($tmp,&HB($s[1]));
+			&mov	($tmp,&DWP(0,$te,$tmp,8));
+			&and	($tmp,0x0000ff00);
+			&xor	($out,$tmp);
+
+	if ($i==3)  {	$tmp=$s[2]; &mov ($s[1],&DWP(4,"esp"));	}##%ebx
+	else        {	mov	($tmp,$s[2]);
+			&shr	($tmp,16);			}
+	if ($i==2)  {	&and	($s[1],0xFF);			}#%edx[2]
+			&and	($tmp,0xFF);
+			&mov	($tmp,&DWP(0,$te,$tmp,8));
+			&and	($tmp,0x00ff0000);
+			&xor	($out,$tmp);
+
+	if ($i==3)  {	$tmp=$s[3]; &mov ($s[2],&DWP(8,"esp"));	}##%ecx
+	elsif($i==2){	&movz	($tmp,&HB($s[3]));		}#%ebx[2]
+	else        {	&mov	($tmp,$s[3]);
+			&shr	($tmp,24);			}
+			&mov	($tmp,&DWP(2,$te,$tmp,8));
+			&and	($tmp,0xff000000);
+			&xor	($out,$tmp);
+	if ($i<2)   {	&mov	(&DWP(4+4*$i,"esp"),$out);	}
+	if ($i==3)  {	&mov	($s[3],$acc);			}
+}
+
+sub _data_word() { my $i; while(defined($i=shift)) { &data_word($i,$i); } }
+
+&public_label("AES_Te");
+&function_begin_B("_x86_AES_encrypt");
+	if ($vertical_spin) {
+		# I need high parts of volatile registers to be accessible...
+		&exch	($s1="edi",$key="ebx");
+		&mov	($s2="esi",$acc="ecx");
+	}
+
+	# note that caller is expected to allocate stack frame for me!
+	&mov	(&DWP(12,"esp"),$key);		# save key
+
+	&xor	($s0,&DWP(0,$key));		# xor with key
+	&xor	($s1,&DWP(4,$key));
+	&xor	($s2,&DWP(8,$key));
+	&xor	($s3,&DWP(12,$key));
+
+	&mov	($acc,&DWP(240,$key));		# load key->rounds
+
+	if ($small_footprint) {
+	    &lea	($acc,&DWP(-2,$acc,$acc));
+	    &lea	($acc,&DWP(0,$key,$acc,8));
+	    &mov	(&DWP(16,"esp"),$acc);	# end of key schedule
+	    &align	(4);
+	    &set_label("loop");
+		if ($vertical_spin) {
+		    &encvert("ebp",$s0,$s1,$s2,$s3);
+		} else {
+		    &encstep(0,"ebp",$s0,$s1,$s2,$s3);
+		    &encstep(1,"ebp",$s1,$s2,$s3,$s0);
+		    &encstep(2,"ebp",$s2,$s3,$s0,$s1);
+		    &encstep(3,"ebp",$s3,$s0,$s1,$s2);
+		}
+		&add	($key,16);		# advance rd_key
+		&xor	($s0,&DWP(0,$key));
+		&xor	($s1,&DWP(4,$key));
+		&xor	($s2,&DWP(8,$key));
+		&xor	($s3,&DWP(12,$key));
+	    &cmp	($key,&DWP(16,"esp"));
+	    &mov	(&DWP(12,"esp"),$key);
+	    &jb		(&label("loop"));
+	}
+	else {
+	    &cmp	($acc,10);
+	    &jle	(&label("10rounds"));
+	    &cmp	($acc,12);
+	    &jle	(&label("12rounds"));
+
+	&set_label("14rounds");
+	    for ($i=1;$i<3;$i++) {
+		if ($vertical_spin) {
+		    &encvert("ebp",$s0,$s1,$s2,$s3);
+		} else {
+		    &encstep(0,"ebp",$s0,$s1,$s2,$s3);
+		    &encstep(1,"ebp",$s1,$s2,$s3,$s0);
+		    &encstep(2,"ebp",$s2,$s3,$s0,$s1);
+		    &encstep(3,"ebp",$s3,$s0,$s1,$s2);
+		}
+		&xor	($s0,&DWP(16*$i+0,$key));
+		&xor	($s1,&DWP(16*$i+4,$key));
+		&xor	($s2,&DWP(16*$i+8,$key));
+		&xor	($s3,&DWP(16*$i+12,$key));
+	    }
+	    &add	($key,32);
+	    &mov	(&DWP(12,"esp"),$key);	# advance rd_key
+	&set_label("12rounds");
+	    for ($i=1;$i<3;$i++) {
+		if ($vertical_spin) {
+		    &encvert("ebp",$s0,$s1,$s2,$s3);
+		} else {
+		    &encstep(0,"ebp",$s0,$s1,$s2,$s3);
+		    &encstep(1,"ebp",$s1,$s2,$s3,$s0);
+		    &encstep(2,"ebp",$s2,$s3,$s0,$s1);
+		    &encstep(3,"ebp",$s3,$s0,$s1,$s2);
+		}
+		&xor	($s0,&DWP(16*$i+0,$key));
+		&xor	($s1,&DWP(16*$i+4,$key));
+		&xor	($s2,&DWP(16*$i+8,$key));
+		&xor	($s3,&DWP(16*$i+12,$key));
+	    }
+	    &add	($key,32);
+	    &mov	(&DWP(12,"esp"),$key);	# advance rd_key
+	&set_label("10rounds");
+	    for ($i=1;$i<10;$i++) {
+		if ($vertical_spin) {
+		    &encvert("ebp",$s0,$s1,$s2,$s3);
+		} else {
+		    &encstep(0,"ebp",$s0,$s1,$s2,$s3);
+		    &encstep(1,"ebp",$s1,$s2,$s3,$s0);
+		    &encstep(2,"ebp",$s2,$s3,$s0,$s1);
+		    &encstep(3,"ebp",$s3,$s0,$s1,$s2);
+		}
+		&xor	($s0,&DWP(16*$i+0,$key));
+		&xor	($s1,&DWP(16*$i+4,$key));
+		&xor	($s2,&DWP(16*$i+8,$key));
+		&xor	($s3,&DWP(16*$i+12,$key));
+	    }
+	}
+
+	if ($vertical_spin) {
+	    # "reincarnate" some registers for "horizontal" spin...
+	    &mov	($s1="ebx",$key="edi");
+	    &mov	($s2="ecx",$acc="esi");
+	}
+	&enclast(0,"ebp",$s0,$s1,$s2,$s3);
+	&enclast(1,"ebp",$s1,$s2,$s3,$s0);
+	&enclast(2,"ebp",$s2,$s3,$s0,$s1);
+	&enclast(3,"ebp",$s3,$s0,$s1,$s2);
+
+	&add	($key,$small_footprint?16:160);
+	&xor	($s0,&DWP(0,$key));
+	&xor	($s1,&DWP(4,$key));
+	&xor	($s2,&DWP(8,$key));
+	&xor	($s3,&DWP(12,$key));
+
+	&ret	();
+
+&set_label("AES_Te",64);	# Yes! I keep it in the code segment!
+	&_data_word(0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6);
+	&_data_word(0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591);
+	&_data_word(0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56);
+	&_data_word(0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec);
+	&_data_word(0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa);
+	&_data_word(0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb);
+	&_data_word(0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45);
+	&_data_word(0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b);
+	&_data_word(0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c);
+	&_data_word(0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83);
+	&_data_word(0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9);
+	&_data_word(0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a);
+	&_data_word(0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d);
+	&_data_word(0x28181830, 0xa1969637, 0x0f05050a, 0xb59a9a2f);
+	&_data_word(0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df);
+	&_data_word(0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea);
+	&_data_word(0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34);
+	&_data_word(0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b);
+	&_data_word(0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d);
+	&_data_word(0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413);
+	&_data_word(0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1);
+	&_data_word(0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6);
+	&_data_word(0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972);
+	&_data_word(0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85);
+	&_data_word(0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed);
+	&_data_word(0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511);
+	&_data_word(0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe);
+	&_data_word(0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b);
+	&_data_word(0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05);
+	&_data_word(0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1);
+	&_data_word(0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142);
+	&_data_word(0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf);
+	&_data_word(0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3);
+	&_data_word(0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e);
+	&_data_word(0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a);
+	&_data_word(0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6);
+	&_data_word(0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3);
+	&_data_word(0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b);
+	&_data_word(0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428);
+	&_data_word(0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad);
+	&_data_word(0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14);
+	&_data_word(0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8);
+	&_data_word(0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4);
+	&_data_word(0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2);
+	&_data_word(0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda);
+	&_data_word(0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949);
+	&_data_word(0xb46c6cd8, 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf);
+	&_data_word(0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810);
+	&_data_word(0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c);
+	&_data_word(0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697);
+	&_data_word(0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e);
+	&_data_word(0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f);
+	&_data_word(0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc);
+	&_data_word(0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c);
+	&_data_word(0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969);
+	&_data_word(0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27);
+	&_data_word(0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122);
+	&_data_word(0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433);
+	&_data_word(0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9);
+	&_data_word(0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5);
+	&_data_word(0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a);
+	&_data_word(0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0);
+	&_data_word(0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e);
+	&_data_word(0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c);
+#rcon:
+	&data_word(0x00000001, 0x00000002, 0x00000004, 0x00000008);
+	&data_word(0x00000010, 0x00000020, 0x00000040, 0x00000080);
+	&data_word(0x0000001b, 0x00000036, 0, 0, 0, 0, 0, 0);
+&function_end_B("_x86_AES_encrypt");
+
+# void AES_encrypt (const void *inp,void *out,const AES_KEY *key);
+&public_label("AES_Te");
+&function_begin("AES_encrypt");
+	&mov	($acc,&wparam(0));		# load inp
+	&mov	($key,&wparam(2));		# load key
+
+	&mov	($s0,"esp");
+	&sub	("esp",24);
+	&and	("esp",-64);
+	&add	("esp",4);
+	&mov	(&DWP(16,"esp"),$s0);
+
+	&call   (&label("pic_point"));          # make it PIC!
+	&set_label("pic_point");
+	&blindpop("ebp");
+	&lea    ("ebp",&DWP(&label("AES_Te")."-".&label("pic_point"),"ebp"));
+
+	&mov	($s0,&DWP(0,$acc));		# load input data
+	&mov	($s1,&DWP(4,$acc));
+	&mov	($s2,&DWP(8,$acc));
+	&mov	($s3,&DWP(12,$acc));
+
+	&call	("_x86_AES_encrypt");
+
+	&mov	("esp",&DWP(16,"esp"));
+
+	&mov	($acc,&wparam(1));		# load out
+	&mov	(&DWP(0,$acc),$s0);		# write output data
+	&mov	(&DWP(4,$acc),$s1);
+	&mov	(&DWP(8,$acc),$s2);
+	&mov	(&DWP(12,$acc),$s3);
+&function_end("AES_encrypt");
+
+#------------------------------------------------------------------#
+
+sub decstep()
+{ my ($i,$td, at s) = @_;
+  my $tmp = $key;
+  my $out = $i==3?$s[0]:$acc;
+
+	# no instructions are reordered, as performance appears
+	# optimal... or rather that all attempts to reorder didn't
+	# result in better performance [which by the way is not a
+	# bit lower than ecryption].
+	if($i==3)   {	&mov	($key,&DWP(12,"esp"));		}
+	else        {	&mov	($out,$s[0]);			}
+			&and	($out,0xFF);
+			&mov	($out,&DWP(0,$td,$out,8));
+
+	if ($i==3)  {	$tmp=$s[1];				}
+			&movz	($tmp,&HB($s[1]));
+			&xor	($out,&DWP(3,$td,$tmp,8));
+
+	if ($i==3)  {	$tmp=$s[2]; &mov ($s[1],$acc);		}
+	else        {	&mov	($tmp,$s[2]);			}
+			&shr	($tmp,16);
+			&and	($tmp,0xFF);
+			&xor	($out,&DWP(2,$td,$tmp,8));
+
+	if ($i==3)  {	$tmp=$s[3]; &mov ($s[2],&DWP(8,"esp"));	}
+	else        {	&mov	($tmp,$s[3]);			}
+			&shr	($tmp,24);
+			&xor	($out,&DWP(1,$td,$tmp,8));
+	if ($i<2)   {	&mov	(&DWP(4+4*$i,"esp"),$out);	}
+	if ($i==3)  {	&mov	($s[3],&DWP(4,"esp"));		}
+			&comment();
+}
+
+sub declast()
+{ my ($i,$td, at s)=@_;
+  my $tmp = $key;
+  my $out = $i==3?$s[0]:$acc;
+
+	if($i==3)   {	&mov	($key,&DWP(12,"esp"));		}
+	else        {	&mov	($out,$s[0]);			}
+			&and	($out,0xFF);
+			&movz	($out,&BP(2048,$td,$out,1));
+
+	if ($i==3)  {	$tmp=$s[1];				}
+			&movz	($tmp,&HB($s[1]));
+			&movz	($tmp,&BP(2048,$td,$tmp,1));
+			&shl	($tmp,8);
+			&xor	($out,$tmp);
+
+	if ($i==3)  {	$tmp=$s[2]; &mov ($s[1],$acc);		}
+	else        {	mov	($tmp,$s[2]);			}
+			&shr	($tmp,16);
+			&and	($tmp,0xFF);
+			&movz	($tmp,&BP(2048,$td,$tmp,1));
+			&shl	($tmp,16);
+			&xor	($out,$tmp);
+
+	if ($i==3)  {	$tmp=$s[3]; &mov ($s[2],&DWP(8,"esp"));	}
+	else        {	&mov	($tmp,$s[3]);			}
+			&shr	($tmp,24);
+			&movz	($tmp,&BP(2048,$td,$tmp,1));
+			&shl	($tmp,24);
+			&xor	($out,$tmp);
+	if ($i<2)   {	&mov	(&DWP(4+4*$i,"esp"),$out);	}
+	if ($i==3)  {	&mov	($s[3],&DWP(4,"esp"));		}
+}
+
+&public_label("AES_Td");
+&function_begin_B("_x86_AES_decrypt");
+	# note that caller is expected to allocate stack frame for me!
+	&mov	(&DWP(12,"esp"),$key);		# save key
+
+	&xor	($s0,&DWP(0,$key));		# xor with key
+	&xor	($s1,&DWP(4,$key));
+	&xor	($s2,&DWP(8,$key));
+	&xor	($s3,&DWP(12,$key));
+
+	&mov	($acc,&DWP(240,$key));		# load key->rounds
+
+	if ($small_footprint) {
+	    &lea	($acc,&DWP(-2,$acc,$acc));
+	    &lea	($acc,&DWP(0,$key,$acc,8));
+	    &mov	(&DWP(16,"esp"),$acc);	# end of key schedule
+	    &align	(4);
+	    &set_label("loop");
+		&decstep(0,"ebp",$s0,$s3,$s2,$s1);
+		&decstep(1,"ebp",$s1,$s0,$s3,$s2);
+		&decstep(2,"ebp",$s2,$s1,$s0,$s3);
+		&decstep(3,"ebp",$s3,$s2,$s1,$s0);
+		&add	($key,16);		# advance rd_key
+		&xor	($s0,&DWP(0,$key));
+		&xor	($s1,&DWP(4,$key));
+		&xor	($s2,&DWP(8,$key));
+		&xor	($s3,&DWP(12,$key));
+	    &cmp	($key,&DWP(16,"esp"));
+	    &mov	(&DWP(12,"esp"),$key);
+	    &jb		(&label("loop"));
+	}
+	else {
+	    &cmp	($acc,10);
+	    &jle	(&label("10rounds"));
+	    &cmp	($acc,12);
+	    &jle	(&label("12rounds"));
+
+	&set_label("14rounds");
+	    for ($i=1;$i<3;$i++) {
+		&decstep(0,"ebp",$s0,$s3,$s2,$s1);
+		&decstep(1,"ebp",$s1,$s0,$s3,$s2);
+		&decstep(2,"ebp",$s2,$s1,$s0,$s3);
+		&decstep(3,"ebp",$s3,$s2,$s1,$s0);
+		&xor	($s0,&DWP(16*$i+0,$key));
+		&xor	($s1,&DWP(16*$i+4,$key));
+		&xor	($s2,&DWP(16*$i+8,$key));
+		&xor	($s3,&DWP(16*$i+12,$key));
+	    }
+	    &add	($key,32);
+	    &mov	(&DWP(12,"esp"),$key);	# advance rd_key
+	&set_label("12rounds");
+	    for ($i=1;$i<3;$i++) {
+		&decstep(0,"ebp",$s0,$s3,$s2,$s1);
+		&decstep(1,"ebp",$s1,$s0,$s3,$s2);
+		&decstep(2,"ebp",$s2,$s1,$s0,$s3);
+		&decstep(3,"ebp",$s3,$s2,$s1,$s0);
+		&xor	($s0,&DWP(16*$i+0,$key));
+		&xor	($s1,&DWP(16*$i+4,$key));
+		&xor	($s2,&DWP(16*$i+8,$key));
+		&xor	($s3,&DWP(16*$i+12,$key));
+	    }
+	    &add	($key,32);
+	    &mov	(&DWP(12,"esp"),$key);	# advance rd_key
+	&set_label("10rounds");
+	    for ($i=1;$i<10;$i++) {
+		&decstep(0,"ebp",$s0,$s3,$s2,$s1);
+		&decstep(1,"ebp",$s1,$s0,$s3,$s2);
+		&decstep(2,"ebp",$s2,$s1,$s0,$s3);
+		&decstep(3,"ebp",$s3,$s2,$s1,$s0);
+		&xor	($s0,&DWP(16*$i+0,$key));
+		&xor	($s1,&DWP(16*$i+4,$key));
+		&xor	($s2,&DWP(16*$i+8,$key));
+		&xor	($s3,&DWP(16*$i+12,$key));
+	    }
+	}
+
+	&declast(0,"ebp",$s0,$s3,$s2,$s1);
+	&declast(1,"ebp",$s1,$s0,$s3,$s2);
+	&declast(2,"ebp",$s2,$s1,$s0,$s3);
+	&declast(3,"ebp",$s3,$s2,$s1,$s0);
+
+	&add	($key,$small_footprint?16:160);
+	&xor	($s0,&DWP(0,$key));
+	&xor	($s1,&DWP(4,$key));
+	&xor	($s2,&DWP(8,$key));
+	&xor	($s3,&DWP(12,$key));
+
+	&ret	();
+
+&set_label("AES_Td",64);	# Yes! I keep it in the code segment!
+	&_data_word(0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a);
+	&_data_word(0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b);
+	&_data_word(0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5);
+	&_data_word(0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5);
+	&_data_word(0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d);
+	&_data_word(0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b);
+	&_data_word(0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295);
+	&_data_word(0x2d83bed4, 0xd3217458, 0x2969e049, 0x44c8c98e);
+	&_data_word(0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927);
+	&_data_word(0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d);
+	&_data_word(0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362);
+	&_data_word(0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9);
+	&_data_word(0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52);
+	&_data_word(0x23d373ab, 0xe2024b72, 0x578f1fe3, 0x2aab5566);
+	&_data_word(0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3);
+	&_data_word(0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed);
+	&_data_word(0x2b1ccf8a, 0x92b479a7, 0xf0f207f3, 0xa1e2694e);
+	&_data_word(0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4);
+	&_data_word(0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4);
+	&_data_word(0x39ec830b, 0xaaef6040, 0x069f715e, 0x51106ebd);
+	&_data_word(0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d);
+	&_data_word(0xb58d5491, 0x055dc471, 0x6fd40604, 0xff155060);
+	&_data_word(0x24fb9819, 0x97e9bdd6, 0xcc434089, 0x779ed967);
+	&_data_word(0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879);
+	&_data_word(0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000);
+	&_data_word(0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c);
+	&_data_word(0xfbff0efd, 0x5638850f, 0x1ed5ae3d, 0x27392d36);
+	&_data_word(0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624);
+	&_data_word(0xb1670a0c, 0x0fe75793, 0xd296eeb4, 0x9e919b1b);
+	&_data_word(0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c);
+	&_data_word(0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12);
+	&_data_word(0x0b0d090e, 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14);
+	&_data_word(0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3);
+	&_data_word(0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b);
+	&_data_word(0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8);
+	&_data_word(0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684);
+	&_data_word(0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7);
+	&_data_word(0x4b2f9e1d, 0xf330b2dc, 0xec52860d, 0xd0e3c177);
+	&_data_word(0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947);
+	&_data_word(0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322);
+	&_data_word(0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498);
+	&_data_word(0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f);
+	&_data_word(0xe49d3a2c, 0x0d927850, 0x9bcc5f6a, 0x62467e54);
+	&_data_word(0xc2138df6, 0xe8b8d890, 0x5ef7392e, 0xf5afc382);
+	&_data_word(0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf);
+	&_data_word(0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb);
+	&_data_word(0x097826cd, 0xf418596e, 0x01b79aec, 0xa89a4f83);
+	&_data_word(0x656e95e6, 0x7ee6ffaa, 0x08cfbc21, 0xe6e815ef);
+	&_data_word(0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029);
+	&_data_word(0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235);
+	&_data_word(0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733);
+	&_data_word(0x4a9804f1, 0xf7daec41, 0x0e50cd7f, 0x2ff69117);
+	&_data_word(0x8dd64d76, 0x4db0ef43, 0x544daacc, 0xdf0496e4);
+	&_data_word(0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546);
+	&_data_word(0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb);
+	&_data_word(0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d);
+	&_data_word(0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb);
+	&_data_word(0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a);
+	&_data_word(0x59dfd29c, 0x3f73f255, 0x79ce1418, 0xbf37c773);
+	&_data_word(0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478);
+	&_data_word(0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2);
+	&_data_word(0x72c31d16, 0x0c25e2bc, 0x8b493c28, 0x41950dff);
+	&_data_word(0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664);
+	&_data_word(0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0);
+#Td4:
+	&data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38);
+	&data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb);
+	&data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87);
+	&data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb);
+	&data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d);
+	&data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e);
+	&data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2);
+	&data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25);
+	&data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16);
+	&data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92);
+	&data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda);
+	&data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84);
+	&data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a);
+	&data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06);
+	&data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02);
+	&data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b);
+	&data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea);
+	&data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73);
+	&data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85);
+	&data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e);
+	&data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89);
+	&data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b);
+	&data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20);
+	&data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4);
+	&data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31);
+	&data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f);
+	&data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d);
+	&data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef);
+	&data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0);
+	&data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61);
+	&data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26);
+	&data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d);
+&function_end_B("_x86_AES_decrypt");
+
+# void AES_decrypt (const void *inp,void *out,const AES_KEY *key);
+&public_label("AES_Td");
+&function_begin("AES_decrypt");
+	&mov	($acc,&wparam(0));		# load inp
+	&mov	($key,&wparam(2));		# load key
+
+	&mov	($s0,"esp");
+	&sub	("esp",24);
+	&and	("esp",-64);
+	&add	("esp",4);
+	&mov	(&DWP(16,"esp"),$s0);
+
+	&call   (&label("pic_point"));          # make it PIC!
+	&set_label("pic_point");
+	&blindpop("ebp");
+	&lea    ("ebp",&DWP(&label("AES_Td")."-".&label("pic_point"),"ebp"));
+
+	# prefetch Td4
+	&lea	("ebp",&DWP(2048+128,"ebp"));
+	&mov	($s0,&DWP(0-128,"ebp"));
+	&mov	($s1,&DWP(32-128,"ebp"));
+	&mov	($s2,&DWP(64-128,"ebp"));
+	&mov	($s3,&DWP(96-128,"ebp"));
+	&mov	($s0,&DWP(128-128,"ebp"));
+	&mov	($s1,&DWP(160-128,"ebp"));
+	&mov	($s2,&DWP(192-128,"ebp"));
+	&mov	($s3,&DWP(224-128,"ebp"));
+	&lea	("ebp",&DWP(-2048-128,"ebp"));
+
+	&mov	($s0,&DWP(0,$acc));		# load input data
+	&mov	($s1,&DWP(4,$acc));
+	&mov	($s2,&DWP(8,$acc));
+	&mov	($s3,&DWP(12,$acc));
+
+	&call	("_x86_AES_decrypt");
+
+	&mov	("esp",&DWP(16,"esp"));
+
+	&mov	($acc,&wparam(1));		# load out
+	&mov	(&DWP(0,$acc),$s0);		# write output data
+	&mov	(&DWP(4,$acc),$s1);
+	&mov	(&DWP(8,$acc),$s2);
+	&mov	(&DWP(12,$acc),$s3);
+&function_end("AES_decrypt");
+
+# void AES_cbc_encrypt (const void char *inp, unsigned char *out,
+#			size_t length, const AES_KEY *key,
+#			unsigned char *ivp,const int enc);
+{
+# stack frame layout
+# -4(%esp)	0(%esp)		return address
+# 0(%esp)	4(%esp)		tmp1
+# 4(%esp)	8(%esp)		tmp2
+# 8(%esp)	12(%esp)	key
+# 12(%esp)	16(%esp)	end of key schedule
+my $_esp=&DWP(16,"esp");	#saved %esp
+my $_inp=&DWP(20,"esp");	#copy of wparam(0)
+my $_out=&DWP(24,"esp");	#copy of wparam(1)
+my $_len=&DWP(28,"esp");	#copy of wparam(2)
+my $_key=&DWP(32,"esp");	#copy of wparam(3)
+my $_ivp=&DWP(36,"esp");	#copy of wparam(4)
+my $_tmp=&DWP(40,"esp");	#volatile variable
+my $ivec=&DWP(44,"esp");	#ivec[16]
+my $aes_key=&DWP(60,"esp");	#copy of aes_key
+my $mark=&DWP(60+240,"esp");	#copy of aes_key->rounds
+
+&public_label("AES_Te");
+&public_label("AES_Td");
+&function_begin("AES_cbc_encrypt");
+	&mov	($s2 eq "ecx"? $s2 : "",&wparam(2));	# load len
+	&cmp	($s2,0);
+	&je	(&label("enc_out"));
+
+	&call   (&label("pic_point"));		# make it PIC!
+	&set_label("pic_point");
+	&blindpop("ebp");
+
+	&pushf	();
+	&cld	();
+
+	&cmp	(&wparam(5),0);
+	&je	(&label("DECRYPT"));
+
+	&lea    ("ebp",&DWP(&label("AES_Te")."-".&label("pic_point"),"ebp"));
+
+	# allocate aligned stack frame...
+	&lea	($key,&DWP(-64-244,"esp"));
+	&and	($key,-64);
+
+	# ... and make sure it doesn't alias with AES_Te modulo 4096
+	&mov	($s0,"ebp");
+	&lea	($s1,&DWP(2048,"ebp"));
+	&mov	($s3,$key);
+	&and	($s0,0xfff);		# s = %ebp&0xfff
+	&and	($s1,0xfff);		# e = (%ebp+2048)&0xfff
+	&and	($s3,0xfff);		# p = %esp&0xfff
+
+	&cmp	($s3,$s1);		# if (p>=e) %esp =- (p-e);
+	&jb	(&label("te_break_out"));
+	&sub	($s3,$s1);
+	&sub	($key,$s3);
+	&jmp	(&label("te_ok"));
+	&set_label("te_break_out");	# else %esp -= (p-s)&0xfff + framesz;
+	&sub	($s3,$s0);
+	&and	($s3,0xfff);
+	&add	($s3,64+256);
+	&sub	($key,$s3);
+	&align	(4);
+	&set_label("te_ok");
+
+	&mov	($s0,&wparam(0));	# load inp
+	&mov	($s1,&wparam(1));	# load out
+	&mov	($s3,&wparam(3));	# load key
+	&mov	($acc,&wparam(4));	# load ivp
+
+	&exch	("esp",$key);
+	&add	("esp",4);		# reserve for return address!
+	&mov	($_esp,$key);		# save %esp
+
+	&mov	($_inp,$s0);		# save copy of inp
+	&mov	($_out,$s1);		# save copy of out
+	&mov	($_len,$s2);		# save copy of len
+	&mov	($_key,$s3);		# save copy of key
+	&mov	($_ivp,$acc);		# save copy of ivp
+
+	&mov	($mark,0);		# copy of aes_key->rounds = 0;
+	if ($compromise) {
+		&cmp	($s2,$compromise);
+		&jb	(&label("skip_ecopy"));
+	}
+	# do we copy key schedule to stack?
+	&mov	($s1 eq "ebx" ? $s1 : "",$s3);
+	&mov	($s2 eq "ecx" ? $s2 : "",244/4);
+	&sub	($s1,"ebp");
+	&mov	("esi",$s3);
+	&and	($s1,0xfff);
+	&lea	("edi",$aes_key);
+	&cmp	($s1,2048);
+	&jb	(&label("do_ecopy"));
+	&cmp	($s1,4096-244);
+	&jb	(&label("skip_ecopy"));
+	&align	(4);
+	&set_label("do_ecopy");
+		&mov	($_key,"edi");
+		&data_word(0xA5F3F689);	# rep movsd
+	&set_label("skip_ecopy");
+
+	&mov	($acc,$s0);
+	&mov	($key,16);
+	&align	(4);
+	&set_label("prefetch_te");
+		&mov	($s0,&DWP(0,"ebp"));
+		&mov	($s1,&DWP(32,"ebp"));
+		&mov	($s2,&DWP(64,"ebp"));
+		&mov	($s3,&DWP(96,"ebp"));
+		&lea	("ebp",&DWP(128,"ebp"));
+		&dec	($key);
+	&jnz	(&label("prefetch_te"));
+	&sub	("ebp",2048);
+
+	&mov	($s2,$_len);
+	&mov	($key,$_ivp);
+	&test	($s2,0xFFFFFFF0);
+	&jz	(&label("enc_tail"));		# short input...
+
+	&mov	($s0,&DWP(0,$key));		# load iv
+	&mov	($s1,&DWP(4,$key));
+
+	&align	(4);
+	&set_label("enc_loop");
+		&mov	($s2,&DWP(8,$key));
+		&mov	($s3,&DWP(12,$key));
+
+		&xor	($s0,&DWP(0,$acc));	# xor input data
+		&xor	($s1,&DWP(4,$acc));
+		&xor	($s2,&DWP(8,$acc));
+		&xor	($s3,&DWP(12,$acc));
+
+		&mov	($key,$_key);		# load key
+		&call	("_x86_AES_encrypt");
+
+		&mov	($acc,$_inp);		# load inp
+		&mov	($key,$_out);		# load out
+
+		&mov	(&DWP(0,$key),$s0);	# save output data
+		&mov	(&DWP(4,$key),$s1);
+		&mov	(&DWP(8,$key),$s2);
+		&mov	(&DWP(12,$key),$s3);
+
+		&mov	($s2,$_len);		# load len
+
+		&lea	($acc,&DWP(16,$acc));
+		&mov	($_inp,$acc);		# save inp
+
+		&lea	($s3,&DWP(16,$key));
+		&mov	($_out,$s3);		# save out
+
+		&sub	($s2,16);
+		&test	($s2,0xFFFFFFF0);
+		&mov	($_len,$s2);		# save len
+	&jnz	(&label("enc_loop"));
+	&test	($s2,15);
+	&jnz	(&label("enc_tail"));
+	&mov	($acc,$_ivp);		# load ivp
+	&mov	($s2,&DWP(8,$key));	# restore last dwords
+	&mov	($s3,&DWP(12,$key));
+	&mov	(&DWP(0,$acc),$s0);	# save ivec
+	&mov	(&DWP(4,$acc),$s1);
+	&mov	(&DWP(8,$acc),$s2);
+	&mov	(&DWP(12,$acc),$s3);
+
+	&cmp	($mark,0);		# was the key schedule copied?
+	&mov	("edi",$_key);
+	&je	(&label("skip_ezero"));
+	# zero copy of key schedule
+	&mov	("ecx",240/4);
+	&xor	("eax","eax");
+	&align	(4);
+	&data_word(0xABF3F689);	# rep stosd
+	&set_label("skip_ezero")
+	&mov	("esp",$_esp);
+	&popf	();
+    &set_label("enc_out");
+	&function_end_A();
+	&pushf	();			# kludge, never executed
+
+    &align	(4);
+    &set_label("enc_tail");
+	&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
+	&je	(&label("enc_in_place"));
+	&align	(4);
+	&data_word(0xA4F3F689);	# rep movsb	# copy input
+	&jmp	(&label("enc_skip_in_place"));
+    &set_label("enc_in_place");
+	&lea	($key,&DWP(0,$key,$s2));
+    &set_label("enc_skip_in_place");
+	&mov	($s2,$s1);
+	&xor	($s0,$s0);
+	&align	(4);
+	&data_word(0xAAF3F689);	# rep stosb	# zero tail
+	&pop	($key);				# pop ivp
+
+	&mov	($acc,$_out);			# output as input
+	&mov	($s0,&DWP(0,$key));
+	&mov	($s1,&DWP(4,$key));
+	&mov	($_len,16);			# len=16
+	&jmp	(&label("enc_loop"));		# one more spin...
+
+#----------------------------- DECRYPT -----------------------------#
+&align	(4);
+&set_label("DECRYPT");
+	&lea    ("ebp",&DWP(&label("AES_Td")."-".&label("pic_point"),"ebp"));
+
+	# allocate aligned stack frame...
+	&lea	($key,&DWP(-64-244,"esp"));
+	&and	($key,-64);
+
+	# ... and make sure it doesn't alias with AES_Td modulo 4096
+	&mov	($s0,"ebp");
+	&lea	($s1,&DWP(2048+256,"ebp"));
+	&mov	($s3,$key);
+	&and	($s0,0xfff);		# s = %ebp&0xfff
+	&and	($s1,0xfff);		# e = (%ebp+2048+256)&0xfff
+	&and	($s3,0xfff);		# p = %esp&0xfff
+
+	&cmp	($s3,$s1);		# if (p>=e) %esp =- (p-e);
+	&jb	(&label("td_break_out"));
+	&sub	($s3,$s1);
+	&sub	($key,$s3);
+	&jmp	(&label("td_ok"));
+	&set_label("td_break_out");	# else %esp -= (p-s)&0xfff + framesz;
+	&sub	($s3,$s0);
+	&and	($s3,0xfff);
+	&add	($s3,64+256);
+	&sub	($key,$s3);
+	&align	(4);
+	&set_label("td_ok");
+
+	&mov	($s0,&wparam(0));	# load inp
+	&mov	($s1,&wparam(1));	# load out
+	&mov	($s3,&wparam(3));	# load key
+	&mov	($acc,&wparam(4));	# load ivp
+
+	&exch	("esp",$key);
+	&add	("esp",4);		# reserve for return address!
+	&mov	($_esp,$key);		# save %esp
+
+	&mov	($_inp,$s0);		# save copy of inp
+	&mov	($_out,$s1);		# save copy of out
+	&mov	($_len,$s2);		# save copy of len
+	&mov	($_key,$s3);		# save copy of key
+	&mov	($_ivp,$acc);		# save copy of ivp
+
+	&mov	($mark,0);		# copy of aes_key->rounds = 0;
+	if ($compromise) {
+		&cmp	($s2,$compromise);
+		&jb	(&label("skip_dcopy"));
+	}
+	# do we copy key schedule to stack?
+	&mov	($s1 eq "ebx" ? $s1 : "",$s3);
+	&mov	($s2 eq "ecx" ? $s2 : "",244/4);
+	&sub	($s1,"ebp");
+	&mov	("esi",$s3);
+	&and	($s1,0xfff);
+	&lea	("edi",$aes_key);
+	&cmp	($s1,2048+256);
+	&jb	(&label("do_dcopy"));
+	&cmp	($s1,4096-244);
+	&jb	(&label("skip_dcopy"));
+	&align	(4);
+	&set_label("do_dcopy");
+		&mov	($_key,"edi");
+		&data_word(0xA5F3F689);	# rep movsd
+	&set_label("skip_dcopy");
+
+	&mov	($acc,$s0);
+	&mov	($key,18);
+	&align	(4);
+	&set_label("prefetch_td");
+		&mov	($s0,&DWP(0,"ebp"));
+		&mov	($s1,&DWP(32,"ebp"));
+		&mov	($s2,&DWP(64,"ebp"));
+		&mov	($s3,&DWP(96,"ebp"));
+		&lea	("ebp",&DWP(128,"ebp"));
+		&dec	($key);
+	&jnz	(&label("prefetch_td"));
+	&sub	("ebp",2048+256);
+
+	&cmp	($acc,$_out);
+	&je	(&label("dec_in_place"));	# in-place processing...
+
+	&mov	($key,$_ivp);		# load ivp
+	&mov	($_tmp,$key);
+
+	&align	(4);
+	&set_label("dec_loop");
+		&mov	($s0,&DWP(0,$acc));	# read input
+		&mov	($s1,&DWP(4,$acc));
+		&mov	($s2,&DWP(8,$acc));
+		&mov	($s3,&DWP(12,$acc));
+
+		&mov	($key,$_key);		# load key
+		&call	("_x86_AES_decrypt");
+
+		&mov	($key,$_tmp);		# load ivp
+		&mov	($acc,$_len);		# load len
+		&xor	($s0,&DWP(0,$key));	# xor iv
+		&xor	($s1,&DWP(4,$key));
+		&xor	($s2,&DWP(8,$key));
+		&xor	($s3,&DWP(12,$key));
+
+		&sub	($acc,16);
+		&jc	(&label("dec_partial"));
+		&mov	($_len,$acc);		# save len
+		&mov	($acc,$_inp);		# load inp
+		&mov	($key,$_out);		# load out
+
+		&mov	(&DWP(0,$key),$s0);	# write output
+		&mov	(&DWP(4,$key),$s1);
+		&mov	(&DWP(8,$key),$s2);
+		&mov	(&DWP(12,$key),$s3);
+
+		&mov	($_tmp,$acc);		# save ivp
+		&lea	($acc,&DWP(16,$acc));
+		&mov	($_inp,$acc);		# save inp
+
+		&lea	($key,&DWP(16,$key));
+		&mov	($_out,$key);		# save out
+
+	&jnz	(&label("dec_loop"));
+	&mov	($key,$_tmp);		# load temp ivp
+    &set_label("dec_end");
+	&mov	($acc,$_ivp);		# load user ivp
+	&mov	($s0,&DWP(0,$key));	# load iv
+	&mov	($s1,&DWP(4,$key));
+	&mov	($s2,&DWP(8,$key));
+	&mov	($s3,&DWP(12,$key));
+	&mov	(&DWP(0,$acc),$s0);	# copy back to user
+	&mov	(&DWP(4,$acc),$s1);
+	&mov	(&DWP(8,$acc),$s2);
+	&mov	(&DWP(12,$acc),$s3);
+	&jmp	(&label("dec_out"));
+
+    &align	(4);
+    &set_label("dec_partial");
+	&lea	($key,$ivec);
+	&mov	(&DWP(0,$key),$s0);	# dump output to stack
+	&mov	(&DWP(4,$key),$s1);
+	&mov	(&DWP(8,$key),$s2);
+	&mov	(&DWP(12,$key),$s3);
+	&lea	($s2 eq "ecx" ? $s2 : "",&DWP(16,$acc));
+	&mov	($acc eq "esi" ? $acc : "",$key);
+	&mov	($key eq "edi" ? $key : "",$_out);	# load out
+	&data_word(0xA4F3F689);	# rep movsb		# copy output
+	&mov	($key,$_inp);				# use inp as temp ivp
+	&jmp	(&label("dec_end"));
+
+    &align	(4);
+    &set_label("dec_in_place");
+	&set_label("dec_in_place_loop");
+		&lea	($key,$ivec);
+		&mov	($s0,&DWP(0,$acc));	# read input
+		&mov	($s1,&DWP(4,$acc));
+		&mov	($s2,&DWP(8,$acc));
+		&mov	($s3,&DWP(12,$acc));
+
+		&mov	(&DWP(0,$key),$s0);	# copy to temp
+		&mov	(&DWP(4,$key),$s1);
+		&mov	(&DWP(8,$key),$s2);
+		&mov	(&DWP(12,$key),$s3);
+
+		&mov	($key,$_key);		# load key
+		&call	("_x86_AES_decrypt");
+
+		&mov	($key,$_ivp);		# load ivp
+		&mov	($acc,$_out);		# load out
+		&xor	($s0,&DWP(0,$key));	# xor iv
+		&xor	($s1,&DWP(4,$key));
+		&xor	($s2,&DWP(8,$key));
+		&xor	($s3,&DWP(12,$key));
+
+		&mov	(&DWP(0,$acc),$s0);	# write output
+		&mov	(&DWP(4,$acc),$s1);
+		&mov	(&DWP(8,$acc),$s2);
+		&mov	(&DWP(12,$acc),$s3);
+
+		&lea	($acc,&DWP(16,$acc));
+		&mov	($_out,$acc);		# save out
+
+		&lea	($acc,$ivec);
+		&mov	($s0,&DWP(0,$acc));	# read temp
+		&mov	($s1,&DWP(4,$acc));
+		&mov	($s2,&DWP(8,$acc));
+		&mov	($s3,&DWP(12,$acc));
+
+		&mov	(&DWP(0,$key),$s0);	# copy iv
+		&mov	(&DWP(4,$key),$s1);
+		&mov	(&DWP(8,$key),$s2);
+		&mov	(&DWP(12,$key),$s3);
+
+		&mov	($acc,$_inp);		# load inp
+
+		&lea	($acc,&DWP(16,$acc));
+		&mov	($_inp,$acc);		# save inp
+
+		&mov	($s2,$_len);		# load len
+		&sub	($s2,16);
+		&jc	(&label("dec_in_place_partial"));
+		&mov	($_len,$s2);		# save len
+	&jnz	(&label("dec_in_place_loop"));
+	&jmp	(&label("dec_out"));
+
+    &align	(4);
+    &set_label("dec_in_place_partial");
+	# one can argue if this is actually required...
+	&mov	($key eq "edi" ? $key : "",$_out);
+	&lea	($acc eq "esi" ? $acc : "",$ivec);
+	&lea	($key,&DWP(0,$key,$s2));
+	&lea	($acc,&DWP(16,$acc,$s2));
+	&neg	($s2 eq "ecx" ? $s2 : "");
+	&data_word(0xA4F3F689);	# rep movsb	# restore tail
+
+    &align	(4);
+    &set_label("dec_out");
+    &cmp	($mark,0);		# was the key schedule copied?
+    &mov	("edi",$_key);
+    &je		(&label("skip_dzero"));
+    # zero copy of key schedule
+    &mov	("ecx",240/4);
+    &xor	("eax","eax");
+    &align	(4);
+    &data_word(0xABF3F689);	# rep stosd
+    &set_label("skip_dzero")
+    &mov	("esp",$_esp);
+    &popf	();
+&function_end("AES_cbc_encrypt");
+}
+
+#------------------------------------------------------------------#
+
+sub enckey()
+{
+	&movz	("esi",&LB("edx"));		# rk[i]>>0
+	&mov	("ebx",&DWP(2,"ebp","esi",8));
+	&movz	("esi",&HB("edx"));		# rk[i]>>8
+	&and	("ebx",0xFF000000);
+	&xor	("eax","ebx");
+
+	&mov	("ebx",&DWP(2,"ebp","esi",8));
+	&shr	("edx",16);
+	&and	("ebx",0x000000FF);
+	&movz	("esi",&LB("edx"));		# rk[i]>>16
+	&xor	("eax","ebx");
+
+	&mov	("ebx",&DWP(0,"ebp","esi",8));
+	&movz	("esi",&HB("edx"));		# rk[i]>>24
+	&and	("ebx",0x0000FF00);
+	&xor	("eax","ebx");
+
+	&mov	("ebx",&DWP(0,"ebp","esi",8));
+	&and	("ebx",0x00FF0000);
+	&xor	("eax","ebx");
+
+	&xor	("eax",&DWP(2048,"ebp","ecx",4));	# rcon
+}
+
+# int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
+#                        AES_KEY *key)
+&public_label("AES_Te");
+&function_begin("AES_set_encrypt_key");
+	&mov	("esi",&wparam(0));		# user supplied key
+	&mov	("edi",&wparam(2));		# private key schedule
+
+	&test	("esi",-1);
+	&jz	(&label("badpointer"));
+	&test	("edi",-1);
+	&jz	(&label("badpointer"));
+
+	&call	(&label("pic_point"));
+	&set_label("pic_point");
+	&blindpop("ebp");
+	&lea	("ebp",&DWP(&label("AES_Te")."-".&label("pic_point"),"ebp"));
+
+	&mov	("ecx",&wparam(1));		# number of bits in key
+	&cmp	("ecx",128);
+	&je	(&label("10rounds"));
+	&cmp	("ecx",192);
+	&je	(&label("12rounds"));
+	&cmp	("ecx",256);
+	&je	(&label("14rounds"));
+	&mov	("eax",-2);			# invalid number of bits
+	&jmp	(&label("exit"));
+
+    &set_label("10rounds");
+	&mov	("eax",&DWP(0,"esi"));		# copy first 4 dwords
+	&mov	("ebx",&DWP(4,"esi"));
+	&mov	("ecx",&DWP(8,"esi"));
+	&mov	("edx",&DWP(12,"esi"));
+	&mov	(&DWP(0,"edi"),"eax");
+	&mov	(&DWP(4,"edi"),"ebx");
+	&mov	(&DWP(8,"edi"),"ecx");
+	&mov	(&DWP(12,"edi"),"edx");
+
+	&xor	("ecx","ecx");
+	&jmp	(&label("10shortcut"));
+
+	&align	(4);
+	&set_label("10loop");
+		&mov	("eax",&DWP(0,"edi"));		# rk[0]
+		&mov	("edx",&DWP(12,"edi"));		# rk[3]
+	&set_label("10shortcut");
+		&enckey	();
+
+		&mov	(&DWP(16,"edi"),"eax");		# rk[4]
+		&xor	("eax",&DWP(4,"edi"));
+		&mov	(&DWP(20,"edi"),"eax");		# rk[5]
+		&xor	("eax",&DWP(8,"edi"));
+		&mov	(&DWP(24,"edi"),"eax");		# rk[6]
+		&xor	("eax",&DWP(12,"edi"));
+		&mov	(&DWP(28,"edi"),"eax");		# rk[7]
+		&inc	("ecx");
+		&add	("edi",16);
+		&cmp	("ecx",10);
+	&jl	(&label("10loop"));
+
+	&mov	(&DWP(80,"edi"),10);		# setup number of rounds
+	&xor	("eax","eax");
+	&jmp	(&label("exit"));
+		
+    &set_label("12rounds");
+	&mov	("eax",&DWP(0,"esi"));		# copy first 6 dwords
+	&mov	("ebx",&DWP(4,"esi"));
+	&mov	("ecx",&DWP(8,"esi"));
+	&mov	("edx",&DWP(12,"esi"));
+	&mov	(&DWP(0,"edi"),"eax");
+	&mov	(&DWP(4,"edi"),"ebx");
+	&mov	(&DWP(8,"edi"),"ecx");
+	&mov	(&DWP(12,"edi"),"edx");
+	&mov	("ecx",&DWP(16,"esi"));
+	&mov	("edx",&DWP(20,"esi"));
+	&mov	(&DWP(16,"edi"),"ecx");
+	&mov	(&DWP(20,"edi"),"edx");
+
+	&xor	("ecx","ecx");
+	&jmp	(&label("12shortcut"));
+
+	&align	(4);
+	&set_label("12loop");
+		&mov	("eax",&DWP(0,"edi"));		# rk[0]
+		&mov	("edx",&DWP(20,"edi"));		# rk[5]
+	&set_label("12shortcut");
+		&enckey	();
+
+		&mov	(&DWP(24,"edi"),"eax");		# rk[6]
+		&xor	("eax",&DWP(4,"edi"));
+		&mov	(&DWP(28,"edi"),"eax");		# rk[7]
+		&xor	("eax",&DWP(8,"edi"));
+		&mov	(&DWP(32,"edi"),"eax");		# rk[8]
+		&xor	("eax",&DWP(12,"edi"));
+		&mov	(&DWP(36,"edi"),"eax");		# rk[9]
+
+		&cmp	("ecx",7);
+		&je	(&label("12break"));
+		&inc	("ecx");
+
+		&xor	("eax",&DWP(16,"edi"));
+		&mov	(&DWP(40,"edi"),"eax");		# rk[10]
+		&xor	("eax",&DWP(20,"edi"));
+		&mov	(&DWP(44,"edi"),"eax");		# rk[11]
+
+		&add	("edi",24);
+	&jmp	(&label("12loop"));
+
+	&set_label("12break");
+	&mov	(&DWP(72,"edi"),12);		# setup number of rounds
+	&xor	("eax","eax");
+	&jmp	(&label("exit"));
+
+    &set_label("14rounds");
+	&mov	("eax",&DWP(0,"esi"));		# copy first 8 dwords
+	&mov	("ebx",&DWP(4,"esi"));
+	&mov	("ecx",&DWP(8,"esi"));
+	&mov	("edx",&DWP(12,"esi"));
+	&mov	(&DWP(0,"edi"),"eax");
+	&mov	(&DWP(4,"edi"),"ebx");
+	&mov	(&DWP(8,"edi"),"ecx");
+	&mov	(&DWP(12,"edi"),"edx");
+	&mov	("eax",&DWP(16,"esi"));
+	&mov	("ebx",&DWP(20,"esi"));
+	&mov	("ecx",&DWP(24,"esi"));
+	&mov	("edx",&DWP(28,"esi"));
+	&mov	(&DWP(16,"edi"),"eax");
+	&mov	(&DWP(20,"edi"),"ebx");
+	&mov	(&DWP(24,"edi"),"ecx");
+	&mov	(&DWP(28,"edi"),"edx");
+
+	&xor	("ecx","ecx");
+	&jmp	(&label("14shortcut"));
+
+	&align	(4);
+	&set_label("14loop");
+		&mov	("edx",&DWP(28,"edi"));		# rk[7]
+	&set_label("14shortcut");
+		&mov	("eax",&DWP(0,"edi"));		# rk[0]
+
+		&enckey	();
+
+		&mov	(&DWP(32,"edi"),"eax");		# rk[8]
+		&xor	("eax",&DWP(4,"edi"));
+		&mov	(&DWP(36,"edi"),"eax");		# rk[9]
+		&xor	("eax",&DWP(8,"edi"));
+		&mov	(&DWP(40,"edi"),"eax");		# rk[10]
+		&xor	("eax",&DWP(12,"edi"));
+		&mov	(&DWP(44,"edi"),"eax");		# rk[11]
+
+		&cmp	("ecx",6);
+		&je	(&label("14break"));
+		&inc	("ecx");
+
+		&mov	("edx","eax");
+		&mov	("eax",&DWP(16,"edi"));		# rk[4]
+		&movz	("esi",&LB("edx"));		# rk[11]>>0
+		&mov	("ebx",&DWP(2,"ebp","esi",8));
+		&movz	("esi",&HB("edx"));		# rk[11]>>8
+		&and	("ebx",0x000000FF);
+		&xor	("eax","ebx");
+
+		&mov	("ebx",&DWP(0,"ebp","esi",8));
+		&shr	("edx",16);
+		&and	("ebx",0x0000FF00);
+		&movz	("esi",&LB("edx"));		# rk[11]>>16
+		&xor	("eax","ebx");
+
+		&mov	("ebx",&DWP(0,"ebp","esi",8));
+		&movz	("esi",&HB("edx"));		# rk[11]>>24
+		&and	("ebx",0x00FF0000);
+		&xor	("eax","ebx");
+
+		&mov	("ebx",&DWP(2,"ebp","esi",8));
+		&and	("ebx",0xFF000000);
+		&xor	("eax","ebx");
+
+		&mov	(&DWP(48,"edi"),"eax");		# rk[12]
+		&xor	("eax",&DWP(20,"edi"));
+		&mov	(&DWP(52,"edi"),"eax");		# rk[13]
+		&xor	("eax",&DWP(24,"edi"));
+		&mov	(&DWP(56,"edi"),"eax");		# rk[14]
+		&xor	("eax",&DWP(28,"edi"));
+		&mov	(&DWP(60,"edi"),"eax");		# rk[15]
+
+		&add	("edi",32);
+	&jmp	(&label("14loop"));
+
+	&set_label("14break");
+	&mov	(&DWP(48,"edi"),14);		# setup number of rounds
+	&xor	("eax","eax");
+	&jmp	(&label("exit"));
+
+    &set_label("badpointer");
+	&mov	("eax",-1);
+    &set_label("exit");
+&function_end("AES_set_encrypt_key");
+
+sub deckey()
+{ my ($i,$ptr,$te,$td) = @_;
+
+	&mov	("eax",&DWP($i,$ptr));
+	&mov	("edx","eax");
+	&movz	("ebx",&HB("eax"));
+	&shr	("edx",16);
+	&and	("eax",0xFF);
+	&movz	("eax",&BP(2,$te,"eax",8));
+	&movz	("ebx",&BP(2,$te,"ebx",8));
+	&mov	("eax",&DWP(0,$td,"eax",8));
+	&xor	("eax",&DWP(3,$td,"ebx",8));
+	&movz	("ebx",&HB("edx"));
+	&and	("edx",0xFF);
+	&movz	("edx",&BP(2,$te,"edx",8));
+	&movz	("ebx",&BP(2,$te,"ebx",8));
+	&xor	("eax",&DWP(2,$td,"edx",8));
+	&xor	("eax",&DWP(1,$td,"ebx",8));
+	&mov	(&DWP($i,$ptr),"eax");
+}
+
+# int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
+#                        AES_KEY *key)
+&public_label("AES_Td");
+&public_label("AES_Te");
+&function_begin_B("AES_set_decrypt_key");
+	&mov	("eax",&wparam(0));
+	&mov	("ecx",&wparam(1));
+	&mov	("edx",&wparam(2));
+	&sub	("esp",12);
+	&mov	(&DWP(0,"esp"),"eax");
+	&mov	(&DWP(4,"esp"),"ecx");
+	&mov	(&DWP(8,"esp"),"edx");
+	&call	("AES_set_encrypt_key");
+	&add	("esp",12);
+	&cmp	("eax",0);
+	&je	(&label("proceed"));
+	&ret	();
+
+    &set_label("proceed");
+	&push	("ebp");
+	&push	("ebx");
+	&push	("esi");
+	&push	("edi");
+
+	&mov	("esi",&wparam(2));
+	&mov	("ecx",&DWP(240,"esi"));	# pull number of rounds
+	&lea	("ecx",&DWP(0,"","ecx",4));
+	&lea	("edi",&DWP(0,"esi","ecx",4));	# pointer to last chunk
+
+	&align	(4);
+	&set_label("invert");			# invert order of chunks
+		&mov	("eax",&DWP(0,"esi"));
+		&mov	("ebx",&DWP(4,"esi"));
+		&mov	("ecx",&DWP(0,"edi"));
+		&mov	("edx",&DWP(4,"edi"));
+		&mov	(&DWP(0,"edi"),"eax");
+		&mov	(&DWP(4,"edi"),"ebx");
+		&mov	(&DWP(0,"esi"),"ecx");
+		&mov	(&DWP(4,"esi"),"edx");
+		&mov	("eax",&DWP(8,"esi"));
+		&mov	("ebx",&DWP(12,"esi"));
+		&mov	("ecx",&DWP(8,"edi"));
+		&mov	("edx",&DWP(12,"edi"));
+		&mov	(&DWP(8,"edi"),"eax");
+		&mov	(&DWP(12,"edi"),"ebx");
+		&mov	(&DWP(8,"esi"),"ecx");
+		&mov	(&DWP(12,"esi"),"edx");
+		&add	("esi",16);
+		&sub	("edi",16);
+		&cmp	("esi","edi");
+	&jne	(&label("invert"));
+
+	&call	(&label("pic_point"));
+	&set_label("pic_point");
+	blindpop("ebp");
+	&lea	("edi",&DWP(&label("AES_Td")."-".&label("pic_point"),"ebp"));
+	&lea	("ebp",&DWP(&label("AES_Te")."-".&label("pic_point"),"ebp"));
+
+	&mov	("esi",&wparam(2));
+	&mov	("ecx",&DWP(240,"esi"));	# pull number of rounds
+	&dec	("ecx");
+	&align	(4);
+	&set_label("permute");			# permute the key schedule
+		&add	("esi",16);
+		&deckey	(0,"esi","ebp","edi");
+		&deckey	(4,"esi","ebp","edi");
+		&deckey	(8,"esi","ebp","edi");
+		&deckey	(12,"esi","ebp","edi");
+		&dec	("ecx");
+	&jnz	(&label("permute"));
+
+	&xor	("eax","eax");			# return success
+&function_end("AES_set_decrypt_key");
+
+&asm_finish();


Property changes on: openssl/branches/upstream/current/crypto/aes/asm/aes-586.pl
___________________________________________________________________
Added: svn:executable
   + *

Modified: openssl/branches/upstream/current/crypto/asn1/asn1.h
===================================================================
--- openssl/branches/upstream/current/crypto/asn1/asn1.h	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/crypto/asn1/asn1.h	2009-05-16 15:25:35 UTC (rev 372)
@@ -158,7 +158,12 @@
 #define MBSTRING_BMP		(MBSTRING_FLAG|2)
 #define MBSTRING_UNIV		(MBSTRING_FLAG|4)
 
+#define SMIME_OLDMIME		0x400
+#define SMIME_CRLFEOL		0x800
+#define SMIME_STREAM		0x1000
+
 struct X509_algor_st;
+DECLARE_STACK_OF(X509_ALGOR)
 
 #define DECLARE_ASN1_SET_OF(type) /* filled in by mkstack.pl */
 #define IMPLEMENT_ASN1_SET_OF(type) /* nothing, no longer needed */
@@ -218,6 +223,13 @@
  * be inserted in the memory buffer 
  */
 #define ASN1_STRING_FLAG_NDEF 0x010 
+
+/* This flag is used by the CMS code to indicate that a string is not
+ * complete and is a place holder for content when it had all been 
+ * accessed. The flag will be reset when content has been written to it.
+ */
+#define ASN1_STRING_FLAG_CONT 0x020 
+
 /* This is the base type that holds just about everything :-) */
 typedef struct asn1_string_st
 	{
@@ -311,8 +323,8 @@
 	int i2d_##name##_NDEF(name *a, unsigned char **out);
 
 #define DECLARE_ASN1_FUNCTIONS_const(name) \
-	name *name##_new(void); \
-	void name##_free(name *a);
+	DECLARE_ASN1_ALLOC_FUNCTIONS(name) \
+	DECLARE_ASN1_ENCODE_FUNCTIONS_const(name, name)
 
 #define DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \
 	type *name##_new(void); \
@@ -522,6 +534,7 @@
 		 * contain the set or sequence bytes */
 		ASN1_STRING *		set;
 		ASN1_STRING *		sequence;
+		ASN1_VALUE  *		asn1_value;
 		} value;
 	} ASN1_TYPE;
 
@@ -599,6 +612,7 @@
 			B_ASN1_GENERALIZEDTIME
 
 #define B_ASN1_PRINTABLE \
+			B_ASN1_NUMERICSTRING| \
 			B_ASN1_PRINTABLESTRING| \
 			B_ASN1_T61STRING| \
 			B_ASN1_IA5STRING| \
@@ -752,6 +766,7 @@
 
 int ASN1_TYPE_get(ASN1_TYPE *a);
 void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value);
+int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value);
 
 ASN1_OBJECT *	ASN1_OBJECT_new(void );
 void		ASN1_OBJECT_free(ASN1_OBJECT *a);
@@ -774,6 +789,7 @@
   /* Since this is used to store all sorts of things, via macros, for now, make
      its data void * */
 int 		ASN1_STRING_set(ASN1_STRING *str, const void *data, int len);
+void		ASN1_STRING_set0(ASN1_STRING *str, void *data, int len);
 int ASN1_STRING_length(ASN1_STRING *x);
 void ASN1_STRING_length_set(ASN1_STRING *x, int n);
 int ASN1_STRING_type(ASN1_STRING *x);
@@ -926,6 +942,12 @@
 
 void *ASN1_item_dup(const ASN1_ITEM *it, void *x);
 
+/* ASN1 alloc/free macros for when a type is only used internally */
+
+#define M_ASN1_new_of(type) (type *)ASN1_item_new(ASN1_ITEM_rptr(type))
+#define M_ASN1_free_of(x, type) \
+		ASN1_item_free(CHECKED_PTR_OF(type, x), ASN1_ITEM_rptr(type))
+
 #ifndef OPENSSL_NO_FP_API
 void *ASN1_d2i_fp(void *(*xnew)(void), d2i_of_void *d2i, FILE *in, void **x);
 
@@ -1054,7 +1076,17 @@
 
 ASN1_TYPE *ASN1_generate_nconf(char *str, CONF *nconf);
 ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf);
-	
+
+typedef int asn1_output_data_fn(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
+					const ASN1_ITEM *it);
+
+int int_smime_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
+				int ctype_nid, int econt_nid,
+				STACK_OF(X509_ALGOR) *mdalgs,
+				asn1_output_data_fn *data_fn,
+				const ASN1_ITEM *it);
+ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it);
+
 /* 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.
@@ -1104,6 +1136,7 @@
 #define ASN1_F_ASN1_ITEM_VERIFY				 197
 #define ASN1_F_ASN1_MBSTRING_NCOPY			 122
 #define ASN1_F_ASN1_OBJECT_NEW				 123
+#define ASN1_F_ASN1_OUTPUT_DATA				 207
 #define ASN1_F_ASN1_PACK_STRING				 124
 #define ASN1_F_ASN1_PCTX_NEW				 205
 #define ASN1_F_ASN1_PKCS5_PBE_SET			 125
@@ -1123,6 +1156,8 @@
 #define ASN1_F_ASN1_UNPACK_STRING			 136
 #define ASN1_F_ASN1_UTCTIME_SET				 187
 #define ASN1_F_ASN1_VERIFY				 137
+#define ASN1_F_B64_READ_ASN1				 208
+#define ASN1_F_B64_WRITE_ASN1				 209
 #define ASN1_F_BITSTR_CB				 180
 #define ASN1_F_BN_TO_ASN1_ENUMERATED			 138
 #define ASN1_F_BN_TO_ASN1_INTEGER			 139
@@ -1163,6 +1198,8 @@
 #define ASN1_F_PARSE_TAGGING				 182
 #define ASN1_F_PKCS5_PBE2_SET				 167
 #define ASN1_F_PKCS5_PBE_SET				 202
+#define ASN1_F_SMIME_READ_ASN1				 210
+#define ASN1_F_SMIME_TEXT				 211
 #define ASN1_F_X509_CINF_NEW				 168
 #define ASN1_F_X509_CRL_ADD0_REVOKED			 169
 #define ASN1_F_X509_INFO_NEW				 170
@@ -1174,11 +1211,14 @@
 
 /* Reason codes. */
 #define ASN1_R_ADDING_OBJECT				 171
+#define ASN1_R_ASN1_PARSE_ERROR				 198
+#define ASN1_R_ASN1_SIG_PARSE_ERROR			 199
 #define ASN1_R_AUX_ERROR				 100
 #define ASN1_R_BAD_CLASS				 101
 #define ASN1_R_BAD_OBJECT_HEADER			 102
 #define ASN1_R_BAD_PASSWORD_READ			 103
 #define ASN1_R_BAD_TAG					 104
+#define ASN1_R_BMPSTRING_IS_WRONG_LENGTH		 210
 #define ASN1_R_BN_LIB					 105
 #define ASN1_R_BOOLEAN_IS_WRONG_LENGTH			 106
 #define ASN1_R_BUFFER_TOO_SMALL				 107
@@ -1220,6 +1260,7 @@
 #define ASN1_R_INTEGER_TOO_LARGE_FOR_LONG		 128
 #define ASN1_R_INVALID_BMPSTRING_LENGTH			 129
 #define ASN1_R_INVALID_DIGIT				 130
+#define ASN1_R_INVALID_MIME_TYPE			 200
 #define ASN1_R_INVALID_MODIFIER				 186
 #define ASN1_R_INVALID_NUMBER				 187
 #define ASN1_R_INVALID_SEPARATOR			 131
@@ -1229,6 +1270,9 @@
 #define ASN1_R_IV_TOO_LARGE				 135
 #define ASN1_R_LENGTH_ERROR				 136
 #define ASN1_R_LIST_ERROR				 188
+#define ASN1_R_MIME_NO_CONTENT_TYPE			 201
+#define ASN1_R_MIME_PARSE_ERROR				 202
+#define ASN1_R_MIME_SIG_PARSE_ERROR			 203
 #define ASN1_R_MISSING_EOC				 137
 #define ASN1_R_MISSING_SECOND_NUMBER			 138
 #define ASN1_R_MISSING_VALUE				 189
@@ -1238,7 +1282,11 @@
 #define ASN1_R_NON_HEX_CHARACTERS			 141
 #define ASN1_R_NOT_ASCII_FORMAT				 190
 #define ASN1_R_NOT_ENOUGH_DATA				 142
+#define ASN1_R_NO_CONTENT_TYPE				 204
 #define ASN1_R_NO_MATCHING_CHOICE_TYPE			 143
+#define ASN1_R_NO_MULTIPART_BODY_FAILURE		 205
+#define ASN1_R_NO_MULTIPART_BOUNDARY			 206
+#define ASN1_R_NO_SIG_CONTENT_TYPE			 207
 #define ASN1_R_NULL_IS_WRONG_LENGTH			 144
 #define ASN1_R_OBJECT_NOT_ASCII_FORMAT			 191
 #define ASN1_R_ODD_NUMBER_OF_CHARS			 145
@@ -1248,6 +1296,8 @@
 #define ASN1_R_SEQUENCE_NOT_CONSTRUCTED			 149
 #define ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG		 192
 #define ASN1_R_SHORT_LINE				 150
+#define ASN1_R_SIG_INVALID_MIME_TYPE			 208
+#define ASN1_R_STREAMING_NOT_SUPPORTED			 209
 #define ASN1_R_STRING_TOO_LONG				 151
 #define ASN1_R_STRING_TOO_SHORT				 152
 #define ASN1_R_TAG_VALUE_TOO_HIGH			 153
@@ -1258,6 +1308,7 @@
 #define ASN1_R_UNABLE_TO_DECODE_RSA_KEY			 157
 #define ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY		 158
 #define ASN1_R_UNEXPECTED_EOC				 159
+#define ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH		 211
 #define ASN1_R_UNKNOWN_FORMAT				 160
 #define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM		 161
 #define ASN1_R_UNKNOWN_OBJECT_TYPE			 162

Added: openssl/branches/upstream/current/crypto/asn1/asn1_err.c
===================================================================
--- openssl/branches/upstream/current/crypto/asn1/asn1_err.c	                        (rev 0)
+++ openssl/branches/upstream/current/crypto/asn1/asn1_err.c	2009-05-16 15:25:35 UTC (rev 372)
@@ -0,0 +1,317 @@
+/* crypto/asn1/asn1_err.c */
+/* ====================================================================
+ * 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
+ * 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 at 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 at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ *
+ */
+
+/* NOTE: this file was auto generated by the mkerr.pl script: any changes
+ * made to it will be overwritten when the script next updates this file,
+ * only reason strings will be preserved.
+ */
+
+#include <stdio.h>
+#include <openssl/err.h>
+#include <openssl/asn1.h>
+
+/* BEGIN ERROR CODES */
+#ifndef OPENSSL_NO_ERR
+
+#define ERR_FUNC(func) ERR_PACK(ERR_LIB_ASN1,func,0)
+#define ERR_REASON(reason) ERR_PACK(ERR_LIB_ASN1,0,reason)
+
+static ERR_STRING_DATA ASN1_str_functs[]=
+	{
+{ERR_FUNC(ASN1_F_A2D_ASN1_OBJECT),	"a2d_ASN1_OBJECT"},
+{ERR_FUNC(ASN1_F_A2I_ASN1_ENUMERATED),	"a2i_ASN1_ENUMERATED"},
+{ERR_FUNC(ASN1_F_A2I_ASN1_INTEGER),	"a2i_ASN1_INTEGER"},
+{ERR_FUNC(ASN1_F_A2I_ASN1_STRING),	"a2i_ASN1_STRING"},
+{ERR_FUNC(ASN1_F_APPEND_EXP),	"APPEND_EXP"},
+{ERR_FUNC(ASN1_F_ASN1_BIT_STRING_SET_BIT),	"ASN1_BIT_STRING_set_bit"},
+{ERR_FUNC(ASN1_F_ASN1_CB),	"ASN1_CB"},
+{ERR_FUNC(ASN1_F_ASN1_CHECK_TLEN),	"ASN1_CHECK_TLEN"},
+{ERR_FUNC(ASN1_F_ASN1_COLLATE_PRIMITIVE),	"ASN1_COLLATE_PRIMITIVE"},
+{ERR_FUNC(ASN1_F_ASN1_COLLECT),	"ASN1_COLLECT"},
+{ERR_FUNC(ASN1_F_ASN1_D2I_EX_PRIMITIVE),	"ASN1_D2I_EX_PRIMITIVE"},
+{ERR_FUNC(ASN1_F_ASN1_D2I_FP),	"ASN1_d2i_fp"},
+{ERR_FUNC(ASN1_F_ASN1_D2I_READ_BIO),	"ASN1_D2I_READ_BIO"},
+{ERR_FUNC(ASN1_F_ASN1_DIGEST),	"ASN1_digest"},
+{ERR_FUNC(ASN1_F_ASN1_DO_ADB),	"ASN1_DO_ADB"},
+{ERR_FUNC(ASN1_F_ASN1_DUP),	"ASN1_dup"},
+{ERR_FUNC(ASN1_F_ASN1_ENUMERATED_SET),	"ASN1_ENUMERATED_set"},
+{ERR_FUNC(ASN1_F_ASN1_ENUMERATED_TO_BN),	"ASN1_ENUMERATED_to_BN"},
+{ERR_FUNC(ASN1_F_ASN1_EX_C2I),	"ASN1_EX_C2I"},
+{ERR_FUNC(ASN1_F_ASN1_FIND_END),	"ASN1_FIND_END"},
+{ERR_FUNC(ASN1_F_ASN1_GENERALIZEDTIME_SET),	"ASN1_GENERALIZEDTIME_set"},
+{ERR_FUNC(ASN1_F_ASN1_GENERATE_V3),	"ASN1_generate_v3"},
+{ERR_FUNC(ASN1_F_ASN1_GET_OBJECT),	"ASN1_get_object"},
+{ERR_FUNC(ASN1_F_ASN1_HEADER_NEW),	"ASN1_HEADER_new"},
+{ERR_FUNC(ASN1_F_ASN1_I2D_BIO),	"ASN1_i2d_bio"},
+{ERR_FUNC(ASN1_F_ASN1_I2D_FP),	"ASN1_i2d_fp"},
+{ERR_FUNC(ASN1_F_ASN1_INTEGER_SET),	"ASN1_INTEGER_set"},
+{ERR_FUNC(ASN1_F_ASN1_INTEGER_TO_BN),	"ASN1_INTEGER_to_BN"},
+{ERR_FUNC(ASN1_F_ASN1_ITEM_D2I_FP),	"ASN1_item_d2i_fp"},
+{ERR_FUNC(ASN1_F_ASN1_ITEM_DUP),	"ASN1_item_dup"},
+{ERR_FUNC(ASN1_F_ASN1_ITEM_EX_COMBINE_NEW),	"ASN1_ITEM_EX_COMBINE_NEW"},
+{ERR_FUNC(ASN1_F_ASN1_ITEM_EX_D2I),	"ASN1_ITEM_EX_D2I"},
+{ERR_FUNC(ASN1_F_ASN1_ITEM_I2D_BIO),	"ASN1_item_i2d_bio"},
+{ERR_FUNC(ASN1_F_ASN1_ITEM_I2D_FP),	"ASN1_item_i2d_fp"},
+{ERR_FUNC(ASN1_F_ASN1_ITEM_PACK),	"ASN1_item_pack"},
+{ERR_FUNC(ASN1_F_ASN1_ITEM_SIGN),	"ASN1_item_sign"},
+{ERR_FUNC(ASN1_F_ASN1_ITEM_UNPACK),	"ASN1_item_unpack"},
+{ERR_FUNC(ASN1_F_ASN1_ITEM_VERIFY),	"ASN1_item_verify"},
+{ERR_FUNC(ASN1_F_ASN1_MBSTRING_NCOPY),	"ASN1_mbstring_ncopy"},
+{ERR_FUNC(ASN1_F_ASN1_OBJECT_NEW),	"ASN1_OBJECT_new"},
+{ERR_FUNC(ASN1_F_ASN1_OUTPUT_DATA),	"ASN1_OUTPUT_DATA"},
+{ERR_FUNC(ASN1_F_ASN1_PACK_STRING),	"ASN1_pack_string"},
+{ERR_FUNC(ASN1_F_ASN1_PCTX_NEW),	"ASN1_PCTX_NEW"},
+{ERR_FUNC(ASN1_F_ASN1_PKCS5_PBE_SET),	"ASN1_PKCS5_PBE_SET"},
+{ERR_FUNC(ASN1_F_ASN1_SEQ_PACK),	"ASN1_seq_pack"},
+{ERR_FUNC(ASN1_F_ASN1_SEQ_UNPACK),	"ASN1_seq_unpack"},
+{ERR_FUNC(ASN1_F_ASN1_SIGN),	"ASN1_sign"},
+{ERR_FUNC(ASN1_F_ASN1_STR2TYPE),	"ASN1_STR2TYPE"},
+{ERR_FUNC(ASN1_F_ASN1_STRING_SET),	"ASN1_STRING_set"},
+{ERR_FUNC(ASN1_F_ASN1_STRING_TABLE_ADD),	"ASN1_STRING_TABLE_add"},
+{ERR_FUNC(ASN1_F_ASN1_STRING_TYPE_NEW),	"ASN1_STRING_type_new"},
+{ERR_FUNC(ASN1_F_ASN1_TEMPLATE_EX_D2I),	"ASN1_TEMPLATE_EX_D2I"},
+{ERR_FUNC(ASN1_F_ASN1_TEMPLATE_NEW),	"ASN1_TEMPLATE_NEW"},
+{ERR_FUNC(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I),	"ASN1_TEMPLATE_NOEXP_D2I"},
+{ERR_FUNC(ASN1_F_ASN1_TIME_SET),	"ASN1_TIME_set"},
+{ERR_FUNC(ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING),	"ASN1_TYPE_get_int_octetstring"},
+{ERR_FUNC(ASN1_F_ASN1_TYPE_GET_OCTETSTRING),	"ASN1_TYPE_get_octetstring"},
+{ERR_FUNC(ASN1_F_ASN1_UNPACK_STRING),	"ASN1_unpack_string"},
+{ERR_FUNC(ASN1_F_ASN1_UTCTIME_SET),	"ASN1_UTCTIME_set"},
+{ERR_FUNC(ASN1_F_ASN1_VERIFY),	"ASN1_verify"},
+{ERR_FUNC(ASN1_F_B64_READ_ASN1),	"B64_READ_ASN1"},
+{ERR_FUNC(ASN1_F_B64_WRITE_ASN1),	"B64_WRITE_ASN1"},
+{ERR_FUNC(ASN1_F_BITSTR_CB),	"BITSTR_CB"},
+{ERR_FUNC(ASN1_F_BN_TO_ASN1_ENUMERATED),	"BN_to_ASN1_ENUMERATED"},
+{ERR_FUNC(ASN1_F_BN_TO_ASN1_INTEGER),	"BN_to_ASN1_INTEGER"},
+{ERR_FUNC(ASN1_F_C2I_ASN1_BIT_STRING),	"c2i_ASN1_BIT_STRING"},
+{ERR_FUNC(ASN1_F_C2I_ASN1_INTEGER),	"c2i_ASN1_INTEGER"},
+{ERR_FUNC(ASN1_F_C2I_ASN1_OBJECT),	"c2i_ASN1_OBJECT"},
+{ERR_FUNC(ASN1_F_COLLECT_DATA),	"COLLECT_DATA"},
+{ERR_FUNC(ASN1_F_D2I_ASN1_BIT_STRING),	"D2I_ASN1_BIT_STRING"},
+{ERR_FUNC(ASN1_F_D2I_ASN1_BOOLEAN),	"d2i_ASN1_BOOLEAN"},
+{ERR_FUNC(ASN1_F_D2I_ASN1_BYTES),	"d2i_ASN1_bytes"},
+{ERR_FUNC(ASN1_F_D2I_ASN1_GENERALIZEDTIME),	"D2I_ASN1_GENERALIZEDTIME"},
+{ERR_FUNC(ASN1_F_D2I_ASN1_HEADER),	"d2i_ASN1_HEADER"},
+{ERR_FUNC(ASN1_F_D2I_ASN1_INTEGER),	"D2I_ASN1_INTEGER"},
+{ERR_FUNC(ASN1_F_D2I_ASN1_OBJECT),	"d2i_ASN1_OBJECT"},
+{ERR_FUNC(ASN1_F_D2I_ASN1_SET),	"d2i_ASN1_SET"},
+{ERR_FUNC(ASN1_F_D2I_ASN1_TYPE_BYTES),	"d2i_ASN1_type_bytes"},
+{ERR_FUNC(ASN1_F_D2I_ASN1_UINTEGER),	"d2i_ASN1_UINTEGER"},
+{ERR_FUNC(ASN1_F_D2I_ASN1_UTCTIME),	"D2I_ASN1_UTCTIME"},
+{ERR_FUNC(ASN1_F_D2I_NETSCAPE_RSA),	"d2i_Netscape_RSA"},
+{ERR_FUNC(ASN1_F_D2I_NETSCAPE_RSA_2),	"D2I_NETSCAPE_RSA_2"},
+{ERR_FUNC(ASN1_F_D2I_PRIVATEKEY),	"d2i_PrivateKey"},
+{ERR_FUNC(ASN1_F_D2I_PUBLICKEY),	"d2i_PublicKey"},
+{ERR_FUNC(ASN1_F_D2I_RSA_NET),	"d2i_RSA_NET"},
+{ERR_FUNC(ASN1_F_D2I_RSA_NET_2),	"D2I_RSA_NET_2"},
+{ERR_FUNC(ASN1_F_D2I_X509),	"D2I_X509"},
+{ERR_FUNC(ASN1_F_D2I_X509_CINF),	"D2I_X509_CINF"},
+{ERR_FUNC(ASN1_F_D2I_X509_PKEY),	"d2i_X509_PKEY"},
+{ERR_FUNC(ASN1_F_I2D_ASN1_SET),	"i2d_ASN1_SET"},
+{ERR_FUNC(ASN1_F_I2D_ASN1_TIME),	"I2D_ASN1_TIME"},
+{ERR_FUNC(ASN1_F_I2D_DSA_PUBKEY),	"i2d_DSA_PUBKEY"},
+{ERR_FUNC(ASN1_F_I2D_EC_PUBKEY),	"i2d_EC_PUBKEY"},
+{ERR_FUNC(ASN1_F_I2D_PRIVATEKEY),	"i2d_PrivateKey"},
+{ERR_FUNC(ASN1_F_I2D_PUBLICKEY),	"i2d_PublicKey"},
+{ERR_FUNC(ASN1_F_I2D_RSA_NET),	"i2d_RSA_NET"},
+{ERR_FUNC(ASN1_F_I2D_RSA_PUBKEY),	"i2d_RSA_PUBKEY"},
+{ERR_FUNC(ASN1_F_LONG_C2I),	"LONG_C2I"},
+{ERR_FUNC(ASN1_F_OID_MODULE_INIT),	"OID_MODULE_INIT"},
+{ERR_FUNC(ASN1_F_PARSE_TAGGING),	"PARSE_TAGGING"},
+{ERR_FUNC(ASN1_F_PKCS5_PBE2_SET),	"PKCS5_pbe2_set"},
+{ERR_FUNC(ASN1_F_PKCS5_PBE_SET),	"PKCS5_pbe_set"},
+{ERR_FUNC(ASN1_F_SMIME_READ_ASN1),	"SMIME_read_ASN1"},
+{ERR_FUNC(ASN1_F_SMIME_TEXT),	"SMIME_text"},
+{ERR_FUNC(ASN1_F_X509_CINF_NEW),	"X509_CINF_NEW"},
+{ERR_FUNC(ASN1_F_X509_CRL_ADD0_REVOKED),	"X509_CRL_add0_revoked"},
+{ERR_FUNC(ASN1_F_X509_INFO_NEW),	"X509_INFO_new"},
+{ERR_FUNC(ASN1_F_X509_NAME_ENCODE),	"X509_NAME_ENCODE"},
+{ERR_FUNC(ASN1_F_X509_NAME_EX_D2I),	"X509_NAME_EX_D2I"},
+{ERR_FUNC(ASN1_F_X509_NAME_EX_NEW),	"X509_NAME_EX_NEW"},
+{ERR_FUNC(ASN1_F_X509_NEW),	"X509_NEW"},
+{ERR_FUNC(ASN1_F_X509_PKEY_NEW),	"X509_PKEY_new"},
+{0,NULL}
+	};
+
+static ERR_STRING_DATA ASN1_str_reasons[]=
+	{
+{ERR_REASON(ASN1_R_ADDING_OBJECT)        ,"adding object"},
+{ERR_REASON(ASN1_R_ASN1_PARSE_ERROR)     ,"asn1 parse error"},
+{ERR_REASON(ASN1_R_ASN1_SIG_PARSE_ERROR) ,"asn1 sig parse error"},
+{ERR_REASON(ASN1_R_AUX_ERROR)            ,"aux error"},
+{ERR_REASON(ASN1_R_BAD_CLASS)            ,"bad class"},
+{ERR_REASON(ASN1_R_BAD_OBJECT_HEADER)    ,"bad object header"},
+{ERR_REASON(ASN1_R_BAD_PASSWORD_READ)    ,"bad password read"},
+{ERR_REASON(ASN1_R_BAD_TAG)              ,"bad tag"},
+{ERR_REASON(ASN1_R_BMPSTRING_IS_WRONG_LENGTH),"bmpstring is wrong length"},
+{ERR_REASON(ASN1_R_BN_LIB)               ,"bn lib"},
+{ERR_REASON(ASN1_R_BOOLEAN_IS_WRONG_LENGTH),"boolean is wrong length"},
+{ERR_REASON(ASN1_R_BUFFER_TOO_SMALL)     ,"buffer too small"},
+{ERR_REASON(ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER),"cipher has no object identifier"},
+{ERR_REASON(ASN1_R_DATA_IS_WRONG)        ,"data is wrong"},
+{ERR_REASON(ASN1_R_DECODE_ERROR)         ,"decode error"},
+{ERR_REASON(ASN1_R_DECODING_ERROR)       ,"decoding error"},
+{ERR_REASON(ASN1_R_DEPTH_EXCEEDED)       ,"depth exceeded"},
+{ERR_REASON(ASN1_R_ENCODE_ERROR)         ,"encode error"},
+{ERR_REASON(ASN1_R_ERROR_GETTING_TIME)   ,"error getting time"},
+{ERR_REASON(ASN1_R_ERROR_LOADING_SECTION),"error loading section"},
+{ERR_REASON(ASN1_R_ERROR_PARSING_SET_ELEMENT),"error parsing set element"},
+{ERR_REASON(ASN1_R_ERROR_SETTING_CIPHER_PARAMS),"error setting cipher params"},
+{ERR_REASON(ASN1_R_EXPECTING_AN_INTEGER) ,"expecting an integer"},
+{ERR_REASON(ASN1_R_EXPECTING_AN_OBJECT)  ,"expecting an object"},
+{ERR_REASON(ASN1_R_EXPECTING_A_BOOLEAN)  ,"expecting a boolean"},
+{ERR_REASON(ASN1_R_EXPECTING_A_TIME)     ,"expecting a time"},
+{ERR_REASON(ASN1_R_EXPLICIT_LENGTH_MISMATCH),"explicit length mismatch"},
+{ERR_REASON(ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED),"explicit tag not constructed"},
+{ERR_REASON(ASN1_R_FIELD_MISSING)        ,"field missing"},
+{ERR_REASON(ASN1_R_FIRST_NUM_TOO_LARGE)  ,"first num too large"},
+{ERR_REASON(ASN1_R_HEADER_TOO_LONG)      ,"header too long"},
+{ERR_REASON(ASN1_R_ILLEGAL_BITSTRING_FORMAT),"illegal bitstring format"},
+{ERR_REASON(ASN1_R_ILLEGAL_BOOLEAN)      ,"illegal boolean"},
+{ERR_REASON(ASN1_R_ILLEGAL_CHARACTERS)   ,"illegal characters"},
+{ERR_REASON(ASN1_R_ILLEGAL_FORMAT)       ,"illegal format"},
+{ERR_REASON(ASN1_R_ILLEGAL_HEX)          ,"illegal hex"},
+{ERR_REASON(ASN1_R_ILLEGAL_IMPLICIT_TAG) ,"illegal implicit tag"},
+{ERR_REASON(ASN1_R_ILLEGAL_INTEGER)      ,"illegal integer"},
+{ERR_REASON(ASN1_R_ILLEGAL_NESTED_TAGGING),"illegal nested tagging"},
+{ERR_REASON(ASN1_R_ILLEGAL_NULL)         ,"illegal null"},
+{ERR_REASON(ASN1_R_ILLEGAL_NULL_VALUE)   ,"illegal null value"},
+{ERR_REASON(ASN1_R_ILLEGAL_OBJECT)       ,"illegal object"},
+{ERR_REASON(ASN1_R_ILLEGAL_OPTIONAL_ANY) ,"illegal optional any"},
+{ERR_REASON(ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE),"illegal options on item template"},
+{ERR_REASON(ASN1_R_ILLEGAL_TAGGED_ANY)   ,"illegal tagged any"},
+{ERR_REASON(ASN1_R_ILLEGAL_TIME_VALUE)   ,"illegal time value"},
+{ERR_REASON(ASN1_R_INTEGER_NOT_ASCII_FORMAT),"integer not ascii format"},
+{ERR_REASON(ASN1_R_INTEGER_TOO_LARGE_FOR_LONG),"integer too large for long"},
+{ERR_REASON(ASN1_R_INVALID_BMPSTRING_LENGTH),"invalid bmpstring length"},
+{ERR_REASON(ASN1_R_INVALID_DIGIT)        ,"invalid digit"},
+{ERR_REASON(ASN1_R_INVALID_MIME_TYPE)    ,"invalid mime type"},
+{ERR_REASON(ASN1_R_INVALID_MODIFIER)     ,"invalid modifier"},
+{ERR_REASON(ASN1_R_INVALID_NUMBER)       ,"invalid number"},
+{ERR_REASON(ASN1_R_INVALID_SEPARATOR)    ,"invalid separator"},
+{ERR_REASON(ASN1_R_INVALID_TIME_FORMAT)  ,"invalid time format"},
+{ERR_REASON(ASN1_R_INVALID_UNIVERSALSTRING_LENGTH),"invalid universalstring length"},
+{ERR_REASON(ASN1_R_INVALID_UTF8STRING)   ,"invalid utf8string"},
+{ERR_REASON(ASN1_R_IV_TOO_LARGE)         ,"iv too large"},
+{ERR_REASON(ASN1_R_LENGTH_ERROR)         ,"length error"},
+{ERR_REASON(ASN1_R_LIST_ERROR)           ,"list error"},
+{ERR_REASON(ASN1_R_MIME_NO_CONTENT_TYPE) ,"mime no content type"},
+{ERR_REASON(ASN1_R_MIME_PARSE_ERROR)     ,"mime parse error"},
+{ERR_REASON(ASN1_R_MIME_SIG_PARSE_ERROR) ,"mime sig parse error"},
+{ERR_REASON(ASN1_R_MISSING_EOC)          ,"missing eoc"},
+{ERR_REASON(ASN1_R_MISSING_SECOND_NUMBER),"missing second number"},
+{ERR_REASON(ASN1_R_MISSING_VALUE)        ,"missing value"},
+{ERR_REASON(ASN1_R_MSTRING_NOT_UNIVERSAL),"mstring not universal"},
+{ERR_REASON(ASN1_R_MSTRING_WRONG_TAG)    ,"mstring wrong tag"},
+{ERR_REASON(ASN1_R_NESTED_ASN1_STRING)   ,"nested asn1 string"},
+{ERR_REASON(ASN1_R_NON_HEX_CHARACTERS)   ,"non hex characters"},
+{ERR_REASON(ASN1_R_NOT_ASCII_FORMAT)     ,"not ascii format"},
+{ERR_REASON(ASN1_R_NOT_ENOUGH_DATA)      ,"not enough data"},
+{ERR_REASON(ASN1_R_NO_CONTENT_TYPE)      ,"no content type"},
+{ERR_REASON(ASN1_R_NO_MATCHING_CHOICE_TYPE),"no matching choice type"},
+{ERR_REASON(ASN1_R_NO_MULTIPART_BODY_FAILURE),"no multipart body failure"},
+{ERR_REASON(ASN1_R_NO_MULTIPART_BOUNDARY),"no multipart boundary"},
+{ERR_REASON(ASN1_R_NO_SIG_CONTENT_TYPE)  ,"no sig content type"},
+{ERR_REASON(ASN1_R_NULL_IS_WRONG_LENGTH) ,"null is wrong length"},
+{ERR_REASON(ASN1_R_OBJECT_NOT_ASCII_FORMAT),"object not ascii format"},
+{ERR_REASON(ASN1_R_ODD_NUMBER_OF_CHARS)  ,"odd number of chars"},
+{ERR_REASON(ASN1_R_PRIVATE_KEY_HEADER_MISSING),"private key header missing"},
+{ERR_REASON(ASN1_R_SECOND_NUMBER_TOO_LARGE),"second number too large"},
+{ERR_REASON(ASN1_R_SEQUENCE_LENGTH_MISMATCH),"sequence length mismatch"},
+{ERR_REASON(ASN1_R_SEQUENCE_NOT_CONSTRUCTED),"sequence not constructed"},
+{ERR_REASON(ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG),"sequence or set needs config"},
+{ERR_REASON(ASN1_R_SHORT_LINE)           ,"short line"},
+{ERR_REASON(ASN1_R_SIG_INVALID_MIME_TYPE),"sig invalid mime type"},
+{ERR_REASON(ASN1_R_STREAMING_NOT_SUPPORTED),"streaming not supported"},
+{ERR_REASON(ASN1_R_STRING_TOO_LONG)      ,"string too long"},
+{ERR_REASON(ASN1_R_STRING_TOO_SHORT)     ,"string too short"},
+{ERR_REASON(ASN1_R_TAG_VALUE_TOO_HIGH)   ,"tag value too high"},
+{ERR_REASON(ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD),"the asn1 object identifier is not known for this md"},
+{ERR_REASON(ASN1_R_TIME_NOT_ASCII_FORMAT),"time not ascii format"},
+{ERR_REASON(ASN1_R_TOO_LONG)             ,"too long"},
+{ERR_REASON(ASN1_R_TYPE_NOT_CONSTRUCTED) ,"type not constructed"},
+{ERR_REASON(ASN1_R_UNABLE_TO_DECODE_RSA_KEY),"unable to decode rsa key"},
+{ERR_REASON(ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY),"unable to decode rsa private key"},
+{ERR_REASON(ASN1_R_UNEXPECTED_EOC)       ,"unexpected eoc"},
+{ERR_REASON(ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH),"universalstring is wrong length"},
+{ERR_REASON(ASN1_R_UNKNOWN_FORMAT)       ,"unknown format"},
+{ERR_REASON(ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM),"unknown message digest algorithm"},
+{ERR_REASON(ASN1_R_UNKNOWN_OBJECT_TYPE)  ,"unknown object type"},
+{ERR_REASON(ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE),"unknown public key type"},
+{ERR_REASON(ASN1_R_UNKNOWN_TAG)          ,"unknown tag"},
+{ERR_REASON(ASN1_R_UNKOWN_FORMAT)        ,"unkown format"},
+{ERR_REASON(ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE),"unsupported any defined by type"},
+{ERR_REASON(ASN1_R_UNSUPPORTED_CIPHER)   ,"unsupported cipher"},
+{ERR_REASON(ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM),"unsupported encryption algorithm"},
+{ERR_REASON(ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE),"unsupported public key type"},
+{ERR_REASON(ASN1_R_UNSUPPORTED_TYPE)     ,"unsupported type"},
+{ERR_REASON(ASN1_R_WRONG_TAG)            ,"wrong tag"},
+{ERR_REASON(ASN1_R_WRONG_TYPE)           ,"wrong type"},
+{0,NULL}
+	};
+
+#endif
+
+void ERR_load_ASN1_strings(void)
+	{
+#ifndef OPENSSL_NO_ERR
+
+	if (ERR_func_error_string(ASN1_str_functs[0].error) == NULL)
+		{
+		ERR_load_strings(0,ASN1_str_functs);
+		ERR_load_strings(0,ASN1_str_reasons);
+		}
+#endif
+	}

Modified: openssl/branches/upstream/current/crypto/asn1/tasn_dec.c
===================================================================
--- openssl/branches/upstream/current/crypto/asn1/tasn_dec.c	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/crypto/asn1/tasn_dec.c	2009-05-16 15:25:35 UTC (rev 372)
@@ -1,5 +1,5 @@
 /* tasn_dec.c */
-/* Written by Dr Stephen N Henson (shenson at bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve at openssl.org) for the OpenSSL
  * project 2000.
  */
 /* ====================================================================
@@ -69,7 +69,7 @@
 static int asn1_find_end(const unsigned char **in, long len, char inf);
 
 static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len,
-				char inf, int tag, int aclass);
+			char inf, int tag, int aclass, int depth);
 
 static int collect_data(BUF_MEM *buf, const unsigned char **p, long plen);
 
@@ -611,7 +611,6 @@
 
 	err:
 	ASN1_template_free(val, tt);
-	*val = NULL;
 	return 0;
 	}
 
@@ -758,7 +757,6 @@
 
 	err:
 	ASN1_template_free(val, tt);
-	*val = NULL;
 	return 0;
 	}
 
@@ -878,7 +876,7 @@
 		 * internally irrespective of the type. So instead just check
 		 * for UNIVERSAL class and ignore the tag.
 		 */
-		if (!asn1_collect(&buf, &p, plen, inf, -1, V_ASN1_UNIVERSAL))
+		if (!asn1_collect(&buf, &p, plen, inf, -1, V_ASN1_UNIVERSAL, 0))
 			{
 			free_cont = 1;
 			goto err;
@@ -944,7 +942,7 @@
 		if (utype != typ->type)
 			ASN1_TYPE_set(typ, utype, NULL);
 		opval = pval;
-		pval = (ASN1_VALUE **)&typ->value.ptr;
+		pval = &typ->value.asn1_value;
 		}
 	switch(utype)
 		{
@@ -1012,6 +1010,18 @@
 		case V_ASN1_SET:
 		case V_ASN1_SEQUENCE:
 		default:
+		if (utype == V_ASN1_BMPSTRING && (len & 1))
+			{
+			ASN1err(ASN1_F_ASN1_EX_C2I,
+					ASN1_R_BMPSTRING_IS_WRONG_LENGTH);
+			goto err;
+			}
+		if (utype == V_ASN1_UNIVERSALSTRING && (len & 3))
+			{
+			ASN1err(ASN1_F_ASN1_EX_C2I,
+					ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH);
+			goto err;
+			}
 		/* All based on ASN1_STRING and handled the same */
 		if (!*pval)
 			{
@@ -1128,8 +1138,18 @@
  * if it is indefinite length.
  */
 
+#ifndef ASN1_MAX_STRING_NEST
+/* This determines how many levels of recursion are permitted in ASN1
+ * string types. If it is not limited stack overflows can occur. If set
+ * to zero no recursion is allowed at all. Although zero should be adequate
+ * examples exist that require a value of 1. So 5 should be more than enough.
+ */
+#define ASN1_MAX_STRING_NEST 5
+#endif
+
+
 static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len,
-				char inf, int tag, int aclass)
+			char inf, int tag, int aclass, int depth)
 	{
 	const unsigned char *p, *q;
 	long plen;
@@ -1171,13 +1191,15 @@
 		/* If indefinite length constructed update max length */
 		if (cst)
 			{
-#ifdef OPENSSL_ALLOW_NESTED_ASN1_STRINGS
-			if (!asn1_collect(buf, &p, plen, ininf, tag, aclass))
+			if (depth >= ASN1_MAX_STRING_NEST)
+				{
+				ASN1err(ASN1_F_ASN1_COLLECT,
+					ASN1_R_NESTED_ASN1_STRING);
 				return 0;
-#else
-			ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_NESTED_ASN1_STRING);
-			return 0;
-#endif
+				}
+			if (!asn1_collect(buf, &p, plen, ininf, tag, aclass,
+						depth + 1))
+				return 0;
 			}
 		else if (plen && !collect_data(buf, &p, plen))
 			return 0;

Modified: openssl/branches/upstream/current/crypto/bio/bio.h
===================================================================
--- openssl/branches/upstream/current/crypto/bio/bio.h	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/crypto/bio/bio.h	2009-05-16 15:25:35 UTC (rev 372)
@@ -95,6 +95,7 @@
 #define BIO_TYPE_BIO		(19|0x0400)		/* (half a) BIO pair */
 #define BIO_TYPE_LINEBUFFER	(20|0x0200)		/* filter */
 #define BIO_TYPE_DGRAM		(21|0x0400|0x0100)
+#define BIO_TYPE_COMP 		(23|0x0200)		/* filter */
 
 #define BIO_TYPE_DESCRIPTOR	0x0100	/* socket, fd, connect or accept */
 #define BIO_TYPE_FILTER		0x0200

Modified: openssl/branches/upstream/current/crypto/bn/bn_mont.c
===================================================================
--- openssl/branches/upstream/current/crypto/bn/bn_mont.c	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/crypto/bn/bn_mont.c	2009-05-16 15:25:35 UTC (rev 372)
@@ -122,12 +122,51 @@
 
 #define MONT_WORD /* use the faster word-based algorithm */
 
+#if defined(MONT_WORD) && defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2<=32)
+/* This condition means we have a specific non-default build:
+ * In the 0.9.8 branch, OPENSSL_BN_ASM_MONT is normally not set for any
+ * BN_BITS2<=32 platform; an explicit "enable-montasm" is required.
+ * I.e., if we are here, the user intentionally deviates from the
+ * normal stable build to get better Montgomery performance from
+ * the 0.9.9-dev backport.
+ *
+ * In this case only, we also enable BN_from_montgomery_word()
+ * (another non-stable feature from 0.9.9-dev).
+ */
+#define MONT_FROM_WORD___NON_DEFAULT_0_9_8_BUILD
+#endif
+
+#ifdef MONT_FROM_WORD___NON_DEFAULT_0_9_8_BUILD
+static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont);
+#endif
+
+
+
 int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
 			  BN_MONT_CTX *mont, BN_CTX *ctx)
 	{
 	BIGNUM *tmp;
 	int ret=0;
+#if defined(OPENSSL_BN_ASM_MONT) && defined(MONT_WORD)
+	int num = mont->N.top;
 
+	if (num>1 && a->top==num && b->top==num)
+		{
+		if (bn_wexpand(r,num) == NULL) return(0);
+#if 0 /* for OpenSSL 0.9.9 mont->n0 */
+		if (bn_mul_mont(r->d,a->d,b->d,mont->N.d,mont->n0,num))
+#else
+		if (bn_mul_mont(r->d,a->d,b->d,mont->N.d,&mont->n0,num))
+#endif
+			{
+			r->neg = a->neg^b->neg;
+			r->top = num;
+			bn_correct_top(r);
+			return(1);
+			}
+		}
+#endif
+
 	BN_CTX_start(ctx);
 	tmp = BN_CTX_get(ctx);
 	if (tmp == NULL) goto err;
@@ -142,7 +181,11 @@
 		if (!BN_mul(tmp,a,b,ctx)) goto err;
 		}
 	/* reduce from aRR to aR */
+#ifdef MONT_FROM_WORD___NON_DEFAULT_0_9_8_BUILD
+	if (!BN_from_montgomery_word(r,tmp,mont)) goto err;
+#else
 	if (!BN_from_montgomery(r,tmp,mont,ctx)) goto err;
+#endif
 	bn_check_top(r);
 	ret=1;
 err:
@@ -150,11 +193,155 @@
 	return(ret);
 	}
 
+#ifdef MONT_FROM_WORD___NON_DEFAULT_0_9_8_BUILD
+static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
+	{
+	BIGNUM *n;
+	BN_ULONG *ap,*np,*rp,n0,v,*nrp;
+	int al,nl,max,i,x,ri;
+
+	n= &(mont->N);
+	/* mont->ri is the size of mont->N in bits (rounded up
+	   to the word size) */
+	al=ri=mont->ri/BN_BITS2;
+
+	nl=n->top;
+	if ((al == 0) || (nl == 0)) { ret->top=0; return(1); }
+
+	max=(nl+al+1); /* allow for overflow (no?) XXX */
+	if (bn_wexpand(r,max) == NULL) return(0);
+
+	r->neg^=n->neg;
+	np=n->d;
+	rp=r->d;
+	nrp= &(r->d[nl]);
+
+	/* clear the top words of T */
+	for (i=r->top; i<max; i++) /* memset? XXX */
+		r->d[i]=0;
+
+	r->top=max;
+#if 0 /* for OpenSSL 0.9.9 mont->n0 */
+	n0=mont->n0[0];
+#else
+	n0=mont->n0;
+#endif
+
+#ifdef BN_COUNT
+	fprintf(stderr,"word BN_from_montgomery_word %d * %d\n",nl,nl);
+#endif
+	for (i=0; i<nl; i++)
+		{
+#ifdef __TANDEM
+                {
+                   long long t1;
+                   long long t2;
+                   long long t3;
+                   t1 = rp[0] * (n0 & 0177777);
+                   t2 = 037777600000l;
+                   t2 = n0 & t2;
+                   t3 = rp[0] & 0177777;
+                   t2 = (t3 * t2) & BN_MASK2;
+                   t1 = t1 + t2;
+                   v=bn_mul_add_words(rp,np,nl,(BN_ULONG) t1);
+                }
+#else
+		v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2);
+#endif
+		nrp++;
+		rp++;
+		if (((nrp[-1]+=v)&BN_MASK2) >= v)
+			continue;
+		else
+			{
+			if (((++nrp[0])&BN_MASK2) != 0) continue;
+			if (((++nrp[1])&BN_MASK2) != 0) continue;
+			for (x=2; (((++nrp[x])&BN_MASK2) == 0); x++) ;
+			}
+		}
+	bn_correct_top(r);
+
+	/* mont->ri will be a multiple of the word size and below code
+	 * is kind of BN_rshift(ret,r,mont->ri) equivalent */
+	if (r->top <= ri)
+		{
+		ret->top=0;
+		return(1);
+		}
+	al=r->top-ri;
+
+	if (bn_wexpand(ret,ri) == NULL) return(0);
+	x=0-(((al-ri)>>(sizeof(al)*8-1))&1);
+	ret->top=x=(ri&~x)|(al&x);	/* min(ri,al) */
+	ret->neg=r->neg;
+
+	rp=ret->d;
+	ap=&(r->d[ri]);
+
+	{
+	size_t m1,m2;
+
+	v=bn_sub_words(rp,ap,np,ri);
+	/* this ----------------^^ works even in al<ri case
+	 * thanks to zealous zeroing of top of the vector in the
+	 * beginning. */
+
+	/* if (al==ri && !v) || al>ri) nrp=rp; else nrp=ap; */
+	/* in other words if subtraction result is real, then
+	 * trick unconditional memcpy below to perform in-place
+	 * "refresh" instead of actual copy. */
+	m1=0-(size_t)(((al-ri)>>(sizeof(al)*8-1))&1);	/* al<ri */
+	m2=0-(size_t)(((ri-al)>>(sizeof(al)*8-1))&1);	/* al>ri */
+	m1|=m2;			/* (al!=ri) */
+	m1|=(0-(size_t)v);	/* (al!=ri || v) */
+	m1&=~m2;		/* (al!=ri || v) && !al>ri */
+	nrp=(BN_ULONG *)(((size_t)rp&~m1)|((size_t)ap&m1));
+	}
+
+	/* 'i<ri' is chosen to eliminate dependency on input data, even
+	 * though it results in redundant copy in al<ri case. */
+	for (i=0,ri-=4; i<ri; i+=4)
+		{
+		BN_ULONG t1,t2,t3,t4;
+		
+		t1=nrp[i+0];
+		t2=nrp[i+1];
+		t3=nrp[i+2];	ap[i+0]=0;
+		t4=nrp[i+3];	ap[i+1]=0;
+		rp[i+0]=t1;	ap[i+2]=0;
+		rp[i+1]=t2;	ap[i+3]=0;
+		rp[i+2]=t3;
+		rp[i+3]=t4;
+		}
+	for (ri+=4; i<ri; i++)
+		rp[i]=nrp[i], ap[i]=0;
+	bn_correct_top(r);
+	bn_correct_top(ret);
+	bn_check_top(ret);
+
+	return(1);
+	}
+
 int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont,
 	     BN_CTX *ctx)
 	{
 	int retn=0;
+	BIGNUM *t;
 
+	BN_CTX_start(ctx);
+	if ((t = BN_CTX_get(ctx)) && BN_copy(t,a))
+		retn = BN_from_montgomery_word(ret,t,mont);
+	BN_CTX_end(ctx);
+	return retn;
+	}
+
+#else /* !MONT_FROM_WORD___NON_DEFAULT_0_9_8_BUILD */
+
+int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont,
+	     BN_CTX *ctx)
+	{
+	int retn=0;
+
 #ifdef MONT_WORD
 	BIGNUM *n,*r;
 	BN_ULONG *ap,*np,*rp,n0,v,*nrp;
@@ -342,6 +529,7 @@
 	BN_CTX_end(ctx);
 	return(retn);
 	}
+#endif /* MONT_FROM_WORD___NON_DEFAULT_0_9_8_BUILD */
 
 BN_MONT_CTX *BN_MONT_CTX_new(void)
 	{
@@ -361,6 +549,11 @@
 	BN_init(&(ctx->RR));
 	BN_init(&(ctx->N));
 	BN_init(&(ctx->Ni));
+#if 0 /* for OpenSSL 0.9.9 mont->n0 */
+	ctx->n0[0] = ctx->n0[1] = 0;
+#else
+	ctx->n0 = 0;
+#endif
 	ctx->flags=0;
 	}
 
@@ -394,14 +587,51 @@
 
 		mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2;
 		BN_zero(R);
+#if 0 /* for OpenSSL 0.9.9 mont->n0, would be "#if defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2<=32)",
+         only certain BN_BITS2<=32 platforms actually need this */
+		if (!(BN_set_bit(R,2*BN_BITS2))) goto err;	/* R */
+#else
 		if (!(BN_set_bit(R,BN_BITS2))) goto err;	/* R */
+#endif
 
 		buf[0]=mod->d[0]; /* tmod = N mod word size */
 		buf[1]=0;
+
+		BN_init(&tmod);
 		tmod.d=buf;
 		tmod.top = buf[0] != 0 ? 1 : 0;
 		tmod.dmax=2;
 		tmod.neg=0;
+
+#if 0 /* for OpenSSL 0.9.9 mont->n0, would be "#if defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2<=32)";
+         only certain BN_BITS2<=32 platforms actually need this */
+								tmod.top=0;
+		if ((buf[0] = mod->d[0]))			tmod.top=1;
+		if ((buf[1] = mod->top>1 ? mod->d[1] : 0))	tmod.top=2;
+
+		if ((BN_mod_inverse(Ri,R,&tmod,ctx)) == NULL)
+			goto err;
+		if (!BN_lshift(Ri,Ri,2*BN_BITS2)) goto err; /* R*Ri */
+		if (!BN_is_zero(Ri))
+			{
+			if (!BN_sub_word(Ri,1)) goto err;
+			}
+		else /* if N mod word size == 1 */
+			{
+			if (bn_expand(Ri,(int)sizeof(BN_ULONG)*2) == NULL)
+				goto err;
+			/* Ri-- (mod double word size) */
+			Ri->neg=0;
+			Ri->d[0]=BN_MASK2;
+			Ri->d[1]=BN_MASK2;
+			Ri->top=2;
+			}
+		if (!BN_div(Ri,NULL,Ri,&tmod,ctx)) goto err;
+		/* Ni = (R*Ri-1)/N,
+		 * keep only couple of least significant words: */
+		mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0;
+		mont->n0[1] = (Ri->top > 1) ? Ri->d[1] : 0;
+#else
 							/* Ri = R^-1 mod N*/
 		if ((BN_mod_inverse(Ri,R,&tmod,ctx)) == NULL)
 			goto err;
@@ -417,7 +647,13 @@
 		if (!BN_div(Ri,NULL,Ri,&tmod,ctx)) goto err;
 		/* Ni = (R*Ri-1)/N,
 		 * keep only least significant word: */
+# if 0 /* for OpenSSL 0.9.9 mont->n0 */
+		mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0;
+		mont->n0[1] = 0;
+# else
 		mont->n0 = (Ri->top > 0) ? Ri->d[0] : 0;
+# endif
+#endif
 		}
 #else /* !MONT_WORD */
 		{ /* bignum version */
@@ -453,7 +689,12 @@
 	if (!BN_copy(&(to->N),&(from->N))) return NULL;
 	if (!BN_copy(&(to->Ni),&(from->Ni))) return NULL;
 	to->ri=from->ri;
+#if 0 /* for OpenSSL 0.9.9 mont->n0 */
+	to->n0[0]=from->n0[0];
+	to->n0[1]=from->n0[1];
+#else
 	to->n0=from->n0;
+#endif
 	return(to);
 	}
 

Added: openssl/branches/upstream/current/crypto/des/asm/desboth.pl
===================================================================
--- openssl/branches/upstream/current/crypto/des/asm/desboth.pl	                        (rev 0)
+++ openssl/branches/upstream/current/crypto/des/asm/desboth.pl	2009-05-16 15:25:35 UTC (rev 372)
@@ -0,0 +1,79 @@
+#!/usr/local/bin/perl
+
+$L="edi";
+$R="esi";
+
+sub DES_encrypt3
+	{
+	local($name,$enc)=@_;
+
+	&function_begin_B($name,"");
+	&push("ebx");
+	&mov("ebx",&wparam(0));
+
+	&push("ebp");
+	&push("esi");
+
+	&push("edi");
+
+	&comment("");
+	&comment("Load the data words");
+	&mov($L,&DWP(0,"ebx","",0));
+	&mov($R,&DWP(4,"ebx","",0));
+	&stack_push(3);
+
+	&comment("");
+	&comment("IP");
+	&IP_new($L,$R,"edx",0);
+
+	# put them back
+	
+	if ($enc)
+		{
+		&mov(&DWP(4,"ebx","",0),$R);
+		 &mov("eax",&wparam(1));
+		&mov(&DWP(0,"ebx","",0),"edx");
+		 &mov("edi",&wparam(2));
+		 &mov("esi",&wparam(3));
+		}
+	else
+		{
+		&mov(&DWP(4,"ebx","",0),$R);
+		 &mov("esi",&wparam(1));
+		&mov(&DWP(0,"ebx","",0),"edx");
+		 &mov("edi",&wparam(2));
+		 &mov("eax",&wparam(3));
+		}
+	&mov(&swtmp(2),	(DWC(($enc)?"1":"0")));
+	&mov(&swtmp(1),	"eax");
+	&mov(&swtmp(0),	"ebx");
+	&call("DES_encrypt2");
+	&mov(&swtmp(2),	(DWC(($enc)?"0":"1")));
+	&mov(&swtmp(1),	"edi");
+	&mov(&swtmp(0),	"ebx");
+	&call("DES_encrypt2");
+	&mov(&swtmp(2),	(DWC(($enc)?"1":"0")));
+	&mov(&swtmp(1),	"esi");
+	&mov(&swtmp(0),	"ebx");
+	&call("DES_encrypt2");
+
+	&stack_pop(3);
+	&mov($L,&DWP(0,"ebx","",0));
+	&mov($R,&DWP(4,"ebx","",0));
+
+	&comment("");
+	&comment("FP");
+	&FP_new($L,$R,"eax",0);
+
+	&mov(&DWP(0,"ebx","",0),"eax");
+	&mov(&DWP(4,"ebx","",0),$R);
+
+	&pop("edi");
+	&pop("esi");
+	&pop("ebp");
+	&pop("ebx");
+	&ret();
+	&function_end_B($name);
+	}
+
+

Modified: openssl/branches/upstream/current/crypto/dh/dh.h
===================================================================
--- openssl/branches/upstream/current/crypto/dh/dh.h	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/crypto/dh/dh.h	2009-05-16 15:25:35 UTC (rev 372)
@@ -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 @@
 
 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 @@
 #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 @@
 /* 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
 

Modified: openssl/branches/upstream/current/crypto/dh/dh_err.c
===================================================================
--- openssl/branches/upstream/current/crypto/dh/dh_err.c	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/crypto/dh/dh_err.c	2009-05-16 15:25:35 UTC (rev 372)
@@ -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 @@
 {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 @@
 	{
 {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}

Modified: openssl/branches/upstream/current/crypto/dh/dh_key.c
===================================================================
--- openssl/branches/upstream/current/crypto/dh/dh_key.c	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/crypto/dh/dh_key.c	2009-05-16 15:25:35 UTC (rev 372)
@@ -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 @@
 		BN_MONT_CTX_free(dh->method_mont_p);
 	return(1);
 	}
+
+#endif

Modified: openssl/branches/upstream/current/crypto/dsa/dsa.h
===================================================================
--- openssl/branches/upstream/current/crypto/dsa/dsa.h	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/crypto/dsa/dsa.h	2009-05-16 15:25:35 UTC (rev 372)
@@ -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 @@
 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 @@
 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 @@
 #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 @@
 /* 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
 }

Modified: openssl/branches/upstream/current/crypto/dsa/dsa_err.c
===================================================================
--- openssl/branches/upstream/current/crypto/dsa/dsa_err.c	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/crypto/dsa/dsa_err.c	2009-05-16 15:25:35 UTC (rev 372)
@@ -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 @@
 {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 @@
 	{
 {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}
 	};
 

Modified: openssl/branches/upstream/current/crypto/dsa/dsa_ossl.c
===================================================================
--- openssl/branches/upstream/current/crypto/dsa/dsa_ossl.c	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/crypto/dsa/dsa_ossl.c	2009-05-16 15:25:35 UTC (rev 372)
@@ -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 @@
 	return(1);
 }
 
+#endif

Added: openssl/branches/upstream/current/crypto/engine/eng_table.c
===================================================================
--- openssl/branches/upstream/current/crypto/engine/eng_table.c	                        (rev 0)
+++ openssl/branches/upstream/current/crypto/engine/eng_table.c	2009-05-16 15:25:35 UTC (rev 372)
@@ -0,0 +1,315 @@
+/* ====================================================================
+ * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing at 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 at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ *
+ */
+
+#include "cryptlib.h"
+#include <openssl/evp.h>
+#include <openssl/lhash.h>
+#include "eng_int.h"
+
+/* The type of the items in the table */
+typedef struct st_engine_pile
+	{
+	/* The 'nid' of this algorithm/mode */
+	int nid;
+	/* ENGINEs that implement this algorithm/mode. */
+	STACK_OF(ENGINE) *sk;
+	/* The default ENGINE to perform this algorithm/mode. */
+	ENGINE *funct;
+	/* Zero if 'sk' is newer than the cached 'funct', non-zero otherwise */
+	int uptodate;
+	} ENGINE_PILE;
+
+/* The type exposed in eng_int.h */
+struct st_engine_table
+	{
+	LHASH piles;
+	}; /* ENGINE_TABLE */
+
+/* Global flags (ENGINE_TABLE_FLAG_***). */
+static unsigned int table_flags = 0;
+
+/* API function manipulating 'table_flags' */
+unsigned int ENGINE_get_table_flags(void)
+	{
+	return table_flags;
+	}
+void ENGINE_set_table_flags(unsigned int flags)
+	{
+	table_flags = flags;
+	}
+
+/* Internal functions for the "piles" hash table */
+static unsigned long engine_pile_hash(const ENGINE_PILE *c)
+	{
+	return c->nid;
+	}
+static int engine_pile_cmp(const ENGINE_PILE *a, const ENGINE_PILE *b)
+	{
+	return a->nid - b->nid;
+	}
+static IMPLEMENT_LHASH_HASH_FN(engine_pile_hash, const ENGINE_PILE *)
+static IMPLEMENT_LHASH_COMP_FN(engine_pile_cmp, const ENGINE_PILE *)
+static int int_table_check(ENGINE_TABLE **t, int create)
+	{
+	LHASH *lh;
+	if(*t) return 1;
+	if(!create) return 0;
+	if((lh = lh_new(LHASH_HASH_FN(engine_pile_hash),
+			LHASH_COMP_FN(engine_pile_cmp))) == NULL)
+		return 0;
+	*t = (ENGINE_TABLE *)lh;
+	return 1;
+	}
+
+/* Privately exposed (via eng_int.h) functions for adding and/or removing
+ * ENGINEs from the implementation table */
+int engine_table_register(ENGINE_TABLE **table, ENGINE_CLEANUP_CB *cleanup,
+		ENGINE *e, const int *nids, int num_nids, int setdefault)
+	{
+	int ret = 0, added = 0;
+	ENGINE_PILE tmplate, *fnd;
+	CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+	if(!(*table))
+		added = 1;
+	if(!int_table_check(table, 1))
+		goto end;
+	if(added)
+		/* The cleanup callback needs to be added */
+		engine_cleanup_add_first(cleanup);
+	while(num_nids--)
+		{
+		tmplate.nid = *nids;
+		fnd = lh_retrieve(&(*table)->piles, &tmplate);
+		if(!fnd)
+			{
+			fnd = OPENSSL_malloc(sizeof(ENGINE_PILE));
+			if(!fnd) goto end;
+			fnd->uptodate = 1;
+			fnd->nid = *nids;
+			fnd->sk = sk_ENGINE_new_null();
+			if(!fnd->sk)
+				{
+				OPENSSL_free(fnd);
+				goto end;
+				}
+			fnd->funct = NULL;
+			lh_insert(&(*table)->piles, fnd);
+			}
+		/* A registration shouldn't add duplciate entries */
+		(void)sk_ENGINE_delete_ptr(fnd->sk, e);
+		/* if 'setdefault', this ENGINE goes to the head of the list */
+		if(!sk_ENGINE_push(fnd->sk, e))
+			goto end;
+		/* "touch" this ENGINE_PILE */
+		fnd->uptodate = 0;
+		if(setdefault)
+			{
+			if(!engine_unlocked_init(e))
+				{
+				ENGINEerr(ENGINE_F_ENGINE_TABLE_REGISTER,
+						ENGINE_R_INIT_FAILED);
+				goto end;
+				}
+			if(fnd->funct)
+				engine_unlocked_finish(fnd->funct, 0);
+			fnd->funct = e;
+			fnd->uptodate = 1;
+			}
+		nids++;
+		}
+	ret = 1;
+end:
+	CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+	return ret;
+	}
+static void int_unregister_cb(ENGINE_PILE *pile, ENGINE *e)
+	{
+	int n;
+	/* Iterate the 'c->sk' stack removing any occurance of 'e' */
+	while((n = sk_ENGINE_find(pile->sk, e)) >= 0)
+		{
+		(void)sk_ENGINE_delete(pile->sk, n);
+		pile->uptodate = 0;
+		}
+	if(pile->funct == e)
+		{
+		engine_unlocked_finish(e, 0);
+		pile->funct = NULL;
+		}
+	}
+static IMPLEMENT_LHASH_DOALL_ARG_FN(int_unregister_cb,ENGINE_PILE *,ENGINE *)
+void engine_table_unregister(ENGINE_TABLE **table, ENGINE *e)
+	{
+	CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+	if(int_table_check(table, 0))
+		lh_doall_arg(&(*table)->piles,
+			LHASH_DOALL_ARG_FN(int_unregister_cb), e);
+	CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+	}
+
+static void int_cleanup_cb(ENGINE_PILE *p)
+	{
+	sk_ENGINE_free(p->sk);
+	if(p->funct)
+		engine_unlocked_finish(p->funct, 0);
+	OPENSSL_free(p);
+	}
+static IMPLEMENT_LHASH_DOALL_FN(int_cleanup_cb,ENGINE_PILE *)
+void engine_table_cleanup(ENGINE_TABLE **table)
+	{
+	CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+	if(*table)
+		{
+		lh_doall(&(*table)->piles, LHASH_DOALL_FN(int_cleanup_cb));
+		lh_free(&(*table)->piles);
+		*table = NULL;
+		}
+	CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+	}
+
+/* return a functional reference for a given 'nid' */
+#ifndef ENGINE_TABLE_DEBUG
+ENGINE *engine_table_select(ENGINE_TABLE **table, int nid)
+#else
+ENGINE *engine_table_select_tmp(ENGINE_TABLE **table, int nid, const char *f, int l)
+#endif
+	{
+	ENGINE *ret = NULL;
+	ENGINE_PILE tmplate, *fnd=NULL;
+	int initres, loop = 0;
+
+	if(!(*table))
+		{
+#ifdef ENGINE_TABLE_DEBUG
+		fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, nothing "
+			"registered!\n", f, l, nid);
+#endif
+		return NULL;
+		}
+	CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+	/* Check again inside the lock otherwise we could race against cleanup
+	 * operations. But don't worry about a fprintf(stderr). */
+	if(!int_table_check(table, 0)) goto end;
+	tmplate.nid = nid;
+	fnd = lh_retrieve(&(*table)->piles, &tmplate);
+	if(!fnd) goto end;
+	if(fnd->funct && engine_unlocked_init(fnd->funct))
+		{
+#ifdef ENGINE_TABLE_DEBUG
+		fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, using "
+			"ENGINE '%s' cached\n", f, l, nid, fnd->funct->id);
+#endif
+		ret = fnd->funct;
+		goto end;
+		}
+	if(fnd->uptodate)
+		{
+		ret = fnd->funct;
+		goto end;
+		}
+trynext:
+	ret = sk_ENGINE_value(fnd->sk, loop++);
+	if(!ret)
+		{
+#ifdef ENGINE_TABLE_DEBUG
+		fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, no "
+				"registered implementations would initialise\n",
+				f, l, nid);
+#endif
+		goto end;
+		}
+	/* Try to initialise the ENGINE? */
+	if((ret->funct_ref > 0) || !(table_flags & ENGINE_TABLE_FLAG_NOINIT))
+		initres = engine_unlocked_init(ret);
+	else
+		initres = 0;
+	if(initres)
+		{
+		/* Update 'funct' */
+		if((fnd->funct != ret) && engine_unlocked_init(ret))
+			{
+			/* If there was a previous default we release it. */
+			if(fnd->funct)
+				engine_unlocked_finish(fnd->funct, 0);
+			fnd->funct = ret;
+#ifdef ENGINE_TABLE_DEBUG
+			fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, "
+				"setting default to '%s'\n", f, l, nid, ret->id);
+#endif
+			}
+#ifdef ENGINE_TABLE_DEBUG
+		fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, using "
+				"newly initialised '%s'\n", f, l, nid, ret->id);
+#endif
+		goto end;
+		}
+	goto trynext;
+end:
+	/* If it failed, it is unlikely to succeed again until some future
+	 * registrations have taken place. In all cases, we cache. */
+	if(fnd) fnd->uptodate = 1;
+#ifdef ENGINE_TABLE_DEBUG
+	if(ret)
+		fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, caching "
+				"ENGINE '%s'\n", f, l, nid, ret->id);
+	else
+		fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, caching "
+				"'no matching ENGINE'\n", f, l, nid);
+#endif
+	CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+	/* Whatever happened, any failed init()s are not failures in this
+	 * context, so clear our error state. */
+	ERR_clear_error();
+	return ret;
+	}

Modified: openssl/branches/upstream/current/crypto/evp/evp.h
===================================================================
--- openssl/branches/upstream/current/crypto/evp/evp.h	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/crypto/evp/evp.h	2009-05-16 15:25:35 UTC (rev 372)
@@ -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 @@
 			    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,7 +317,18 @@
 						* 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
 	{
 	int nid;
@@ -347,6 +372,14 @@
 #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 @@
 #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 @@
 		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 @@
 		    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 @@
 
 /* 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 @@
 #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 @@
 #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

Modified: openssl/branches/upstream/current/crypto/evp/evp_lib.c
===================================================================
--- openssl/branches/upstream/current/crypto/evp/evp_lib.c	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/crypto/evp/evp_lib.c	2009-05-16 15:25:35 UTC (rev 372)
@@ -67,6 +67,8 @@
 
 	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 @@
 
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	{
 	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);
+	}

Modified: openssl/branches/upstream/current/crypto/md2/md2.h
===================================================================
--- openssl/branches/upstream/current/crypto/md2/md2.h	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/crypto/md2/md2.h	2009-05-16 15:25:35 UTC (rev 372)
@@ -81,6 +81,9 @@
 	} MD2_CTX;
 
 const char *MD2_options(void);
+#ifdef OPENSSL_FIPS
+int private_MD2_Init(MD2_CTX *c);
+#endif
 int MD2_Init(MD2_CTX *c);
 int MD2_Update(MD2_CTX *c, const unsigned char *data, size_t len);
 int MD2_Final(unsigned char *md, MD2_CTX *c);

Modified: openssl/branches/upstream/current/crypto/md4/md4.h
===================================================================
--- openssl/branches/upstream/current/crypto/md4/md4.h	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/crypto/md4/md4.h	2009-05-16 15:25:35 UTC (rev 372)
@@ -105,6 +105,9 @@
 	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);

Modified: openssl/branches/upstream/current/crypto/md5/md5.h
===================================================================
--- openssl/branches/upstream/current/crypto/md5/md5.h	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/crypto/md5/md5.h	2009-05-16 15:25:35 UTC (rev 372)
@@ -105,6 +105,9 @@
 	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);

Modified: openssl/branches/upstream/current/crypto/ocsp/ocsp.h
===================================================================
--- openssl/branches/upstream/current/crypto/ocsp/ocsp.h	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/crypto/ocsp/ocsp.h	2009-05-16 15:25:35 UTC (rev 372)
@@ -186,11 +186,11 @@
  *      responseStatus         OCSPResponseStatus,
  *      responseBytes          [0] EXPLICIT ResponseBytes OPTIONAL }
  */
-typedef struct ocsp_response_st
+struct ocsp_response_st
 	{
 	ASN1_ENUMERATED *responseStatus;
 	OCSP_RESPBYTES  *responseBytes;
-	} OCSP_RESPONSE;
+	};
 
 /*   ResponderID ::= CHOICE {
  *      byName   [1] Name,
@@ -198,14 +198,18 @@
  */
 #define V_OCSP_RESPID_NAME 0
 #define V_OCSP_RESPID_KEY  1
-typedef struct ocsp_responder_id_st
+struct ocsp_responder_id_st
 	{
 	int type;
 	union   {
 		X509_NAME* byName;
         	ASN1_OCTET_STRING *byKey;
 		} value;
-	} OCSP_RESPID;
+	};
+
+DECLARE_STACK_OF(OCSP_RESPID)
+DECLARE_ASN1_FUNCTIONS(OCSP_RESPID)
+
 /*   KeyHash ::= OCTET STRING --SHA-1 hash of responder's public key
  *                            --(excluding the tag and length fields)
  */
@@ -397,6 +401,10 @@
 		(char *(*)())d2i_OCSP_CERTSTATUS,(char *)(cs))
 
 OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, char *path, OCSP_REQUEST *req);
+OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, char *path, OCSP_REQUEST *req,
+								int maxline);
+int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx);
+void OCSP_REQ_CTX_free(OCSP_REQ_CTX *rctx);
 
 OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, X509 *subject, X509 *issuer);
 
@@ -574,6 +582,7 @@
 #define OCSP_F_OCSP_REQUEST_VERIFY			 116
 #define OCSP_F_OCSP_RESPONSE_GET1_BASIC			 111
 #define OCSP_F_OCSP_SENDREQ_BIO				 112
+#define OCSP_F_PARSE_HTTP_LINE1				 117
 #define OCSP_F_REQUEST_VERIFY				 113
 
 /* Reason codes. */

Modified: openssl/branches/upstream/current/crypto/pem/pem.h
===================================================================
--- openssl/branches/upstream/current/crypto/pem/pem.h	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/crypto/pem/pem.h	2009-05-16 15:25:35 UTC (rev 372)
@@ -125,6 +125,7 @@
 #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"
@@ -133,6 +134,7 @@
 #define PEM_STRING_ECDSA_PUBLIC "ECDSA PUBLIC KEY"
 #define PEM_STRING_ECPARAMETERS "EC PARAMETERS"
 #define PEM_STRING_ECPRIVATEKEY	"EC PRIVATE KEY"
+#define PEM_STRING_CMS		"CMS"
 
   /* Note that this structure is initialised by PEM_SealInit and cleaned up
      by PEM_SealFinal (at least for now) */
@@ -213,7 +215,9 @@
 
 #define IMPLEMENT_PEM_read_fp(name, type, str, asn1) /**/
 #define IMPLEMENT_PEM_write_fp(name, type, str, asn1) /**/
+#define IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) /**/
 #define IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) /**/
+#define IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) /**/
 
 #else
 
@@ -353,6 +357,7 @@
 
 #define DECLARE_PEM_read_fp(name, type) /**/
 #define DECLARE_PEM_write_fp(name, type) /**/
+#define DECLARE_PEM_write_fp_const(name, type) /**/
 #define DECLARE_PEM_write_cb_fp(name, type) /**/
 
 #else
@@ -390,6 +395,7 @@
 
 #define DECLARE_PEM_read_bio(name, type) /**/
 #define DECLARE_PEM_write_bio(name, type) /**/
+#define DECLARE_PEM_write_bio_const(name, type) /**/
 #define DECLARE_PEM_write_cb_bio(name, type) /**/
 
 #endif

Added: openssl/branches/upstream/current/crypto/perlasm/cbc.pl
===================================================================
--- openssl/branches/upstream/current/crypto/perlasm/cbc.pl	                        (rev 0)
+++ openssl/branches/upstream/current/crypto/perlasm/cbc.pl	2009-05-16 15:25:35 UTC (rev 372)
@@ -0,0 +1,351 @@
+#!/usr/local/bin/perl
+
+# void des_ncbc_encrypt(input, output, length, schedule, ivec, enc)
+# des_cblock (*input);
+# des_cblock (*output);
+# long length;
+# des_key_schedule schedule;
+# des_cblock (*ivec);
+# int enc;
+#
+# calls 
+# des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT);
+#
+
+#&cbc("des_ncbc_encrypt","des_encrypt",0);
+#&cbc("BF_cbc_encrypt","BF_encrypt","BF_encrypt",
+#	1,4,5,3,5,-1);
+#&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt",
+#	0,4,5,3,5,-1);
+#&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3",
+#	0,6,7,3,4,5);
+#
+# When doing a cipher that needs bigendian order,
+# for encrypt, the iv is kept in bigendian form,
+# while for decrypt, it is kept in little endian.
+sub cbc
+	{
+	local($name,$enc_func,$dec_func,$swap,$iv_off,$enc_off,$p1,$p2,$p3)=@_;
+	# name is the function name
+	# enc_func and dec_func and the functions to call for encrypt/decrypt
+	# swap is true if byte order needs to be reversed
+	# iv_off is parameter number for the iv 
+	# enc_off is parameter number for the encrypt/decrypt flag
+	# p1,p2,p3 are the offsets for parameters to be passed to the
+	# underlying calls.
+
+	&function_begin_B($name,"");
+	&comment("");
+
+	$in="esi";
+	$out="edi";
+	$count="ebp";
+
+	&push("ebp");
+	&push("ebx");
+	&push("esi");
+	&push("edi");
+
+	$data_off=4;
+	$data_off+=4 if ($p1 > 0);
+	$data_off+=4 if ($p2 > 0);
+	$data_off+=4 if ($p3 > 0);
+
+	&mov($count,	&wparam(2));	# length
+
+	&comment("getting iv ptr from parameter $iv_off");
+	&mov("ebx",	&wparam($iv_off));	# Get iv ptr
+
+	&mov($in,	&DWP(0,"ebx","",0));#	iv[0]
+	&mov($out,	&DWP(4,"ebx","",0));#	iv[1]
+
+	&push($out);
+	&push($in);
+	&push($out);	# used in decrypt for iv[1]
+	&push($in);	# used in decrypt for iv[0]
+
+	&mov("ebx",	"esp");		# This is the address of tin[2]
+
+	&mov($in,	&wparam(0));	# in
+	&mov($out,	&wparam(1));	# out
+
+	# We have loaded them all, how lets push things
+	&comment("getting encrypt flag from parameter $enc_off");
+	&mov("ecx",	&wparam($enc_off));	# Get enc flag
+	if ($p3 > 0)
+		{
+		&comment("get and push parameter $p3");
+		if ($enc_off != $p3)
+			{ &mov("eax",	&wparam($p3)); &push("eax"); }
+		else	{ &push("ecx"); }
+		}
+	if ($p2 > 0)
+		{
+		&comment("get and push parameter $p2");
+		if ($enc_off != $p2)
+			{ &mov("eax",	&wparam($p2)); &push("eax"); }
+		else	{ &push("ecx"); }
+		}
+	if ($p1 > 0)
+		{
+		&comment("get and push parameter $p1");
+		if ($enc_off != $p1)
+			{ &mov("eax",	&wparam($p1)); &push("eax"); }
+		else	{ &push("ecx"); }
+		}
+	&push("ebx");		# push data/iv
+
+	&cmp("ecx",0);
+	&jz(&label("decrypt"));
+
+	&and($count,0xfffffff8);
+	&mov("eax",	&DWP($data_off,"esp","",0));	# load iv[0]
+	&mov("ebx",	&DWP($data_off+4,"esp","",0));	# load iv[1]
+
+	&jz(&label("encrypt_finish"));
+
+	#############################################################
+
+	&set_label("encrypt_loop");
+	# encrypt start 
+	# "eax" and "ebx" hold iv (or the last cipher text)
+
+	&mov("ecx",	&DWP(0,$in,"",0));	# load first 4 bytes
+	&mov("edx",	&DWP(4,$in,"",0));	# second 4 bytes
+
+	&xor("eax",	"ecx");
+	&xor("ebx",	"edx");
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov(&DWP($data_off,"esp","",0),	"eax");	# put in array for call
+	&mov(&DWP($data_off+4,"esp","",0),	"ebx");	#
+
+	&call($enc_func);
+
+	&mov("eax",	&DWP($data_off,"esp","",0));
+	&mov("ebx",	&DWP($data_off+4,"esp","",0));
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov(&DWP(0,$out,"",0),"eax");
+	&mov(&DWP(4,$out,"",0),"ebx");
+
+	# eax and ebx are the next iv.
+
+	&add($in,	8);
+	&add($out,	8);
+
+	&sub($count,	8);
+	&jnz(&label("encrypt_loop"));
+
+###################################################################3
+	&set_label("encrypt_finish");
+	&mov($count,	&wparam(2));	# length
+	&and($count,	7);
+	&jz(&label("finish"));
+	&call(&label("PIC_point"));
+&set_label("PIC_point");
+	&blindpop("edx");
+	&lea("ecx",&DWP(&label("cbc_enc_jmp_table")."-".&label("PIC_point"),"edx"));
+	&mov($count,&DWP(0,"ecx",$count,4))
+	&add($count,"edx");
+	&xor("ecx","ecx");
+	&xor("edx","edx");
+	#&mov($count,&DWP(&label("cbc_enc_jmp_table"),"",$count,4));
+	&jmp_ptr($count);
+
+&set_label("ej7");
+	&xor("edx",		"edx") if $ppro; # ppro friendly
+	&movb(&HB("edx"),	&BP(6,$in,"",0));
+	&shl("edx",8);
+&set_label("ej6");
+	&movb(&HB("edx"),	&BP(5,$in,"",0));
+&set_label("ej5");
+	&movb(&LB("edx"),	&BP(4,$in,"",0));
+&set_label("ej4");
+	&mov("ecx",		&DWP(0,$in,"",0));
+	&jmp(&label("ejend"));
+&set_label("ej3");
+	&movb(&HB("ecx"),	&BP(2,$in,"",0));
+	&xor("ecx",		"ecx") if $ppro; # ppro friendly
+	&shl("ecx",8);
+&set_label("ej2");
+	&movb(&HB("ecx"),	&BP(1,$in,"",0));
+&set_label("ej1");
+	&movb(&LB("ecx"),	&BP(0,$in,"",0));
+&set_label("ejend");
+
+	&xor("eax",	"ecx");
+	&xor("ebx",	"edx");
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov(&DWP($data_off,"esp","",0),	"eax");	# put in array for call
+	&mov(&DWP($data_off+4,"esp","",0),	"ebx");	#
+
+	&call($enc_func);
+
+	&mov("eax",	&DWP($data_off,"esp","",0));
+	&mov("ebx",	&DWP($data_off+4,"esp","",0));
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov(&DWP(0,$out,"",0),"eax");
+	&mov(&DWP(4,$out,"",0),"ebx");
+
+	&jmp(&label("finish"));
+
+	#############################################################
+	#############################################################
+	&set_label("decrypt",1);
+	# decrypt start 
+	&and($count,0xfffffff8);
+	# The next 2 instructions are only for if the jz is taken
+	&mov("eax",	&DWP($data_off+8,"esp","",0));	# get iv[0]
+	&mov("ebx",	&DWP($data_off+12,"esp","",0));	# get iv[1]
+	&jz(&label("decrypt_finish"));
+
+	&set_label("decrypt_loop");
+	&mov("eax",	&DWP(0,$in,"",0));	# load first 4 bytes
+	&mov("ebx",	&DWP(4,$in,"",0));	# second 4 bytes
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov(&DWP($data_off,"esp","",0),	"eax");	# put back
+	&mov(&DWP($data_off+4,"esp","",0),	"ebx");	#
+
+	&call($dec_func);
+
+	&mov("eax",	&DWP($data_off,"esp","",0));	# get return
+	&mov("ebx",	&DWP($data_off+4,"esp","",0));	#
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov("ecx",	&DWP($data_off+8,"esp","",0));	# get iv[0]
+	&mov("edx",	&DWP($data_off+12,"esp","",0));	# get iv[1]
+
+	&xor("ecx",	"eax");
+	&xor("edx",	"ebx");
+
+	&mov("eax",	&DWP(0,$in,"",0));	# get old cipher text,
+	&mov("ebx",	&DWP(4,$in,"",0));	# next iv actually
+
+	&mov(&DWP(0,$out,"",0),"ecx");
+	&mov(&DWP(4,$out,"",0),"edx");
+
+	&mov(&DWP($data_off+8,"esp","",0),	"eax");	# save iv
+	&mov(&DWP($data_off+12,"esp","",0),	"ebx");	#
+
+	&add($in,	8);
+	&add($out,	8);
+
+	&sub($count,	8);
+	&jnz(&label("decrypt_loop"));
+############################ ENDIT #######################3
+	&set_label("decrypt_finish");
+	&mov($count,	&wparam(2));	# length
+	&and($count,	7);
+	&jz(&label("finish"));
+
+	&mov("eax",	&DWP(0,$in,"",0));	# load first 4 bytes
+	&mov("ebx",	&DWP(4,$in,"",0));	# second 4 bytes
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov(&DWP($data_off,"esp","",0),	"eax");	# put back
+	&mov(&DWP($data_off+4,"esp","",0),	"ebx");	#
+
+	&call($dec_func);
+
+	&mov("eax",	&DWP($data_off,"esp","",0));	# get return
+	&mov("ebx",	&DWP($data_off+4,"esp","",0));	#
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov("ecx",	&DWP($data_off+8,"esp","",0));	# get iv[0]
+	&mov("edx",	&DWP($data_off+12,"esp","",0));	# get iv[1]
+
+	&xor("ecx",	"eax");
+	&xor("edx",	"ebx");
+
+	# this is for when we exit
+	&mov("eax",	&DWP(0,$in,"",0));	# get old cipher text,
+	&mov("ebx",	&DWP(4,$in,"",0));	# next iv actually
+
+&set_label("dj7");
+	&rotr("edx",	16);
+	&movb(&BP(6,$out,"",0),	&LB("edx"));
+	&shr("edx",16);
+&set_label("dj6");
+	&movb(&BP(5,$out,"",0),	&HB("edx"));
+&set_label("dj5");
+	&movb(&BP(4,$out,"",0),	&LB("edx"));
+&set_label("dj4");
+	&mov(&DWP(0,$out,"",0),	"ecx");
+	&jmp(&label("djend"));
+&set_label("dj3");
+	&rotr("ecx",	16);
+	&movb(&BP(2,$out,"",0),	&LB("ecx"));
+	&shl("ecx",16);
+&set_label("dj2");
+	&movb(&BP(1,$in,"",0),	&HB("ecx"));
+&set_label("dj1");
+	&movb(&BP(0,$in,"",0),	&LB("ecx"));
+&set_label("djend");
+
+	# final iv is still in eax:ebx
+	&jmp(&label("finish"));
+
+
+############################ FINISH #######################3
+	&set_label("finish",1);
+	&mov("ecx",	&wparam($iv_off));	# Get iv ptr
+
+	#################################################
+	$total=16+4;
+	$total+=4 if ($p1 > 0);
+	$total+=4 if ($p2 > 0);
+	$total+=4 if ($p3 > 0);
+	&add("esp",$total);
+
+	&mov(&DWP(0,"ecx","",0),	"eax");	# save iv
+	&mov(&DWP(4,"ecx","",0),	"ebx");	# save iv
+
+	&function_end_A($name);
+
+	&align(64);
+	&set_label("cbc_enc_jmp_table");
+	&data_word("0");
+	&data_word(&label("ej1")."-".&label("PIC_point"));
+	&data_word(&label("ej2")."-".&label("PIC_point"));
+	&data_word(&label("ej3")."-".&label("PIC_point"));
+	&data_word(&label("ej4")."-".&label("PIC_point"));
+	&data_word(&label("ej5")."-".&label("PIC_point"));
+	&data_word(&label("ej6")."-".&label("PIC_point"));
+	&data_word(&label("ej7")."-".&label("PIC_point"));
+	# not used
+	#&set_label("cbc_dec_jmp_table",1);
+	#&data_word("0");
+	#&data_word(&label("dj1")."-".&label("PIC_point"));
+	#&data_word(&label("dj2")."-".&label("PIC_point"));
+	#&data_word(&label("dj3")."-".&label("PIC_point"));
+	#&data_word(&label("dj4")."-".&label("PIC_point"));
+	#&data_word(&label("dj5")."-".&label("PIC_point"));
+	#&data_word(&label("dj6")."-".&label("PIC_point"));
+	#&data_word(&label("dj7")."-".&label("PIC_point"));
+	&align(64);
+
+	&function_end_B($name);
+	
+	}
+
+1;

Added: openssl/branches/upstream/current/crypto/perlasm/x86unix.pl
===================================================================
--- openssl/branches/upstream/current/crypto/perlasm/x86unix.pl	                        (rev 0)
+++ openssl/branches/upstream/current/crypto/perlasm/x86unix.pl	2009-05-16 15:25:35 UTC (rev 372)
@@ -0,0 +1,725 @@
+#!/usr/local/bin/perl
+
+package x86unix;	# GAS actually...
+
+$label="L000";
+$const="";
+$constl=0;
+
+$align=($main'aout)?"4":"16";
+$under=($main'aout or $main'coff)?"_":"";
+$dot=($main'aout)?"":".";
+$com_start="#" if ($main'aout or $main'coff);
+
+sub main'asm_init_output { @out=(); }
+sub main'asm_get_output { return(@out); }
+sub main'get_labels { return(@labels); }
+sub main'external_label { push(@labels, at _); }
+
+if ($main'cpp)
+	{
+	$align="ALIGN";
+	$under="";
+	$com_start='/*';
+	$com_end='*/';
+	}
+
+%lb=(	'eax',	'%al',
+	'ebx',	'%bl',
+	'ecx',	'%cl',
+	'edx',	'%dl',
+	'ax',	'%al',
+	'bx',	'%bl',
+	'cx',	'%cl',
+	'dx',	'%dl',
+	);
+
+%hb=(	'eax',	'%ah',
+	'ebx',	'%bh',
+	'ecx',	'%ch',
+	'edx',	'%dh',
+	'ax',	'%ah',
+	'bx',	'%bh',
+	'cx',	'%ch',
+	'dx',	'%dh',
+	);
+
+%regs=(	'eax',	'%eax',
+	'ebx',	'%ebx',
+	'ecx',	'%ecx',
+	'edx',	'%edx',
+	'esi',	'%esi',
+	'edi',	'%edi',
+	'ebp',	'%ebp',
+	'esp',	'%esp',
+
+	'mm0',	'%mm0',
+	'mm1',	'%mm1',
+	'mm2',	'%mm2',
+	'mm3',	'%mm3',
+	'mm4',	'%mm4',
+	'mm5',	'%mm5',
+	'mm6',	'%mm6',
+	'mm7',	'%mm7',
+
+	'xmm0',	'%xmm0',
+	'xmm1',	'%xmm1',
+	'xmm2',	'%xmm2',
+	'xmm3',	'%xmm3',
+	'xmm4',	'%xmm4',
+	'xmm5',	'%xmm5',
+	'xmm6',	'%xmm6',
+	'xmm7',	'%xmm7',
+	);
+
+%reg_val=(
+	'eax',	0x00,
+	'ebx',	0x03,
+	'ecx',	0x01,
+	'edx',	0x02,
+	'esi',	0x06,
+	'edi',	0x07,
+	'ebp',	0x05,
+	'esp',	0x04,
+	);
+
+sub main'LB
+	{
+	(defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n";
+	return($lb{$_[0]});
+	}
+
+sub main'HB
+	{
+	(defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n";
+	return($hb{$_[0]});
+	}
+
+sub main'DWP
+	{
+	local($addr,$reg1,$reg2,$idx)=@_;
+
+	$ret="";
+	$addr =~ s/(^|[+ \t])([A-Za-z_]+[A-Za-z0-9_]+)($|[+ \t])/$1$under$2$3/;
+	$reg1="$regs{$reg1}" if defined($regs{$reg1});
+	$reg2="$regs{$reg2}" if defined($regs{$reg2});
+	$ret.=$addr if ($addr ne "") && ($addr ne 0);
+	if ($reg2 ne "")
+		{
+		if($idx ne "" && $idx != 0)
+		    { $ret.="($reg1,$reg2,$idx)"; }
+		else
+		    { $ret.="($reg1,$reg2)"; }
+	        }
+	elsif ($reg1 ne "")
+		{ $ret.="($reg1)" }
+	return($ret);
+	}
+
+sub main'QWP
+	{
+	return(&main'DWP(@_));
+	}
+
+sub main'BP
+	{
+	return(&main'DWP(@_));
+	}
+
+sub main'BC
+	{
+	return @_;
+	}
+
+sub main'DWC
+	{
+	return @_;
+	}
+
+#sub main'BP
+#	{
+#	local($addr,$reg1,$reg2,$idx)=@_;
+#
+#	$ret="";
+#
+#	$addr =~ s/(^|[+ \t])([A-Za-z_]+)($|[+ \t])/$1$under$2$3/;
+#	$reg1="$regs{$reg1}" if defined($regs{$reg1});
+#	$reg2="$regs{$reg2}" if defined($regs{$reg2});
+#	$ret.=$addr if ($addr ne "") && ($addr ne 0);
+#	if ($reg2 ne "")
+#		{ $ret.="($reg1,$reg2,$idx)"; }
+#	else
+#		{ $ret.="($reg1)" }
+#	return($ret);
+#	}
+
+sub main'mov	{ &out2("movl", at _); }
+sub main'movb	{ &out2("movb", at _); }
+sub main'and	{ &out2("andl", at _); }
+sub main'or	{ &out2("orl", at _); }
+sub main'shl	{ &out2("sall", at _); }
+sub main'shr	{ &out2("shrl", at _); }
+sub main'xor	{ &out2("xorl", at _); }
+sub main'xorb	{ &out2("xorb", at _); }
+sub main'add	{ &out2($_[0]=~/%[a-d][lh]/?"addb":"addl", at _); }
+sub main'adc	{ &out2("adcl", at _); }
+sub main'sub	{ &out2("subl", at _); }
+sub main'sbb	{ &out2("sbbl", at _); }
+sub main'rotl	{ &out2("roll", at _); }
+sub main'rotr	{ &out2("rorl", at _); }
+sub main'exch	{ &out2($_[0]=~/%[a-d][lh]/?"xchgb":"xchgl", at _); }
+sub main'cmp	{ &out2("cmpl", at _); }
+sub main'lea	{ &out2("leal", at _); }
+sub main'mul	{ &out1("mull", at _); }
+sub main'imul	{ &out2("imull", at _); }
+sub main'div	{ &out1("divl", at _); }
+sub main'jmp	{ &out1("jmp", at _); }
+sub main'jmp_ptr { &out1p("jmp", at _); }
+sub main'je	{ &out1("je", at _); }
+sub main'jle	{ &out1("jle", at _); }
+sub main'jne	{ &out1("jne", at _); }
+sub main'jnz	{ &out1("jnz", at _); }
+sub main'jz	{ &out1("jz", at _); }
+sub main'jge	{ &out1("jge", at _); }
+sub main'jl	{ &out1("jl", at _); }
+sub main'ja	{ &out1("ja", at _); }
+sub main'jae	{ &out1("jae", at _); }
+sub main'jb	{ &out1("jb", at _); }
+sub main'jbe	{ &out1("jbe", at _); }
+sub main'jc	{ &out1("jc", at _); }
+sub main'jnc	{ &out1("jnc", at _); }
+sub main'jno	{ &out1("jno", at _); }
+sub main'dec	{ &out1("decl", at _); }
+sub main'inc	{ &out1($_[0]=~/%[a-d][hl]/?"incb":"incl", at _); }
+sub main'push	{ &out1("pushl", at _); $stack+=4; }
+sub main'pop	{ &out1("popl", at _); $stack-=4; }
+sub main'pushf	{ &out0("pushfl"); $stack+=4; }
+sub main'popf	{ &out0("popfl"); $stack-=4; }
+sub main'not	{ &out1("notl", at _); }
+sub main'call	{	my $pre=$under;
+			foreach $i (%label)
+			{ if ($label{$i} eq $_[0]) { $pre=''; last; } }
+			&out1("call",$pre.$_[0]);
+		}
+sub main'call_ptr { &out1p("call", at _); }
+sub main'ret	{ &out0("ret"); }
+sub main'nop	{ &out0("nop"); }
+sub main'test	{ &out2("testl", at _); }
+sub main'bt	{ &out2("btl", at _); }
+sub main'leave	{ &out0("leave"); }
+sub main'cpuid	{ &out0(".byte\t0x0f,0xa2"); }
+sub main'rdtsc	{ &out0(".byte\t0x0f,0x31"); }
+sub main'halt	{ &out0("hlt"); }
+sub main'movz	{ &out2("movzbl", at _); }
+sub main'neg	{ &out1("negl", at _); }
+sub main'cld	{ &out0("cld"); }
+
+# SSE2
+sub main'emms	{ &out0("emms"); }
+sub main'movd	{ &out2("movd", at _); }
+sub main'movdqu	{ &out2("movdqu", at _); }
+sub main'movdqa	{ &out2("movdqa", at _); }
+sub main'movdq2q{ &out2("movdq2q", at _); }
+sub main'movq2dq{ &out2("movq2dq", at _); }
+sub main'paddq	{ &out2("paddq", at _); }
+sub main'pmuludq{ &out2("pmuludq", at _); }
+sub main'psrlq	{ &out2("psrlq", at _); }
+sub main'psllq	{ &out2("psllq", at _); }
+sub main'pxor	{ &out2("pxor", at _); }
+sub main'por	{ &out2("por", at _); }
+sub main'pand	{ &out2("pand", at _); }
+sub main'movq	{
+	local($p1,$p2,$optimize)=@_;
+	if ($optimize && $p1=~/^mm[0-7]$/ && $p2=~/^mm[0-7]$/)
+		# movq between mmx registers can sink Intel CPUs
+		{	push(@out,"\tpshufw\t\$0xe4,%$p2,%$p1\n");	}
+	else	{	&out2("movq", at _);				}
+	}
+
+# The bswapl instruction is new for the 486. Emulate if i386.
+sub main'bswap
+	{
+	if ($main'i386)
+		{
+		&main'comment("bswapl @_");
+		&main'exch(main'HB(@_),main'LB(@_));
+		&main'rotr(@_,16);
+		&main'exch(main'HB(@_),main'LB(@_));
+		}
+	else
+		{
+		&out1("bswapl", at _);
+		}
+	}
+
+sub out2
+	{
+	local($name,$p1,$p2)=@_;
+	local($l,$ll,$t);
+	local(%special)=(	"roll",0xD1C0,"rorl",0xD1C8,
+				"rcll",0xD1D0,"rcrl",0xD1D8,
+				"shll",0xD1E0,"shrl",0xD1E8,
+				"sarl",0xD1F8);
+	
+	if ((defined($special{$name})) && defined($regs{$p1}) && ($p2 == 1))
+		{
+		$op=$special{$name}|$reg_val{$p1};
+		$tmp1=sprintf(".byte %d\n",($op>>8)&0xff);
+		$tmp2=sprintf(".byte %d\t",$op     &0xff);
+		push(@out,$tmp1);
+		push(@out,$tmp2);
+
+		$p2=&conv($p2);
+		$p1=&conv($p1);
+		&main'comment("$name $p2 $p1");
+		return;
+		}
+
+	push(@out,"\t$name\t");
+	$t=&conv($p2).",";
+	$l=length($t);
+	push(@out,$t);
+	$ll=4-($l+9)/8;
+	$tmp1=sprintf("\t" x $ll);
+	push(@out,$tmp1);
+	push(@out,&conv($p1)."\n");
+	}
+
+sub out1
+	{
+	local($name,$p1)=@_;
+	local($l,$t);
+	local(%special)=("bswapl",0x0FC8);
+
+	if ((defined($special{$name})) && defined($regs{$p1}))
+		{
+		$op=$special{$name}|$reg_val{$p1};
+		$tmp1=sprintf(".byte %d\n",($op>>8)&0xff);
+		$tmp2=sprintf(".byte %d\t",$op     &0xff);
+		push(@out,$tmp1);
+		push(@out,$tmp2);
+
+		$p2=&conv($p2);
+		$p1=&conv($p1);
+		&main'comment("$name $p2 $p1");
+		return;
+		}
+
+	push(@out,"\t$name\t".&conv($p1)."\n");
+	}
+
+sub out1p
+	{
+	local($name,$p1)=@_;
+	local($l,$t);
+
+	push(@out,"\t$name\t*".&conv($p1)."\n");
+	}
+
+sub out0
+	{
+	push(@out,"\t$_[0]\n");
+	}
+
+sub conv
+	{
+	local($p)=@_;
+
+#	$p =~ s/0x([0-9A-Fa-f]+)/0$1h/;
+
+	$p=$regs{$p} if (defined($regs{$p}));
+
+	$p =~ s/^(-{0,1}[0-9A-Fa-f]+)$/\$$1/;
+	$p =~ s/^(0x[0-9A-Fa-f]+)$/\$$1/;
+	return $p;
+	}
+
+sub main'file
+	{
+	local($file)=@_;
+
+	local($tmp)=<<"EOF";
+	.file	"$file.s"
+EOF
+	push(@out,$tmp);
+	}
+
+sub main'function_begin
+	{
+	local($func)=@_;
+
+	&main'external_label($func);
+	$func=$under.$func;
+
+	local($tmp)=<<"EOF";
+.text
+.globl	$func
+EOF
+	push(@out,$tmp);
+	if ($main'cpp)
+		{ $tmp=push(@out,"TYPE($func,\@function)\n"); }
+	elsif ($main'coff)
+		{ $tmp=push(@out,".def\t$func;\t.scl\t2;\t.type\t32;\t.endef\n"); }
+	elsif ($main'aout and !$main'pic)
+		{ }
+	else	{ $tmp=push(@out,".type\t$func,\@function\n"); }
+	push(@out,".align\t$align\n");
+	push(@out,"$func:\n");
+	$tmp=<<"EOF";
+	pushl	%ebp
+	pushl	%ebx
+	pushl	%esi
+	pushl	%edi
+
+EOF
+	push(@out,$tmp);
+	$stack=20;
+	}
+
+sub main'function_begin_B
+	{
+	local($func,$extra)=@_;
+
+	&main'external_label($func);
+	$func=$under.$func;
+
+	local($tmp)=<<"EOF";
+.text
+.globl	$func
+EOF
+	push(@out,$tmp);
+	if ($main'cpp)
+		{ push(@out,"TYPE($func,\@function)\n"); }
+	elsif ($main'coff)
+		{ $tmp=push(@out,".def\t$func;\t.scl\t2;\t.type\t32;\t.endef\n"); }
+	elsif ($main'aout and !$main'pic)
+		{ }
+	else	{ push(@out,".type	$func,\@function\n"); }
+	push(@out,".align\t$align\n");
+	push(@out,"$func:\n");
+	$stack=4;
+	}
+
+sub main'function_end
+	{
+	local($func)=@_;
+
+	$func=$under.$func;
+
+	local($tmp)=<<"EOF";
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	popl	%ebp
+	ret
+${dot}L_${func}_end:
+EOF
+	push(@out,$tmp);
+
+	if ($main'cpp)
+		{ push(@out,"SIZE($func,${dot}L_${func}_end-$func)\n"); }
+	elsif ($main'coff or $main'aout)
+                { }
+	else	{ push(@out,".size\t$func,${dot}L_${func}_end-$func\n"); }
+	push(@out,".ident	\"$func\"\n");
+	$stack=0;
+	%label=();
+	}
+
+sub main'function_end_A
+	{
+	local($func)=@_;
+
+	local($tmp)=<<"EOF";
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	popl	%ebp
+	ret
+EOF
+	push(@out,$tmp);
+	}
+
+sub main'function_end_B
+	{
+	local($func)=@_;
+
+	$func=$under.$func;
+
+	push(@out,"${dot}L_${func}_end:\n");
+	if ($main'cpp)
+		{ push(@out,"SIZE($func,${dot}L_${func}_end-$func)\n"); }
+        elsif ($main'coff or $main'aout)
+                { }
+	else	{ push(@out,".size\t$func,${dot}L_${func}_end-$func\n"); }
+	push(@out,".ident	\"$func\"\n");
+	$stack=0;
+	%label=();
+	}
+
+sub main'wparam
+	{
+	local($num)=@_;
+
+	return(&main'DWP($stack+$num*4,"esp","",0));
+	}
+
+sub main'stack_push
+	{
+	local($num)=@_;
+	$stack+=$num*4;
+	&main'sub("esp",$num*4);
+	}
+
+sub main'stack_pop
+	{
+	local($num)=@_;
+	$stack-=$num*4;
+	&main'add("esp",$num*4);
+	}
+
+sub main'swtmp
+	{
+	return(&main'DWP($_[0]*4,"esp","",0));
+	}
+
+# Should use swtmp, which is above esp.  Linix can trash the stack above esp
+#sub main'wtmp
+#	{
+#	local($num)=@_;
+#
+#	return(&main'DWP(-($num+1)*4,"esp","",0));
+#	}
+
+sub main'comment
+	{
+	if (!defined($com_start) or $main'elf)
+		{	# Regarding $main'elf above...
+			# GNU and SVR4 as'es use different comment delimiters,
+		push(@out,"\n");	# so we just skip ELF comments...
+		return;
+		}
+	foreach (@_)
+		{
+		if (/^\s*$/)
+			{ push(@out,"\n"); }
+		else
+			{ push(@out,"\t$com_start $_ $com_end\n"); }
+		}
+	}
+
+sub main'public_label
+	{
+	$label{$_[0]}="${under}${_[0]}"	if (!defined($label{$_[0]}));
+	push(@out,".globl\t$label{$_[0]}\n");
+	}
+
+sub main'label
+	{
+	if (!defined($label{$_[0]}))
+		{
+		$label{$_[0]}="${dot}${label}${_[0]}";
+		$label++;
+		}
+	return($label{$_[0]});
+	}
+
+sub main'set_label
+	{
+	if (!defined($label{$_[0]}))
+		{
+		$label{$_[0]}="${dot}${label}${_[0]}";
+		$label++;
+		}
+	if ($_[1]!=0)
+		{
+		if ($_[1]>1)	{ main'align($_[1]);		}
+		else		{ push(@out,".align $align\n");	}
+		}
+	push(@out,"$label{$_[0]}:\n");
+	}
+
+sub main'file_end
+	{
+	# try to detect if SSE2 or MMX extensions were used on ELF platform...
+	if ($main'elf && grep {/\b%[x]*mm[0-7]\b|OPENSSL_ia32cap_P\b/i} @out) {
+		local($tmp);
+
+		push (@out,"\n.section\t.bss\n");
+		push (@out,".comm\t${under}OPENSSL_ia32cap_P,4,4\n");
+
+		return;
+	}
+
+	if ($const ne "")
+		{
+		push(@out,".section .rodata\n");
+		push(@out,$const);
+		$const="";
+		}
+	}
+
+sub main'data_byte
+	{
+	push(@out,"\t.byte\t".join(',', at _)."\n");
+	}
+
+sub main'data_word
+	{
+	push(@out,"\t.long\t".join(',', at _)."\n");
+	}
+
+sub main'align
+	{
+	my $val=$_[0],$p2,$i;
+	if ($main'aout) {
+		for ($p2=0;$val!=0;$val>>=1) { $p2++; }
+		$val=$p2-1;
+		$val.=",0x90";
+	}
+	push(@out,".align\t$val\n");
+	}
+
+# debug output functions: puts, putx, printf
+
+sub main'puts
+	{
+	&pushvars();
+	&main'push('$Lstring' . ++$constl);
+	&main'call('puts');
+	$stack-=4;
+	&main'add("esp",4);
+	&popvars();
+
+	$const .= "Lstring$constl:\n\t.string \"@_[0]\"\n";
+	}
+
+sub main'putx
+	{
+	&pushvars();
+	&main'push($_[0]);
+	&main'push('$Lstring' . ++$constl);
+	&main'call('printf');
+	&main'add("esp",8);
+	$stack-=8;
+	&popvars();
+
+	$const .= "Lstring$constl:\n\t.string \"\%X\"\n";
+	}
+
+sub main'printf
+	{
+	$ostack = $stack;
+	&pushvars();
+	for ($i = @_ - 1; $i >= 0; $i--)
+		{
+		if ($i == 0) # change this to support %s format strings
+			{
+			&main'push('$Lstring' . ++$constl);
+			$const .= "Lstring$constl:\n\t.string \"@_[$i]\"\n";
+			}
+		else
+			{
+			if ($_[$i] =~ /([0-9]*)\(%esp\)/)
+				{
+				&main'push(($1 + $stack - $ostack) . '(%esp)');
+				}
+			else
+				{
+				&main'push($_[$i]);
+				}
+			}
+		}
+	&main'call('printf');
+	$stack-=4*@_;
+	&main'add("esp",4*@_);
+	&popvars();
+	}
+
+sub pushvars
+	{
+	&main'pushf();
+	&main'push("edx");
+	&main'push("ecx");
+	&main'push("eax");
+	}
+
+sub popvars
+	{
+	&main'pop("eax");
+	&main'pop("ecx");
+	&main'pop("edx");
+	&main'popf();
+	}
+
+sub main'picmeup
+	{
+	local($dst,$sym)=@_;
+	if ($main'cpp)
+		{
+		local($tmp)=<<___;
+#if (defined(ELF) || defined(SOL)) && defined(PIC)
+	call	1f
+1:	popl	$regs{$dst}
+	addl	\$_GLOBAL_OFFSET_TABLE_+[.-1b],$regs{$dst}
+	movl	$sym\@GOT($regs{$dst}),$regs{$dst}
+#else
+	leal	$sym,$regs{$dst}
+#endif
+___
+		push(@out,$tmp);
+		}
+	elsif ($main'pic && ($main'elf || $main'aout))
+		{
+		&main'call(&main'label("PIC_me_up"));
+		&main'set_label("PIC_me_up");
+		&main'blindpop($dst);
+		&main'add($dst,"\$${under}_GLOBAL_OFFSET_TABLE_+[.-".
+				&main'label("PIC_me_up") . "]");
+		&main'mov($dst,&main'DWP($under.$sym."\@GOT",$dst));
+		}
+	else
+		{
+		&main'lea($dst,&main'DWP($sym));
+		}
+	}
+
+sub main'blindpop { &out1("popl", at _); }
+
+sub main'initseg
+	{
+	local($f)=@_;
+	local($tmp);
+	if ($main'elf)
+		{
+		$tmp=<<___;
+.section	.init
+	call	$under$f
+	jmp	.Linitalign
+.align	$align
+.Linitalign:
+___
+		}
+	elsif ($main'coff)
+		{
+		$tmp=<<___;	# applies to both Cygwin and Mingw
+.section	.ctors
+.long	$under$f
+___
+		}
+	elsif ($main'aout)
+		{
+		local($ctor)="${under}_GLOBAL_\$I\$$f";
+		$tmp=".text\n";
+		$tmp.=".type	$ctor,\@function\n" if ($main'pic);
+		$tmp.=<<___;	# OpenBSD way...
+.globl	$ctor
+.align	2
+$ctor:
+	jmp	$under$f
+___
+		}
+	push(@out,$tmp) if ($tmp);
+	}
+
+1;

Modified: openssl/branches/upstream/current/crypto/pkcs7/pk7_mime.c
===================================================================
--- openssl/branches/upstream/current/crypto/pkcs7/pk7_mime.c	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/crypto/pkcs7/pk7_mime.c	2009-05-16 15:25:35 UTC (rev 372)
@@ -1,5 +1,5 @@
 /* pk7_mime.c */
-/* Written by Dr Stephen N Henson (shenson at bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve at openssl.org) for the OpenSSL
  * project.
  */
 /* ====================================================================
@@ -377,57 +377,6 @@
 
 }
 
-/* Copy text from one BIO to another making the output CRLF at EOL */
-int SMIME_crlf_copy(BIO *in, BIO *out, int flags)
-{
-	char eol;
-	int len;
-	char linebuf[MAX_SMLEN];
-	if(flags & PKCS7_BINARY) {
-		while((len = BIO_read(in, linebuf, MAX_SMLEN)) > 0)
-						BIO_write(out, linebuf, len);
-		return 1;
-	}
-	if(flags & PKCS7_TEXT)
-		BIO_printf(out, "Content-Type: text/plain\r\n\r\n");
-	while ((len = BIO_gets(in, linebuf, MAX_SMLEN)) > 0) {
-		eol = strip_eol(linebuf, &len);
-		if (len)
-			BIO_write(out, linebuf, len);
-		if(eol) BIO_write(out, "\r\n", 2);
-	}
-	return 1;
-}
-
-/* Strip off headers if they are text/plain */
-int SMIME_text(BIO *in, BIO *out)
-{
-	char iobuf[4096];
-	int len;
-	STACK_OF(MIME_HEADER) *headers;
-	MIME_HEADER *hdr;
-
-	if (!(headers = mime_parse_hdr(in))) {
-		PKCS7err(PKCS7_F_SMIME_TEXT,PKCS7_R_MIME_PARSE_ERROR);
-		return 0;
-	}
-	if(!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) {
-		PKCS7err(PKCS7_F_SMIME_TEXT,PKCS7_R_MIME_NO_CONTENT_TYPE);
-		sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
-		return 0;
-	}
-	if (strcmp (hdr->value, "text/plain")) {
-		PKCS7err(PKCS7_F_SMIME_TEXT,PKCS7_R_INVALID_MIME_TYPE);
-		ERR_add_error_data(2, "type: ", hdr->value);
-		sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
-		return 0;
-	}
-	sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
-	while ((len = BIO_read(in, iobuf, sizeof(iobuf))) > 0)
-						BIO_write(out, iobuf, len);
-	return 1;
-}
-
 /* Split a multipart/XXX message body into component parts: result is
  * canonical parts in a STACK of bios
  */

Modified: openssl/branches/upstream/current/crypto/rand/md_rand.c
===================================================================
--- openssl/branches/upstream/current/crypto/rand/md_rand.c	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/crypto/rand/md_rand.c	2009-05-16 15:25:35 UTC (rev 372)
@@ -126,7 +126,11 @@
 
 #include <openssl/crypto.h>
 #include <openssl/err.h>
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
 
+
 #ifdef BN_DEBUG
 # define PREDICT
 #endif
@@ -332,6 +336,14 @@
 #endif
 	int do_stir_pool = 0;
 
+#ifdef OPENSSL_FIPS
+	if(FIPS_mode())
+	    {
+	    FIPSerr(FIPS_F_SSLEAY_RAND_BYTES,FIPS_R_NON_FIPS_METHOD);
+	    return 0;
+	    }
+#endif
+
 #ifdef PREDICT
 	if (rand_predictable)
 		{

Modified: openssl/branches/upstream/current/crypto/ripemd/ripemd.h
===================================================================
--- openssl/branches/upstream/current/crypto/ripemd/ripemd.h	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/crypto/ripemd/ripemd.h	2009-05-16 15:25:35 UTC (rev 372)
@@ -90,7 +90,9 @@
 	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);

Modified: openssl/branches/upstream/current/crypto/rsa/rsa.h
===================================================================
--- openssl/branches/upstream/current/crypto/rsa/rsa.h	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/crypto/rsa/rsa.h	2009-05-16 15:25:35 UTC (rev 372)
@@ -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 @@
 # 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 @@
 
 /* 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_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(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 @@
 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 @@
 /* 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 @@
 #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 @@
 #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

Modified: openssl/branches/upstream/current/crypto/rsa/rsa_eay.c
===================================================================
--- openssl/branches/upstream/current/crypto/rsa/rsa_eay.c	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/crypto/rsa/rsa_eay.c	2009-05-16 15:25:35 UTC (rev 372)
@@ -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 @@
 	return(&rsa_pkcs1_eay_meth);
 	}
 
-/* Usage example;
- *    MONT_HELPER(rsa, bn_ctx, p, rsa->flags & RSA_FLAG_CACHE_PRIVATE, goto err);
- */
-#define MONT_HELPER(rsa, ctx, m, pre_cond, err_instr) \
-	if((pre_cond) && ((rsa)->_method_mod_##m == NULL) && \
-			!BN_MONT_CTX_set_locked(&((rsa)->_method_mod_##m), \
-				CRYPTO_LOCK_RSA, \
-				(rsa)->m, (ctx))) \
-		err_instr
-
 static int RSA_eay_public_encrypt(int flen, const unsigned char *from,
 	     unsigned char *to, RSA *rsa, int padding)
 	{
@@ -227,13 +217,15 @@
 	if (BN_bin2bn(buf,num,f) == NULL) goto err;
 	
 	if (BN_ucmp(f, rsa->n) >= 0)
-		{	
+		{
 		/* usually the padding functions would catch this */
 		RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT,RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
 		goto err;
 		}
 
-	MONT_HELPER(rsa, ctx, 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;
@@ -436,9 +428,11 @@
 			BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
 			}
 		else
-			d = rsa->d;
+			d= rsa->d;
 
-		MONT_HELPER(rsa, ctx, 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 @@
 		else
 			d = rsa->d;
 
-		MONT_HELPER(rsa, ctx, 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 @@
 		goto err;
 		}
 
-	MONT_HELPER(rsa, ctx, 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;
@@ -717,7 +715,6 @@
 	BIGNUM *r1,*m1,*vrfy;
 	BIGNUM local_dmp1,local_dmq1,local_c,local_r1;
 	BIGNUM *dmp1,*dmq1,*c,*pr1;
-	int bn_flags;
 	int ret=0;
 
 	BN_CTX_start(ctx);
@@ -725,32 +722,42 @@
 	m1 = BN_CTX_get(ctx);
 	vrfy = BN_CTX_get(ctx);
 
-	/* Make sure mod_inverse in montgomerey intialization use correct 
-	 * BN_FLG_CONSTTIME flag.
-	 */
-	bn_flags = rsa->p->flags;
-	if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
-		{
-		rsa->p->flags |= BN_FLG_CONSTTIME;
-		}
-	MONT_HELPER(rsa, ctx, p, rsa->flags & RSA_FLAG_CACHE_PRIVATE, goto err);
-	/* We restore bn_flags back */
-	rsa->p->flags = bn_flags;
+	{
+		BIGNUM local_p, local_q;
+		BIGNUM *p = NULL, *q = NULL;
 
-        /* Make sure mod_inverse in montgomerey intialization use correct
-         * BN_FLG_CONSTTIME flag.
-         */
-	bn_flags = rsa->q->flags;
-	if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
-		{
-		rsa->q->flags |= BN_FLG_CONSTTIME;
-		}
-	MONT_HELPER(rsa, ctx, q, rsa->flags & RSA_FLAG_CACHE_PRIVATE, goto err);
-	/* We restore bn_flags back */
-	rsa->q->flags = bn_flags;	
+		/* Make sure BN_mod_inverse in Montgomery intialization uses the
+		 * BN_FLG_CONSTTIME flag (unless RSA_FLAG_NO_CONSTTIME is set)
+		 */
+		if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
+			{
+			BN_init(&local_p);
+			p = &local_p;
+			BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME);
 
-	MONT_HELPER(rsa, ctx, n, rsa->flags & RSA_FLAG_CACHE_PUBLIC, goto err);
+			BN_init(&local_q);
+			q = &local_q;
+			BN_with_flags(q, rsa->q, BN_FLG_CONSTTIME);
+			}
+		else
+			{
+			p = rsa->p;
+			q = rsa->q;
+			}
 
+		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;
+			}
+	}
+
+	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))
 		{

Modified: openssl/branches/upstream/current/crypto/rsa/rsa_err.c
===================================================================
--- openssl/branches/upstream/current/crypto/rsa/rsa_err.c	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/crypto/rsa/rsa_err.c	2009-05-16 15:25:35 UTC (rev 372)
@@ -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 @@
 {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 @@
 {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"},

Modified: openssl/branches/upstream/current/crypto/rsa/rsa_sign.c
===================================================================
--- openssl/branches/upstream/current/crypto/rsa/rsa_sign.c	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/crypto/rsa/rsa_sign.c	2009-05-16 15:25:35 UTC (rev 372)
@@ -90,6 +90,14 @@
 		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 @@
 		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;

Modified: openssl/branches/upstream/current/crypto/sha/sha.h
===================================================================
--- openssl/branches/upstream/current/crypto/sha/sha.h	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/crypto/sha/sha.h	2009-05-16 15:25:35 UTC (rev 372)
@@ -106,6 +106,9 @@
 	} 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);

Modified: openssl/branches/upstream/current/crypto/x509v3/pcy_tree.c
===================================================================
--- openssl/branches/upstream/current/crypto/x509v3/pcy_tree.c	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/crypto/x509v3/pcy_tree.c	2009-05-16 15:25:35 UTC (rev 372)
@@ -1,5 +1,5 @@
 /* pcy_tree.c */
-/* Written by Dr Stephen N Henson (shenson at bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve at openssl.org) for the OpenSSL
  * project 2004.
  */
 /* ====================================================================
@@ -130,9 +130,9 @@
 			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 @@
 			/* 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 @@
 		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 @@
 
 		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))
 			{

Added: openssl/branches/upstream/current/crypto/x509v3/v3_utl.c
===================================================================
--- openssl/branches/upstream/current/crypto/x509v3/v3_utl.c	                        (rev 0)
+++ openssl/branches/upstream/current/crypto/x509v3/v3_utl.c	2009-05-16 15:25:35 UTC (rev 372)
@@ -0,0 +1,871 @@
+/* v3_utl.c */
+/* Written by Dr Stephen N Henson (steve at openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2003 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 at 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 at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ *
+ */
+/* X509 v3 extension utilities */
+
+
+#include <stdio.h>
+#include <ctype.h>
+#include "cryptlib.h"
+#include <openssl/conf.h>
+#include <openssl/x509v3.h>
+#include <openssl/bn.h>
+
+static char *strip_spaces(char *name);
+static int sk_strcmp(const char * const *a, const char * const *b);
+static STACK *get_email(X509_NAME *name, GENERAL_NAMES *gens);
+static void str_free(void *str);
+static int append_ia5(STACK **sk, ASN1_IA5STRING *email);
+
+static int ipv4_from_asc(unsigned char *v4, const char *in);
+static int ipv6_from_asc(unsigned char *v6, const char *in);
+static int ipv6_cb(const char *elem, int len, void *usr);
+static int ipv6_hex(unsigned char *out, const char *in, int inlen);
+
+/* Add a CONF_VALUE name value pair to stack */
+
+int X509V3_add_value(const char *name, const char *value,
+						STACK_OF(CONF_VALUE) **extlist)
+{
+	CONF_VALUE *vtmp = NULL;
+	char *tname = NULL, *tvalue = NULL;
+	if(name && !(tname = BUF_strdup(name))) goto err;
+	if(value && !(tvalue = BUF_strdup(value))) goto err;
+	if(!(vtmp = (CONF_VALUE *)OPENSSL_malloc(sizeof(CONF_VALUE)))) goto err;
+	if(!*extlist && !(*extlist = sk_CONF_VALUE_new_null())) goto err;
+	vtmp->section = NULL;
+	vtmp->name = tname;
+	vtmp->value = tvalue;
+	if(!sk_CONF_VALUE_push(*extlist, vtmp)) goto err;
+	return 1;
+	err:
+	X509V3err(X509V3_F_X509V3_ADD_VALUE,ERR_R_MALLOC_FAILURE);
+	if(vtmp) OPENSSL_free(vtmp);
+	if(tname) OPENSSL_free(tname);
+	if(tvalue) OPENSSL_free(tvalue);
+	return 0;
+}
+
+int X509V3_add_value_uchar(const char *name, const unsigned char *value,
+			   STACK_OF(CONF_VALUE) **extlist)
+    {
+    return X509V3_add_value(name,(const char *)value,extlist);
+    }
+
+/* Free function for STACK_OF(CONF_VALUE) */
+
+void X509V3_conf_free(CONF_VALUE *conf)
+{
+	if(!conf) return;
+	if(conf->name) OPENSSL_free(conf->name);
+	if(conf->value) OPENSSL_free(conf->value);
+	if(conf->section) OPENSSL_free(conf->section);
+	OPENSSL_free(conf);
+}
+
+int X509V3_add_value_bool(const char *name, int asn1_bool,
+						STACK_OF(CONF_VALUE) **extlist)
+{
+	if(asn1_bool) return X509V3_add_value(name, "TRUE", extlist);
+	return X509V3_add_value(name, "FALSE", extlist);
+}
+
+int X509V3_add_value_bool_nf(char *name, int asn1_bool,
+						STACK_OF(CONF_VALUE) **extlist)
+{
+	if(asn1_bool) return X509V3_add_value(name, "TRUE", extlist);
+	return 1;
+}
+
+
+char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, ASN1_ENUMERATED *a)
+{
+	BIGNUM *bntmp = NULL;
+	char *strtmp = NULL;
+	if(!a) return NULL;
+	if(!(bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) ||
+	    !(strtmp = BN_bn2dec(bntmp)) )
+		X509V3err(X509V3_F_I2S_ASN1_ENUMERATED,ERR_R_MALLOC_FAILURE);
+	BN_free(bntmp);
+	return strtmp;
+}
+
+char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, ASN1_INTEGER *a)
+{
+	BIGNUM *bntmp = NULL;
+	char *strtmp = NULL;
+	if(!a) return NULL;
+	if(!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) ||
+	    !(strtmp = BN_bn2dec(bntmp)) )
+		X509V3err(X509V3_F_I2S_ASN1_INTEGER,ERR_R_MALLOC_FAILURE);
+	BN_free(bntmp);
+	return strtmp;
+}
+
+ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, char *value)
+{
+	BIGNUM *bn = NULL;
+	ASN1_INTEGER *aint;
+	int isneg, ishex;
+	int ret;
+	if (!value) {
+		X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_INVALID_NULL_VALUE);
+		return 0;
+	}
+	bn = BN_new();
+	if (value[0] == '-') {
+		value++;
+		isneg = 1;
+	} else isneg = 0;
+
+	if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) {
+		value += 2;
+		ishex = 1;
+	} else ishex = 0;
+
+	if (ishex) ret = BN_hex2bn(&bn, value);
+	else ret = BN_dec2bn(&bn, value);
+
+	if (!ret || value[ret]) {
+		BN_free(bn);
+		X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_BN_DEC2BN_ERROR);
+		return 0;
+	}
+
+	if (isneg && BN_is_zero(bn)) isneg = 0;
+
+	aint = BN_to_ASN1_INTEGER(bn, NULL);
+	BN_free(bn);
+	if (!aint) {
+		X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_BN_TO_ASN1_INTEGER_ERROR);
+		return 0;
+	}
+	if (isneg) aint->type |= V_ASN1_NEG;
+	return aint;
+}
+
+int X509V3_add_value_int(const char *name, ASN1_INTEGER *aint,
+	     STACK_OF(CONF_VALUE) **extlist)
+{
+	char *strtmp;
+	int ret;
+	if(!aint) return 1;
+	if(!(strtmp = i2s_ASN1_INTEGER(NULL, aint))) return 0;
+	ret = X509V3_add_value(name, strtmp, extlist);
+	OPENSSL_free(strtmp);
+	return ret;
+}
+
+int X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool)
+{
+	char *btmp;
+	if(!(btmp = value->value)) goto err;
+	if(!strcmp(btmp, "TRUE") || !strcmp(btmp, "true")
+		 || !strcmp(btmp, "Y") || !strcmp(btmp, "y")
+		|| !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) {
+		*asn1_bool = 0xff;
+		return 1;
+	} else if(!strcmp(btmp, "FALSE") || !strcmp(btmp, "false")
+		 || !strcmp(btmp, "N") || !strcmp(btmp, "n")
+		|| !strcmp(btmp, "NO") || !strcmp(btmp, "no")) {
+		*asn1_bool = 0;
+		return 1;
+	}
+	err:
+	X509V3err(X509V3_F_X509V3_GET_VALUE_BOOL,X509V3_R_INVALID_BOOLEAN_STRING);
+	X509V3_conf_err(value);
+	return 0;
+}
+
+int X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint)
+{
+	ASN1_INTEGER *itmp;
+	if(!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) {
+		X509V3_conf_err(value);
+		return 0;
+	}
+	*aint = itmp;
+	return 1;
+}
+
+#define HDR_NAME	1
+#define HDR_VALUE	2
+
+/*#define DEBUG*/
+
+STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line)
+{
+	char *p, *q, c;
+	char *ntmp, *vtmp;
+	STACK_OF(CONF_VALUE) *values = NULL;
+	char *linebuf;
+	int state;
+	/* We are going to modify the line so copy it first */
+	linebuf = BUF_strdup(line);
+	state = HDR_NAME;
+	ntmp = NULL;
+	/* Go through all characters */
+	for(p = linebuf, q = linebuf; (c = *p) && (c!='\r') && (c!='\n'); p++) {
+
+		switch(state) {
+			case HDR_NAME:
+			if(c == ':') {
+				state = HDR_VALUE;
+				*p = 0;
+				ntmp = strip_spaces(q);
+				if(!ntmp) {
+					X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME);
+					goto err;
+				}
+				q = p + 1;
+			} else if(c == ',') {
+				*p = 0;
+				ntmp = strip_spaces(q);
+				q = p + 1;
+#if 0
+				printf("%s\n", ntmp);
+#endif
+				if(!ntmp) {
+					X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME);
+					goto err;
+				}
+				X509V3_add_value(ntmp, NULL, &values);
+			}
+			break ;
+
+			case HDR_VALUE:
+			if(c == ',') {
+				state = HDR_NAME;
+				*p = 0;
+				vtmp = strip_spaces(q);
+#if 0
+				printf("%s\n", ntmp);
+#endif
+				if(!vtmp) {
+					X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_VALUE);
+					goto err;
+				}
+				X509V3_add_value(ntmp, vtmp, &values);
+				ntmp = NULL;
+				q = p + 1;
+			}
+
+		}
+	}
+
+	if(state == HDR_VALUE) {
+		vtmp = strip_spaces(q);
+#if 0
+		printf("%s=%s\n", ntmp, vtmp);
+#endif
+		if(!vtmp) {
+			X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_VALUE);
+			goto err;
+		}
+		X509V3_add_value(ntmp, vtmp, &values);
+	} else {
+		ntmp = strip_spaces(q);
+#if 0
+		printf("%s\n", ntmp);
+#endif
+		if(!ntmp) {
+			X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME);
+			goto err;
+		}
+		X509V3_add_value(ntmp, NULL, &values);
+	}
+OPENSSL_free(linebuf);
+return values;
+
+err:
+OPENSSL_free(linebuf);
+sk_CONF_VALUE_pop_free(values, X509V3_conf_free);
+return NULL;
+
+}
+
+/* Delete leading and trailing spaces from a string */
+static char *strip_spaces(char *name)
+{
+	char *p, *q;
+	/* Skip over leading spaces */
+	p = name;
+	while(*p && isspace((unsigned char)*p)) p++;
+	if(!*p) return NULL;
+	q = p + strlen(p) - 1;
+	while((q != p) && isspace((unsigned char)*q)) q--;
+	if(p != q) q[1] = 0;
+	if(!*p) return NULL;
+	return p;
+}
+
+/* hex string utilities */
+
+/* Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its
+ * hex representation
+ * @@@ (Contents of buffer are always kept in ASCII, also on EBCDIC machines)
+ */
+
+char *hex_to_string(unsigned char *buffer, long len)
+{
+	char *tmp, *q;
+	unsigned char *p;
+	int i;
+	const static char hexdig[] = "0123456789ABCDEF";
+	if(!buffer || !len) return NULL;
+	if(!(tmp = OPENSSL_malloc(len * 3 + 1))) {
+		X509V3err(X509V3_F_HEX_TO_STRING,ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+	q = tmp;
+	for(i = 0, p = buffer; i < len; i++,p++) {
+		*q++ = hexdig[(*p >> 4) & 0xf];
+		*q++ = hexdig[*p & 0xf];
+		*q++ = ':';
+	}
+	q[-1] = 0;
+#ifdef CHARSET_EBCDIC
+	ebcdic2ascii(tmp, tmp, q - tmp - 1);
+#endif
+
+	return tmp;
+}
+
+/* Give a string of hex digits convert to
+ * a buffer
+ */
+
+unsigned char *string_to_hex(char *str, long *len)
+{
+	unsigned char *hexbuf, *q;
+	unsigned char ch, cl, *p;
+	if(!str) {
+		X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_INVALID_NULL_ARGUMENT);
+		return NULL;
+	}
+	if(!(hexbuf = OPENSSL_malloc(strlen(str) >> 1))) goto err;
+	for(p = (unsigned char *)str, q = hexbuf; *p;) {
+		ch = *p++;
+#ifdef CHARSET_EBCDIC
+		ch = os_toebcdic[ch];
+#endif
+		if(ch == ':') continue;
+		cl = *p++;
+#ifdef CHARSET_EBCDIC
+		cl = os_toebcdic[cl];
+#endif
+		if(!cl) {
+			X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_ODD_NUMBER_OF_DIGITS);
+			OPENSSL_free(hexbuf);
+			return NULL;
+		}
+		if(isupper(ch)) ch = tolower(ch);
+		if(isupper(cl)) cl = tolower(cl);
+
+		if((ch >= '0') && (ch <= '9')) ch -= '0';
+		else if ((ch >= 'a') && (ch <= 'f')) ch -= 'a' - 10;
+		else goto badhex;
+
+		if((cl >= '0') && (cl <= '9')) cl -= '0';
+		else if ((cl >= 'a') && (cl <= 'f')) cl -= 'a' - 10;
+		else goto badhex;
+
+		*q++ = (ch << 4) | cl;
+	}
+
+	if(len) *len = q - hexbuf;
+
+	return hexbuf;
+
+	err:
+	if(hexbuf) OPENSSL_free(hexbuf);
+	X509V3err(X509V3_F_STRING_TO_HEX,ERR_R_MALLOC_FAILURE);
+	return NULL;
+
+	badhex:
+	OPENSSL_free(hexbuf);
+	X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_ILLEGAL_HEX_DIGIT);
+	return NULL;
+
+}
+
+/* V2I name comparison function: returns zero if 'name' matches
+ * cmp or cmp.*
+ */
+
+int name_cmp(const char *name, const char *cmp)
+{
+	int len, ret;
+	char c;
+	len = strlen(cmp);
+	if((ret = strncmp(name, cmp, len))) return ret;
+	c = name[len];
+	if(!c || (c=='.')) return 0;
+	return 1;
+}
+
+static int sk_strcmp(const char * const *a, const char * const *b)
+{
+	return strcmp(*a, *b);
+}
+
+STACK *X509_get1_email(X509 *x)
+{
+	GENERAL_NAMES *gens;
+	STACK *ret;
+	gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
+	ret = get_email(X509_get_subject_name(x), gens);
+	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
+	return ret;
+}
+
+STACK *X509_get1_ocsp(X509 *x)
+{
+	AUTHORITY_INFO_ACCESS *info;
+	STACK *ret = NULL;
+	int i;
+	info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL);
+	if (!info)
+		return NULL;
+	for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++)
+		{
+		ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i);
+		if (OBJ_obj2nid(ad->method) == NID_ad_OCSP)
+			{
+			if (ad->location->type == GEN_URI)
+				{
+				if (!append_ia5(&ret, ad->location->d.uniformResourceIdentifier))
+					break;
+				}
+			}
+		}
+	AUTHORITY_INFO_ACCESS_free(info);
+	return ret;
+}
+
+STACK *X509_REQ_get1_email(X509_REQ *x)
+{
+	GENERAL_NAMES *gens;
+	STACK_OF(X509_EXTENSION) *exts;
+	STACK *ret;
+	exts = X509_REQ_get_extensions(x);
+	gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL);
+	ret = get_email(X509_REQ_get_subject_name(x), gens);
+	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
+	sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
+	return ret;
+}
+
+
+static STACK *get_email(X509_NAME *name, GENERAL_NAMES *gens)
+{
+	STACK *ret = NULL;
+	X509_NAME_ENTRY *ne;
+	ASN1_IA5STRING *email;
+	GENERAL_NAME *gen;
+	int i;
+	/* Now add any email address(es) to STACK */
+	i = -1;
+	/* First supplied X509_NAME */
+	while((i = X509_NAME_get_index_by_NID(name,
+					 NID_pkcs9_emailAddress, i)) >= 0) {
+		ne = X509_NAME_get_entry(name, i);
+		email = X509_NAME_ENTRY_get_data(ne);
+		if(!append_ia5(&ret, email)) return NULL;
+	}
+	for(i = 0; i < sk_GENERAL_NAME_num(gens); i++)
+	{
+		gen = sk_GENERAL_NAME_value(gens, i);
+		if(gen->type != GEN_EMAIL) continue;
+		if(!append_ia5(&ret, gen->d.ia5)) return NULL;
+	}
+	return ret;
+}
+
+static void str_free(void *str)
+{
+	OPENSSL_free(str);
+}
+
+static int append_ia5(STACK **sk, ASN1_IA5STRING *email)
+{
+	char *emtmp;
+	/* First some sanity checks */
+	if(email->type != V_ASN1_IA5STRING) return 1;
+	if(!email->data || !email->length) return 1;
+	if(!*sk) *sk = sk_new(sk_strcmp);
+	if(!*sk) return 0;
+	/* Don't add duplicates */
+	if(sk_find(*sk, (char *)email->data) != -1) return 1;
+	emtmp = BUF_strdup((char *)email->data);
+	if(!emtmp || !sk_push(*sk, emtmp)) {
+		X509_email_free(*sk);
+		*sk = NULL;
+		return 0;
+	}
+	return 1;
+}
+
+void X509_email_free(STACK *sk)
+{
+	sk_pop_free(sk, str_free);
+}
+
+/* Convert IP addresses both IPv4 and IPv6 into an 
+ * OCTET STRING compatible with RFC3280.
+ */
+
+ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc)
+	{
+	unsigned char ipout[16];
+	ASN1_OCTET_STRING *ret;
+	int iplen;
+
+	/* If string contains a ':' assume IPv6 */
+
+	iplen = a2i_ipadd(ipout, ipasc);
+
+	if (!iplen)
+		return NULL;
+
+	ret = ASN1_OCTET_STRING_new();
+	if (!ret)
+		return NULL;
+	if (!ASN1_OCTET_STRING_set(ret, ipout, iplen))
+		{
+		ASN1_OCTET_STRING_free(ret);
+		return NULL;
+		}
+	return ret;
+	}
+
+ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc)
+	{
+	ASN1_OCTET_STRING *ret = NULL;
+	unsigned char ipout[32];
+	char *iptmp = NULL, *p;
+	int iplen1, iplen2;
+	p = strchr(ipasc,'/');
+	if (!p)
+		return NULL;
+	iptmp = BUF_strdup(ipasc);
+	if (!iptmp)
+		return NULL;
+	p = iptmp + (p - ipasc);
+	*p++ = 0;
+
+	iplen1 = a2i_ipadd(ipout, iptmp);
+
+	if (!iplen1)
+		goto err;
+
+	iplen2 = a2i_ipadd(ipout + iplen1, p);
+
+	OPENSSL_free(iptmp);
+	iptmp = NULL;
+
+	if (!iplen2 || (iplen1 != iplen2))
+		goto err;
+
+	ret = ASN1_OCTET_STRING_new();
+	if (!ret)
+		goto err;
+	if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2))
+		goto err;
+
+	return ret;
+
+	err:
+	if (iptmp)
+		OPENSSL_free(iptmp);
+	if (ret)
+		ASN1_OCTET_STRING_free(ret);
+	return NULL;
+	}
+	
+
+int a2i_ipadd(unsigned char *ipout, const char *ipasc)
+	{
+	/* If string contains a ':' assume IPv6 */
+
+	if (strchr(ipasc, ':'))
+		{
+		if (!ipv6_from_asc(ipout, ipasc))
+			return 0;
+		return 16;
+		}
+	else
+		{
+		if (!ipv4_from_asc(ipout, ipasc))
+			return 0;
+		return 4;
+		}
+	}
+
+static int ipv4_from_asc(unsigned char *v4, const char *in)
+	{
+	int a0, a1, a2, a3;
+	if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4)
+		return 0;
+	if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255)
+		|| (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255))
+		return 0;
+	v4[0] = a0;
+	v4[1] = a1;
+	v4[2] = a2;
+	v4[3] = a3;
+	return 1;
+	}
+
+typedef struct {
+		/* Temporary store for IPV6 output */
+		unsigned char tmp[16];
+		/* Total number of bytes in tmp */
+		int total;
+		/* The position of a zero (corresponding to '::') */
+		int zero_pos;
+		/* Number of zeroes */
+		int zero_cnt;
+	} IPV6_STAT;
+
+
+static int ipv6_from_asc(unsigned char *v6, const char *in)
+	{
+	IPV6_STAT v6stat;
+	v6stat.total = 0;
+	v6stat.zero_pos = -1;
+	v6stat.zero_cnt = 0;
+	/* Treat the IPv6 representation as a list of values
+	 * separated by ':'. The presence of a '::' will parse
+ 	 * as one, two or three zero length elements.
+	 */
+	if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat))
+		return 0;
+
+	/* Now for some sanity checks */
+
+	if (v6stat.zero_pos == -1)
+		{
+		/* If no '::' must have exactly 16 bytes */
+		if (v6stat.total != 16)
+			return 0;
+		}
+	else 
+		{
+		/* If '::' must have less than 16 bytes */
+		if (v6stat.total == 16)
+			return 0;
+		/* More than three zeroes is an error */
+		if (v6stat.zero_cnt > 3)
+			return 0;
+		/* Can only have three zeroes if nothing else present */
+		else if (v6stat.zero_cnt == 3)
+			{
+			if (v6stat.total > 0)
+				return 0;
+			}
+		/* Can only have two zeroes if at start or end */
+		else if (v6stat.zero_cnt == 2)
+			{
+			if ((v6stat.zero_pos != 0)
+				&& (v6stat.zero_pos != v6stat.total))
+				return 0;
+			}
+		else 
+		/* Can only have one zero if *not* start or end */
+			{
+			if ((v6stat.zero_pos == 0)
+				|| (v6stat.zero_pos == v6stat.total))
+				return 0;
+			}
+		}
+
+	/* Format result */
+
+	if (v6stat.zero_pos >= 0)
+		{
+		/* Copy initial part */
+		memcpy(v6, v6stat.tmp, v6stat.zero_pos);
+		/* 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);
+		}
+	else
+		memcpy(v6, v6stat.tmp, 16);
+
+	return 1;
+	}
+
+static int ipv6_cb(const char *elem, int len, void *usr)
+	{
+	IPV6_STAT *s = usr;
+	/* Error if 16 bytes written */
+	if (s->total == 16)
+		return 0;
+	if (len == 0)
+		{
+		/* Zero length element, corresponds to '::' */
+		if (s->zero_pos == -1)
+			s->zero_pos = s->total;
+		/* If we've already got a :: its an error */
+		else if (s->zero_pos != s->total)
+			return 0;
+		s->zero_cnt++;
+		}
+	else 
+		{
+		/* If more than 4 characters could be final a.b.c.d form */
+		if (len > 4)
+			{
+			/* Need at least 4 bytes left */
+			if (s->total > 12)
+				return 0;
+			/* Must be end of string */
+			if (elem[len])
+				return 0;
+			if (!ipv4_from_asc(s->tmp + s->total, elem))
+				return 0;
+			s->total += 4;
+			}
+		else
+			{
+			if (!ipv6_hex(s->tmp + s->total, elem, len))
+				return 0;
+			s->total += 2;
+			}
+		}
+	return 1;
+	}
+
+/* Convert a string of up to 4 hex digits into the corresponding
+ * IPv6 form.
+ */
+
+static int ipv6_hex(unsigned char *out, const char *in, int inlen)
+	{
+	unsigned char c;
+	unsigned int num = 0;
+	if (inlen > 4)
+		return 0;
+	while(inlen--)
+		{
+		c = *in++;
+		num <<= 4;
+		if ((c >= '0') && (c <= '9'))
+			num |= c - '0';
+		else if ((c >= 'A') && (c <= 'F'))
+			num |= c - 'A' + 10;
+		else if ((c >= 'a') && (c <= 'f'))
+			num |=  c - 'a' + 10;
+		else
+			return 0;
+		}
+	out[0] = num >> 8;
+	out[1] = num & 0xff;
+	return 1;
+	}
+
+
+int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE)*dn_sk,
+						unsigned long chtype)
+	{
+	CONF_VALUE *v;
+	int i, mval;
+	char *p, *type;
+	if (!nm)
+		return 0;
+
+	for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++)
+		{
+		v=sk_CONF_VALUE_value(dn_sk,i);
+		type=v->name;
+		/* Skip past any leading X. X: X, etc to allow for
+		 * multiple instances 
+		 */
+		for(p = type; *p ; p++) 
+#ifndef CHARSET_EBCDIC
+			if ((*p == ':') || (*p == ',') || (*p == '.'))
+#else
+			if ((*p == os_toascii[':']) || (*p == os_toascii[',']) || (*p == os_toascii['.']))
+#endif
+				{
+				p++;
+				if(*p) type = p;
+				break;
+				}
+#ifndef CHARSET_EBCDIC
+		if (*type == '+')
+#else
+		if (*type == os_toascii['+'])
+#endif
+			{
+			mval = -1;
+			type++;
+			}
+		else
+			mval = 0;
+		if (!X509_NAME_add_entry_by_txt(nm,type, chtype,
+				(unsigned char *) v->value,-1,-1,mval))
+					return 0;
+
+		}
+	return 1;
+	}

Modified: openssl/branches/upstream/current/crypto/x86_64cpuid.pl
===================================================================
--- openssl/branches/upstream/current/crypto/x86_64cpuid.pl	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/crypto/x86_64cpuid.pl	2009-05-16 15:25:35 UTC (rev 372)
@@ -1,19 +1,12 @@
 #!/usr/bin/env perl
 
 $output=shift;
-$win64a=1 if ($output =~ /win64a\.[s|asm]/);
+$masm=1 if ($output =~ /\.asm/);
 open STDOUT,">$output" || die "can't open $output: $!";
 
-print<<___ if(defined($win64a));
+print<<___ if(defined($masm));
 _TEXT	SEGMENT
 PUBLIC	OPENSSL_rdtsc
-ALIGN	16
-OPENSSL_rdtsc	PROC
-	rdtsc
-	shl	rdx,32
-	or	rax,rdx
-	ret
-OPENSSL_rdtsc	ENDP
 
 PUBLIC	OPENSSL_atomic_add
 ALIGN	16
@@ -45,35 +38,16 @@
 	lea	rax,QWORD PTR[rsp+8]
 	ret
 OPENSSL_wipe_cpu	ENDP
-
-OPENSSL_ia32_cpuid	PROC
-	mov	r8,rbx
-	mov	eax,1
-	cpuid
-	shl	rcx,32
-	mov	eax,edx
-	mov	rbx,r8
-	or	rax,rcx
-	ret
-OPENSSL_ia32_cpuid	ENDP
 _TEXT	ENDS
 
 CRT\$XIU	SEGMENT
 EXTRN	OPENSSL_cpuid_setup:PROC
 DQ	OPENSSL_cpuid_setup
 CRT\$XIU	ENDS
-END
+
 ___
-print<<___ if(!defined($win64a));
+print<<___ if(!defined($masm));
 .text
-.globl	OPENSSL_rdtsc
-.align	16
-OPENSSL_rdtsc:
-	rdtsc
-	shlq	\$32,%rdx
-	orq	%rdx,%rax
-	ret
-.size	OPENSSL_rdtsc,.-OPENSSL_rdtsc
 
 .globl	OPENSSL_atomic_add
 .type	OPENSSL_atomic_add,\@function
@@ -120,19 +94,66 @@
 	ret
 .size	OPENSSL_wipe_cpu,.-OPENSSL_wipe_cpu
 
+.section	.init
+	call	OPENSSL_cpuid_setup
+
+___
+
+open STDOUT,"| $^X perlasm/x86_64-xlate.pl $output";
+print<<___;
+.text
+
+.globl	OPENSSL_rdtsc
+.type	OPENSSL_rdtsc,\@abi-omnipotent
+.align	16
+OPENSSL_rdtsc:
+	rdtsc
+	shl	\$32,%rdx
+	or	%rdx,%rax
+	ret
+.size	OPENSSL_rdtsc,.-OPENSSL_rdtsc
+
 .globl	OPENSSL_ia32_cpuid
+.type	OPENSSL_ia32_cpuid,\@abi-omnipotent
 .align	16
 OPENSSL_ia32_cpuid:
-	movq	%rbx,%r8
-	movl	\$1,%eax
+	mov	%rbx,%r8
+
+	xor	%eax,%eax
 	cpuid
-	shlq	\$32,%rcx
-	movl	%edx,%eax
-	movq	%r8,%rbx
-	orq	%rcx,%rax
+	xor	%eax,%eax
+	cmp	\$0x756e6547,%ebx	# "Genu"
+	setne	%al
+	mov	%eax,%r9d
+	cmp	\$0x49656e69,%edx	# "ineI"
+	setne	%al
+	or	%eax,%r9d
+	cmp	\$0x6c65746e,%ecx	# "ntel"
+	setne	%al
+	or	%eax,%r9d
+
+	mov	\$1,%eax
+	cpuid
+	cmp	\$0,%r9d
+	jne	.Lnotintel
+	or	\$0x00100000,%edx	# use reserved 20th bit to engage RC4_CHAR
+	and	\$15,%ah
+	cmp	\$15,%ah		# examine Family ID
+	je	.Lnotintel
+	or	\$0x40000000,%edx	# use reserved bit to skip unrolled loop
+.Lnotintel:
+	bt	\$28,%edx		# test hyper-threading bit
+	jnc	.Ldone
+	shr	\$16,%ebx
+	cmp	\$1,%bl			# see if cache is shared
+	ja	.Ldone
+	and	\$0xefffffff,%edx	# ~(1<<28)
+.Ldone:
+	shl	\$32,%rcx
+	mov	%edx,%eax
+	mov	%r8,%rbx
+	or	%rcx,%rax
 	ret
 .size	OPENSSL_ia32_cpuid,.-OPENSSL_ia32_cpuid
-
-.section	.init
-	call	OPENSSL_cpuid_setup
 ___
+close STDOUT;	# flush

Added: openssl/branches/upstream/current/crypto/x86cpuid.pl
===================================================================
--- openssl/branches/upstream/current/crypto/x86cpuid.pl	                        (rev 0)
+++ openssl/branches/upstream/current/crypto/x86cpuid.pl	2009-05-16 15:25:35 UTC (rev 372)
@@ -0,0 +1,225 @@
+#!/usr/bin/env perl
+
+push(@INC,"perlasm");
+require "x86asm.pl";
+
+&asm_init($ARGV[0],"x86cpuid");
+
+for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); }
+
+&function_begin("OPENSSL_ia32_cpuid");
+	&xor	("edx","edx");
+	&pushf	();
+	&pop	("eax");
+	&mov	("ecx","eax");
+	&xor	("eax",1<<21);
+	&push	("eax");
+	&popf	();
+	&pushf	();
+	&pop	("eax");
+	&xor	("ecx","eax");
+	&bt	("ecx",21);
+	&jnc	(&label("done"));
+	&xor	("eax","eax");
+	&cpuid	();
+	&xor	("eax","eax");
+	&cmp	("ebx",0x756e6547);	# "Genu"
+	&data_byte(0x0f,0x95,0xc0);	#&setne	(&LB("eax"));
+	&mov	("ebp","eax");
+	&cmp	("edx",0x49656e69);	# "ineI"
+	&data_byte(0x0f,0x95,0xc0);	#&setne	(&LB("eax"));
+	&or	("ebp","eax");
+	&cmp	("ecx",0x6c65746e);	# "ntel"
+	&data_byte(0x0f,0x95,0xc0);	#&setne	(&LB("eax"));
+	&or	("ebp","eax");
+	&mov	("eax",1);
+	&cpuid	();
+	&cmp	("ebp",0);
+	&jne	(&label("notP4"));
+	&and	("eax",15<<8);		# familiy ID
+	&cmp	("eax",15<<8);		# P4?
+	&jne	(&label("notP4"));
+	&or	("edx",1<<20);		# use reserved bit to engage RC4_CHAR
+&set_label("notP4");
+	&bt	("edx",28);		# test hyper-threading bit
+	&jnc	(&label("done"));
+	&shr	("ebx",16);
+	&and	("ebx",0xff);
+	&cmp	("ebx",1);		# see if cache is shared(*)
+	&ja	(&label("done"));
+	&and	("edx",0xefffffff);	# clear hyper-threading bit if not
+&set_label("done");
+	&mov	("eax","edx");
+	&mov	("edx","ecx");
+&function_end("OPENSSL_ia32_cpuid");
+# (*)	on Core2 this value is set to 2 denoting the fact that L2
+#	cache is shared between cores.
+
+&external_label("OPENSSL_ia32cap_P");
+
+&function_begin_B("OPENSSL_rdtsc","EXTRN\t_OPENSSL_ia32cap_P:DWORD");
+	&xor	("eax","eax");
+	&xor	("edx","edx");
+	&picmeup("ecx","OPENSSL_ia32cap_P");
+	&bt	(&DWP(0,"ecx"),4);
+	&jnc	(&label("notsc"));
+	&rdtsc	();
+&set_label("notsc");
+	&ret	();
+&function_end_B("OPENSSL_rdtsc");
+
+# This works in Ring 0 only [read DJGPP+MS-DOS+privileged DPMI host],
+# but it's safe to call it on any [supported] 32-bit platform...
+# Just check for [non-]zero return value...
+&function_begin_B("OPENSSL_instrument_halt","EXTRN\t_OPENSSL_ia32cap_P:DWORD");
+	&picmeup("ecx","OPENSSL_ia32cap_P");
+	&bt	(&DWP(0,"ecx"),4);
+	&jnc	(&label("nohalt"));	# no TSC
+
+	&data_word(0x9058900e);		# push %cs; pop %eax
+	&and	("eax",3);
+	&jnz	(&label("nohalt"));	# not enough privileges
+
+	&pushf	();
+	&pop	("eax")
+	&bt	("eax",9);
+	&jnc	(&label("nohalt"));	# interrupts are disabled
+
+	&rdtsc	();
+	&push	("edx");
+	&push	("eax");
+	&halt	();
+	&rdtsc	();
+
+	&sub	("eax",&DWP(0,"esp"));
+	&sbb	("edx",&DWP(4,"esp"));
+	&add	("esp",8);
+	&ret	();
+
+&set_label("nohalt");
+	&xor	("eax","eax");
+	&xor	("edx","edx");
+	&ret	();
+&function_end_B("OPENSSL_instrument_halt");
+
+# Essentially there is only one use for this function. Under DJGPP:
+#
+#	#include <go32.h>
+#	...
+#	i=OPENSSL_far_spin(_dos_ds,0x46c);
+#	...
+# to obtain the number of spins till closest timer interrupt.
+
+&function_begin_B("OPENSSL_far_spin");
+	&pushf	();
+	&pop	("eax")
+	&bt	("eax",9);
+	&jnc	(&label("nospin"));	# interrupts are disabled
+
+	&mov	("eax",&DWP(4,"esp"));
+	&mov	("ecx",&DWP(8,"esp"));
+	&data_word (0x90d88e1e);	# push %ds, mov %eax,%ds
+	&xor	("eax","eax");
+	&mov	("edx",&DWP(0,"ecx"));
+	&jmp	(&label("spin"));
+
+	&align	(16);
+&set_label("spin");
+	&inc	("eax");
+	&cmp	("edx",&DWP(0,"ecx"));
+	&je	(&label("spin"));
+
+	&data_word (0x1f909090);	# pop	%ds
+	&ret	();
+
+&set_label("nospin");
+	&xor	("eax","eax");
+	&xor	("edx","edx");
+	&ret	();
+&function_end_B("OPENSSL_far_spin");
+
+&function_begin_B("OPENSSL_wipe_cpu","EXTRN\t_OPENSSL_ia32cap_P:DWORD");
+	&xor	("eax","eax");
+	&xor	("edx","edx");
+	&picmeup("ecx","OPENSSL_ia32cap_P");
+	&mov	("ecx",&DWP(0,"ecx"));
+	&bt	(&DWP(0,"ecx"),1);
+	&jnc	(&label("no_x87"));
+	if ($sse2) {
+		&bt	(&DWP(0,"ecx"),26);
+		&jnc	(&label("no_sse2"));
+		&pxor	("xmm0","xmm0");
+		&pxor	("xmm1","xmm1");
+		&pxor	("xmm2","xmm2");
+		&pxor	("xmm3","xmm3");
+		&pxor	("xmm4","xmm4");
+		&pxor	("xmm5","xmm5");
+		&pxor	("xmm6","xmm6");
+		&pxor	("xmm7","xmm7");
+	&set_label("no_sse2");
+	}
+	# just a bunch of fldz to zap the fp/mm bank followed by finit...
+	&data_word(0xeed9eed9,0xeed9eed9,0xeed9eed9,0xeed9eed9,0x90e3db9b);
+&set_label("no_x87");
+	&lea	("eax",&DWP(4,"esp"));
+	&ret	();
+&function_end_B("OPENSSL_wipe_cpu");
+
+&function_begin_B("OPENSSL_atomic_add");
+	&mov	("edx",&DWP(4,"esp"));	# fetch the pointer, 1st arg
+	&mov	("ecx",&DWP(8,"esp"));	# fetch the increment, 2nd arg
+	&push	("ebx");
+	&nop	();
+	&mov	("eax",&DWP(0,"edx"));
+&set_label("spin");
+	&lea	("ebx",&DWP(0,"eax","ecx"));
+	&nop	();
+	&data_word(0x1ab10ff0);	# lock;	cmpxchg	%ebx,(%edx)	# %eax is envolved and is always reloaded
+	&jne	(&label("spin"));
+	&mov	("eax","ebx");	# OpenSSL expects the new value
+	&pop	("ebx");
+	&ret	();
+&function_end_B("OPENSSL_atomic_add");
+
+# This function can become handy under Win32 in situations when
+# we don't know which calling convention, __stdcall or __cdecl(*),
+# indirect callee is using. In C it can be deployed as
+#
+#ifdef OPENSSL_CPUID_OBJ
+#	type OPENSSL_indirect_call(void *f,...);
+#	...
+#	OPENSSL_indirect_call(func,[up to $max arguments]);
+#endif
+#
+# (*)	it's designed to work even for __fastcall if number of
+#	arguments is 1 or 2!
+&function_begin_B("OPENSSL_indirect_call");
+	{
+	my $i,$max=7;		# $max has to be chosen as 4*n-1
+				# in order to preserve eventual
+				# stack alignment
+	&push	("ebp");
+	&mov	("ebp","esp");
+	&sub	("esp",$max*4);
+	&mov	("ecx",&DWP(12,"ebp"));
+	&mov	(&DWP(0,"esp"),"ecx");
+	&mov	("edx",&DWP(16,"ebp"));
+	&mov	(&DWP(4,"esp"),"edx");
+	for($i=2;$i<$max;$i++)
+		{
+		# Some copies will be redundant/bogus...
+		&mov	("eax",&DWP(12+$i*4,"ebp"));
+		&mov	(&DWP(0+$i*4,"esp"),"eax");
+		}
+	&call_ptr	(&DWP(8,"ebp"));# make the call...
+	&mov	("esp","ebp");	# ... and just restore the stack pointer
+				# without paying attention to what we called,
+				# (__cdecl *func) or (__stdcall *one).
+	&pop	("ebp");
+	&ret	();
+	}
+&function_end_B("OPENSSL_indirect_call");
+
+&initseg("OPENSSL_cpuid_setup");
+
+&asm_finish();

Modified: openssl/branches/upstream/current/engines/Makefile
===================================================================
--- openssl/branches/upstream/current/engines/Makefile	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/engines/Makefile	2009-05-16 15:25:35 UTC (rev 372)
@@ -20,7 +20,7 @@
 APPS=
 
 LIB=$(TOP)/libcrypto.a
-LIBNAMES= 4758cca aep atalla cswift gmp chil nuron sureware ubsec
+LIBNAMES= 4758cca aep atalla cswift gmp chil nuron sureware ubsec capi
 
 LIBSRC=	e_4758cca.c \
 	e_aep.c \
@@ -30,7 +30,8 @@
 	e_chil.c \
 	e_nuron.c \
 	e_sureware.c \
-	e_ubsec.c
+	e_ubsec.c \
+	e_capi.c
 LIBOBJ= e_4758cca.o \
 	e_aep.o \
 	e_atalla.o \
@@ -39,7 +40,8 @@
 	e_chil.o \
 	e_nuron.o \
 	e_sureware.o \
-	e_ubsec.o
+	e_ubsec.o \
+	e_capi.o
 
 SRC= $(LIBSRC)
 
@@ -52,7 +54,8 @@
 	e_chil_err.c e_chil_err.h \
 	e_nuron_err.c e_nuron_err.h \
 	e_sureware_err.c e_sureware_err.h \
-	e_ubsec_err.c e_ubsec_err.h
+	e_ubsec_err.c e_ubsec_err.h \
+	e_capi_err.c e_capi_err.h
 
 ALL=    $(GENERAL) $(SRC) $(HEADER)
 
@@ -143,38 +146,61 @@
 e_4758cca.o: ../include/openssl/e_os2.h ../include/openssl/ec.h
 e_4758cca.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h
 e_4758cca.o: ../include/openssl/engine.h ../include/openssl/err.h
-e_4758cca.o: ../include/openssl/evp.h ../include/openssl/lhash.h
-e_4758cca.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
-e_4758cca.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
-e_4758cca.o: ../include/openssl/ossl_typ.h ../include/openssl/pkcs7.h
-e_4758cca.o: ../include/openssl/rand.h ../include/openssl/rsa.h
-e_4758cca.o: ../include/openssl/safestack.h ../include/openssl/sha.h
-e_4758cca.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
-e_4758cca.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h
-e_4758cca.o: e_4758cca.c e_4758cca_err.c e_4758cca_err.h
-e_4758cca.o: vendor_defns/hw_4758_cca.h
+e_4758cca.o: ../include/openssl/evp.h ../include/openssl/fips.h
+e_4758cca.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h
+e_4758cca.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
+e_4758cca.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
+e_4758cca.o: ../include/openssl/pkcs7.h ../include/openssl/rand.h
+e_4758cca.o: ../include/openssl/rsa.h ../include/openssl/safestack.h
+e_4758cca.o: ../include/openssl/sha.h ../include/openssl/stack.h
+e_4758cca.o: ../include/openssl/symhacks.h ../include/openssl/x509.h
+e_4758cca.o: ../include/openssl/x509_vfy.h e_4758cca.c e_4758cca_err.c
+e_4758cca.o: e_4758cca_err.h vendor_defns/hw_4758_cca.h
 e_aep.o: ../include/openssl/asn1.h ../include/openssl/bio.h
 e_aep.o: ../include/openssl/bn.h ../include/openssl/buffer.h
 e_aep.o: ../include/openssl/crypto.h ../include/openssl/dh.h
 e_aep.o: ../include/openssl/dsa.h ../include/openssl/dso.h
-e_aep.o: ../include/openssl/e_os2.h ../include/openssl/engine.h
-e_aep.o: ../include/openssl/err.h ../include/openssl/lhash.h
-e_aep.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
-e_aep.o: ../include/openssl/ossl_typ.h ../include/openssl/rsa.h
-e_aep.o: ../include/openssl/safestack.h ../include/openssl/stack.h
-e_aep.o: ../include/openssl/symhacks.h e_aep.c e_aep_err.c e_aep_err.h
-e_aep.o: vendor_defns/aep.h
+e_aep.o: ../include/openssl/e_os2.h ../include/openssl/ec.h
+e_aep.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h
+e_aep.o: ../include/openssl/engine.h ../include/openssl/err.h
+e_aep.o: ../include/openssl/evp.h ../include/openssl/fips.h
+e_aep.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h
+e_aep.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
+e_aep.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
+e_aep.o: ../include/openssl/pkcs7.h ../include/openssl/rsa.h
+e_aep.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+e_aep.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+e_aep.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h e_aep.c
+e_aep.o: e_aep_err.c e_aep_err.h vendor_defns/aep.h
 e_atalla.o: ../include/openssl/asn1.h ../include/openssl/bio.h
 e_atalla.o: ../include/openssl/bn.h ../include/openssl/buffer.h
 e_atalla.o: ../include/openssl/crypto.h ../include/openssl/dh.h
 e_atalla.o: ../include/openssl/dsa.h ../include/openssl/dso.h
-e_atalla.o: ../include/openssl/e_os2.h ../include/openssl/engine.h
-e_atalla.o: ../include/openssl/err.h ../include/openssl/lhash.h
-e_atalla.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
-e_atalla.o: ../include/openssl/ossl_typ.h ../include/openssl/rsa.h
-e_atalla.o: ../include/openssl/safestack.h ../include/openssl/stack.h
-e_atalla.o: ../include/openssl/symhacks.h e_atalla.c e_atalla_err.c
-e_atalla.o: e_atalla_err.h vendor_defns/atalla.h
+e_atalla.o: ../include/openssl/e_os2.h ../include/openssl/ec.h
+e_atalla.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h
+e_atalla.o: ../include/openssl/engine.h ../include/openssl/err.h
+e_atalla.o: ../include/openssl/evp.h ../include/openssl/fips.h
+e_atalla.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h
+e_atalla.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
+e_atalla.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
+e_atalla.o: ../include/openssl/pkcs7.h ../include/openssl/rsa.h
+e_atalla.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+e_atalla.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+e_atalla.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h e_atalla.c
+e_atalla.o: e_atalla_err.c e_atalla_err.h vendor_defns/atalla.h
+e_capi.o: ../include/openssl/asn1.h ../include/openssl/bio.h
+e_capi.o: ../include/openssl/bn.h ../include/openssl/buffer.h
+e_capi.o: ../include/openssl/crypto.h ../include/openssl/e_os2.h
+e_capi.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+e_capi.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h
+e_capi.o: ../include/openssl/evp.h ../include/openssl/fips.h
+e_capi.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h
+e_capi.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
+e_capi.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
+e_capi.o: ../include/openssl/pkcs7.h ../include/openssl/rsa.h
+e_capi.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+e_capi.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+e_capi.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h e_capi.c
 e_chil.o: ../include/openssl/asn1.h ../include/openssl/bio.h
 e_chil.o: ../include/openssl/bn.h ../include/openssl/buffer.h
 e_chil.o: ../include/openssl/crypto.h ../include/openssl/dh.h
@@ -182,42 +208,63 @@
 e_chil.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
 e_chil.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h
 e_chil.o: ../include/openssl/err.h ../include/openssl/evp.h
-e_chil.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h
-e_chil.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
-e_chil.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
-e_chil.o: ../include/openssl/pem.h ../include/openssl/pem2.h
-e_chil.o: ../include/openssl/pkcs7.h ../include/openssl/rand.h
-e_chil.o: ../include/openssl/rsa.h ../include/openssl/safestack.h
-e_chil.o: ../include/openssl/sha.h ../include/openssl/stack.h
-e_chil.o: ../include/openssl/symhacks.h ../include/openssl/ui.h
-e_chil.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h e_chil.c
-e_chil.o: e_chil_err.c e_chil_err.h vendor_defns/hwcryptohook.h
+e_chil.o: ../include/openssl/fips.h ../include/openssl/lhash.h
+e_chil.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+e_chil.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+e_chil.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+e_chil.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+e_chil.o: ../include/openssl/rand.h ../include/openssl/rsa.h
+e_chil.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+e_chil.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+e_chil.o: ../include/openssl/ui.h ../include/openssl/x509.h
+e_chil.o: ../include/openssl/x509_vfy.h e_chil.c e_chil_err.c e_chil_err.h
+e_chil.o: vendor_defns/hwcryptohook.h
 e_cswift.o: ../include/openssl/asn1.h ../include/openssl/bio.h
 e_cswift.o: ../include/openssl/bn.h ../include/openssl/buffer.h
 e_cswift.o: ../include/openssl/crypto.h ../include/openssl/dh.h
 e_cswift.o: ../include/openssl/dsa.h ../include/openssl/dso.h
-e_cswift.o: ../include/openssl/e_os2.h ../include/openssl/engine.h
-e_cswift.o: ../include/openssl/err.h ../include/openssl/lhash.h
-e_cswift.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
-e_cswift.o: ../include/openssl/ossl_typ.h ../include/openssl/rand.h
+e_cswift.o: ../include/openssl/e_os2.h ../include/openssl/ec.h
+e_cswift.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h
+e_cswift.o: ../include/openssl/engine.h ../include/openssl/err.h
+e_cswift.o: ../include/openssl/evp.h ../include/openssl/fips.h
+e_cswift.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h
+e_cswift.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
+e_cswift.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
+e_cswift.o: ../include/openssl/pkcs7.h ../include/openssl/rand.h
 e_cswift.o: ../include/openssl/rsa.h ../include/openssl/safestack.h
-e_cswift.o: ../include/openssl/stack.h ../include/openssl/symhacks.h e_cswift.c
-e_cswift.o: e_cswift_err.c e_cswift_err.h vendor_defns/cswift.h
-e_gmp.o: ../include/openssl/buffer.h ../include/openssl/crypto.h
-e_gmp.o: ../include/openssl/e_os2.h ../include/openssl/engine.h
-e_gmp.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
-e_gmp.o: ../include/openssl/ossl_typ.h ../include/openssl/safestack.h
-e_gmp.o: ../include/openssl/stack.h ../include/openssl/symhacks.h e_gmp.c
+e_cswift.o: ../include/openssl/sha.h ../include/openssl/stack.h
+e_cswift.o: ../include/openssl/symhacks.h ../include/openssl/x509.h
+e_cswift.o: ../include/openssl/x509_vfy.h e_cswift.c e_cswift_err.c
+e_cswift.o: e_cswift_err.h vendor_defns/cswift.h
+e_gmp.o: ../include/openssl/asn1.h ../include/openssl/bio.h
+e_gmp.o: ../include/openssl/bn.h ../include/openssl/buffer.h
+e_gmp.o: ../include/openssl/crypto.h ../include/openssl/e_os2.h
+e_gmp.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+e_gmp.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h
+e_gmp.o: ../include/openssl/evp.h ../include/openssl/fips.h
+e_gmp.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h
+e_gmp.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
+e_gmp.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
+e_gmp.o: ../include/openssl/pkcs7.h ../include/openssl/rsa.h
+e_gmp.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+e_gmp.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+e_gmp.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h e_gmp.c
 e_nuron.o: ../include/openssl/asn1.h ../include/openssl/bio.h
 e_nuron.o: ../include/openssl/bn.h ../include/openssl/buffer.h
 e_nuron.o: ../include/openssl/crypto.h ../include/openssl/dh.h
 e_nuron.o: ../include/openssl/dsa.h ../include/openssl/dso.h
-e_nuron.o: ../include/openssl/e_os2.h ../include/openssl/engine.h
-e_nuron.o: ../include/openssl/err.h ../include/openssl/lhash.h
-e_nuron.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
-e_nuron.o: ../include/openssl/ossl_typ.h ../include/openssl/rsa.h
-e_nuron.o: ../include/openssl/safestack.h ../include/openssl/stack.h
-e_nuron.o: ../include/openssl/symhacks.h e_nuron.c e_nuron_err.c e_nuron_err.h
+e_nuron.o: ../include/openssl/e_os2.h ../include/openssl/ec.h
+e_nuron.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h
+e_nuron.o: ../include/openssl/engine.h ../include/openssl/err.h
+e_nuron.o: ../include/openssl/evp.h ../include/openssl/fips.h
+e_nuron.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h
+e_nuron.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
+e_nuron.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
+e_nuron.o: ../include/openssl/pkcs7.h ../include/openssl/rsa.h
+e_nuron.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+e_nuron.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+e_nuron.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h e_nuron.c
+e_nuron.o: e_nuron_err.c e_nuron_err.h
 e_sureware.o: ../include/openssl/asn1.h ../include/openssl/bio.h
 e_sureware.o: ../include/openssl/bn.h ../include/openssl/buffer.h
 e_sureware.o: ../include/openssl/crypto.h ../include/openssl/dh.h
@@ -225,25 +272,30 @@
 e_sureware.o: ../include/openssl/e_os2.h ../include/openssl/ec.h
 e_sureware.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h
 e_sureware.o: ../include/openssl/engine.h ../include/openssl/err.h
-e_sureware.o: ../include/openssl/evp.h ../include/openssl/lhash.h
-e_sureware.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
-e_sureware.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
-e_sureware.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
-e_sureware.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
-e_sureware.o: ../include/openssl/rand.h ../include/openssl/rsa.h
-e_sureware.o: ../include/openssl/safestack.h ../include/openssl/sha.h
-e_sureware.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
-e_sureware.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h
-e_sureware.o: e_sureware.c e_sureware_err.c e_sureware_err.h
-e_sureware.o: vendor_defns/sureware.h
+e_sureware.o: ../include/openssl/evp.h ../include/openssl/fips.h
+e_sureware.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h
+e_sureware.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
+e_sureware.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
+e_sureware.o: ../include/openssl/pem.h ../include/openssl/pem2.h
+e_sureware.o: ../include/openssl/pkcs7.h ../include/openssl/rand.h
+e_sureware.o: ../include/openssl/rsa.h ../include/openssl/safestack.h
+e_sureware.o: ../include/openssl/sha.h ../include/openssl/stack.h
+e_sureware.o: ../include/openssl/symhacks.h ../include/openssl/x509.h
+e_sureware.o: ../include/openssl/x509_vfy.h e_sureware.c e_sureware_err.c
+e_sureware.o: e_sureware_err.h vendor_defns/sureware.h
 e_ubsec.o: ../include/openssl/asn1.h ../include/openssl/bio.h
 e_ubsec.o: ../include/openssl/bn.h ../include/openssl/buffer.h
 e_ubsec.o: ../include/openssl/crypto.h ../include/openssl/dh.h
 e_ubsec.o: ../include/openssl/dsa.h ../include/openssl/dso.h
-e_ubsec.o: ../include/openssl/e_os2.h ../include/openssl/engine.h
-e_ubsec.o: ../include/openssl/err.h ../include/openssl/lhash.h
-e_ubsec.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
-e_ubsec.o: ../include/openssl/ossl_typ.h ../include/openssl/rsa.h
-e_ubsec.o: ../include/openssl/safestack.h ../include/openssl/stack.h
-e_ubsec.o: ../include/openssl/symhacks.h e_ubsec.c e_ubsec_err.c e_ubsec_err.h
-e_ubsec.o: vendor_defns/hw_ubsec.h
+e_ubsec.o: ../include/openssl/e_os2.h ../include/openssl/ec.h
+e_ubsec.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h
+e_ubsec.o: ../include/openssl/engine.h ../include/openssl/err.h
+e_ubsec.o: ../include/openssl/evp.h ../include/openssl/fips.h
+e_ubsec.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h
+e_ubsec.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
+e_ubsec.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
+e_ubsec.o: ../include/openssl/pkcs7.h ../include/openssl/rsa.h
+e_ubsec.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+e_ubsec.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+e_ubsec.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h e_ubsec.c
+e_ubsec.o: e_ubsec_err.c e_ubsec_err.h vendor_defns/hw_ubsec.h

Modified: openssl/branches/upstream/current/ssl/s2_clnt.c
===================================================================
--- openssl/branches/upstream/current/ssl/s2_clnt.c	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/ssl/s2_clnt.c	2009-05-16 15:25:35 UTC (rev 372)
@@ -1044,7 +1044,7 @@
 
 	i=ssl_verify_cert_chain(s,sk);
 		
-	if ((s->verify_mode != SSL_VERIFY_NONE) && (!i))
+	if ((s->verify_mode != SSL_VERIFY_NONE) && (i <= 0))
 		{
 		SSLerr(SSL_F_SSL2_SET_CERTIFICATE,SSL_R_CERTIFICATE_VERIFY_FAILED);
 		goto err;

Added: openssl/branches/upstream/current/ssl/s2_srvr.c
===================================================================
--- openssl/branches/upstream/current/ssl/s2_srvr.c	                        (rev 0)
+++ openssl/branches/upstream/current/ssl/s2_srvr.c	2009-05-16 15:25:35 UTC (rev 372)
@@ -0,0 +1,1143 @@
+/* ssl/s2_srvr.c */
+/* Copyright (C) 1995-1998 Eric Young (eay at cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay at cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh at cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay at cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh at cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core at 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 at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ *
+ */
+
+#include "ssl_locl.h"
+#ifndef OPENSSL_NO_SSL2
+#include <stdio.h>
+#include <openssl/bio.h>
+#include <openssl/rand.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+
+static SSL_METHOD *ssl2_get_server_method(int ver);
+static int get_client_master_key(SSL *s);
+static int get_client_hello(SSL *s);
+static int server_hello(SSL *s); 
+static int get_client_finished(SSL *s);
+static int server_verify(SSL *s);
+static int server_finish(SSL *s);
+static int request_certificate(SSL *s);
+static int ssl_rsa_private_decrypt(CERT *c, int len, unsigned char *from,
+	unsigned char *to,int padding);
+#define BREAK	break
+
+static SSL_METHOD *ssl2_get_server_method(int ver)
+	{
+	if (ver == SSL2_VERSION)
+		return(SSLv2_server_method());
+	else
+		return(NULL);
+	}
+
+IMPLEMENT_ssl2_meth_func(SSLv2_server_method,
+			ssl2_accept,
+			ssl_undefined_function,
+			ssl2_get_server_method)
+
+int ssl2_accept(SSL *s)
+	{
+	unsigned long l=(unsigned long)time(NULL);
+	BUF_MEM *buf=NULL;
+	int ret= -1;
+	long num1;
+	void (*cb)(const SSL *ssl,int type,int val)=NULL;
+	int new_state,state;
+
+	RAND_add(&l,sizeof(l),0);
+	ERR_clear_error();
+	clear_sys_error();
+
+	if (s->info_callback != NULL)
+		cb=s->info_callback;
+	else if (s->ctx->info_callback != NULL)
+		cb=s->ctx->info_callback;
+
+	/* init things to blank */
+	s->in_handshake++;
+	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);
+
+	if (s->cert == NULL)
+		{
+		SSLerr(SSL_F_SSL2_ACCEPT,SSL_R_NO_CERTIFICATE_SET);
+		return(-1);
+		}
+
+	clear_sys_error();
+	for (;;)
+		{
+		state=s->state;
+
+		switch (s->state)
+			{
+		case SSL_ST_BEFORE:
+		case SSL_ST_ACCEPT:
+		case SSL_ST_BEFORE|SSL_ST_ACCEPT:
+		case SSL_ST_OK|SSL_ST_ACCEPT:
+
+			s->server=1;
+			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
+
+			s->version=SSL2_VERSION;
+			s->type=SSL_ST_ACCEPT;
+
+			buf=s->init_buf;
+			if ((buf == NULL) && ((buf=BUF_MEM_new()) == NULL))
+				{ ret= -1; goto end; }
+			if (!BUF_MEM_grow(buf,(int)
+				SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER))
+				{ ret= -1; goto end; }
+			s->init_buf=buf;
+			s->init_num=0;
+			s->ctx->stats.sess_accept++;
+			s->handshake_func=ssl2_accept;
+			s->state=SSL2_ST_GET_CLIENT_HELLO_A;
+			BREAK;
+
+		case SSL2_ST_GET_CLIENT_HELLO_A:
+		case SSL2_ST_GET_CLIENT_HELLO_B:
+		case SSL2_ST_GET_CLIENT_HELLO_C:
+			s->shutdown=0;
+			ret=get_client_hello(s);
+			if (ret <= 0) goto end;
+			s->init_num=0;
+			s->state=SSL2_ST_SEND_SERVER_HELLO_A;
+			BREAK;
+
+		case SSL2_ST_SEND_SERVER_HELLO_A:
+		case SSL2_ST_SEND_SERVER_HELLO_B:
+			ret=server_hello(s);
+			if (ret <= 0) goto end;
+			s->init_num=0;
+			if (!s->hit)
+				{
+				s->state=SSL2_ST_GET_CLIENT_MASTER_KEY_A;
+				BREAK;
+				}
+			else
+				{
+				s->state=SSL2_ST_SERVER_START_ENCRYPTION;
+				BREAK;
+				}
+		case SSL2_ST_GET_CLIENT_MASTER_KEY_A:
+		case SSL2_ST_GET_CLIENT_MASTER_KEY_B:
+			ret=get_client_master_key(s);
+			if (ret <= 0) goto end;
+			s->init_num=0;
+			s->state=SSL2_ST_SERVER_START_ENCRYPTION;
+			BREAK;
+
+		case SSL2_ST_SERVER_START_ENCRYPTION:
+			/* Ok we how have sent all the stuff needed to
+			 * start encrypting, the next packet back will
+			 * be encrypted. */
+			if (!ssl2_enc_init(s,0))
+				{ ret= -1; goto end; }
+			s->s2->clear_text=0;
+			s->state=SSL2_ST_SEND_SERVER_VERIFY_A;
+			BREAK;
+
+		case SSL2_ST_SEND_SERVER_VERIFY_A:
+		case SSL2_ST_SEND_SERVER_VERIFY_B:
+			ret=server_verify(s);
+			if (ret <= 0) goto end;
+			s->init_num=0;
+			if (s->hit)
+				{
+				/* If we are in here, we have been
+				 * buffering the output, so we need to
+				 * flush it and remove buffering from
+				 * future traffic */
+				s->state=SSL2_ST_SEND_SERVER_VERIFY_C;
+				BREAK;
+				}
+			else
+				{
+				s->state=SSL2_ST_GET_CLIENT_FINISHED_A;
+				break;
+				}
+
+ 		case SSL2_ST_SEND_SERVER_VERIFY_C:
+ 			/* get the number of bytes to write */
+ 			num1=BIO_ctrl(s->wbio,BIO_CTRL_INFO,0,NULL);
+ 			if (num1 != 0)
+ 				{
+				s->rwstate=SSL_WRITING;
+ 				num1=BIO_flush(s->wbio);
+ 				if (num1 <= 0) { ret= -1; goto end; }
+				s->rwstate=SSL_NOTHING;
+				}
+
+ 			/* flushed and now remove buffering */
+ 			s->wbio=BIO_pop(s->wbio);
+
+ 			s->state=SSL2_ST_GET_CLIENT_FINISHED_A;
+  			BREAK;
+
+		case SSL2_ST_GET_CLIENT_FINISHED_A:
+		case SSL2_ST_GET_CLIENT_FINISHED_B:
+			ret=get_client_finished(s);
+			if (ret <= 0)
+				goto end;
+			s->init_num=0;
+			s->state=SSL2_ST_SEND_REQUEST_CERTIFICATE_A;
+			BREAK;
+
+		case SSL2_ST_SEND_REQUEST_CERTIFICATE_A:
+		case SSL2_ST_SEND_REQUEST_CERTIFICATE_B:
+		case SSL2_ST_SEND_REQUEST_CERTIFICATE_C:
+		case SSL2_ST_SEND_REQUEST_CERTIFICATE_D:
+			/* don't do a 'request certificate' if we
+			 * don't want to, or we already have one, and
+			 * we only want to do it once. */
+			if (!(s->verify_mode & SSL_VERIFY_PEER) ||
+				((s->session->peer != NULL) &&
+				(s->verify_mode & SSL_VERIFY_CLIENT_ONCE)))
+				{
+				s->state=SSL2_ST_SEND_SERVER_FINISHED_A;
+				break;
+				}
+			else
+				{
+				ret=request_certificate(s);
+				if (ret <= 0) goto end;
+				s->init_num=0;
+				s->state=SSL2_ST_SEND_SERVER_FINISHED_A;
+				}
+			BREAK;
+
+		case SSL2_ST_SEND_SERVER_FINISHED_A:
+		case SSL2_ST_SEND_SERVER_FINISHED_B:
+			ret=server_finish(s);
+			if (ret <= 0) goto end;
+			s->init_num=0;
+			s->state=SSL_ST_OK;
+			break;
+
+		case SSL_ST_OK:
+			BUF_MEM_free(s->init_buf);
+			ssl_free_wbio_buffer(s);
+			s->init_buf=NULL;
+			s->init_num=0;
+		/*	ERR_clear_error();*/
+
+			ssl_update_cache(s,SSL_SESS_CACHE_SERVER);
+
+			s->ctx->stats.sess_accept_good++;
+			/* s->server=1; */
+			ret=1;
+
+			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1);
+
+			goto end;
+			/* BREAK; */
+
+		default:
+			SSLerr(SSL_F_SSL2_ACCEPT,SSL_R_UNKNOWN_STATE);
+			ret= -1;
+			goto end;
+			/* BREAK; */
+			}
+		
+		if ((cb != NULL) && (s->state != state))
+			{
+			new_state=s->state;
+			s->state=state;
+			cb(s,SSL_CB_ACCEPT_LOOP,1);
+			s->state=new_state;
+			}
+		}
+end:
+	s->in_handshake--;
+	if (cb != NULL)
+		cb(s,SSL_CB_ACCEPT_EXIT,ret);
+	return(ret);
+	}
+
+static int get_client_master_key(SSL *s)
+	{
+	int is_export,i,n,keya,ek;
+	unsigned long len;
+	unsigned char *p;
+	SSL_CIPHER *cp;
+	const EVP_CIPHER *c;
+	const EVP_MD *md;
+
+	p=(unsigned char *)s->init_buf->data;
+	if (s->state == SSL2_ST_GET_CLIENT_MASTER_KEY_A)
+		{
+		i=ssl2_read(s,(char *)&(p[s->init_num]),10-s->init_num);
+
+		if (i < (10-s->init_num))
+			return(ssl2_part_read(s,SSL_F_GET_CLIENT_MASTER_KEY,i));
+		s->init_num = 10;
+
+		if (*(p++) != SSL2_MT_CLIENT_MASTER_KEY)
+			{
+			if (p[-1] != SSL2_MT_ERROR)
+				{
+				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+				SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_READ_WRONG_PACKET_TYPE);
+				}
+			else
+				SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, SSL_R_PEER_ERROR);
+			return(-1);
+			}
+
+		cp=ssl2_get_cipher_by_char(p);
+		if (cp == NULL)
+			{
+			ssl2_return_error(s,SSL2_PE_NO_CIPHER);
+			SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, SSL_R_NO_CIPHER_MATCH);
+			return(-1);
+			}
+		s->session->cipher= cp;
+
+		p+=3;
+		n2s(p,i); s->s2->tmp.clear=i;
+		n2s(p,i); s->s2->tmp.enc=i;
+		n2s(p,i); s->session->key_arg_length=i;
+		if(s->session->key_arg_length > SSL_MAX_KEY_ARG_LENGTH)
+			{
+			ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+			SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, SSL_R_KEY_ARG_TOO_LONG);
+			return -1;
+			}
+		s->state=SSL2_ST_GET_CLIENT_MASTER_KEY_B;
+		}
+
+	/* SSL2_ST_GET_CLIENT_MASTER_KEY_B */
+	p=(unsigned char *)s->init_buf->data;
+	if (s->init_buf->length < SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER)
+		{
+		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+		SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, ERR_R_INTERNAL_ERROR);
+		return -1;
+		}
+	keya=s->session->key_arg_length;
+	len = 10 + (unsigned long)s->s2->tmp.clear + (unsigned long)s->s2->tmp.enc + (unsigned long)keya;
+	if (len > SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER)
+		{
+		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+		SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_MESSAGE_TOO_LONG);
+		return -1;
+		}
+	n = (int)len - s->init_num;
+	i = ssl2_read(s,(char *)&(p[s->init_num]),n);
+	if (i != n) return(ssl2_part_read(s,SSL_F_GET_CLIENT_MASTER_KEY,i));
+	if (s->msg_callback)
+		s->msg_callback(0, s->version, 0, p, (size_t)len, s, s->msg_callback_arg); /* CLIENT-MASTER-KEY */
+	p += 10;
+
+	memcpy(s->session->key_arg,&(p[s->s2->tmp.clear+s->s2->tmp.enc]),
+		(unsigned int)keya);
+
+	if (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL)
+		{
+		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+		SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_NO_PRIVATEKEY);
+		return(-1);
+		}
+	i=ssl_rsa_private_decrypt(s->cert,s->s2->tmp.enc,
+		&(p[s->s2->tmp.clear]),&(p[s->s2->tmp.clear]),
+		(s->s2->ssl2_rollback)?RSA_SSLV23_PADDING:RSA_PKCS1_PADDING);
+
+	is_export=SSL_C_IS_EXPORT(s->session->cipher);
+	
+	if (!ssl_cipher_get_evp(s->session,&c,&md,NULL))
+		{
+		ssl2_return_error(s,SSL2_PE_NO_CIPHER);
+		SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS);
+		return(0);
+		}
+
+	if (s->session->cipher->algorithm2 & SSL2_CF_8_BYTE_ENC)
+		{
+		is_export=1;
+		ek=8;
+		}
+	else
+		ek=5;
+
+	/* bad decrypt */
+#if 1
+	/* If a bad decrypt, continue with protocol but with a
+	 * random master secret (Bleichenbacher attack) */
+	if ((i < 0) ||
+		((!is_export && (i != EVP_CIPHER_key_length(c)))
+		|| (is_export && ((i != ek) || (s->s2->tmp.clear+(unsigned int)i !=
+			(unsigned int)EVP_CIPHER_key_length(c))))))
+		{
+		ERR_clear_error();
+		if (is_export)
+			i=ek;
+		else
+			i=EVP_CIPHER_key_length(c);
+		if (RAND_pseudo_bytes(p,i) <= 0)
+			return 0;
+		}
+#else
+	if (i < 0)
+		{
+		error=1;
+		SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_BAD_RSA_DECRYPT);
+		}
+	/* incorrect number of key bytes for non export cipher */
+	else if ((!is_export && (i != EVP_CIPHER_key_length(c)))
+		|| (is_export && ((i != ek) || (s->s2->tmp.clear+i !=
+			EVP_CIPHER_key_length(c)))))
+		{
+		error=1;
+		SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_WRONG_NUMBER_OF_KEY_BITS);
+		}
+	if (error)
+		{
+		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+		return(-1);
+		}
+#endif
+
+	if (is_export) i+=s->s2->tmp.clear;
+
+	if (i > SSL_MAX_MASTER_KEY_LENGTH)
+		{
+		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+		SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, ERR_R_INTERNAL_ERROR);
+		return -1;
+		}
+	s->session->master_key_length=i;
+	memcpy(s->session->master_key,p,(unsigned int)i);
+	return(1);
+	}
+
+static int get_client_hello(SSL *s)
+	{
+	int i,n;
+	unsigned long len;
+	unsigned char *p;
+	STACK_OF(SSL_CIPHER) *cs; /* a stack of SSL_CIPHERS */
+	STACK_OF(SSL_CIPHER) *cl; /* the ones we want to use */
+	STACK_OF(SSL_CIPHER) *prio, *allow;
+	int z;
+
+	/* This is a bit of a hack to check for the correct packet
+	 * type the first time round. */
+	if (s->state == SSL2_ST_GET_CLIENT_HELLO_A)
+		{
+		s->first_packet=1;
+		s->state=SSL2_ST_GET_CLIENT_HELLO_B;
+		}
+
+	p=(unsigned char *)s->init_buf->data;
+	if (s->state == SSL2_ST_GET_CLIENT_HELLO_B)
+		{
+		i=ssl2_read(s,(char *)&(p[s->init_num]),9-s->init_num);
+		if (i < (9-s->init_num)) 
+			return(ssl2_part_read(s,SSL_F_GET_CLIENT_HELLO,i));
+		s->init_num = 9;
+	
+		if (*(p++) != SSL2_MT_CLIENT_HELLO)
+			{
+			if (p[-1] != SSL2_MT_ERROR)
+				{
+				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+				SSLerr(SSL_F_GET_CLIENT_HELLO,SSL_R_READ_WRONG_PACKET_TYPE);
+				}
+			else
+				SSLerr(SSL_F_GET_CLIENT_HELLO,SSL_R_PEER_ERROR);
+			return(-1);
+			}
+		n2s(p,i);
+		if (i < s->version) s->version=i;
+		n2s(p,i); s->s2->tmp.cipher_spec_length=i;
+		n2s(p,i); s->s2->tmp.session_id_length=i;
+		n2s(p,i); s->s2->challenge_length=i;
+		if (	(i < SSL2_MIN_CHALLENGE_LENGTH) ||
+			(i > SSL2_MAX_CHALLENGE_LENGTH))
+			{
+			ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+			SSLerr(SSL_F_GET_CLIENT_HELLO,SSL_R_INVALID_CHALLENGE_LENGTH);
+			return(-1);
+			}
+		s->state=SSL2_ST_GET_CLIENT_HELLO_C;
+		}
+
+	/* SSL2_ST_GET_CLIENT_HELLO_C */
+	p=(unsigned char *)s->init_buf->data;
+	len = 9 + (unsigned long)s->s2->tmp.cipher_spec_length + (unsigned long)s->s2->challenge_length + (unsigned long)s->s2->tmp.session_id_length;
+	if (len > SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER)
+		{
+		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+		SSLerr(SSL_F_GET_CLIENT_HELLO,SSL_R_MESSAGE_TOO_LONG);
+		return -1;
+		}
+	n = (int)len - s->init_num;
+	i = ssl2_read(s,(char *)&(p[s->init_num]),n);
+	if (i != n) return(ssl2_part_read(s,SSL_F_GET_CLIENT_HELLO,i));
+	if (s->msg_callback)
+		s->msg_callback(0, s->version, 0, p, (size_t)len, s, s->msg_callback_arg); /* CLIENT-HELLO */
+	p += 9;
+
+	/* get session-id before cipher stuff so we can get out session
+	 * structure if it is cached */
+	/* session-id */
+	if ((s->s2->tmp.session_id_length != 0) && 
+		(s->s2->tmp.session_id_length != SSL2_SSL_SESSION_ID_LENGTH))
+		{
+		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+		SSLerr(SSL_F_GET_CLIENT_HELLO,SSL_R_BAD_SSL_SESSION_ID_LENGTH);
+		return(-1);
+		}
+
+	if (s->s2->tmp.session_id_length == 0)
+		{
+		if (!ssl_get_new_session(s,1))
+			{
+			ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+			return(-1);
+			}
+		}
+	else
+		{
+		i=ssl_get_prev_session(s,&(p[s->s2->tmp.cipher_spec_length]),
+			s->s2->tmp.session_id_length, NULL);
+		if (i == 1)
+			{ /* previous session */
+			s->hit=1;
+			}
+		else if (i == -1)
+			{
+			ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+			return(-1);
+			}
+		else
+			{
+			if (s->cert == NULL)
+				{
+				ssl2_return_error(s,SSL2_PE_NO_CERTIFICATE);
+				SSLerr(SSL_F_GET_CLIENT_HELLO,SSL_R_NO_CERTIFICATE_SET);
+				return(-1);
+				}
+
+			if (!ssl_get_new_session(s,1))
+				{
+				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+				return(-1);
+				}
+			}
+		}
+
+	if (!s->hit)
+		{
+		cs=ssl_bytes_to_cipher_list(s,p,s->s2->tmp.cipher_spec_length,
+			&s->session->ciphers);
+		if (cs == NULL) goto mem_err;
+
+		cl=SSL_get_ciphers(s);
+
+		if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE)
+		    {
+		    prio=sk_SSL_CIPHER_dup(cl);
+		    if (prio == NULL) goto mem_err;
+		    allow = cs;
+		    }
+		else
+		    {
+		    prio = cs;
+		    allow = cl;
+		    }
+		for (z=0; z<sk_SSL_CIPHER_num(prio); z++)
+			{
+			if (sk_SSL_CIPHER_find(allow,sk_SSL_CIPHER_value(prio,z)) < 0)
+				{
+				(void)sk_SSL_CIPHER_delete(prio,z);
+				z--;
+				}
+			}
+		if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE)
+		    {
+		    sk_SSL_CIPHER_free(s->session->ciphers);
+		    s->session->ciphers = prio;
+		    }
+		/* s->session->ciphers should now have a list of
+		 * ciphers that are on both the client and server.
+		 * This list is ordered by the order the client sent
+		 * the ciphers or in the order of the server's preference
+		 * if SSL_OP_CIPHER_SERVER_PREFERENCE was set.
+		 */
+		}
+	p+=s->s2->tmp.cipher_spec_length;
+	/* done cipher selection */
+
+	/* session id extracted already */
+	p+=s->s2->tmp.session_id_length;
+
+	/* challenge */
+	if (s->s2->challenge_length > sizeof s->s2->challenge)
+		{
+		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+		SSLerr(SSL_F_GET_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+		return -1;
+		}
+	memcpy(s->s2->challenge,p,(unsigned int)s->s2->challenge_length);
+	return(1);
+mem_err:
+	SSLerr(SSL_F_GET_CLIENT_HELLO,ERR_R_MALLOC_FAILURE);
+	return(0);
+	}
+
+static int server_hello(SSL *s)
+	{
+	unsigned char *p,*d;
+	int n,hit;
+	STACK_OF(SSL_CIPHER) *sk;
+
+	p=(unsigned char *)s->init_buf->data;
+	if (s->state == SSL2_ST_SEND_SERVER_HELLO_A)
+		{
+		d=p+11;
+		*(p++)=SSL2_MT_SERVER_HELLO;		/* type */
+		hit=s->hit;
+		*(p++)=(unsigned char)hit;
+#if 1
+		if (!hit)
+			{
+			if (s->session->sess_cert != NULL)
+				/* This can't really happen because get_client_hello
+				 * has called ssl_get_new_session, which does not set
+				 * sess_cert. */
+				ssl_sess_cert_free(s->session->sess_cert);
+			s->session->sess_cert = ssl_sess_cert_new();
+			if (s->session->sess_cert == NULL)
+				{
+				SSLerr(SSL_F_SERVER_HELLO, ERR_R_MALLOC_FAILURE);
+				return(-1);
+				}
+			}
+		/* If 'hit' is set, then s->sess_cert may be non-NULL or NULL,
+		 * depending on whether it survived in the internal cache
+		 * or was retrieved from an external cache.
+		 * If it is NULL, we cannot put any useful data in it anyway,
+		 * so we don't touch it.
+		 */
+
+#else /* That's what used to be done when cert_st and sess_cert_st were
+	   * the same. */
+		if (!hit)
+			{			/* else add cert to session */
+			CRYPTO_add(&s->cert->references,1,CRYPTO_LOCK_SSL_CERT);
+			if (s->session->sess_cert != NULL)
+				ssl_cert_free(s->session->sess_cert);
+			s->session->sess_cert=s->cert;		
+			}
+		else	/* We have a session id-cache hit, if the
+			 * session-id has no certificate listed against
+			 * the 'cert' structure, grab the 'old' one
+			 * listed against the SSL connection */
+			{
+			if (s->session->sess_cert == NULL)
+				{
+				CRYPTO_add(&s->cert->references,1,
+					CRYPTO_LOCK_SSL_CERT);
+				s->session->sess_cert=s->cert;
+				}
+			}
+#endif
+
+		if (s->cert == NULL)
+			{
+			ssl2_return_error(s,SSL2_PE_NO_CERTIFICATE);
+			SSLerr(SSL_F_SERVER_HELLO,SSL_R_NO_CERTIFICATE_SPECIFIED);
+			return(-1);
+			}
+
+		if (hit)
+			{
+			*(p++)=0;		/* no certificate type */
+			s2n(s->version,p);	/* version */
+			s2n(0,p);		/* cert len */
+			s2n(0,p);		/* ciphers len */
+			}
+		else
+			{
+			/* EAY EAY */
+			/* put certificate type */
+			*(p++)=SSL2_CT_X509_CERTIFICATE;
+			s2n(s->version,p);	/* version */
+			n=i2d_X509(s->cert->pkeys[SSL_PKEY_RSA_ENC].x509,NULL);
+			s2n(n,p);		/* certificate length */
+			i2d_X509(s->cert->pkeys[SSL_PKEY_RSA_ENC].x509,&d);
+			n=0;
+			
+			/* lets send out the ciphers we like in the
+			 * prefered order */
+			sk= s->session->ciphers;
+			n=ssl_cipher_list_to_bytes(s,s->session->ciphers,d,0);
+			d+=n;
+			s2n(n,p);		/* add cipher length */
+			}
+
+		/* make and send conn_id */
+		s2n(SSL2_CONNECTION_ID_LENGTH,p);	/* add conn_id length */
+		s->s2->conn_id_length=SSL2_CONNECTION_ID_LENGTH;
+		if (RAND_pseudo_bytes(s->s2->conn_id,(int)s->s2->conn_id_length) <= 0)
+			return -1;
+		memcpy(d,s->s2->conn_id,SSL2_CONNECTION_ID_LENGTH);
+		d+=SSL2_CONNECTION_ID_LENGTH;
+
+		s->state=SSL2_ST_SEND_SERVER_HELLO_B;
+		s->init_num=d-(unsigned char *)s->init_buf->data;
+		s->init_off=0;
+		}
+	/* SSL2_ST_SEND_SERVER_HELLO_B */
+ 	/* If we are using TCP/IP, the performance is bad if we do 2
+ 	 * writes without a read between them.  This occurs when
+ 	 * Session-id reuse is used, so I will put in a buffering module
+ 	 */
+ 	if (s->hit)
+ 		{
+		if (!ssl_init_wbio_buffer(s,1)) return(-1);
+ 		}
+ 
+	return(ssl2_do_write(s));
+	}
+
+static int get_client_finished(SSL *s)
+	{
+	unsigned char *p;
+	int i, n;
+	unsigned long len;
+
+	p=(unsigned char *)s->init_buf->data;
+	if (s->state == SSL2_ST_GET_CLIENT_FINISHED_A)
+		{
+		i=ssl2_read(s,(char *)&(p[s->init_num]),1-s->init_num);
+		if (i < 1-s->init_num)
+			return(ssl2_part_read(s,SSL_F_GET_CLIENT_FINISHED,i));
+		s->init_num += i;
+
+		if (*p != SSL2_MT_CLIENT_FINISHED)
+			{
+			if (*p != SSL2_MT_ERROR)
+				{
+				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+				SSLerr(SSL_F_GET_CLIENT_FINISHED,SSL_R_READ_WRONG_PACKET_TYPE);
+				}
+			else
+				{
+				SSLerr(SSL_F_GET_CLIENT_FINISHED,SSL_R_PEER_ERROR);
+				/* try to read the error message */
+				i=ssl2_read(s,(char *)&(p[s->init_num]),3-s->init_num);
+				return ssl2_part_read(s,SSL_F_GET_SERVER_VERIFY,i);
+				}
+			return(-1);
+			}
+		s->state=SSL2_ST_GET_CLIENT_FINISHED_B;
+		}
+
+	/* SSL2_ST_GET_CLIENT_FINISHED_B */
+	if (s->s2->conn_id_length > sizeof s->s2->conn_id)
+		{
+		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+		SSLerr(SSL_F_GET_CLIENT_FINISHED, ERR_R_INTERNAL_ERROR);
+		return -1;
+		}
+	len = 1 + (unsigned long)s->s2->conn_id_length;
+	n = (int)len - s->init_num;
+	i = ssl2_read(s,(char *)&(p[s->init_num]),n);
+	if (i < n)
+		{
+		return(ssl2_part_read(s,SSL_F_GET_CLIENT_FINISHED,i));
+		}
+	if (s->msg_callback)
+		s->msg_callback(0, s->version, 0, p, len, s, s->msg_callback_arg); /* CLIENT-FINISHED */
+	p += 1;
+	if (memcmp(p,s->s2->conn_id,s->s2->conn_id_length) != 0)
+		{
+		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+		SSLerr(SSL_F_GET_CLIENT_FINISHED,SSL_R_CONNECTION_ID_IS_DIFFERENT);
+		return(-1);
+		}
+	return(1);
+	}
+
+static int server_verify(SSL *s)
+	{
+	unsigned char *p;
+
+	if (s->state == SSL2_ST_SEND_SERVER_VERIFY_A)
+		{
+		p=(unsigned char *)s->init_buf->data;
+		*(p++)=SSL2_MT_SERVER_VERIFY;
+		if (s->s2->challenge_length > sizeof s->s2->challenge)
+			{
+			SSLerr(SSL_F_SERVER_VERIFY, ERR_R_INTERNAL_ERROR);
+			return -1;
+			}
+		memcpy(p,s->s2->challenge,(unsigned int)s->s2->challenge_length);
+		/* p+=s->s2->challenge_length; */
+
+		s->state=SSL2_ST_SEND_SERVER_VERIFY_B;
+		s->init_num=s->s2->challenge_length+1;
+		s->init_off=0;
+		}
+	return(ssl2_do_write(s));
+	}
+
+static int server_finish(SSL *s)
+	{
+	unsigned char *p;
+
+	if (s->state == SSL2_ST_SEND_SERVER_FINISHED_A)
+		{
+		p=(unsigned char *)s->init_buf->data;
+		*(p++)=SSL2_MT_SERVER_FINISHED;
+
+		if (s->session->session_id_length > sizeof s->session->session_id)
+			{
+			SSLerr(SSL_F_SERVER_FINISH, ERR_R_INTERNAL_ERROR);
+			return -1;
+			}
+		memcpy(p,s->session->session_id, (unsigned int)s->session->session_id_length);
+		/* p+=s->session->session_id_length; */
+
+		s->state=SSL2_ST_SEND_SERVER_FINISHED_B;
+		s->init_num=s->session->session_id_length+1;
+		s->init_off=0;
+		}
+
+	/* SSL2_ST_SEND_SERVER_FINISHED_B */
+	return(ssl2_do_write(s));
+	}
+
+/* send the request and check the response */
+static int request_certificate(SSL *s)
+	{
+	const unsigned char *cp;
+	unsigned char *p,*p2,*buf2;
+	unsigned char *ccd;
+	int i,j,ctype,ret= -1;
+	unsigned long len;
+	X509 *x509=NULL;
+	STACK_OF(X509) *sk=NULL;
+
+	ccd=s->s2->tmp.ccl;
+	if (s->state == SSL2_ST_SEND_REQUEST_CERTIFICATE_A)
+		{
+		p=(unsigned char *)s->init_buf->data;
+		*(p++)=SSL2_MT_REQUEST_CERTIFICATE;
+		*(p++)=SSL2_AT_MD5_WITH_RSA_ENCRYPTION;
+		if (RAND_pseudo_bytes(ccd,SSL2_MIN_CERT_CHALLENGE_LENGTH) <= 0)
+			return -1;
+		memcpy(p,ccd,SSL2_MIN_CERT_CHALLENGE_LENGTH);
+
+		s->state=SSL2_ST_SEND_REQUEST_CERTIFICATE_B;
+		s->init_num=SSL2_MIN_CERT_CHALLENGE_LENGTH+2;
+		s->init_off=0;
+		}
+
+	if (s->state == SSL2_ST_SEND_REQUEST_CERTIFICATE_B)
+		{
+		i=ssl2_do_write(s);
+		if (i <= 0)
+			{
+			ret=i;
+			goto end;
+			}
+
+		s->init_num=0;
+		s->state=SSL2_ST_SEND_REQUEST_CERTIFICATE_C;
+		}
+
+	if (s->state == SSL2_ST_SEND_REQUEST_CERTIFICATE_C)
+		{
+		p=(unsigned char *)s->init_buf->data;
+		i=ssl2_read(s,(char *)&(p[s->init_num]),6-s->init_num); /* try to read 6 octets ... */
+		if (i < 3-s->init_num) /* ... but don't call ssl2_part_read now if we got at least 3
+		                        * (probably NO-CERTIFICATE-ERROR) */
+			{
+			ret=ssl2_part_read(s,SSL_F_REQUEST_CERTIFICATE,i);
+			goto end;
+			}
+		s->init_num += i;
+
+		if ((s->init_num >= 3) && (p[0] == SSL2_MT_ERROR))
+			{
+			n2s(p,i);
+			if (i != SSL2_PE_NO_CERTIFICATE)
+				{
+				/* not the error message we expected -- let ssl2_part_read handle it */
+				s->init_num -= 3;
+				ret = ssl2_part_read(s,SSL_F_REQUEST_CERTIFICATE, 3);
+				goto end;
+				}
+
+			if (s->msg_callback)
+				s->msg_callback(0, s->version, 0, p, 3, s, s->msg_callback_arg); /* ERROR */
+
+			/* this is the one place where we can recover from an SSL 2.0 error */
+
+			if (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)
+				{
+				ssl2_return_error(s,SSL2_PE_BAD_CERTIFICATE);
+				SSLerr(SSL_F_REQUEST_CERTIFICATE,SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
+				goto end;
+				}
+			ret=1;
+			goto end;
+			}
+		if ((*(p++) != SSL2_MT_CLIENT_CERTIFICATE) || (s->init_num < 6))
+			{
+			ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+			SSLerr(SSL_F_REQUEST_CERTIFICATE,SSL_R_SHORT_READ);
+			goto end;
+			}
+		if (s->init_num != 6)
+			{
+			SSLerr(SSL_F_REQUEST_CERTIFICATE, ERR_R_INTERNAL_ERROR);
+			goto end;
+			}
+		
+		/* ok we have a response */
+		/* certificate type, there is only one right now. */
+		ctype= *(p++);
+		if (ctype != SSL2_AT_MD5_WITH_RSA_ENCRYPTION)
+			{
+			ssl2_return_error(s,SSL2_PE_UNSUPPORTED_CERTIFICATE_TYPE);
+			SSLerr(SSL_F_REQUEST_CERTIFICATE,SSL_R_BAD_RESPONSE_ARGUMENT);
+			goto end;
+			}
+		n2s(p,i); s->s2->tmp.clen=i;
+		n2s(p,i); s->s2->tmp.rlen=i;
+		s->state=SSL2_ST_SEND_REQUEST_CERTIFICATE_D;
+		}
+
+	/* SSL2_ST_SEND_REQUEST_CERTIFICATE_D */
+	p=(unsigned char *)s->init_buf->data;
+	len = 6 + (unsigned long)s->s2->tmp.clen + (unsigned long)s->s2->tmp.rlen;
+	if (len > SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER)
+		{
+		SSLerr(SSL_F_REQUEST_CERTIFICATE,SSL_R_MESSAGE_TOO_LONG);
+		goto end;
+		}
+	j = (int)len - s->init_num;
+	i = ssl2_read(s,(char *)&(p[s->init_num]),j);
+	if (i < j) 
+		{
+		ret=ssl2_part_read(s,SSL_F_REQUEST_CERTIFICATE,i);
+		goto end;
+		}
+	if (s->msg_callback)
+		s->msg_callback(0, s->version, 0, p, len, s, s->msg_callback_arg); /* CLIENT-CERTIFICATE */
+	p += 6;
+
+	cp = p;
+	x509=(X509 *)d2i_X509(NULL,&cp,(long)s->s2->tmp.clen);
+	if (x509 == NULL)
+		{
+		SSLerr(SSL_F_REQUEST_CERTIFICATE,ERR_R_X509_LIB);
+		goto msg_end;
+		}
+
+	if (((sk=sk_X509_new_null()) == NULL) || (!sk_X509_push(sk,x509)))
+		{
+		SSLerr(SSL_F_REQUEST_CERTIFICATE,ERR_R_MALLOC_FAILURE);
+		goto msg_end;
+		}
+
+	i=ssl_verify_cert_chain(s,sk);
+
+	if (i > 0)	/* we like the packet, now check the chksum */
+		{
+		EVP_MD_CTX ctx;
+		EVP_PKEY *pkey=NULL;
+
+		EVP_MD_CTX_init(&ctx);
+		EVP_VerifyInit_ex(&ctx,s->ctx->rsa_md5, NULL);
+		EVP_VerifyUpdate(&ctx,s->s2->key_material,
+				 s->s2->key_material_length);
+		EVP_VerifyUpdate(&ctx,ccd,SSL2_MIN_CERT_CHALLENGE_LENGTH);
+
+		i=i2d_X509(s->cert->pkeys[SSL_PKEY_RSA_ENC].x509,NULL);
+		buf2=OPENSSL_malloc((unsigned int)i);
+		if (buf2 == NULL)
+			{
+			SSLerr(SSL_F_REQUEST_CERTIFICATE,ERR_R_MALLOC_FAILURE);
+			goto msg_end;
+			}
+		p2=buf2;
+		i=i2d_X509(s->cert->pkeys[SSL_PKEY_RSA_ENC].x509,&p2);
+		EVP_VerifyUpdate(&ctx,buf2,(unsigned int)i);
+		OPENSSL_free(buf2);
+
+		pkey=X509_get_pubkey(x509);
+		if (pkey == NULL) goto end;
+		i=EVP_VerifyFinal(&ctx,cp,s->s2->tmp.rlen,pkey);
+		EVP_PKEY_free(pkey);
+		EVP_MD_CTX_cleanup(&ctx);
+
+		if (i > 0)
+			{
+			if (s->session->peer != NULL)
+				X509_free(s->session->peer);
+			s->session->peer=x509;
+			CRYPTO_add(&x509->references,1,CRYPTO_LOCK_X509);
+			s->session->verify_result = s->verify_result;
+			ret=1;
+			goto end;
+			}
+		else
+			{
+			SSLerr(SSL_F_REQUEST_CERTIFICATE,SSL_R_BAD_CHECKSUM);
+			goto msg_end;
+			}
+		}
+	else
+		{
+msg_end:
+		ssl2_return_error(s,SSL2_PE_BAD_CERTIFICATE);
+		}
+end:
+	sk_X509_free(sk);
+	X509_free(x509);
+	return(ret);
+	}
+
+static int ssl_rsa_private_decrypt(CERT *c, int len, unsigned char *from,
+	     unsigned char *to, int padding)
+	{
+	RSA *rsa;
+	int i;
+
+	if ((c == NULL) || (c->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL))
+		{
+		SSLerr(SSL_F_SSL_RSA_PRIVATE_DECRYPT,SSL_R_NO_PRIVATEKEY);
+		return(-1);
+		}
+	if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey->type != EVP_PKEY_RSA)
+		{
+		SSLerr(SSL_F_SSL_RSA_PRIVATE_DECRYPT,SSL_R_PUBLIC_KEY_IS_NOT_RSA);
+		return(-1);
+		}
+	rsa=c->pkeys[SSL_PKEY_RSA_ENC].privatekey->pkey.rsa;
+
+	/* we have the public key */
+	i=RSA_private_decrypt(len,from,to,rsa,padding);
+	if (i < 0)
+		SSLerr(SSL_F_SSL_RSA_PRIVATE_DECRYPT,ERR_R_RSA_LIB);
+	return(i);
+	}
+#else /* !OPENSSL_NO_SSL2 */
+
+# if PEDANTIC
+static void *dummy=&dummy;
+# endif
+
+#endif

Added: openssl/branches/upstream/current/ssl/s3_clnt.c
===================================================================
--- openssl/branches/upstream/current/ssl/s3_clnt.c	                        (rev 0)
+++ openssl/branches/upstream/current/ssl/s3_clnt.c	2009-05-16 15:25:35 UTC (rev 372)
@@ -0,0 +1,2744 @@
+/* ssl/s3_clnt.c */
+/* Copyright (C) 1995-1998 Eric Young (eay at cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay at cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh at cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay at cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh at cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2003 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 at 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 at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * Portions of the attached software ("Contribution") are developed by 
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the OpenSSL open source
+ * license provided above.
+ *
+ * ECC cipher suite support in OpenSSL originally written by
+ * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
+ *
+ */
+
+#include <stdio.h>
+#include "ssl_locl.h"
+#include "kssl_lcl.h"
+#include <openssl/buffer.h>
+#include <openssl/rand.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include <openssl/md5.h>
+#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);
+#ifndef OPENSSL_NO_TLSEXT
+static int ssl3_check_finished(SSL *s);
+#endif
+
+#ifndef OPENSSL_NO_ECDH
+static int curve_id2nid(int curve_id);
+int check_srvr_ecc_cert_and_alg(X509 *x, SSL_CIPHER *cs);
+#endif
+
+static SSL_METHOD *ssl3_get_client_method(int ver)
+	{
+	if (ver == SSL3_VERSION)
+		return(SSLv3_client_method());
+	else
+		return(NULL);
+	}
+
+IMPLEMENT_ssl3_meth_func(SSLv3_client_method,
+			ssl_undefined_function,
+			ssl3_connect,
+			ssl3_get_client_method)
+
+int ssl3_connect(SSL *s)
+	{
+	BUF_MEM *buf=NULL;
+	unsigned long Time=(unsigned long)time(NULL),l;
+	long num1;
+	void (*cb)(const SSL *ssl,int type,int val)=NULL;
+	int ret= -1;
+	int new_state,state,skip=0;
+
+	RAND_add(&Time,sizeof(Time),0);
+	ERR_clear_error();
+	clear_sys_error();
+
+	if (s->info_callback != NULL)
+		cb=s->info_callback;
+	else if (s->ctx->info_callback != NULL)
+		cb=s->ctx->info_callback;
+	
+	s->in_handshake++;
+	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); 
+
+	for (;;)
+		{
+		state=s->state;
+
+		switch(s->state)
+			{
+		case SSL_ST_RENEGOTIATE:
+			s->new_session=1;
+			s->state=SSL_ST_CONNECT;
+			s->ctx->stats.sess_connect_renegotiate++;
+			/* break */
+		case SSL_ST_BEFORE:
+		case SSL_ST_CONNECT:
+		case SSL_ST_BEFORE|SSL_ST_CONNECT:
+		case SSL_ST_OK|SSL_ST_CONNECT:
+
+			s->server=0;
+			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
+
+			if ((s->version & 0xff00 ) != 0x0300)
+				{
+				SSLerr(SSL_F_SSL3_CONNECT, ERR_R_INTERNAL_ERROR);
+				ret = -1;
+				goto end;
+				}
+				
+			/* s->version=SSL3_VERSION; */
+			s->type=SSL_ST_CONNECT;
+
+			if (s->init_buf == NULL)
+				{
+				if ((buf=BUF_MEM_new()) == NULL)
+					{
+					ret= -1;
+					goto end;
+					}
+				if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH))
+					{
+					ret= -1;
+					goto end;
+					}
+				s->init_buf=buf;
+				buf=NULL;
+				}
+
+			if (!ssl3_setup_buffers(s)) { ret= -1; goto end; }
+
+			/* setup buffing BIO */
+			if (!ssl_init_wbio_buffer(s,0)) { ret= -1; goto end; }
+
+			/* don't push the buffering BIO quite yet */
+
+			ssl3_init_finished_mac(s);
+
+			s->state=SSL3_ST_CW_CLNT_HELLO_A;
+			s->ctx->stats.sess_connect++;
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_CW_CLNT_HELLO_A:
+		case SSL3_ST_CW_CLNT_HELLO_B:
+
+			s->shutdown=0;
+			ret=ssl3_client_hello(s);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_CR_SRVR_HELLO_A;
+			s->init_num=0;
+
+			/* turn on buffering for the next lot of output */
+			if (s->bbio != s->wbio)
+				s->wbio=BIO_push(s->bbio,s->wbio);
+
+			break;
+
+		case SSL3_ST_CR_SRVR_HELLO_A:
+		case SSL3_ST_CR_SRVR_HELLO_B:
+			ret=ssl3_get_server_hello(s);
+			if (ret <= 0) goto end;
+			if (s->hit)
+				s->state=SSL3_ST_CR_FINISHED_A;
+			else
+				s->state=SSL3_ST_CR_CERT_A;
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_CR_CERT_A:
+		case SSL3_ST_CR_CERT_B:
+#ifndef OPENSSL_NO_TLSEXT
+			ret=ssl3_check_finished(s);
+			if (ret <= 0) goto end;
+			if (ret == 2)
+				{
+				s->hit = 1;
+				if (s->tlsext_ticket_expected)
+					s->state=SSL3_ST_CR_SESSION_TICKET_A;
+				else
+					s->state=SSL3_ST_CR_FINISHED_A;
+				s->init_num=0;
+				break;
+				}
+#endif
+			/* Check if it is anon DH/ECDH */
+			if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL))
+				{
+				ret=ssl3_get_server_certificate(s);
+				if (ret <= 0) goto end;
+#ifndef OPENSSL_NO_TLSEXT
+				if (s->tlsext_status_expected)
+					s->state=SSL3_ST_CR_CERT_STATUS_A;
+				else
+					s->state=SSL3_ST_CR_KEY_EXCH_A;
+				}
+			else
+				{
+				skip = 1;
+				s->state=SSL3_ST_CR_KEY_EXCH_A;
+				}
+#else
+				}
+			else
+				skip=1;
+
+			s->state=SSL3_ST_CR_KEY_EXCH_A;
+#endif
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_CR_KEY_EXCH_A:
+		case SSL3_ST_CR_KEY_EXCH_B:
+			ret=ssl3_get_key_exchange(s);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_CR_CERT_REQ_A;
+			s->init_num=0;
+
+			/* at this point we check that we have the
+			 * required stuff from the server */
+			if (!ssl3_check_cert_and_algorithm(s))
+				{
+				ret= -1;
+				goto end;
+				}
+			break;
+
+		case SSL3_ST_CR_CERT_REQ_A:
+		case SSL3_ST_CR_CERT_REQ_B:
+			ret=ssl3_get_certificate_request(s);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_CR_SRVR_DONE_A;
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_CR_SRVR_DONE_A:
+		case SSL3_ST_CR_SRVR_DONE_B:
+			ret=ssl3_get_server_done(s);
+			if (ret <= 0) goto end;
+			if (s->s3->tmp.cert_req)
+				s->state=SSL3_ST_CW_CERT_A;
+			else
+				s->state=SSL3_ST_CW_KEY_EXCH_A;
+			s->init_num=0;
+
+			break;
+
+		case SSL3_ST_CW_CERT_A:
+		case SSL3_ST_CW_CERT_B:
+		case SSL3_ST_CW_CERT_C:
+		case SSL3_ST_CW_CERT_D:
+			ret=ssl3_send_client_certificate(s);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_CW_KEY_EXCH_A;
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_CW_KEY_EXCH_A:
+		case SSL3_ST_CW_KEY_EXCH_B:
+			ret=ssl3_send_client_key_exchange(s);
+			if (ret <= 0) goto end;
+			l=s->s3->tmp.new_cipher->algorithms;
+			/* EAY EAY EAY need to check for DH fix cert
+			 * sent back */
+			/* For TLS, cert_req is set to 2, so a cert chain
+			 * of nothing is sent, but no verify packet is sent */
+			/* XXX: For now, we do not support client 
+			 * authentication in ECDH cipher suites with
+			 * ECDH (rather than ECDSA) certificates.
+			 * We need to skip the certificate verify 
+			 * message when client's ECDH public key is sent 
+			 * inside the client certificate.
+			 */
+			if (s->s3->tmp.cert_req == 1)
+				{
+				s->state=SSL3_ST_CW_CERT_VRFY_A;
+				}
+			else
+				{
+				s->state=SSL3_ST_CW_CHANGE_A;
+				s->s3->change_cipher_spec=0;
+				}
+
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_CW_CERT_VRFY_A:
+		case SSL3_ST_CW_CERT_VRFY_B:
+			ret=ssl3_send_client_verify(s);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_CW_CHANGE_A;
+			s->init_num=0;
+			s->s3->change_cipher_spec=0;
+			break;
+
+		case SSL3_ST_CW_CHANGE_A:
+		case SSL3_ST_CW_CHANGE_B:
+			ret=ssl3_send_change_cipher_spec(s,
+				SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_CW_FINISHED_A;
+			s->init_num=0;
+
+			s->session->cipher=s->s3->tmp.new_cipher;
+#ifdef OPENSSL_NO_COMP
+			s->session->compress_meth=0;
+#else
+			if (s->s3->tmp.new_compression == NULL)
+				s->session->compress_meth=0;
+			else
+				s->session->compress_meth=
+					s->s3->tmp.new_compression->id;
+#endif
+			if (!s->method->ssl3_enc->setup_key_block(s))
+				{
+				ret= -1;
+				goto end;
+				}
+
+			if (!s->method->ssl3_enc->change_cipher_state(s,
+				SSL3_CHANGE_CIPHER_CLIENT_WRITE))
+				{
+				ret= -1;
+				goto end;
+				}
+
+			break;
+
+		case SSL3_ST_CW_FINISHED_A:
+		case SSL3_ST_CW_FINISHED_B:
+			ret=ssl3_send_finished(s,
+				SSL3_ST_CW_FINISHED_A,SSL3_ST_CW_FINISHED_B,
+				s->method->ssl3_enc->client_finished_label,
+				s->method->ssl3_enc->client_finished_label_len);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_CW_FLUSH;
+
+			/* clear flags */
+			s->s3->flags&= ~SSL3_FLAGS_POP_BUFFER;
+			if (s->hit)
+				{
+				s->s3->tmp.next_state=SSL_ST_OK;
+				if (s->s3->flags & SSL3_FLAGS_DELAY_CLIENT_FINISHED)
+					{
+					s->state=SSL_ST_OK;
+					s->s3->flags|=SSL3_FLAGS_POP_BUFFER;
+					s->s3->delay_buf_pop_ret=0;
+					}
+				}
+			else
+				{
+#ifndef OPENSSL_NO_TLSEXT
+				/* Allow NewSessionTicket if ticket expected */
+				if (s->tlsext_ticket_expected)
+					s->s3->tmp.next_state=SSL3_ST_CR_SESSION_TICKET_A;
+				else
+#endif
+				
+				s->s3->tmp.next_state=SSL3_ST_CR_FINISHED_A;
+				}
+			s->init_num=0;
+			break;
+
+#ifndef OPENSSL_NO_TLSEXT
+		case SSL3_ST_CR_SESSION_TICKET_A:
+		case SSL3_ST_CR_SESSION_TICKET_B:
+			ret=ssl3_get_new_session_ticket(s);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_CR_FINISHED_A;
+			s->init_num=0;
+		break;
+
+		case SSL3_ST_CR_CERT_STATUS_A:
+		case SSL3_ST_CR_CERT_STATUS_B:
+			ret=ssl3_get_cert_status(s);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_CR_KEY_EXCH_A;
+			s->init_num=0;
+		break;
+#endif
+
+		case SSL3_ST_CR_FINISHED_A:
+		case SSL3_ST_CR_FINISHED_B:
+
+			ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A,
+				SSL3_ST_CR_FINISHED_B);
+			if (ret <= 0) goto end;
+
+			if (s->hit)
+				s->state=SSL3_ST_CW_CHANGE_A;
+			else
+				s->state=SSL_ST_OK;
+			s->init_num=0;
+			break;
+
+		case SSL3_ST_CW_FLUSH:
+			/* number of bytes to be flushed */
+			num1=BIO_ctrl(s->wbio,BIO_CTRL_INFO,0,NULL);
+			if (num1 > 0)
+				{
+				s->rwstate=SSL_WRITING;
+				num1=BIO_flush(s->wbio);
+				if (num1 <= 0) { ret= -1; goto end; }
+				s->rwstate=SSL_NOTHING;
+				}
+
+			s->state=s->s3->tmp.next_state;
+			break;
+
+		case SSL_ST_OK:
+			/* clean a few things up */
+			ssl3_cleanup_key_block(s);
+
+			if (s->init_buf != NULL)
+				{
+				BUF_MEM_free(s->init_buf);
+				s->init_buf=NULL;
+				}
+
+			/* If we are not 'joining' the last two packets,
+			 * remove the buffering now */
+			if (!(s->s3->flags & SSL3_FLAGS_POP_BUFFER))
+				ssl_free_wbio_buffer(s);
+			/* else do it later in ssl3_write */
+
+			s->init_num=0;
+			s->new_session=0;
+
+			ssl_update_cache(s,SSL_SESS_CACHE_CLIENT);
+			if (s->hit) s->ctx->stats.sess_hit++;
+
+			ret=1;
+			/* s->server=0; */
+			s->handshake_func=ssl3_connect;
+			s->ctx->stats.sess_connect_good++;
+
+			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1);
+
+			goto end;
+			/* break; */
+			
+		default:
+			SSLerr(SSL_F_SSL3_CONNECT,SSL_R_UNKNOWN_STATE);
+			ret= -1;
+			goto end;
+			/* break; */
+			}
+
+		/* did we do anything */
+		if (!s->s3->tmp.reuse_message && !skip)
+			{
+			if (s->debug)
+				{
+				if ((ret=BIO_flush(s->wbio)) <= 0)
+					goto end;
+				}
+
+			if ((cb != NULL) && (s->state != state))
+				{
+				new_state=s->state;
+				s->state=state;
+				cb(s,SSL_CB_CONNECT_LOOP,1);
+				s->state=new_state;
+				}
+			}
+		skip=0;
+		}
+end:
+	s->in_handshake--;
+	if (buf != NULL)
+		BUF_MEM_free(buf);
+	if (cb != NULL)
+		cb(s,SSL_CB_CONNECT_EXIT,ret);
+	return(ret);
+	}
+
+
+int ssl3_client_hello(SSL *s)
+	{
+	unsigned char *buf;
+	unsigned char *p,*d;
+	int i;
+	unsigned long Time,l;
+#ifndef OPENSSL_NO_COMP
+	int j;
+	SSL_COMP *comp;
+#endif
+
+	buf=(unsigned char *)s->init_buf->data;
+	if (s->state == SSL3_ST_CW_CLNT_HELLO_A)
+		{
+		if ((s->session == NULL) ||
+			(s->session->ssl_version != s->version) ||
+			(s->session->not_resumable))
+			{
+			if (!ssl_get_new_session(s,0))
+				goto err;
+			}
+		/* else use the pre-loaded session */
+
+		p=s->s3->client_random;
+		Time=(unsigned long)time(NULL);			/* Time */
+		l2n(Time,p);
+		if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
+			goto err;
+
+		/* Do the message type and length last */
+		d=p= &(buf[4]);
+
+		*(p++)=s->version>>8;
+		*(p++)=s->version&0xff;
+		s->client_version=s->version;
+
+		/* Random stuff */
+		memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE);
+		p+=SSL3_RANDOM_SIZE;
+
+		/* Session ID */
+		if (s->new_session)
+			i=0;
+		else
+			i=s->session->session_id_length;
+		*(p++)=i;
+		if (i != 0)
+			{
+			if (i > (int)sizeof(s->session->session_id))
+				{
+				SSLerr(SSL_F_SSL3_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+				goto err;
+				}
+			memcpy(p,s->session->session_id,i);
+			p+=i;
+			}
+		
+		/* Ciphers supported */
+		i=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),&(p[2]),0);
+		if (i == 0)
+			{
+			SSLerr(SSL_F_SSL3_CLIENT_HELLO,SSL_R_NO_CIPHERS_AVAILABLE);
+			goto err;
+			}
+		s2n(i,p);
+		p+=i;
+
+		/* COMPRESSION */
+#ifdef OPENSSL_NO_COMP
+		*(p++)=1;
+#else
+		if (s->ctx->comp_methods == NULL)
+			j=0;
+		else
+			j=sk_SSL_COMP_num(s->ctx->comp_methods);
+		*(p++)=1+j;
+		for (i=0; i<j; i++)
+			{
+			comp=sk_SSL_COMP_value(s->ctx->comp_methods,i);
+			*(p++)=comp->id;
+			}
+#endif
+		*(p++)=0; /* Add the NULL method */
+#ifndef OPENSSL_NO_TLSEXT
+		if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
+			{
+			SSLerr(SSL_F_SSL3_CLIENT_HELLO,ERR_R_INTERNAL_ERROR);
+			goto err;
+			}
+#endif		
+		l=(p-d);
+		d=buf;
+		*(d++)=SSL3_MT_CLIENT_HELLO;
+		l2n3(l,d);
+
+		s->state=SSL3_ST_CW_CLNT_HELLO_B;
+		/* number of bytes to write */
+		s->init_num=p-buf;
+		s->init_off=0;
+		}
+
+	/* SSL3_ST_CW_CLNT_HELLO_B */
+	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+err:
+	return(-1);
+	}
+
+int ssl3_get_server_hello(SSL *s)
+	{
+	STACK_OF(SSL_CIPHER) *sk;
+	SSL_CIPHER *c;
+	unsigned char *p,*d;
+	int i,al,ok;
+	unsigned int j;
+	long n;
+#ifndef OPENSSL_NO_COMP
+	SSL_COMP *comp;
+#endif
+
+	n=s->method->ssl_get_message(s,
+		SSL3_ST_CR_SRVR_HELLO_A,
+		SSL3_ST_CR_SRVR_HELLO_B,
+		-1,
+		20000, /* ?? */
+		&ok);
+
+	if (!ok) return((int)n);
+
+	if ( SSL_version(s) == DTLS1_VERSION)
+		{
+		if ( s->s3->tmp.message_type == DTLS1_MT_HELLO_VERIFY_REQUEST)
+			{
+			if ( s->d1->send_cookie == 0)
+				{
+				s->s3->tmp.reuse_message = 1;
+				return 1;
+				}
+			else /* already sent a cookie */
+				{
+				al=SSL_AD_UNEXPECTED_MESSAGE;
+				SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_BAD_MESSAGE_TYPE);
+				goto f_err;
+				}
+			}
+		}
+	
+	if ( s->s3->tmp.message_type != SSL3_MT_SERVER_HELLO)
+		{
+		al=SSL_AD_UNEXPECTED_MESSAGE;
+		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_BAD_MESSAGE_TYPE);
+		goto f_err;
+		}
+
+	d=p=(unsigned char *)s->init_msg;
+
+	if ((p[0] != (s->version>>8)) || (p[1] != (s->version&0xff)))
+		{
+		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_SSL_VERSION);
+		s->version=(s->version&0xff00)|p[1];
+		al=SSL_AD_PROTOCOL_VERSION;
+		goto f_err;
+		}
+	p+=2;
+
+	/* load the server hello data */
+	/* load the server random */
+	memcpy(s->s3->server_random,p,SSL3_RANDOM_SIZE);
+	p+=SSL3_RANDOM_SIZE;
+
+	/* get the session-id */
+	j= *(p++);
+
+	if ((j > sizeof s->session->session_id) || (j > SSL3_SESSION_ID_SIZE))
+		{
+		al=SSL_AD_ILLEGAL_PARAMETER;
+		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_SSL3_SESSION_ID_TOO_LONG);
+		goto f_err;
+		}
+
+	if (j != 0 && j == s->session->session_id_length
+	    && memcmp(p,s->session->session_id,j) == 0)
+	    {
+	    if(s->sid_ctx_length != s->session->sid_ctx_length
+	       || memcmp(s->session->sid_ctx,s->sid_ctx,s->sid_ctx_length))
+		{
+		/* actually a client application bug */
+		al=SSL_AD_ILLEGAL_PARAMETER;
+		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
+		goto f_err;
+		}
+	    s->hit=1;
+	    }
+	else	/* a miss or crap from the other end */
+		{
+		/* If we were trying for session-id reuse, make a new
+		 * SSL_SESSION so we don't stuff up other people */
+		s->hit=0;
+		if (s->session->session_id_length > 0)
+			{
+			if (!ssl_get_new_session(s,0))
+				{
+				al=SSL_AD_INTERNAL_ERROR;
+				goto f_err;
+				}
+			}
+		s->session->session_id_length=j;
+		memcpy(s->session->session_id,p,j); /* j could be 0 */
+		}
+	p+=j;
+	c=ssl_get_cipher_by_char(s,p);
+	if (c == NULL)
+		{
+		/* unknown cipher */
+		al=SSL_AD_ILLEGAL_PARAMETER;
+		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNKNOWN_CIPHER_RETURNED);
+		goto f_err;
+		}
+	p+=ssl_put_cipher_by_char(s,NULL,NULL);
+
+	sk=ssl_get_ciphers_by_id(s);
+	i=sk_SSL_CIPHER_find(sk,c);
+	if (i < 0)
+		{
+		/* we did not say we would use this cipher */
+		al=SSL_AD_ILLEGAL_PARAMETER;
+		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_CIPHER_RETURNED);
+		goto f_err;
+		}
+
+	/* Depending on the session caching (internal/external), the cipher
+	   and/or cipher_id values may not be set. Make sure that
+	   cipher_id is set and use it for comparison. */
+	if (s->session->cipher)
+		s->session->cipher_id = s->session->cipher->id;
+	if (s->hit && (s->session->cipher_id != c->id))
+		{
+		if (!(s->options &
+			SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG))
+			{
+			al=SSL_AD_ILLEGAL_PARAMETER;
+			SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED);
+			goto f_err;
+			}
+		}
+	s->s3->tmp.new_cipher=c;
+
+	/* lets get the compression algorithm */
+	/* COMPRESSION */
+#ifdef OPENSSL_NO_COMP
+	if (*(p++) != 0)
+		{
+		al=SSL_AD_ILLEGAL_PARAMETER;
+		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
+		goto f_err;
+		}
+#else
+	j= *(p++);
+	if (j == 0)
+		comp=NULL;
+	else
+		comp=ssl3_comp_find(s->ctx->comp_methods,j);
+	
+	if ((j != 0) && (comp == NULL))
+		{
+		al=SSL_AD_ILLEGAL_PARAMETER;
+		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
+		goto f_err;
+		}
+	else
+		{
+		s->s3->tmp.new_compression=comp;
+		}
+#endif
+#ifndef OPENSSL_NO_TLSEXT
+	/* TLS extensions*/
+	if (s->version > SSL3_VERSION)
+		{
+		if (!ssl_parse_serverhello_tlsext(s,&p,d,n, &al))
+			{
+			/* 'al' set by ssl_parse_serverhello_tlsext */
+			SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_PARSE_TLSEXT);
+			goto f_err; 
+			}
+		if (ssl_check_serverhello_tlsext(s) <= 0)
+			{
+			SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_SERVERHELLO_TLSEXT);
+				goto err;
+			}
+		}
+#endif
+
+
+	if (p != (d+n))
+		{
+		/* wrong packet length */
+		al=SSL_AD_DECODE_ERROR;
+		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_BAD_PACKET_LENGTH);
+		goto err;
+		}
+
+	return(1);
+f_err:
+	ssl3_send_alert(s,SSL3_AL_FATAL,al);
+err:
+	return(-1);
+	}
+
+int ssl3_get_server_certificate(SSL *s)
+	{
+	int al,i,ok,ret= -1;
+	unsigned long n,nc,llen,l;
+	X509 *x=NULL;
+	const unsigned char *q,*p;
+	unsigned char *d;
+	STACK_OF(X509) *sk=NULL;
+	SESS_CERT *sc;
+	EVP_PKEY *pkey=NULL;
+	int need_cert = 1; /* VRS: 0=> will allow null cert if auth == KRB5 */
+
+	n=s->method->ssl_get_message(s,
+		SSL3_ST_CR_CERT_A,
+		SSL3_ST_CR_CERT_B,
+		-1,
+		s->max_cert_list,
+		&ok);
+
+	if (!ok) return((int)n);
+
+	if ((s->s3->tmp.message_type == SSL3_MT_SERVER_KEY_EXCHANGE) ||
+		((s->s3->tmp.new_cipher->algorithms & SSL_aKRB5) && 
+		(s->s3->tmp.message_type == SSL3_MT_SERVER_DONE)))
+		{
+		s->s3->tmp.reuse_message=1;
+		return(1);
+		}
+
+	if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE)
+		{
+		al=SSL_AD_UNEXPECTED_MESSAGE;
+		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_BAD_MESSAGE_TYPE);
+		goto f_err;
+		}
+	p=d=(unsigned char *)s->init_msg;
+
+	if ((sk=sk_X509_new_null()) == NULL)
+		{
+		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,ERR_R_MALLOC_FAILURE);
+		goto err;
+		}
+
+	n2l3(p,llen);
+	if (llen+3 != n)
+		{
+		al=SSL_AD_DECODE_ERROR;
+		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_LENGTH_MISMATCH);
+		goto f_err;
+		}
+	for (nc=0; nc<llen; )
+		{
+		n2l3(p,l);
+		if ((l+nc+3) > llen)
+			{
+			al=SSL_AD_DECODE_ERROR;
+			SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH);
+			goto f_err;
+			}
+
+		q=p;
+		x=d2i_X509(NULL,&q,l);
+		if (x == NULL)
+			{
+			al=SSL_AD_BAD_CERTIFICATE;
+			SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,ERR_R_ASN1_LIB);
+			goto f_err;
+			}
+		if (q != (p+l))
+			{
+			al=SSL_AD_DECODE_ERROR;
+			SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH);
+			goto f_err;
+			}
+		if (!sk_X509_push(sk,x))
+			{
+			SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+		x=NULL;
+		nc+=l+3;
+		p=q;
+		}
+
+	i=ssl_verify_cert_chain(s,sk);
+	if ((s->verify_mode != SSL_VERIFY_NONE) && (i <= 0)
+#ifndef OPENSSL_NO_KRB5
+	        && (s->s3->tmp.new_cipher->algorithms & (SSL_MKEY_MASK|SSL_AUTH_MASK))
+	        != (SSL_aKRB5|SSL_kKRB5)
+#endif /* OPENSSL_NO_KRB5 */
+	        )
+		{
+		al=ssl_verify_alarm_type(s->verify_result);
+		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_CERTIFICATE_VERIFY_FAILED);
+		goto f_err; 
+		}
+	ERR_clear_error(); /* but we keep s->verify_result */
+
+	sc=ssl_sess_cert_new();
+	if (sc == NULL) goto err;
+
+	if (s->session->sess_cert) ssl_sess_cert_free(s->session->sess_cert);
+	s->session->sess_cert=sc;
+
+	sc->cert_chain=sk;
+	/* Inconsistency alert: cert_chain does include the peer's
+	 * certificate, which we don't include in s3_srvr.c */
+	x=sk_X509_value(sk,0);
+	sk=NULL;
+ 	/* VRS 19990621: possible memory leak; sk=null ==> !sk_pop_free() @end*/
+
+	pkey=X509_get_pubkey(x);
+
+	/* VRS: allow null cert if auth == KRB5 */
+	need_cert =	((s->s3->tmp.new_cipher->algorithms
+	                 & (SSL_MKEY_MASK|SSL_AUTH_MASK))
+	                 == (SSL_aKRB5|SSL_kKRB5))? 0: 1;
+
+#ifdef KSSL_DEBUG
+	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);
+#endif    /* KSSL_DEBUG */
+
+	if (need_cert && ((pkey == NULL) || EVP_PKEY_missing_parameters(pkey)))
+		{
+		x=NULL;
+		al=SSL3_AL_FATAL;
+		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,
+			SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS);
+		goto f_err;
+		}
+
+	i=ssl_cert_type(x,pkey);
+	if (need_cert && i < 0)
+		{
+		x=NULL;
+		al=SSL3_AL_FATAL;
+		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,
+			SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+		goto f_err;
+		}
+
+	if (need_cert)
+		{
+		sc->peer_cert_type=i;
+		CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509);
+		/* Why would the following ever happen?
+		 * We just created sc a couple of lines ago. */
+		if (sc->peer_pkeys[i].x509 != NULL)
+			X509_free(sc->peer_pkeys[i].x509);
+		sc->peer_pkeys[i].x509=x;
+		sc->peer_key= &(sc->peer_pkeys[i]);
+
+		if (s->session->peer != NULL)
+			X509_free(s->session->peer);
+		CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509);
+		s->session->peer=x;
+		}
+	else
+		{
+		sc->peer_cert_type=i;
+		sc->peer_key= NULL;
+
+		if (s->session->peer != NULL)
+			X509_free(s->session->peer);
+		s->session->peer=NULL;
+		}
+	s->session->verify_result = s->verify_result;
+
+	x=NULL;
+	ret=1;
+
+	if (0)
+		{
+f_err:
+		ssl3_send_alert(s,SSL3_AL_FATAL,al);
+		}
+err:
+	EVP_PKEY_free(pkey);
+	X509_free(x);
+	sk_X509_pop_free(sk,X509_free);
+	return(ret);
+	}
+
+int ssl3_get_key_exchange(SSL *s)
+	{
+#ifndef OPENSSL_NO_RSA
+	unsigned char *q,md_buf[EVP_MAX_MD_SIZE*2];
+#endif
+	EVP_MD_CTX md_ctx;
+	unsigned char *param,*p;
+	int al,i,j,param_len,ok;
+	long n,alg;
+	EVP_PKEY *pkey=NULL;
+#ifndef OPENSSL_NO_RSA
+	RSA *rsa=NULL;
+#endif
+#ifndef OPENSSL_NO_DH
+	DH *dh=NULL;
+#endif
+#ifndef OPENSSL_NO_ECDH
+	EC_KEY *ecdh = NULL;
+	BN_CTX *bn_ctx = NULL;
+	EC_POINT *srvr_ecpoint = NULL;
+	int curve_nid = 0;
+	int encoded_pt_len = 0;
+#endif
+
+	/* use same message size as in ssl3_get_certificate_request()
+	 * as ServerKeyExchange message may be skipped */
+	n=s->method->ssl_get_message(s,
+		SSL3_ST_CR_KEY_EXCH_A,
+		SSL3_ST_CR_KEY_EXCH_B,
+		-1,
+		s->max_cert_list,
+		&ok);
+
+	if (!ok) return((int)n);
+
+	if (s->s3->tmp.message_type != SSL3_MT_SERVER_KEY_EXCHANGE)
+		{
+		s->s3->tmp.reuse_message=1;
+		return(1);
+		}
+
+	param=p=(unsigned char *)s->init_msg;
+
+	if (s->session->sess_cert != NULL)
+		{
+#ifndef OPENSSL_NO_RSA
+		if (s->session->sess_cert->peer_rsa_tmp != NULL)
+			{
+			RSA_free(s->session->sess_cert->peer_rsa_tmp);
+			s->session->sess_cert->peer_rsa_tmp=NULL;
+			}
+#endif
+#ifndef OPENSSL_NO_DH
+		if (s->session->sess_cert->peer_dh_tmp)
+			{
+			DH_free(s->session->sess_cert->peer_dh_tmp);
+			s->session->sess_cert->peer_dh_tmp=NULL;
+			}
+#endif
+#ifndef OPENSSL_NO_ECDH
+		if (s->session->sess_cert->peer_ecdh_tmp)
+			{
+			EC_KEY_free(s->session->sess_cert->peer_ecdh_tmp);
+			s->session->sess_cert->peer_ecdh_tmp=NULL;
+			}
+#endif
+		}
+	else
+		{
+		s->session->sess_cert=ssl_sess_cert_new();
+		}
+
+	param_len=0;
+	alg=s->s3->tmp.new_cipher->algorithms;
+	EVP_MD_CTX_init(&md_ctx);
+
+#ifndef OPENSSL_NO_RSA
+	if (alg & SSL_kRSA)
+		{
+		if ((rsa=RSA_new()) == NULL)
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+		n2s(p,i);
+		param_len=i+2;
+		if (param_len > n)
+			{
+			al=SSL_AD_DECODE_ERROR;
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_RSA_MODULUS_LENGTH);
+			goto f_err;
+			}
+		if (!(rsa->n=BN_bin2bn(p,i,rsa->n)))
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
+			goto err;
+			}
+		p+=i;
+
+		n2s(p,i);
+		param_len+=i+2;
+		if (param_len > n)
+			{
+			al=SSL_AD_DECODE_ERROR;
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_RSA_E_LENGTH);
+			goto f_err;
+			}
+		if (!(rsa->e=BN_bin2bn(p,i,rsa->e)))
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
+			goto err;
+			}
+		p+=i;
+		n-=param_len;
+
+		/* this should be because we are using an export cipher */
+		if (alg & SSL_aRSA)
+			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
+		else
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+			goto err;
+			}
+		s->session->sess_cert->peer_rsa_tmp=rsa;
+		rsa=NULL;
+		}
+#else /* OPENSSL_NO_RSA */
+	if (0)
+		;
+#endif
+#ifndef OPENSSL_NO_DH
+	else if (alg & SSL_kEDH)
+		{
+		if ((dh=DH_new()) == NULL)
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_DH_LIB);
+			goto err;
+			}
+		n2s(p,i);
+		param_len=i+2;
+		if (param_len > n)
+			{
+			al=SSL_AD_DECODE_ERROR;
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_DH_P_LENGTH);
+			goto f_err;
+			}
+		if (!(dh->p=BN_bin2bn(p,i,NULL)))
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
+			goto err;
+			}
+		p+=i;
+
+		n2s(p,i);
+		param_len+=i+2;
+		if (param_len > n)
+			{
+			al=SSL_AD_DECODE_ERROR;
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_DH_G_LENGTH);
+			goto f_err;
+			}
+		if (!(dh->g=BN_bin2bn(p,i,NULL)))
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
+			goto err;
+			}
+		p+=i;
+
+		n2s(p,i);
+		param_len+=i+2;
+		if (param_len > n)
+			{
+			al=SSL_AD_DECODE_ERROR;
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_DH_PUB_KEY_LENGTH);
+			goto f_err;
+			}
+		if (!(dh->pub_key=BN_bin2bn(p,i,NULL)))
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
+			goto err;
+			}
+		p+=i;
+		n-=param_len;
+
+#ifndef OPENSSL_NO_RSA
+		if (alg & SSL_aRSA)
+			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
+#else
+		if (0)
+			;
+#endif
+#ifndef OPENSSL_NO_DSA
+		else if (alg & SSL_aDSS)
+			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_DSA_SIGN].x509);
+#endif
+		/* else anonymous DH, so no certificate or pkey. */
+
+		s->session->sess_cert->peer_dh_tmp=dh;
+		dh=NULL;
+		}
+	else if ((alg & SSL_kDHr) || (alg & SSL_kDHd))
+		{
+		al=SSL_AD_ILLEGAL_PARAMETER;
+		SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER);
+		goto f_err;
+		}
+#endif /* !OPENSSL_NO_DH */
+
+#ifndef OPENSSL_NO_ECDH
+	else if (alg & SSL_kECDHE)
+		{
+		EC_GROUP *ngroup;
+		const EC_GROUP *group;
+
+		if ((ecdh=EC_KEY_new()) == NULL)
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+
+		/* Extract elliptic curve parameters and the
+		 * server's ephemeral ECDH public key.
+		 * Keep accumulating lengths of various components in
+		 * param_len and make sure it never exceeds n.
+		 */
+
+		/* XXX: For now we only support named (not generic) curves
+		 * and the ECParameters in this case is just three bytes.
+		 */
+		param_len=3;
+		if ((param_len > n) ||
+		    (*p != NAMED_CURVE_TYPE) || 
+		    ((curve_nid = curve_id2nid(*(p + 2))) == 0)) 
+			{
+			al=SSL_AD_INTERNAL_ERROR;
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
+			goto f_err;
+			}
+
+		ngroup = EC_GROUP_new_by_curve_name(curve_nid);
+		if (ngroup == NULL)
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_EC_LIB);
+			goto err;
+			}
+		if (EC_KEY_set_group(ecdh, ngroup) == 0)
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_EC_LIB);
+			goto err;
+			}
+		EC_GROUP_free(ngroup);
+
+		group = EC_KEY_get0_group(ecdh);
+
+		if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) &&
+		    (EC_GROUP_get_degree(group) > 163))
+			{
+			al=SSL_AD_EXPORT_RESTRICTION;
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER);
+			goto f_err;
+			}
+
+		p+=3;
+
+		/* Next, get the encoded ECPoint */
+		if (((srvr_ecpoint = EC_POINT_new(group)) == NULL) ||
+		    ((bn_ctx = BN_CTX_new()) == NULL))
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+
+		encoded_pt_len = *p;  /* length of encoded point */
+		p+=1;
+		param_len += (1 + encoded_pt_len);
+		if ((param_len > n) ||
+		    (EC_POINT_oct2point(group, srvr_ecpoint, 
+			p, encoded_pt_len, bn_ctx) == 0))
+			{
+			al=SSL_AD_DECODE_ERROR;
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_ECPOINT);
+			goto f_err;
+			}
+
+		n-=param_len;
+		p+=encoded_pt_len;
+
+		/* The ECC/TLS specification does not mention
+		 * the use of DSA to sign ECParameters in the server
+		 * key exchange message. We do support RSA and ECDSA.
+		 */
+		if (0) ;
+#ifndef OPENSSL_NO_RSA
+		else if (alg & SSL_aRSA)
+			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
+#endif
+#ifndef OPENSSL_NO_ECDSA
+		else if (alg & SSL_aECDSA)
+			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_ECC].x509);
+#endif
+		/* else anonymous ECDH, so no certificate or pkey. */
+		EC_KEY_set_public_key(ecdh, srvr_ecpoint);
+		s->session->sess_cert->peer_ecdh_tmp=ecdh;
+		ecdh=NULL;
+		BN_CTX_free(bn_ctx);
+		EC_POINT_free(srvr_ecpoint);
+		srvr_ecpoint = NULL;
+		}
+	else if (alg & SSL_kECDH)
+		{
+		al=SSL_AD_UNEXPECTED_MESSAGE;
+		SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
+		goto f_err;
+		}
+#endif /* !OPENSSL_NO_ECDH */
+	if (alg & SSL_aFZA)
+		{
+		al=SSL_AD_HANDSHAKE_FAILURE;
+		SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER);
+		goto f_err;
+		}
+
+
+	/* p points to the next byte, there are 'n' bytes left */
+
+	/* if it was signed, check the signature */
+	if (pkey != NULL)
+		{
+		n2s(p,i);
+		n-=2;
+		j=EVP_PKEY_size(pkey);
+
+		if ((i != n) || (n > j) || (n <= 0))
+			{
+			/* wrong packet length */
+			al=SSL_AD_DECODE_ERROR;
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_WRONG_SIGNATURE_LENGTH);
+			goto f_err;
+			}
+
+#ifndef OPENSSL_NO_RSA
+		if (pkey->type == EVP_PKEY_RSA)
+			{
+			int num;
+
+			j=0;
+			q=md_buf;
+			for (num=2; num > 0; num--)
+				{
+				EVP_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);
+				EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
+				EVP_DigestUpdate(&md_ctx,param,param_len);
+				EVP_DigestFinal_ex(&md_ctx,q,(unsigned int *)&i);
+				q+=i;
+				j+=i;
+				}
+			i=RSA_verify(NID_md5_sha1, md_buf, j, p, n,
+								pkey->pkey.rsa);
+			if (i < 0)
+				{
+				al=SSL_AD_DECRYPT_ERROR;
+				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_RSA_DECRYPT);
+				goto f_err;
+				}
+			if (i == 0)
+				{
+				/* bad signature */
+				al=SSL_AD_DECRYPT_ERROR;
+				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SIGNATURE);
+				goto f_err;
+				}
+			}
+		else
+#endif
+#ifndef OPENSSL_NO_DSA
+			if (pkey->type == EVP_PKEY_DSA)
+			{
+			/* lets do DSS */
+			EVP_VerifyInit_ex(&md_ctx,EVP_dss1(), NULL);
+			EVP_VerifyUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
+			EVP_VerifyUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
+			EVP_VerifyUpdate(&md_ctx,param,param_len);
+			if (EVP_VerifyFinal(&md_ctx,p,(int)n,pkey) <= 0)
+				{
+				/* bad signature */
+				al=SSL_AD_DECRYPT_ERROR;
+				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SIGNATURE);
+				goto f_err;
+				}
+			}
+		else
+#endif
+#ifndef OPENSSL_NO_ECDSA
+			if (pkey->type == EVP_PKEY_EC)
+			{
+			/* let's do ECDSA */
+			EVP_VerifyInit_ex(&md_ctx,EVP_ecdsa(), NULL);
+			EVP_VerifyUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
+			EVP_VerifyUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
+			EVP_VerifyUpdate(&md_ctx,param,param_len);
+			if (EVP_VerifyFinal(&md_ctx,p,(int)n,pkey) <= 0)
+				{
+				/* bad signature */
+				al=SSL_AD_DECRYPT_ERROR;
+				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SIGNATURE);
+				goto f_err;
+				}
+			}
+		else
+#endif
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+			goto err;
+			}
+		}
+	else
+		{
+		/* still data left over */
+		if (!(alg & SSL_aNULL))
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+			goto err;
+			}
+		if (n != 0)
+			{
+			al=SSL_AD_DECODE_ERROR;
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_EXTRA_DATA_IN_MESSAGE);
+			goto f_err;
+			}
+		}
+	EVP_PKEY_free(pkey);
+	EVP_MD_CTX_cleanup(&md_ctx);
+	return(1);
+f_err:
+	ssl3_send_alert(s,SSL3_AL_FATAL,al);
+err:
+	EVP_PKEY_free(pkey);
+#ifndef OPENSSL_NO_RSA
+	if (rsa != NULL)
+		RSA_free(rsa);
+#endif
+#ifndef OPENSSL_NO_DH
+	if (dh != NULL)
+		DH_free(dh);
+#endif
+#ifndef OPENSSL_NO_ECDH
+	BN_CTX_free(bn_ctx);
+	EC_POINT_free(srvr_ecpoint);
+	if (ecdh != NULL)
+		EC_KEY_free(ecdh);
+#endif
+	EVP_MD_CTX_cleanup(&md_ctx);
+	return(-1);
+	}
+
+int ssl3_get_certificate_request(SSL *s)
+	{
+	int ok,ret=0;
+	unsigned long n,nc,l;
+	unsigned int llen,ctype_num,i;
+	X509_NAME *xn=NULL;
+	const unsigned char *p,*q;
+	unsigned char *d;
+	STACK_OF(X509_NAME) *ca_sk=NULL;
+
+	n=s->method->ssl_get_message(s,
+		SSL3_ST_CR_CERT_REQ_A,
+		SSL3_ST_CR_CERT_REQ_B,
+		-1,
+		s->max_cert_list,
+		&ok);
+
+	if (!ok) return((int)n);
+
+	s->s3->tmp.cert_req=0;
+
+	if (s->s3->tmp.message_type == SSL3_MT_SERVER_DONE)
+		{
+		s->s3->tmp.reuse_message=1;
+		return(1);
+		}
+
+	if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE_REQUEST)
+		{
+		ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
+		SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_WRONG_MESSAGE_TYPE);
+		goto err;
+		}
+
+	/* TLS does not like anon-DH with client cert */
+	if (s->version > SSL3_VERSION)
+		{
+		l=s->s3->tmp.new_cipher->algorithms;
+		if (l & SSL_aNULL)
+			{
+			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
+			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER);
+			goto err;
+			}
+		}
+
+	p=d=(unsigned char *)s->init_msg;
+
+	if ((ca_sk=sk_X509_NAME_new(ca_dn_cmp)) == NULL)
+		{
+		SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,ERR_R_MALLOC_FAILURE);
+		goto err;
+		}
+
+	/* get the certificate types */
+	ctype_num= *(p++);
+	if (ctype_num > SSL3_CT_NUMBER)
+		ctype_num=SSL3_CT_NUMBER;
+	for (i=0; i<ctype_num; i++)
+		s->s3->tmp.ctype[i]= p[i];
+	p+=ctype_num;
+
+	/* get the CA RDNs */
+	n2s(p,llen);
+#if 0
+{
+FILE *out;
+out=fopen("/tmp/vsign.der","w");
+fwrite(p,1,llen,out);
+fclose(out);
+}
+#endif
+
+	if ((llen+ctype_num+2+1) != n)
+		{
+		ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
+		SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_LENGTH_MISMATCH);
+		goto err;
+		}
+
+	for (nc=0; nc<llen; )
+		{
+		n2s(p,l);
+		if ((l+nc+2) > llen)
+			{
+			if ((s->options & SSL_OP_NETSCAPE_CA_DN_BUG))
+				goto cont; /* netscape bugs */
+			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
+			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_CA_DN_TOO_LONG);
+			goto err;
+			}
+
+		q=p;
+
+		if ((xn=d2i_X509_NAME(NULL,&q,l)) == NULL)
+			{
+			/* If netscape tolerance is on, ignore errors */
+			if (s->options & SSL_OP_NETSCAPE_CA_DN_BUG)
+				goto cont;
+			else
+				{
+				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
+				SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,ERR_R_ASN1_LIB);
+				goto err;
+				}
+			}
+
+		if (q != (p+l))
+			{
+			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
+			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_CA_DN_LENGTH_MISMATCH);
+			goto err;
+			}
+		if (!sk_X509_NAME_push(ca_sk,xn))
+			{
+			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+
+		p+=l;
+		nc+=l+2;
+		}
+
+	if (0)
+		{
+cont:
+		ERR_clear_error();
+		}
+
+	/* we should setup a certificate to return.... */
+	s->s3->tmp.cert_req=1;
+	s->s3->tmp.ctype_num=ctype_num;
+	if (s->s3->tmp.ca_names != NULL)
+		sk_X509_NAME_pop_free(s->s3->tmp.ca_names,X509_NAME_free);
+	s->s3->tmp.ca_names=ca_sk;
+	ca_sk=NULL;
+
+	ret=1;
+err:
+	if (ca_sk != NULL) sk_X509_NAME_pop_free(ca_sk,X509_NAME_free);
+	return(ret);
+	}
+
+static int ca_dn_cmp(const X509_NAME * const *a, const X509_NAME * const *b)
+	{
+	return(X509_NAME_cmp(*a,*b));
+	}
+#ifndef OPENSSL_NO_TLSEXT
+int ssl3_get_new_session_ticket(SSL *s)
+	{
+	int ok,al,ret=0, ticklen;
+	long n;
+	const unsigned char *p;
+	unsigned char *d;
+
+	n=s->method->ssl_get_message(s,
+		SSL3_ST_CR_SESSION_TICKET_A,
+		SSL3_ST_CR_SESSION_TICKET_B,
+		-1,
+		16384,
+		&ok);
+
+	if (!ok)
+		return((int)n);
+
+	if (s->s3->tmp.message_type == SSL3_MT_FINISHED)
+		{
+		s->s3->tmp.reuse_message=1;
+		return(1);
+		}
+	if (s->s3->tmp.message_type != SSL3_MT_NEWSESSION_TICKET)
+		{
+		al=SSL_AD_UNEXPECTED_MESSAGE;
+		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_BAD_MESSAGE_TYPE);
+		goto f_err;
+		}
+	if (n < 6)
+		{
+		/* need at least ticket_lifetime_hint + ticket length */
+		al = SSL3_AL_FATAL,SSL_AD_DECODE_ERROR;
+		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_LENGTH_MISMATCH);
+		goto f_err;
+		}
+	p=d=(unsigned char *)s->init_msg;
+	n2l(p, s->session->tlsext_tick_lifetime_hint);
+	n2s(p, ticklen);
+	/* ticket_lifetime_hint + ticket_length + ticket */
+	if (ticklen + 6 != n)
+		{
+		al = SSL3_AL_FATAL,SSL_AD_DECODE_ERROR;
+		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_LENGTH_MISMATCH);
+		goto f_err;
+		}
+	if (s->session->tlsext_tick)
+		{
+		OPENSSL_free(s->session->tlsext_tick);
+		s->session->tlsext_ticklen = 0;
+		}
+	s->session->tlsext_tick = OPENSSL_malloc(ticklen);
+	if (!s->session->tlsext_tick)
+		{
+		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,ERR_R_MALLOC_FAILURE);
+		goto err;
+		}
+	memcpy(s->session->tlsext_tick, p, ticklen);
+	s->session->tlsext_ticklen = ticklen;
+	
+	ret=1;
+	return(ret);
+f_err:
+	ssl3_send_alert(s,SSL3_AL_FATAL,al);
+err:
+	return(-1);
+	}
+
+int ssl3_get_cert_status(SSL *s)
+	{
+	int ok, al;
+	unsigned long resplen;
+	long n;
+	const unsigned char *p;
+
+	n=s->method->ssl_get_message(s,
+		SSL3_ST_CR_CERT_STATUS_A,
+		SSL3_ST_CR_CERT_STATUS_B,
+		SSL3_MT_CERTIFICATE_STATUS,
+		16384,
+		&ok);
+
+	if (!ok) return((int)n);
+	if (n < 4)
+		{
+		/* need at least status type + length */
+		al = SSL_AD_DECODE_ERROR;
+		SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_LENGTH_MISMATCH);
+		goto f_err;
+		}
+	p = (unsigned char *)s->init_msg;
+	if (*p++ != TLSEXT_STATUSTYPE_ocsp)
+		{
+		al = SSL_AD_DECODE_ERROR;
+		SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_UNSUPPORTED_STATUS_TYPE);
+		goto f_err;
+		}
+	n2l3(p, resplen);
+	if (resplen + 4 != (unsigned long)n)
+		{
+		al = SSL_AD_DECODE_ERROR;
+		SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_LENGTH_MISMATCH);
+		goto f_err;
+		}
+	if (s->tlsext_ocsp_resp)
+		OPENSSL_free(s->tlsext_ocsp_resp);
+	s->tlsext_ocsp_resp = BUF_memdup(p, resplen);
+	if (!s->tlsext_ocsp_resp)
+		{
+		al = SSL_AD_INTERNAL_ERROR;
+		SSLerr(SSL_F_SSL3_GET_CERT_STATUS,ERR_R_MALLOC_FAILURE);
+		goto f_err;
+		}
+	s->tlsext_ocsp_resplen = resplen;
+	if (s->ctx->tlsext_status_cb)
+		{
+		int ret;
+		ret = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
+		if (ret == 0)
+			{
+			al = SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE;
+			SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_INVALID_STATUS_RESPONSE);
+			goto f_err;
+			}
+		if (ret < 0)
+			{
+			al = SSL_AD_INTERNAL_ERROR;
+			SSLerr(SSL_F_SSL3_GET_CERT_STATUS,ERR_R_MALLOC_FAILURE);
+			goto f_err;
+			}
+		}
+	return 1;
+f_err:
+	ssl3_send_alert(s,SSL3_AL_FATAL,al);
+	return(-1);
+	}
+#endif
+
+int ssl3_get_server_done(SSL *s)
+	{
+	int ok,ret=0;
+	long n;
+
+	n=s->method->ssl_get_message(s,
+		SSL3_ST_CR_SRVR_DONE_A,
+		SSL3_ST_CR_SRVR_DONE_B,
+		SSL3_MT_SERVER_DONE,
+		30, /* should be very small, like 0 :-) */
+		&ok);
+
+	if (!ok) return((int)n);
+	if (n > 0)
+		{
+		/* should contain no data */
+		ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
+		SSLerr(SSL_F_SSL3_GET_SERVER_DONE,SSL_R_LENGTH_MISMATCH);
+		return -1;
+		}
+	ret=1;
+	return(ret);
+	}
+
+
+int ssl3_send_client_key_exchange(SSL *s)
+	{
+	unsigned char *p,*d;
+	int n;
+	unsigned long l;
+#ifndef OPENSSL_NO_RSA
+	unsigned char *q;
+	EVP_PKEY *pkey=NULL;
+#endif
+#ifndef OPENSSL_NO_KRB5
+	KSSL_ERR kssl_err;
+#endif /* OPENSSL_NO_KRB5 */
+#ifndef OPENSSL_NO_ECDH
+	EC_KEY *clnt_ecdh = NULL;
+	const EC_POINT *srvr_ecpoint = NULL;
+	EVP_PKEY *srvr_pub_pkey = NULL;
+	unsigned char *encodedPoint = NULL;
+	int encoded_pt_len = 0;
+	BN_CTX * bn_ctx = NULL;
+#endif
+
+	if (s->state == SSL3_ST_CW_KEY_EXCH_A)
+		{
+		d=(unsigned char *)s->init_buf->data;
+		p= &(d[4]);
+
+		l=s->s3->tmp.new_cipher->algorithms;
+
+		/* Fool emacs indentation */
+		if (0) {}
+#ifndef OPENSSL_NO_RSA
+		else if (l & SSL_kRSA)
+			{
+			RSA *rsa;
+			unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
+
+			if (s->session->sess_cert->peer_rsa_tmp != NULL)
+				rsa=s->session->sess_cert->peer_rsa_tmp;
+			else
+				{
+				pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
+				if ((pkey == NULL) ||
+					(pkey->type != EVP_PKEY_RSA) ||
+					(pkey->pkey.rsa == NULL))
+					{
+					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+					goto err;
+					}
+				rsa=pkey->pkey.rsa;
+				EVP_PKEY_free(pkey);
+				}
+				
+			tmp_buf[0]=s->client_version>>8;
+			tmp_buf[1]=s->client_version&0xff;
+			if (RAND_bytes(&(tmp_buf[2]),sizeof tmp_buf-2) <= 0)
+					goto err;
+
+			s->session->master_key_length=sizeof tmp_buf;
+
+			q=p;
+			/* Fix buf for TLS and beyond */
+			if (s->version > SSL3_VERSION)
+				p+=2;
+			n=RSA_public_encrypt(sizeof tmp_buf,
+				tmp_buf,p,rsa,RSA_PKCS1_PADDING);
+#ifdef PKCS1_CHECK
+			if (s->options & SSL_OP_PKCS1_CHECK_1) p[1]++;
+			if (s->options & SSL_OP_PKCS1_CHECK_2) tmp_buf[0]=0x70;
+#endif
+			if (n <= 0)
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_ENCRYPT);
+				goto err;
+				}
+
+			/* Fix buf for TLS and beyond */
+			if (s->version > SSL3_VERSION)
+				{
+				s2n(n,q);
+				n+=2;
+				}
+
+			s->session->master_key_length=
+				s->method->ssl3_enc->generate_master_secret(s,
+					s->session->master_key,
+					tmp_buf,sizeof tmp_buf);
+			OPENSSL_cleanse(tmp_buf,sizeof tmp_buf);
+			}
+#endif
+#ifndef OPENSSL_NO_KRB5
+		else if (l & SSL_kKRB5)
+			{
+			krb5_error_code	krb5rc;
+			KSSL_CTX	*kssl_ctx = s->kssl_ctx;
+			/*  krb5_data	krb5_ap_req;  */
+			krb5_data	*enc_ticket;
+			krb5_data	authenticator, *authp = NULL;
+			EVP_CIPHER_CTX	ciph_ctx;
+			EVP_CIPHER	*enc = NULL;
+			unsigned char	iv[EVP_MAX_IV_LENGTH];
+			unsigned char	tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
+			unsigned char	epms[SSL_MAX_MASTER_KEY_LENGTH 
+						+ EVP_MAX_IV_LENGTH];
+			int 		padl, outl = sizeof(epms);
+
+			EVP_CIPHER_CTX_init(&ciph_ctx);
+
+#ifdef KSSL_DEBUG
+			printf("ssl3_send_client_key_exchange(%lx & %lx)\n",
+			        l, SSL_kKRB5);
+#endif	/* KSSL_DEBUG */
+
+			authp = NULL;
+#ifdef KRB5SENDAUTH
+			if (KRB5SENDAUTH)  authp = &authenticator;
+#endif	/* KRB5SENDAUTH */
+
+			krb5rc = kssl_cget_tkt(kssl_ctx, &enc_ticket, authp,
+				&kssl_err);
+			enc = kssl_map_enc(kssl_ctx->enctype);
+			if (enc == NULL)
+			    goto err;
+#ifdef KSSL_DEBUG
+			{
+			printf("kssl_cget_tkt rtn %d\n", krb5rc);
+			if (krb5rc && kssl_err.text)
+			  printf("kssl_cget_tkt kssl_err=%s\n", kssl_err.text);
+			}
+#endif	/* KSSL_DEBUG */
+
+			if (krb5rc)
+				{
+				ssl3_send_alert(s,SSL3_AL_FATAL,
+						SSL_AD_HANDSHAKE_FAILURE);
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+						kssl_err.reason);
+				goto err;
+				}
+
+			/*  20010406 VRS - Earlier versions used KRB5 AP_REQ
+			**  in place of RFC 2712 KerberosWrapper, as in:
+			**
+			**  Send ticket (copy to *p, set n = length)
+			**  n = krb5_ap_req.length;
+			**  memcpy(p, krb5_ap_req.data, krb5_ap_req.length);
+			**  if (krb5_ap_req.data)  
+			**    kssl_krb5_free_data_contents(NULL,&krb5_ap_req);
+			**
+			**  Now using real RFC 2712 KerberosWrapper
+			**  (Thanks to Simon Wilkinson <sxw at sxw.org.uk>)
+			**  Note: 2712 "opaque" types are here replaced
+			**  with a 2-byte length followed by the value.
+			**  Example:
+			**  KerberosWrapper= xx xx asn1ticket 0 0 xx xx encpms
+			**  Where "xx xx" = length bytes.  Shown here with
+			**  optional authenticator omitted.
+			*/
+
+			/*  KerberosWrapper.Ticket		*/
+			s2n(enc_ticket->length,p);
+			memcpy(p, enc_ticket->data, enc_ticket->length);
+			p+= enc_ticket->length;
+			n = enc_ticket->length + 2;
+
+			/*  KerberosWrapper.Authenticator	*/
+			if (authp  &&  authp->length)  
+				{
+				s2n(authp->length,p);
+				memcpy(p, authp->data, authp->length);
+				p+= authp->length;
+				n+= authp->length + 2;
+				
+				free(authp->data);
+				authp->data = NULL;
+				authp->length = 0;
+				}
+			else
+				{
+				s2n(0,p);/*  null authenticator length	*/
+				n+=2;
+				}
+ 
+			    tmp_buf[0]=s->client_version>>8;
+			    tmp_buf[1]=s->client_version&0xff;
+			    if (RAND_bytes(&(tmp_buf[2]),sizeof tmp_buf-2) <= 0)
+				goto err;
+
+			/*  20010420 VRS.  Tried it this way; failed.
+			**	EVP_EncryptInit_ex(&ciph_ctx,enc, NULL,NULL);
+			**	EVP_CIPHER_CTX_set_key_length(&ciph_ctx,
+			**				kssl_ctx->length);
+			**	EVP_EncryptInit_ex(&ciph_ctx,NULL, key,iv);
+			*/
+
+			memset(iv, 0, sizeof iv);  /* per RFC 1510 */
+			EVP_EncryptInit_ex(&ciph_ctx,enc, NULL,
+				kssl_ctx->key,iv);
+			EVP_EncryptUpdate(&ciph_ctx,epms,&outl,tmp_buf,
+				sizeof tmp_buf);
+			EVP_EncryptFinal_ex(&ciph_ctx,&(epms[outl]),&padl);
+			outl += padl;
+			if (outl > sizeof epms)
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+				goto err;
+				}
+			EVP_CIPHER_CTX_cleanup(&ciph_ctx);
+
+			/*  KerberosWrapper.EncryptedPreMasterSecret	*/
+			s2n(outl,p);
+			memcpy(p, epms, outl);
+			p+=outl;
+			n+=outl + 2;
+
+			s->session->master_key_length=
+			        s->method->ssl3_enc->generate_master_secret(s,
+					s->session->master_key,
+					tmp_buf, sizeof tmp_buf);
+
+			OPENSSL_cleanse(tmp_buf, sizeof tmp_buf);
+			OPENSSL_cleanse(epms, outl);
+			}
+#endif
+#ifndef OPENSSL_NO_DH
+		else if (l & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
+			{
+			DH *dh_srvr,*dh_clnt;
+
+			if (s->session->sess_cert == NULL) 
+				{
+				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
+				goto err;
+			        }
+
+			if (s->session->sess_cert->peer_dh_tmp != NULL)
+				dh_srvr=s->session->sess_cert->peer_dh_tmp;
+			else
+				{
+				/* we get them from the cert */
+				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNABLE_TO_FIND_DH_PARAMETERS);
+				goto err;
+				}
+			
+			/* generate a new random key */
+			if ((dh_clnt=DHparams_dup(dh_srvr)) == NULL)
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
+				goto err;
+				}
+			if (!DH_generate_key(dh_clnt))
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
+				goto err;
+				}
+
+			/* use the 'p' output buffer for the DH key, but
+			 * make sure to clear it out afterwards */
+
+			n=DH_compute_key(p,dh_srvr->pub_key,dh_clnt);
+
+			if (n <= 0)
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
+				goto err;
+				}
+
+			/* generate master key from the result */
+			s->session->master_key_length=
+				s->method->ssl3_enc->generate_master_secret(s,
+					s->session->master_key,p,n);
+			/* clean up */
+			memset(p,0,n);
+
+			/* send off the data */
+			n=BN_num_bytes(dh_clnt->pub_key);
+			s2n(n,p);
+			BN_bn2bin(dh_clnt->pub_key,p);
+			n+=2;
+
+			DH_free(dh_clnt);
+
+			/* perhaps clean things up a bit EAY EAY EAY EAY*/
+			}
+#endif
+
+#ifndef OPENSSL_NO_ECDH 
+		else if ((l & SSL_kECDH) || (l & SSL_kECDHE))
+			{
+			const EC_GROUP *srvr_group = NULL;
+			EC_KEY *tkey;
+			int ecdh_clnt_cert = 0;
+			int field_size = 0;
+
+			/* Did we send out the client's
+			 * ECDH share for use in premaster
+			 * computation as part of client certificate?
+			 * If so, set ecdh_clnt_cert to 1.
+			 */
+			if ((l & SSL_kECDH) && (s->cert != NULL)) 
+				{
+				/* XXX: For now, we do not support client
+				 * authentication using ECDH certificates.
+				 * To add such support, one needs to add
+				 * code that checks for appropriate 
+				 * conditions and sets ecdh_clnt_cert to 1.
+				 * For example, the cert have an ECC
+				 * key on the same curve as the server's
+				 * and the key should be authorized for
+				 * key agreement.
+				 *
+				 * One also needs to add code in ssl3_connect
+				 * to skip sending the certificate verify
+				 * message.
+				 *
+				 * if ((s->cert->key->privatekey != NULL) &&
+				 *     (s->cert->key->privatekey->type ==
+				 *      EVP_PKEY_EC) && ...)
+				 * ecdh_clnt_cert = 1;
+				 */
+				}
+
+			if (s->session->sess_cert->peer_ecdh_tmp != NULL)
+				{
+				tkey = s->session->sess_cert->peer_ecdh_tmp;
+				}
+			else
+				{
+				/* Get the Server Public Key from Cert */
+				srvr_pub_pkey = X509_get_pubkey(s->session-> \
+				    sess_cert->peer_pkeys[SSL_PKEY_ECC].x509);
+				if ((srvr_pub_pkey == NULL) ||
+				    (srvr_pub_pkey->type != EVP_PKEY_EC) ||
+				    (srvr_pub_pkey->pkey.ec == NULL))
+					{
+					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+					    ERR_R_INTERNAL_ERROR);
+					goto err;
+					}
+
+				tkey = srvr_pub_pkey->pkey.ec;
+				}
+
+			srvr_group   = EC_KEY_get0_group(tkey);
+			srvr_ecpoint = EC_KEY_get0_public_key(tkey);
+
+			if ((srvr_group == NULL) || (srvr_ecpoint == NULL))
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+				    ERR_R_INTERNAL_ERROR);
+				goto err;
+				}
+
+			if ((clnt_ecdh=EC_KEY_new()) == NULL) 
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
+				goto err;
+				}
+
+			if (!EC_KEY_set_group(clnt_ecdh, srvr_group))
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_EC_LIB);
+				goto err;
+				}
+			if (ecdh_clnt_cert) 
+				{ 
+				/* Reuse key info from our certificate
+				 * We only need our private key to perform
+				 * the ECDH computation.
+				 */
+				const BIGNUM *priv_key;
+				tkey = s->cert->key->privatekey->pkey.ec;
+				priv_key = EC_KEY_get0_private_key(tkey);
+				if (priv_key == NULL)
+					{
+					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
+					goto err;
+					}
+				if (!EC_KEY_set_private_key(clnt_ecdh, priv_key))
+					{
+					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_EC_LIB);
+					goto err;
+					}
+				}
+			else 
+				{
+				/* Generate a new ECDH key pair */
+				if (!(EC_KEY_generate_key(clnt_ecdh)))
+					{
+					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB);
+					goto err;
+					}
+				}
+
+			/* use the 'p' output buffer for the ECDH key, but
+			 * make sure to clear it out afterwards
+			 */
+
+			field_size = EC_GROUP_get_degree(srvr_group);
+			if (field_size <= 0)
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, 
+				       ERR_R_ECDH_LIB);
+				goto err;
+				}
+			n=ECDH_compute_key(p, (field_size+7)/8, srvr_ecpoint, clnt_ecdh, NULL);
+			if (n <= 0)
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, 
+				       ERR_R_ECDH_LIB);
+				goto err;
+				}
+
+			/* generate master key from the result */
+			s->session->master_key_length = s->method->ssl3_enc \
+			    -> generate_master_secret(s, 
+				s->session->master_key,
+				p, n);
+
+			memset(p, 0, n); /* clean up */
+
+			if (ecdh_clnt_cert) 
+				{
+				/* Send empty client key exch message */
+				n = 0;
+				}
+			else 
+				{
+				/* First check the size of encoding and
+				 * allocate memory accordingly.
+				 */
+				encoded_pt_len = 
+				    EC_POINT_point2oct(srvr_group, 
+					EC_KEY_get0_public_key(clnt_ecdh), 
+					POINT_CONVERSION_UNCOMPRESSED, 
+					NULL, 0, NULL);
+
+				encodedPoint = (unsigned char *) 
+				    OPENSSL_malloc(encoded_pt_len * 
+					sizeof(unsigned char)); 
+				bn_ctx = BN_CTX_new();
+				if ((encodedPoint == NULL) || 
+				    (bn_ctx == NULL)) 
+					{
+					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
+					goto err;
+					}
+
+				/* Encode the public key */
+				n = EC_POINT_point2oct(srvr_group, 
+				    EC_KEY_get0_public_key(clnt_ecdh), 
+				    POINT_CONVERSION_UNCOMPRESSED, 
+				    encodedPoint, encoded_pt_len, bn_ctx);
+
+				*p = n; /* length of encoded point */
+				/* Encoded point will be copied here */
+				p += 1; 
+				/* copy the point */
+				memcpy((unsigned char *)p, encodedPoint, n);
+				/* increment n to account for length field */
+				n += 1; 
+				}
+
+			/* Free allocated memory */
+			BN_CTX_free(bn_ctx);
+			if (encodedPoint != NULL) OPENSSL_free(encodedPoint);
+			if (clnt_ecdh != NULL) 
+				 EC_KEY_free(clnt_ecdh);
+			EVP_PKEY_free(srvr_pub_pkey);
+			}
+#endif /* !OPENSSL_NO_ECDH */
+		else
+			{
+			ssl3_send_alert(s, SSL3_AL_FATAL,
+			    SSL_AD_HANDSHAKE_FAILURE);
+			SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+			    ERR_R_INTERNAL_ERROR);
+			goto err;
+			}
+		
+		*(d++)=SSL3_MT_CLIENT_KEY_EXCHANGE;
+		l2n3(n,d);
+
+		s->state=SSL3_ST_CW_KEY_EXCH_B;
+		/* number of bytes to write */
+		s->init_num=n+4;
+		s->init_off=0;
+		}
+
+	/* SSL3_ST_CW_KEY_EXCH_B */
+	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+err:
+#ifndef OPENSSL_NO_ECDH
+	BN_CTX_free(bn_ctx);
+	if (encodedPoint != NULL) OPENSSL_free(encodedPoint);
+	if (clnt_ecdh != NULL) 
+		EC_KEY_free(clnt_ecdh);
+	EVP_PKEY_free(srvr_pub_pkey);
+#endif
+	return(-1);
+	}
+
+int ssl3_send_client_verify(SSL *s)
+	{
+	unsigned char *p,*d;
+	unsigned char data[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH];
+	EVP_PKEY *pkey;
+#ifndef OPENSSL_NO_RSA
+	unsigned u=0;
+#endif
+	unsigned long n;
+#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_ECDSA)
+	int j;
+#endif
+
+	if (s->state == SSL3_ST_CW_CERT_VRFY_A)
+		{
+		d=(unsigned char *)s->init_buf->data;
+		p= &(d[4]);
+		pkey=s->cert->key->privatekey;
+
+		s->method->ssl3_enc->cert_verify_mac(s,&(s->s3->finish_dgst2),
+			&(data[MD5_DIGEST_LENGTH]));
+
+#ifndef OPENSSL_NO_RSA
+		if (pkey->type == EVP_PKEY_RSA)
+			{
+			s->method->ssl3_enc->cert_verify_mac(s,
+				&(s->s3->finish_dgst1),&(data[0]));
+			if (RSA_sign(NID_md5_sha1, data,
+					 MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH,
+					&(p[2]), &u, pkey->pkey.rsa) <= 0 )
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_RSA_LIB);
+				goto err;
+				}
+			s2n(u,p);
+			n=u+2;
+			}
+		else
+#endif
+#ifndef OPENSSL_NO_DSA
+			if (pkey->type == EVP_PKEY_DSA)
+			{
+			if (!DSA_sign(pkey->save_type,
+				&(data[MD5_DIGEST_LENGTH]),
+				SHA_DIGEST_LENGTH,&(p[2]),
+				(unsigned int *)&j,pkey->pkey.dsa))
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_DSA_LIB);
+				goto err;
+				}
+			s2n(j,p);
+			n=j+2;
+			}
+		else
+#endif
+#ifndef OPENSSL_NO_ECDSA
+			if (pkey->type == EVP_PKEY_EC)
+			{
+			if (!ECDSA_sign(pkey->save_type,
+				&(data[MD5_DIGEST_LENGTH]),
+				SHA_DIGEST_LENGTH,&(p[2]),
+				(unsigned int *)&j,pkey->pkey.ec))
+				{
+				SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,
+				    ERR_R_ECDSA_LIB);
+				goto err;
+				}
+			s2n(j,p);
+			n=j+2;
+			}
+		else
+#endif
+			{
+			SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_INTERNAL_ERROR);
+			goto err;
+			}
+		*(d++)=SSL3_MT_CERTIFICATE_VERIFY;
+		l2n3(n,d);
+
+		s->state=SSL3_ST_CW_CERT_VRFY_B;
+		s->init_num=(int)n+4;
+		s->init_off=0;
+		}
+	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+err:
+	return(-1);
+	}
+
+int ssl3_send_client_certificate(SSL *s)
+	{
+	X509 *x509=NULL;
+	EVP_PKEY *pkey=NULL;
+	int i;
+	unsigned long l;
+
+	if (s->state ==	SSL3_ST_CW_CERT_A)
+		{
+		if ((s->cert == NULL) ||
+			(s->cert->key->x509 == NULL) ||
+			(s->cert->key->privatekey == NULL))
+			s->state=SSL3_ST_CW_CERT_B;
+		else
+			s->state=SSL3_ST_CW_CERT_C;
+		}
+
+	/* We need to get a client cert */
+	if (s->state == SSL3_ST_CW_CERT_B)
+		{
+		/* If we get an error, we need to
+		 * ssl->rwstate=SSL_X509_LOOKUP; return(-1);
+		 * We then get retied later */
+		i=0;
+		i = ssl_do_client_cert_cb(s, &x509, &pkey);
+		if (i < 0)
+			{
+			s->rwstate=SSL_X509_LOOKUP;
+			return(-1);
+			}
+		s->rwstate=SSL_NOTHING;
+		if ((i == 1) && (pkey != NULL) && (x509 != NULL))
+			{
+			s->state=SSL3_ST_CW_CERT_B;
+			if (	!SSL_use_certificate(s,x509) ||
+				!SSL_use_PrivateKey(s,pkey))
+				i=0;
+			}
+		else if (i == 1)
+			{
+			i=0;
+			SSLerr(SSL_F_SSL3_SEND_CLIENT_CERTIFICATE,SSL_R_BAD_DATA_RETURNED_BY_CALLBACK);
+			}
+
+		if (x509 != NULL) X509_free(x509);
+		if (pkey != NULL) EVP_PKEY_free(pkey);
+		if (i == 0)
+			{
+			if (s->version == SSL3_VERSION)
+				{
+				s->s3->tmp.cert_req=0;
+				ssl3_send_alert(s,SSL3_AL_WARNING,SSL_AD_NO_CERTIFICATE);
+				return(1);
+				}
+			else
+				{
+				s->s3->tmp.cert_req=2;
+				}
+			}
+
+		/* Ok, we have a cert */
+		s->state=SSL3_ST_CW_CERT_C;
+		}
+
+	if (s->state == SSL3_ST_CW_CERT_C)
+		{
+		s->state=SSL3_ST_CW_CERT_D;
+		l=ssl3_output_cert_chain(s,
+			(s->s3->tmp.cert_req == 2)?NULL:s->cert->key->x509);
+		s->init_num=(int)l;
+		s->init_off=0;
+		}
+	/* SSL3_ST_CW_CERT_D */
+	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+	}
+
+#define has_bits(i,m)	(((i)&(m)) == (m))
+
+int ssl3_check_cert_and_algorithm(SSL *s)
+	{
+	int i,idx;
+	long algs;
+	EVP_PKEY *pkey=NULL;
+	SESS_CERT *sc;
+#ifndef OPENSSL_NO_RSA
+	RSA *rsa;
+#endif
+#ifndef OPENSSL_NO_DH
+	DH *dh;
+#endif
+
+	sc=s->session->sess_cert;
+
+	algs=s->s3->tmp.new_cipher->algorithms;
+
+	/* we don't have a certificate */
+	if (algs & (SSL_aDH|SSL_aNULL|SSL_aKRB5))
+		return(1);
+
+	if (sc == NULL)
+		{
+		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,ERR_R_INTERNAL_ERROR);
+		goto err;
+		}
+
+#ifndef OPENSSL_NO_RSA
+	rsa=s->session->sess_cert->peer_rsa_tmp;
+#endif
+#ifndef OPENSSL_NO_DH
+	dh=s->session->sess_cert->peer_dh_tmp;
+#endif
+
+	/* This is the passed certificate */
+
+	idx=sc->peer_cert_type;
+#ifndef OPENSSL_NO_ECDH
+	if (idx == SSL_PKEY_ECC)
+		{
+		if (check_srvr_ecc_cert_and_alg(sc->peer_pkeys[idx].x509,
+		    s->s3->tmp.new_cipher) == 0) 
+			{ /* check failed */
+			SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_BAD_ECC_CERT);
+			goto f_err;			
+			}
+		else 
+			{
+			return 1;
+			}
+		}
+#endif
+	pkey=X509_get_pubkey(sc->peer_pkeys[idx].x509);
+	i=X509_certificate_type(sc->peer_pkeys[idx].x509,pkey);
+	EVP_PKEY_free(pkey);
+
+	
+	/* Check that we have a certificate if we require one */
+	if ((algs & SSL_aRSA) && !has_bits(i,EVP_PK_RSA|EVP_PKT_SIGN))
+		{
+		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_RSA_SIGNING_CERT);
+		goto f_err;
+		}
+#ifndef OPENSSL_NO_DSA
+	else if ((algs & SSL_aDSS) && !has_bits(i,EVP_PK_DSA|EVP_PKT_SIGN))
+		{
+		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DSA_SIGNING_CERT);
+		goto f_err;
+		}
+#endif
+#ifndef OPENSSL_NO_RSA
+	if ((algs & SSL_kRSA) &&
+		!(has_bits(i,EVP_PK_RSA|EVP_PKT_ENC) || (rsa != NULL)))
+		{
+		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_RSA_ENCRYPTING_CERT);
+		goto f_err;
+		}
+#endif
+#ifndef OPENSSL_NO_DH
+	if ((algs & SSL_kEDH) &&
+		!(has_bits(i,EVP_PK_DH|EVP_PKT_EXCH) || (dh != NULL)))
+		{
+		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_KEY);
+		goto f_err;
+		}
+	else if ((algs & SSL_kDHr) && !has_bits(i,EVP_PK_DH|EVP_PKS_RSA))
+		{
+		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_RSA_CERT);
+		goto f_err;
+		}
+#ifndef OPENSSL_NO_DSA
+	else if ((algs & SSL_kDHd) && !has_bits(i,EVP_PK_DH|EVP_PKS_DSA))
+		{
+		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_DSA_CERT);
+		goto f_err;
+		}
+#endif
+#endif
+
+	if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && !has_bits(i,EVP_PKT_EXP))
+		{
+#ifndef OPENSSL_NO_RSA
+		if (algs & SSL_kRSA)
+			{
+			if (rsa == NULL
+			    || RSA_size(rsa)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher))
+				{
+				SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_EXPORT_TMP_RSA_KEY);
+				goto f_err;
+				}
+			}
+		else
+#endif
+#ifndef OPENSSL_NO_DH
+			if (algs & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
+			    {
+			    if (dh == NULL
+				|| DH_size(dh)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher))
+				{
+				SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_EXPORT_TMP_DH_KEY);
+				goto f_err;
+				}
+			}
+		else
+#endif
+			{
+			SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
+			goto f_err;
+			}
+		}
+	return(1);
+f_err:
+	ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
+err:
+	return(0);
+	}
+
+
+#ifndef OPENSSL_NO_ECDH
+/* This is the complement of nid2curve_id in s3_srvr.c. */
+static int curve_id2nid(int curve_id)
+{
+	/* ECC curves from draft-ietf-tls-ecc-01.txt (Mar 15, 2001)
+	 * (no changes in draft-ietf-tls-ecc-03.txt [June 2003]) */
+	static int nid_list[26] =
+	{
+		0,
+		NID_sect163k1, /* sect163k1 (1) */
+		NID_sect163r1, /* sect163r1 (2) */
+		NID_sect163r2, /* sect163r2 (3) */
+		NID_sect193r1, /* sect193r1 (4) */ 
+		NID_sect193r2, /* sect193r2 (5) */ 
+		NID_sect233k1, /* sect233k1 (6) */
+		NID_sect233r1, /* sect233r1 (7) */ 
+		NID_sect239k1, /* sect239k1 (8) */ 
+		NID_sect283k1, /* sect283k1 (9) */
+		NID_sect283r1, /* sect283r1 (10) */ 
+		NID_sect409k1, /* sect409k1 (11) */ 
+		NID_sect409r1, /* sect409r1 (12) */
+		NID_sect571k1, /* sect571k1 (13) */ 
+		NID_sect571r1, /* sect571r1 (14) */ 
+		NID_secp160k1, /* secp160k1 (15) */
+		NID_secp160r1, /* secp160r1 (16) */ 
+		NID_secp160r2, /* secp160r2 (17) */ 
+		NID_secp192k1, /* secp192k1 (18) */
+		NID_X9_62_prime192v1, /* secp192r1 (19) */ 
+		NID_secp224k1, /* secp224k1 (20) */ 
+		NID_secp224r1, /* secp224r1 (21) */
+		NID_secp256k1, /* secp256k1 (22) */ 
+		NID_X9_62_prime256v1, /* secp256r1 (23) */ 
+		NID_secp384r1, /* secp384r1 (24) */
+		NID_secp521r1  /* secp521r1 (25) */	
+	};
+	
+	if ((curve_id < 1) || (curve_id > 25)) return 0;
+
+	return nid_list[curve_id];
+}
+#endif
+
+/* Check to see if handshake is full or resumed. Usually this is just a
+ * case of checking to see if a cache hit has occurred. In the case of
+ * session tickets we have to check the next message to be sure.
+ */
+
+#ifndef OPENSSL_NO_TLSEXT
+static int ssl3_check_finished(SSL *s)
+	{
+	int ok;
+	long n;
+	/* If we have no ticket or session ID is non-zero length (a match of
+	 * a non-zero session length would never reach here) it cannot be a
+	 * resumed session.
+	 */
+	if (!s->session->tlsext_tick || s->session->session_id_length)
+		return 1;
+	/* this function is called when we really expect a Certificate
+	 * message, so permit appropriate message length */
+	n=s->method->ssl_get_message(s,
+		SSL3_ST_CR_CERT_A,
+		SSL3_ST_CR_CERT_B,
+		-1,
+		s->max_cert_list,
+		&ok);
+	if (!ok) return((int)n);
+	s->s3->tmp.reuse_message = 1;
+	if ((s->s3->tmp.message_type == SSL3_MT_FINISHED)
+		|| (s->s3->tmp.message_type == SSL3_MT_NEWSESSION_TICKET))
+		return 2;
+
+	return 1;
+	}
+#endif
+
+int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey)
+	{
+	int i = 0;
+#ifndef OPENSSL_NO_ENGINE
+	if (s->ctx->client_cert_engine)
+		{
+		i = ENGINE_load_ssl_client_cert(s->ctx->client_cert_engine, s,
+						SSL_get_client_CA_list(s),
+						px509, ppkey, NULL, NULL, NULL);
+		if (i != 0)
+			return i;
+		}
+#endif
+	if (s->ctx->client_cert_cb)
+		i = s->ctx->client_cert_cb(s,px509,ppkey);
+	return i;
+	}

Modified: openssl/branches/upstream/current/ssl/s3_srvr.c
===================================================================
--- openssl/branches/upstream/current/ssl/s3_srvr.c	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/ssl/s3_srvr.c	2009-05-16 15:25:35 UTC (rev 372)
@@ -290,9 +290,18 @@
 		case SSL3_ST_SW_SRVR_HELLO_B:
 			ret=ssl3_send_server_hello(s);
 			if (ret <= 0) goto end;
-
+#ifndef OPENSSL_NO_TLSEXT
 			if (s->hit)
-				s->state=SSL3_ST_SW_CHANGE_A;
+				{
+				if (s->tlsext_ticket_expected)
+					s->state=SSL3_ST_SW_SESSION_TICKET_A;
+				else
+					s->state=SSL3_ST_SW_CHANGE_A;
+				}
+#else
+			if (s->hit)
+					s->state=SSL3_ST_SW_CHANGE_A;
+#endif
 			else
 				s->state=SSL3_ST_SW_CERT_A;
 			s->init_num=0;
@@ -306,10 +315,24 @@
 				{
 				ret=ssl3_send_server_certificate(s);
 				if (ret <= 0) goto end;
+#ifndef OPENSSL_NO_TLSEXT
+				if (s->tlsext_status_expected)
+					s->state=SSL3_ST_SW_CERT_STATUS_A;
+				else
+					s->state=SSL3_ST_SW_KEY_EXCH_A;
 				}
 			else
+				{
+				skip = 1;
+				s->state=SSL3_ST_SW_KEY_EXCH_A;
+				}
+#else
+				}
+			else
 				skip=1;
+
 			s->state=SSL3_ST_SW_KEY_EXCH_A;
+#endif
 			s->init_num=0;
 			break;
 
@@ -512,6 +535,14 @@
 			s->init_num=0;
 			break;
 
+		case SSL3_ST_SW_CERT_STATUS_A:
+		case SSL3_ST_SW_CERT_STATUS_B:
+			ret=ssl3_send_cert_status(s);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_SW_KEY_EXCH_A;
+			s->init_num=0;
+			break;
+
 #endif
 
 		case SSL3_ST_SW_CHANGE_A:
@@ -871,22 +902,28 @@
 				break;
 				}
 			}
-		if (j == 0)
+		if (j == 0 && (s->options & SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) && (sk_SSL_CIPHER_num(ciphers) == 1))
 			{
-			if ((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)
 				{
-				/* Very bad for multi-threading.... */
-				s->session->cipher=sk_SSL_CIPHER_value(ciphers, 0);
+				s->session->cipher = c;
+				j = 1;
 				}
-			else
-				{
-				/* 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;
-				}
 			}
+		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 */
@@ -1093,8 +1130,16 @@
 		 * session-id if we want it to be single use.
 		 * Currently I will not implement the '0' length session-id
 		 * 12-Jan-98 - I'll now support the '0' length stuff.
+		 *
+		 * We also have an additional case where stateless session
+		 * resumption is successful: we always send back the old
+		 * session id. In this case s->hit is non zero: this can
+		 * only happen if stateless session resumption is succesful
+		 * if session caching is disabled so existing functionality
+		 * is unaffected.
 		 */
-		if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER))
+		if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER)
+			&& !s->hit)
 			s->session->session_id_length=0;
 
 		sl=s->session->session_id_length;
@@ -1133,13 +1178,13 @@
 		*(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));
 	}
 
@@ -1163,7 +1208,7 @@
 		s->init_off=0;
 		}
 
-	/* SSL3_ST_CW_CLNT_HELLO_B */
+	/* SSL3_ST_SW_SRVR_DONE_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 	}
 
@@ -1501,6 +1546,8 @@
 				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);
@@ -2519,7 +2566,7 @@
 	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);
@@ -2664,6 +2711,8 @@
 		unsigned int hlen;
 		EVP_CIPHER_CTX ctx;
 		HMAC_CTX hctx;
+		unsigned char iv[EVP_MAX_IV_LENGTH];
+		unsigned char key_name[16];
 
 		/* get session encoding length */
 		slen = i2d_SSL_SESSION(s->session, NULL);
@@ -2694,29 +2743,47 @@
 		*(p++)=SSL3_MT_NEWSESSION_TICKET;
 		/* Skip message length for now */
 		p += 3;
+		EVP_CIPHER_CTX_init(&ctx);
+		HMAC_CTX_init(&hctx);
+		/* Initialize HMAC and cipher contexts. If callback present
+		 * it does all the work otherwise use generated values
+		 * from parent ctx.
+		 */
+		if (s->ctx->tlsext_ticket_key_cb)
+			{
+			if (s->ctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx,
+							 &hctx, 1) < 0)
+				{
+				OPENSSL_free(senc);
+				return -1;
+				}
+			}
+		else
+			{
+			RAND_pseudo_bytes(iv, 16);
+			EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
+					s->ctx->tlsext_tick_aes_key, iv);
+			HMAC_Init_ex(&hctx, s->ctx->tlsext_tick_hmac_key, 16,
+					tlsext_tick_md(), NULL);
+			memcpy(key_name, s->ctx->tlsext_tick_key_name, 16);
+			}
 		l2n(s->session->tlsext_tick_lifetime_hint, p);
 		/* Skip ticket length for now */
 		p += 2;
 		/* Output key name */
 		macstart = p;
-		memcpy(p, s->ctx->tlsext_tick_key_name, 16);
+		memcpy(p, key_name, 16);
 		p += 16;
-		/* Generate and output IV */
-		RAND_pseudo_bytes(p, 16);
-		EVP_CIPHER_CTX_init(&ctx);
+		/* output IV */
+		memcpy(p, iv, EVP_CIPHER_CTX_iv_length(&ctx));
+		p += EVP_CIPHER_CTX_iv_length(&ctx);
 		/* Encrypt session data */
-		EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
-					s->ctx->tlsext_tick_aes_key, p);
-		p += 16;
 		EVP_EncryptUpdate(&ctx, p, &len, senc, slen);
 		p += len;
 		EVP_EncryptFinal(&ctx, p, &len);
 		p += len;
 		EVP_CIPHER_CTX_cleanup(&ctx);
 
-		HMAC_CTX_init(&hctx);
-		HMAC_Init_ex(&hctx, s->ctx->tlsext_tick_hmac_key, 16,
-				tlsext_tick_md(), NULL);
 		HMAC_Update(&hctx, macstart, p - macstart);
 		HMAC_Final(&hctx, p, &hlen);
 		HMAC_CTX_cleanup(&hctx);
@@ -2740,4 +2807,39 @@
 	/* SSL3_ST_SW_SESSION_TICKET_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 	}
+
+int ssl3_send_cert_status(SSL *s)
+	{
+	if (s->state == SSL3_ST_SW_CERT_STATUS_A)
+		{
+		unsigned char *p;
+		/* Grow buffer if need be: the length calculation is as
+ 		 * follows 1 (message type) + 3 (message length) +
+ 		 * 1 (ocsp response type) + 3 (ocsp response length)
+ 		 * + (ocsp response)
+ 		 */
+		if (!BUF_MEM_grow(s->init_buf, 8 + s->tlsext_ocsp_resplen))
+			return -1;
+
+		p=(unsigned char *)s->init_buf->data;
+
+		/* do the header */
+		*(p++)=SSL3_MT_CERTIFICATE_STATUS;
+		/* message length */
+		l2n3(s->tlsext_ocsp_resplen + 4, p);
+		/* status type */
+		*(p++)= s->tlsext_status_type;
+		/* length of OCSP response */
+		l2n3(s->tlsext_ocsp_resplen, p);
+		/* actual response */
+		memcpy(p, s->tlsext_ocsp_resp, s->tlsext_ocsp_resplen);
+		/* number of bytes to write */
+		s->init_num = 8 + s->tlsext_ocsp_resplen;
+		s->state=SSL3_ST_SW_CERT_STATUS_B;
+		s->init_off = 0;
+		}
+
+	/* SSL3_ST_SW_CERT_STATUS_B */
+	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+	}
 #endif

Modified: openssl/branches/upstream/current/ssl/ssl.h
===================================================================
--- openssl/branches/upstream/current/ssl/ssl.h	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/ssl/ssl.h	2009-05-16 15:25:35 UTC (rev 372)
@@ -187,6 +187,7 @@
 #include <openssl/buffer.h>
 #endif
 #include <openssl/pem.h>
+#include <openssl/hmac.h>
 
 #include <openssl/kssl.h>
 #include <openssl/safestack.h>
@@ -251,6 +252,7 @@
 #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"
@@ -360,9 +362,6 @@
 
 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
 	{
@@ -759,6 +758,12 @@
 
 	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 *);
@@ -767,6 +772,16 @@
 	unsigned char tlsext_tick_key_name[16];
 	unsigned char tlsext_tick_hmac_key[16];
 	unsigned char tlsext_tick_aes_key[16];
+	/* Callback to support customisation of ticket key setting */
+	int (*tlsext_ticket_key_cb)(SSL *ssl,
+					unsigned char *name, unsigned char *iv,
+					EVP_CIPHER_CTX *ectx,
+					HMAC_CTX *hctx, int enc);
+
+	/* certificate status request info */
+	/* Callback for status request */
+	int (*tlsext_status_cb)(SSL *ssl, void *arg);
+	void *tlsext_status_arg;
 #endif
 
 	};
@@ -818,6 +833,9 @@
 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));
 
@@ -1002,6 +1020,18 @@
 	                          1 : prepare 2, allow last ack just after in server callback.
 	                          2 : don't call servername callback, no ack in server hello
 	                       */
+	/* certificate status request info */
+	/* Status type or -1 if no status type */
+	int tlsext_status_type;
+	/* Expect OCSP CertificateStatus message */
+	int tlsext_status_expected;
+	/* OCSP status request only */
+	STACK_OF(OCSP_RESPID) *tlsext_ocsp_ids;
+	X509_EXTENSIONS *tlsext_ocsp_exts;
+	/* OCSP response received or to be sent */
+	unsigned char *tlsext_ocsp_resp;
+	int tlsext_ocsp_resplen;
+
 	/* RFC4507 session ticket expected to be received or sent */
 	int tlsext_ticket_expected;
 	SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */
@@ -1157,6 +1187,7 @@
 #define SSL_AD_UNSUPPORTED_EXTENSION	TLS1_AD_UNSUPPORTED_EXTENSION
 #define SSL_AD_CERTIFICATE_UNOBTAINABLE TLS1_AD_CERTIFICATE_UNOBTAINABLE
 #define SSL_AD_UNRECOGNIZED_NAME	TLS1_AD_UNRECOGNIZED_NAME
+#define SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE
 
 #define SSL_ERROR_NONE			0
 #define SSL_ERROR_SSL			1
@@ -1224,6 +1255,18 @@
 #define SSL_CTRL_SET_TLSEXT_DEBUG_ARG		57
 #define SSL_CTRL_GET_TLSEXT_TICKET_KEYS		58
 #define SSL_CTRL_SET_TLSEXT_TICKET_KEYS		59
+
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB	63
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG	64
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE	65
+#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS	66
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS	67
+#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS	68
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS	69
+#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP	70
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP	71
+
+#define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB	72
 #endif
 
 #define SSL_session_reused(ssl) \
@@ -1666,9 +1709,11 @@
 #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
+#define SSL_F_SSL3_GET_CERT_STATUS			 288
 #define SSL_F_SSL3_GET_CERT_VERIFY			 136
 #define SSL_F_SSL3_GET_CLIENT_CERTIFICATE		 137
 #define SSL_F_SSL3_GET_CLIENT_HELLO			 138
@@ -1718,6 +1763,7 @@
 #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
@@ -1853,6 +1899,7 @@
 #define SSL_R_INVALID_CHALLENGE_LENGTH			 158
 #define SSL_R_INVALID_COMMAND				 280
 #define SSL_R_INVALID_PURPOSE				 278
+#define SSL_R_INVALID_STATUS_RESPONSE			 316
 #define SSL_R_INVALID_TICKET_KEYS_LENGTH		 275
 #define SSL_R_INVALID_TRUST				 279
 #define SSL_R_KEY_ARG_TOO_LONG				 284
@@ -1897,6 +1944,7 @@
 #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
@@ -2009,6 +2057,7 @@
 #define SSL_R_UNSUPPORTED_ELLIPTIC_CURVE		 315
 #define SSL_R_UNSUPPORTED_PROTOCOL			 258
 #define SSL_R_UNSUPPORTED_SSL_VERSION			 259
+#define SSL_R_UNSUPPORTED_STATUS_TYPE			 329
 #define SSL_R_WRITE_BIO_NOT_SET				 260
 #define SSL_R_WRONG_CIPHER_RETURNED			 261
 #define SSL_R_WRONG_MESSAGE_TYPE			 262

Modified: openssl/branches/upstream/current/ssl/ssl_lib.c
===================================================================
--- openssl/branches/upstream/current/ssl/ssl_lib.c	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/ssl/ssl_lib.c	2009-05-16 15:25:35 UTC (rev 372)
@@ -126,9 +126,13 @@
 #include <openssl/lhash.h>
 #include <openssl/x509v3.h>
 #include <openssl/rand.h>
+#include <openssl/ocsp.h>
 #ifndef OPENSSL_NO_DH
 #include <openssl/dh.h>
 #endif
+#ifndef OPENSSL_NO_ENGINE
+#include <openssl/engine.h>
+#endif
 
 const char *SSL_version_str=OPENSSL_VERSION_TEXT;
 
@@ -311,6 +315,12 @@
 	s->tlsext_debug_cb = 0;
 	s->tlsext_debug_arg = NULL;
 	s->tlsext_ticket_expected = 0;
+	s->tlsext_status_type = -1;
+	s->tlsext_status_expected = 0;
+	s->tlsext_ocsp_ids = NULL;
+	s->tlsext_ocsp_exts = NULL;
+	s->tlsext_ocsp_resp = NULL;
+	s->tlsext_ocsp_resplen = -1;
 	CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX);
 	s->initial_ctx=ctx;
 #endif
@@ -500,7 +510,16 @@
 
 	if (s->ctx) SSL_CTX_free(s->ctx);
 #ifndef OPENSSL_NO_TLSEXT
+	if (s->tlsext_hostname)
+		OPENSSL_free(s->tlsext_hostname);
 	if (s->initial_ctx) SSL_CTX_free(s->initial_ctx);
+	if (s->tlsext_ocsp_exts)
+		sk_X509_EXTENSION_pop_free(s->tlsext_ocsp_exts,
+						X509_EXTENSION_free);
+	if (s->tlsext_ocsp_ids)
+		sk_OCSP_RESPID_pop_free(s->tlsext_ocsp_ids, OCSP_RESPID_free);
+	if (s->tlsext_ocsp_resp)
+		OPENSSL_free(s->tlsext_ocsp_resp);
 #endif
 	if (s->client_CA != NULL)
 		sk_X509_NAME_pop_free(s->client_CA,X509_NAME_free);
@@ -1379,6 +1398,14 @@
 		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);
@@ -1494,8 +1521,32 @@
 		|| (RAND_bytes(ret->tlsext_tick_aes_key, 16) <= 0))
 		ret->options |= SSL_OP_NO_TICKET;
 
+	ret->tlsext_status_cb = 0;
+	ret->tlsext_status_arg = NULL;
+
 #endif
 
+#ifndef OPENSSL_NO_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);
 err:
 	SSLerr(SSL_F_SSL_CTX_NEW,ERR_R_MALLOC_FAILURE);
@@ -1566,6 +1617,10 @@
 #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);
 	}
 

Added: openssl/branches/upstream/current/ssl/ssltest.c
===================================================================
--- openssl/branches/upstream/current/ssl/ssltest.c	                        (rev 0)
+++ openssl/branches/upstream/current/ssl/ssltest.c	2009-05-16 15:25:35 UTC (rev 372)
@@ -0,0 +1,2315 @@
+/* ssl/ssltest.c */
+/* Copyright (C) 1995-1998 Eric Young (eay at cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay at cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh at cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay at cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh at cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core at 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 at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECC cipher suite support in OpenSSL originally developed by 
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#define _BSD_SOURCE 1		/* Or gethostname won't be declared properly
+				   on Linux and GNU platforms. */
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#define USE_SOCKETS
+#include "e_os.h"
+
+#define _XOPEN_SOURCE 500	/* Or isascii won't be declared properly on
+				   VMS (at least with DECompHP C).  */
+#include <ctype.h>
+
+#include <openssl/bio.h>
+#include <openssl/crypto.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/ssl.h>
+#ifndef OPENSSL_NO_ENGINE
+#include <openssl/engine.h>
+#endif
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#ifndef OPENSSL_NO_RSA
+#include <openssl/rsa.h>
+#endif
+#ifndef OPENSSL_NO_DSA
+#include <openssl/dsa.h>
+#endif
+#ifndef OPENSSL_NO_DH
+#include <openssl/dh.h>
+#endif
+#include <openssl/bn.h>
+
+#define _XOPEN_SOURCE_EXTENDED	1 /* Or gethostname won't be declared properly
+				     on Compaq platforms (at least with DEC C).
+				     Do not try to put it earlier, or IPv6 includes
+				     get screwed...
+				  */
+
+#ifdef OPENSSL_SYS_WINDOWS
+#include <winsock.h>
+#else
+#include OPENSSL_UNISTD
+#endif
+
+#ifdef OPENSSL_SYS_VMS
+#  define TEST_SERVER_CERT "SYS$DISK:[-.APPS]SERVER.PEM"
+#  define TEST_CLIENT_CERT "SYS$DISK:[-.APPS]CLIENT.PEM"
+#elif defined(OPENSSL_SYS_WINCE)
+#  define TEST_SERVER_CERT "\\OpenSSL\\server.pem"
+#  define TEST_CLIENT_CERT "\\OpenSSL\\client.pem"
+#elif defined(OPENSSL_SYS_NETWARE)
+#  define TEST_SERVER_CERT "\\openssl\\apps\\server.pem"
+#  define TEST_CLIENT_CERT "\\openssl\\apps\\client.pem"
+#else
+#  define TEST_SERVER_CERT "../apps/server.pem"
+#  define TEST_CLIENT_CERT "../apps/client.pem"
+#endif
+
+/* There is really no standard for this, so let's assign some tentative
+   numbers.  In any case, these numbers are only for this test */
+#define COMP_RLE	255
+#define COMP_ZLIB	1
+
+static int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx);
+#ifndef OPENSSL_NO_RSA
+static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export,int keylength);
+static void free_tmp_rsa(void);
+#endif
+static int MS_CALLBACK app_verify_callback(X509_STORE_CTX *ctx, void *arg);
+#define APP_CALLBACK_STRING "Test Callback Argument"
+struct app_verify_arg
+	{
+	char *string;
+	int app_verify;
+	int allow_proxy_certs;
+	char *proxy_auth;
+	char *proxy_cond;
+	};
+
+#ifndef OPENSSL_NO_DH
+static DH *get_dh512(void);
+static DH *get_dh1024(void);
+static DH *get_dh1024dsa(void);
+#endif
+
+static BIO *bio_err=NULL;
+static BIO *bio_stdout=NULL;
+
+static char *cipher=NULL;
+static int verbose=0;
+static int debug=0;
+#if 0
+/* Not used yet. */
+#ifdef FIONBIO
+static int s_nbio=0;
+#endif
+#endif
+
+static const char rnd_seed[] = "string to make the random number generator think it has entropy";
+
+int doit_biopair(SSL *s_ssl,SSL *c_ssl,long bytes,clock_t *s_time,clock_t *c_time);
+int doit(SSL *s_ssl,SSL *c_ssl,long bytes);
+static int do_test_cipherlist(void);
+static void sv_usage(void)
+	{
+	fprintf(stderr,"usage: ssltest [args ...]\n");
+	fprintf(stderr,"\n");
+#ifdef OPENSSL_FIPS
+	fprintf(stderr,"-F             - run test in FIPS mode\n");
+#endif
+	fprintf(stderr," -server_auth  - check server certificate\n");
+	fprintf(stderr," -client_auth  - do client authentication\n");
+	fprintf(stderr," -proxy        - allow proxy certificates\n");
+	fprintf(stderr," -proxy_auth <val> - set proxy policy rights\n");
+	fprintf(stderr," -proxy_cond <val> - experssion to test proxy policy rights\n");
+	fprintf(stderr," -v            - more output\n");
+	fprintf(stderr," -d            - debug output\n");
+	fprintf(stderr," -reuse        - use session-id reuse\n");
+	fprintf(stderr," -num <val>    - number of connections to perform\n");
+	fprintf(stderr," -bytes <val>  - number of bytes to swap between client/server\n");
+#ifndef OPENSSL_NO_DH
+	fprintf(stderr," -dhe1024      - use 1024 bit key (safe prime) for DHE\n");
+	fprintf(stderr," -dhe1024dsa   - use 1024 bit key (with 160-bit subprime) for DHE\n");
+	fprintf(stderr," -no_dhe       - disable DHE\n");
+#endif
+#ifndef OPENSSL_NO_ECDH
+	fprintf(stderr," -no_ecdhe     - disable ECDHE\n");
+#endif
+#ifndef OPENSSL_NO_SSL2
+	fprintf(stderr," -ssl2         - use SSLv2\n");
+#endif
+#ifndef OPENSSL_NO_SSL3
+	fprintf(stderr," -ssl3         - use SSLv3\n");
+#endif
+#ifndef OPENSSL_NO_TLS1
+	fprintf(stderr," -tls1         - use TLSv1\n");
+#endif
+	fprintf(stderr," -CApath arg   - PEM format directory of CA's\n");
+	fprintf(stderr," -CAfile arg   - PEM format file of CA's\n");
+	fprintf(stderr," -cert arg     - Server certificate file\n");
+	fprintf(stderr," -key arg      - Server key file (default: same as -cert)\n");
+	fprintf(stderr," -c_cert arg   - Client certificate file\n");
+	fprintf(stderr," -c_key arg    - Client key file (default: same as -c_cert)\n");
+	fprintf(stderr," -cipher arg   - The cipher list\n");
+	fprintf(stderr," -bio_pair     - Use BIO pairs\n");
+	fprintf(stderr," -f            - Test even cases that can't work\n");
+	fprintf(stderr," -time         - measure processor time used by client and server\n");
+	fprintf(stderr," -zlib         - use zlib compression\n");
+	fprintf(stderr," -rle          - use rle compression\n");
+#ifndef OPENSSL_NO_ECDH
+	fprintf(stderr," -named_curve arg  - Elliptic curve name to use for ephemeral ECDH keys.\n" \
+	               "                 Use \"openssl ecparam -list_curves\" for all names\n"  \
+	               "                 (default is sect163r2).\n");
+#endif
+	fprintf(stderr," -test_cipherlist - verifies the order of the ssl cipher lists\n");
+	}
+
+static void print_details(SSL *c_ssl, const char *prefix)
+	{
+	SSL_CIPHER *ciph;
+	X509 *cert;
+		
+	ciph=SSL_get_current_cipher(c_ssl);
+	BIO_printf(bio_stdout,"%s%s, cipher %s %s",
+		prefix,
+		SSL_get_version(c_ssl),
+		SSL_CIPHER_get_version(ciph),
+		SSL_CIPHER_get_name(ciph));
+	cert=SSL_get_peer_certificate(c_ssl);
+	if (cert != NULL)
+		{
+		EVP_PKEY *pkey = X509_get_pubkey(cert);
+		if (pkey != NULL)
+			{
+			if (0) 
+				;
+#ifndef OPENSSL_NO_RSA
+			else if (pkey->type == EVP_PKEY_RSA && pkey->pkey.rsa != NULL
+				&& pkey->pkey.rsa->n != NULL)
+				{
+				BIO_printf(bio_stdout, ", %d bit RSA",
+					BN_num_bits(pkey->pkey.rsa->n));
+				}
+#endif
+#ifndef OPENSSL_NO_DSA
+			else if (pkey->type == EVP_PKEY_DSA && pkey->pkey.dsa != NULL
+				&& pkey->pkey.dsa->p != NULL)
+				{
+				BIO_printf(bio_stdout, ", %d bit DSA",
+					BN_num_bits(pkey->pkey.dsa->p));
+				}
+#endif
+			EVP_PKEY_free(pkey);
+			}
+		X509_free(cert);
+		}
+	/* The SSL API does not allow us to look at temporary RSA/DH keys,
+	 * otherwise we should print their lengths too */
+	BIO_printf(bio_stdout,"\n");
+	}
+
+static void lock_dbg_cb(int mode, int type, const char *file, int line)
+	{
+	static int modes[CRYPTO_NUM_LOCKS]; /* = {0, 0, ... } */
+	const char *errstr = NULL;
+	int rw;
+	
+	rw = mode & (CRYPTO_READ|CRYPTO_WRITE);
+	if (!((rw == CRYPTO_READ) || (rw == CRYPTO_WRITE)))
+		{
+		errstr = "invalid mode";
+		goto err;
+		}
+
+	if (type < 0 || type >= CRYPTO_NUM_LOCKS)
+		{
+		errstr = "type out of bounds";
+		goto err;
+		}
+
+	if (mode & CRYPTO_LOCK)
+		{
+		if (modes[type])
+			{
+			errstr = "already locked";
+			/* must not happen in a single-threaded program
+			 * (would deadlock) */
+			goto err;
+			}
+
+		modes[type] = rw;
+		}
+	else if (mode & CRYPTO_UNLOCK)
+		{
+		if (!modes[type])
+			{
+			errstr = "not locked";
+			goto err;
+			}
+		
+		if (modes[type] != rw)
+			{
+			errstr = (rw == CRYPTO_READ) ?
+				"CRYPTO_r_unlock on write lock" :
+				"CRYPTO_w_unlock on read lock";
+			}
+
+		modes[type] = 0;
+		}
+	else
+		{
+		errstr = "invalid mode";
+		goto err;
+		}
+
+ err:
+	if (errstr)
+		{
+		/* we cannot use bio_err here */
+		fprintf(stderr, "openssl (lock_dbg_cb): %s (mode=%d, type=%d) at %s:%d\n",
+			errstr, mode, type, file, line);
+		}
+	}
+
+
+int main(int argc, char *argv[])
+	{
+	char *CApath=NULL,*CAfile=NULL;
+	int badop=0;
+	int bio_pair=0;
+	int force=0;
+	int tls1=0,ssl2=0,ssl3=0,ret=1;
+	int client_auth=0;
+	int server_auth=0,i;
+	struct app_verify_arg app_verify_arg =
+		{ APP_CALLBACK_STRING, 0, 0, NULL, NULL };
+	char *server_cert=TEST_SERVER_CERT;
+	char *server_key=NULL;
+	char *client_cert=TEST_CLIENT_CERT;
+	char *client_key=NULL;
+#ifndef OPENSSL_NO_ECDH
+	char *named_curve = NULL;
+#endif
+	SSL_CTX *s_ctx=NULL;
+	SSL_CTX *c_ctx=NULL;
+	SSL_METHOD *meth=NULL;
+	SSL *c_ssl,*s_ssl;
+	int number=1,reuse=0;
+	long bytes=256L;
+#ifndef OPENSSL_NO_DH
+	DH *dh;
+	int dhe1024 = 1, dhe1024dsa = 0;
+#endif
+#ifndef OPENSSL_NO_ECDH
+	EC_KEY *ecdh = NULL;
+#endif
+	int no_dhe = 0;
+	int no_ecdhe = 0;
+	int print_time = 0;
+	clock_t s_time = 0, c_time = 0;
+	int comp = 0;
+#ifndef OPENSSL_NO_COMP
+	COMP_METHOD *cm = NULL;
+#endif
+	STACK_OF(SSL_COMP) *ssl_comp_methods = NULL;
+	int test_cipherlist = 0;
+#ifdef OPENSSL_FIPS
+	int fips_mode=0;
+#endif
+
+	verbose = 0;
+	debug = 0;
+	cipher = 0;
+
+	bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);	
+
+	CRYPTO_set_locking_callback(lock_dbg_cb);
+
+	/* enable memory leak checking unless explicitly disabled */
+	if (!((getenv("OPENSSL_DEBUG_MEMORY") != NULL) && (0 == strcmp(getenv("OPENSSL_DEBUG_MEMORY"), "off"))))
+		{
+		CRYPTO_malloc_debug_init();
+		CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
+		}
+	else
+		{
+		/* OPENSSL_DEBUG_MEMORY=off */
+		CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0);
+		}
+	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
+
+	RAND_seed(rnd_seed, sizeof rnd_seed);
+
+	bio_stdout=BIO_new_fp(stdout,BIO_NOCLOSE);
+
+	argc--;
+	argv++;
+
+	while (argc >= 1)
+		{
+		if(!strcmp(*argv,"-F"))
+			{
+#ifdef OPENSSL_FIPS
+			fips_mode=1;
+#else
+			fprintf(stderr,"not compiled with FIPS support, so exitting without running.\n");
+			EXIT(0);
+#endif
+			}
+		else if	(strcmp(*argv,"-server_auth") == 0)
+			server_auth=1;
+		else if	(strcmp(*argv,"-client_auth") == 0)
+			client_auth=1;
+		else if (strcmp(*argv,"-proxy_auth") == 0)
+			{
+			if (--argc < 1) goto bad;
+			app_verify_arg.proxy_auth= *(++argv);
+			}
+		else if (strcmp(*argv,"-proxy_cond") == 0)
+			{
+			if (--argc < 1) goto bad;
+			app_verify_arg.proxy_cond= *(++argv);
+			}
+		else if	(strcmp(*argv,"-v") == 0)
+			verbose=1;
+		else if	(strcmp(*argv,"-d") == 0)
+			debug=1;
+		else if	(strcmp(*argv,"-reuse") == 0)
+			reuse=1;
+		else if	(strcmp(*argv,"-dhe1024") == 0)
+			{
+#ifndef OPENSSL_NO_DH
+			dhe1024=1;
+#else
+			fprintf(stderr,"ignoring -dhe1024, since I'm compiled without DH\n");
+#endif
+			}
+		else if	(strcmp(*argv,"-dhe1024dsa") == 0)
+			{
+#ifndef OPENSSL_NO_DH
+			dhe1024dsa=1;
+#else
+			fprintf(stderr,"ignoring -dhe1024, since I'm compiled without DH\n");
+#endif
+			}
+		else if	(strcmp(*argv,"-no_dhe") == 0)
+			no_dhe=1;
+		else if	(strcmp(*argv,"-no_ecdhe") == 0)
+			no_ecdhe=1;
+		else if	(strcmp(*argv,"-ssl2") == 0)
+			ssl2=1;
+		else if	(strcmp(*argv,"-tls1") == 0)
+			tls1=1;
+		else if	(strcmp(*argv,"-ssl3") == 0)
+			ssl3=1;
+		else if	(strncmp(*argv,"-num",4) == 0)
+			{
+			if (--argc < 1) goto bad;
+			number= atoi(*(++argv));
+			if (number == 0) number=1;
+			}
+		else if	(strcmp(*argv,"-bytes") == 0)
+			{
+			if (--argc < 1) goto bad;
+			bytes= atol(*(++argv));
+			if (bytes == 0L) bytes=1L;
+			i=strlen(argv[0]);
+			if (argv[0][i-1] == 'k') bytes*=1024L;
+			if (argv[0][i-1] == 'm') bytes*=1024L*1024L;
+			}
+		else if	(strcmp(*argv,"-cert") == 0)
+			{
+			if (--argc < 1) goto bad;
+			server_cert= *(++argv);
+			}
+		else if	(strcmp(*argv,"-s_cert") == 0)
+			{
+			if (--argc < 1) goto bad;
+			server_cert= *(++argv);
+			}
+		else if	(strcmp(*argv,"-key") == 0)
+			{
+			if (--argc < 1) goto bad;
+			server_key= *(++argv);
+			}
+		else if	(strcmp(*argv,"-s_key") == 0)
+			{
+			if (--argc < 1) goto bad;
+			server_key= *(++argv);
+			}
+		else if	(strcmp(*argv,"-c_cert") == 0)
+			{
+			if (--argc < 1) goto bad;
+			client_cert= *(++argv);
+			}
+		else if	(strcmp(*argv,"-c_key") == 0)
+			{
+			if (--argc < 1) goto bad;
+			client_key= *(++argv);
+			}
+		else if	(strcmp(*argv,"-cipher") == 0)
+			{
+			if (--argc < 1) goto bad;
+			cipher= *(++argv);
+			}
+		else if	(strcmp(*argv,"-CApath") == 0)
+			{
+			if (--argc < 1) goto bad;
+			CApath= *(++argv);
+			}
+		else if	(strcmp(*argv,"-CAfile") == 0)
+			{
+			if (--argc < 1) goto bad;
+			CAfile= *(++argv);
+			}
+		else if	(strcmp(*argv,"-bio_pair") == 0)
+			{
+			bio_pair = 1;
+			}
+		else if	(strcmp(*argv,"-f") == 0)
+			{
+			force = 1;
+			}
+		else if	(strcmp(*argv,"-time") == 0)
+			{
+			print_time = 1;
+			}
+		else if	(strcmp(*argv,"-zlib") == 0)
+			{
+			comp = COMP_ZLIB;
+			}
+		else if	(strcmp(*argv,"-rle") == 0)
+			{
+			comp = COMP_RLE;
+			}
+		else if	(strcmp(*argv,"-named_curve") == 0)
+			{
+			if (--argc < 1) goto bad;
+#ifndef OPENSSL_NO_ECDH		
+			named_curve = *(++argv);
+#else
+			fprintf(stderr,"ignoring -named_curve, since I'm compiled without ECDH\n");
+			++argv;
+#endif
+			}
+		else if	(strcmp(*argv,"-app_verify") == 0)
+			{
+			app_verify_arg.app_verify = 1;
+			}
+		else if	(strcmp(*argv,"-proxy") == 0)
+			{
+			app_verify_arg.allow_proxy_certs = 1;
+			}
+		else if (strcmp(*argv,"-test_cipherlist") == 0)
+			{
+			test_cipherlist = 1;
+			}
+		else
+			{
+			fprintf(stderr,"unknown option %s\n",*argv);
+			badop=1;
+			break;
+			}
+		argc--;
+		argv++;
+		}
+	if (badop)
+		{
+bad:
+		sv_usage();
+		goto end;
+		}
+
+	if (test_cipherlist == 1)
+		{
+		/* ensure that the cipher list are correctly sorted and exit */
+		if (do_test_cipherlist() == 0)
+			EXIT(1);
+		ret = 0;
+		goto end;
+		}
+
+	if (!ssl2 && !ssl3 && !tls1 && number > 1 && !reuse && !force)
+		{
+		fprintf(stderr, "This case cannot work.  Use -f to perform "
+			"the test anyway (and\n-d to see what happens), "
+			"or add one of -ssl2, -ssl3, -tls1, -reuse\n"
+			"to avoid protocol mismatch.\n");
+		EXIT(1);
+		}
+
+#ifdef OPENSSL_FIPS
+	if(fips_mode)
+		{
+		if(!FIPS_mode_set(1))
+			{
+			ERR_load_crypto_strings();
+			ERR_print_errors(BIO_new_fp(stderr,BIO_NOCLOSE));
+			EXIT(1);
+			}
+		else
+			fprintf(stderr,"*** IN FIPS MODE ***\n");
+		}
+#endif
+
+	if (print_time)
+		{
+		if (!bio_pair)
+			{
+			fprintf(stderr, "Using BIO pair (-bio_pair)\n");
+			bio_pair = 1;
+			}
+		if (number < 50 && !force)
+			fprintf(stderr, "Warning: For accurate timings, use more connections (e.g. -num 1000)\n");
+		}
+
+/*	if (cipher == NULL) cipher=getenv("SSL_CIPHER"); */
+
+	SSL_library_init();
+	SSL_load_error_strings();
+
+#ifndef OPENSSL_NO_COMP
+	if (comp == COMP_ZLIB) cm = COMP_zlib();
+	if (comp == COMP_RLE) cm = COMP_rle();
+	if (cm != NULL)
+		{
+		if (cm->type != NID_undef)
+			{
+			if (SSL_COMP_add_compression_method(comp, cm) != 0)
+				{
+				fprintf(stderr,
+					"Failed to add compression method\n");
+				ERR_print_errors_fp(stderr);
+				}
+			}
+		else
+			{
+			fprintf(stderr,
+				"Warning: %s compression not supported\n",
+				(comp == COMP_RLE ? "rle" :
+					(comp == COMP_ZLIB ? "zlib" :
+						"unknown")));
+			ERR_print_errors_fp(stderr);
+			}
+		}
+	ssl_comp_methods = SSL_COMP_get_compression_methods();
+	fprintf(stderr, "Available compression methods:\n");
+	{
+	int j, n = sk_SSL_COMP_num(ssl_comp_methods);
+	if (n == 0)
+		fprintf(stderr, "  NONE\n");
+	else
+		for (j = 0; j < n; j++)
+			{
+			SSL_COMP *c = sk_SSL_COMP_value(ssl_comp_methods, j);
+			fprintf(stderr, "  %d: %s\n", c->id, c->name);
+			}
+	}
+#endif
+
+#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
+	if (ssl2)
+		meth=SSLv2_method();
+	else 
+	if (tls1)
+		meth=TLSv1_method();
+	else
+	if (ssl3)
+		meth=SSLv3_method();
+	else
+		meth=SSLv23_method();
+#else
+#ifdef OPENSSL_NO_SSL2
+	meth=SSLv3_method();
+#else
+	meth=SSLv2_method();
+#endif
+#endif
+
+	c_ctx=SSL_CTX_new(meth);
+	s_ctx=SSL_CTX_new(meth);
+	if ((c_ctx == NULL) || (s_ctx == NULL))
+		{
+		ERR_print_errors(bio_err);
+		goto end;
+		}
+
+	if (cipher != NULL)
+		{
+		SSL_CTX_set_cipher_list(c_ctx,cipher);
+		SSL_CTX_set_cipher_list(s_ctx,cipher);
+		}
+
+#ifndef OPENSSL_NO_DH
+	if (!no_dhe)
+		{
+		if (dhe1024dsa)
+			{
+			/* use SSL_OP_SINGLE_DH_USE to avoid small subgroup attacks */
+			SSL_CTX_set_options(s_ctx, SSL_OP_SINGLE_DH_USE);
+			dh=get_dh1024dsa();
+			}
+		else if (dhe1024)
+			dh=get_dh1024();
+		else
+			dh=get_dh512();
+		SSL_CTX_set_tmp_dh(s_ctx,dh);
+		DH_free(dh);
+		}
+#else
+	(void)no_dhe;
+#endif
+
+#ifndef OPENSSL_NO_ECDH
+	if (!no_ecdhe)
+		{
+		int nid;
+
+		if (named_curve != NULL)
+			{
+			nid = OBJ_sn2nid(named_curve);
+			if (nid == 0)
+			{
+				BIO_printf(bio_err, "unknown curve name (%s)\n", named_curve);
+				goto end;
+				}
+			}
+		else
+			nid = NID_sect163r2;
+
+		ecdh = EC_KEY_new_by_curve_name(nid);
+		if (ecdh == NULL)
+			{
+			BIO_printf(bio_err, "unable to create curve\n");
+			goto end;
+			}
+
+		SSL_CTX_set_tmp_ecdh(s_ctx, ecdh);
+		SSL_CTX_set_options(s_ctx, SSL_OP_SINGLE_ECDH_USE);
+		EC_KEY_free(ecdh);
+		}
+#else
+	(void)no_ecdhe;
+#endif
+
+#ifndef OPENSSL_NO_RSA
+	SSL_CTX_set_tmp_rsa_callback(s_ctx,tmp_rsa_cb);
+#endif
+
+	if (!SSL_CTX_use_certificate_file(s_ctx,server_cert,SSL_FILETYPE_PEM))
+		{
+		ERR_print_errors(bio_err);
+		}
+	else if (!SSL_CTX_use_PrivateKey_file(s_ctx,
+		(server_key?server_key:server_cert), SSL_FILETYPE_PEM))
+		{
+		ERR_print_errors(bio_err);
+		goto end;
+		}
+
+	if (client_auth)
+		{
+		SSL_CTX_use_certificate_file(c_ctx,client_cert,
+			SSL_FILETYPE_PEM);
+		SSL_CTX_use_PrivateKey_file(c_ctx,
+			(client_key?client_key:client_cert),
+			SSL_FILETYPE_PEM);
+		}
+
+	if (	(!SSL_CTX_load_verify_locations(s_ctx,CAfile,CApath)) ||
+		(!SSL_CTX_set_default_verify_paths(s_ctx)) ||
+		(!SSL_CTX_load_verify_locations(c_ctx,CAfile,CApath)) ||
+		(!SSL_CTX_set_default_verify_paths(c_ctx)))
+		{
+		/* fprintf(stderr,"SSL_load_verify_locations\n"); */
+		ERR_print_errors(bio_err);
+		/* goto end; */
+		}
+
+	if (client_auth)
+		{
+		BIO_printf(bio_err,"client authentication\n");
+		SSL_CTX_set_verify(s_ctx,
+			SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
+			verify_callback);
+		SSL_CTX_set_cert_verify_callback(s_ctx, app_verify_callback, &app_verify_arg);
+		}
+	if (server_auth)
+		{
+		BIO_printf(bio_err,"server authentication\n");
+		SSL_CTX_set_verify(c_ctx,SSL_VERIFY_PEER,
+			verify_callback);
+		SSL_CTX_set_cert_verify_callback(c_ctx, app_verify_callback, &app_verify_arg);
+		}
+	
+	{
+		int session_id_context = 0;
+		SSL_CTX_set_session_id_context(s_ctx, (void *)&session_id_context, sizeof session_id_context);
+	}
+
+	c_ssl=SSL_new(c_ctx);
+	s_ssl=SSL_new(s_ctx);
+
+#ifndef OPENSSL_NO_KRB5
+	if (c_ssl  &&  c_ssl->kssl_ctx)
+                {
+                char	localhost[MAXHOSTNAMELEN+2];
+
+		if (gethostname(localhost, sizeof localhost-1) == 0)
+                        {
+			localhost[sizeof localhost-1]='\0';
+			if(strlen(localhost) == sizeof localhost-1)
+				{
+				BIO_printf(bio_err,"localhost name too long\n");
+				goto end;
+				}
+			kssl_ctx_setstring(c_ssl->kssl_ctx, KSSL_SERVER,
+                                localhost);
+			}
+		}
+#endif    /* OPENSSL_NO_KRB5  */
+
+	for (i=0; i<number; i++)
+		{
+		if (!reuse) SSL_set_session(c_ssl,NULL);
+		if (bio_pair)
+			ret=doit_biopair(s_ssl,c_ssl,bytes,&s_time,&c_time);
+		else
+			ret=doit(s_ssl,c_ssl,bytes);
+		}
+
+	if (!verbose)
+		{
+		print_details(c_ssl, "");
+		}
+	if ((number > 1) || (bytes > 1L))
+		BIO_printf(bio_stdout, "%d handshakes of %ld bytes done\n",number,bytes);
+	if (print_time)
+		{
+#ifdef CLOCKS_PER_SEC
+		/* "To determine the time in seconds, the value returned
+		 * by the clock function should be divided by the value
+		 * of the macro CLOCKS_PER_SEC."
+		 *                                       -- ISO/IEC 9899 */
+		BIO_printf(bio_stdout, "Approximate total server time: %6.2f s\n"
+			"Approximate total client time: %6.2f s\n",
+			(double)s_time/CLOCKS_PER_SEC,
+			(double)c_time/CLOCKS_PER_SEC);
+#else
+		/* "`CLOCKS_PER_SEC' undeclared (first use this function)"
+		 *                            -- cc on NeXTstep/OpenStep */
+		BIO_printf(bio_stdout,
+			"Approximate total server time: %6.2f units\n"
+			"Approximate total client time: %6.2f units\n",
+			(double)s_time,
+			(double)c_time);
+#endif
+		}
+
+	SSL_free(s_ssl);
+	SSL_free(c_ssl);
+
+end:
+	if (s_ctx != NULL) SSL_CTX_free(s_ctx);
+	if (c_ctx != NULL) SSL_CTX_free(c_ctx);
+
+	if (bio_stdout != NULL) BIO_free(bio_stdout);
+
+#ifndef OPENSSL_NO_RSA
+	free_tmp_rsa();
+#endif
+#ifndef OPENSSL_NO_ENGINE
+	ENGINE_cleanup();
+#endif
+	CRYPTO_cleanup_all_ex_data();
+	ERR_free_strings();
+	ERR_remove_state(0);
+	EVP_cleanup();
+	CRYPTO_mem_leaks(bio_err);
+	if (bio_err != NULL) BIO_free(bio_err);
+	EXIT(ret);
+	return ret;
+	}
+
+int doit_biopair(SSL *s_ssl, SSL *c_ssl, long count,
+	clock_t *s_time, clock_t *c_time)
+	{
+	long cw_num = count, cr_num = count, sw_num = count, sr_num = count;
+	BIO *s_ssl_bio = NULL, *c_ssl_bio = NULL;
+	BIO *server = NULL, *server_io = NULL, *client = NULL, *client_io = NULL;
+	int ret = 1;
+	
+	size_t bufsiz = 256; /* small buffer for testing */
+
+	if (!BIO_new_bio_pair(&server, bufsiz, &server_io, bufsiz))
+		goto err;
+	if (!BIO_new_bio_pair(&client, bufsiz, &client_io, bufsiz))
+		goto err;
+	
+	s_ssl_bio = BIO_new(BIO_f_ssl());
+	if (!s_ssl_bio)
+		goto err;
+
+	c_ssl_bio = BIO_new(BIO_f_ssl());
+	if (!c_ssl_bio)
+		goto err;
+
+	SSL_set_connect_state(c_ssl);
+	SSL_set_bio(c_ssl, client, client);
+	(void)BIO_set_ssl(c_ssl_bio, c_ssl, BIO_NOCLOSE);
+
+	SSL_set_accept_state(s_ssl);
+	SSL_set_bio(s_ssl, server, server);
+	(void)BIO_set_ssl(s_ssl_bio, s_ssl, BIO_NOCLOSE);
+
+	do
+		{
+		/* c_ssl_bio:          SSL filter BIO
+		 *
+		 * client:             pseudo-I/O for SSL library
+		 *
+		 * client_io:          client's SSL communication; usually to be
+		 *                     relayed over some I/O facility, but in this
+		 *                     test program, we're the server, too:
+		 *
+		 * server_io:          server's SSL communication
+		 *
+		 * server:             pseudo-I/O for SSL library
+		 *
+		 * s_ssl_bio:          SSL filter BIO
+		 *
+		 * The client and the server each employ a "BIO pair":
+		 * client + client_io, server + server_io.
+		 * BIO pairs are symmetric.  A BIO pair behaves similar
+		 * to a non-blocking socketpair (but both endpoints must
+		 * be handled by the same thread).
+		 * [Here we could connect client and server to the ends
+		 * of a single BIO pair, but then this code would be less
+		 * suitable as an example for BIO pairs in general.]
+		 *
+		 * Useful functions for querying the state of BIO pair endpoints:
+		 *
+		 * BIO_ctrl_pending(bio)              number of bytes we can read now
+		 * BIO_ctrl_get_read_request(bio)     number of bytes needed to fulfil
+		 *                                      other side's read attempt
+		 * BIO_ctrl_get_write_guarantee(bio)   number of bytes we can write now
+		 *
+		 * ..._read_request is never more than ..._write_guarantee;
+		 * it depends on the application which one you should use.
+		 */
+
+		/* We have non-blocking behaviour throughout this test program, but
+		 * can be sure that there is *some* progress in each iteration; so
+		 * we don't have to worry about ..._SHOULD_READ or ..._SHOULD_WRITE
+		 * -- we just try everything in each iteration
+		 */
+
+			{
+			/* CLIENT */
+		
+			MS_STATIC char cbuf[1024*8];
+			int i, r;
+			clock_t c_clock = clock();
+
+			memset(cbuf, 0, sizeof(cbuf));
+
+			if (debug)
+				if (SSL_in_init(c_ssl))
+					printf("client waiting in SSL_connect - %s\n",
+						SSL_state_string_long(c_ssl));
+
+			if (cw_num > 0)
+				{
+				/* Write to server. */
+				
+				if (cw_num > (long)sizeof cbuf)
+					i = sizeof cbuf;
+				else
+					i = (int)cw_num;
+				r = BIO_write(c_ssl_bio, cbuf, i);
+				if (r < 0)
+					{
+					if (!BIO_should_retry(c_ssl_bio))
+						{
+						fprintf(stderr,"ERROR in CLIENT\n");
+						goto err;
+						}
+					/* BIO_should_retry(...) can just be ignored here.
+					 * The library expects us to call BIO_write with
+					 * the same arguments again, and that's what we will
+					 * do in the next iteration. */
+					}
+				else if (r == 0)
+					{
+					fprintf(stderr,"SSL CLIENT STARTUP FAILED\n");
+					goto err;
+					}
+				else
+					{
+					if (debug)
+						printf("client wrote %d\n", r);
+					cw_num -= r;				
+					}
+				}
+
+			if (cr_num > 0)
+				{
+				/* Read from server. */
+
+				r = BIO_read(c_ssl_bio, cbuf, sizeof(cbuf));
+				if (r < 0)
+					{
+					if (!BIO_should_retry(c_ssl_bio))
+						{
+						fprintf(stderr,"ERROR in CLIENT\n");
+						goto err;
+						}
+					/* Again, "BIO_should_retry" can be ignored. */
+					}
+				else if (r == 0)
+					{
+					fprintf(stderr,"SSL CLIENT STARTUP FAILED\n");
+					goto err;
+					}
+				else
+					{
+					if (debug)
+						printf("client read %d\n", r);
+					cr_num -= r;
+					}
+				}
+
+			/* c_time and s_time increments will typically be very small
+			 * (depending on machine speed and clock tick intervals),
+			 * but sampling over a large number of connections should
+			 * result in fairly accurate figures.  We cannot guarantee
+			 * a lot, however -- if each connection lasts for exactly
+			 * one clock tick, it will be counted only for the client
+			 * or only for the server or even not at all.
+			 */
+			*c_time += (clock() - c_clock);
+			}
+
+			{
+			/* SERVER */
+		
+			MS_STATIC char sbuf[1024*8];
+			int i, r;
+			clock_t s_clock = clock();
+
+			memset(sbuf, 0, sizeof(sbuf));
+
+			if (debug)
+				if (SSL_in_init(s_ssl))
+					printf("server waiting in SSL_accept - %s\n",
+						SSL_state_string_long(s_ssl));
+
+			if (sw_num > 0)
+				{
+				/* Write to client. */
+				
+				if (sw_num > (long)sizeof sbuf)
+					i = sizeof sbuf;
+				else
+					i = (int)sw_num;
+				r = BIO_write(s_ssl_bio, sbuf, i);
+				if (r < 0)
+					{
+					if (!BIO_should_retry(s_ssl_bio))
+						{
+						fprintf(stderr,"ERROR in SERVER\n");
+						goto err;
+						}
+					/* Ignore "BIO_should_retry". */
+					}
+				else if (r == 0)
+					{
+					fprintf(stderr,"SSL SERVER STARTUP FAILED\n");
+					goto err;
+					}
+				else
+					{
+					if (debug)
+						printf("server wrote %d\n", r);
+					sw_num -= r;				
+					}
+				}
+
+			if (sr_num > 0)
+				{
+				/* Read from client. */
+
+				r = BIO_read(s_ssl_bio, sbuf, sizeof(sbuf));
+				if (r < 0)
+					{
+					if (!BIO_should_retry(s_ssl_bio))
+						{
+						fprintf(stderr,"ERROR in SERVER\n");
+						goto err;
+						}
+					/* blah, blah */
+					}
+				else if (r == 0)
+					{
+					fprintf(stderr,"SSL SERVER STARTUP FAILED\n");
+					goto err;
+					}
+				else
+					{
+					if (debug)
+						printf("server read %d\n", r);
+					sr_num -= r;
+					}
+				}
+
+			*s_time += (clock() - s_clock);
+			}
+			
+			{
+			/* "I/O" BETWEEN CLIENT AND SERVER. */
+
+			size_t r1, r2;
+			BIO *io1 = server_io, *io2 = client_io;
+			/* we use the non-copying interface for io1
+			 * and the standard BIO_write/BIO_read interface for io2
+			 */
+			
+			static int prev_progress = 1;
+			int progress = 0;
+			
+			/* io1 to io2 */
+			do
+				{
+				size_t num;
+				int r;
+
+				r1 = BIO_ctrl_pending(io1);
+				r2 = BIO_ctrl_get_write_guarantee(io2);
+
+				num = r1;
+				if (r2 < num)
+					num = r2;
+				if (num)
+					{
+					char *dataptr;
+
+					if (INT_MAX < num) /* yeah, right */
+						num = INT_MAX;
+					
+					r = BIO_nread(io1, &dataptr, (int)num);
+					assert(r > 0);
+					assert(r <= (int)num);
+					/* possibly r < num (non-contiguous data) */
+					num = r;
+					r = BIO_write(io2, dataptr, (int)num);
+					if (r != (int)num) /* can't happen */
+						{
+						fprintf(stderr, "ERROR: BIO_write could not write "
+							"BIO_ctrl_get_write_guarantee() bytes");
+						goto err;
+						}
+					progress = 1;
+
+					if (debug)
+						printf((io1 == client_io) ?
+							"C->S relaying: %d bytes\n" :
+							"S->C relaying: %d bytes\n",
+							(int)num);
+					}
+				}
+			while (r1 && r2);
+
+			/* io2 to io1 */
+			{
+				size_t num;
+				int r;
+
+				r1 = BIO_ctrl_pending(io2);
+				r2 = BIO_ctrl_get_read_request(io1);
+				/* here we could use ..._get_write_guarantee instead of
+				 * ..._get_read_request, but by using the latter
+				 * we test restartability of the SSL implementation
+				 * more thoroughly */
+				num = r1;
+				if (r2 < num)
+					num = r2;
+				if (num)
+					{
+					char *dataptr;
+					
+					if (INT_MAX < num)
+						num = INT_MAX;
+
+					if (num > 1)
+						--num; /* test restartability even more thoroughly */
+					
+					r = BIO_nwrite0(io1, &dataptr);
+					assert(r > 0);
+					if (r < (int)num)
+						num = r;
+					r = BIO_read(io2, dataptr, (int)num);
+					if (r != (int)num) /* can't happen */
+						{
+						fprintf(stderr, "ERROR: BIO_read could not read "
+							"BIO_ctrl_pending() bytes");
+						goto err;
+						}
+					progress = 1;
+					r = BIO_nwrite(io1, &dataptr, (int)num);
+					if (r != (int)num) /* can't happen */
+						{
+						fprintf(stderr, "ERROR: BIO_nwrite() did not accept "
+							"BIO_nwrite0() bytes");
+						goto err;
+						}
+					
+					if (debug)
+						printf((io2 == client_io) ?
+							"C->S relaying: %d bytes\n" :
+							"S->C relaying: %d bytes\n",
+							(int)num);
+					}
+			} /* no loop, BIO_ctrl_get_read_request now returns 0 anyway */
+
+			if (!progress && !prev_progress)
+				if (cw_num > 0 || cr_num > 0 || sw_num > 0 || sr_num > 0)
+					{
+					fprintf(stderr, "ERROR: got stuck\n");
+					if (strcmp("SSLv2", SSL_get_version(c_ssl)) == 0)
+						{
+						fprintf(stderr, "This can happen for SSL2 because "
+							"CLIENT-FINISHED and SERVER-VERIFY are written \n"
+							"concurrently ...");
+						if (strncmp("2SCF", SSL_state_string(c_ssl), 4) == 0
+							&& strncmp("2SSV", SSL_state_string(s_ssl), 4) == 0)
+							{
+							fprintf(stderr, " ok.\n");
+							goto end;
+							}
+						}
+					fprintf(stderr, " ERROR.\n");
+					goto err;
+					}
+			prev_progress = progress;
+			}
+		}
+	while (cw_num > 0 || cr_num > 0 || sw_num > 0 || sr_num > 0);
+
+	if (verbose)
+		print_details(c_ssl, "DONE via BIO pair: ");
+end:
+	ret = 0;
+
+ err:
+	ERR_print_errors(bio_err);
+	
+	if (server)
+		BIO_free(server);
+	if (server_io)
+		BIO_free(server_io);
+	if (client)
+		BIO_free(client);
+	if (client_io)
+		BIO_free(client_io);
+	if (s_ssl_bio)
+		BIO_free(s_ssl_bio);
+	if (c_ssl_bio)
+		BIO_free(c_ssl_bio);
+
+	return ret;
+	}
+
+
+#define W_READ	1
+#define W_WRITE	2
+#define C_DONE	1
+#define S_DONE	2
+
+int doit(SSL *s_ssl, SSL *c_ssl, long count)
+	{
+	MS_STATIC char cbuf[1024*8],sbuf[1024*8];
+	long cw_num=count,cr_num=count;
+	long sw_num=count,sr_num=count;
+	int ret=1;
+	BIO *c_to_s=NULL;
+	BIO *s_to_c=NULL;
+	BIO *c_bio=NULL;
+	BIO *s_bio=NULL;
+	int c_r,c_w,s_r,s_w;
+	int c_want,s_want;
+	int i,j;
+	int done=0;
+	int c_write,s_write;
+	int do_server=0,do_client=0;
+
+	memset(cbuf,0,sizeof(cbuf));
+	memset(sbuf,0,sizeof(sbuf));
+
+	c_to_s=BIO_new(BIO_s_mem());
+	s_to_c=BIO_new(BIO_s_mem());
+	if ((s_to_c == NULL) || (c_to_s == NULL))
+		{
+		ERR_print_errors(bio_err);
+		goto err;
+		}
+
+	c_bio=BIO_new(BIO_f_ssl());
+	s_bio=BIO_new(BIO_f_ssl());
+	if ((c_bio == NULL) || (s_bio == NULL))
+		{
+		ERR_print_errors(bio_err);
+		goto err;
+		}
+
+	SSL_set_connect_state(c_ssl);
+	SSL_set_bio(c_ssl,s_to_c,c_to_s);
+	BIO_set_ssl(c_bio,c_ssl,BIO_NOCLOSE);
+
+	SSL_set_accept_state(s_ssl);
+	SSL_set_bio(s_ssl,c_to_s,s_to_c);
+	BIO_set_ssl(s_bio,s_ssl,BIO_NOCLOSE);
+
+	c_r=0; s_r=1;
+	c_w=1; s_w=0;
+	c_want=W_WRITE;
+	s_want=0;
+	c_write=1,s_write=0;
+
+	/* We can always do writes */
+	for (;;)
+		{
+		do_server=0;
+		do_client=0;
+
+		i=(int)BIO_pending(s_bio);
+		if ((i && s_r) || s_w) do_server=1;
+
+		i=(int)BIO_pending(c_bio);
+		if ((i && c_r) || c_w) do_client=1;
+
+		if (do_server && debug)
+			{
+			if (SSL_in_init(s_ssl))
+				printf("server waiting in SSL_accept - %s\n",
+					SSL_state_string_long(s_ssl));
+/*			else if (s_write)
+				printf("server:SSL_write()\n");
+			else
+				printf("server:SSL_read()\n"); */
+			}
+
+		if (do_client && debug)
+			{
+			if (SSL_in_init(c_ssl))
+				printf("client waiting in SSL_connect - %s\n",
+					SSL_state_string_long(c_ssl));
+/*			else if (c_write)
+				printf("client:SSL_write()\n");
+			else
+				printf("client:SSL_read()\n"); */
+			}
+
+		if (!do_client && !do_server)
+			{
+			fprintf(stdout,"ERROR IN STARTUP\n");
+			ERR_print_errors(bio_err);
+			break;
+			}
+		if (do_client && !(done & C_DONE))
+			{
+			if (c_write)
+				{
+				j = (cw_num > (long)sizeof(cbuf)) ?
+					(int)sizeof(cbuf) : (int)cw_num;
+				i=BIO_write(c_bio,cbuf,j);
+				if (i < 0)
+					{
+					c_r=0;
+					c_w=0;
+					if (BIO_should_retry(c_bio))
+						{
+						if (BIO_should_read(c_bio))
+							c_r=1;
+						if (BIO_should_write(c_bio))
+							c_w=1;
+						}
+					else
+						{
+						fprintf(stderr,"ERROR in CLIENT\n");
+						ERR_print_errors(bio_err);
+						goto err;
+						}
+					}
+				else if (i == 0)
+					{
+					fprintf(stderr,"SSL CLIENT STARTUP FAILED\n");
+					goto err;
+					}
+				else
+					{
+					if (debug)
+						printf("client wrote %d\n",i);
+					/* ok */
+					s_r=1;
+					c_write=0;
+					cw_num-=i;
+					}
+				}
+			else
+				{
+				i=BIO_read(c_bio,cbuf,sizeof(cbuf));
+				if (i < 0)
+					{
+					c_r=0;
+					c_w=0;
+					if (BIO_should_retry(c_bio))
+						{
+						if (BIO_should_read(c_bio))
+							c_r=1;
+						if (BIO_should_write(c_bio))
+							c_w=1;
+						}
+					else
+						{
+						fprintf(stderr,"ERROR in CLIENT\n");
+						ERR_print_errors(bio_err);
+						goto err;
+						}
+					}
+				else if (i == 0)
+					{
+					fprintf(stderr,"SSL CLIENT STARTUP FAILED\n");
+					goto err;
+					}
+				else
+					{
+					if (debug)
+						printf("client read %d\n",i);
+					cr_num-=i;
+					if (sw_num > 0)
+						{
+						s_write=1;
+						s_w=1;
+						}
+					if (cr_num <= 0)
+						{
+						s_write=1;
+						s_w=1;
+						done=S_DONE|C_DONE;
+						}
+					}
+				}
+			}
+
+		if (do_server && !(done & S_DONE))
+			{
+			if (!s_write)
+				{
+				i=BIO_read(s_bio,sbuf,sizeof(cbuf));
+				if (i < 0)
+					{
+					s_r=0;
+					s_w=0;
+					if (BIO_should_retry(s_bio))
+						{
+						if (BIO_should_read(s_bio))
+							s_r=1;
+						if (BIO_should_write(s_bio))
+							s_w=1;
+						}
+					else
+						{
+						fprintf(stderr,"ERROR in SERVER\n");
+						ERR_print_errors(bio_err);
+						goto err;
+						}
+					}
+				else if (i == 0)
+					{
+					ERR_print_errors(bio_err);
+					fprintf(stderr,"SSL SERVER STARTUP FAILED in SSL_read\n");
+					goto err;
+					}
+				else
+					{
+					if (debug)
+						printf("server read %d\n",i);
+					sr_num-=i;
+					if (cw_num > 0)
+						{
+						c_write=1;
+						c_w=1;
+						}
+					if (sr_num <= 0)
+						{
+						s_write=1;
+						s_w=1;
+						c_write=0;
+						}
+					}
+				}
+			else
+				{
+				j = (sw_num > (long)sizeof(sbuf)) ?
+					(int)sizeof(sbuf) : (int)sw_num;
+				i=BIO_write(s_bio,sbuf,j);
+				if (i < 0)
+					{
+					s_r=0;
+					s_w=0;
+					if (BIO_should_retry(s_bio))
+						{
+						if (BIO_should_read(s_bio))
+							s_r=1;
+						if (BIO_should_write(s_bio))
+							s_w=1;
+						}
+					else
+						{
+						fprintf(stderr,"ERROR in SERVER\n");
+						ERR_print_errors(bio_err);
+						goto err;
+						}
+					}
+				else if (i == 0)
+					{
+					ERR_print_errors(bio_err);
+					fprintf(stderr,"SSL SERVER STARTUP FAILED in SSL_write\n");
+					goto err;
+					}
+				else
+					{
+					if (debug)
+						printf("server wrote %d\n",i);
+					sw_num-=i;
+					s_write=0;
+					c_r=1;
+					if (sw_num <= 0)
+						done|=S_DONE;
+					}
+				}
+			}
+
+		if ((done & S_DONE) && (done & C_DONE)) break;
+		}
+
+	if (verbose)
+		print_details(c_ssl, "DONE: ");
+	ret=0;
+err:
+	/* We have to set the BIO's to NULL otherwise they will be
+	 * OPENSSL_free()ed twice.  Once when th s_ssl is SSL_free()ed and
+	 * again when c_ssl is SSL_free()ed.
+	 * This is a hack required because s_ssl and c_ssl are sharing the same
+	 * BIO structure and SSL_set_bio() and SSL_free() automatically
+	 * BIO_free non NULL entries.
+	 * You should not normally do this or be required to do this */
+	if (s_ssl != NULL)
+		{
+		s_ssl->rbio=NULL;
+		s_ssl->wbio=NULL;
+		}
+	if (c_ssl != NULL)
+		{
+		c_ssl->rbio=NULL;
+		c_ssl->wbio=NULL;
+		}
+
+	if (c_to_s != NULL) BIO_free(c_to_s);
+	if (s_to_c != NULL) BIO_free(s_to_c);
+	if (c_bio != NULL) BIO_free_all(c_bio);
+	if (s_bio != NULL) BIO_free_all(s_bio);
+	return(ret);
+	}
+
+static int get_proxy_auth_ex_data_idx(void)
+	{
+	static volatile int idx = -1;
+	if (idx < 0)
+		{
+		CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
+		if (idx < 0)
+			{
+			idx = X509_STORE_CTX_get_ex_new_index(0,
+				"SSLtest for verify callback", NULL,NULL,NULL);
+			}
+		CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
+		}
+	return idx;
+	}
+
+static int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx)
+	{
+	char *s,buf[256];
+
+	s=X509_NAME_oneline(X509_get_subject_name(ctx->current_cert),buf,
+			    sizeof buf);
+	if (s != NULL)
+		{
+		if (ok)
+			fprintf(stderr,"depth=%d %s\n",
+				ctx->error_depth,buf);
+		else
+			{
+			fprintf(stderr,"depth=%d error=%d %s\n",
+				ctx->error_depth,ctx->error,buf);
+			}
+		}
+
+	if (ok == 0)
+		{
+		fprintf(stderr,"Error string: %s\n",
+			X509_verify_cert_error_string(ctx->error));
+		switch (ctx->error)
+			{
+		case X509_V_ERR_CERT_NOT_YET_VALID:
+		case X509_V_ERR_CERT_HAS_EXPIRED:
+		case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
+			fprintf(stderr,"  ... ignored.\n");
+			ok=1;
+			}
+		}
+
+	if (ok == 1)
+		{
+		X509 *xs = ctx->current_cert;
+#if 0
+		X509 *xi = ctx->current_issuer;
+#endif
+
+		if (xs->ex_flags & EXFLAG_PROXY)
+			{
+			unsigned int *letters =
+				X509_STORE_CTX_get_ex_data(ctx,
+					get_proxy_auth_ex_data_idx());
+
+			if (letters)
+				{
+				int found_any = 0;
+				int i;
+				PROXY_CERT_INFO_EXTENSION *pci =
+					X509_get_ext_d2i(xs, NID_proxyCertInfo,
+						NULL, NULL);
+
+				switch (OBJ_obj2nid(pci->proxyPolicy->policyLanguage))
+					{
+				case NID_Independent:
+					/* Completely meaningless in this
+					   program, as there's no way to
+					   grant explicit rights to a
+					   specific PrC.  Basically, using
+					   id-ppl-Independent is the perfect
+					   way to grant no rights at all. */
+					fprintf(stderr, "  Independent proxy certificate");
+					for (i = 0; i < 26; i++)
+						letters[i] = 0;
+					break;
+				case NID_id_ppl_inheritAll:
+					/* This is basically a NOP, we
+					   simply let the current rights
+					   stand as they are. */
+					fprintf(stderr, "  Proxy certificate inherits all");
+					break;
+				default:
+					s = (char *)
+						pci->proxyPolicy->policy->data;
+					i = pci->proxyPolicy->policy->length;
+
+					/* The algorithm works as follows:
+					   it is assumed that previous
+					   iterations or the initial granted
+					   rights has already set some elements
+					   of `letters'.  What we need to do is
+					   to clear those that weren't granted
+					   by the current PrC as well.  The
+					   easiest way to do this is to add 1
+					   to all the elements whose letters
+					   are given with the current policy.
+					   That way, all elements that are set
+					   by the current policy and were
+					   already set by earlier policies and
+					   through the original grant of rights
+					   will get the value 2 or higher.
+					   The last thing to do is to sweep
+					   through `letters' and keep the
+					   elements having the value 2 as set,
+					   and clear all the others. */
+
+					fprintf(stderr, "  Certificate proxy rights = %*.*s", i, i, s);
+					while(i-- > 0)
+						{
+						int c = *s++;
+						if (isascii(c) && isalpha(c))
+							{
+							if (islower(c))
+								c = toupper(c);
+							letters[c - 'A']++;
+							}
+						}
+					for (i = 0; i < 26; i++)
+						if (letters[i] < 2)
+							letters[i] = 0;
+						else
+							letters[i] = 1;
+					}
+
+				found_any = 0;
+				fprintf(stderr,
+					", resulting proxy rights = ");
+				for(i = 0; i < 26; i++)
+					if (letters[i])
+						{
+						fprintf(stderr, "%c", i + 'A');
+						found_any = 1;
+						}
+				if (!found_any)
+					fprintf(stderr, "none");
+				fprintf(stderr, "\n");
+
+				PROXY_CERT_INFO_EXTENSION_free(pci);
+				}
+			}
+		}
+
+	return(ok);
+	}
+
+static void process_proxy_debug(int indent, const char *format, ...)
+	{
+	static const char indentation[] =
+		">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
+		">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"; /* That's 80 > */
+	char my_format[256];
+	va_list args;
+
+	BIO_snprintf(my_format, sizeof(my_format), "%*.*s %s",
+		indent, indent, indentation, format);
+
+	va_start(args, format);
+	vfprintf(stderr, my_format, args);
+	va_end(args);
+	}
+/* Priority levels:
+   0	[!]var, ()
+   1	& ^
+   2	|
+*/
+static int process_proxy_cond_adders(unsigned int letters[26],
+	const char *cond, const char **cond_end, int *pos, int indent);
+static int process_proxy_cond_val(unsigned int letters[26],
+	const char *cond, const char **cond_end, int *pos, int indent)
+	{
+	int c;
+	int ok = 1;
+	int negate = 0;
+
+	while(isspace((int)*cond))
+		{
+		cond++; (*pos)++;
+		}
+	c = *cond;
+
+	if (debug)
+		process_proxy_debug(indent,
+			"Start process_proxy_cond_val at position %d: %s\n",
+			*pos, cond);
+
+	while(c == '!')
+		{
+		negate = !negate;
+		cond++; (*pos)++;
+		while(isspace((int)*cond))
+			{
+			cond++; (*pos)++;
+			}
+		c = *cond;
+		}
+
+	if (c == '(')
+		{
+		cond++; (*pos)++;
+		ok = process_proxy_cond_adders(letters, cond, cond_end, pos,
+			indent + 1);
+		cond = *cond_end;
+		if (ok < 0)
+			goto end;
+		while(isspace((int)*cond))
+			{
+			cond++; (*pos)++;
+			}
+		c = *cond;
+		if (c != ')')
+			{
+			fprintf(stderr,
+				"Weird condition character in position %d: "
+				"%c\n", *pos, c);
+			ok = -1;
+			goto end;
+			}
+		cond++; (*pos)++;
+		}
+	else if (isascii(c) && isalpha(c))
+		{
+		if (islower(c))
+			c = toupper(c);
+		ok = letters[c - 'A'];
+		cond++; (*pos)++;
+		}
+	else
+		{
+		fprintf(stderr,
+			"Weird condition character in position %d: "
+			"%c\n", *pos, c);
+		ok = -1;
+		goto end;
+		}
+ end:
+	*cond_end = cond;
+	if (ok >= 0 && negate)
+		ok = !ok;
+
+	if (debug)
+		process_proxy_debug(indent,
+			"End process_proxy_cond_val at position %d: %s, returning %d\n",
+			*pos, cond, ok);
+
+	return ok;
+	}
+static int process_proxy_cond_multipliers(unsigned int letters[26],
+	const char *cond, const char **cond_end, int *pos, int indent)
+	{
+	int ok;
+	char c;
+
+	if (debug)
+		process_proxy_debug(indent,
+			"Start process_proxy_cond_multipliers at position %d: %s\n",
+			*pos, cond);
+
+	ok = process_proxy_cond_val(letters, cond, cond_end, pos, indent + 1);
+	cond = *cond_end;
+	if (ok < 0)
+		goto end;
+
+	while(ok >= 0)
+		{
+		while(isspace((int)*cond))
+			{
+			cond++; (*pos)++;
+			}
+		c = *cond;
+
+		switch(c)
+			{
+		case '&':
+		case '^':
+			{
+			int save_ok = ok;
+
+			cond++; (*pos)++;
+			ok = process_proxy_cond_val(letters,
+				cond, cond_end, pos, indent + 1);
+			cond = *cond_end;
+			if (ok < 0)
+				break;
+
+			switch(c)
+				{
+			case '&':
+				ok &= save_ok;
+				break;
+			case '^':
+				ok ^= save_ok;
+				break;
+			default:
+				fprintf(stderr, "SOMETHING IS SERIOUSLY WRONG!"
+					" STOPPING\n");
+				EXIT(1);
+				}
+			}
+			break;
+		default:
+			goto end;
+			}
+		}
+ end:
+	if (debug)
+		process_proxy_debug(indent,
+			"End process_proxy_cond_multipliers at position %d: %s, returning %d\n",
+			*pos, cond, ok);
+
+	*cond_end = cond;
+	return ok;
+	}
+static int process_proxy_cond_adders(unsigned int letters[26],
+	const char *cond, const char **cond_end, int *pos, int indent)
+	{
+	int ok;
+	char c;
+
+	if (debug)
+		process_proxy_debug(indent,
+			"Start process_proxy_cond_adders at position %d: %s\n",
+			*pos, cond);
+
+	ok = process_proxy_cond_multipliers(letters, cond, cond_end, pos,
+		indent + 1);
+	cond = *cond_end;
+	if (ok < 0)
+		goto end;
+
+	while(ok >= 0)
+		{
+		while(isspace((int)*cond))
+			{
+			cond++; (*pos)++;
+			}
+		c = *cond;
+
+		switch(c)
+			{
+		case '|':
+			{
+			int save_ok = ok;
+
+			cond++; (*pos)++;
+			ok = process_proxy_cond_multipliers(letters,
+				cond, cond_end, pos, indent + 1);
+			cond = *cond_end;
+			if (ok < 0)
+				break;
+
+			switch(c)
+				{
+			case '|':
+				ok |= save_ok;
+				break;
+			default:
+				fprintf(stderr, "SOMETHING IS SERIOUSLY WRONG!"
+					" STOPPING\n");
+				EXIT(1);
+				}
+			}
+			break;
+		default:
+			goto end;
+			}
+		}
+ end:
+	if (debug)
+		process_proxy_debug(indent,
+			"End process_proxy_cond_adders at position %d: %s, returning %d\n",
+			*pos, cond, ok);
+
+	*cond_end = cond;
+	return ok;
+	}
+
+static int process_proxy_cond(unsigned int letters[26],
+	const char *cond, const char **cond_end)
+	{
+	int pos = 1;
+	return process_proxy_cond_adders(letters, cond, cond_end, &pos, 1);
+	}
+
+static int MS_CALLBACK app_verify_callback(X509_STORE_CTX *ctx, void *arg)
+	{
+	int ok=1;
+	struct app_verify_arg *cb_arg = arg;
+	unsigned int letters[26]; /* only used with proxy_auth */
+
+	if (cb_arg->app_verify)
+		{
+		char *s = NULL,buf[256];
+
+		fprintf(stderr, "In app_verify_callback, allowing cert. ");
+		fprintf(stderr, "Arg is: %s\n", cb_arg->string);
+		fprintf(stderr, "Finished printing do we have a context? 0x%p a cert? 0x%p\n",
+			(void *)ctx, (void *)ctx->cert);
+		if (ctx->cert)
+			s=X509_NAME_oneline(X509_get_subject_name(ctx->cert),buf,256);
+		if (s != NULL)
+			{
+			fprintf(stderr,"cert depth=%d %s\n",ctx->error_depth,buf);
+			}
+		return(1);
+		}
+	if (cb_arg->proxy_auth)
+		{
+		int found_any = 0, i;
+		char *sp;
+
+		for(i = 0; i < 26; i++)
+			letters[i] = 0;
+		for(sp = cb_arg->proxy_auth; *sp; sp++)
+			{
+			int c = *sp;
+			if (isascii(c) && isalpha(c))
+				{
+				if (islower(c))
+					c = toupper(c);
+				letters[c - 'A'] = 1;
+				}
+			}
+
+		fprintf(stderr,
+			"  Initial proxy rights = ");
+		for(i = 0; i < 26; i++)
+			if (letters[i])
+				{
+				fprintf(stderr, "%c", i + 'A');
+				found_any = 1;
+				}
+		if (!found_any)
+			fprintf(stderr, "none");
+		fprintf(stderr, "\n");
+
+		X509_STORE_CTX_set_ex_data(ctx,
+			get_proxy_auth_ex_data_idx(),letters);
+		}
+	if (cb_arg->allow_proxy_certs)
+		{
+		X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_ALLOW_PROXY_CERTS);
+		}
+
+#ifndef OPENSSL_NO_X509_VERIFY
+	ok = X509_verify_cert(ctx);
+#endif
+
+	if (cb_arg->proxy_auth)
+		{
+		if (ok > 0)
+			{
+			const char *cond_end = NULL;
+
+			ok = process_proxy_cond(letters,
+				cb_arg->proxy_cond, &cond_end);
+
+			if (ok < 0)
+				EXIT(3);
+			if (*cond_end)
+				{
+				fprintf(stderr, "Stopped processing condition before it's end.\n");
+				ok = 0;
+				}
+			if (!ok)
+				fprintf(stderr, "Proxy rights check with condition '%s' proved invalid\n",
+					cb_arg->proxy_cond);
+			else
+				fprintf(stderr, "Proxy rights check with condition '%s' proved valid\n",
+					cb_arg->proxy_cond);
+			}
+		}
+	return(ok);
+	}
+
+#ifndef OPENSSL_NO_RSA
+static RSA *rsa_tmp=NULL;
+
+static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export, int keylength)
+	{
+	BIGNUM *bn = NULL;
+	if (rsa_tmp == NULL)
+		{
+		bn = BN_new();
+		rsa_tmp = RSA_new();
+		if(!bn || !rsa_tmp || !BN_set_word(bn, RSA_F4))
+			{
+			BIO_printf(bio_err, "Memory error...");
+			goto end;
+			}
+		BIO_printf(bio_err,"Generating temp (%d bit) RSA key...",keylength);
+		(void)BIO_flush(bio_err);
+		if(!RSA_generate_key_ex(rsa_tmp,keylength,bn,NULL))
+			{
+			BIO_printf(bio_err, "Error generating key.");
+			RSA_free(rsa_tmp);
+			rsa_tmp = NULL;
+			}
+end:
+		BIO_printf(bio_err,"\n");
+		(void)BIO_flush(bio_err);
+		}
+	if(bn) BN_free(bn);
+	return(rsa_tmp);
+	}
+
+static void free_tmp_rsa(void)
+	{
+	if (rsa_tmp != NULL)
+		{
+		RSA_free(rsa_tmp);
+		rsa_tmp = NULL;
+		}
+	}
+#endif
+
+#ifndef OPENSSL_NO_DH
+/* These DH parameters have been generated as follows:
+ *    $ openssl dhparam -C -noout 512
+ *    $ openssl dhparam -C -noout 1024
+ *    $ openssl dhparam -C -noout -dsaparam 1024
+ * (The third function has been renamed to avoid name conflicts.)
+ */
+static DH *get_dh512()
+	{
+	static unsigned char dh512_p[]={
+		0xCB,0xC8,0xE1,0x86,0xD0,0x1F,0x94,0x17,0xA6,0x99,0xF0,0xC6,
+		0x1F,0x0D,0xAC,0xB6,0x25,0x3E,0x06,0x39,0xCA,0x72,0x04,0xB0,
+		0x6E,0xDA,0xC0,0x61,0xE6,0x7A,0x77,0x25,0xE8,0x3B,0xB9,0x5F,
+		0x9A,0xB6,0xB5,0xFE,0x99,0x0B,0xA1,0x93,0x4E,0x35,0x33,0xB8,
+		0xE1,0xF1,0x13,0x4F,0x59,0x1A,0xD2,0x57,0xC0,0x26,0x21,0x33,
+		0x02,0xC5,0xAE,0x23,
+		};
+	static unsigned char dh512_g[]={
+		0x02,
+		};
+	DH *dh;
+
+	if ((dh=DH_new()) == NULL) return(NULL);
+	dh->p=BN_bin2bn(dh512_p,sizeof(dh512_p),NULL);
+	dh->g=BN_bin2bn(dh512_g,sizeof(dh512_g),NULL);
+	if ((dh->p == NULL) || (dh->g == NULL))
+		{ DH_free(dh); return(NULL); }
+	return(dh);
+	}
+
+static DH *get_dh1024()
+	{
+	static unsigned char dh1024_p[]={
+		0xF8,0x81,0x89,0x7D,0x14,0x24,0xC5,0xD1,0xE6,0xF7,0xBF,0x3A,
+		0xE4,0x90,0xF4,0xFC,0x73,0xFB,0x34,0xB5,0xFA,0x4C,0x56,0xA2,
+		0xEA,0xA7,0xE9,0xC0,0xC0,0xCE,0x89,0xE1,0xFA,0x63,0x3F,0xB0,
+		0x6B,0x32,0x66,0xF1,0xD1,0x7B,0xB0,0x00,0x8F,0xCA,0x87,0xC2,
+		0xAE,0x98,0x89,0x26,0x17,0xC2,0x05,0xD2,0xEC,0x08,0xD0,0x8C,
+		0xFF,0x17,0x52,0x8C,0xC5,0x07,0x93,0x03,0xB1,0xF6,0x2F,0xB8,
+		0x1C,0x52,0x47,0x27,0x1B,0xDB,0xD1,0x8D,0x9D,0x69,0x1D,0x52,
+		0x4B,0x32,0x81,0xAA,0x7F,0x00,0xC8,0xDC,0xE6,0xD9,0xCC,0xC1,
+		0x11,0x2D,0x37,0x34,0x6C,0xEA,0x02,0x97,0x4B,0x0E,0xBB,0xB1,
+		0x71,0x33,0x09,0x15,0xFD,0xDD,0x23,0x87,0x07,0x5E,0x89,0xAB,
+		0x6B,0x7C,0x5F,0xEC,0xA6,0x24,0xDC,0x53,
+		};
+	static unsigned char dh1024_g[]={
+		0x02,
+		};
+	DH *dh;
+
+	if ((dh=DH_new()) == NULL) return(NULL);
+	dh->p=BN_bin2bn(dh1024_p,sizeof(dh1024_p),NULL);
+	dh->g=BN_bin2bn(dh1024_g,sizeof(dh1024_g),NULL);
+	if ((dh->p == NULL) || (dh->g == NULL))
+		{ DH_free(dh); return(NULL); }
+	return(dh);
+	}
+
+static DH *get_dh1024dsa()
+	{
+	static unsigned char dh1024_p[]={
+		0xC8,0x00,0xF7,0x08,0x07,0x89,0x4D,0x90,0x53,0xF3,0xD5,0x00,
+		0x21,0x1B,0xF7,0x31,0xA6,0xA2,0xDA,0x23,0x9A,0xC7,0x87,0x19,
+		0x3B,0x47,0xB6,0x8C,0x04,0x6F,0xFF,0xC6,0x9B,0xB8,0x65,0xD2,
+		0xC2,0x5F,0x31,0x83,0x4A,0xA7,0x5F,0x2F,0x88,0x38,0xB6,0x55,
+		0xCF,0xD9,0x87,0x6D,0x6F,0x9F,0xDA,0xAC,0xA6,0x48,0xAF,0xFC,
+		0x33,0x84,0x37,0x5B,0x82,0x4A,0x31,0x5D,0xE7,0xBD,0x52,0x97,
+		0xA1,0x77,0xBF,0x10,0x9E,0x37,0xEA,0x64,0xFA,0xCA,0x28,0x8D,
+		0x9D,0x3B,0xD2,0x6E,0x09,0x5C,0x68,0xC7,0x45,0x90,0xFD,0xBB,
+		0x70,0xC9,0x3A,0xBB,0xDF,0xD4,0x21,0x0F,0xC4,0x6A,0x3C,0xF6,
+		0x61,0xCF,0x3F,0xD6,0x13,0xF1,0x5F,0xBC,0xCF,0xBC,0x26,0x9E,
+		0xBC,0x0B,0xBD,0xAB,0x5D,0xC9,0x54,0x39,
+		};
+	static unsigned char dh1024_g[]={
+		0x3B,0x40,0x86,0xE7,0xF3,0x6C,0xDE,0x67,0x1C,0xCC,0x80,0x05,
+		0x5A,0xDF,0xFE,0xBD,0x20,0x27,0x74,0x6C,0x24,0xC9,0x03,0xF3,
+		0xE1,0x8D,0xC3,0x7D,0x98,0x27,0x40,0x08,0xB8,0x8C,0x6A,0xE9,
+		0xBB,0x1A,0x3A,0xD6,0x86,0x83,0x5E,0x72,0x41,0xCE,0x85,0x3C,
+		0xD2,0xB3,0xFC,0x13,0xCE,0x37,0x81,0x9E,0x4C,0x1C,0x7B,0x65,
+		0xD3,0xE6,0xA6,0x00,0xF5,0x5A,0x95,0x43,0x5E,0x81,0xCF,0x60,
+		0xA2,0x23,0xFC,0x36,0xA7,0x5D,0x7A,0x4C,0x06,0x91,0x6E,0xF6,
+		0x57,0xEE,0x36,0xCB,0x06,0xEA,0xF5,0x3D,0x95,0x49,0xCB,0xA7,
+		0xDD,0x81,0xDF,0x80,0x09,0x4A,0x97,0x4D,0xA8,0x22,0x72,0xA1,
+		0x7F,0xC4,0x70,0x56,0x70,0xE8,0x20,0x10,0x18,0x8F,0x2E,0x60,
+		0x07,0xE7,0x68,0x1A,0x82,0x5D,0x32,0xA2,
+		};
+	DH *dh;
+
+	if ((dh=DH_new()) == NULL) return(NULL);
+	dh->p=BN_bin2bn(dh1024_p,sizeof(dh1024_p),NULL);
+	dh->g=BN_bin2bn(dh1024_g,sizeof(dh1024_g),NULL);
+	if ((dh->p == NULL) || (dh->g == NULL))
+		{ DH_free(dh); return(NULL); }
+	dh->length = 160;
+	return(dh);
+	}
+#endif
+
+static int do_test_cipherlist(void)
+	{
+	int i = 0;
+	const SSL_METHOD *meth;
+	SSL_CIPHER *ci, *tci = NULL;
+
+#ifndef OPENSSL_NO_SSL2
+	fprintf(stderr, "testing SSLv2 cipher list order: ");
+	meth = SSLv2_method();
+	while ((ci = meth->get_cipher(i++)) != NULL)
+		{
+		if (tci != NULL)
+			if (ci->id >= tci->id)
+				{
+				fprintf(stderr, "failed %lx vs. %lx\n", ci->id, tci->id);
+				return 0;
+				}
+		tci = ci;
+		}
+	fprintf(stderr, "ok\n");
+#endif
+#ifndef OPENSSL_NO_SSL3
+	fprintf(stderr, "testing SSLv3 cipher list order: ");
+	meth = SSLv3_method();
+	tci = NULL;
+	while ((ci = meth->get_cipher(i++)) != NULL)
+		{
+		if (tci != NULL)
+			if (ci->id >= tci->id)
+				{
+				fprintf(stderr, "failed %lx vs. %lx\n", ci->id, tci->id);
+				return 0;
+				}
+		tci = ci;
+		}
+	fprintf(stderr, "ok\n");
+#endif
+#ifndef OPENSSL_NO_TLS1
+	fprintf(stderr, "testing TLSv1 cipher list order: ");
+	meth = TLSv1_method();
+	tci = NULL;
+	while ((ci = meth->get_cipher(i++)) != NULL)
+		{
+		if (tci != NULL)
+			if (ci->id >= tci->id)
+				{
+				fprintf(stderr, "failed %lx vs. %lx\n", ci->id, tci->id);
+				return 0;
+				}
+		tci = ci;
+		}
+	fprintf(stderr, "ok\n");
+#endif
+
+	return 1;
+	}

Modified: openssl/branches/upstream/current/ssl/t1_enc.c
===================================================================
--- openssl/branches/upstream/current/ssl/t1_enc.c	2009-05-16 15:13:35 UTC (rev 371)
+++ openssl/branches/upstream/current/ssl/t1_enc.c	2009-05-16 15:25:35 UTC (rev 372)
@@ -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 @@
 
 	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 @@
 #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 @@
 	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 @@
 		{
                 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 @@
 
 #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 @@
 	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 @@
 	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);
 		}
 	}

Added: openssl/branches/upstream/current/ssl/t1_lib.c
===================================================================
--- openssl/branches/upstream/current/ssl/t1_lib.c	                        (rev 0)
+++ openssl/branches/upstream/current/ssl/t1_lib.c	2009-05-16 15:25:35 UTC (rev 372)
@@ -0,0 +1,878 @@
+/* ssl/t1_lib.c */
+/* Copyright (C) 1995-1998 Eric Young (eay at cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay at cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh at cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay at cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh at cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/ocsp.h>
+#include "ssl_locl.h"
+
+const char tls1_version_str[]="TLSv1" OPENSSL_VERSION_PTEXT;
+
+#ifndef OPENSSL_NO_TLSEXT
+static int tls_decrypt_ticket(SSL *s, const unsigned char *tick, int ticklen,
+				const unsigned char *sess_id, int sesslen,
+				SSL_SESSION **psess);
+#endif
+
+SSL3_ENC_METHOD TLSv1_enc_data={
+	tls1_enc,
+	tls1_mac,
+	tls1_setup_key_block,
+	tls1_generate_master_secret,
+	tls1_change_cipher_state,
+	tls1_final_finish_mac,
+	TLS1_FINISH_MAC_LENGTH,
+	tls1_cert_verify_mac,
+	TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE,
+	TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE,
+	tls1_alert_code,
+	};
+
+long tls1_default_timeout(void)
+	{
+	/* 2 hours, the 24 hours mentioned in the TLSv1 spec
+	 * is way too long for http, the cache would over fill */
+	return(60*60*2);
+	}
+
+IMPLEMENT_tls1_meth_func(tlsv1_base_method,
+			ssl_undefined_function,
+			ssl_undefined_function,
+			ssl_bad_method)
+
+int tls1_new(SSL *s)
+	{
+	if (!ssl3_new(s)) return(0);
+	s->method->ssl_clear(s);
+	return(1);
+	}
+
+void tls1_free(SSL *s)
+	{
+	ssl3_free(s);
+	}
+
+void tls1_clear(SSL *s)
+	{
+	ssl3_clear(s);
+	s->version=TLS1_VERSION;
+	}
+
+#if 0
+long tls1_ctrl(SSL *s, int cmd, long larg, char *parg)
+	{
+	return(0);
+	}
+
+long tls1_callback_ctrl(SSL *s, int cmd, void *(*fp)())
+	{
+	return(0);
+	}
+#endif
+
+#ifndef OPENSSL_NO_TLSEXT
+unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit)
+	{
+	int extdatalen=0;
+	unsigned char *ret = p;
+
+	ret+=2;
+
+	if (ret>=limit) return NULL; /* this really never occurs, but ... */
+
+ 	if (s->tlsext_hostname != NULL)
+		{ 
+		/* Add TLS extension servername to the Client Hello message */
+		unsigned long size_str;
+		long lenmax; 
+
+		/* check for enough space.
+		   4 for the servername type and entension length
+		   2 for servernamelist length
+		   1 for the hostname type
+		   2 for hostname length
+		   + hostname length 
+		*/
+		   
+		if ((lenmax = limit - ret - 9) < 0 
+		|| (size_str = strlen(s->tlsext_hostname)) > (unsigned long)lenmax) 
+			return NULL;
+			
+		/* extension type and length */
+		s2n(TLSEXT_TYPE_server_name,ret); 
+		s2n(size_str+5,ret);
+		
+		/* length of servername list */
+		s2n(size_str+3,ret);
+	
+		/* hostname type, length and hostname */
+		*(ret++) = (unsigned char) TLSEXT_NAMETYPE_host_name;
+		s2n(size_str,ret);
+		memcpy(ret, s->tlsext_hostname, size_str);
+		ret+=size_str;
+
+		}
+
+	if (!(SSL_get_options(s) & SSL_OP_NO_TICKET))
+		{
+		int ticklen;
+		if (s->session && s->session->tlsext_tick)
+			ticklen = s->session->tlsext_ticklen;
+		else
+			ticklen = 0;
+		/* Check for enough room 2 for extension type, 2 for len
+ 		 * rest for ticket
+  		 */
+		if (limit - ret - 4 - ticklen < 0)
+			return NULL;
+		s2n(TLSEXT_TYPE_session_ticket,ret); 
+		s2n(ticklen,ret);
+		if (ticklen)
+			{
+			memcpy(ret, s->session->tlsext_tick, ticklen);
+			ret += ticklen;
+			}
+		}
+
+	if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp)
+		{
+		int i;
+		long extlen, idlen, itmp;
+		OCSP_RESPID *id;
+
+		idlen = 0;
+		for (i = 0; i < sk_OCSP_RESPID_num(s->tlsext_ocsp_ids); i++)
+			{
+			id = sk_OCSP_RESPID_value(s->tlsext_ocsp_ids, i);
+			itmp = i2d_OCSP_RESPID(id, NULL);
+			if (itmp <= 0)
+				return NULL;
+			idlen += itmp + 2;
+			}
+
+		if (s->tlsext_ocsp_exts)
+			{
+			extlen = i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, NULL);
+			if (extlen < 0)
+				return NULL;
+			}
+		else
+			extlen = 0;
+			
+		if ((long)(limit - ret - 7 - extlen - idlen) < 0) return NULL;
+		s2n(TLSEXT_TYPE_status_request, ret);
+		if (extlen + idlen > 0xFFF0)
+			return NULL;
+		s2n(extlen + idlen + 5, ret);
+		*(ret++) = TLSEXT_STATUSTYPE_ocsp;
+		s2n(idlen, ret);
+		for (i = 0; i < sk_OCSP_RESPID_num(s->tlsext_ocsp_ids); i++)
+			{
+			/* save position of id len */
+			unsigned char *q = ret;
+			id = sk_OCSP_RESPID_value(s->tlsext_ocsp_ids, i);
+			/* skip over id len */
+			ret += 2;
+			itmp = i2d_OCSP_RESPID(id, &ret);
+			/* write id len */
+			s2n(itmp, q);
+			}
+		s2n(extlen, ret);
+		if (extlen > 0)
+			i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, &ret);
+		}
+
+	if ((extdatalen = ret-p-2)== 0) 
+		return p;
+
+	s2n(extdatalen,p);
+	return ret;
+	}
+
+unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit)
+	{
+	int extdatalen=0;
+	unsigned char *ret = p;
+
+	ret+=2;
+	if (ret>=limit) return NULL; /* this really never occurs, but ... */
+
+	if (!s->hit && s->servername_done == 1 && s->session->tlsext_hostname != NULL)
+		{ 
+		if (limit - ret - 4 < 0) return NULL; 
+
+		s2n(TLSEXT_TYPE_server_name,ret);
+		s2n(0,ret);
+		}
+	
+	if (s->tlsext_ticket_expected
+		&& !(SSL_get_options(s) & SSL_OP_NO_TICKET)) 
+		{ 
+		if (limit - ret - 4 < 0) return NULL; 
+		s2n(TLSEXT_TYPE_session_ticket,ret);
+		s2n(0,ret);
+		}
+
+	if (s->tlsext_status_expected)
+		{ 
+		if ((long)(limit - ret - 4) < 0) return NULL; 
+		s2n(TLSEXT_TYPE_status_request,ret);
+		s2n(0,ret);
+		}
+
+	if ((extdatalen = ret-p-2)== 0) 
+		return p;
+
+	s2n(extdatalen,p);
+	return ret;
+	}
+
+int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al)
+	{
+	unsigned short type;
+	unsigned short size;
+	unsigned short len;
+	unsigned char *data = *p;
+	s->servername_done = 0;
+	s->tlsext_status_type = -1;
+
+	if (data >= (d+n-2))
+		return 1;
+	n2s(data,len);
+
+	if (data > (d+n-len)) 
+		return 1;
+
+	while (data <= (d+n-4))
+		{
+		n2s(data,type);
+		n2s(data,size);
+
+		if (data+size > (d+n))
+	   		return 1;
+
+		if (s->tlsext_debug_cb)
+			s->tlsext_debug_cb(s, 0, type, data, size,
+						s->tlsext_debug_arg);
+/* The servername extension is treated as follows:
+
+   - Only the hostname type is supported with a maximum length of 255.
+   - The servername is rejected if too long or if it contains zeros,
+     in which case an fatal alert is generated.
+   - The servername field is maintained together with the session cache.
+   - When a session is resumed, the servername call back invoked in order
+     to allow the application to position itself to the right context. 
+   - The servername is acknowledged if it is new for a session or when 
+     it is identical to a previously used for the same session. 
+     Applications can control the behaviour.  They can at any time
+     set a 'desirable' servername for a new SSL object. This can be the
+     case for example with HTTPS when a Host: header field is received and
+     a renegotiation is requested. In this case, a possible servername
+     presented in the new client hello is only acknowledged if it matches
+     the value of the Host: field. 
+   - Applications must  use SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
+     if they provide for changing an explicit servername context for the session,
+     i.e. when the session has been established with a servername extension. 
+   - On session reconnect, the servername extension may be absent. 
+
+*/      
+
+		if (type == TLSEXT_TYPE_server_name)
+			{
+			unsigned char *sdata;
+			int servname_type;
+			int dsize; 
+		
+			if (size < 2) 
+				{
+				*al = SSL_AD_DECODE_ERROR;
+				return 0;
+				}
+			n2s(data,dsize);  
+			size -= 2;
+			if (dsize > size  ) 
+				{
+				*al = SSL_AD_DECODE_ERROR;
+				return 0;
+				} 
+
+			sdata = data;
+			while (dsize > 3) 
+				{
+	 			servname_type = *(sdata++); 
+				n2s(sdata,len);
+				dsize -= 3;
+
+				if (len > dsize) 
+					{
+					*al = SSL_AD_DECODE_ERROR;
+					return 0;
+					}
+				if (s->servername_done == 0)
+				switch (servname_type)
+					{
+				case TLSEXT_NAMETYPE_host_name:
+					if (s->session->tlsext_hostname == NULL)
+						{
+						if (len > TLSEXT_MAXLEN_host_name || 
+							((s->session->tlsext_hostname = OPENSSL_malloc(len+1)) == NULL))
+							{
+							*al = TLS1_AD_UNRECOGNIZED_NAME;
+							return 0;
+							}
+						memcpy(s->session->tlsext_hostname, sdata, len);
+						s->session->tlsext_hostname[len]='\0';
+						if (strlen(s->session->tlsext_hostname) != len) {
+							OPENSSL_free(s->session->tlsext_hostname);
+							s->session->tlsext_hostname = NULL;
+							*al = TLS1_AD_UNRECOGNIZED_NAME;
+							return 0;
+						}
+						s->servername_done = 1; 
+
+						}
+					else 
+						s->servername_done = strlen(s->session->tlsext_hostname) == len 
+							&& strncmp(s->session->tlsext_hostname, (char *)sdata, len) == 0;
+					
+					break;
+
+				default:
+					break;
+					}
+				 
+				dsize -= len;
+				}
+			if (dsize != 0) 
+				{
+				*al = SSL_AD_DECODE_ERROR;
+				return 0;
+				}
+
+			}
+		else if (type == TLSEXT_TYPE_status_request
+						&& s->ctx->tlsext_status_cb)
+			{
+		
+			if (size < 5) 
+				{
+				*al = SSL_AD_DECODE_ERROR;
+				return 0;
+				}
+
+			s->tlsext_status_type = *data++;
+			size--;
+			if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp)
+				{
+				const unsigned char *sdata;
+				int dsize;
+				/* Read in responder_id_list */
+				n2s(data,dsize);
+				size -= 2;
+				if (dsize > size  ) 
+					{
+					*al = SSL_AD_DECODE_ERROR;
+					return 0;
+					}
+				while (dsize > 0)
+					{
+					OCSP_RESPID *id;
+					int idsize;
+					if (dsize < 4)
+						{
+						*al = SSL_AD_DECODE_ERROR;
+						return 0;
+						}
+					n2s(data, idsize);
+					dsize -= 2 + idsize;
+					if (dsize < 0)
+						{
+						*al = SSL_AD_DECODE_ERROR;
+						return 0;
+						}
+					sdata = data;
+					data += idsize;
+					id = d2i_OCSP_RESPID(NULL,
+								&sdata, idsize);
+					if (!id)
+						{
+						*al = SSL_AD_DECODE_ERROR;
+						return 0;
+						}
+					if (data != sdata)
+						{
+						OCSP_RESPID_free(id);
+						*al = SSL_AD_DECODE_ERROR;
+						return 0;
+						}
+					if (!s->tlsext_ocsp_ids
+						&& !(s->tlsext_ocsp_ids =
+						sk_OCSP_RESPID_new_null()))
+						{
+						OCSP_RESPID_free(id);
+						*al = SSL_AD_INTERNAL_ERROR;
+						return 0;
+						}
+					if (!sk_OCSP_RESPID_push(
+							s->tlsext_ocsp_ids, id))
+						{
+						OCSP_RESPID_free(id);
+						*al = SSL_AD_INTERNAL_ERROR;
+						return 0;
+						}
+					}
+
+				/* Read in request_extensions */
+				n2s(data,dsize);
+				size -= 2;
+				if (dsize > size) 
+					{
+					*al = SSL_AD_DECODE_ERROR;
+					return 0;
+					}
+				sdata = data;
+				if (dsize > 0)
+					{
+					s->tlsext_ocsp_exts =
+						d2i_X509_EXTENSIONS(NULL,
+							&sdata, dsize);
+					if (!s->tlsext_ocsp_exts
+						|| (data + dsize != sdata))
+						{
+						*al = SSL_AD_DECODE_ERROR;
+						return 0;
+						}
+					}
+				}
+				/* We don't know what to do with any other type
+ 			 	* so ignore it.
+ 			 	*/
+				else
+					s->tlsext_status_type = -1;
+			}
+		/* session ticket processed earlier */
+
+		data+=size;		
+		}
+
+	*p = data;
+	return 1;
+	}
+
+int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al)
+	{
+	unsigned short type;
+	unsigned short size;
+	unsigned short len;  
+	unsigned char *data = *p;
+
+	int tlsext_servername = 0;
+
+	if (data >= (d+n-2))
+		return 1;
+
+	n2s(data,len);
+
+	while(data <= (d+n-4))
+		{
+		n2s(data,type);
+		n2s(data,size);
+
+		if (data+size > (d+n))
+	   		return 1;
+
+		if (s->tlsext_debug_cb)
+			s->tlsext_debug_cb(s, 1, type, data, size,
+						s->tlsext_debug_arg);
+
+		if (type == TLSEXT_TYPE_server_name)
+			{
+			if (s->tlsext_hostname == NULL || size > 0)
+				{
+				*al = TLS1_AD_UNRECOGNIZED_NAME;
+				return 0;
+				}
+			tlsext_servername = 1;   
+			}
+		else if (type == TLSEXT_TYPE_session_ticket)
+			{
+			if ((SSL_get_options(s) & SSL_OP_NO_TICKET)
+				|| (size > 0))
+				{
+				*al = TLS1_AD_UNSUPPORTED_EXTENSION;
+				return 0;
+				}
+			s->tlsext_ticket_expected = 1;
+			}
+		else if (type == TLSEXT_TYPE_status_request)
+			{
+			/* MUST be empty and only sent if we've requested
+			 * a status request message.
+			 */ 
+			if ((s->tlsext_status_type == -1) || (size > 0))
+				{
+				*al = TLS1_AD_UNSUPPORTED_EXTENSION;
+				return 0;
+				}
+			/* Set flag to expect CertificateStatus message */
+			s->tlsext_status_expected = 1;
+			}
+
+		data+=size;		
+		}
+
+	if (data != d+n)
+		{
+		*al = SSL_AD_DECODE_ERROR;
+		return 0;
+		}
+
+	if (!s->hit && tlsext_servername == 1)
+		{
+ 		if (s->tlsext_hostname)
+			{
+			if (s->session->tlsext_hostname == NULL)
+				{
+				s->session->tlsext_hostname = BUF_strdup(s->tlsext_hostname);	
+				if (!s->session->tlsext_hostname)
+					{
+					*al = SSL_AD_UNRECOGNIZED_NAME;
+					return 0;
+					}
+				}
+			else 
+				{
+				*al = SSL_AD_DECODE_ERROR;
+				return 0;
+				}
+			}
+		}
+
+	*p = data;
+	return 1;
+	}
+
+int ssl_check_clienthello_tlsext(SSL *s)
+	{
+	int ret=SSL_TLSEXT_ERR_NOACK;
+	int al = SSL_AD_UNRECOGNIZED_NAME;
+
+	if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0) 
+		ret = s->ctx->tlsext_servername_callback(s, &al, s->ctx->tlsext_servername_arg);
+	else if (s->initial_ctx != NULL && s->initial_ctx->tlsext_servername_callback != 0) 		
+		ret = s->initial_ctx->tlsext_servername_callback(s, &al, s->initial_ctx->tlsext_servername_arg);
+
+	/* If status request then ask callback what to do.
+ 	 * Note: this must be called after servername callbacks in case 
+ 	 * the certificate has changed.
+ 	 */
+	if ((s->tlsext_status_type != -1) && s->ctx->tlsext_status_cb)
+		{
+		int r;
+		r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
+		switch (r)
+			{
+			/* We don't want to send a status request response */
+			case SSL_TLSEXT_ERR_NOACK:
+				s->tlsext_status_expected = 0;
+				break;
+			/* status request response should be sent */
+			case SSL_TLSEXT_ERR_OK:
+				if (s->tlsext_ocsp_resp)
+					s->tlsext_status_expected = 1;
+				else
+					s->tlsext_status_expected = 0;
+				break;
+			/* something bad happened */
+			case SSL_TLSEXT_ERR_ALERT_FATAL:
+				ret = SSL_TLSEXT_ERR_ALERT_FATAL;
+				al = SSL_AD_INTERNAL_ERROR;
+				goto err;
+			}
+		}
+	else
+		s->tlsext_status_expected = 0;
+	err:
+	switch (ret)
+		{
+		case SSL_TLSEXT_ERR_ALERT_FATAL:
+			ssl3_send_alert(s,SSL3_AL_FATAL,al); 
+			return -1;
+
+		case SSL_TLSEXT_ERR_ALERT_WARNING:
+			ssl3_send_alert(s,SSL3_AL_WARNING,al);
+			return 1; 
+					
+		case SSL_TLSEXT_ERR_NOACK:
+			s->servername_done=0;
+			default:
+		return 1;
+		}
+	}
+
+int ssl_check_serverhello_tlsext(SSL *s)
+	{
+	int ret=SSL_TLSEXT_ERR_NOACK;
+	int al = SSL_AD_UNRECOGNIZED_NAME;
+
+	if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0) 
+		ret = s->ctx->tlsext_servername_callback(s, &al, s->ctx->tlsext_servername_arg);
+	else if (s->initial_ctx != NULL && s->initial_ctx->tlsext_servername_callback != 0) 		
+		ret = s->initial_ctx->tlsext_servername_callback(s, &al, s->initial_ctx->tlsext_servername_arg);
+
+	/* If we've requested certificate status and we wont get one
+ 	 * tell the callback
+ 	 */
+	if ((s->tlsext_status_type != -1) && !(s->tlsext_status_expected)
+			&& s->ctx->tlsext_status_cb)
+		{
+		int r;
+		/* Set resp to NULL, resplen to -1 so callback knows
+ 		 * there is no response.
+ 		 */
+		if (s->tlsext_ocsp_resp)
+			{
+			OPENSSL_free(s->tlsext_ocsp_resp);
+			s->tlsext_ocsp_resp = NULL;
+			}
+		s->tlsext_ocsp_resplen = -1;
+		r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
+		if (r == 0)
+			{
+			al = SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE;
+			ret = SSL_TLSEXT_ERR_ALERT_FATAL;
+			}
+		if (r < 0)
+			{
+			al = SSL_AD_INTERNAL_ERROR;
+			ret = SSL_TLSEXT_ERR_ALERT_FATAL;
+			}
+		}
+
+	switch (ret)
+		{
+		case SSL_TLSEXT_ERR_ALERT_FATAL:
+			ssl3_send_alert(s,SSL3_AL_FATAL,al); 
+			return -1;
+
+		case SSL_TLSEXT_ERR_ALERT_WARNING:
+			ssl3_send_alert(s,SSL3_AL_WARNING,al);
+			return 1; 
+					
+		case SSL_TLSEXT_ERR_NOACK:
+			s->servername_done=0;
+			default:
+		return 1;
+		}
+	}
+
+/* Since the server cache lookup is done early on in the processing of client
+ * hello and other operations depend on the result we need to handle any TLS
+ * session ticket extension at the same time.
+ */
+
+int tls1_process_ticket(SSL *s, unsigned char *session_id, int len,
+				const unsigned char *limit, SSL_SESSION **ret)
+	{
+	/* Point after session ID in client hello */
+	const unsigned char *p = session_id + len;
+	unsigned short i;
+
+	/* If tickets disabled behave as if no ticket present
+ 	 * to permit stateful resumption.
+ 	 */
+	if (SSL_get_options(s) & SSL_OP_NO_TICKET)
+		return 1;
+
+	if ((s->version <= SSL3_VERSION) || !limit)
+		return 1;
+	if (p >= limit)
+		return -1;
+	/* Skip past cipher list */
+	n2s(p, i);
+	p+= i;
+	if (p >= limit)
+		return -1;
+	/* Skip past compression algorithm list */
+	i = *(p++);
+	p += i;
+	if (p > limit)
+		return -1;
+	/* Now at start of extensions */
+	if ((p + 2) >= limit)
+		return 1;
+	n2s(p, i);
+	while ((p + 4) <= limit)
+		{
+		unsigned short type, size;
+		n2s(p, type);
+		n2s(p, size);
+		if (p + size > limit)
+			return 1;
+		if (type == TLSEXT_TYPE_session_ticket)
+			{
+			/* If zero length note client will accept a ticket
+ 			 * and indicate cache miss to trigger full handshake
+ 			 */
+			if (size == 0)
+				{
+				s->tlsext_ticket_expected = 1;
+				return 0;	/* Cache miss */
+				}
+			return tls_decrypt_ticket(s, p, size, session_id, len,
+									ret);
+			}
+		p += size;
+		}
+	return 1;
+	}
+
+static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen,
+				const unsigned char *sess_id, int sesslen,
+				SSL_SESSION **psess)
+	{
+	SSL_SESSION *sess;
+	unsigned char *sdec;
+	const unsigned char *p;
+	int slen, mlen, renew_ticket = 0;
+	unsigned char tick_hmac[EVP_MAX_MD_SIZE];
+	HMAC_CTX hctx;
+	EVP_CIPHER_CTX ctx;
+	/* Need at least keyname + iv + some encrypted data */
+	if (eticklen < 48)
+		goto tickerr;
+	/* Initialize session ticket encryption and HMAC contexts */
+	HMAC_CTX_init(&hctx);
+	EVP_CIPHER_CTX_init(&ctx);
+	if (s->ctx->tlsext_ticket_key_cb)
+		{
+		unsigned char *nctick = (unsigned char *)etick;
+		int rv = s->ctx->tlsext_ticket_key_cb(s, nctick, nctick + 16,
+							&ctx, &hctx, 0);
+		if (rv < 0)
+			return -1;
+		if (rv == 0)
+			goto tickerr;
+		if (rv == 2)
+			renew_ticket = 1;
+		}
+	else
+		{
+		/* Check key name matches */
+		if (memcmp(etick, s->ctx->tlsext_tick_key_name, 16))
+			goto tickerr;
+		HMAC_Init_ex(&hctx, s->ctx->tlsext_tick_hmac_key, 16,
+					tlsext_tick_md(), NULL);
+		EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
+				s->ctx->tlsext_tick_aes_key, etick + 16);
+		}
+	/* Attempt to process session ticket, first conduct sanity and
+ 	 * integrity checks on ticket.
+ 	 */
+	mlen = HMAC_size(&hctx);
+	eticklen -= mlen;
+	/* Check HMAC of encrypted ticket */
+	HMAC_Update(&hctx, etick, eticklen);
+	HMAC_Final(&hctx, tick_hmac, NULL);
+	HMAC_CTX_cleanup(&hctx);
+	if (memcmp(tick_hmac, etick + eticklen, mlen))
+		goto tickerr;
+	/* Attempt to decrypt session data */
+	/* Move p after IV to start of encrypted ticket, update length */
+	p = etick + 16 + EVP_CIPHER_CTX_iv_length(&ctx);
+	eticklen -= 16 + EVP_CIPHER_CTX_iv_length(&ctx);
+	sdec = OPENSSL_malloc(eticklen);
+	if (!sdec)
+		{
+		EVP_CIPHER_CTX_cleanup(&ctx);
+		return -1;
+		}
+	EVP_DecryptUpdate(&ctx, sdec, &slen, p, eticklen);
+	if (EVP_DecryptFinal(&ctx, sdec + slen, &mlen) <= 0)
+		goto tickerr;
+	slen += mlen;
+	EVP_CIPHER_CTX_cleanup(&ctx);
+	p = sdec;
+		
+	sess = d2i_SSL_SESSION(NULL, &p, slen);
+	OPENSSL_free(sdec);
+	if (sess)
+		{
+		/* The session ID if non-empty is used by some clients to
+ 		 * detect that the ticket has been accepted. So we copy it to
+ 		 * the session structure. If it is empty set length to zero
+ 		 * as required by standard.
+ 		 */
+		if (sesslen)
+			memcpy(sess->session_id, sess_id, sesslen);
+		sess->session_id_length = sesslen;
+		*psess = sess;
+		s->tlsext_ticket_expected = renew_ticket;
+		return 1;
+		}
+	/* If session decrypt failure indicate a cache miss and set state to
+ 	 * send a new ticket
+ 	 */
+	tickerr:	
+	s->tlsext_ticket_expected = 1;
+	return 0;
+	}
+
+#endif




More information about the Pkg-openssl-changes mailing list