openssl-1.0.0 upgrade

external/openssl

    Updated version to 1.0.0
	openssl.version

    Updated small records patch for 1.0.0. This is probably the most significant change.
	patches/small_records.patch

    Removed bad_version.patch since fix is included in 0.9.8n and beyond
	patches/README
	patches/bad_version.patch
	openssl.config

    Changed import_openssl.sh to generate armv4 asm with the 1.0.0
    scripts, not our backported 0.9.9-dev backported version in
    patches/arm-asm.patch.
	import_openssl.sh
	openssl.config
	patches/README
	patches/arm-asm.patch

    Added -DOPENSSL_NO_STORE to match ./Configure output
    Added -DOPENSSL_NO_WHIRLPOOL (no-whrlpool) to skip new optional cipher
	android-config.mk
	openssl.config

    Fixed import to remove include directory during import like other
    imported directories (apps, ssl, crypto)
	import_openssl.sh

    Updated UNNEEDED_SOURCES. Pruned Makefiles which we don't use.
	openssl.config

    Updated to build newly required files
	patches/apps_Android.mk
	patches/crypto_Android.mk

    Disable some new openssl tools
	patches/progs.patch

    Updated upgrade testing notes to include running BigInteger tests
	README.android

    Automatically imported
	android.testssl/
	apps/
	crypto/
	e_os.h
	e_os2.h
	include/
	ssl/

dalvik

   Change makeCipherList to skip SSLv2 ciphers that 1.0.0 now returns
   so there are not duplicate ciphersuite names in getEnabledCipherSuites.
	libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp

   Updated OpenSSLSocketImpl_cipherauthenticationmethod for new
   SSL_CIPHER algorithms -> algorithm_auth (and const-ness)
	libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp

   Update to const SSL_CIPHER in OpenSSLSessionImpl_getCipherSuite (and cipherauthenticationmethod)
	libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp

   test_EnabledCipherSuites on both SSLSocketTest and
   SSLServerSocketTest caught the makeCipherList problem. However the
   asserts where a bit out of sync and didn't give good messages
   because they didn't actually show what was going on. As part of
   debugging the issue they found, I tried to make align the asserts
   and improve their output for the future.

	libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLServerSocketTest.java
	libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLSocketTest.java

vendor/google

    Add const to X509V3_EXT_METHOD* for 1.0.0 compatibility
	libraries/libjingle/talk/base/openssladapter.cc

Change-Id: I608dbb2ecf4b7a15e13b3f3dcea7c0443ff01e32
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 15650da..3157f20 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -58,7 +58,7 @@
  * [including the GNU Public Licence.]
  */
 /* ====================================================================
- * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1998-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
@@ -115,6 +115,32 @@
  * ECC cipher suite support in OpenSSL originally developed by 
  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
  */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
 
 #ifdef REF_CHECK
 #  include <assert.h>
@@ -143,9 +169,9 @@
 	ssl_undefined_function,
 	(int (*)(SSL *, unsigned char *, unsigned char *, int))ssl_undefined_function,
 	(int (*)(SSL*, int))ssl_undefined_function,
-	(int (*)(SSL *, EVP_MD_CTX *, EVP_MD_CTX *, const char*, int, unsigned char *))ssl_undefined_function,
+	(int (*)(SSL *,  const char*, int, unsigned char *))ssl_undefined_function,
 	0,	/* finish_mac_length */
-	(int (*)(SSL *, EVP_MD_CTX *, unsigned char *))ssl_undefined_function,
+	(int (*)(SSL *, int, unsigned char *))ssl_undefined_function,
 	NULL,	/* client_finished_label */
 	0,	/* client_finished_label_len */
 	NULL,	/* server_finished_label */
@@ -204,6 +230,8 @@
 		}
 
 	ssl_clear_cipher_ctx(s);
+	ssl_clear_hash_ctx(&s->read_hash);
+	ssl_clear_hash_ctx(&s->write_hash);
 
 	s->first_packet=0;
 
@@ -224,14 +252,15 @@
 	}
 
 /** Used to change an SSL_CTXs default SSL method type */
-int SSL_CTX_set_ssl_version(SSL_CTX *ctx,SSL_METHOD *meth)
+int SSL_CTX_set_ssl_version(SSL_CTX *ctx,const SSL_METHOD *meth)
 	{
 	STACK_OF(SSL_CIPHER) *sk;
 
 	ctx->method=meth;
 
 	sk=ssl_create_cipher_list(ctx->method,&(ctx->cipher_list),
-		&(ctx->cipher_list_by_id),SSL_DEFAULT_CIPHER_LIST);
+		&(ctx->cipher_list_by_id),
+		meth->version == SSL2_VERSION ? "SSLv2" : SSL_DEFAULT_CIPHER_LIST);
 	if ((sk == NULL) || (sk_SSL_CIPHER_num(sk) <= 0))
 		{
 		SSLerr(SSL_F_SSL_CTX_SET_SSL_VERSION,SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS);
@@ -308,6 +337,7 @@
 	s->trust = ctx->trust;
 #endif
 	s->quiet_shutdown=ctx->quiet_shutdown;
+	s->max_send_fragment = ctx->max_send_fragment;
 
 	CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX);
 	s->ctx=ctx;
@@ -324,6 +354,7 @@
 	CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX);
 	s->initial_ctx=ctx;
 #endif
+
 	s->verify_result=X509_V_OK;
 
 	s->method=ctx->method;
@@ -338,6 +369,11 @@
 
 	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data);
 
+#ifndef OPENSSL_NO_PSK
+	s->psk_client_callback=ctx->psk_client_callback;
+	s->psk_server_callback=ctx->psk_server_callback;
+#endif
+
 	return(s);
 err:
 	if (s != NULL)
