Add TLS exporter.
diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c
index c3b77c8..a94290a 100644
--- a/ssl/d1_lib.c
+++ b/ssl/d1_lib.c
@@ -82,6 +82,7 @@
 	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,
+	tls1_export_keying_material,
 	};
 
 long dtls1_default_timeout(void)
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index a81c80d..3dcf50e 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -2904,6 +2904,9 @@
 	SSL3_MD_CLIENT_FINISHED_CONST,4,
 	SSL3_MD_SERVER_FINISHED_CONST,4,
 	ssl3_alert_code,
+	(int (*)(SSL *, unsigned char *, unsigned int, const char *,
+		 unsigned int, const unsigned char *, unsigned int,
+		 int use_context))ssl_undefined_function,
 	};
 
 long ssl3_default_timeout(void)
diff --git a/ssl/ssl.h b/ssl/ssl.h
index 9d46d6b..ffbe611 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -2259,6 +2259,7 @@
 #define SSL_F_TLS1_CHANGE_CIPHER_STATE			 209
 #define SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT		 274
 #define SSL_F_TLS1_ENC					 210
+#define SSL_F_TLS1_EXPORT_KEYING_MATERIAL		 312
 #define SSL_F_TLS1_PREPARE_CLIENTHELLO_TLSEXT		 275
 #define SSL_F_TLS1_PREPARE_SERVERHELLO_TLSEXT		 276
 #define SSL_F_TLS1_PRF					 284
@@ -2513,6 +2514,7 @@
 #define SSL_R_TLSV1_UNRECOGNIZED_NAME			 1112
 #define SSL_R_TLSV1_UNSUPPORTED_EXTENSION		 1110
 #define SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER	 232
+#define SSL_R_TLS_ILLEGAL_EXPORTER_LABEL		 367
 #define SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST		 157
 #define SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST 233
 #define SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG	 234
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index b899dcb..0426aaf 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -277,6 +277,7 @@
 {ERR_FUNC(SSL_F_TLS1_CHANGE_CIPHER_STATE),	"TLS1_CHANGE_CIPHER_STATE"},
 {ERR_FUNC(SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT),	"TLS1_CHECK_SERVERHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_TLS1_ENC),	"TLS1_ENC"},
+{ERR_FUNC(SSL_F_TLS1_EXPORT_KEYING_MATERIAL),	"TLS1_EXPORT_KEYING_MATERIAL"},
 {ERR_FUNC(SSL_F_TLS1_PREPARE_CLIENTHELLO_TLSEXT),	"TLS1_PREPARE_CLIENTHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_TLS1_PREPARE_SERVERHELLO_TLSEXT),	"TLS1_PREPARE_SERVERHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_TLS1_PRF),	"tls1_prf"},
@@ -534,6 +535,7 @@
 {ERR_REASON(SSL_R_TLSV1_UNRECOGNIZED_NAME),"tlsv1 unrecognized name"},
 {ERR_REASON(SSL_R_TLSV1_UNSUPPORTED_EXTENSION),"tlsv1 unsupported extension"},
 {ERR_REASON(SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER),"tls client cert req with anon cipher"},
+{ERR_REASON(SSL_R_TLS_ILLEGAL_EXPORTER_LABEL),"tls illegal exporter label"},
 {ERR_REASON(SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST),"tls invalid ecpointformat list"},
 {ERR_REASON(SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST),"tls peer did not respond with certificate list"},
 {ERR_REASON(SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG),"tls rsa encrypted value length is wrong"},
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 14664cf..df78447 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -177,7 +177,10 @@
 	0,	/* client_finished_label_len */
 	NULL,	/* server_finished_label */
 	0,	/* server_finished_label_len */
-	(int (*)(int))ssl_undefined_function
+	(int (*)(int))ssl_undefined_function,
+	(int (*)(SSL *, unsigned char *, unsigned int, const char *,
+		 unsigned int, const unsigned char *, unsigned int,
+		 int use_context))ssl_undefined_function,
 	};
 
 int SSL_clear(SSL *s)
@@ -1627,6 +1630,17 @@
 # endif
 #endif
 
+int SSL_export_keying_material(SSL *s, unsigned char *out, int olen, 
+        char *label, int llen, unsigned char *p, int plen, int use_context)
+	{
+	if (s->version < TLS1_VERSION)
+		return -1;
+
+	return s->method->ssl3_enc->export_keying_material(s, out, olen, label,
+							   llen, p, plen,
+							   use_context);
+	}
+
 static unsigned long ssl_session_hash(const SSL_SESSION *a)
 	{
 	unsigned long l;
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index e5eec19..bda365d 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -569,6 +569,10 @@
 	const char *server_finished_label;
 	int server_finished_label_len;
 	int (*alert_value)(int);
+        int (*export_keying_material)(SSL *, unsigned char *, unsigned int,
+				      const char *, unsigned int,
+				      const unsigned char *, unsigned int,
+				      int use_context);
 	} SSL3_ENC_METHOD;
 
 #ifndef OPENSSL_NO_COMP
@@ -1055,6 +1059,9 @@
 int tls1_mac(SSL *ssl, unsigned char *md, int snd);
 int tls1_generate_master_secret(SSL *s, unsigned char *out,
 	unsigned char *p, int len);
+int tls1_export_keying_material(SSL *s, unsigned char *out, unsigned int olen, 
+	const char *label, unsigned int llen, const unsigned char *p, 
+        unsigned int plen, int use_context);
 int tls1_alert_code(int code);
 int ssl3_alert_code(int code);
 int ssl_ok(SSL *s);
diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c
index 3452b25..b9d0dd3 100644
--- a/ssl/t1_enc.c
+++ b/ssl/t1_enc.c
@@ -1119,6 +1119,95 @@
 	return(SSL3_MASTER_SECRET_SIZE);
 	}
 
+int tls1_export_keying_material(SSL *s, unsigned char *out, unsigned int olen, 
+         const char *label, unsigned int llen, const unsigned char *context, 
+         unsigned int contextlen, int use_context)
+	{
+	unsigned char *buff;
+	unsigned char *val;
+	unsigned int vallen, currentvalpos, rv;
+
+#ifdef KSSL_DEBUG
+	printf ("tls1_export_keying_material(%p, %p,%d, %s,%d, %p,%d)\n", s, out,olen, label,llen, p,plen);
+#endif	/* KSSL_DEBUG */
+
+	buff = OPENSSL_malloc(olen);
+	if (buff == NULL) goto err2;
+
+	/* construct PRF arguments
+	 * we construct the PRF argument ourself rather than passing separate
+	 * values into the TLS PRF to ensure that the concatenation of values
+	 * does not create a prohibited label.
+	 */
+	vallen = llen + SSL3_RANDOM_SIZE * 2;
+        if (use_context) 
+                {
+                vallen +=  2 + contextlen;
+                }
+
+	val = OPENSSL_malloc(vallen);
+	if (val == NULL) goto err2;
+	currentvalpos = 0;
+	memcpy(val + currentvalpos, (unsigned char *) label, llen);
+	currentvalpos += llen;
+	memcpy(val + currentvalpos, s->s3->client_random, SSL3_RANDOM_SIZE);
+	currentvalpos += SSL3_RANDOM_SIZE;
+	memcpy(val + currentvalpos, s->s3->server_random, SSL3_RANDOM_SIZE);
+	currentvalpos += SSL3_RANDOM_SIZE;
+
+        if (use_context)
+                {
+                val[currentvalpos] = (contextlen << 8) & 0xff;
+                currentvalpos++;
+                val[currentvalpos] = contextlen & 0xff;
+                currentvalpos++;
+                if ((contextlen > 0) || (context != NULL)) 
+                        {
+                        memcpy(val + currentvalpos, context, contextlen);
+                        }
+                }
+
+	/* disallow prohibited labels
+	 * note that SSL3_RANDOM_SIZE > max(prohibited label len) =
+	 * 15, so size of val > max(prohibited label len) = 15 and the
+	 * comparisons won't have buffer overflow
+	 */
+	if (bcmp(val, TLS_MD_CLIENT_FINISH_CONST,
+		 TLS_MD_CLIENT_FINISH_CONST_SIZE) == 0) goto err1;
+	if (bcmp(val, TLS_MD_SERVER_FINISH_CONST,
+		 TLS_MD_SERVER_FINISH_CONST_SIZE) == 0) goto err1;
+	if (bcmp(val, TLS_MD_MASTER_SECRET_CONST,
+		 TLS_MD_MASTER_SECRET_CONST_SIZE) == 0) goto err1;
+	if (bcmp(val, TLS_MD_KEY_EXPANSION_CONST,
+		 TLS_MD_KEY_EXPANSION_CONST_SIZE) == 0) goto err1;
+
+	tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
+		val, vallen,
+		NULL, 0,
+		NULL, 0,
+		NULL, 0,
+		NULL, 0,
+		s->session->master_key,s->session->master_key_length,
+		out,buff,olen);
+
+#ifdef KSSL_DEBUG
+	printf ("tls1_export_keying_material() complete\n");
+#endif	/* KSSL_DEBUG */
+	rv = olen;
+	goto ret;
+err1:
+	SSLerr(SSL_F_TLS1_EXPORT_KEYING_MATERIAL, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL);
+	rv = 0;
+	goto ret;
+err2:
+	SSLerr(SSL_F_TLS1_EXPORT_KEYING_MATERIAL, ERR_R_MALLOC_FAILURE);
+	rv = 0;
+ret:
+	if (buff != NULL) OPENSSL_free(buff);
+	if (val != NULL) OPENSSL_free(val);
+	return(rv);
+	}
+
 int tls1_alert_code(int code)
 	{
 	switch (code)
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 473bd94..7b54dc9 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -136,6 +136,7 @@
 	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,
+	tls1_export_keying_material,
 	};
 
 long tls1_default_timeout(void)
diff --git a/ssl/tls1.h b/ssl/tls1.h
index f443bb1..545383a 100644
--- a/ssl/tls1.h
+++ b/ssl/tls1.h
@@ -262,8 +262,10 @@
 
 #define TLSEXT_MAXLEN_host_name 255
 
-const char *SSL_get_servername(const SSL *s, const int type) ;
-int SSL_get_servername_type(const SSL *s) ;
+const char *SSL_get_servername(const SSL *s, const int type);
+int SSL_get_servername_type(const SSL *s);
+int SSL_export_keying_material(SSL *s, unsigned char *out, int olen, 
+        char *label, int llen, unsigned char *p, int plen, int use_context);
 
 #define SSL_set_tlsext_host_name(s,name) \
 SSL_ctrl(s,SSL_CTRL_SET_TLSEXT_HOSTNAME,TLSEXT_NAMETYPE_host_name,(char *)name)