Merge remote branch 'goog/dalvik-dev' into dalvik-dev-to-master
diff --git a/README.android b/README.android
index be1e365..1dd32bf 100644
--- a/README.android
+++ b/README.android
@@ -65,6 +65,12 @@
      harmony_tests.jar is built from Subversion http://harmony.apache.org/
      Within Google it can be found at ~dalvik-prebuild/bin/harmony_tests.jar
 
+     # You can also run openssl s_server as a test server on the device:
+     adb push ./android.testssl/CAss.cnf /sdcard/CAss.cnf
+     adb shell openssl req -config /sdcard/CAss.cnf -x509 -nodes -days 365 -subj '/C=US/ST=California/L=Mountain View/CN=localhost' -newkey rsa:1024 -keyout /sdcard/server.pem -out /sdcard/server.pem
+     adb shell openssl s_server -cert /sdcard/server.pem -www -verify 1
+     adb shell am start https://localhost:4433 # confirm result in browser
+
 8) Do a full build before checking in:
 
      m -j16
diff --git a/apps/Android.mk b/apps/Android.mk
index e9f215c..06e07a2 100644
--- a/apps/Android.mk
+++ b/apps/Android.mk
@@ -32,6 +32,9 @@
 	pkcs12.c \
 	pkcs7.c \
 	pkcs8.c \
+	pkey.c \
+	pkeyparam.c \
+	pkeyutl.c \
 	prime.c \
 	rand.c \
 	req.c \
@@ -39,6 +42,7 @@
 	rsautl.c \
 	s_cb.c \
 	s_client.c \
+	s_server.c \
 	s_socket.c \
 	s_time.c \
 	sess_id.c \