@@ -425,7 +461,7 @@
 		}
 
 	CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
-	p = (SSL_SESSION *)lh_retrieve(ssl->ctx->sessions, &r);
+	p = lh_SSL_SESSION_retrieve(ssl->ctx->sessions, &r);
 	CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
 	return (p != NULL);
 	}
@@ -450,6 +486,16 @@
 	return X509_VERIFY_PARAM_set_trust(s->param, trust);
 	}
 
+int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm)
+	{
+	return X509_VERIFY_PARAM_set1(ctx->param, vpm);
+	}
+
+int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm)
+	{
+	return X509_VERIFY_PARAM_set1(ssl->param, vpm);
+	}
+
 void SSL_free(SSL *s)
 	{
 	int i;
@@ -504,6 +550,8 @@
 		}
 
 	ssl_clear_cipher_ctx(s);
+	ssl_clear_hash_ctx(&s->read_hash);
+	ssl_clear_hash_ctx(&s->write_hash);
 
 	if (s->cert != NULL) ssl_cert_free(s->cert);
 	/* Free up if allocated */
@@ -512,6 +560,11 @@
 	if (s->tlsext_hostname)
 		OPENSSL_free(s->tlsext_hostname);
 	if (s->initial_ctx) SSL_CTX_free(s->initial_ctx);
+#ifndef OPENSSL_NO_EC
+	if (s->tlsext_ecpointformatlist) OPENSSL_free(s->tlsext_ecpointformatlist);
+	if (s->tlsext_ellipticcurvelist) OPENSSL_free(s->tlsext_ellipticcurvelist);
+#endif /* OPENSSL_NO_EC */
+	if (s->tlsext_opaque_prf_input) OPENSSL_free(s->tlsext_opaque_prf_input);
 	if (s->tlsext_ocsp_exts)
 		sk_X509_EXTENSION_pop_free(s->tlsext_ocsp_exts,
 						X509_EXTENSION_free);
@@ -520,6 +573,7 @@
 	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);
 
@@ -844,7 +898,7 @@
 		}
 	if (ssl->cert == NULL)
 		{
-                SSLerr(SSL_F_SSL_CHECK_PRIVATE_KEY,SSL_R_NO_CERTIFICATE_ASSIGNED);
+		SSLerr(SSL_F_SSL_CHECK_PRIVATE_KEY,SSL_R_NO_CERTIFICATE_ASSIGNED);
 		return 0;
 		}
 	if (ssl->cert->key->x509 == NULL)
@@ -1007,6 +1061,11 @@
 			return larg;
 			}
 		return 0;
+	case SSL_CTRL_SET_MAX_SEND_FRAGMENT:
+		if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH)
+			return 0;
+		s->max_send_fragment = larg;
+		return 1;
 	case SSL_CTRL_GET_RI_SUPPORT:
 		if (s->s3)
 			return s->s3->send_connection_binding;
@@ -1029,7 +1088,7 @@
 		}
 	}
 
-struct lhash_st *SSL_CTX_sessions(SSL_CTX *ctx)
+LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx)
 	{
 	return ctx->sessions;
 	}
@@ -1072,7 +1131,7 @@
 		return(ctx->session_cache_mode);
 
 	case SSL_CTRL_SESS_NUMBER:
-		return(ctx->sessions->num_items);
+		return(lh_SSL_SESSION_num_items(ctx->sessions));
 	case SSL_CTRL_SESS_CONNECT:
 		return(ctx->stats.sess_connect);
 	case SSL_CTRL_SESS_CONNECT_GOOD:
@@ -1103,6 +1162,11 @@
 		return(ctx->mode|=larg);
 	case SSL_CTRL_CLEAR_MODE:
 		return(ctx->mode&=~larg);
+	case SSL_CTRL_SET_MAX_SEND_FRAGMENT:
+		if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH)
+			return 0;
+		ctx->max_send_fragment = larg;
+		return 1;
 	default:
 		return(ctx->method->ssl_ctx_ctrl(ctx,cmd,larg,parg));
 		}
@@ -1207,8 +1271,8 @@
 	/* ssl_create_cipher_list may return an empty stack if it
 	 * was unable to find a cipher matching the given rule string
 	 * (for example if the rule string specifies a cipher which
-	 * has been disabled). This is not an error as far as 
-	 * ssl_create_cipher_list is concerned, and hence 
+	 * has been disabled). This is not an error as far as
+	 * ssl_create_cipher_list is concerned, and hence
 	 * ctx->cipher_list and ctx->cipher_list_by_id has been
 	 * updated. */
 	if (sk == NULL)
@@ -1276,13 +1340,13 @@
 	}
 
 int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p,
