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