diff --git a/apps/pkey.c b/apps/pkey.c
new file mode 100644
index 0000000..17e6702
--- /dev/null
+++ b/apps/pkey.c
@@ -0,0 +1,284 @@
+/* apps/pkey.c */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2006
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include "apps.h"
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+
+#define PROG pkey_main
+
+int MAIN(int, char **);
+
+int MAIN(int argc, char **argv)
+	{
+	ENGINE *e = NULL;
+	char **args, *infile = NULL, *outfile = NULL;
+	char *passargin = NULL, *passargout = NULL;
+	BIO *in = NULL, *out = NULL;
+	const EVP_CIPHER *cipher = NULL;
+	int informat, outformat;
+	int pubin = 0, pubout = 0, pubtext = 0, text = 0, noout = 0;
+	EVP_PKEY *pkey=NULL;
+	char *passin = NULL, *passout = NULL;
+	int badarg = 0;
+#ifndef OPENSSL_NO_ENGINE
+	char *engine=NULL;
+#endif
+	int ret = 1;
+
+	if (bio_err == NULL)
+		bio_err = BIO_new_fp (stderr, BIO_NOCLOSE);
+
+	if (!load_config(bio_err, NULL))
+		goto end;
+
+	informat=FORMAT_PEM;
+	outformat=FORMAT_PEM;
+
+	ERR_load_crypto_strings();
+	OpenSSL_add_all_algorithms();
+	args = argv + 1;
+	while (!badarg && *args && *args[0] == '-')
+		{
+		if (!strcmp(*args,"-inform"))
+			{
+			if (args[1])
+				{
+				args++;
+				informat=str2fmt(*args);
+				}
+			else badarg = 1;
+			}
+		else if (!strcmp(*args,"-outform"))
+			{
+			if (args[1])
+				{
+				args++;
+				outformat=str2fmt(*args);
+				}
+			else badarg = 1;
+			}
+		else if (!strcmp(*args,"-passin"))
+			{
+			if (!args[1]) goto bad;
+			passargin= *(++args);
+			}
+		else if (!strcmp(*args,"-passout"))
+			{
+			if (!args[1]) goto bad;
+			passargout= *(++args);
+			}
+#ifndef OPENSSL_NO_ENGINE
+		else if (strcmp(*args,"-engine") == 0)
+			{
+			if (!args[1]) goto bad;
+			engine= *(++args);
+			}
+#endif
+		else if (!strcmp (*args, "-in"))
+			{
+			if (args[1])
+				{
+				args++;
+				infile = *args;
+				}
+			else badarg = 1;
+			}
+		else if (!strcmp (*args, "-out"))
+			{
+			if (args[1])
+				{
+				args++;
+				outfile = *args;
+				}
+			else badarg = 1;
+			}
+		else if (strcmp(*args,"-pubin") == 0)
+			{
+			pubin=1;
+			pubout=1;
+			pubtext=1;
+			}
+		else if (strcmp(*args,"-pubout") == 0)
+			pubout=1;
+		else if (strcmp(*args,"-text_pub") == 0)
+			{
+			pubtext=1;
+			text=1;
+			}
+		else if (strcmp(*args,"-text") == 0)
+			text=1;
+		else if (strcmp(*args,"-noout") == 0)
+			noout=1;
+		else
+			{
+			cipher = EVP_get_cipherbyname(*args + 1);
+			if (!cipher)
+				{
+				BIO_printf(bio_err, "Unknown cipher %s\n",
+								*args + 1);
+				badarg = 1;
+				}
+			}
+		args++;
+		}
+
+	if (badarg)
+		{
+		bad:
+		BIO_printf(bio_err, "Usage pkey [options]\n");
+		BIO_printf(bio_err, "where options are\n");
+		BIO_printf(bio_err, "-in file        input file\n");
+		BIO_printf(bio_err, "-inform X       input format (DER or PEM)\n");
+		BIO_printf(bio_err, "-passin arg     input file pass phrase source\n");
+		BIO_printf(bio_err, "-outform X      output format (DER or PEM)\n");
+		BIO_printf(bio_err, "-out file       output file\n");
+		BIO_printf(bio_err, "-passout arg    output file pass phrase source\n");
+#ifndef OPENSSL_NO_ENGINE
+		BIO_printf(bio_err, "-engine e       use engine e, possibly a hardware device.\n");
+#endif
+		return 1;
+		}
+
+#ifndef OPENSSL_NO_ENGINE
+        e = setup_engine(bio_err, engine, 0);
+#endif
+
+	if (!app_passwd(bio_err, passargin, passargout, &passin, &passout))
+		{
+		BIO_printf(bio_err, "Error getting passwords\n");
+		goto end;
+		}
+
+	if (outfile)
+		{
+		if (!(out = BIO_new_file (outfile, "wb")))
+			{
+			BIO_printf(bio_err,
+				 "Can't open output file %s\n", outfile);
+			goto end;
+			}
+		}
+	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 (pubin)
+		pkey = load_pubkey(bio_err, infile, informat, 1,
+			passin, e, "Public Key");
+	else
+		pkey = load_key(bio_err, infile, informat, 1,
+			passin, e, "key");
+	if (!pkey)
+		goto end;
+
+	if (!noout)
+		{
+		if (outformat == FORMAT_PEM) 
+			{
+			if (pubout)
+				PEM_write_bio_PUBKEY(out,pkey);
+			else
+				PEM_write_bio_PrivateKey(out, pkey, cipher,
+							NULL, 0, NULL, passout);
+			}
+		else if (outformat == FORMAT_ASN1)
+			{
+			if (pubout)
+				i2d_PUBKEY_bio(out, pkey);
+			else
+				i2d_PrivateKey_bio(out, pkey);
+			}
+		else
+			{
+			BIO_printf(bio_err, "Bad format specified for key\n");
+			goto end;
+			}
+
+		}
+
+	if (text)
+		{
+		if (pubtext)
+			EVP_PKEY_print_public(out, pkey, 0, NULL);
+		else
+			EVP_PKEY_print_private(out, pkey, 0, NULL);
+		}
+
+	ret = 0;
+
+	end:
+	EVP_PKEY_free(pkey);
+	BIO_free_all(out);
+	BIO_free(in);
+	if (passin)
+		OPENSSL_free(passin);
+	if (passout)
+		OPENSSL_free(passout);
+
+	return ret;
+	}
diff --git a/apps/pkeyparam.c b/apps/pkeyparam.c
new file mode 100644
index 0000000..7f18010
--- /dev/null
+++ b/apps/pkeyparam.c
@@ -0,0 +1,201 @@
+/* apps/pkeyparam.c */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2006
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include "apps.h"
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+
+#define PROG pkeyparam_main
+
+int MAIN(int, char **);
+
+int MAIN(int argc, char **argv)
+	{
+	char **args, *infile = NULL, *outfile = NULL;
+	BIO *in = NULL, *out = NULL;
+	int text = 0, noout = 0;
+	EVP_PKEY *pkey=NULL;
+	int badarg = 0;
+#ifndef OPENSSL_NO_ENGINE
+	ENGINE *e = NULL;
+	char *engine=NULL;
+#endif
+	int ret = 1;
+
+	if (bio_err == NULL)
+		bio_err = BIO_new_fp (stderr, BIO_NOCLOSE);
+
+	if (!load_config(bio_err, NULL))
+		goto end;
+
+	ERR_load_crypto_strings();
+	OpenSSL_add_all_algorithms();
+	args = argv + 1;
+	while (!badarg && *args && *args[0] == '-')
+		{
+		if (!strcmp (*args, "-in"))
+			{
+			if (args[1])
+				{
+				args++;
+				infile = *args;
+				}
+			else badarg = 1;
+			}
+		else if (!strcmp (*args, "-out"))
+			{
+			if (args[1])
+				{
+				args++;
+				outfile = *args;
+				}
+			else badarg = 1;
+			}
+#ifndef OPENSSL_NO_ENGINE
+		else if (strcmp(*args,"-engine") == 0)
+			{
+			if (!args[1]) goto bad;
+			engine= *(++args);
+			}
+#endif
+
+		else if (strcmp(*args,"-text") == 0)
+			text=1;
+		else if (strcmp(*args,"-noout") == 0)
+			noout=1;
+		args++;
+		}
+
+	if (badarg)
+		{
+#ifndef OPENSSL_NO_ENGINE
+		bad:
+#endif
+		BIO_printf(bio_err, "Usage pkeyparam [options]\n");
+		BIO_printf(bio_err, "where options are\n");
+		BIO_printf(bio_err, "-in file        input file\n");
+		BIO_printf(bio_err, "-out file       output file\n");
+		BIO_printf(bio_err, "-text           print parameters as text\n");
+		BIO_printf(bio_err, "-noout          don't output encoded parameters\n");
+#ifndef OPENSSL_NO_ENGINE
+		BIO_printf(bio_err, "-engine e       use engine e, possibly a hardware device.\n");
+#endif
+		return 1;
+		}
+
+#ifndef OPENSSL_NO_ENGINE
+        e = setup_engine(bio_err, engine, 0);
+#endif
+
+	if (infile)
+		{
+		if (!(in = BIO_new_file (infile, "r")))
+			{
+			BIO_printf(bio_err,
+				 "Can't open input file %s\n", infile);
+			goto end;
+			}
+		}
+	else
+		in = BIO_new_fp (stdin, BIO_NOCLOSE);
+
+	if (outfile)
+		{
+		if (!(out = BIO_new_file (outfile, "w")))
+			{
+			BIO_printf(bio_err,
+				 "Can't open output file %s\n", outfile);
+			goto end;
+			}
+		}
+	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
+		}
+
+	pkey = PEM_read_bio_Parameters(in, NULL);
+	if (!pkey)
+		{
+		BIO_printf(bio_err, "Error reading parameters\n");
+		ERR_print_errors(bio_err);
+		goto end;
+		}
+
+	if (!noout)
+		PEM_write_bio_Parameters(out,pkey);
+
+	if (text)
+		EVP_PKEY_print_params(out, pkey, 0, NULL);
+
+	ret = 0;
+
+	end:
+	EVP_PKEY_free(pkey);
+	BIO_free_all(out);
+	BIO_free(in);
+
+	return ret;
+	}
diff --git a/apps/pkeyutl.c b/apps/pkeyutl.c
new file mode 100644
index 0000000..22a6c4b
--- /dev/null
+++ b/apps/pkeyutl.c
@@ -0,0 +1,570 @@
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2006.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+
+#include "apps.h"
+#include <string.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/evp.h>
+
+#define KEY_PRIVKEY	1
+#define KEY_PUBKEY	2
+#define KEY_CERT	3
+
+static void usage(void);
+
+#undef PROG
+
+#define PROG pkeyutl_main
+
+static EVP_PKEY_CTX *init_ctx(int *pkeysize,
+				char *keyfile, int keyform, int key_type,
+				char *passargin, int pkey_op, ENGINE *e);
+
+static int setup_peer(BIO *err, EVP_PKEY_CTX *ctx, int peerform,
+							const char *file);
+
+static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
+		unsigned char *out, size_t *poutlen,
+		unsigned char *in, size_t inlen);
+
+int MAIN(int argc, char **);
+
+int MAIN(int argc, char **argv)
+{
+	BIO *in = NULL, *out = NULL;
+	char *infile = NULL, *outfile = NULL, *sigfile = NULL;
+	ENGINE *e = NULL;
+	int pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY;
+	int keyform = FORMAT_PEM, peerform = FORMAT_PEM;
+	char badarg = 0, rev = 0;
+	char hexdump = 0, asn1parse = 0;
+	EVP_PKEY_CTX *ctx = NULL;
+	char *passargin = NULL;
+	int keysize = -1;
+
+	unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL;
+	size_t buf_outlen;
+	int buf_inlen = 0, siglen = -1;
+
+	int ret = 1, rv = -1;
+
+	argc--;
+	argv++;
+
+	if(!bio_err) bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
+
+	if (!load_config(bio_err, NULL))
+		goto end;
+	ERR_load_crypto_strings();
+	OpenSSL_add_all_algorithms();
+	
+	while(argc >= 1)
+		{
+		if (!strcmp(*argv,"-in"))
+			{
+			if (--argc < 1) badarg = 1;
+                        infile= *(++argv);
+			}
+		else if (!strcmp(*argv,"-out"))
+			{
+			if (--argc < 1) badarg = 1;
+			outfile= *(++argv);
+			}
+		else if (!strcmp(*argv,"-sigfile"))
+			{
+			if (--argc < 1) badarg = 1;
+			sigfile= *(++argv);
+			}
+		else if(!strcmp(*argv, "-inkey"))
+			{
+			if (--argc < 1)
+				badarg = 1;
+			else
+				{
+				ctx = init_ctx(&keysize,
+						*(++argv), keyform, key_type,
+						passargin, pkey_op, e);
+				if (!ctx)
+					{
+					BIO_puts(bio_err,
+						"Error initializing context\n");
+					ERR_print_errors(bio_err);
+					badarg = 1;
+					}
+				}
+			}
+		else if (!strcmp(*argv,"-peerkey"))
+			{
+			if (--argc < 1)
+				badarg = 1;
+			else if (!setup_peer(bio_err, ctx, peerform, *(++argv)))
+				badarg = 1;
+			}
+		else if (!strcmp(*argv,"-passin"))
+			{
+			if (--argc < 1) badarg = 1;
+			passargin= *(++argv);
+			}
+		else if (strcmp(*argv,"-peerform") == 0)
+			{
+			if (--argc < 1) badarg = 1;
+			peerform=str2fmt(*(++argv));
+			}
+		else if (strcmp(*argv,"-keyform") == 0)
+			{
+			if (--argc < 1) badarg = 1;
+			keyform=str2fmt(*(++argv));
+			}
+#ifndef OPENSSL_NO_ENGINE
+		else if(!strcmp(*argv, "-engine"))
+			{
+			if (--argc < 1)
+				badarg = 1;
+			else
+				e = setup_engine(bio_err, *(++argv), 0);
+			}
+#endif
+		else if(!strcmp(*argv, "-pubin"))
+			key_type = KEY_PUBKEY;
+		else if(!strcmp(*argv, "-certin"))
+			key_type = KEY_CERT;
+		else if(!strcmp(*argv, "-asn1parse"))
+			asn1parse = 1;
+		else if(!strcmp(*argv, "-hexdump"))
+			hexdump = 1;
+		else if(!strcmp(*argv, "-sign"))
+			pkey_op = EVP_PKEY_OP_SIGN;
+		else if(!strcmp(*argv, "-verify"))
+			pkey_op = EVP_PKEY_OP_VERIFY;
+		else if(!strcmp(*argv, "-verifyrecover"))
+			pkey_op = EVP_PKEY_OP_VERIFYRECOVER;
+		else if(!strcmp(*argv, "-rev"))
+			rev = 1;
+		else if(!strcmp(*argv, "-encrypt"))
+			pkey_op = EVP_PKEY_OP_ENCRYPT;
+		else if(!strcmp(*argv, "-decrypt"))
+			pkey_op = EVP_PKEY_OP_DECRYPT;
+		else if(!strcmp(*argv, "-derive"))
+			pkey_op = EVP_PKEY_OP_DERIVE;
+		else if (strcmp(*argv,"-pkeyopt") == 0)
+			{
+			if (--argc < 1)
+				badarg = 1;
+			else if (!ctx)
+				{
+				BIO_puts(bio_err,
+					"-pkeyopt command before -inkey\n");
+				badarg = 1;
+				}
+			else if (pkey_ctrl_string(ctx, *(++argv)) <= 0)
+				{
+				BIO_puts(bio_err, "parameter setting error\n");
+				ERR_print_errors(bio_err);
+				goto end;
+				}
+			}
+		else badarg = 1;
+		if(badarg)
+			{
+			usage();
+			goto end;
+			}
+		argc--;
+		argv++;
+		}
+
+	if (!ctx)
+		{
+		usage();
+		goto end;
+		}
+
+	if (sigfile && (pkey_op != EVP_PKEY_OP_VERIFY))
+		{
+		BIO_puts(bio_err, "Signature file specified for non verify\n");
+		goto end;
+		}
+
+	if (!sigfile && (pkey_op == EVP_PKEY_OP_VERIFY))
+		{
+		BIO_puts(bio_err, "No signature file specified for verify\n");
+		goto end;
+		}
+
+/* FIXME: seed PRNG only if needed */
+	app_RAND_load_file(NULL, bio_err, 0);
+
+	if (pkey_op != EVP_PKEY_OP_DERIVE)
+		{
+		if(infile)
+			{
+			if(!(in = BIO_new_file(infile, "rb")))
+				{
+				BIO_puts(bio_err,
+					"Error Opening Input File\n");
+				ERR_print_errors(bio_err);	
+				goto end;
+				}
+			}
+		else
+			in = BIO_new_fp(stdin, BIO_NOCLOSE);
+		}
+
+	if(outfile)
+		{
+		if(!(out = BIO_new_file(outfile, "wb")))
+			{
+			BIO_printf(bio_err, "Error Creating Output File\n");
+			ERR_print_errors(bio_err);	
+			goto end;
+			}
+		}
+	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 (sigfile)
+		{
+		BIO *sigbio = BIO_new_file(sigfile, "rb");
+		if (!sigbio)
+			{
+			BIO_printf(bio_err, "Can't open signature file %s\n",
+								sigfile);
+			goto end;
+			}
+		siglen = bio_to_mem(&sig, keysize * 10, sigbio);
+		BIO_free(sigbio);
+		if (siglen <= 0)
+			{
+			BIO_printf(bio_err, "Error reading signature data\n");
+			goto end;
+			}
+		}
+	
+	if (in)
+		{
+		/* Read the input data */
+		buf_inlen = bio_to_mem(&buf_in, keysize * 10, in);
+		if(buf_inlen <= 0)
+			{
+			BIO_printf(bio_err, "Error reading input Data\n");
+			exit(1);
+			}
+		if(rev)
+			{
+			size_t i;
+			unsigned char ctmp;
+			size_t l = (size_t)buf_inlen;
+			for(i = 0; i < l/2; i++)
+				{
+				ctmp = buf_in[i];
+				buf_in[i] = buf_in[l - 1 - i];
+				buf_in[l - 1 - i] = ctmp;
+				}
+			}
+		}
+
+	if(pkey_op == EVP_PKEY_OP_VERIFY)
+		{
+		rv  = EVP_PKEY_verify(ctx, sig, (size_t)siglen,
+				      buf_in, (size_t)buf_inlen);
+		if (rv == 0)
+			BIO_puts(out, "Signature Verification Failure\n");
+		else if (rv == 1)
+			BIO_puts(out, "Signature Verified Successfully\n");
+		if (rv >= 0)
+			goto end;
+		}
+	else
+		{	
+		rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen,
+			      buf_in, (size_t)buf_inlen);
+		if (rv > 0)
+			{
+			buf_out = OPENSSL_malloc(buf_outlen);
+			if (!buf_out)
+				rv = -1;
+			else
+				rv = do_keyop(ctx, pkey_op,
+						buf_out, (size_t *)&buf_outlen,
+						buf_in, (size_t)buf_inlen);
+			}
+		}
+
+	if(rv <= 0)
+		{
+		BIO_printf(bio_err, "Public Key operation error\n");
+		ERR_print_errors(bio_err);
+		goto end;
+		}
+	ret = 0;
+	if(asn1parse)
+		{
+		if(!ASN1_parse_dump(out, buf_out, buf_outlen, 1, -1))
+			ERR_print_errors(bio_err);
+		}
+	else if(hexdump)
+		BIO_dump(out, (char *)buf_out, buf_outlen);
+	else
+		BIO_write(out, buf_out, buf_outlen);
+
+	end:
+	if (ctx)
+		EVP_PKEY_CTX_free(ctx);
+	BIO_free(in);
+	BIO_free_all(out);
+	if (buf_in)
+		OPENSSL_free(buf_in);
+	if (buf_out)
+		OPENSSL_free(buf_out);
+	if (sig)
+		OPENSSL_free(sig);
+	return ret;
+}
+
+static void usage()
+{
+	BIO_printf(bio_err, "Usage: pkeyutl [options]\n");
+	BIO_printf(bio_err, "-in file        input file\n");
+	BIO_printf(bio_err, "-out file       output file\n");
+	BIO_printf(bio_err, "-sigfile file signature file (verify operation only)\n");
+	BIO_printf(bio_err, "-inkey file     input key\n");
+	BIO_printf(bio_err, "-keyform arg    private key format - default PEM\n");
+	BIO_printf(bio_err, "-pubin          input is a public key\n");
+	BIO_printf(bio_err, "-certin         input is a certificate carrying a public key\n");
+	BIO_printf(bio_err, "-pkeyopt X:Y    public key options\n");
+	BIO_printf(bio_err, "-sign           sign with private key\n");
+	BIO_printf(bio_err, "-verify         verify with public key\n");
+	BIO_printf(bio_err, "-verifyrecover  verify with public key, recover original data\n");
+	BIO_printf(bio_err, "-encrypt        encrypt with public key\n");
+	BIO_printf(bio_err, "-decrypt        decrypt with private key\n");
+	BIO_printf(bio_err, "-derive         derive shared secret\n");
+	BIO_printf(bio_err, "-hexdump        hex dump output\n");
+#ifndef OPENSSL_NO_ENGINE
+	BIO_printf(bio_err, "-engine e       use engine e, possibly a hardware device.\n");
+#endif
+	BIO_printf(bio_err, "-passin arg     pass phrase source\n");
+
+}
+
+static EVP_PKEY_CTX *init_ctx(int *pkeysize,
+				char *keyfile, int keyform, int key_type,
+				char *passargin, int pkey_op, ENGINE *e)
+	{
+	EVP_PKEY *pkey = NULL;
+	EVP_PKEY_CTX *ctx = NULL;
+	char *passin = NULL;
+	int rv = -1;
+	X509 *x;
+	if(((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT) 
+		|| (pkey_op == EVP_PKEY_OP_DERIVE))
+		&& (key_type != KEY_PRIVKEY))
+		{
+		BIO_printf(bio_err, "A private key is needed for this operation\n");
+		goto end;
+		}
+	if(!app_passwd(bio_err, passargin, NULL, &passin, NULL))
+		{
+		BIO_printf(bio_err, "Error getting password\n");
+		goto end;
+		}
+	switch(key_type)
+		{
+		case KEY_PRIVKEY:
+		pkey = load_key(bio_err, keyfile, keyform, 0,
+			passin, e, "Private Key");
+		break;
+
+		case KEY_PUBKEY:
+		pkey = load_pubkey(bio_err, keyfile, keyform, 0,
+			NULL, e, "Public Key");
+		break;
+
+		case KEY_CERT:
+		x = load_cert(bio_err, keyfile, keyform,
+			NULL, e, "Certificate");
+		if(x)
+			{
+			pkey = X509_get_pubkey(x);
+			X509_free(x);
+			}
+		break;
+
+		}
+
+	*pkeysize = EVP_PKEY_size(pkey);
+
+	if (!pkey)
+		goto end;
+
+	ctx = EVP_PKEY_CTX_new(pkey, e);
+
+	EVP_PKEY_free(pkey);
+
+	if (!ctx)
+		goto end;
+
+	switch(pkey_op)
+		{
+		case EVP_PKEY_OP_SIGN:
+		rv = EVP_PKEY_sign_init(ctx);
+		break;
+
+		case EVP_PKEY_OP_VERIFY:
+		rv = EVP_PKEY_verify_init(ctx);
+		break;
+
+		case EVP_PKEY_OP_VERIFYRECOVER:
+		rv = EVP_PKEY_verify_recover_init(ctx);
+		break;
+
+		case EVP_PKEY_OP_ENCRYPT:
+		rv = EVP_PKEY_encrypt_init(ctx);
+		break;
+
+		case EVP_PKEY_OP_DECRYPT:
+		rv = EVP_PKEY_decrypt_init(ctx);
+		break;
+
+		case EVP_PKEY_OP_DERIVE:
+		rv = EVP_PKEY_derive_init(ctx);
+		break;
+		}
+
+	if (rv <= 0)
+		{
+		EVP_PKEY_CTX_free(ctx);
+		ctx = NULL;
+		}
+
+	end:
+
+	if (passin)
+		OPENSSL_free(passin);
+
+	return ctx;
+
+
+	}
+
+static int setup_peer(BIO *err, EVP_PKEY_CTX *ctx, int peerform,
+							const char *file)
+	{
+	EVP_PKEY *peer = NULL;
+	int ret;
+	if (!ctx)
+		{
+		BIO_puts(err, "-peerkey command before -inkey\n");
+		return 0;
+		}
+		
+	peer = load_pubkey(bio_err, file, peerform, 0, NULL, NULL, "Peer Key");
+
+	if (!peer)
+		{
+		BIO_printf(bio_err, "Error reading peer key %s\n", file);
+		ERR_print_errors(err);
+		return 0;
+		}
+
+	ret = EVP_PKEY_derive_set_peer(ctx, peer);
+
+	EVP_PKEY_free(peer);
+	if (ret <= 0)
+		ERR_print_errors(err);
+	return ret;
+	}
+
+static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
+		unsigned char *out, size_t *poutlen,
+		unsigned char *in, size_t inlen)
+	{
+	int rv = 0;
+	switch(pkey_op)
+		{
+		case EVP_PKEY_OP_VERIFYRECOVER:
+		rv  = EVP_PKEY_verify_recover(ctx, out, poutlen, in, inlen);
+		break;
+
+		case EVP_PKEY_OP_SIGN:
+		rv  = EVP_PKEY_sign(ctx, out, poutlen, in, inlen);
+		break;
+
+		case EVP_PKEY_OP_ENCRYPT:
+		rv  = EVP_PKEY_encrypt(ctx, out, poutlen, in, inlen);
+		break;
+
+		case EVP_PKEY_OP_DECRYPT:
+		rv  = EVP_PKEY_decrypt(ctx, out, poutlen, in, inlen);
+		break; 
+
+		case EVP_PKEY_OP_DERIVE:
+		rv  = EVP_PKEY_derive(ctx, out, poutlen);
+		break;
+
+		}
+	return rv;
+	}
diff --git a/apps/progs.h b/apps/progs.h
index 40bfcb5..728bb6d 100644
--- a/apps/progs.h
+++ b/apps/progs.h
@@ -43,9 +43,7 @@
 extern int smime_main(int argc,char *argv[]);
 extern int rand_main(int argc,char *argv[]);
 extern int engine_main(int argc,char *argv[]);