-                             int (*put_cb)(const SSL_CIPHER *, unsigned char *))
+			     int (*put_cb)(const SSL_CIPHER *, unsigned char *))
 	{
 	int i,j=0;
 	SSL_CIPHER *c;
 	unsigned char *q;
 #ifndef OPENSSL_NO_KRB5
-        int nokrb5 = !kssl_tgt_is_available(s->kssl_ctx);
+	int nokrb5 = !kssl_tgt_is_available(s->kssl_ctx);
 #endif /* OPENSSL_NO_KRB5 */
 
 	if (sk == NULL) return(0);
@@ -1292,10 +1356,16 @@
 		{
 		c=sk_SSL_CIPHER_value(sk,i);
 #ifndef OPENSSL_NO_KRB5
-                if ((c->algorithms & SSL_KRB5) && nokrb5)
-                    continue;
-#endif /* OPENSSL_NO_KRB5 */                    
-
+		if (((c->algorithm_mkey & SSL_kKRB5) || (c->algorithm_auth & SSL_aKRB5)) &&
+		    nokrb5)
+		    continue;
+#endif /* OPENSSL_NO_KRB5 */
+#ifndef OPENSSL_NO_PSK
+		/* with PSK there must be client callback set */
+		if (((c->algorithm_mkey & SSL_kPSK) || (c->algorithm_auth & SSL_aPSK)) &&
+		    s->psk_client_callback == NULL)
+			continue;
+#endif /* OPENSSL_NO_PSK */
 		j = put_cb ? put_cb(c,p) : ssl_put_cipher_by_char(s,c,p);
 		p+=j;
 		}
@@ -1306,7 +1376,7 @@
 		{
 		static SSL_CIPHER scsv =
 			{
-			0, NULL, SSL3_CK_SCSV, 0, 0, 0, 0, 0, 0, 0,
+			0, NULL, SSL3_CK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0
 			};
 		j = put_cb ? put_cb(&scsv,p) : ssl_put_cipher_by_char(s,&scsv,p);
 		p+=j;
@@ -1321,7 +1391,7 @@
 STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num,
 					       STACK_OF(SSL_CIPHER) **skp)
 	{
-	SSL_CIPHER *c;
+	const SSL_CIPHER *c;
 	STACK_OF(SSL_CIPHER) *sk;
 	int i,n;
 	if (s->s3)
@@ -1384,6 +1454,7 @@
 	return(NULL);
 	}
 
+
 #ifndef OPENSSL_NO_TLSEXT
 /** return a servername extension value if provided in Client Hello, or NULL.
  * So far, only host_name types are defined (RFC 3546).
@@ -1407,7 +1478,7 @@
 	}
 #endif
 
-unsigned long SSL_SESSION_hash(const SSL_SESSION *a)
+static unsigned long ssl_session_hash(const SSL_SESSION *a)
 	{
 	unsigned long l;
 
@@ -1424,7 +1495,7 @@
  * SSL_CTX_has_matching_session_id() is checked accordingly. It relies on being
  * able to construct an SSL_SESSION that will collide with any existing session
  * with a matching session ID. */
-int SSL_SESSION_cmp(const SSL_SESSION *a,const SSL_SESSION *b)
+static int ssl_session_cmp(const SSL_SESSION *a,const SSL_SESSION *b)
 	{
 	if (a->ssl_version != b->ssl_version)
 		return(1);
@@ -1437,27 +1508,19 @@
  * SSL_SESSION_hash and SSL_SESSION_cmp for void* types and casting each
  * variable. The reason is that the functions aren't static, they're exposed via
  * ssl.h. */
-static IMPLEMENT_LHASH_HASH_FN(SSL_SESSION_hash, SSL_SESSION *)
-static IMPLEMENT_LHASH_COMP_FN(SSL_SESSION_cmp, SSL_SESSION *)
+static IMPLEMENT_LHASH_HASH_FN(ssl_session, SSL_SESSION)
+static IMPLEMENT_LHASH_COMP_FN(ssl_session, SSL_SESSION)
 
-SSL_CTX *SSL_CTX_new(SSL_METHOD *meth)
+SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
 	{
 	SSL_CTX *ret=NULL;
-	
+
 	if (meth == NULL)
 		{
 		SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_NULL_SSL_METHOD_PASSED);
 		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);
@@ -1520,15 +1583,14 @@
 	ret->app_gen_cookie_cb=0;
 	ret->app_verify_cookie_cb=0;
 
-	ret->sessions=lh_new(LHASH_HASH_FN(SSL_SESSION_hash),
-			LHASH_COMP_FN(SSL_SESSION_cmp));
+	ret->sessions=lh_SSL_SESSION_new();
 	if (ret->sessions == NULL) goto err;
 	ret->cert_store=X509_STORE_new();
 	if (ret->cert_store == NULL) goto err;
 
 	ssl_create_cipher_list(ret->method,
 		&ret->cipher_list,&ret->cipher_list_by_id,
-		SSL_DEFAULT_CIPHER_LIST);
+		meth->version == SSL2_VERSION ? "SSLv2" : SSL_DEFAULT_CIPHER_LIST);
 	if (ret->cipher_list == NULL
 	    || sk_SSL_CIPHER_num(ret->cipher_list) <= 0)
 		{
@@ -1564,6 +1626,8 @@
 	ret->extra_certs=NULL;
 	ret->comp_methods=SSL_COMP_get_compression_methods();
 
+	ret->max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH;
+
 #ifndef OPENSSL_NO_TLSEXT
 	ret->tlsext_servername_callback = 0;
 	ret->tlsext_servername_arg = NULL;
@@ -1577,7 +1641,29 @@
 	ret->tlsext_status_arg = NULL;
 
 #endif
-
+#ifndef OPENSSL_NO_PSK
+	ret->psk_identity_hint=NULL;
+	ret->psk_client_callback=NULL;
+	ret->psk_server_callback=NULL;
+#endif
+#ifndef OPENSSL_NO_BUF_FREELISTS
+	ret->freelist_max_len = SSL_MAX_BUF_FREELIST_LEN_DEFAULT;
+	ret->rbuf_freelist = OPENSSL_malloc(sizeof(SSL3_BUF_FREELIST));
+	if (!ret->rbuf_freelist)
+		goto err;
+	ret->rbuf_freelist->chunklen = 0;
+	ret->rbuf_freelist->len = 0;
+	ret->rbuf_freelist->head = NULL;
+	ret->wbuf_freelist = OPENSSL_malloc(sizeof(SSL3_BUF_FREELIST));
+	if (!ret->wbuf_freelist)
+		{
+		OPENSSL_free(ret->rbuf_freelist);
+		goto err;
+		}
+	ret->wbuf_freelist->chunklen = 0;
+	ret->wbuf_freelist->len = 0;
+	ret->wbuf_freelist->head = NULL;
+#endif
 #ifndef OPENSSL_NO_ENGINE
 	ret->client_cert_engine = NULL;
 #ifdef OPENSSL_SSL_CLIENT_ENGINE_AUTO
@@ -1616,6 +1702,20 @@
     { OPENSSL_free(comp); }
 #endif
 
+#ifndef OPENSSL_NO_BUF_FREELISTS
+static void
+ssl_buf_freelist_free(SSL3_BUF_FREELIST *list)
+	{
+	SSL3_BUF_FREELIST_ENTRY *ent, *next;
+	for (ent = list->head; ent; ent = next)
+		{
+		next = ent->next;
+		OPENSSL_free(ent);
+		}
+	OPENSSL_free(list);
+	}
+#endif
+
 void SSL_CTX_free(SSL_CTX *a)
 	{
 	int i;
@@ -1653,7 +1753,7 @@
 	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_CTX, a, &a->ex_data);
 
 	if (a->sessions != NULL)
-		lh_free(a->sessions);
+		lh_SSL_SESSION_free(a->sessions);
 
 	if (a->cert_store != NULL)
 		X509_STORE_free(a->cert_store);
@@ -1673,10 +1773,23 @@
 #else
 	a->comp_methods = NULL;
 #endif
+
+#ifndef OPENSSL_NO_PSK
+	if (a->psk_identity_hint)
+		OPENSSL_free(a->psk_identity_hint);
+#endif
 #ifndef OPENSSL_NO_ENGINE
 	if (a->client_cert_engine)
 		ENGINE_finish(a->client_cert_engine);
 #endif
+
+#ifndef OPENSSL_NO_BUF_FREELISTS
+	if (a->wbuf_freelist)
+		ssl_buf_freelist_free(a->wbuf_freelist);
+	if (a->rbuf_freelist)
+		ssl_buf_freelist_free(a->rbuf_freelist);
+#endif
+
 	OPENSSL_free(a);
 	}
 
@@ -1707,13 +1820,13 @@
 	X509_VERIFY_PARAM_set_depth(ctx->param, depth);
 	}
 
