diff options
Diffstat (limited to 'main/openssl/ssl/s3_clnt.c')
| -rw-r--r-- | main/openssl/ssl/s3_clnt.c | 359 | 
1 files changed, 207 insertions, 152 deletions
diff --git a/main/openssl/ssl/s3_clnt.c b/main/openssl/ssl/s3_clnt.c index f71470a3..b65b12d9 100644 --- a/main/openssl/ssl/s3_clnt.c +++ b/main/openssl/ssl/s3_clnt.c @@ -345,9 +345,10 @@ int ssl3_connect(SSL *s)  				}  #endif  			/* Check if it is anon DH/ECDH */ -			/* or PSK */ +			/* or non-RSA PSK */  			if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && -			    !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) +			    !((s->s3->tmp.new_cipher->algorithm_auth & SSL_aPSK) && +			      !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kRSA)))  				{  				ret=ssl3_get_server_certificate(s);  				if (ret <= 0) goto end; @@ -1377,12 +1378,14 @@ int ssl3_get_key_exchange(SSL *s)  		   omitted if no identity hint is sent. Set  		   session->sess_cert anyway to avoid problems  		   later.*/ -		if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK) +		if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aPSK)  			{  			s->session->sess_cert=ssl_sess_cert_new(); -			if (s->ctx->psk_identity_hint) -				OPENSSL_free(s->ctx->psk_identity_hint); -			s->ctx->psk_identity_hint = NULL; +			if (s->session->psk_identity_hint) +				{ +				OPENSSL_free(s->session->psk_identity_hint); +				s->session->psk_identity_hint = NULL; +				}  			}  #endif  		s->s3->tmp.reuse_message=1; @@ -1425,52 +1428,58 @@ int ssl3_get_key_exchange(SSL *s)  	EVP_MD_CTX_init(&md_ctx);  #ifndef OPENSSL_NO_PSK -	if (alg_k & SSL_kPSK) +	if (alg_a & SSL_aPSK)  		{  		char tmp_id_hint[PSK_MAX_IDENTITY_LEN+1];  		al=SSL_AD_HANDSHAKE_FAILURE;  		n2s(p,i);  		param_len=i+2; -		/* Store PSK identity hint for later use, hint is used -		 * in ssl3_send_client_key_exchange.  Assume that the -		 * maximum length of a PSK identity hint can be as -		 * long as the maximum length of a PSK identity. */ -		if (i > PSK_MAX_IDENTITY_LEN) -			{ -			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, -				SSL_R_DATA_LENGTH_TOO_LONG); -			goto f_err; +		if (s->session->psk_identity_hint) +			{ +			OPENSSL_free(s->session->psk_identity_hint); +			s->session->psk_identity_hint = NULL;  			} -		if (param_len > n) +		if (i != 0)  			{ -			al=SSL_AD_DECODE_ERROR; -			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, -				SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH); -			goto f_err; +			/* Store PSK identity hint for later use, hint is used +			 * in ssl3_send_client_key_exchange.  Assume that the +			 * maximum length of a PSK identity hint can be as +			 * long as the maximum length of a PSK identity. */ +			if (i > PSK_MAX_IDENTITY_LEN) +				{ +				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, +					SSL_R_DATA_LENGTH_TOO_LONG); +				goto f_err; +				} +			if (param_len > n) +				{ +				al=SSL_AD_DECODE_ERROR; +				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, +					SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH); +				goto f_err; +				} +			/* If received PSK identity hint contains NULL +			 * characters, the hint is truncated from the first +			 * NULL. p may not be ending with NULL, so create a +			 * NULL-terminated string. */ +			memcpy(tmp_id_hint, p, i); +			memset(tmp_id_hint+i, 0, PSK_MAX_IDENTITY_LEN+1-i); +			s->session->psk_identity_hint = BUF_strdup(tmp_id_hint); +			if (s->session->psk_identity_hint == NULL) +				{ +				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); +				goto f_err; +				}  			} -		/* If received PSK identity hint contains NULL -		 * characters, the hint is truncated from the first -		 * NULL. p may not be ending with NULL, so create a -		 * NULL-terminated string. */ -		memcpy(tmp_id_hint, p, i); -		memset(tmp_id_hint+i, 0, PSK_MAX_IDENTITY_LEN+1-i); -		if (s->ctx->psk_identity_hint != NULL) -			OPENSSL_free(s->ctx->psk_identity_hint); -		s->ctx->psk_identity_hint = BUF_strdup(tmp_id_hint); -		if (s->ctx->psk_identity_hint == NULL) -			{ -			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); -			goto f_err; -			}	    -  		p+=i;  		n-=param_len;  		} -	else  #endif /* !OPENSSL_NO_PSK */ + +	if (0) {}  #ifndef OPENSSL_NO_SRP -	if (alg_k & SSL_kSRP) +	else if (alg_k & SSL_kSRP)  		{  		n2s(p,i);  		param_len=i+2; @@ -1547,10 +1556,9 @@ int ssl3_get_key_exchange(SSL *s)  			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_DSA_SIGN].x509);  #endif  		} -	else  #endif /* !OPENSSL_NO_SRP */  #ifndef OPENSSL_NO_RSA -	if (alg_k & SSL_kRSA) +	else if (alg_k & SSL_kRSA)  		{  		if ((rsa=RSA_new()) == NULL)  			{ @@ -1599,9 +1607,6 @@ int ssl3_get_key_exchange(SSL *s)  		s->session->sess_cert->peer_rsa_tmp=rsa;  		rsa=NULL;  		} -#else /* OPENSSL_NO_RSA */ -	if (0) -		;  #endif  #ifndef OPENSSL_NO_DH  	else if (alg_k & SSL_kEDH) @@ -1782,14 +1787,14 @@ int ssl3_get_key_exchange(SSL *s)  		EC_POINT_free(srvr_ecpoint);  		srvr_ecpoint = NULL;  		} -	else if (alg_k) +#endif /* !OPENSSL_NO_ECDH */ + +	else if (!(alg_k & SSL_kPSK))  		{  		al=SSL_AD_UNEXPECTED_MESSAGE;  		SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);  		goto f_err;  		} -#endif /* !OPENSSL_NO_ECDH */ -  	/* p points to the next byte, there are 'n' bytes left */ @@ -1894,8 +1899,9 @@ fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));  		}  	else  		{ -		if (!(alg_a & SSL_aNULL) && !(alg_k & SSL_kPSK)) -			/* aNULL or kPSK do not need public keys */ +		if (!(alg_a & SSL_aNULL) && +			/* Among PSK ciphers only RSA_PSK needs a public key */ +			!((alg_a & SSL_aPSK) && !(alg_k & SSL_kRSA)))  			{  			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);  			goto err; @@ -2297,6 +2303,7 @@ int ssl3_send_client_key_exchange(SSL *s)  	unsigned char *p,*d;  	int n;  	unsigned long alg_k; +	unsigned long alg_a;  #ifndef OPENSSL_NO_RSA  	unsigned char *q;  	EVP_PKEY *pkey=NULL; @@ -2311,7 +2318,11 @@ int ssl3_send_client_key_exchange(SSL *s)  	unsigned char *encodedPoint = NULL;  	int encoded_pt_len = 0;  	BN_CTX * bn_ctx = NULL; -#endif +#ifndef OPENSSL_NO_PSK +	unsigned int psk_len = 0; +	unsigned char psk[PSK_MAX_PSK_LEN]; +#endif /* OPENSSL_NO_PSK */ +#endif /* OPENSSL_NO_ECDH */  	if (s->state == SSL3_ST_CW_KEY_EXCH_A)  		{ @@ -2319,7 +2330,89 @@ int ssl3_send_client_key_exchange(SSL *s)  		p= &(d[4]);  		alg_k=s->s3->tmp.new_cipher->algorithm_mkey; +		alg_a=s->s3->tmp.new_cipher->algorithm_auth; + +#ifndef OPENSSL_NO_PSK +		if (alg_a & SSL_aPSK) +			{ +			char identity[PSK_MAX_IDENTITY_LEN + 1]; +			size_t identity_len; +			unsigned char *t = NULL; +			unsigned char pre_ms[PSK_MAX_PSK_LEN*2+4]; +			unsigned int pre_ms_len = 0; +			int psk_err = 1; + +			n = 0; +			if (s->psk_client_callback == NULL) +				{ +				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, +					SSL_R_PSK_NO_CLIENT_CB); +				goto err; +				} + +			memset(identity, 0, sizeof(identity)); +			psk_len = s->psk_client_callback(s, s->session->psk_identity_hint, +				identity, sizeof(identity), psk, sizeof(psk)); +			if (psk_len > PSK_MAX_PSK_LEN) +				{ +				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, +					ERR_R_INTERNAL_ERROR); +				goto psk_err; +				} +			else if (psk_len == 0) +				{ +				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, +					SSL_R_PSK_IDENTITY_NOT_FOUND); +				goto psk_err; +				} +			identity_len = strnlen(identity, sizeof(identity)); +			if (identity_len > PSK_MAX_IDENTITY_LEN) +				{ +				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, +					ERR_R_INTERNAL_ERROR); +				goto psk_err; +				} +			if (!(alg_k & SSL_kEECDH)) +				{ +				/* Create the shared secret now if we're not using ECDHE-PSK.*/ +				pre_ms_len = 2+psk_len+2+psk_len; +				t = pre_ms; +				s2n(psk_len, t); +				memset(t, 0, psk_len); +				t+=psk_len; +				s2n(psk_len, t); +				memcpy(t, psk, psk_len); + +				s->session->master_key_length = +					s->method->ssl3_enc->generate_master_secret(s, +						s->session->master_key, +						pre_ms, pre_ms_len); +				s2n(identity_len, p); +				memcpy(p, identity, identity_len); +				n = 2 + identity_len; +				} + +			if (s->session->psk_identity != NULL) +				OPENSSL_free(s->session->psk_identity); +			s->session->psk_identity = BUF_strdup(identity); +			if (s->session->psk_identity == NULL) +				{ +				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, +					ERR_R_MALLOC_FAILURE); +				goto psk_err; +				} +			psk_err = 0; +		psk_err: +			OPENSSL_cleanse(identity, PSK_MAX_IDENTITY_LEN); +			OPENSSL_cleanse(pre_ms, sizeof(pre_ms)); +			if (psk_err != 0) +				{ +				ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); +				goto err; +				} +			} +#endif  		/* Fool emacs indentation */  		if (0) {}  #ifndef OPENSSL_NO_RSA @@ -2580,14 +2673,19 @@ int ssl3_send_client_key_exchange(SSL *s)  			/* perhaps clean things up a bit EAY EAY EAY EAY*/  			}  #endif - -#ifndef OPENSSL_NO_ECDH  +#ifndef OPENSSL_NO_ECDH  		else if (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe))  			{  			const EC_GROUP *srvr_group = NULL;  			EC_KEY *tkey;  			int ecdh_clnt_cert = 0;  			int field_size = 0; +#ifndef OPENSSL_NO_PSK +			unsigned char *pre_ms; +			unsigned char *t; +			unsigned int pre_ms_len; +			unsigned int i; +#endif  			/* Did we send out the client's  			 * ECDH share for use in premaster @@ -2708,15 +2806,41 @@ int ssl3_send_client_key_exchange(SSL *s)  				goto err;  				} -			/* generate master key from the result */ -			s->session->master_key_length = s->method->ssl3_enc \ -			    -> generate_master_secret(s,  -				s->session->master_key, -				p, n); - +#ifndef OPENSSL_NO_PSK +			/* ECDHE PSK ciphersuites from RFC 5489 */ +			if ((alg_a & SSL_aPSK) && psk_len != 0) +				{ +				pre_ms_len = 2+psk_len+2+n; +				pre_ms = OPENSSL_malloc(pre_ms_len); +				if (pre_ms == NULL) +					{ +					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, +			    		ERR_R_MALLOC_FAILURE); +					goto err; +					} +				memset(pre_ms, 0, pre_ms_len); +				t = pre_ms; +				s2n(psk_len, t); +				memcpy(t, psk, psk_len); +				t += psk_len; +				s2n(n, t); +				memcpy(t, p, n); +				s->session->master_key_length = s->method->ssl3_enc \ +					-> generate_master_secret(s, +						s->session->master_key, pre_ms, pre_ms_len); +				OPENSSL_cleanse(pre_ms, pre_ms_len); +				OPENSSL_free(pre_ms); +				} +#endif /* OPENSSL_NO_PSK */ +			if (!(alg_a & SSL_aPSK)) +				{ +				/* generate master key from the result */ +				s->session->master_key_length = s->method->ssl3_enc \ +					-> generate_master_secret(s, +						s->session->master_key, p, n); +				}  			memset(p, 0, n); /* clean up */ - -			if (ecdh_clnt_cert)  +			if (ecdh_clnt_cert)  				{  				/* Send empty client key exch message */  				n = 0; @@ -2744,29 +2868,42 @@ int ssl3_send_client_key_exchange(SSL *s)  					}  				/* Encode the public key */ -				n = EC_POINT_point2oct(srvr_group,  -				    EC_KEY_get0_public_key(clnt_ecdh),  -				    POINT_CONVERSION_UNCOMPRESSED,  +				encoded_pt_len = EC_POINT_point2oct(srvr_group, +				    EC_KEY_get0_public_key(clnt_ecdh), +				    POINT_CONVERSION_UNCOMPRESSED,  				    encodedPoint, encoded_pt_len, bn_ctx); +				 +				n = 0; +#ifndef OPENSSL_NO_PSK +				if ((alg_a & SSL_aPSK) && psk_len != 0) +					{ +					i = strlen(s->session->psk_identity); +					s2n(i, p); +					memcpy(p, s->session->psk_identity, i); +					p += i; +					n = i + 2; +					} +#endif -				*p = n; /* length of encoded point */ +				*p = encoded_pt_len; /* length of encoded point */  				/* Encoded point will be copied here */ -				p += 1;  +				p += 1; +				n += 1;  				/* copy the point */ -				memcpy((unsigned char *)p, encodedPoint, n); +				memcpy((unsigned char *)p, encodedPoint, encoded_pt_len);  				/* increment n to account for length field */ -				n += 1;  +				n += encoded_pt_len;  				}  			/* Free allocated memory */  			BN_CTX_free(bn_ctx);  			if (encodedPoint != NULL) OPENSSL_free(encodedPoint); -			if (clnt_ecdh != NULL)  +			if (clnt_ecdh != NULL)  				 EC_KEY_free(clnt_ecdh);  			EVP_PKEY_free(srvr_pub_pkey);  			}  #endif /* !OPENSSL_NO_ECDH */ -		else if (alg_k & SSL_kGOST)  +		else if (alg_k & SSL_kGOST)  			{  			/* GOST key exchange message creation */  			EVP_PKEY_CTX *pkey_ctx; @@ -2889,89 +3026,7 @@ int ssl3_send_client_key_exchange(SSL *s)  				}  			}  #endif -#ifndef OPENSSL_NO_PSK -		else if (alg_k & SSL_kPSK) -			{ -			char identity[PSK_MAX_IDENTITY_LEN]; -			unsigned char *t = NULL; -			unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN*2+4]; -			unsigned int pre_ms_len = 0, psk_len = 0; -			int psk_err = 1; - -			n = 0; -			if (s->psk_client_callback == NULL) -				{ -				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, -					SSL_R_PSK_NO_CLIENT_CB); -				goto err; -				} - -			psk_len = s->psk_client_callback(s, s->ctx->psk_identity_hint, -				identity, PSK_MAX_IDENTITY_LEN, -				psk_or_pre_ms, sizeof(psk_or_pre_ms)); -			if (psk_len > PSK_MAX_PSK_LEN) -				{ -				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, -					ERR_R_INTERNAL_ERROR); -				goto psk_err; -				} -			else if (psk_len == 0) -				{ -				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, -					SSL_R_PSK_IDENTITY_NOT_FOUND); -				goto psk_err; -				} - -			/* create PSK pre_master_secret */ -			pre_ms_len = 2+psk_len+2+psk_len; -			t = psk_or_pre_ms; -			memmove(psk_or_pre_ms+psk_len+4, psk_or_pre_ms, psk_len); -			s2n(psk_len, t); -			memset(t, 0, psk_len); -			t+=psk_len; -			s2n(psk_len, t); - -			if (s->session->psk_identity_hint != NULL) -				OPENSSL_free(s->session->psk_identity_hint); -			s->session->psk_identity_hint = BUF_strdup(s->ctx->psk_identity_hint); -			if (s->ctx->psk_identity_hint != NULL && -				s->session->psk_identity_hint == NULL) -				{ -				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, -					ERR_R_MALLOC_FAILURE); -				goto psk_err; -				} - -			if (s->session->psk_identity != NULL) -				OPENSSL_free(s->session->psk_identity); -			s->session->psk_identity = BUF_strdup(identity); -			if (s->session->psk_identity == NULL) -				{ -				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, -					ERR_R_MALLOC_FAILURE); -				goto psk_err; -				} - -			s->session->master_key_length = -				s->method->ssl3_enc->generate_master_secret(s, -					s->session->master_key, -					psk_or_pre_ms, pre_ms_len);  -			n = strlen(identity); -			s2n(n, p); -			memcpy(p, identity, n); -			n+=2; -			psk_err = 0; -		psk_err: -			OPENSSL_cleanse(identity, PSK_MAX_IDENTITY_LEN); -			OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms)); -			if (psk_err != 0) -				{ -				ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); -				goto err; -				} -			} -#endif -		else +		else if (!(alg_k & SSL_kPSK))  			{  			ssl3_send_alert(s, SSL3_AL_FATAL,  			    SSL_AD_HANDSHAKE_FAILURE); @@ -3276,7 +3331,7 @@ int ssl3_check_cert_and_algorithm(SSL *s)  	alg_a=s->s3->tmp.new_cipher->algorithm_auth;  	/* we don't have a certificate */ -	if ((alg_a & (SSL_aDH|SSL_aNULL|SSL_aKRB5)) || (alg_k & SSL_kPSK)) +	if ((alg_a & (SSL_aDH|SSL_aNULL|SSL_aKRB5)) || ((alg_a & SSL_aPSK) && !(alg_k & SSL_kRSA)))  		return(1);  	sc=s->session->sess_cert;  | 