-#ifndef OPENSSL_NO_OCSP
 extern int ocsp_main(int argc,char *argv[]);
-#endif
 extern int prime_main(int argc,char *argv[]);
 extern int ts_main(int argc,char *argv[]);
 
@@ -109,9 +107,7 @@
 #endif
 	{FUNC_TYPE_GENERAL,"genpkey",genpkey_main},
 #if !defined(OPENSSL_NO_SOCK) && !(defined(OPENSSL_NO_SSL2) && defined(OPENSSL_NO_SSL3))
-#if 0 /* ANDROID */
-        {FUNC_TYPE_GENERAL,"s_server",s_server_main},
-#endif
+	{FUNC_TYPE_GENERAL,"s_server",s_server_main},
 #endif
 #if !defined(OPENSSL_NO_SOCK) && !(defined(OPENSSL_NO_SSL2) && defined(OPENSSL_NO_SSL3))
 	{FUNC_TYPE_GENERAL,"s_client",s_client_main},
@@ -137,11 +133,9 @@
 	{FUNC_TYPE_GENERAL,"pkcs12",pkcs12_main},
 #endif
 	{FUNC_TYPE_GENERAL,"pkcs8",pkcs8_main},
-#if 0 /* ANDROID */
 	{FUNC_TYPE_GENERAL,"pkey",pkey_main},
 	{FUNC_TYPE_GENERAL,"pkeyparam",pkeyparam_main},
 	{FUNC_TYPE_GENERAL,"pkeyutl",pkeyutl_main},