-void ssl_set_cert_masks(CERT *c, SSL_CIPHER *cipher)
+void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher)
 	{
 	CERT_PKEY *cpk;
 	int rsa_enc,rsa_tmp,rsa_sign,dh_tmp,dh_rsa,dh_dsa,dsa_sign;
 	int rsa_enc_export,dh_rsa_export,dh_dsa_export;
 	int rsa_tmp_export,dh_tmp_export,kl;
-	unsigned long mask,emask;
+	unsigned long mask_k,mask_a,emask_k,emask_a;
 	int have_ecc_cert, ecdh_ok, ecdsa_ok, ecc_pkey_size;
 #ifndef OPENSSL_NO_ECDH
 	int have_ecdh_tmp;
@@ -1760,60 +1873,77 @@
 	dh_dsa_export=(dh_dsa && EVP_PKEY_size(cpk->privatekey)*8 <= kl);
 	cpk= &(c->pkeys[SSL_PKEY_ECC]);
 	have_ecc_cert= (cpk->x509 != NULL && cpk->privatekey != NULL);
-	mask=0;
-	emask=0;
+	mask_k=0;
+	mask_a=0;
+	emask_k=0;
+	emask_a=0;
+
+	
 
 #ifdef CIPHER_DEBUG
-	printf("rt=%d rte=%d dht=%d re=%d ree=%d rs=%d ds=%d dhr=%d dhd=%d\n",
-		rsa_tmp,rsa_tmp_export,dh_tmp,
+	printf("rt=%d rte=%d dht=%d ecdht=%d re=%d ree=%d rs=%d ds=%d dhr=%d dhd=%d\n",
+	        rsa_tmp,rsa_tmp_export,dh_tmp,have_ecdh_tmp,
 		rsa_enc,rsa_enc_export,rsa_sign,dsa_sign,dh_rsa,dh_dsa);
 #endif
+	
+	cpk = &(c->pkeys[SSL_PKEY_GOST01]);
+	if (cpk->x509 != NULL && cpk->privatekey !=NULL) {
+		mask_k |= SSL_kGOST;
+		mask_a |= SSL_aGOST01;
+	}
+	cpk = &(c->pkeys[SSL_PKEY_GOST94]);
+	if (cpk->x509 != NULL && cpk->privatekey !=NULL) {
+		mask_k |= SSL_kGOST;
+		mask_a |= SSL_aGOST94;
+	}
 
 	if (rsa_enc || (rsa_tmp && rsa_sign))
-		mask|=SSL_kRSA;
+		mask_k|=SSL_kRSA;
 	if (rsa_enc_export || (rsa_tmp_export && (rsa_sign || rsa_enc)))
-		emask|=SSL_kRSA;
+		emask_k|=SSL_kRSA;
 
 #if 0
 	/* The match needs to be both kEDH and aRSA or aDSA, so don't worry */
-	if (	(dh_tmp || dh_rsa || dh_dsa) && 
+	if (	(dh_tmp || dh_rsa || dh_dsa) &&
 		(rsa_enc || rsa_sign || dsa_sign))
-		mask|=SSL_kEDH;
+		mask_k|=SSL_kEDH;
 	if ((dh_tmp_export || dh_rsa_export || dh_dsa_export) &&
 		(rsa_enc || rsa_sign || dsa_sign))
-		emask|=SSL_kEDH;
+		emask_k|=SSL_kEDH;
 #endif
 
-	if (dh_tmp_export) 
-		emask|=SSL_kEDH;
+	if (dh_tmp_export)
+		emask_k|=SSL_kEDH;
 
 	if (dh_tmp)
-		mask|=SSL_kEDH;
+		mask_k|=SSL_kEDH;
 
-	if (dh_rsa) mask|=SSL_kDHr;
-	if (dh_rsa_export) emask|=SSL_kDHr;
+	if (dh_rsa) mask_k|=SSL_kDHr;
+	if (dh_rsa_export) emask_k|=SSL_kDHr;
 
-	if (dh_dsa) mask|=SSL_kDHd;
-	if (dh_dsa_export) emask|=SSL_kDHd;
+	if (dh_dsa) mask_k|=SSL_kDHd;
+	if (dh_dsa_export) emask_k|=SSL_kDHd;
 
 	if (rsa_enc || rsa_sign)
 		{
-		mask|=SSL_aRSA;
-		emask|=SSL_aRSA;
+		mask_a|=SSL_aRSA;
+		emask_a|=SSL_aRSA;
 		}
 
 	if (dsa_sign)
 		{
-		mask|=SSL_aDSS;
-		emask|=SSL_aDSS;
+		mask_a|=SSL_aDSS;
+		emask_a|=SSL_aDSS;
 		}
 
-	mask|=SSL_aNULL;
-	emask|=SSL_aNULL;
+	mask_a|=SSL_aNULL;
+	emask_a|=SSL_aNULL;
 
 #ifndef OPENSSL_NO_KRB5
-	mask|=SSL_kKRB5|SSL_aKRB5;
-	emask|=SSL_kKRB5|SSL_aKRB5;
+	mask_k|=SSL_kKRB5;
+	mask_a|=SSL_aKRB5;
+	emask_k|=SSL_kKRB5;
+	emask_a|=SSL_aKRB5;
 #endif
 
 	/* An ECC certificate may be usable for ECDH and/or
@@ -1821,7 +1951,7 @@
 	 */
 	if (have_ecc_cert)
 		{
-                /* This call populates extension flags (ex_flags) */
+		/* This call populates extension flags (ex_flags) */
 		x = (c->pkeys[SSL_PKEY_ECC]).x509;
 		X509_check_purpose(x, -1, 0);
 		ecdh_ok = (x->ex_flags & EXFLAG_KUSAGE) ?
@@ -1829,7 +1959,7 @@
 		ecdsa_ok = (x->ex_flags & EXFLAG_KUSAGE) ?
 		    (x->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE) : 1;
 		ecc_pkey = X509_get_pubkey(x);
-		ecc_pkey_size = (ecc_pkey != NULL) ? 
+		ecc_pkey_size = (ecc_pkey != NULL) ?
 		    EVP_PKEY_bits(ecc_pkey) : 0;
 		EVP_PKEY_free(ecc_pkey);
 		if ((x->sig_alg) && (x->sig_alg->algorithm))
@@ -1837,27 +1967,41 @@
 #ifndef OPENSSL_NO_ECDH
 		if (ecdh_ok)
 			{
-			if ((signature_nid == NID_md5WithRSAEncryption) ||
-			    (signature_nid == NID_md4WithRSAEncryption) ||
-			    (signature_nid == NID_md2WithRSAEncryption))
+			const char *sig = OBJ_nid2ln(signature_nid);
+			if (sig == NULL)
 				{
-				mask|=SSL_kECDH|SSL_aRSA;
-				if (ecc_pkey_size <= 163)
-					emask|=SSL_kECDH|SSL_aRSA;
+				ERR_clear_error();
+				sig = "unknown";
 				}
+				
+			if (strstr(sig, "WithRSA"))
+				{
+				mask_k|=SSL_kECDHr;
+				mask_a|=SSL_aECDH;
+				if (ecc_pkey_size <= 163)
+					{
+					emask_k|=SSL_kECDHr;
+					emask_a|=SSL_aECDH;
+					}
+				}
+
 			if (signature_nid == NID_ecdsa_with_SHA1)
 				{
-				mask|=SSL_kECDH|SSL_aECDSA;
+				mask_k|=SSL_kECDHe;
+				mask_a|=SSL_aECDH;
 				if (ecc_pkey_size <= 163)
-					emask|=SSL_kECDH|SSL_aECDSA;
+					{
+					emask_k|=SSL_kECDHe;
+					emask_a|=SSL_aECDH;
+					}
 				}
 			}
 #endif
 #ifndef OPENSSL_NO_ECDSA
 		if (ecdsa_ok)
 			{
-			mask|=SSL_aECDSA;
-			emask|=SSL_aECDSA;
+			mask_a|=SSL_aECDSA;
+			emask_a|=SSL_aECDSA;
 			}
 #endif
 		}
@@ -1865,12 +2009,22 @@
 #ifndef OPENSSL_NO_ECDH
 	if (have_ecdh_tmp)
 		{
-		mask|=SSL_kECDHE;
-		emask|=SSL_kECDHE;
+		mask_k|=SSL_kEECDH;
+		emask_k|=SSL_kEECDH;
 		}
 #endif
-	c->mask=mask;
-	c->export_mask=emask;
+
+#ifndef OPENSSL_NO_PSK
+	mask_k |= SSL_kPSK;
+	mask_a |= SSL_aPSK;
+	emask_k |= SSL_kPSK;
+	emask_a |= SSL_aPSK;
+#endif
+
+	c->mask_k=mask_k;
+	c->mask_a=mask_a;
+	c->export_mask_k=emask_k;
+	c->export_mask_a=emask_a;
 	c->valid=1;
 	}
 
@@ -1878,13 +2032,18 @@
 #define ku_reject(x, usage) \
 	(((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage)))
 
-int check_srvr_ecc_cert_and_alg(X509 *x, SSL_CIPHER *cs)
+#ifndef OPENSSL_NO_EC
+
+int ssl_check_srvr_ecc_cert_and_alg(X509 *x, const SSL_CIPHER *cs)
 	{
-	unsigned long alg = cs->algorithms;
+	unsigned long alg_k, alg_a;
 	EVP_PKEY *pkey = NULL;
 	int keysize = 0;
 	int signature_nid = 0;
 
+	alg_k = cs->algorithm_mkey;
+	alg_a = cs->algorithm_auth;
+
 	if (SSL_C_IS_EXPORT(cs))
 		{
 		/* ECDH key length in export ciphers must be <= 163 bits */
@@ -1899,37 +2058,46 @@
 	X509_check_purpose(x, -1, 0);
 	if ((x->sig_alg) && (x->sig_alg->algorithm))
 		signature_nid = OBJ_obj2nid(x->sig_alg->algorithm);
-	if (alg & SSL_kECDH) 
+	if (alg_k & SSL_kECDHe || alg_k & SSL_kECDHr)
 		{
 		/* key usage, if present, must allow key agreement */
 		if (ku_reject(x, X509v3_KU_KEY_AGREEMENT))
 			{
+			SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG, SSL_R_ECC_CERT_NOT_FOR_KEY_AGREEMENT);
 			return 0;
 			}
-		if (alg & SSL_aECDSA) 
+		if (alg_k & SSL_kECDHe)
 			{
 			/* signature alg must be ECDSA */
 			if (signature_nid != NID_ecdsa_with_SHA1)
 				{
+				SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG, SSL_R_ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE);
 				return 0;
 				}
 			}
-		if (alg & SSL_aRSA)
+		if (alg_k & SSL_kECDHr)
 			{
 			/* signature alg must be RSA */
-			if ((signature_nid != NID_md5WithRSAEncryption) &&
-			    (signature_nid != NID_md4WithRSAEncryption) &&
-			    (signature_nid != NID_md2WithRSAEncryption))
+
+			const char *sig = OBJ_nid2ln(signature_nid);
+			if (sig == NULL)
 				{
+				ERR_clear_error();
+				sig = "unknown";
+				}
+			if (strstr(sig, "WithRSA") == NULL)
+				{
+				SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG, SSL_R_ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE);
 				return 0;
 				}
 			}
-		} 
-	else if (alg & SSL_aECDSA)
+		}
+	if (alg_a & SSL_aECDSA)
 		{
 		/* key usage, if present, must allow signing */
 		if (ku_reject(x, X509v3_KU_DIGITAL_SIGNATURE))
 			{
+			SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG, SSL_R_ECC_CERT_NOT_FOR_SIGNING);
 			return 0;
 			}
 		}
@@ -1937,58 +2105,74 @@
 	return 1;  /* all checks are ok */
 	}
 
+#endif
+
 /* THIS NEEDS CLEANING UP */
 X509 *ssl_get_server_send_cert(SSL *s)
 	{
-	unsigned long alg,mask,kalg;
+	unsigned long alg_k,alg_a,mask_k,mask_a;
 	CERT *c;
 	int i,is_export;
 
 	c=s->cert;
 	ssl_set_cert_masks(c, s->s3->tmp.new_cipher);
-	alg=s->s3->tmp.new_cipher->algorithms;
 	is_export=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher);
-	mask=is_export?c->export_mask:c->mask;
-	kalg=alg&(SSL_MKEY_MASK|SSL_AUTH_MASK);
-
-	if (kalg & SSL_kECDH)
+	if (is_export)
 		{
-		/* we don't need to look at SSL_kECDHE 
+		mask_k = c->export_mask_k;
+		mask_a = c->export_mask_a;
+		}
+	else
+		{
+		mask_k = c->mask_k;
+		mask_a = c->mask_a;
+		}
+	
+	alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+	alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+
+	if (alg_k & (SSL_kECDHr|SSL_kECDHe))
+		{
+		/* we don't need to look at SSL_kEECDH
 		 * since no certificate is needed for
 		 * anon ECDH and for authenticated
-		 * ECDHE, the check for the auth 
+		 * EECDH, the check for the auth
 		 * algorithm will set i correctly
 		 * NOTE: For ECDH-RSA, we need an ECC
-		 * not an RSA cert but for ECDHE-RSA
+		 * not an RSA cert but for EECDH-RSA
 		 * we need an RSA cert. Placing the
 		 * checks for SSL_kECDH before RSA
 		 * checks ensures the correct cert is chosen.
 		 */
 		i=SSL_PKEY_ECC;
 		}