-#endif
 	{FUNC_TYPE_GENERAL,"spkac",spkac_main},
 	{FUNC_TYPE_GENERAL,"smime",smime_main},
 	{FUNC_TYPE_GENERAL,"rand",rand_main},
diff --git a/apps/s_client.c b/apps/s_client.c
index f2b8b43..6ed90f7 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -216,9 +216,6 @@
 /* Default PSK identity and key */
 static char *psk_identity="Client_identity";
 /*char *psk_key=NULL;  by default PSK is not used */
-#if 1 /* ANDROID */
-char *psk_key=NULL;
-#endif
 
 static unsigned int psk_client_cb(SSL *ssl, const char *hint, char *identity,
 	unsigned int max_identity_len, unsigned char *psk,
diff --git a/import_openssl.sh b/import_openssl.sh
index 36b2306..6f60198 100755
--- a/import_openssl.sh
+++ b/import_openssl.sh
@@ -99,13 +99,14 @@
 function import() {
   declare -r OPENSSL_SOURCE=$1
 
-  untar $OPENSSL_SOURCE
-  applypatches
+  untar $OPENSSL_SOURCE readonly
+  applypatches $OPENSSL_DIR
 
   cd $OPENSSL_DIR
 
   # Configure source (and print Makefile defines for review, see README.android)
   ./Configure $CONFIGURE_ARGS
+  rm -f apps/CA.pl.bak crypto/opensslconf.h.bak
   echo
   echo BEGIN Makefile defines to compare with android-config.mk
   echo
@@ -182,8 +183,8 @@
   declare -r OPENSSL_SOURCE=$2
 
   untar $OPENSSL_SOURCE
+  applypatches $OPENSSL_DIR_ORIG $patch
   prune
-  applypatches
 
   for i in $NEEDED_SOURCES; do
     echo "Restoring $i"
@@ -197,6 +198,7 @@
 
 function untar() {
   declare -r OPENSSL_SOURCE=$1
+  declare -r readonly=$2
 
   # Remove old source
   cleantar
@@ -204,7 +206,9 @@
   # Process new source
   tar -zxf $OPENSSL_SOURCE
   mv $OPENSSL_DIR $OPENSSL_DIR_ORIG
-  find $OPENSSL_DIR_ORIG -type f -print0 | xargs -0 chmod a-w
+  if [ ! -z $readonly ]; then
+    find $OPENSSL_DIR_ORIG -type f -print0 | xargs -0 chmod a-w
+  fi
   tar -zxf $OPENSSL_SOURCE
 }
 
@@ -220,12 +224,20 @@
 }
 
 function applypatches () {
-  cd $OPENSSL_DIR
+  declare -r dir=$1
+  declare -r skip_patch=$2
+
+  cd $dir
 
   # Apply appropriate patches
   for i in $OPENSSL_PATCHES; do
-    echo "Applying patch $i"
-    patch -p1 < ../patches/$i || die "Could not apply patches/$i. Fix source and run: $0 regenerate patches/$i"
+    if [ ! "$skip_patch" = "patches/$i" ]; then
+      echo "Applying patch $i"
+      patch -p1 < ../patches/$i || die "Could not apply patches/$i. Fix source and run: $0 regenerate patches/$i"
+    else
+      echo "Skiping patch $i"
+    fi
+
   done
 
   # Cleanup patch output
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index f9e34ec..a620f6f 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -1528,6 +1528,8 @@
 int	SSL_use_PrivateKey_ASN1(int pk,SSL *ssl, const unsigned char *d, long len);
 int	SSL_use_certificate(SSL *ssl, X509 *x);
 int	SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len);
+int	SSL_use_certificate_chain(SSL *ssl, STACK_OF(X509) *cert_chain);
+STACK_OF(X509) * SSL_get_certificate_chain(SSL *ssl, X509 *x);
 
 #ifndef OPENSSL_NO_STDIO
 int	SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type);
@@ -2014,6 +2016,7 @@
 #define SSL_F_SSL_UNDEFINED_VOID_FUNCTION		 244
 #define SSL_F_SSL_USE_CERTIFICATE			 198
 #define SSL_F_SSL_USE_CERTIFICATE_ASN1			 199
+#define SSL_F_SSL_USE_CERTIFICATE_CHAIN			 2000
 #define SSL_F_SSL_USE_CERTIFICATE_FILE			 200
 #define SSL_F_SSL_USE_PRIVATEKEY			 201
 #define SSL_F_SSL_USE_PRIVATEKEY_ASN1			 202
diff --git a/openssl.config b/openssl.config
index b12945f..0471619 100644
--- a/openssl.config
+++ b/openssl.config
@@ -59,11 +59,7 @@
 README \
 README.ASN1 \
 README.ENGINE \
-apps/CA.pl.bak \
 apps/Makefile \
-apps/pkey.c \
-apps/pkeyparam.c \
-apps/pkeyutl.c \
 apps/ts.c \
 apps/tsget \
 config \
@@ -101,7 +97,6 @@
 crypto/modes/modes.h \
 crypto/objects/Makefile \
 crypto/ocsp/Makefile \
-crypto/opensslconf.h.bak
 crypto/pem/Makefile \
 crypto/pkcs12/Makefile \
 crypto/pkcs7/Makefile \
@@ -194,9 +189,12 @@
 ssl/ssl.h \
 ssl/d1_clnt.c \
 ssl/s23_clnt.c \
+ssl/s3_both.c \
 ssl/s3_clnt.c \
 ssl/s3_srvr.c \
 ssl/ssl_err.c \
 ssl/ssl_lib.c \
+ssl/ssl_locl.h
+ssl/ssl_rsa.c \
 ssl/ssl_sess.c \
 "
diff --git a/patches/apps_Android.mk b/patches/apps_Android.mk
index e9f215c..06e07a2 100644
--- a/patches/apps_Android.mk
+++ b/patches/apps_Android.mk
@@ -32,6 +32,9 @@
 	pkcs12.c \
 	pkcs7.c \
 	pkcs8.c \
+	pkey.c \
+	pkeyparam.c \
+	pkeyutl.c \
 	prime.c \
 	rand.c \
 	req.c \
@@ -39,6 +42,7 @@
 	rsautl.c \
 	s_cb.c \
 	s_client.c \