-	else if (kalg & SSL_aECDSA)
+	else if (alg_a & SSL_aECDSA)
 		{
 		i=SSL_PKEY_ECC;
 		}
-	else if (kalg & SSL_kDHr)
+	else if (alg_k & SSL_kDHr)
 		i=SSL_PKEY_DH_RSA;
-	else if (kalg & SSL_kDHd)
+	else if (alg_k & SSL_kDHd)
 		i=SSL_PKEY_DH_DSA;
-	else if (kalg & SSL_aDSS)
+	else if (alg_a & SSL_aDSS)
 		i=SSL_PKEY_DSA_SIGN;
-	else if (kalg & SSL_aRSA)
+	else if (alg_a & SSL_aRSA)
 		{
 		if (c->pkeys[SSL_PKEY_RSA_ENC].x509 == NULL)
 			i=SSL_PKEY_RSA_SIGN;
 		else
 			i=SSL_PKEY_RSA_ENC;
 		}
-	else if (kalg & SSL_aKRB5)
+	else if (alg_a & SSL_aKRB5)
 		{
 		/* VRS something else here? */
 		return(NULL);
 		}
-	else /* if (kalg & SSL_aNULL) */
+	else if (alg_a & SSL_aGOST94) 
+		i=SSL_PKEY_GOST94;
+	else if (alg_a & SSL_aGOST01)
+		i=SSL_PKEY_GOST01;
+	else /* if (alg_a & SSL_aNULL) */
 		{
 		SSLerr(SSL_F_SSL_GET_SERVER_SEND_CERT,ERR_R_INTERNAL_ERROR);
 		return(NULL);
@@ -1998,18 +2182,18 @@
 	return(c->pkeys[i].x509);
 	}
 