+	s_server.c \
 	s_socket.c \
 	s_time.c \
 	sess_id.c \
diff --git a/patches/jsse.patch b/patches/jsse.patch
index b0ae319..09087de 100644
--- a/patches/jsse.patch
+++ b/patches/jsse.patch
@@ -1,6 +1,6 @@
---- openssl-1.0.0.orig/ssl/ssl.h	2010-01-06 09:37:38.000000000 -0800
-+++ openssl-1.0.0/ssl/ssl.h	2010-05-03 01:44:52.000000000 -0700
-@@ -1083,6 +1090,9 @@ struct ssl_st
+--- openssl-1.0.0.orig/ssl/ssl.h	2010-07-13 22:24:27.000000000 +0000
++++ openssl-1.0.0/ssl/ssl.h	2010-07-13 22:24:27.000000000 +0000
+@@ -1090,6 +1090,9 @@ struct ssl_st
  	/* This can also be in the session once a session is established */
  	SSL_SESSION *session;
  
@@ -10,7 +10,7 @@
  	/* Default generate session ID callback. */
  	GEN_SESSION_CB generate_session_id;
  
-@@ -1500,6 +1512,7 @@ BIO *	SSL_get_rbio(const SSL *s);
+@@ -1509,6 +1512,7 @@ BIO *	SSL_get_rbio(const SSL *s);
  BIO *	SSL_get_wbio(const SSL *s);
  #endif
  int	SSL_set_cipher_list(SSL *s, const char *str);
@@ -18,7 +18,16 @@
  void	SSL_set_read_ahead(SSL *s, int yes);
  int	SSL_get_verify_mode(const SSL *s);
  int	SSL_get_verify_depth(const SSL *s);
-@@ -1559,6 +1572,7 @@ int	SSL_SESSION_print(BIO *fp,const SSL_
+@@ -1524,6 +1528,8 @@ int	SSL_use_PrivateKey(SSL *ssl, EVP_PKE
+ int	SSL_use_PrivateKey_ASN1(int pk,SSL *ssl, const unsigned char *d, long len);
+ int	SSL_use_certificate(SSL *ssl, X509 *x);
+ int	SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len);
++int	SSL_use_certificate_chain(SSL *ssl, STACK_OF(X509) *cert_chain);
++STACK_OF(X509) * SSL_get_certificate_chain(SSL *ssl, X509 *x);
+ 
+ #ifndef OPENSSL_NO_STDIO
+ int	SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type);
+@@ -1568,6 +1574,7 @@ int	SSL_SESSION_print(BIO *fp,const SSL_
  void	SSL_SESSION_free(SSL_SESSION *ses);
  int	i2d_SSL_SESSION(SSL_SESSION *in,unsigned char **pp);
  int	SSL_set_session(SSL *to, SSL_SESSION *session);
@@ -26,7 +35,15 @@
  int	SSL_CTX_add_session(SSL_CTX *s, SSL_SESSION *c);
  int	SSL_CTX_remove_session(SSL_CTX *,SSL_SESSION *c);
  int	SSL_CTX_set_generate_session_id(SSL_CTX *, GEN_SESSION_CB);
-@@ -2204,6 +2218,7 @@ void ERR_load_SSL_strings(void);
+@@ -2009,6 +2016,7 @@ void ERR_load_SSL_strings(void);
+ #define SSL_F_SSL_UNDEFINED_VOID_FUNCTION		 244
+ #define SSL_F_SSL_USE_CERTIFICATE			 198
+ #define SSL_F_SSL_USE_CERTIFICATE_ASN1			 199
++#define SSL_F_SSL_USE_CERTIFICATE_CHAIN			 2000
+ #define SSL_F_SSL_USE_CERTIFICATE_FILE			 200
+ #define SSL_F_SSL_USE_PRIVATEKEY			 201
+ #define SSL_F_SSL_USE_PRIVATEKEY_ASN1			 202
+@@ -2213,6 +2221,7 @@ void ERR_load_SSL_strings(void);
  #define SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING		 345
  #define SSL_R_SERVERHELLO_TLSEXT			 275
  #define SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED		 277
@@ -34,8 +51,8 @@
  #define SSL_R_SHORT_READ				 219
  #define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE	 220
  #define SSL_R_SSL23_DOING_SESSION_ID_REUSE		 221
---- openssl-1.0.0.orig/ssl/d1_clnt.c	2010-01-26 11:46:29.000000000 -0800
-+++ openssl-1.0.0/ssl/d1_clnt.c	2010-05-12 22:07:36.000000000 -0700
+--- openssl-1.0.0.orig/ssl/d1_clnt.c	2010-01-26 19:46:29.000000000 +0000
++++ openssl-1.0.0/ssl/d1_clnt.c	2010-07-13 22:24:27.000000000 +0000
 @@ -613,6 +613,12 @@ int dtls1_client_hello(SSL *s)
  #endif
  			(s->session->not_resumable))
@@ -49,8 +66,8 @@
  			if (!ssl_get_new_session(s,0))
  				goto err;
  			}
---- openssl-1.0.0.orig/ssl/s23_clnt.c	2010-02-16 06:20:40.000000000 -0800
-+++ openssl-1.0.0/ssl/s23_clnt.c	2010-05-12 22:07:36.000000000 -0700
+--- openssl-1.0.0.orig/ssl/s23_clnt.c	2010-02-16 14:20:40.000000000 +0000
++++ openssl-1.0.0/ssl/s23_clnt.c	2010-07-13 22:24:27.000000000 +0000
 @@ -687,6 +687,13 @@ static int ssl23_get_server_hello(SSL *s
  
  	/* Since, if we are sending a ssl23 client hello, we are not
@@ -65,9 +82,35 @@
  	if (!ssl_get_new_session(s,0))
  		goto err;
  
---- openssl-1.0.0.orig/ssl/s3_clnt.c	2010-02-27 16:24:24.000000000 -0800
-+++ openssl-1.0.0/ssl/s3_clnt.c	2010-05-12 22:07:36.000000000 -0700
-@@ -621,6 +668,12 @@ int ssl3_client_hello(SSL *s)
+--- openssl-1.0.0.orig/ssl/s3_both.c	2010-07-13 22:24:27.000000000 +0000
++++ openssl-1.0.0/ssl/s3_both.c	2010-07-13 22:24:27.000000000 +0000
+@@ -322,8 +322,11 @@ unsigned long ssl3_output_cert_chain(SSL
+ 	unsigned long l=7;
+ 	BUF_MEM *buf;
+ 	int no_chain;
++	STACK_OF(X509) *cert_chain;
+ 
+-	if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || s->ctx->extra_certs)
++	cert_chain = SSL_get_certificate_chain(s, x);
++
++	if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || s->ctx->extra_certs || cert_chain)
+ 		no_chain = 1;
+ 	else
+ 		no_chain = 0;
+@@ -375,6 +378,10 @@ unsigned long ssl3_output_cert_chain(SSL
+ 			return(0);
+ 		}
+ 
++	for (i=0; i<sk_X509_num(cert_chain); i++)
++		if (ssl3_add_cert_to_buf(buf, &l, sk_X509_value(cert_chain,i)))
++			return(0);
++
+ 	l-=7;
+ 	p=(unsigned char *)&(buf->data[4]);
+ 	l2n3(l,p);
+--- openssl-1.0.0.orig/ssl/s3_clnt.c	2010-07-13 22:24:27.000000000 +0000
++++ openssl-1.0.0/ssl/s3_clnt.c	2010-07-13 22:24:27.000000000 +0000
+@@ -668,6 +668,12 @@ int ssl3_client_hello(SSL *s)
  #endif
  			(sess->not_resumable))
  			{
@@ -80,7 +123,7 @@
  			if (!ssl_get_new_session(s,0))
  				goto err;
  			}
-@@ -829,6 +882,12 @@ int ssl3_get_server_hello(SSL *s)
+@@ -876,6 +882,12 @@ int ssl3_get_server_hello(SSL *s)
  		s->hit=0;
  		if (s->session->session_id_length > 0)
  			{
@@ -93,8 +136,8 @@
  			if (!ssl_get_new_session(s,0))
  				{
  				al=SSL_AD_INTERNAL_ERROR;
---- openssl-1.0.0.orig/ssl/s3_srvr.c	2010-02-27 15:04:10.000000000 -0800
-+++ openssl-1.0.0/ssl/s3_srvr.c	2010-05-12 22:07:36.000000000 -0700
+--- openssl-1.0.0.orig/ssl/s3_srvr.c	2010-02-27 23:04:10.000000000 +0000
++++ openssl-1.0.0/ssl/s3_srvr.c	2010-07-13 22:24:27.000000000 +0000
 @@ -869,6 +869,12 @@ int ssl3_get_client_hello(SSL *s)
  	 */
  	if ((s->new_session && (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)))
@@ -121,8 +164,8 @@
  			if (!ssl_get_new_session(s,1))
  				goto err;
  			}
---- openssl-1.0.0.orig/ssl/ssl_err.c	2010-01-06 09:37:38.000000000 -0800
-+++ openssl-1.0.0/ssl/ssl_err.c	2010-05-12 22:07:36.000000000 -0700
+--- openssl-1.0.0.orig/ssl/ssl_err.c	2010-01-06 17:37:38.000000000 +0000
++++ openssl-1.0.0/ssl/ssl_err.c	2010-07-13 22:24:27.000000000 +0000
 @@ -462,6 +462,7 @@ static ERR_STRING_DATA SSL_str_reasons[]
  {ERR_REASON(SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING),"scsv received when renegotiating"},
  {ERR_REASON(SSL_R_SERVERHELLO_TLSEXT)    ,"serverhello tlsext"},
@@ -131,8 +174,8 @@
  {ERR_REASON(SSL_R_SHORT_READ)            ,"short read"},
  {ERR_REASON(SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE),"signature for non signing certificate"},
  {ERR_REASON(SSL_R_SSL23_DOING_SESSION_ID_REUSE),"ssl23 doing session id reuse"},
---- openssl-1.0.0.orig/ssl/ssl_lib.c	2010-02-17 11:43:46.000000000 -0800
-+++ openssl-1.0.0/ssl/ssl_lib.c	2010-05-12 22:07:36.000000000 -0700
+--- openssl-1.0.0.orig/ssl/ssl_lib.c	2010-07-13 22:24:27.000000000 +0000
++++ openssl-1.0.0/ssl/ssl_lib.c	2010-07-13 22:24:27.000000000 +0000
 @@ -326,6 +326,7 @@ SSL *SSL_new(SSL_CTX *ctx)
  	OPENSSL_assert(s->sid_ctx_length <= sizeof s->sid_ctx);
  	memcpy(&s->sid_ctx,&ctx->sid_ctx,sizeof(s->sid_ctx));