-EVP_PKEY *ssl_get_sign_pkey(SSL *s,SSL_CIPHER *cipher)
+EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *cipher)
 	{
-	unsigned long alg;
+	unsigned long alg_a;
 	CERT *c;
 
-	alg=cipher->algorithms;
+	alg_a = cipher->algorithm_auth;
 	c=s->cert;
 
-	if ((alg & SSL_aDSS) &&
+	if ((alg_a & SSL_aDSS) &&
 		(c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL))
 		return(c->pkeys[SSL_PKEY_DSA_SIGN].privatekey);
-	else if (alg & SSL_aRSA)
+	else if (alg_a & SSL_aRSA)
 		{
 		if (c->pkeys[SSL_PKEY_RSA_SIGN].privatekey != NULL)
 			return(c->pkeys[SSL_PKEY_RSA_SIGN].privatekey);
@@ -2018,10 +2202,10 @@
 		else
 			return(NULL);
 		}
-	else if ((alg & SSL_aECDSA) &&
+	else if ((alg_a & SSL_aECDSA) &&
 	         (c->pkeys[SSL_PKEY_ECC].privatekey != NULL))
 		return(c->pkeys[SSL_PKEY_ECC].privatekey);
-	else /* if (alg & SSL_aNULL) */
+	else /* if (alg_a & SSL_aNULL) */
 		{
 		SSLerr(SSL_F_SSL_GET_SIGN_PKEY,ERR_R_INTERNAL_ERROR);
 		return(NULL);
@@ -2036,14 +2220,14 @@
 	 * and it would be rather hard to do anyway :-) */
 	if (s->session->session_id_length == 0) return;
 
-	i=s->ctx->session_cache_mode;
+	i=s->session_ctx->session_cache_mode;
 	if ((i & mode) && (!s->hit)
 		&& ((i & SSL_SESS_CACHE_NO_INTERNAL_STORE)
-		    || SSL_CTX_add_session(s->ctx,s->session))
-		&& (s->ctx->new_session_cb != NULL))
+		    || SSL_CTX_add_session(s->session_ctx,s->session))
+		&& (s->session_ctx->new_session_cb != NULL))
 		{
 		CRYPTO_add(&s->session->references,1,CRYPTO_LOCK_SSL_SESSION);
-		if (!s->ctx->new_session_cb(s,s->session))
+		if (!s->session_ctx->new_session_cb(s,s->session))
 			SSL_SESSION_free(s->session);
 		}
 
@@ -2052,20 +2236,20 @@
 		((i & mode) == mode))
 		{
 		if (  (((mode & SSL_SESS_CACHE_CLIENT)
-			?s->ctx->stats.sess_connect_good
-			:s->ctx->stats.sess_accept_good) & 0xff) == 0xff)
+			?s->session_ctx->stats.sess_connect_good
+			:s->session_ctx->stats.sess_accept_good) & 0xff) == 0xff)
 			{
-			SSL_CTX_flush_sessions(s->ctx,(unsigned long)time(NULL));
+			SSL_CTX_flush_sessions(s->session_ctx,(unsigned long)time(NULL));
 			}
 		}
 	}
 
-SSL_METHOD *SSL_get_ssl_method(SSL *s)
+const SSL_METHOD *SSL_get_ssl_method(SSL *s)
 	{
 	return(s->method);
 	}
 
-int SSL_set_ssl_method(SSL *s,SSL_METHOD *meth)
+int SSL_set_ssl_method(SSL *s, const SSL_METHOD *meth)
 	{
 	int conn= -1;
 	int ret=1;
@@ -2208,6 +2392,8 @@
 	s->handshake_func=s->method->ssl_accept;
 	/* clear the current cipher */
 	ssl_clear_cipher_ctx(s);
+	ssl_clear_hash_ctx(&s->read_hash);
+	ssl_clear_hash_ctx(&s->write_hash);
 	}
 
 void SSL_set_connect_state(SSL *s)
@@ -2218,6 +2404,8 @@
 	s->handshake_func=s->method->ssl_connect;
 	/* clear the current cipher */
 	ssl_clear_cipher_ctx(s);
+	ssl_clear_hash_ctx(&s->read_hash);
+	ssl_clear_hash_ctx(&s->write_hash);
 	}
 
 int ssl_undefined_function(SSL *s)
@@ -2262,7 +2450,7 @@
 	X509_NAME *xn;
 	SSL *ret;
 	int i;
-		 
+	
 	if ((ret=SSL_new(SSL_get_SSL_CTX(s))) == NULL)
 	    return(NULL);
 
@@ -2432,7 +2620,7 @@
 		return(NULL);
 	}
 
-SSL_CIPHER *SSL_get_current_cipher(const SSL *s)
+const SSL_CIPHER *SSL_get_current_cipher(const SSL *s)
 	{
 	if ((s->session != NULL) && (s->session->cipher != NULL))
 		return(s->session->cipher);
@@ -2510,7 +2698,7 @@
 		s->wbio=BIO_pop(s->wbio);
 #ifdef REF_CHECK /* not the usual REF_CHECK, but this avoids adding one more preprocessor symbol */
 		assert(s->wbio != NULL);
-#endif	
+#endif
 	}
 	BIO_free(s->bbio);
 	s->bbio=NULL;
@@ -2595,7 +2783,7 @@
 
 /* One compiler (Diab DCC) doesn't like argument names in returned
    function pointer.  */
-void (*SSL_get_info_callback(const SSL *ssl))(const SSL * /*ssl*/,int /*type*/,int /*val*/) 
+void (*SSL_get_info_callback(const SSL *ssl))(const SSL * /*ssl*/,int /*type*/,int /*val*/)
 	{
 	return ssl->info_callback;
 	}
@@ -2716,13 +2904,13 @@
 
 #ifndef OPENSSL_NO_DH
 void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,DH *(*dh)(SSL *ssl,int is_export,
-							int keylength))
+                                                        int keylength))
 	{
 	SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TMP_DH_CB,(void (*)(void))dh);
 	}
 
 void SSL_set_tmp_dh_callback(SSL *ssl,DH *(*dh)(SSL *ssl,int is_export,
-						int keylength))
+                                                int keylength))
 	{
 	SSL_callback_ctrl(ssl,SSL_CTRL_SET_TMP_DH_CB,(void (*)(void))dh);
 	}
@@ -2730,18 +2918,109 @@
 
 #ifndef OPENSSL_NO_ECDH
 void SSL_CTX_set_tmp_ecdh_callback(SSL_CTX *ctx,EC_KEY *(*ecdh)(SSL *ssl,int is_export,
-							int keylength))
+                                                                int keylength))
 	{
 	SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TMP_ECDH_CB,(void (*)(void))ecdh);
 	}
 
 void SSL_set_tmp_ecdh_callback(SSL *ssl,EC_KEY *(*ecdh)(SSL *ssl,int is_export,
-						int keylength))
+                                                        int keylength))
 	{
 	SSL_callback_ctrl(ssl,SSL_CTRL_SET_TMP_ECDH_CB,(void (*)(void))ecdh);
 	}
 #endif
 
+#ifndef OPENSSL_NO_PSK
+int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint)
+	{
+	if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT, SSL_R_DATA_LENGTH_TOO_LONG);
+		return 0;
+		}
+	if (ctx->psk_identity_hint != NULL)
+		OPENSSL_free(ctx->psk_identity_hint);
+	if (identity_hint != NULL)
+		{
+		ctx->psk_identity_hint = BUF_strdup(identity_hint);
+		if (ctx->psk_identity_hint == NULL)
+			return 0;
+		}
+	else
+		ctx->psk_identity_hint = NULL;
+	return 1;
+	}
+
+int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint)
+	{
+	if (s == NULL)
+		return 0;
+
+	if (s->session == NULL)
+		return 1; /* session not created yet, ignored */
+
+	if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN)
+		{
+		SSLerr(SSL_F_SSL_USE_PSK_IDENTITY_HINT, SSL_R_DATA_LENGTH_TOO_LONG);
+		return 0;
+		}
+	if (s->session->psk_identity_hint != NULL)
+		OPENSSL_free(s->session->psk_identity_hint);
+	if (identity_hint != NULL)
+		{
+		s->session->psk_identity_hint = BUF_strdup(identity_hint);
+		if (s->session->psk_identity_hint == NULL)
+			return 0;
+		}
+	else
+		s->session->psk_identity_hint = NULL;
+	return 1;
+	}
+
+const char *SSL_get_psk_identity_hint(const SSL *s)
+	{
+	if (s == NULL || s->session == NULL)
+		return NULL;
+	return(s->session->psk_identity_hint);
+	}
+
+const char *SSL_get_psk_identity(const SSL *s)
+	{
+	if (s == NULL || s->session == NULL)
+		return NULL;
+	return(s->session->psk_identity);
+	}
+
+void SSL_set_psk_client_callback(SSL *s,
+    unsigned int (*cb)(SSL *ssl, const char *hint,
+                       char *identity, unsigned int max_identity_len, unsigned char *psk,
+                       unsigned int max_psk_len))
+	{
+	s->psk_client_callback = cb;
+	}
+
+void SSL_CTX_set_psk_client_callback(SSL_CTX *ctx,
+    unsigned int (*cb)(SSL *ssl, const char *hint,
+                       char *identity, unsigned int max_identity_len, unsigned char *psk,
+                       unsigned int max_psk_len))
+	{
+	ctx->psk_client_callback = cb;
+	}
+
+void SSL_set_psk_server_callback(SSL *s,
+    unsigned int (*cb)(SSL *ssl, const char *identity,
+                       unsigned char *psk, unsigned int max_psk_len))
+	{
+	s->psk_server_callback = cb;
+	}
+
+void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx,
+    unsigned int (*cb)(SSL *ssl, const char *identity,
+                       unsigned char *psk, unsigned int max_psk_len))
+	{
+	ctx->psk_server_callback = cb;
+	}
+#endif
 
 void SSL_CTX_set_msg_callback(SSL_CTX *ctx, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg))
 	{
@@ -2752,7 +3031,25 @@
 	SSL_callback_ctrl(ssl, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb);
 	}
 
+/* Allocates new EVP_MD_CTX and sets pointer to it into given pointer
+ * vairable, freeing  EVP_MD_CTX previously stored in that variable, if
+ * any. If EVP_MD pointer is passed, initializes ctx with this md
+ * Returns newly allocated ctx;
+ */
 
+EVP_MD_CTX *ssl_replace_hash(EVP_MD_CTX **hash,const EVP_MD *md) 
+{
+	ssl_clear_hash_ctx(hash);
+	*hash = EVP_MD_CTX_create();
+	if (md) EVP_DigestInit_ex(*hash,md,NULL);
+	return *hash;
+}
+void ssl_clear_hash_ctx(EVP_MD_CTX **hash) 
+{
+
+	if (*hash) EVP_MD_CTX_destroy(*hash);
+	*hash=NULL;
+}
 
 #if defined(_WINDLL) && defined(OPENSSL_SYS_WIN16)
 #include "../crypto/bio/bss_file.c"
@@ -2760,3 +3057,6 @@
 
 IMPLEMENT_STACK_OF(SSL_CIPHER)
 IMPLEMENT_STACK_OF(SSL_COMP)
+IMPLEMENT_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER,
+				    ssl_cipher_id);
+