@@ -174,8 +217,63 @@
  /* works well for SSLv2, not so good for SSLv3 */
  char *SSL_get_shared_ciphers(const SSL *s,char *buf,int len)
  	{
---- openssl-1.0.0.orig/ssl/ssl_sess.c	2010-02-01 08:49:42.000000000 -0800
-+++ openssl-1.0.0/ssl/ssl_sess.c	2010-05-12 22:07:36.000000000 -0700
+--- openssl-1.0.0.orig/ssl/ssl_locl.h	2009-12-08 11:38:18.000000000 +0000
++++ openssl-1.0.0/ssl/ssl_locl.h	2010-07-13 22:24:27.000000000 +0000
+@@ -456,6 +456,7 @@
+ typedef struct cert_pkey_st
+ 	{
+ 	X509 *x509;
++	STACK_OF(X509) *cert_chain;
+ 	EVP_PKEY *privatekey;
+ 	} CERT_PKEY;
+ 
+--- openssl-1.0.0.orig/ssl/ssl_rsa.c	2009-09-12 23:09:26.000000000 +0000
++++ openssl-1.0.0/ssl/ssl_rsa.c	2010-07-13 22:24:27.000000000 +0000
+@@ -697,6 +697,42 @@ int SSL_CTX_use_PrivateKey_ASN1(int type
+ 	}
+ 
+ 
++int SSL_use_certificate_chain(SSL *ssl, STACK_OF(X509) *cert_chain)
++	{
++	if (ssl == NULL)
++		{
++		SSLerr(SSL_F_SSL_USE_CERTIFICATE_CHAIN,ERR_R_PASSED_NULL_PARAMETER);
++		return(0);
++		}
++	if (ssl->cert == NULL)
++		{
++		SSLerr(SSL_F_SSL_USE_CERTIFICATE_CHAIN,SSL_R_NO_CERTIFICATE_ASSIGNED);
++		return(0);
++		}
++	if (ssl->cert->key == NULL)
++		{
++		SSLerr(SSL_F_SSL_USE_CERTIFICATE_CHAIN,SSL_R_NO_CERTIFICATE_ASSIGNED);
++		return(0);
++		}
++	ssl->cert->key->cert_chain = cert_chain;
++	return(1);
++	}
++
++STACK_OF(X509) *SSL_get_certificate_chain(SSL *ssl, X509 *x)
++	{
++	int i;
++	if (x == NULL)
++		return NULL;
++	if (ssl == NULL)
++		return NULL;
++	if (ssl->cert == NULL)
++		return NULL;
++	for (i = 0; i < SSL_PKEY_NUM; i++)
++		if (ssl->cert->pkeys[i].x509 == x)
++			return ssl->cert->pkeys[i].cert_chain;
++	return NULL;
++	}
++
+ #ifndef OPENSSL_NO_STDIO
+ /* Read a file that contains our certificate in "PEM" format,
+  * possibly followed by a sequence of CA certificates that should be
+--- openssl-1.0.0.orig/ssl/ssl_sess.c	2010-02-01 16:49:42.000000000 +0000
++++ openssl-1.0.0/ssl/ssl_sess.c	2010-07-13 22:24:27.000000000 +0000
 @@ -261,6 +261,11 @@ static int def_generate_session_id(const
  	return 0;
  }
diff --git a/patches/progs.patch b/patches/progs.patch
index a00af00..16fd9b0 100644
--- a/patches/progs.patch
+++ b/patches/progs.patch
@@ -13,39 +13,6 @@
  			config = NULL;
 --- openssl-1.0.0.orig/apps/progs.h	2009-06-30 08:08:38.000000000 -0700
 +++ openssl-1.0.0/apps/progs.h	2010-05-18 14:05:38.000000000 -0700
-@@ -43,7 +43,9 @@ extern int spkac_main(int argc,char *arg
- extern int smime_main(int argc,char *argv[]);
- extern int rand_main(int argc,char *argv[]);
- extern int engine_main(int argc,char *argv[]);
-+#ifndef OPENSSL_NO_OCSP
- extern int ocsp_main(int argc,char *argv[]);
-+#endif
- extern int prime_main(int argc,char *argv[]);
- extern int ts_main(int argc,char *argv[]);
- 
-@@ -107,7 +109,9 @@ FUNCTION functions[] = {
- #endif
- 	{FUNC_TYPE_GENERAL,"genpkey",genpkey_main},
- #if !defined(OPENSSL_NO_SOCK) && !(defined(OPENSSL_NO_SSL2) && defined(OPENSSL_NO_SSL3))
--	{FUNC_TYPE_GENERAL,"s_server",s_server_main},
-+#if 0 /* ANDROID */
-+        {FUNC_TYPE_GENERAL,"s_server",s_server_main},
-+#endif
- #endif
- #if !defined(OPENSSL_NO_SOCK) && !(defined(OPENSSL_NO_SSL2) && defined(OPENSSL_NO_SSL3))
- 	{FUNC_TYPE_GENERAL,"s_client",s_client_main},
-@@ -133,9 +137,11 @@ FUNCTION functions[] = {
- 	{FUNC_TYPE_GENERAL,"pkcs12",pkcs12_main},
- #endif
- 	{FUNC_TYPE_GENERAL,"pkcs8",pkcs8_main},
-+#if 0 /* ANDROID */
- 	{FUNC_TYPE_GENERAL,"pkey",pkey_main},
- 	{FUNC_TYPE_GENERAL,"pkeyparam",pkeyparam_main},
- 	{FUNC_TYPE_GENERAL,"pkeyutl",pkeyutl_main},
-+#endif
- 	{FUNC_TYPE_GENERAL,"spkac",spkac_main},
- 	{FUNC_TYPE_GENERAL,"smime",smime_main},
- 	{FUNC_TYPE_GENERAL,"rand",rand_main},
 @@ -146,7 +152,9 @@ FUNCTION functions[] = {
  	{FUNC_TYPE_GENERAL,"ocsp",ocsp_main},
  #endif
@@ -85,15 +52,3 @@
  # undef  TERMIOS
  # define TERMIO
  # undef  SGTTY
---- openssl-1.0.0.orig/apps/s_client.c	2009-12-16 12:28:28.000000000 -0800
-+++ openssl-1.0.0/apps/s_client.c	2010-04-14 14:25:09.000000000 -0700
-@@ -216,6 +216,9 @@ static int c_ign_eof=0;
- /* Default PSK identity and key */
- static char *psk_identity="Client_identity";
- /*char *psk_key=NULL;  by default PSK is not used */
-+#if 1 /* ANDROID */
-+char *psk_key=NULL;
-+#endif
- 
- static unsigned int psk_client_cb(SSL *ssl, const char *hint, char *identity,
- 	unsigned int max_identity_len, unsigned char *psk,
diff --git a/ssl/s3_both.c b/ssl/s3_both.c
index cb391cd..06d5b2c 100644
--- a/ssl/s3_both.c
+++ b/ssl/s3_both.c
@@ -322,8 +322,11 @@
 	unsigned long l=7;
 	BUF_MEM *buf;
 	int no_chain;
+	STACK_OF(X509) *cert_chain;
 
-	if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || s->ctx->extra_certs)
+	cert_chain = SSL_get_certificate_chain(s, x);
+
+	if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || s->ctx->extra_certs || cert_chain)
 		no_chain = 1;
 	else
 		no_chain = 0;
@@ -375,6 +378,10 @@
 			return(0);
 		}
 
+	for (i=0; i<sk_X509_num(cert_chain); i++)
+		if (ssl3_add_cert_to_buf(buf, &l, sk_X509_value(cert_chain,i)))
+			return(0);
+
 	l-=7;
 	p=(unsigned char *)&(buf->data[4]);
 	l2n3(l,p);
diff --git a/ssl/ssl.h b/ssl/ssl.h
index f9e34ec..a620f6f 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -1528,6 +1528,8 @@
 int	SSL_use_PrivateKey_ASN1(int pk,SSL *ssl, const unsigned char *d, long len);
 int	SSL_use_certificate(SSL *ssl, X509 *x);
 int	SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len);
+int	SSL_use_certificate_chain(SSL *ssl, STACK_OF(X509) *cert_chain);
+STACK_OF(X509) * SSL_get_certificate_chain(SSL *ssl, X509 *x);
 
 #ifndef OPENSSL_NO_STDIO
 int	SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type);
@@ -2014,6 +2016,7 @@
 #define SSL_F_SSL_UNDEFINED_VOID_FUNCTION		 244
 #define SSL_F_SSL_USE_CERTIFICATE			 198
 #define SSL_F_SSL_USE_CERTIFICATE_ASN1			 199
+#define SSL_F_SSL_USE_CERTIFICATE_CHAIN			 2000
 #define SSL_F_SSL_USE_CERTIFICATE_FILE			 200
 #define SSL_F_SSL_USE_PRIVATEKEY			 201
 #define SSL_F_SSL_USE_PRIVATEKEY_ASN1			 202
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 4c78393..73d2290 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -456,6 +456,7 @@
 typedef struct cert_pkey_st
 	{
 	X509 *x509;
+	STACK_OF(X509) *cert_chain;
 	EVP_PKEY *privatekey;
 	} CERT_PKEY;
 
diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c
index c0960b5..c43f3e2 100644
--- a/ssl/ssl_rsa.c
+++ b/ssl/ssl_rsa.c
@@ -697,6 +697,42 @@
 	}
 
 
+int SSL_use_certificate_chain(SSL *ssl, STACK_OF(X509) *cert_chain)
+	{
+	if (ssl == NULL)
+		{
+		SSLerr(SSL_F_SSL_USE_CERTIFICATE_CHAIN,ERR_R_PASSED_NULL_PARAMETER);
+		return(0);
+		}
+	if (ssl->cert == NULL)
+		{
+		SSLerr(SSL_F_SSL_USE_CERTIFICATE_CHAIN,SSL_R_NO_CERTIFICATE_ASSIGNED);
+		return(0);
+		}
+	if (ssl->cert->key == NULL)
+		{
+		SSLerr(SSL_F_SSL_USE_CERTIFICATE_CHAIN,SSL_R_NO_CERTIFICATE_ASSIGNED);
+		return(0);
+		}
+	ssl->cert->key->cert_chain = cert_chain;
+	return(1);
+	}
+
+STACK_OF(X509) *SSL_get_certificate_chain(SSL *ssl, X509 *x)
+	{
+	int i;
+	if (x == NULL)
+		return NULL;
+	if (ssl == NULL)
+		return NULL;
+	if (ssl->cert == NULL)
+		return NULL;
+	for (i = 0; i < SSL_PKEY_NUM; i++)
+		if (ssl->cert->pkeys[i].x509 == x)
+			return ssl->cert->pkeys[i].cert_chain;
+	return NULL;
+	}
+
 #ifndef OPENSSL_NO_STDIO
 /* Read a file that contains our certificate in "PEM" format,
  * possibly followed by a sequence of CA certificates that should be