diff options
| author | Arne Schwabe <arne@rfc2549.org> | 2014-10-28 23:07:58 +0100 | 
|---|---|---|
| committer | Arne Schwabe <arne@rfc2549.org> | 2014-10-28 23:07:58 +0100 | 
| commit | 192f5b50e32ed14945317325a5465f40abfcc587 (patch) | |
| tree | c58aa6ba75e3c0acaa4f9d91ab62efecf8d838bc | |
| parent | 22feeb602f32f1d58f4aa5168b5fc139e086e85d (diff) | |
Update Openssl to aosp/master (includes useless (for OpenVPN)) SSLv3 Fallback fix
--HG--
extra : rebase_source : 4ec3b7a7844aa1ca198c4538ecdf28f027ceb1b1
61 files changed, 1565 insertions, 727 deletions
| diff --git a/main/openssl/Crypto-config-target.mk b/main/openssl/Crypto-config-target.mk index bd29dfe5..5851e5a3 100644 --- a/main/openssl/Crypto-config-target.mk +++ b/main/openssl/Crypto-config-target.mk @@ -695,6 +695,10 @@ mips_exclude_files := \    crypto/aes/aes_core.c \    crypto/bn/bn_asm.c \ +# At least crypto/aes/asm/bsaes-armv7.S does not compile with Clang +LOCAL_CLANG_ASFLAGS_arm += -no-integrated-as +# crypto/aes/asm/aesv8-armx-64.S failed to compile. +LOCAL_CLANG_ASFLAGS_arm64 += -no-integrated-as  LOCAL_CFLAGS += $(common_cflags)  LOCAL_C_INCLUDES += $(common_c_includes) diff --git a/main/openssl/Ssl.mk b/main/openssl/Ssl.mk index 0cb93eac..f3263ff0 100644 --- a/main/openssl/Ssl.mk +++ b/main/openssl/Ssl.mk @@ -1,5 +1,6 @@  #######################################  # target static library +  include $(CLEAR_VARS)  include $(LOCAL_PATH)/ndk-build-clear.mk @@ -25,6 +26,7 @@ include $(BUILD_STATIC_LIBRARY)  # target shared library  include $(CLEAR_VARS)  include $(LOCAL_PATH)/ndk-build-clear.mk +  LOCAL_SHARED_LIBRARIES := $(log_shared_libraries)  LOCAL_C_INCLUDES := $(log_c_includes) diff --git a/main/openssl/apps/s_client.c b/main/openssl/apps/s_client.c index 0c705803..299facdc 100644 --- a/main/openssl/apps/s_client.c +++ b/main/openssl/apps/s_client.c @@ -335,6 +335,7 @@ static void sc_usage(void)  	BIO_printf(bio_err," -tls1_1       - just use TLSv1.1\n");  	BIO_printf(bio_err," -tls1         - just use TLSv1\n");  	BIO_printf(bio_err," -dtls1        - just use DTLSv1\n");     +	BIO_printf(bio_err," -fallback_scsv - send TLS_FALLBACK_SCSV\n");  	BIO_printf(bio_err," -mtu          - set the link layer MTU\n");  	BIO_printf(bio_err," -no_tls1_2/-no_tls1_1/-no_tls1/-no_ssl3/-no_ssl2 - turn off that protocol\n");  	BIO_printf(bio_err," -bugs         - Switch on all SSL implementation bug workarounds\n"); @@ -621,6 +622,7 @@ int MAIN(int argc, char **argv)  	char *sess_out = NULL;  	struct sockaddr peer;  	int peerlen = sizeof(peer); +	int fallback_scsv = 0;  	int enable_timeouts = 0 ;  	long socket_mtu = 0;  #ifndef OPENSSL_NO_JPAKE @@ -827,6 +829,10 @@ int MAIN(int argc, char **argv)  			meth=DTLSv1_client_method();  			socket_type=SOCK_DGRAM;  			} +		else if (strcmp(*argv,"-fallback_scsv") == 0) +			{ +			fallback_scsv = 1; +			}  		else if (strcmp(*argv,"-timeout") == 0)  			enable_timeouts=1;  		else if (strcmp(*argv,"-mtu") == 0) @@ -1273,6 +1279,10 @@ bad:  		SSL_set_session(con, sess);  		SSL_SESSION_free(sess);  		} + +	if (fallback_scsv) +		SSL_set_mode(con, SSL_MODE_SEND_FALLBACK_SCSV); +  #ifndef OPENSSL_NO_TLSEXT  	if (servername != NULL)  		{ diff --git a/main/openssl/crypto/err/openssl.ec b/main/openssl/crypto/err/openssl.ec index e0554b43..34754e55 100644 --- a/main/openssl/crypto/err/openssl.ec +++ b/main/openssl/crypto/err/openssl.ec @@ -71,6 +71,7 @@ R SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION		1060  R SSL_R_TLSV1_ALERT_PROTOCOL_VERSION		1070  R SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY	1071  R SSL_R_TLSV1_ALERT_INTERNAL_ERROR		1080 +R SSL_R_SSLV3_ALERT_INAPPROPRIATE_FALLBACK	1086  R SSL_R_TLSV1_ALERT_USER_CANCELLED		1090  R SSL_R_TLSV1_ALERT_NO_RENEGOTIATION		1100  R SSL_R_TLSV1_UNSUPPORTED_EXTENSION		1110 diff --git a/main/openssl/flavor.mk b/main/openssl/flavor.mk new file mode 100644 index 00000000..f32fe41a --- /dev/null +++ b/main/openssl/flavor.mk @@ -0,0 +1,4 @@ +# This makefile exists to be included by makefiles in other directories so that +# they can detect whether BoringSSL or OpenSSL is being used. + +OPENSSL_FLAVOR=OpenSSL diff --git a/main/openssl/include/openssl/dtls1.h b/main/openssl/include/openssl/dtls1.h index e65d5011..192c5def 100644 --- a/main/openssl/include/openssl/dtls1.h +++ b/main/openssl/include/openssl/dtls1.h @@ -84,6 +84,8 @@ extern "C" {  #endif  #define DTLS1_VERSION			0xFEFF +#define DTLS_MAX_VERSION		DTLS1_VERSION +  #define DTLS1_BAD_VER			0x0100  #if 0 @@ -284,4 +286,3 @@ typedef struct dtls1_record_data_st  }  #endif  #endif - diff --git a/main/openssl/include/openssl/ssl.h b/main/openssl/include/openssl/ssl.h index 7566f2df..a89ab237 100644 --- a/main/openssl/include/openssl/ssl.h +++ b/main/openssl/include/openssl/ssl.h @@ -676,6 +676,11 @@ struct ssl_session_st   * attacks. */  #define SSL_MODE_CBC_RECORD_SPLITTING 0x00000100L +/* Send TLS_FALLBACK_SCSV in the ClientHello. + * To be set by applications that reconnect with a downgraded protocol + * version; see draft-ietf-tls-downgrade-scsv-00 for details. */ +#define SSL_MODE_SEND_FALLBACK_SCSV 0x00000200L +  /* Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value,   * they cannot be used to clear bits. */ @@ -1615,6 +1620,7 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)  #define SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE  #define SSL_AD_BAD_CERTIFICATE_HASH_VALUE TLS1_AD_BAD_CERTIFICATE_HASH_VALUE  #define SSL_AD_UNKNOWN_PSK_IDENTITY     TLS1_AD_UNKNOWN_PSK_IDENTITY /* fatal */ +#define SSL_AD_INAPPROPRIATE_FALLBACK	TLS1_AD_INAPPROPRIATE_FALLBACK /* fatal */  #define SSL_ERROR_NONE			0  #define SSL_ERROR_SSL			1 @@ -1729,6 +1735,8 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)  #define SSL_CTRL_GET_EXTRA_CHAIN_CERTS		82  #define SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS	83 +#define SSL_CTRL_CHECK_PROTO_VERSION		119 +  #define DTLSv1_get_timeout(ssl, arg) \  	SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg)  #define DTLSv1_handle_timeout(ssl) \ @@ -2519,6 +2527,7 @@ void ERR_load_SSL_strings(void);  #define SSL_R_HTTPS_PROXY_REQUEST			 155  #define SSL_R_HTTP_REQUEST				 156  #define SSL_R_ILLEGAL_PADDING				 283 +#define SSL_R_INAPPROPRIATE_FALLBACK			 380  #define SSL_R_INCONSISTENT_COMPRESSION			 340  #define SSL_R_INVALID_CHALLENGE_LENGTH			 158  #define SSL_R_INVALID_COMMAND				 280 @@ -2668,6 +2677,7 @@ void ERR_load_SSL_strings(void);  #define SSL_R_TLSV1_ALERT_DECRYPTION_FAILED		 1021  #define SSL_R_TLSV1_ALERT_DECRYPT_ERROR			 1051  #define SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION		 1060 +#define SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK	 1086  #define SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY		 1071  #define SSL_R_TLSV1_ALERT_INTERNAL_ERROR		 1080  #define SSL_R_TLSV1_ALERT_NO_RENEGOTIATION		 1100 diff --git a/main/openssl/include/openssl/ssl3.h b/main/openssl/include/openssl/ssl3.h index 83d59bff..cba94345 100644 --- a/main/openssl/include/openssl/ssl3.h +++ b/main/openssl/include/openssl/ssl3.h @@ -128,9 +128,14 @@  extern "C" {  #endif -/* Signalling cipher suite value: from draft-ietf-tls-renegotiation-03.txt */ +/* Signalling cipher suite value from RFC 5746 + * (TLS_EMPTY_RENEGOTIATION_INFO_SCSV) */  #define SSL3_CK_SCSV				0x030000FF +/* Signalling cipher suite value from draft-ietf-tls-downgrade-scsv-00 + * (TLS_FALLBACK_SCSV) */ +#define SSL3_CK_FALLBACK_SCSV			0x03005600 +  #define SSL3_CK_RSA_NULL_MD5			0x03000001  #define SSL3_CK_RSA_NULL_SHA			0x03000002  #define SSL3_CK_RSA_RC4_40_MD5 			0x03000003 diff --git a/main/openssl/include/openssl/tls1.h b/main/openssl/include/openssl/tls1.h index b9a0899e..dc36f79f 100644 --- a/main/openssl/include/openssl/tls1.h +++ b/main/openssl/include/openssl/tls1.h @@ -159,17 +159,19 @@ extern "C" {  #define TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES	0 +#define TLS1_VERSION			0x0301 +#define TLS1_1_VERSION			0x0302  #define TLS1_2_VERSION			0x0303 -#define TLS1_2_VERSION_MAJOR		0x03 -#define TLS1_2_VERSION_MINOR		0x03 +#define TLS_MAX_VERSION			TLS1_2_VERSION + +#define TLS1_VERSION_MAJOR		0x03 +#define TLS1_VERSION_MINOR		0x01 -#define TLS1_1_VERSION			0x0302  #define TLS1_1_VERSION_MAJOR		0x03  #define TLS1_1_VERSION_MINOR		0x02 -#define TLS1_VERSION			0x0301 -#define TLS1_VERSION_MAJOR		0x03 -#define TLS1_VERSION_MINOR		0x01 +#define TLS1_2_VERSION_MAJOR		0x03 +#define TLS1_2_VERSION_MINOR		0x03  #define TLS1_get_version(s) \  		((s->version >> 8) == TLS1_VERSION_MAJOR ? s->version : 0) @@ -187,6 +189,7 @@ extern "C" {  #define TLS1_AD_PROTOCOL_VERSION	70	/* fatal */  #define TLS1_AD_INSUFFICIENT_SECURITY	71	/* fatal */  #define TLS1_AD_INTERNAL_ERROR		80	/* fatal */ +#define TLS1_AD_INAPPROPRIATE_FALLBACK	86	/* fatal */  #define TLS1_AD_USER_CANCELLED		90  #define TLS1_AD_NO_RENEGOTIATION	100  /* codes 110-114 are from RFC3546 */ diff --git a/main/openssl/patches/README b/main/openssl/patches/README index 13e9bd8b..53444701 100644 --- a/main/openssl/patches/README +++ b/main/openssl/patches/README @@ -75,3 +75,8 @@ psk_client_callback_128_byte_id_bug.patch  Fixes the issue where it was impossible to return a 128 byte long PSK identity  (the maximum supported length) from psk_client_callback. + +tls_fallback_scsv.patch + +Adds the signalling cipher suite value (SCSV) from +https://tools.ietf.org/html/draft-ietf-tls-downgrade-scsv-00 diff --git a/main/openssl/ssl/d1_lib.c b/main/openssl/ssl/d1_lib.c index 6bde16fa..82ca6539 100644 --- a/main/openssl/ssl/d1_lib.c +++ b/main/openssl/ssl/d1_lib.c @@ -266,6 +266,16 @@ long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg)  	case DTLS_CTRL_LISTEN:  		ret = dtls1_listen(s, parg);  		break; +	case SSL_CTRL_CHECK_PROTO_VERSION: +		/* For library-internal use; checks that the current protocol +		 * is the highest enabled version (according to s->ctx->method, +		 * as version negotiation may have changed s->method). */ +#if DTLS_MAX_VERSION != DTLS1_VERSION +#  error Code needs update for DTLS_method() support beyond DTLS1_VERSION. +#endif +		/* Just one protocol version is supported so far; +		 * fail closed if the version is not as expected. */ +		return s->version == DTLS_MAX_VERSION;  	default:  		ret = ssl3_ctrl(s, cmd, larg, parg); diff --git a/main/openssl/ssl/dtls1.h b/main/openssl/ssl/dtls1.h index e65d5011..192c5def 100644 --- a/main/openssl/ssl/dtls1.h +++ b/main/openssl/ssl/dtls1.h @@ -84,6 +84,8 @@ extern "C" {  #endif  #define DTLS1_VERSION			0xFEFF +#define DTLS_MAX_VERSION		DTLS1_VERSION +  #define DTLS1_BAD_VER			0x0100  #if 0 @@ -284,4 +286,3 @@ typedef struct dtls1_record_data_st  }  #endif  #endif - diff --git a/main/openssl/ssl/s23_clnt.c b/main/openssl/ssl/s23_clnt.c index 2bc92141..467adfea 100644 --- a/main/openssl/ssl/s23_clnt.c +++ b/main/openssl/ssl/s23_clnt.c @@ -736,6 +736,9 @@ static int ssl23_get_server_hello(SSL *s)  			goto err;  			} +		/* ensure that TLS_MAX_VERSION is up-to-date */ +		OPENSSL_assert(s->version <= TLS_MAX_VERSION); +  		if (p[0] == SSL3_RT_ALERT && p[5] != SSL3_AL_WARNING)  			{  			/* fatal alert */ diff --git a/main/openssl/ssl/s23_srvr.c b/main/openssl/ssl/s23_srvr.c index 48778490..82d6867b 100644 --- a/main/openssl/ssl/s23_srvr.c +++ b/main/openssl/ssl/s23_srvr.c @@ -425,6 +425,9 @@ int ssl23_get_client_hello(SSL *s)  			}  		} +	/* ensure that TLS_MAX_VERSION is up-to-date */ +	OPENSSL_assert(s->version <= TLS_MAX_VERSION); +  #ifdef OPENSSL_FIPS  	if (FIPS_mode() && (s->version < TLS1_VERSION))  		{ diff --git a/main/openssl/ssl/s2_lib.c b/main/openssl/ssl/s2_lib.c index 99146041..b9624b95 100644 --- a/main/openssl/ssl/s2_lib.c +++ b/main/openssl/ssl/s2_lib.c @@ -391,6 +391,8 @@ long ssl2_ctrl(SSL *s, int cmd, long larg, void *parg)  	case SSL_CTRL_GET_SESSION_REUSED:  		ret=s->hit;  		break; +	case SSL_CTRL_CHECK_PROTO_VERSION: +		return ssl3_ctrl(s, SSL_CTRL_CHECK_PROTO_VERSION, larg, parg);  	default:  		break;  		} diff --git a/main/openssl/ssl/s3_enc.c b/main/openssl/ssl/s3_enc.c index 53b94b7c..3595cff4 100644 --- a/main/openssl/ssl/s3_enc.c +++ b/main/openssl/ssl/s3_enc.c @@ -891,7 +891,7 @@ int ssl3_alert_code(int code)  	case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE: return(SSL3_AD_HANDSHAKE_FAILURE);  	case SSL_AD_BAD_CERTIFICATE_HASH_VALUE: return(SSL3_AD_HANDSHAKE_FAILURE);  	case SSL_AD_UNKNOWN_PSK_IDENTITY:return(TLS1_AD_UNKNOWN_PSK_IDENTITY); +	case SSL_AD_INAPPROPRIATE_FALLBACK:return(TLS1_AD_INAPPROPRIATE_FALLBACK);  	default:			return(-1);  		}  	} - diff --git a/main/openssl/ssl/s3_lib.c b/main/openssl/ssl/s3_lib.c index 896d1e19..dca9858d 100644 --- a/main/openssl/ssl/s3_lib.c +++ b/main/openssl/ssl/s3_lib.c @@ -3439,6 +3439,33 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)  		return 64;  #endif /* !OPENSSL_NO_TLSEXT */ + +	case SSL_CTRL_CHECK_PROTO_VERSION: +		/* For library-internal use; checks that the current protocol +		 * is the highest enabled version (according to s->ctx->method, +		 * as version negotiation may have changed s->method). */ +		if (s->version == s->ctx->method->version) +			return 1; +		/* Apparently we're using a version-flexible SSL_METHOD +		 * (not at its highest protocol version). */ +		if (s->ctx->method->version == SSLv23_method()->version) +			{ +#if TLS_MAX_VERSION != TLS1_2_VERSION +#  error Code needs update for SSLv23_method() support beyond TLS1_2_VERSION. +#endif +			if (!(s->options & SSL_OP_NO_TLSv1_2)) +				return s->version == TLS1_2_VERSION; +			if (!(s->options & SSL_OP_NO_TLSv1_1)) +				return s->version == TLS1_1_VERSION; +			if (!(s->options & SSL_OP_NO_TLSv1)) +				return s->version == TLS1_VERSION; +			if (!(s->options & SSL_OP_NO_SSLv3)) +				return s->version == SSL3_VERSION; +			if (!(s->options & SSL_OP_NO_SSLv2)) +				return s->version == SSL2_VERSION; +			} +		return 0; /* Unexpected state; fail closed. */ +  	default:  		break;  		} @@ -3816,6 +3843,7 @@ long ssl3_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp)(void))  		break;  #endif  #endif +  	default:  		return(0);  		} @@ -4406,4 +4434,3 @@ long ssl_get_algorithm2(SSL *s)  		return SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256;  	return alg2;  	} -		 diff --git a/main/openssl/ssl/ssl.h b/main/openssl/ssl/ssl.h index 7566f2df..a89ab237 100644 --- a/main/openssl/ssl/ssl.h +++ b/main/openssl/ssl/ssl.h @@ -676,6 +676,11 @@ struct ssl_session_st   * attacks. */  #define SSL_MODE_CBC_RECORD_SPLITTING 0x00000100L +/* Send TLS_FALLBACK_SCSV in the ClientHello. + * To be set by applications that reconnect with a downgraded protocol + * version; see draft-ietf-tls-downgrade-scsv-00 for details. */ +#define SSL_MODE_SEND_FALLBACK_SCSV 0x00000200L +  /* Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value,   * they cannot be used to clear bits. */ @@ -1615,6 +1620,7 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)  #define SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE  #define SSL_AD_BAD_CERTIFICATE_HASH_VALUE TLS1_AD_BAD_CERTIFICATE_HASH_VALUE  #define SSL_AD_UNKNOWN_PSK_IDENTITY     TLS1_AD_UNKNOWN_PSK_IDENTITY /* fatal */ +#define SSL_AD_INAPPROPRIATE_FALLBACK	TLS1_AD_INAPPROPRIATE_FALLBACK /* fatal */  #define SSL_ERROR_NONE			0  #define SSL_ERROR_SSL			1 @@ -1729,6 +1735,8 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)  #define SSL_CTRL_GET_EXTRA_CHAIN_CERTS		82  #define SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS	83 +#define SSL_CTRL_CHECK_PROTO_VERSION		119 +  #define DTLSv1_get_timeout(ssl, arg) \  	SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg)  #define DTLSv1_handle_timeout(ssl) \ @@ -2519,6 +2527,7 @@ void ERR_load_SSL_strings(void);  #define SSL_R_HTTPS_PROXY_REQUEST			 155  #define SSL_R_HTTP_REQUEST				 156  #define SSL_R_ILLEGAL_PADDING				 283 +#define SSL_R_INAPPROPRIATE_FALLBACK			 380  #define SSL_R_INCONSISTENT_COMPRESSION			 340  #define SSL_R_INVALID_CHALLENGE_LENGTH			 158  #define SSL_R_INVALID_COMMAND				 280 @@ -2668,6 +2677,7 @@ void ERR_load_SSL_strings(void);  #define SSL_R_TLSV1_ALERT_DECRYPTION_FAILED		 1021  #define SSL_R_TLSV1_ALERT_DECRYPT_ERROR			 1051  #define SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION		 1060 +#define SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK	 1086  #define SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY		 1071  #define SSL_R_TLSV1_ALERT_INTERNAL_ERROR		 1080  #define SSL_R_TLSV1_ALERT_NO_RENEGOTIATION		 1100 diff --git a/main/openssl/ssl/ssl3.h b/main/openssl/ssl/ssl3.h index 83d59bff..cba94345 100644 --- a/main/openssl/ssl/ssl3.h +++ b/main/openssl/ssl/ssl3.h @@ -128,9 +128,14 @@  extern "C" {  #endif -/* Signalling cipher suite value: from draft-ietf-tls-renegotiation-03.txt */ +/* Signalling cipher suite value from RFC 5746 + * (TLS_EMPTY_RENEGOTIATION_INFO_SCSV) */  #define SSL3_CK_SCSV				0x030000FF +/* Signalling cipher suite value from draft-ietf-tls-downgrade-scsv-00 + * (TLS_FALLBACK_SCSV) */ +#define SSL3_CK_FALLBACK_SCSV			0x03005600 +  #define SSL3_CK_RSA_NULL_MD5			0x03000001  #define SSL3_CK_RSA_NULL_SHA			0x03000002  #define SSL3_CK_RSA_RC4_40_MD5 			0x03000003 diff --git a/main/openssl/ssl/ssl_err.c b/main/openssl/ssl/ssl_err.c index ac0aad9b..816f6eef 100644 --- a/main/openssl/ssl/ssl_err.c +++ b/main/openssl/ssl/ssl_err.c @@ -391,6 +391,7 @@ static ERR_STRING_DATA SSL_str_reasons[]=  {ERR_REASON(SSL_R_HTTPS_PROXY_REQUEST)   ,"https proxy request"},  {ERR_REASON(SSL_R_HTTP_REQUEST)          ,"http request"},  {ERR_REASON(SSL_R_ILLEGAL_PADDING)       ,"illegal padding"}, +{ERR_REASON(SSL_R_INAPPROPRIATE_FALLBACK),"inappropriate fallback"},  {ERR_REASON(SSL_R_INCONSISTENT_COMPRESSION),"inconsistent compression"},  {ERR_REASON(SSL_R_INVALID_CHALLENGE_LENGTH),"invalid challenge length"},  {ERR_REASON(SSL_R_INVALID_COMMAND)       ,"invalid command"}, @@ -540,6 +541,7 @@ static ERR_STRING_DATA SSL_str_reasons[]=  {ERR_REASON(SSL_R_TLSV1_ALERT_DECRYPTION_FAILED),"tlsv1 alert decryption failed"},  {ERR_REASON(SSL_R_TLSV1_ALERT_DECRYPT_ERROR),"tlsv1 alert decrypt error"},  {ERR_REASON(SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION),"tlsv1 alert export restriction"}, +{ERR_REASON(SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK),"tlsv1 alert inappropriate fallback"},  {ERR_REASON(SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY),"tlsv1 alert insufficient security"},  {ERR_REASON(SSL_R_TLSV1_ALERT_INTERNAL_ERROR),"tlsv1 alert internal error"},  {ERR_REASON(SSL_R_TLSV1_ALERT_NO_RENEGOTIATION),"tlsv1 alert no renegotiation"}, diff --git a/main/openssl/ssl/ssl_lib.c b/main/openssl/ssl/ssl_lib.c index 3de68a78..ec0ec2e5 100644 --- a/main/openssl/ssl/ssl_lib.c +++ b/main/openssl/ssl/ssl_lib.c @@ -1441,6 +1441,8 @@ int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p,  	if (sk == NULL) return(0);  	q=p; +	if (put_cb == NULL) +		put_cb = s->method->put_cipher_by_char;  	for (i=0; i<sk_SSL_CIPHER_num(sk); i++)  		{ @@ -1460,25 +1462,36 @@ int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p,  		    s->psk_client_callback == NULL)  			continue;  #endif /* OPENSSL_NO_PSK */ -		j = put_cb ? put_cb(c,p) : ssl_put_cipher_by_char(s,c,p); +		j = put_cb(c,p);  		p+=j;  		} -	/* If p == q, no ciphers and caller indicates an error. Otherwise -	 * add SCSV if not renegotiating. -	 */ -	if (p != q && !s->renegotiate) +	/* If p == q, no ciphers; caller indicates an error. +	 * Otherwise, add applicable SCSVs. */ +	if (p != q)  		{ -		static SSL_CIPHER scsv = +		if (!s->renegotiate)  			{ -			0, NULL, SSL3_CK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0 -			}; -		j = put_cb ? put_cb(&scsv,p) : ssl_put_cipher_by_char(s,&scsv,p); -		p+=j; +			static SSL_CIPHER scsv = +				{ +				0, NULL, SSL3_CK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0 +				}; +			j = put_cb(&scsv,p); +			p+=j;  #ifdef OPENSSL_RI_DEBUG -		fprintf(stderr, "SCSV sent by client\n"); +			fprintf(stderr, "TLS_EMPTY_RENEGOTIATION_INFO_SCSV sent by client\n");  #endif -		} +			} +		if (s->mode & SSL_MODE_SEND_FALLBACK_SCSV) +			{ +			static SSL_CIPHER scsv = +				{ +				0, NULL, SSL3_CK_FALLBACK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0 +				}; +			j = put_cb(&scsv,p); +			p+=j; +			} + 		}  	return(p-q);  	} @@ -1488,11 +1501,12 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num,  	const SSL_CIPHER *c;  	STACK_OF(SSL_CIPHER) *sk;  	int i,n; +  	if (s->s3)  		s->s3->send_connection_binding = 0;  	n=ssl_put_cipher_by_char(s,NULL,NULL); -	if ((num%n) != 0) +	if (n == 0 || (num%n) != 0)  		{  		SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);  		return(NULL); @@ -1507,7 +1521,7 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num,  	for (i=0; i<num; i+=n)  		{ -		/* Check for SCSV */ +		/* Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV */  		if (s->s3 && (n != 3 || !p[0]) &&  			(p[n-2] == ((SSL3_CK_SCSV >> 8) & 0xff)) &&  			(p[n-1] == (SSL3_CK_SCSV & 0xff))) @@ -1527,6 +1541,22 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num,  			continue;  			} +		/* Check for TLS_FALLBACK_SCSV */ +		if (s->s3 && (n != 3 || !p[0]) && +			(p[n-2] == ((SSL3_CK_FALLBACK_SCSV >> 8) & 0xff)) && +			(p[n-1] == (SSL3_CK_FALLBACK_SCSV & 0xff))) +			{ +			/* The SCSV indicates that the client previously tried a higher version. +			 * Fail if the current version is an unexpected downgrade. */ +			if (!SSL_ctrl(s, SSL_CTRL_CHECK_PROTO_VERSION, 0, NULL)) +				{ +				SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,SSL_R_INAPPROPRIATE_FALLBACK); +				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_INAPPROPRIATE_FALLBACK); +				goto err; +				} +			continue; +			} +  		c=ssl_get_cipher_by_char(s,p);  		p+=n;  		if (c != NULL) diff --git a/main/openssl/ssl/t1_enc.c b/main/openssl/ssl/t1_enc.c index 22dd3cab..b8d497ec 100644 --- a/main/openssl/ssl/t1_enc.c +++ b/main/openssl/ssl/t1_enc.c @@ -1266,6 +1266,7 @@ int tls1_alert_code(int code)  	case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE: return(TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE);  	case SSL_AD_BAD_CERTIFICATE_HASH_VALUE: return(TLS1_AD_BAD_CERTIFICATE_HASH_VALUE);  	case SSL_AD_UNKNOWN_PSK_IDENTITY:return(TLS1_AD_UNKNOWN_PSK_IDENTITY); +	case SSL_AD_INAPPROPRIATE_FALLBACK:return(TLS1_AD_INAPPROPRIATE_FALLBACK);  #if 0 /* not appropriate for TLS, not used for DTLS */  	case DTLS1_AD_MISSING_HANDSHAKE_MESSAGE: return   					  (DTLS1_AD_MISSING_HANDSHAKE_MESSAGE); diff --git a/main/openssl/ssl/tls1.h b/main/openssl/ssl/tls1.h index b9a0899e..dc36f79f 100644 --- a/main/openssl/ssl/tls1.h +++ b/main/openssl/ssl/tls1.h @@ -159,17 +159,19 @@ extern "C" {  #define TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES	0 +#define TLS1_VERSION			0x0301 +#define TLS1_1_VERSION			0x0302  #define TLS1_2_VERSION			0x0303 -#define TLS1_2_VERSION_MAJOR		0x03 -#define TLS1_2_VERSION_MINOR		0x03 +#define TLS_MAX_VERSION			TLS1_2_VERSION + +#define TLS1_VERSION_MAJOR		0x03 +#define TLS1_VERSION_MINOR		0x01 -#define TLS1_1_VERSION			0x0302  #define TLS1_1_VERSION_MAJOR		0x03  #define TLS1_1_VERSION_MINOR		0x02 -#define TLS1_VERSION			0x0301 -#define TLS1_VERSION_MAJOR		0x03 -#define TLS1_VERSION_MINOR		0x01 +#define TLS1_2_VERSION_MAJOR		0x03 +#define TLS1_2_VERSION_MINOR		0x03  #define TLS1_get_version(s) \  		((s->version >> 8) == TLS1_VERSION_MAJOR ? s->version : 0) @@ -187,6 +189,7 @@ extern "C" {  #define TLS1_AD_PROTOCOL_VERSION	70	/* fatal */  #define TLS1_AD_INSUFFICIENT_SECURITY	71	/* fatal */  #define TLS1_AD_INTERNAL_ERROR		80	/* fatal */ +#define TLS1_AD_INAPPROPRIATE_FALLBACK	86	/* fatal */  #define TLS1_AD_USER_CANCELLED		90  #define TLS1_AD_NO_RENEGOTIATION	100  /* codes 110-114 are from RFC3546 */ diff --git a/main/openvpn/config-version.h b/main/openvpn/config-version.h index 61285e2f..34e3c054 100644 --- a/main/openvpn/config-version.h +++ b/main/openvpn/config-version.h @@ -1,2 +1,2 @@ -#define CONFIGURE_GIT_REVISION "icsopenvpn_619-5e33ca4c82137c4c" +#define CONFIGURE_GIT_REVISION "aead-cipher-modes6-e37234f2dae8a7c4"  #define CONFIGURE_GIT_FLAGS "" diff --git a/main/openvpn/config.h b/main/openvpn/config.h index b825e2bd..6b699028 100644 --- a/main/openvpn/config.h +++ b/main/openvpn/config.h @@ -631,3 +631,5 @@  #define IPPROTO_IP IPPROTO_IP  #define IPPROTO_TCP IPPROTO_TCP + +#define HAVE_AEAD_CIPHER_MODES 1 diff --git a/main/openvpn/configure.ac b/main/openvpn/configure.ac index 608ab6d1..dddadec4 100644 --- a/main/openvpn/configure.ac +++ b/main/openvpn/configure.ac @@ -79,6 +79,13 @@ AC_ARG_ENABLE(  )  AC_ARG_ENABLE( +	[aead-modes], +	[AS_HELP_STRING([--disable-aead-modes], [disable AEAD crypto modes @<:@default=yes@:>@])], +	, +	[enable_aead_modes="yes"] +) + +AC_ARG_ENABLE(  	[ssl],  	[AS_HELP_STRING([--disable-ssl], [disable SSL support for TLS-based key exchange @<:@default=yes@:>@])],  	, @@ -799,6 +806,16 @@ if test "${have_openssl_crypto}" = "yes"; then  		[have_openssl_engine="no"; break]  	) +	have_crypto_aead_modes="yes" +	AC_CHECK_FUNCS( +		[ \ +			EVP_aes_256_ccm \ +			EVP_aes_256_gcm \ +		], +		, +		[have_crypto_aead_modes="no"; break] +	) +  	CFLAGS="${saved_CFLAGS}"  	LIBS="${saved_LIBS}"  fi @@ -828,8 +845,10 @@ fi  if test "${with_crypto_library}" = "polarssl" ; then  	AC_MSG_CHECKING([polarssl version]) -	old_CFLAGS="${CFLAGS}" -	CFLAGS="${POLARSSL_CFLAGS} ${CFLAGS}" +	saved_CFLAGS="${CFLAGS}" +	saved_LIBS="${LIBS}" +	CFLAGS="${POLARSSL_CFLAGS} ${PKCS11_HELPER_CFLAGS} ${CFLAGS}" +	LIBS="${POLARSSL_LIBS} ${PKCS11_HELPER_LIBS} ${LIBS}"  	AC_COMPILE_IFELSE(  		[AC_LANG_PROGRAM(  			[[ @@ -858,7 +877,6 @@ if test "${with_crypto_library}" = "polarssl" ; then  			]]  		)],  		polarssl_with_pkcs11="yes") -	CFLAGS="${old_CFLAGS}"  	AC_MSG_CHECKING([polarssl pkcs11 support])  	if test "${enable_pkcs11}" = "yes"; then @@ -875,6 +893,17 @@ if test "${with_crypto_library}" = "polarssl" ; then  		fi  	fi +	have_crypto_aead_modes="yes" +	AC_CHECK_FUNCS( +		[ \ +			cipher_write_tag \ +			cipher_check_tag \ +		], +		, +		[have_crypto_aead_modes="no"; break] +	) +	CFLAGS="${saved_CFLAGS}" +	LIBS="${saved_LIBS}"  fi  AC_ARG_VAR([LZO_CFLAGS], [C compiler flags for lzo]) @@ -1091,6 +1120,10 @@ fi  if test "${enable_crypto}" = "yes"; then  	test "${have_crypto_crypto}" != "yes" && AC_MSG_ERROR([${with_crypto_library} crypto is required but missing])  	test "${enable_crypto_ofb_cfb}" = "yes" && AC_DEFINE([ENABLE_OFB_CFB_MODE], [1], [Enable OFB and CFB cipher modes]) +	if test "${enable_aead_modes}" = "yes"; then +		test "${have_crypto_aead_modes}" = "yes" && AC_DEFINE([HAVE_AEAD_CIPHER_MODES], [1], [Use crypto library]) +		test "${have_crypto_aead_modes}" != "yes" && AC_MSG_ERROR([AEAD modes required but missing]) +	fi  	OPTIONAL_CRYPTO_CFLAGS="${OPTIONAL_CRYPTO_CFLAGS} ${CRYPTO_CRYPTO_CFLAGS}"  	OPTIONAL_CRYPTO_LIBS="${OPTIONAL_CRYPTO_LIBS} ${CRYPTO_CRYPTO_LIBS}"  	AC_DEFINE([ENABLE_CRYPTO], [1], [Enable crypto library]) diff --git a/main/openvpn/doc/openvpn.8 b/main/openvpn/doc/openvpn.8 index f2911c0e..a3d3e28c 100644 --- a/main/openvpn/doc/openvpn.8 +++ b/main/openvpn/doc/openvpn.8 @@ -4238,13 +4238,18 @@ Not available with PolarSSL.  File containing Diffie Hellman parameters  in .pem format (required for  .B \-\-tls-server -only). Use +only). -.B openssl dhparam -out dh1024.pem 1024 +Set +.B file=none +to disable Diffie Hellman key exchange (and use ECDH only). Note that this +requires peers to be using an SSL library that supports ECDH TLS cipher suites +(e.g. OpenSSL 1.0.1+, or PolarSSL 1.3+). -to generate your own, or use the existing dh1024.pem file -included with the OpenVPN distribution.  Diffie Hellman parameters -may be considered public. +Use +.B openssl dhparam -out dh2048.pem 2048 +to generate 2048-bit DH parameters. Diffie Hellman parameters may be considered +public.  .\"*********************************************************  .TP  .B \-\-ecdh-curve name @@ -4330,6 +4335,11 @@ and version is not recognized, we will only accept the highest TLS  version supported by the local SSL implementation.  .\"*********************************************************  .TP +.B \-\-tls-version-max version +Set the maximum TLS version we will use (default is the highest version +supported).  Examples for version include "1.0", "1.1", or "1.2". +.\"********************************************************* +.TP  .B \-\-pkcs12 file  Specify a PKCS #12 file containing local private key,  local certificate, and root CA certificate. diff --git a/main/openvpn/sample/sample-config-files/loopback-client b/main/openvpn/sample/sample-config-files/loopback-client index d7f59e69..ee5691b1 100644 --- a/main/openvpn/sample/sample-config-files/loopback-client +++ b/main/openvpn/sample/sample-config-files/loopback-client @@ -20,6 +20,6 @@ tls-client  ca sample-keys/ca.crt  key sample-keys/client.key  cert sample-keys/client.crt -cipher DES-EDE3-CBC +cipher AES-128-GCM  ping 1  inactive 120 10000000 diff --git a/main/openvpn/sample/sample-config-files/loopback-server b/main/openvpn/sample/sample-config-files/loopback-server index 9d21bcec..9724c915 100644 --- a/main/openvpn/sample/sample-config-files/loopback-server +++ b/main/openvpn/sample/sample-config-files/loopback-server @@ -21,6 +21,6 @@ dh sample-keys/dh1024.pem  ca sample-keys/ca.crt  key sample-keys/server.key  cert sample-keys/server.crt -cipher DES-EDE3-CBC +cipher AES-128-GCM  ping 1  inactive 120 10000000 diff --git a/main/openvpn/src/openvpn/crypto.c b/main/openvpn/src/openvpn/crypto.c index 59a6c737..1aaefbb4 100644 --- a/main/openvpn/src/openvpn/crypto.c +++ b/main/openvpn/src/openvpn/crypto.c @@ -65,6 +65,61 @@  #define CRYPT_ERROR(format) \    do { msg (D_CRYPT_ERRORS, "%s: " format, error_prefix); goto error_exit; } while (false) +static void +crypto_options_debug(const unsigned int flags, const char * prefix, +    const struct crypto_options *opt) { +  struct gc_arena gc = gc_new(); + +  const char *encrypt_cipher = "none"; +  const char *encrypt_impl_iv = "none"; + +  const char *decrypt_cipher = "none"; +  const char *decrypt_impl_iv = "none"; + +  ASSERT(opt); + +  const cipher_kt_t *cipher; + +  if (opt->key_ctx_bi.encrypt.cipher) { +    const struct key_ctx *ctx = &opt->key_ctx_bi.encrypt; + +    cipher = cipher_ctx_get_cipher_kt(ctx->cipher); +    if (cipher) encrypt_cipher = cipher_kt_name(cipher); + +    encrypt_impl_iv = ctx->implicit_iv_len +	? format_hex(ctx->implicit_iv, ctx->implicit_iv_len, 0, &gc) +	: "NULL"; +  } + +  if (opt->key_ctx_bi.decrypt.cipher) { +    const struct key_ctx *ctx = &opt->key_ctx_bi.decrypt; + +    cipher = cipher_ctx_get_cipher_kt(ctx->cipher); +    if (cipher) decrypt_cipher = cipher_kt_name(cipher); + +    decrypt_impl_iv = ctx->implicit_iv_len +	? format_hex(ctx->implicit_iv, ctx->implicit_iv_len, 0, &gc) +	: "NULL"; +  } + +  dmsg(flags, "%s: crypto options (%p) {\n" +      "  flags = %x\n" +      "  encrypt cipher = %s\n" +      "    encr implicit iv = %s\n" +      "  decrypt cipher = %s\n" +      "    encr implicit iv = %s\n" +      "}", +      prefix, +      opt, +      opt->flags, +      encrypt_cipher, +      encrypt_impl_iv, +      decrypt_cipher, +      decrypt_impl_iv); + +  gc_free(&gc); +} +  /**   * As memcmp(), but constant-time.   * Returns 0 when data is equal, non-zero otherwise. @@ -85,22 +140,22 @@ memcmp_constant_time (const void *a, const void *b, size_t size) {  void  openvpn_encrypt (struct buffer *buf, struct buffer work, -		 const struct crypto_options *opt, -		 const struct frame* frame) +		 struct crypto_options *opt, const struct frame* frame)  {    struct gc_arena gc; +  const cipher_kt_t *cipher_kt = NULL;    gc_init (&gc); -  if (buf->len > 0 && opt->key_ctx_bi) +  if (buf->len > 0 && opt)      { -      struct key_ctx *ctx = &opt->key_ctx_bi->encrypt; +      const struct key_ctx *ctx = &opt->key_ctx_bi.encrypt;        /* Do Encrypt from buf -> work */        if (ctx->cipher)  	{  	  uint8_t iv_buf[OPENVPN_MAX_IV_LENGTH];  	  const int iv_size = cipher_ctx_iv_length (ctx->cipher); -	  const cipher_kt_t *cipher_kt = cipher_ctx_get_cipher_kt (ctx->cipher); +	  cipher_kt = cipher_ctx_get_cipher_kt (ctx->cipher);  	  int outlen;  	  if (cipher_kt_mode_cbc(cipher_kt)) @@ -111,11 +166,11 @@ openvpn_encrypt (struct buffer *buf, struct buffer work,  	      if (opt->flags & CO_USE_IV)  		prng_bytes (iv_buf, iv_size); -	      /* Put packet ID in plaintext buffer or IV, depending on cipher mode */ -	      if (opt->packet_id) +	      /* Put packet ID in plaintext buffer */ +	      if (packet_id_initialized(&opt->packet_id))  		{  		  struct packet_id_net pin; -		  packet_id_alloc_outgoing (&opt->packet_id->send, &pin, BOOL_CAST (opt->flags & CO_PACKET_ID_LONG_FORM)); +		  packet_id_alloc_outgoing (&opt->packet_id.send, &pin, BOOL_CAST (opt->flags & CO_PACKET_ID_LONG_FORM));  		  ASSERT (packet_id_write (&pin, buf, BOOL_CAST (opt->flags & CO_PACKET_ID_LONG_FORM), true));  		}  	    } @@ -124,15 +179,38 @@ openvpn_encrypt (struct buffer *buf, struct buffer work,  	      struct packet_id_net pin;  	      struct buffer b; -	      ASSERT (opt->flags & CO_USE_IV);    /* IV and packet-ID required */ -	      ASSERT (opt->packet_id); /*  for this mode. */ +	      /* IV and packet-ID required for this mode. */ +	      ASSERT (opt->flags & CO_USE_IV); +	      ASSERT (packet_id_initialized(&opt->packet_id)); -	      packet_id_alloc_outgoing (&opt->packet_id->send, &pin, true); +	      packet_id_alloc_outgoing (&opt->packet_id.send, &pin, true);  	      memset (iv_buf, 0, iv_size);  	      buf_set_write (&b, iv_buf, iv_size);  	      ASSERT (packet_id_write (&pin, &b, true, false));  	    } -	  else /* We only support CBC, CFB, or OFB modes right now */ +	  else if (cipher_kt_mode_aead (cipher_kt)) +            { +	      struct packet_id_net pin; +	      struct buffer b; + +	      /* IV, packet-ID and implicit IV required for this mode. */ +	      ASSERT (opt->flags & CO_USE_IV); +	      ASSERT (iv_size >= 12); +	      ASSERT (packet_id_initialized(&opt->packet_id)); +	      ASSERT (ctx->implicit_iv_len); + +	      /* Prepare IV buffer */ +	      memset(iv_buf, 0, iv_size); +	      buf_set_write (&b, iv_buf, iv_size); + +	      /* IV starts with implicit IV (must be unique for each session) */ +	      ASSERT (buf_write (&b, ctx->implicit_iv, ctx->implicit_iv_len)); + +	      /* Append packet counter to make the IV unique for packet */ +	      packet_id_alloc_outgoing (&opt->packet_id.send, &pin, true); +	      ASSERT (packet_id_write (&pin, &b, false, false)); +	    } +	  else /* We only support CBC, CFB, OFB, or AEAD modes right now */  	    {  	      ASSERT (0);  	    } @@ -151,7 +229,8 @@ openvpn_encrypt (struct buffer *buf, struct buffer work,  	  ASSERT (cipher_ctx_reset(ctx->cipher, iv_buf));  	  /* Buffer overflow check */ -	  if (!buf_safe (&work, buf->len + cipher_ctx_block_size(ctx->cipher))) +	  int block_size = cipher_ctx_block_size(ctx->cipher); +	  if (!buf_safe (&work, buf->len + block_size))  	    {  	      msg (D_CRYPT_ERRORS, "ENCRYPT: buffer size error, bc=%d bo=%d bl=%d wc=%d wo=%d wl=%d cbs=%d",  		   buf->capacity, @@ -160,10 +239,16 @@ openvpn_encrypt (struct buffer *buf, struct buffer work,  		   work.capacity,  		   work.offset,  		   work.len, -		   cipher_ctx_block_size (ctx->cipher)); +		   block_size);  	      goto err;  	    } +	  /* For AEAD ciphers, we need to update with the AD before ciphertext */ +	  if (cipher_kt_mode_aead (cipher_kt)) +	    { +	      ASSERT (cipher_ctx_update_ad (ctx->cipher, iv_buf, iv_size)); +	    } +  	  /* Encrypt packet ID, payload */  	  ASSERT (cipher_ctx_update (ctx->cipher, BPTR (&work), &outlen, BPTR (buf), BLEN (buf)));  	  work.len += outlen; @@ -179,9 +264,11 @@ openvpn_encrypt (struct buffer *buf, struct buffer work,  	  /* prepend the IV to the ciphertext */  	  if (opt->flags & CO_USE_IV)  	    { -	      uint8_t *output = buf_prepend (&work, iv_size); +	      uint8_t *output = buf_prepend (&work, +		  iv_size - ctx->implicit_iv_len);  	      ASSERT (output); -	      memcpy (output, iv_buf, iv_size); +	      memcpy (output, iv_buf + ctx->implicit_iv_len, +		  iv_size - ctx->implicit_iv_len);  	    }  	  dmsg (D_PACKET_CONTENT, "ENCRYPT TO: %s", @@ -189,10 +276,10 @@ openvpn_encrypt (struct buffer *buf, struct buffer work,  	}        else				/* No Encryption */  	{ -	  if (opt->packet_id) +	  if (packet_id_initialized(&opt->packet_id))  	    {  	      struct packet_id_net pin; -	      packet_id_alloc_outgoing (&opt->packet_id->send, &pin, BOOL_CAST (opt->flags & CO_PACKET_ID_LONG_FORM)); +	      packet_id_alloc_outgoing (&opt->packet_id.send, &pin, BOOL_CAST (opt->flags & CO_PACKET_ID_LONG_FORM));  	      ASSERT (packet_id_write (&pin, buf, BOOL_CAST (opt->flags & CO_PACKET_ID_LONG_FORM), true));  	    }  	  work = *buf; @@ -209,6 +296,15 @@ openvpn_encrypt (struct buffer *buf, struct buffer work,  	  ASSERT (output);  	  hmac_ctx_final (ctx->hmac, output);  	} +      else if (cipher_kt && cipher_kt_mode_aead(cipher_kt)) +	{ +	  int tag_len = cipher_kt_tag_size (cipher_kt); +	  uint8_t* output = NULL; + +	  output = buf_prepend (&work, tag_len); +	  ASSERT (output); +	  ASSERT (cipher_ctx_get_tag (ctx->cipher, output, tag_len)); +	}        *buf = work;      } @@ -223,6 +319,30 @@ err:    return;  } +int verify_hmac(struct buffer *buf, struct key_ctx *ctx, int offset) +{ +  uint8_t local_hmac[MAX_HMAC_KEY_LENGTH]; /* HMAC of ciphertext computed locally */ +  int hmac_len = 0; + +  hmac_ctx_reset(ctx->hmac); +  /* Assume the length of the input HMAC */ +  hmac_len = hmac_ctx_size (ctx->hmac); + +  /* Authentication fails if insufficient data in packet for HMAC */ +  if (buf->len - offset < hmac_len) +    return 0; + +  hmac_ctx_update (ctx->hmac, BPTR (buf) + hmac_len + offset, +  	BLEN (buf) - hmac_len - offset); +  hmac_ctx_final (ctx->hmac, local_hmac); + +  /* Compare locally computed HMAC with packet HMAC */ +  if (memcmp_constant_time (local_hmac, BPTR (buf) + offset, hmac_len) == 0) +    return hmac_len; + +  return 0; +} +  /*   * If (opt->flags & CO_USE_IV) is not NULL, we will read an IV from the packet.   * @@ -233,64 +353,68 @@ err:   */  bool  openvpn_decrypt (struct buffer *buf, struct buffer work, -		 const struct crypto_options *opt, -		 const struct frame* frame) +		 struct crypto_options *opt, const struct frame* frame)  {    static const char error_prefix[] = "Authenticate/Decrypt packet error";    struct gc_arena gc;    gc_init (&gc); -  if (buf->len > 0 && opt->key_ctx_bi) +  if (buf->len > 0 && opt)      { -      struct key_ctx *ctx = &opt->key_ctx_bi->decrypt; +      const struct key_ctx *ctx = &opt->key_ctx_bi.decrypt;        struct packet_id_net pin;        bool have_pin = false; +      crypto_options_debug(D_CRYPTO_DEBUG, __func__, opt); +        /* Verify the HMAC */        if (ctx->hmac)  	{ -	  int hmac_len; -	  uint8_t local_hmac[MAX_HMAC_KEY_LENGTH]; /* HMAC of ciphertext computed locally */ - -	  hmac_ctx_reset(ctx->hmac); - -	  /* Assume the length of the input HMAC */ -	  hmac_len = hmac_ctx_size (ctx->hmac); - -	  /* Authentication fails if insufficient data in packet for HMAC */ -	  if (buf->len < hmac_len) -	    CRYPT_ERROR ("missing authentication info"); - -	  hmac_ctx_update (ctx->hmac, BPTR (buf) + hmac_len, BLEN (buf) - hmac_len); -	  hmac_ctx_final (ctx->hmac, local_hmac); - -	  /* Compare locally computed HMAC with packet HMAC */ -	  if (memcmp_constant_time (local_hmac, BPTR (buf), hmac_len)) +	  int hmac_len = verify_hmac(buf, ctx, 0); +	  if (hmac_len == 0)  	    CRYPT_ERROR ("packet HMAC authentication failed"); -  	  ASSERT (buf_advance (buf, hmac_len));  	}        /* Decrypt packet ID + payload */ -        if (ctx->cipher)  	{  	  const int iv_size = cipher_ctx_iv_length (ctx->cipher);  	  const cipher_kt_t *cipher_kt = cipher_ctx_get_cipher_kt (ctx->cipher);  	  uint8_t iv_buf[OPENVPN_MAX_IV_LENGTH]; +	  int tag_size = 0; +	  uint8_t tag_buf[MAX_HMAC_KEY_LENGTH]; /* tag of AEAD ciphertext */  	  int outlen; +	  int retval = 0;  	  /* initialize work buffer with FRAME_HEADROOM bytes of prepend capacity */  	  ASSERT (buf_init (&work, FRAME_HEADROOM_ADJ (frame, FRAME_HEADROOM_MARKER_DECRYPT))); +	  /* for AEAD ciphers, keep the tag value to feed in later */ +	  CLEAR (tag_buf); +	  if (cipher_kt_mode_aead(cipher_kt)) +	    { +	      tag_size = cipher_kt_tag_size(cipher_kt); +	      if (buf->len < tag_size) +		CRYPT_ERROR ("missing tag"); +	      memcpy (tag_buf, BPTR (buf), tag_size); +	      ASSERT (buf_advance (buf, tag_size)); +	    } +  	  /* use IV if user requested it */  	  CLEAR (iv_buf);  	  if (opt->flags & CO_USE_IV)  	    { -	      if (buf->len < iv_size) +	      ASSERT (ctx->implicit_iv_len <= iv_size); +	      if (ctx->implicit_iv_len + buf->len < iv_size)  		CRYPT_ERROR ("missing IV info"); -	      memcpy (iv_buf, BPTR (buf), iv_size); -	      ASSERT (buf_advance (buf, iv_size)); + +	      /* Get implicit part of IV */ +	      memcpy (iv_buf, ctx->implicit_iv, ctx->implicit_iv_len); +	      /* Read explicit part of IV from packet */ +	      memcpy (iv_buf + ctx->implicit_iv_len, BPTR (buf), +		  iv_size - ctx->implicit_iv_len); +	      ASSERT (buf_advance (buf, iv_size - ctx->implicit_iv_len));  	    }  	  /* show the IV's initial state */ @@ -308,13 +432,25 @@ openvpn_decrypt (struct buffer *buf, struct buffer work,  	  if (!buf_safe (&work, buf->len))  	    CRYPT_ERROR ("buffer overflow"); +	  /* feed in tag and the authenticated data for AEAD mode ciphers */ +	  if (cipher_kt_mode_aead(cipher_kt)) +	    { +	      ASSERT (cipher_ctx_update_ad (ctx->cipher, iv_buf, iv_size)); +	    } +  	  /* Decrypt packet ID, payload */  	  if (!cipher_ctx_update (ctx->cipher, BPTR (&work), &outlen, BPTR (buf), BLEN (buf)))  	    CRYPT_ERROR ("cipher update failed");  	  work.len += outlen;  	  /* Flush the decryption buffer */ -	  if (!cipher_ctx_final (ctx->cipher, BPTR (&work) + outlen, &outlen)) +	  if (cipher_kt_mode_aead(cipher_kt)) { +	    retval = cipher_ctx_final_check_tag (ctx->cipher, BPTR (&work) + outlen, &outlen, tag_buf, tag_size); +	  } else { +	    retval = cipher_ctx_final (ctx->cipher, BPTR (&work) + outlen, &outlen); +	  } + +	  if (!retval)  	    CRYPT_ERROR ("cipher final failed");  	  work.len += outlen; @@ -325,26 +461,30 @@ openvpn_decrypt (struct buffer *buf, struct buffer work,  	  {  	    if (cipher_kt_mode_cbc(cipher_kt))  	      { -		if (opt->packet_id) +		if (packet_id_initialized(&opt->packet_id))  		  {  		    if (!packet_id_read (&pin, &work, BOOL_CAST (opt->flags & CO_PACKET_ID_LONG_FORM)))  		      CRYPT_ERROR ("error reading CBC packet-id");  		    have_pin = true;  		  }  	      } -	    else if (cipher_kt_mode_ofb_cfb(cipher_kt)) +	    else if (cipher_kt_mode_ofb_cfb(cipher_kt) || +		cipher_kt_mode_aead(cipher_kt))  	      {  		struct buffer b;  		ASSERT (opt->flags & CO_USE_IV);    /* IV and packet-ID required */ -		ASSERT (opt->packet_id); /*  for this mode. */ +		ASSERT (packet_id_initialized(&opt->packet_id)); /*  for this mode. */ + +		ASSERT (ctx->implicit_iv_len <= iv_size); +		buf_set_read (&b, iv_buf + ctx->implicit_iv_len, +		    iv_size - ctx->implicit_iv_len); -		buf_set_read (&b, iv_buf, iv_size); -		if (!packet_id_read (&pin, &b, true)) -		  CRYPT_ERROR ("error reading CFB/OFB packet-id"); +		if (!packet_id_read (&pin, &b, !ctx->implicit_iv_len)) +		  CRYPT_ERROR ("error reading CFB/OFB/AEAD packet-id");  		have_pin = true;  	      } -	    else /* We only support CBC, CFB, or OFB modes right now */ +	    else /* We only support CBC, CFB, OFB, or AEAD modes right now */  	      {  		ASSERT (0);  	      } @@ -353,7 +493,7 @@ openvpn_decrypt (struct buffer *buf, struct buffer work,        else  	{  	  work = *buf; -	  if (opt->packet_id) +	  if (packet_id_initialized(&opt->packet_id))  	    {  	      if (!packet_id_read (&pin, &work, BOOL_CAST (opt->flags & CO_PACKET_ID_LONG_FORM)))  		CRYPT_ERROR ("error reading packet-id"); @@ -363,12 +503,13 @@ openvpn_decrypt (struct buffer *buf, struct buffer work,        if (have_pin)  	{ -	  packet_id_reap_test (&opt->packet_id->rec); -	  if (packet_id_test (&opt->packet_id->rec, &pin)) +	  packet_id_reap_test (&opt->packet_id.rec); +	  if (packet_id_test (&opt->packet_id.rec, &pin))  	    { -	      packet_id_add (&opt->packet_id->rec, &pin); -	      if (opt->pid_persist && (opt->flags & CO_PACKET_ID_LONG_FORM)) -		packet_id_persist_save_obj (opt->pid_persist, opt->packet_id); +	      packet_id_add (&opt->packet_id.rec, &pin); +	      if (opt->pid_persist && (opt->flags & CO_PACKET_ID_LONG_FORM) && +		  !ctx->implicit_iv_len) +		packet_id_persist_save_obj (opt->pid_persist, &opt->packet_id);  	    }  	  else  	    { @@ -399,49 +540,17 @@ openvpn_decrypt (struct buffer *buf, struct buffer work,  bool  crypto_test_hmac (struct buffer *buf, const struct crypto_options *opt)  { -  struct gc_arena gc; -  gc_init (&gc); -  int offset = 4; /* 1 byte opcode + 3 bytes session-id */ - -  if (buf->len > 0 && opt->key_ctx_bi) +  if (buf->len > 0 && opt)      { -      struct key_ctx *ctx = &opt->key_ctx_bi->decrypt; +      const struct key_ctx *ctx = &opt->key_ctx_bi.decrypt;        /* Verify the HMAC */        if (ctx->hmac)  	{ -	  int hmac_len; -	  uint8_t local_hmac[MAX_HMAC_KEY_LENGTH]; /* HMAC of ciphertext computed locally */ - -	  hmac_ctx_reset(ctx->hmac); - -	  /* Assume the length of the input HMAC */ -	  hmac_len = hmac_ctx_size (ctx->hmac); - -	  /* Authentication fails if insufficient data in packet for HMAC */ -	  if ((buf->len - offset) < hmac_len) -	    { -	      gc_free (&gc); -	      return false; -	    } - -	  hmac_ctx_update (ctx->hmac, BPTR (buf) + offset + hmac_len, -			   BLEN (buf) - offset - hmac_len); -	  hmac_ctx_final (ctx->hmac, local_hmac); - -	  /* Compare locally computed HMAC with packet HMAC */ -	  if (memcmp_constant_time (local_hmac, BPTR (buf) + offset, hmac_len)) -	    { -	      gc_free (&gc); -	      return false; -	    } - -	  gc_free (&gc); -	  return true; +	  /* sizeof(uint32_t) comes from peer_id (3 bytes) and opcode (1 byte) */ +	  return verify_hmac(buf, ctx, sizeof(uint32_t)) != 0;  	}      } - -  gc_free (&gc);    return false;  } @@ -457,11 +566,30 @@ crypto_adjust_frame_parameters(struct frame *frame,  			       bool packet_id,  			       bool packet_id_long_form)  { -  frame_add_to_extra_frame (frame, -			    (packet_id ? packet_id_size (packet_id_long_form) : 0) + -			    ((cipher_defined && use_iv) ? cipher_kt_iv_size (kt->cipher) : 0) + -			    (cipher_defined ? cipher_kt_block_size (kt->cipher) : 0) + /* worst case padding expansion */ -			    kt->hmac_length); +  size_t crypto_overhead = 0; + +  if (packet_id) +    crypto_overhead += packet_id_size (packet_id_long_form); + +  if (cipher_defined) +    { +      if (use_iv) +	crypto_overhead += cipher_kt_iv_size (kt->cipher); + +      if (cipher_kt_mode_aead (kt->cipher)) +	crypto_overhead += cipher_kt_tag_size (kt->cipher); + +      if (cipher_kt_mode_cbc (kt->cipher)) +	/* worst case padding expansion */ +	crypto_overhead += cipher_kt_block_size (kt->cipher); +    } + +  crypto_overhead += kt->hmac_length; + +  frame_add_to_extra_frame (frame, crypto_overhead); + +  msg(D_MTU_DEBUG, "%s: Adjusting frame parameters for crypto by %zu bytes", +      __func__, crypto_overhead);  }  /* @@ -471,8 +599,10 @@ void  init_key_type (struct key_type *kt, const char *ciphername,  	       bool ciphername_defined, const char *authname,  	       bool authname_defined, int keysize, -	       bool cfb_ofb_allowed, bool warn) +	       bool tls_mode, bool warn)  { +  bool aead_cipher = false; +    CLEAR (*kt);    if (ciphername && ciphername_defined)      { @@ -482,14 +612,14 @@ init_key_type (struct key_type *kt, const char *ciphername,  	kt->cipher_length = keysize;        /* check legal cipher mode */ -      { -	if (!(cipher_kt_mode_cbc(kt->cipher) +      aead_cipher = cipher_kt_mode_aead(kt->cipher); +      if (!(cipher_kt_mode_cbc(kt->cipher) +	    || (tls_mode && aead_cipher)  #ifdef ENABLE_OFB_CFB_MODE -	      || (cfb_ofb_allowed && cipher_kt_mode_ofb_cfb(kt->cipher)) +	    || (tls_mode && cipher_kt_mode_ofb_cfb(kt->cipher))  #endif -	      )) -	  msg (M_FATAL, "Cipher '%s' mode not supported", ciphername); -      } +	    )) +	msg (M_FATAL, "Cipher '%s' mode not supported", ciphername);      }    else      { @@ -498,10 +628,12 @@ init_key_type (struct key_type *kt, const char *ciphername,      }    if (authname && authname_defined)      { -      kt->digest = md_kt_get (authname); -      kt->hmac_length = md_kt_size (kt->digest); +      if (!aead_cipher) { /* Ignore auth for AEAD ciphers */ +	kt->digest = md_kt_get (authname); +	kt->hmac_length = md_kt_size (kt->digest); +      }      } -  else +  else if (!aead_cipher)      {        if (warn)  	msg (M_WARN, "******* WARNING *******: null MAC specified, no authentication will be used"); @@ -525,7 +657,7 @@ init_key_ctx (struct key_ctx *ctx, struct key *key,        msg (D_HANDSHAKE, "%s: Cipher '%s' initialized with %d bit key",            prefix, -          cipher_kt_name(kt->cipher), +          translate_cipher_name_to_openvpn(cipher_kt_name(kt->cipher)),            kt->cipher_length *8);        dmsg (D_SHOW_KEYS, "%s: CIPHER KEY: %s", prefix, @@ -571,6 +703,12 @@ free_key_ctx (struct key_ctx *ctx)        free(ctx->hmac);        ctx->hmac = NULL;      } +  if (ctx->implicit_iv) +    { +      free(ctx->implicit_iv); +      ctx->implicit_iv = 0; +    } +  ctx->implicit_iv_len = 0;  }  void @@ -580,6 +718,20 @@ free_key_ctx_bi (struct key_ctx_bi *ctx)    free_key_ctx(&ctx->decrypt);  } +bool +key_ctx_set_implicit_iv (struct key_ctx *ctx, const uint8_t *iv, size_t len) +{ +  if (ctx->implicit_iv) free (ctx->implicit_iv); + +  ctx->implicit_iv = malloc (len); +  if (!ctx->implicit_iv) return false; + +  ctx->implicit_iv_len = len; +  memcpy (ctx->implicit_iv, iv, len); + +  return true; +} +  static bool  key_is_zero (struct key *key, const struct key_type *kt) @@ -727,7 +879,7 @@ key2_print (const struct key2* k,  }  void -test_crypto (const struct crypto_options *co, struct frame* frame) +test_crypto (struct crypto_options *co, struct frame* frame)  {    int i, j;    struct gc_arena gc = gc_new (); @@ -740,6 +892,22 @@ test_crypto (const struct crypto_options *co, struct frame* frame)    /* init work */    ASSERT (buf_init (&work, FRAME_HEADROOM (frame))); +#ifdef HAVE_AEAD_CIPHER_MODES +  /* init implicit IV */ +  { +    const cipher_kt_t *cipher = cipher_ctx_get_cipher_kt( +	co->key_ctx_bi.encrypt.cipher); + +    if (cipher_kt_mode_aead(cipher)) +      { +	key_ctx_set_implicit_iv(&co->key_ctx_bi.encrypt,\ +	    (const uint8_t *) "01234567", 8); +	key_ctx_set_implicit_iv(&co->key_ctx_bi.decrypt, +	    (const uint8_t *) "01234567", 8); +      } +  } +#endif +    msg (M_INFO, "Entering " PACKAGE_NAME " crypto self-test mode.");    for (i = 1; i <= TUN_MTU_SIZE (frame); ++i)      { @@ -792,13 +960,8 @@ get_tls_handshake_key (const struct key_type *key_type,    if (passphrase_file && key_type->hmac_length)      {        struct key2 key2; -      struct key_type kt = *key_type;        struct key_direction_state kds; -      /* for control channel we are only authenticating, not encrypting */ -      kt.cipher_length = 0; -      kt.cipher = NULL; -        if (flags & GHK_INLINE)  	{  	  /* key was specified inline, key text is in passphrase_file */ @@ -830,10 +993,10 @@ get_tls_handshake_key (const struct key_type *key_type,  	    /* failed, now try to get hash from a freeform file */  	    hash_size = read_passphrase_hash (passphrase_file, -					      kt.digest, +					      key_type->digest,  					      key2.keys[0].hmac,  					      MAX_HMAC_KEY_LENGTH); -	    ASSERT (hash_size == kt.hmac_length); +	    ASSERT (hash_size == key_type->hmac_length);  	    /* suceeded */  	    key2.n = 1; @@ -850,9 +1013,9 @@ get_tls_handshake_key (const struct key_type *key_type,        /* initialize hmac key in both directions */ -      init_key_ctx (&ctx->encrypt, &key2.keys[kds.out_key], &kt, OPENVPN_OP_ENCRYPT, +      init_key_ctx (&ctx->encrypt, &key2.keys[kds.out_key], key_type, OPENVPN_OP_ENCRYPT,  		    "Outgoing Control Channel Authentication"); -      init_key_ctx (&ctx->decrypt, &key2.keys[kds.in_key], &kt, OPENVPN_OP_DECRYPT, +      init_key_ctx (&ctx->decrypt, &key2.keys[kds.in_key], key_type, OPENVPN_OP_DECRYPT,  		    "Incoming Control Channel Authentication");        CLEAR (key2); @@ -1508,4 +1671,42 @@ md5_digest_equal (const struct md5_digest *d1, const struct md5_digest *d2)    return memcmp(d1->digest, d2->digest, MD5_DIGEST_LENGTH) == 0;  } +static const cipher_name_pair * +get_cipher_name_pair(const char *cipher_name) { +  const cipher_name_pair *pair; +  size_t i = 0; + +  /* Search for a cipher name translation */ +  for (; i < cipher_name_translation_table_count; i++) +    { +      pair = &cipher_name_translation_table[i]; +      if (0 == strcmp (cipher_name, pair->openvpn_name) || +	  0 == strcmp (cipher_name, pair->ssllib_name)) +	  return pair; +    } + +  /* Nothing found, return null */ +  return NULL; +} + +const char * +translate_cipher_name_from_openvpn (const char *cipher_name) { +  const cipher_name_pair *pair = get_cipher_name_pair(cipher_name); + +  if (NULL == pair) +    return cipher_name; + +  return pair->ssllib_name; +} + +const char * +translate_cipher_name_to_openvpn (const char *cipher_name) { +  const cipher_name_pair *pair = get_cipher_name_pair(cipher_name); + +  if (NULL == pair) +    return cipher_name; + +  return pair->openvpn_name; +} +  #endif /* ENABLE_CRYPTO */ diff --git a/main/openvpn/src/openvpn/crypto.h b/main/openvpn/src/openvpn/crypto.h index 3c4e59d7..b0b1df48 100644 --- a/main/openvpn/src/openvpn/crypto.h +++ b/main/openvpn/src/openvpn/crypto.h @@ -63,13 +63,15 @@ struct key  /** - * Container for one set of OpenSSL cipher and/or HMAC contexts. + * Container for one set of cipher and/or HMAC contexts.   * @ingroup control_processor   */  struct key_ctx  {    cipher_ctx_t *cipher;      	/**< Generic cipher %context. */ -  hmac_ctx_t *hmac;               /**< Generic HMAC %context. */ +  hmac_ctx_t *hmac;             /**< Generic HMAC %context. */ +  uint8_t *implicit_iv;		/**< The implicit part of the IV */ +  size_t implicit_iv_len;       /**< The length of implicit_iv */  };  #define KEY_DIRECTION_BIDIRECTIONAL 0 /* same keys for both directions */ @@ -120,10 +122,10 @@ struct key_direction_state   */  struct key_ctx_bi  { -  struct key_ctx encrypt;       /**< OpenSSL cipher and/or HMAC contexts -                                 *   for sending direction. */ -  struct key_ctx decrypt;       /**< OpenSSL cipher and/or HMAC contexts -                                 *   for receiving direction. */ +  struct key_ctx encrypt;       /**< Cipher and/or HMAC contexts for sending +				 *   direction. */ +  struct key_ctx decrypt;       /**< cipher and/or HMAC contexts for +                                 *   receiving direction. */  };  /** @@ -132,11 +134,11 @@ struct key_ctx_bi   */  struct crypto_options  { -  struct key_ctx_bi *key_ctx_bi; +  struct key_ctx_bi key_ctx_bi;                                  /**< OpenSSL cipher and HMAC contexts for                                   *   both sending and receiving                                   *   directions. */ -  struct packet_id *packet_id;  /**< Current packet ID state for both +  struct packet_id packet_id;   /**< Current packet ID state for both                                   *   sending and receiving directions. */    struct packet_id_persist *pid_persist;                                  /**< Persistent packet ID state for @@ -203,6 +205,17 @@ void free_key_ctx (struct key_ctx *ctx);  void free_key_ctx_bi (struct key_ctx_bi *ctx); +/** + * Set an implicit IV for a key context. + * + * @param ctx	The key context to update + * @param iv	The implicit IV to load into ctx + * @param len	The length (in bytes) of iv + */ +bool key_ctx_set_implicit_iv (struct key_ctx *ctx, const uint8_t *iv, +    size_t len); + +  /**************************************************************************/  /** @name Functions for performing security operations on data channel packets @@ -236,8 +249,7 @@ void free_key_ctx_bi (struct key_ctx_bi *ctx);   *     error occurred.   */  void openvpn_encrypt (struct buffer *buf, struct buffer work, -		      const struct crypto_options *opt, -		      const struct frame* frame); +		      struct crypto_options *opt, const struct frame* frame);  /** @@ -272,8 +284,7 @@ void openvpn_encrypt (struct buffer *buf, struct buffer work,   *     an error occurred.   */  bool openvpn_decrypt (struct buffer *buf, struct buffer work, -		      const struct crypto_options *opt, -		      const struct frame* frame); +		      struct crypto_options *opt, const struct frame* frame);  bool crypto_test_hmac (struct buffer *buf, const struct crypto_options *opt); @@ -325,7 +336,7 @@ void prng_bytes (uint8_t *output, int len);  void prng_uninit (); -void test_crypto (const struct crypto_options *co, struct frame* f); +void test_crypto (struct crypto_options *co, struct frame* f);  /* key direction functions */ diff --git a/main/openvpn/src/openvpn/crypto_backend.h b/main/openvpn/src/openvpn/crypto_backend.h index bc067a7d..faf40594 100644 --- a/main/openvpn/src/openvpn/crypto_backend.h +++ b/main/openvpn/src/openvpn/crypto_backend.h @@ -38,6 +38,18 @@  #endif  #include "basic.h" +/* TLS uses a tag of 128 bytes, let's do the same for OpenVPN */ +#define OPENVPN_AEAD_TAG_LENGTH 16 + +/** Struct used in cipher name translation table */ +typedef struct { +  const char * openvpn_name; +  const char * ssllib_name; +} cipher_name_pair; + +/** Cipher name translation table */ +extern const cipher_name_pair cipher_name_translation_table[]; +extern const size_t cipher_name_translation_table_count;  /*   * This routine should have additional OpenSSL crypto library initialisations @@ -221,6 +233,16 @@ int cipher_kt_iv_size (const cipher_kt_t *cipher_kt);  int cipher_kt_block_size (const cipher_kt_t *cipher_kt);  /** + * Returns the MAC tag size of the cipher, in bytes. + * + * @param ctx		Static cipher parameters. May not be NULL. + * + * @return		Tag size, in bytes, or 0 if the cipher is not an + * 			authenticated encryption mode. + */ +int cipher_kt_tag_size (const cipher_kt_t *cipher_kt); + +/**   * Returns the mode that the cipher runs in.   *   * @param cipher_kt 	Static cipher parameters @@ -250,6 +272,16 @@ bool cipher_kt_mode_cbc(const cipher_kt_t *cipher)  bool cipher_kt_mode_ofb_cfb(const cipher_kt_t *cipher)    __attribute__((nonnull)); +/** + * Check if the supplied cipher is a supported AEAD mode cipher. + * + * @param cipher	Static cipher parameters. May not be NULL. + * + * @return		true iff the cipher is a AEAD mode cipher. + */ +bool cipher_kt_mode_aead(const cipher_kt_t *cipher) +  __attribute__((nonnull)); +  /**   * @@ -289,6 +321,15 @@ void cipher_ctx_cleanup (cipher_ctx_t *ctx);  int cipher_ctx_iv_length (const cipher_ctx_t *ctx);  /** + * Gets the computed message authenticated code (MAC) tag for this cipher. + * + * @param ctx		The cipher's context + * @param tag		The buffer to write computed tag in. + * @param tag_size	The tag buffer size, in bytes. + */ +int cipher_ctx_get_tag (cipher_ctx_t *ctx, uint8_t* tag, int tag_len); + +/**   * Returns the block size of the cipher, in bytes.   *   * @param ctx	 	The cipher's context @@ -329,6 +370,18 @@ const cipher_kt_t *cipher_ctx_get_cipher_kt (const cipher_ctx_t *ctx)  int cipher_ctx_reset (cipher_ctx_t *ctx, uint8_t *iv_buf);  /** + * Updates the given cipher context, setting the additional data (AD) used + * with authenticated encryption with additional data (AEAD) cipher modes. + * + * @param ctx 		Cipher's context. May not be NULL. + * @param src		Source buffer + * @param src_len	Length of the source buffer, in bytes + * + * @return 		\c 0 on failure, \c 1 on success. + */ +int cipher_ctx_update_ad (cipher_ctx_t *ctx, uint8_t *src, int src_len); + +/**   * Updates the given cipher context, encrypting data in the source buffer, and   * placing any complete blocks in the destination buffer.   * @@ -360,6 +413,22 @@ int cipher_ctx_update (cipher_ctx_t *ctx, uint8_t *dst, int *dst_len,   */  int cipher_ctx_final (cipher_ctx_t *ctx, uint8_t *dst, int *dst_len); +/** + * Like \c cipher_ctx_final, but check the computed authentication tag against + * the supplied (expected) tag. This function reports failure when the tags + * don't match. + * + * @param ctx           Cipher's context. May not be NULL. + * @param dst           Destination buffer. + * @param dst_len       Length of the destination buffer, in bytes. + * @param tag           The expected authentication tag. + * @param tag_len       The length of tag, in bytes. + * + * @return              \c 0 on failure, \c 1 on success. + */ +int cipher_ctx_final_check_tag (cipher_ctx_t *ctx, uint8_t *dst, int *dst_len, +    const uint8_t *tag, size_t tag_len); +  /*   *   * Generic message digest information functions @@ -527,4 +596,19 @@ void hmac_ctx_update (hmac_ctx_t *ctx, const uint8_t *src, int src_len);   */  void hmac_ctx_final (hmac_ctx_t *ctx, uint8_t *dst); +/** + * Check if mode is an AEAD cipher mode. + * + * @param mode          The mode to check. + * + * @return              true if mode is a supported AEAD mode, false otherwise. + */ +bool crypto_aead_mode (int mode); + +/** XXX doxygen */ +const char * translate_cipher_name_from_openvpn (const char *cipher_name); + +/** XXX doxygen */ +const char * translate_cipher_name_to_openvpn (const char *cipher_name); +  #endif /* CRYPTO_BACKEND_H_ */ diff --git a/main/openvpn/src/openvpn/crypto_openssl.c b/main/openvpn/src/openvpn/crypto_openssl.c index 0ac89a19..ef487944 100644 --- a/main/openvpn/src/openvpn/crypto_openssl.c +++ b/main/openvpn/src/openvpn/crypto_openssl.c @@ -45,6 +45,8 @@  #include <openssl/objects.h>  #include <openssl/evp.h>  #include <openssl/des.h> +#include <openssl/ssl.h> +#include <openssl/err.h>  /*   * Check for key size creepage. @@ -100,13 +102,14 @@ setup_engine (const char *engine)        if ((e = ENGINE_by_id (engine)) == NULL  	 && (e = try_load_engine (engine)) == NULL)  	{ -	  msg (M_FATAL, "OpenSSL error: cannot load engine '%s'", engine); +	  crypto_msg (M_FATAL, "OpenSSL error: cannot load engine '%s'", +	      engine);  	}        if (!ENGINE_set_default (e, ENGINE_METHOD_ALL))  	{ -	  msg (M_FATAL, "OpenSSL error: ENGINE_set_default failed on engine '%s'", -	       engine); +	  crypto_msg (M_FATAL, "OpenSSL error: ENGINE_set_default failed on " +	      "engine '%s'", engine);  	}        msg (M_INFO, "Initializing OpenSSL support for engine '%s'", @@ -195,6 +198,26 @@ crypto_clear_error (void)    ERR_clear_error ();  } +void +crypto_print_openssl_errors(const unsigned int flags) { +  size_t err = 0; + +  while ((err = ERR_get_error ())) +    { +      /* Be more clear about frequently occurring "no shared cipher" error */ +      if (err == ERR_PACK(ERR_LIB_SSL,SSL_F_SSL3_GET_CLIENT_HELLO, +	  SSL_R_NO_SHARED_CIPHER)) +	{ +	  msg (D_CRYPT_ERRORS, "TLS error: The server has no TLS ciphersuites " +	      "in common with the client. Your --tls-cipher setting might be " +	      "too restrictive."); +	} + +      msg (flags, "OpenSSL: %s", ERR_error_string (err, NULL)); +    } +} + +  /*   *   * OpenSSL memory debugging.  If dmalloc debugging is enabled, tell @@ -231,17 +254,17 @@ crypto_init_dmalloc (void)  }  #endif /* DMALLOC */ -const char * -translate_cipher_name_from_openvpn (const char *cipher_name) { -  // OpenSSL doesn't require any translation -  return cipher_name; -} +const cipher_name_pair cipher_name_translation_table[] = { +    { "AES-128-CCM", "id-aes128-CCM" }, +    { "AES-192-CCM", "id-aes192-CCM" }, +    { "AES-256-CCM", "id-aes256-CCM" }, +    { "AES-128-GCM", "id-aes128-GCM" }, +    { "AES-192-GCM", "id-aes192-GCM" }, +    { "AES-256-GCM", "id-aes256-GCM" }, +}; +const size_t cipher_name_translation_table_count = +    sizeof (cipher_name_translation_table) / sizeof (*cipher_name_translation_table); -const char * -translate_cipher_name_to_openvpn (const char *cipher_name) { -  // OpenSSL doesn't require any translation -  return cipher_name; -}  void  show_available_ciphers () @@ -249,12 +272,12 @@ show_available_ciphers ()    int nid;  #ifndef ENABLE_SMALL -  printf ("The following ciphers and cipher modes are available\n" -	  "for use with " PACKAGE_NAME ".  Each cipher shown below may be\n" -	  "used as a parameter to the --cipher option.  The default\n" -	  "key size is shown as well as whether or not it can be\n" -          "changed with the --keysize directive.  Using a CBC mode\n" -	  "is recommended. In static key mode only CBC mode is allowed.\n\n"); +  printf ("The following ciphers and cipher modes are available for use\n" +	  "with " PACKAGE_NAME ".  Each cipher shown below may be use as a\n" +	  "parameter to the --cipher option.  The default key size is\n" +	  "shown as well as whether or not it can be changed with the\n" +          "--keysize directive.  Using a CBC or GCM mode is recommended.\n" +	  "In static key mode only CBC mode is allowed.\n\n");  #endif    for (nid = 0; nid < 10000; ++nid)	/* is there a better way to get the size of the nid list? */ @@ -266,17 +289,20 @@ show_available_ciphers ()  #ifdef ENABLE_OFB_CFB_MODE  	      || cipher_kt_mode_ofb_cfb(cipher)  #endif +#ifdef HAVE_AEAD_CIPHER_MODES +	      || cipher_kt_mode_aead(cipher) +#endif  	      )  	    {  	      const char *var_key_size =  		  (EVP_CIPHER_flags (cipher) & EVP_CIPH_VARIABLE_LENGTH) ?  		       "variable" : "fixed"; -	      const char *ssl_only = cipher_kt_mode_ofb_cfb(cipher) ? -		  " (TLS client/server mode)" : ""; +	      const char *ssl_only = cipher_kt_mode_cbc(cipher) ? +		  "" : " (TLS client/server mode)"; -	      printf ("%s %d bit default key (%s)%s\n", OBJ_nid2sn (nid), -		      EVP_CIPHER_key_length (cipher) * 8, var_key_size, -		      ssl_only); +	      printf ("%s %d bit default key (%s)%s\n", +		  translate_cipher_name_to_openvpn(OBJ_nid2sn (nid)), +		  EVP_CIPHER_key_length (cipher) * 8, var_key_size, ssl_only);  	    }  	}      } @@ -386,17 +412,20 @@ key_des_check (uint8_t *key, int key_len, int ndc)        DES_cblock *dc = (DES_cblock*) buf_read_alloc (&b, sizeof (DES_cblock));        if (!dc)  	{ -	  msg (D_CRYPT_ERRORS, "CRYPTO INFO: check_key_DES: insufficient key material"); +	  msg (D_CRYPT_ERRORS, "CRYPTO INFO: check_key_DES: insufficient key " +	      "material");  	  goto err;  	}        if (DES_is_weak_key(dc))  	{ -	  msg (D_CRYPT_ERRORS, "CRYPTO INFO: check_key_DES: weak key detected"); +	  crypto_msg (D_CRYPT_ERRORS, "CRYPTO INFO: check_key_DES: weak key " +	      "detected");  	  goto err;  	}        if (!DES_check_key_parity (dc))  	{ -	  msg (D_CRYPT_ERRORS, "CRYPTO INFO: check_key_DES: bad parity detected"); +	  crypto_msg (D_CRYPT_ERRORS, "CRYPTO INFO: check_key_DES: bad parity " +	      "detected");  	  goto err;  	}      } @@ -445,7 +474,7 @@ cipher_kt_get (const char *ciphername)    cipher = EVP_get_cipherbyname (ciphername);    if (NULL == cipher) -    msg (M_SSLERR, "Cipher algorithm '%s' not found", ciphername); +    crypto_msg (M_FATAL, "Cipher algorithm '%s' not found", ciphername);    if (EVP_CIPHER_key_length (cipher) > MAX_CIPHER_KEY_LENGTH)      msg (M_FATAL, "Cipher algorithm '%s' uses a default key size (%d bytes) which is larger than " PACKAGE_NAME "'s current maximum key size (%d bytes)", @@ -483,6 +512,15 @@ cipher_kt_block_size (const EVP_CIPHER *cipher_kt)  }  int +cipher_kt_tag_size (const EVP_CIPHER *cipher_kt) +{ +  if (cipher_kt_mode_aead(cipher_kt)) +    return OPENVPN_AEAD_TAG_LENGTH; +  else +    return 0; +} + +int  cipher_kt_mode (const EVP_CIPHER *cipher_kt)  {    ASSERT(NULL != cipher_kt); @@ -512,6 +550,17 @@ cipher_kt_mode_ofb_cfb(const cipher_kt_t *cipher)      ;  } +bool +cipher_kt_mode_aead(const cipher_kt_t *cipher) +{ +#ifdef HAVE_AEAD_CIPHER_MODES +  return (cipher_kt_mode(cipher) == OPENVPN_MODE_GCM || +	  cipher_kt_mode(cipher) == OPENVPN_MODE_CCM); +#else +  return false; +#endif +} +  /*   *   * Generic cipher context functions @@ -529,13 +578,13 @@ cipher_ctx_init (EVP_CIPHER_CTX *ctx, uint8_t *key, int key_len,    EVP_CIPHER_CTX_init (ctx);    if (!EVP_CipherInit (ctx, kt, NULL, NULL, enc)) -    msg (M_SSLERR, "EVP cipher init #1"); +    crypto_msg (M_FATAL, "EVP cipher init #1");  #ifdef HAVE_EVP_CIPHER_CTX_SET_KEY_LENGTH    if (!EVP_CIPHER_CTX_set_key_length (ctx, key_len)) -    msg (M_SSLERR, "EVP set key size"); +    crypto_msg (M_FATAL, "EVP set key size");  #endif    if (!EVP_CipherInit (ctx, NULL, key, NULL, enc)) -    msg (M_SSLERR, "EVP cipher init #2"); +    crypto_msg (M_FATAL, "EVP cipher init #2");    /* make sure we used a big enough key */    ASSERT (EVP_CIPHER_CTX_key_length (ctx) <= key_len); @@ -553,6 +602,15 @@ cipher_ctx_iv_length (const EVP_CIPHER_CTX *ctx)    return EVP_CIPHER_CTX_iv_length (ctx);  } +int cipher_ctx_get_tag (EVP_CIPHER_CTX *ctx, uint8_t *tag_buf, int tag_size) +{ +#ifdef HAVE_AEAD_CIPHER_MODES +  return EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_GET_TAG, tag_size, tag_buf); +#else +  ASSERT (0); +#endif +} +  int  cipher_ctx_block_size(const EVP_CIPHER_CTX *ctx)  { @@ -579,6 +637,17 @@ cipher_ctx_reset (EVP_CIPHER_CTX *ctx, uint8_t *iv_buf)  }  int +cipher_ctx_update_ad (EVP_CIPHER_CTX *ctx, uint8_t* src, int src_len) +{ +#ifdef HAVE_AEAD_CIPHER_MODES +  int len; +  return EVP_CipherUpdate (ctx, NULL, &len, src, src_len); +#else +  ASSERT (0); +#endif +} + +int  cipher_ctx_update (EVP_CIPHER_CTX *ctx, uint8_t *dst, int *dst_len,      uint8_t *src, int src_len)  { @@ -591,6 +660,21 @@ cipher_ctx_final (EVP_CIPHER_CTX *ctx, uint8_t *dst, int *dst_len)    return EVP_CipherFinal (ctx, dst, dst_len);  } +int +cipher_ctx_final_check_tag (EVP_CIPHER_CTX *ctx, uint8_t *dst, int *dst_len, +    const uint8_t *tag, size_t tag_len) +{ +#ifdef HAVE_AEAD_CIPHER_MODES +  /* Setting a tag does not change the tag, so casting away const... */ +  if (!EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_SET_TAG, tag_len, +      (uint8_t *) tag)) +    return 0; + +  return cipher_ctx_final (ctx, dst, dst_len); +#else +  ASSERT (0); +#endif +}  void  cipher_des_encrypt_ecb (const unsigned char key[DES_KEY_LENGTH], @@ -617,9 +701,11 @@ md_kt_get (const char *digest)    ASSERT (digest);    md = EVP_get_digestbyname (digest);    if (!md) -    msg (M_SSLERR, "Message hash algorithm '%s' not found", digest); +    crypto_msg (M_FATAL, "Message hash algorithm '%s' not found", digest);    if (EVP_MD_size (md) > MAX_HMAC_KEY_LENGTH) -    msg (M_FATAL, "Message hash algorithm '%s' uses a default hash size (%d bytes) which is larger than " PACKAGE_NAME "'s current maximum hash size (%d bytes)", +    crypto_msg (M_FATAL, "Message hash algorithm '%s' uses a default hash size " +	 "(%d bytes) which is larger than " PACKAGE_NAME "'s current maximum " +	 "hash size (%d bytes)",  	 digest,  	 EVP_MD_size (md),  	 MAX_HMAC_KEY_LENGTH); @@ -747,4 +833,14 @@ hmac_ctx_final (HMAC_CTX *ctx, uint8_t *dst)    HMAC_Final (ctx, dst, &in_hmac_len);  } +bool +crypto_aead_mode (int mode) +{ +#ifdef HAVE_AEAD_CIPHER_MODES +  return mode == OPENVPN_MODE_CCM || mode == OPENVPN_MODE_GCM; +#else +  return false; +#endif +} +  #endif /* ENABLE_CRYPTO && ENABLE_CRYPTO_OPENSSL */ diff --git a/main/openvpn/src/openvpn/crypto_openssl.h b/main/openvpn/src/openvpn/crypto_openssl.h index f883c2a5..b99fd67f 100644 --- a/main/openvpn/src/openvpn/crypto_openssl.h +++ b/main/openvpn/src/openvpn/crypto_openssl.h @@ -61,6 +61,16 @@ typedef HMAC_CTX hmac_ctx_t;  /** Cipher is in CFB mode */  #define OPENVPN_MODE_CFB 	EVP_CIPH_CFB_MODE +#ifdef HAVE_AEAD_CIPHER_MODES + +/** Cipher is in CCM mode */ +#define OPENVPN_MODE_CCM 	EVP_CIPH_CCM_MODE + +/** Cipher is in GCM mode */ +#define OPENVPN_MODE_GCM 	EVP_CIPH_GCM_MODE + +#endif /* HAVE_AEAD_CIPHER_MODES */ +  /** Cipher should encrypt */  #define OPENVPN_OP_ENCRYPT 	1 @@ -70,4 +80,29 @@ typedef HMAC_CTX hmac_ctx_t;  #define DES_KEY_LENGTH 8  #define MD4_DIGEST_LENGTH 	16 +/** + * Retrieve any occurred OpenSSL errors and print those errors. + * + * Note that this function uses the not thread-safe OpenSSL error API. + * + * @param flags		Flags to indicate error type and priority. + */ +void crypto_print_openssl_errors(const unsigned int flags); + +/** + * Retrieve any OpenSSL errors, then print the supplied error message. + * + * This is just a convenience wrapper for often occurring situations. + * + * @param flags		Flags to indicate error type and priority. + * @param format	Format string to print. + * @param format args	(optional) arguments for the format string. + */ +# define crypto_msg(flags, ...) \ +do { \ +  crypto_print_openssl_errors(nonfatal(flags)); \ +  msg((flags), __VA_ARGS__); \ +} while (false) + +  #endif /* CRYPTO_OPENSSL_H_ */ diff --git a/main/openvpn/src/openvpn/crypto_polarssl.c b/main/openvpn/src/openvpn/crypto_polarssl.c index 1a986dbd..c7a41baf 100644 --- a/main/openvpn/src/openvpn/crypto_polarssl.c +++ b/main/openvpn/src/openvpn/crypto_polarssl.c @@ -46,6 +46,7 @@  #include "misc.h"  #include <polarssl/des.h> +#include <polarssl/error.h>  #include <polarssl/md5.h>  #include <polarssl/cipher.h>  #include <polarssl/havege.h> @@ -86,6 +87,32 @@ crypto_clear_error (void)  {  } +bool polar_log_err(unsigned int flags, int errval, const char *prefix) +{ +  if (0 != errval) +    { +      char errstr[256]; +      polarssl_strerror(errval, errstr, sizeof(errstr)); + +      if (NULL == prefix) prefix = "PolarSSL error"; +      msg (flags, "%s: %s", prefix, errstr); +    } + +  return 0 == errval; +} + +bool polar_log_func_line(unsigned int flags, int errval, const char *func, +    int line) +{ +  char prefix[256]; + +  if (!openvpn_snprintf(prefix, sizeof(prefix), "%s:%d", func, line)) +    return polar_log_err(flags, errval, func); + +  return polar_log_err(flags, errval, prefix); +} + +  #ifdef DMALLOC  void  crypto_init_dmalloc (void) @@ -94,52 +121,15 @@ crypto_init_dmalloc (void)  }  #endif /* DMALLOC */ -typedef struct { const char * openvpn_name; const char * polarssl_name; } cipher_name_pair; -cipher_name_pair cipher_name_translation_table[] = { +const cipher_name_pair cipher_name_translation_table[] = {      { "BF-CBC", "BLOWFISH-CBC" },      { "BF-CFB", "BLOWFISH-CFB64" },      { "CAMELLIA-128-CFB", "CAMELLIA-128-CFB128" },      { "CAMELLIA-192-CFB", "CAMELLIA-192-CFB128" },      { "CAMELLIA-256-CFB", "CAMELLIA-256-CFB128" }  }; - -const cipher_name_pair * -get_cipher_name_pair(const char *cipher_name) { -  cipher_name_pair *pair; -  size_t i = 0; - -  /* Search for a cipher name translation */ -  for (; i < sizeof (cipher_name_translation_table) / sizeof (*cipher_name_translation_table); i++) -    { -      pair = &cipher_name_translation_table[i]; -      if (0 == strcmp (cipher_name, pair->openvpn_name) || -	  0 == strcmp (cipher_name, pair->polarssl_name)) -	  return pair; -    } - -  /* Nothing found, return null */ -  return NULL; -} - -const char * -translate_cipher_name_from_openvpn (const char *cipher_name) { -  const cipher_name_pair *pair = get_cipher_name_pair(cipher_name); - -  if (NULL == pair) -    return cipher_name; - -  return pair->polarssl_name; -} - -const char * -translate_cipher_name_to_openvpn (const char *cipher_name) { -  const cipher_name_pair *pair = get_cipher_name_pair(cipher_name); - -  if (NULL == pair) -    return cipher_name; - -  return pair->openvpn_name; -} +const size_t cipher_name_translation_table_count = +    sizeof (cipher_name_translation_table) / sizeof (*cipher_name_translation_table);  void  show_available_ciphers () @@ -147,21 +137,28 @@ show_available_ciphers ()    const int *ciphers = cipher_list();  #ifndef ENABLE_SMALL -  printf ("The following ciphers and cipher modes are available\n" -	  "for use with " PACKAGE_NAME ".  Each cipher shown below may be\n" -	  "used as a parameter to the --cipher option.  The default\n" -	  "key size is shown as well as whether or not it can be\n" -          "changed with the --keysize directive.  Using a CBC mode\n" -	  "is recommended.\n\n"); +  printf ("The following ciphers and cipher modes are available for use\n" +	  "with " PACKAGE_NAME ".  Each cipher shown below may be used as a\n" +	  "parameter to the --cipher option.  Using a CBC or GCM mode is\n" +	  "recommended.  In static key mode only CBC mode is allowed.\n\n");  #endif    while (*ciphers != 0)      { -      const cipher_info_t *info = cipher_info_from_type(*ciphers); +      const cipher_kt_t *info = cipher_info_from_type(*ciphers); -      if (info && info->mode == POLARSSL_MODE_CBC) -	printf ("%s %d bit default key\n", -		cipher_kt_name(info), cipher_kt_key_size(info) * 8); +      if (info && (cipher_kt_mode_cbc(info) +#ifdef HAVE_AEAD_CIPHER_MODES +          || cipher_kt_mode_aead(info) +#endif +          )) +	{ +	  const char *ssl_only = cipher_kt_mode_cbc(info) ? +	      "" : " (TLS client/server mode)"; + +	  printf ("%s %d bit default key%s\n", +	      cipher_kt_name(info), cipher_kt_key_size(info) * 8, ssl_only); +	}        ciphers++;      } @@ -234,7 +231,8 @@ ctr_drbg_context * rand_ctx_get()        /* Initialise PolarSSL RNG, and built-in entropy sources */        entropy_init(&ec); -      if (0 != ctr_drbg_init(&cd_ctx, entropy_func, &ec, BPTR(&pers_string), BLEN(&pers_string))) +      if (!polar_ok(ctr_drbg_init(&cd_ctx, entropy_func, &ec, +		    BPTR(&pers_string), BLEN(&pers_string))))          msg (M_FATAL, "Failed to initialize random generator");        gc_free(&gc); @@ -410,6 +408,16 @@ cipher_kt_block_size (const cipher_info_t *cipher_kt)  }  int +cipher_kt_tag_size (const cipher_info_t *cipher_kt) +{ +#ifdef HAVE_AEAD_CIPHER_MODES +  if (cipher_kt && cipher_kt_mode_aead(cipher_kt)) +    return OPENVPN_AEAD_TAG_LENGTH; +#endif +  return 0; +} + +int  cipher_kt_mode (const cipher_info_t *cipher_kt)  {    ASSERT(NULL != cipher_kt); @@ -429,6 +437,12 @@ cipher_kt_mode_ofb_cfb(const cipher_kt_t *cipher)  	  cipher_kt_mode(cipher) == OPENVPN_MODE_CFB);  } +bool +cipher_kt_mode_aead(const cipher_kt_t *cipher) +{ +  return cipher_kt_mode(cipher) == OPENVPN_MODE_GCM; +} +  /*   * @@ -445,10 +459,10 @@ cipher_ctx_init (cipher_context_t *ctx, uint8_t *key, int key_len,    CLEAR (*ctx); -  if (0 != cipher_init_ctx(ctx, kt)) +  if (!polar_ok(cipher_init_ctx(ctx, kt)))      msg (M_FATAL, "PolarSSL cipher context init #1"); -  if (0 != cipher_setkey(ctx, key, key_len*8, enc)) +  if (!polar_ok(cipher_setkey(ctx, key, key_len*8, enc)))      msg (M_FATAL, "PolarSSL cipher set key");    /* make sure we used a big enough key */ @@ -457,7 +471,7 @@ cipher_ctx_init (cipher_context_t *ctx, uint8_t *key, int key_len,  void cipher_ctx_cleanup (cipher_context_t *ctx)  { -  cipher_free_ctx(ctx); +  ASSERT (polar_ok(cipher_free_ctx(ctx)));  }  int cipher_ctx_iv_length (const cipher_context_t *ctx) @@ -465,6 +479,21 @@ int cipher_ctx_iv_length (const cipher_context_t *ctx)    return cipher_get_iv_size(ctx);  } +int cipher_ctx_get_tag (cipher_ctx_t *ctx, uint8_t* tag, int tag_len) +{ +#ifdef HAVE_AEAD_CIPHER_MODES +  if (tag_len > SIZE_MAX) +    return 0; + +  if (!polar_ok(cipher_write_tag(ctx, (unsigned char *) tag, tag_len))) +    return 0; + +  return 1; +#else +  ASSERT(0); +#endif /* HAVE_AEAD_CIPHER_MODES */ +} +  int cipher_ctx_block_size(const cipher_context_t *ctx)  {    return cipher_get_block_size(ctx); @@ -487,36 +516,74 @@ cipher_ctx_get_cipher_kt (const cipher_ctx_t *ctx)  int cipher_ctx_reset (cipher_context_t *ctx, uint8_t *iv_buf)  { -  int retval = cipher_reset(ctx); +  if (!polar_ok(cipher_reset(ctx))) +    return 0; + +  if (!polar_ok(cipher_set_iv(ctx, iv_buf, ctx->cipher_info->iv_size))) +    return 0; + +  return 1; +} + +int cipher_ctx_update_ad (cipher_ctx_t *ctx, uint8_t *src, int src_len) +{ +  if (src_len > SIZE_MAX) +    return 0; -  if (0 == retval) -    retval = cipher_set_iv(ctx, iv_buf, ctx->cipher_info->iv_size); +  if (!polar_ok(cipher_update_ad(ctx, src, src_len))) +    return 0; -  return 0 == retval; +  return 1;  }  int cipher_ctx_update (cipher_context_t *ctx, uint8_t *dst, int *dst_len,      uint8_t *src, int src_len)  { -  int retval = 0;    size_t s_dst_len = *dst_len; -  retval = cipher_update(ctx, src, (size_t)src_len, dst, &s_dst_len); +  if (!polar_ok(cipher_update(ctx, src, (size_t)src_len, dst, &s_dst_len))) +    return 0;    *dst_len = s_dst_len; -  return 0 == retval; +  return 1;  }  int cipher_ctx_final (cipher_context_t *ctx, uint8_t *dst, int *dst_len)  { -  int retval = 0;    size_t s_dst_len = *dst_len; -  retval = cipher_finish(ctx, dst, &s_dst_len); +  if (!polar_ok(cipher_finish(ctx, dst, &s_dst_len))) +    return 0; +    *dst_len = s_dst_len; -  return 0 == retval; +  return 1; +} + +int cipher_ctx_final_check_tag (cipher_context_t *ctx, uint8_t *dst, int *dst_len, +    const uint8_t *tag, size_t tag_len) +{ +#ifdef HAVE_AEAD_CIPHER_MODES +  if (POLARSSL_DECRYPT != ctx->operation) +    return 0; + +  if (tag_len > SIZE_MAX) +    return 0; + +  if (!cipher_ctx_final(ctx, dst, dst_len)) +    { +      msg(D_CRYPT_ERRORS, "%s: cipher_ctx_final() failed", __func__); +      return 0; +    } + +  if (!polar_ok(cipher_check_tag(ctx, (const unsigned char *) tag, tag_len))) +    return 0; + +  return 1; +#else +  ASSERT(0); +#endif /* HAVE_AEAD_CIPHER_MODES */  }  void @@ -526,8 +593,8 @@ cipher_des_encrypt_ecb (const unsigned char key[DES_KEY_LENGTH],  {      des_context ctx; -    des_setkey_enc(&ctx, key); -    des_crypt_ecb(&ctx, src, dst); +    ASSERT (polar_ok(des_setkey_enc(&ctx, key))); +    ASSERT (polar_ok(des_crypt_ecb(&ctx, src, dst)));  } diff --git a/main/openvpn/src/openvpn/crypto_polarssl.h b/main/openvpn/src/openvpn/crypto_polarssl.h index b6da4363..75aa8643 100644 --- a/main/openvpn/src/openvpn/crypto_polarssl.h +++ b/main/openvpn/src/openvpn/crypto_polarssl.h @@ -61,6 +61,9 @@ typedef md_context_t hmac_ctx_t;  /** Cipher is in CFB mode */  #define OPENVPN_MODE_CFB 	POLARSSL_MODE_CFB +/** Cipher is in GCM mode */ +#define OPENVPN_MODE_GCM	POLARSSL_MODE_GCM +  /** Cipher should encrypt */  #define OPENVPN_OP_ENCRYPT 	POLARSSL_ENCRYPT @@ -91,4 +94,44 @@ ctr_drbg_context * rand_ctx_get();  void rand_ctx_enable_prediction_resistance();  #endif +/** + * Log the supplied PolarSSL error, then print the supplied error message. + * + * @param flags		Flags to indicate error type and priority. + * @param errval	PolarSSL error code to convert to error message. + * @param prefix	Prefix to PolarSSL error message. + * + * @returns true if no errors are detected, false otherwise. + */ +bool polar_log_err(unsigned int flags, int errval, const char *prefix); + +/** + * Log the supplied PolarSSL error, then print the supplied error message. + * + * @param flags		Flags to indicate error type and priority. + * @param errval	PolarSSL error code to convert to error message. + * @param func		Function name where error was reported. + * @param line		Line number where error was reported. + * + * @returns true if no errors are detected, false otherwise. + */ +bool polar_log_func_line(unsigned int flags, int errval, const char *func, +    int line); + +/** + * Check errval and log on error. + * + * Convenience wrapper to put around polarssl library calls, e.g. + *   if (!polar_ok(polarssl_func())) return 0; + * or + *   ASSERT (polar_ok(polarssl_func())); + * + * @param errval	PolarSSL error code to convert to error message. + * + * @returns true if no errors are detected, false otherwise. + */ +#define polar_ok(errval) \ +  polar_log_func_line(D_CRYPT_ERRORS, errval, __func__, __LINE__) + +  #endif /* CRYPTO_POLARSSL_H_ */ diff --git a/main/openvpn/src/openvpn/error.c b/main/openvpn/src/openvpn/error.c index af865f32..72ebfab6 100644 --- a/main/openvpn/src/openvpn/error.c +++ b/main/openvpn/src/openvpn/error.c @@ -43,13 +43,6 @@  #include "ps.h"  #include "mstats.h" -#ifdef ENABLE_CRYPTO -#ifdef ENABLE_CRYPTO_OPENSSL -#include <openssl/err.h> -#endif -#endif - -#include "memdbg.h"  #if SYSLOG_CAPABILITY  #ifndef LOG_OPENVPN @@ -269,28 +262,6 @@ void x_msg_va (const unsigned int flags, const char *format, va_list arglist)        SWAP;      } -#ifdef ENABLE_CRYPTO -#ifdef ENABLE_CRYPTO_OPENSSL -  if (flags & M_SSL) -    { -      int nerrs = 0; -      size_t err; -      while ((err = ERR_get_error ())) -	{ -	  openvpn_snprintf (m2, ERR_BUF_SIZE, "%s: %s", -			    m1, ERR_error_string (err, NULL)); -	  SWAP; -	  ++nerrs; -	} -      if (!nerrs) -	{ -	  openvpn_snprintf (m2, ERR_BUF_SIZE, "%s (OpenSSL)", m1); -	  SWAP; -	} -    } -#endif -#endif -    if (flags & M_OPTERR)      {        openvpn_snprintf (m2, ERR_BUF_SIZE, "Options error: %s", m1); diff --git a/main/openvpn/src/openvpn/error.h b/main/openvpn/src/openvpn/error.h index 1e1f2acf..d5204f3f 100644 --- a/main/openvpn/src/openvpn/error.h +++ b/main/openvpn/src/openvpn/error.h @@ -93,10 +93,6 @@ extern int x_msg_line_num;  #define M_ERRNO           (1<<8)	 /* show errno description */ -#ifdef ENABLE_CRYPTO_OPENSSL -#  define M_SSL             (1<<10)	 /* show SSL error */ -#endif -  #define M_NOMUTE          (1<<11)        /* don't do mute processing */  #define M_NOPREFIX        (1<<12)        /* don't show date/time prefix */  #define M_USAGE_SMALL     (1<<13)        /* fatal options error, call usage_small */ @@ -107,7 +103,6 @@ extern int x_msg_line_num;  /* flag combinations which are frequently used */  #define M_ERR     (M_FATAL | M_ERRNO) -#define M_SSLERR  (M_FATAL | M_SSL)  #define M_USAGE   (M_USAGE_SMALL | M_NOPREFIX | M_OPTERR)  #define M_CLIENT  (M_MSG_VIRT_OUT | M_NOMUTE | M_NOIPREFIX) @@ -354,6 +349,12 @@ ignore_sys_error (const int err)    return false;  } +/** Convert fatal errors to nonfatal, don't touch other errors */ +static inline const unsigned int +nonfatal(const unsigned int err) { +  return err & M_FATAL ? (err ^ M_FATAL) | M_NONFATAL : err; +} +  #include "errlevel.h"  #endif diff --git a/main/openvpn/src/openvpn/forward.c b/main/openvpn/src/openvpn/forward.c index a43361b4..73bed9b8 100644 --- a/main/openvpn/src/openvpn/forward.c +++ b/main/openvpn/src/openvpn/forward.c @@ -433,6 +433,7 @@ encrypt_sign (struct context *c, bool comp_frag)  {    struct context_buffers *b = c->c2.buffers;    const uint8_t *orig_buf = c->c2.buf.data; +  struct crypto_options *co = NULL;  #if P2MP_SERVER    /* @@ -464,15 +465,19 @@ encrypt_sign (struct context *c, bool comp_frag)     */    if (c->c2.tls_multi)      { -      tls_pre_encrypt (c->c2.tls_multi, &c->c2.buf, &c->c2.crypto_options); +      tls_pre_encrypt (c->c2.tls_multi, &c->c2.buf, &co);      } +  else  #endif +    { +      co = &c->c2.crypto_options; +    }    /*     * Encrypt the packet and write an optional     * HMAC signature.     */ -  openvpn_encrypt (&c->c2.buf, b->encrypt_buf, &c->c2.crypto_options, &c->c2.frame); +  openvpn_encrypt (&c->c2.buf, b->encrypt_buf, co, &c->c2.frame);  #endif    /*     * Get the address we will be sending the packet to. @@ -788,6 +793,7 @@ process_incoming_link (struct context *c)     */    if (c->c2.buf.len > 0)      { +      struct crypto_options *co = NULL;        if (!link_socket_verify_incoming_addr (&c->c2.buf, lsi, &c->c2.from))  	link_socket_bad_incoming_addr (&c->c2.buf, lsi, &c->c2.from); @@ -805,7 +811,7 @@ process_incoming_link (struct context *c)  	   * will load crypto_options with the correct encryption key  	   * and return false.  	   */ -	  if (tls_pre_decrypt (c->c2.tls_multi, &c->c2.from, &c->c2.buf, &c->c2.crypto_options)) +	  if (tls_pre_decrypt (c->c2.tls_multi, &c->c2.from, &c->c2.buf, &co))  	    {  	      interval_action (&c->c2.tmp_int); @@ -814,6 +820,10 @@ process_incoming_link (struct context *c)  		event_timeout_reset (&c->c2.ping_rec_interval);  	    }  	} +      else +	{ +	  co = &c->c2.crypto_options; +	}  #if P2MP_SERVER        /*         * Drop non-TLS packet if client-connect script/plugin has not @@ -822,10 +832,12 @@ process_incoming_link (struct context *c)        if (c->c2.context_auth != CAS_SUCCEEDED)  	c->c2.buf.len = 0;  #endif +#else +      co = &c->c2.crypto_options;  #endif /* ENABLE_SSL */        /* authenticate and decrypt the incoming packet */ -      decrypt_status = openvpn_decrypt (&c->c2.buf, c->c2.buffers->decrypt_buf, &c->c2.crypto_options, &c->c2.frame); +      decrypt_status = openvpn_decrypt (&c->c2.buf, c->c2.buffers->decrypt_buf, co, &c->c2.frame);        if (!decrypt_status && link_socket_connection_oriented (c->c2.link_socket))  	{ @@ -948,6 +960,15 @@ read_incoming_tun (struct context *c)        return;		        } +  /* Was TUN/TAP I/O operation aborted? */ +  if (tuntap_abort(c->c2.buf.len)) +  { +     register_signal(c, SIGTERM, "tun-abort"); +     msg(M_FATAL, "TUN/TAP I/O operation aborted, exiting"); +     perf_pop(); +     return; +  } +    /* Check the status return from read() */    check_status (c->c2.buf.len, "read from TUN/TAP", NULL, c->c1.tuntap); diff --git a/main/openvpn/src/openvpn/httpdigest.c b/main/openvpn/src/openvpn/httpdigest.c index 78b8344d..2590d1b1 100644 --- a/main/openvpn/src/openvpn/httpdigest.c +++ b/main/openvpn/src/openvpn/httpdigest.c @@ -74,22 +74,23 @@ DigestCalcHA1(    HASH HA1;    md_ctx_t md5_ctx;    const md_kt_t *md5_kt = md_kt_get("MD5"); +  const uint8_t colon = ':';    md_ctx_init(&md5_ctx, md5_kt); -  md_ctx_update(&md5_ctx, pszUserName, strlen(pszUserName)); -  md_ctx_update(&md5_ctx, ":", 1); -  md_ctx_update(&md5_ctx, pszRealm, strlen(pszRealm)); -  md_ctx_update(&md5_ctx, ":", 1); -  md_ctx_update(&md5_ctx, pszPassword, strlen(pszPassword)); +  md_ctx_update(&md5_ctx, (uint8_t *) pszUserName, strlen(pszUserName)); +  md_ctx_update(&md5_ctx, &colon, 1); +  md_ctx_update(&md5_ctx, (uint8_t *) pszRealm, strlen(pszRealm)); +  md_ctx_update(&md5_ctx, &colon, 1); +  md_ctx_update(&md5_ctx, (uint8_t *) pszPassword, strlen(pszPassword));    md_ctx_final(&md5_ctx, HA1);    if (pszAlg && strcasecmp(pszAlg, "md5-sess") == 0)      {        md_ctx_init(&md5_ctx, md5_kt);        md_ctx_update(&md5_ctx, HA1, HASHLEN); -      md_ctx_update(&md5_ctx, ":", 1); -      md_ctx_update(&md5_ctx, pszNonce, strlen(pszNonce)); -      md_ctx_update(&md5_ctx, ":", 1); -      md_ctx_update(&md5_ctx, pszCNonce, strlen(pszCNonce)); +      md_ctx_update(&md5_ctx, &colon, 1); +      md_ctx_update(&md5_ctx, (uint8_t *) pszNonce, strlen(pszNonce)); +      md_ctx_update(&md5_ctx, &colon, 1); +      md_ctx_update(&md5_ctx, (uint8_t *) pszCNonce, strlen(pszCNonce));        md_ctx_final(&md5_ctx, HA1);      };    md_ctx_cleanup(&md5_ctx); @@ -116,15 +117,16 @@ DigestCalcResponse(    md_ctx_t md5_ctx;    const md_kt_t *md5_kt = md_kt_get("MD5"); +  const uint8_t colon = ':';    /* calculate H(A2) */    md_ctx_init(&md5_ctx, md5_kt); -  md_ctx_update(&md5_ctx, pszMethod, strlen(pszMethod)); -  md_ctx_update(&md5_ctx, ":", 1); -  md_ctx_update(&md5_ctx, pszDigestUri, strlen(pszDigestUri)); +  md_ctx_update(&md5_ctx, (uint8_t *) pszMethod, strlen(pszMethod)); +  md_ctx_update(&md5_ctx, &colon, 1); +  md_ctx_update(&md5_ctx, (uint8_t *) pszDigestUri, strlen(pszDigestUri));    if (strcasecmp(pszQop, "auth-int") == 0)      { -      md_ctx_update(&md5_ctx, ":", 1); +      md_ctx_update(&md5_ctx, &colon, 1);        md_ctx_update(&md5_ctx, HEntity, HASHHEXLEN);      };    md_ctx_final(&md5_ctx, HA2); @@ -133,17 +135,17 @@ DigestCalcResponse(    /* calculate response */    md_ctx_init(&md5_ctx, md5_kt);    md_ctx_update(&md5_ctx, HA1, HASHHEXLEN); -  md_ctx_update(&md5_ctx, ":", 1); -  md_ctx_update(&md5_ctx, pszNonce, strlen(pszNonce)); -  md_ctx_update(&md5_ctx, ":", 1); +  md_ctx_update(&md5_ctx, &colon, 1); +  md_ctx_update(&md5_ctx, (uint8_t *) pszNonce, strlen(pszNonce)); +  md_ctx_update(&md5_ctx, &colon, 1);    if (*pszQop)      { -      md_ctx_update(&md5_ctx, pszNonceCount, strlen(pszNonceCount)); -      md_ctx_update(&md5_ctx, ":", 1); -      md_ctx_update(&md5_ctx, pszCNonce, strlen(pszCNonce)); -      md_ctx_update(&md5_ctx, ":", 1); -      md_ctx_update(&md5_ctx, pszQop, strlen(pszQop)); -      md_ctx_update(&md5_ctx, ":", 1); +      md_ctx_update(&md5_ctx, (uint8_t *) pszNonceCount, strlen(pszNonceCount)); +      md_ctx_update(&md5_ctx, &colon, 1); +      md_ctx_update(&md5_ctx, (uint8_t *) pszCNonce, strlen(pszCNonce)); +      md_ctx_update(&md5_ctx, &colon, 1); +      md_ctx_update(&md5_ctx, (uint8_t *) pszQop, strlen(pszQop)); +      md_ctx_update(&md5_ctx, &colon, 1);      };    md_ctx_update(&md5_ctx, HA2Hex, HASHHEXLEN);    md_ctx_final(&md5_ctx, RespHash); diff --git a/main/openvpn/src/openvpn/httpdigest.h b/main/openvpn/src/openvpn/httpdigest.h index 84238413..24bd85d8 100644 --- a/main/openvpn/src/openvpn/httpdigest.h +++ b/main/openvpn/src/openvpn/httpdigest.h @@ -25,7 +25,7 @@  #if PROXY_DIGEST_AUTH  #define HASHLEN 16 -typedef unsigned char HASH[HASHLEN]; +typedef uint8_t HASH[HASHLEN];  #define HASHHEXLEN 32  typedef unsigned char HASHHEX[HASHHEXLEN+1];  #undef IN diff --git a/main/openvpn/src/openvpn/init.c b/main/openvpn/src/openvpn/init.c index 6380719f..af517ee9 100644 --- a/main/openvpn/src/openvpn/init.c +++ b/main/openvpn/src/openvpn/init.c @@ -1719,7 +1719,7 @@ pull_permission_mask (const struct context *c)      | OPT_P_EXPLICIT_NOTIFY      | OPT_P_ECHO      | OPT_P_PULL_MODE -    | OPT_P_SESSION_ID; +    | OPT_P_PEER_ID;    if (!c->options.route_nopull)      flags |= (OPT_P_ROUTE | OPT_P_IPWIN32); @@ -1797,11 +1797,11 @@ do_deferred_options (struct context *c, const unsigned int found)    if (found & OPT_P_SETENV)      msg (D_PUSH, "OPTIONS IMPORT: environment modified"); -  if (found & OPT_P_SESSION_ID) +  if (found & OPT_P_PEER_ID)      { -      msg (D_PUSH, "OPTIONS IMPORT: session-id set"); -      c->c2.tls_multi->use_session_id = true; -      c->c2.tls_multi->vpn_session_id = c->options.vpn_session_id; +      msg (D_PUSH, "OPTIONS IMPORT: peer-id set"); +      c->c2.tls_multi->use_peer_id = true; +      c->c2.tls_multi->peer_id = c->options.peer_id;      }  } @@ -1893,39 +1893,38 @@ do_startup_pause (struct context *c)   * Finalize MTU parameters based on command line or config file options.   */  static void -frame_finalize_options (struct context *c, const struct options *o) +frame_finalize_options (struct frame *frame, const struct options *o, +    bool cipher_enabled)  { -  if (!o) -    o = &c->options; +  ASSERT(o);    /*     * Set adjustment factor for buffer alignment when no     * cipher is used.     */ -  if (!CIPHER_ENABLED (c)) +  if (!cipher_enabled)      { -      frame_align_to_extra_frame (&c->c2.frame); -      frame_or_align_flags (&c->c2.frame, +      frame_align_to_extra_frame (frame); +      frame_or_align_flags (frame,  			    FRAME_HEADROOM_MARKER_FRAGMENT  			    |FRAME_HEADROOM_MARKER_READ_LINK  			    |FRAME_HEADROOM_MARKER_READ_STREAM);      } -  frame_finalize (&c->c2.frame, +  frame_finalize (frame,  		  o->ce.link_mtu_defined,  		  o->ce.link_mtu,  		  o->ce.tun_mtu_defined,  		  o->ce.tun_mtu);  } +#ifdef ENABLE_CRYPTO  /*   * Free a key schedule, including OpenSSL components.   */  static void  key_schedule_free (struct key_schedule *ks, bool free_ssl_ctx)  { -#ifdef ENABLE_CRYPTO -  free_key_ctx_bi (&ks->static_key);  #ifdef ENABLE_SSL    if (tls_ctx_initialised(&ks->ssl_ctx) && free_ssl_ctx)      { @@ -1933,12 +1932,9 @@ key_schedule_free (struct key_schedule *ks, bool free_ssl_ctx)        free_key_ctx_bi (&ks->tls_auth_key);      }  #endif /* ENABLE_SSL */ -#endif /* ENABLE_CRYPTO */    CLEAR (*ks);  } -#ifdef ENABLE_CRYPTO -  static void  init_crypto_pre (struct context *c, const unsigned int flags)  { @@ -1952,14 +1948,6 @@ init_crypto_pre (struct context *c, const unsigned int flags)  	packet_id_persist_load (&c->c1.pid_persist, c->options.packet_id_file);      } -  /* Initialize crypto options */ - -  if (c->options.use_iv) -    c->c2.crypto_options.flags |= CO_USE_IV; - -  if (c->options.mute_replay_warnings) -    c->c2.crypto_options.flags |= CO_MUTE_REPLAY_WARNINGS; -  #ifdef ENABLE_PREDICTION_RESISTANCE    if (c->options.use_prediction_resistance)      rand_ctx_enable_prediction_resistance(); @@ -1978,22 +1966,28 @@ do_init_crypto_static (struct context *c, const unsigned int flags)    init_crypto_pre (c, flags); +  /* Initialize flags */ +  if (c->options.use_iv) +    c->c2.crypto_options.flags |= CO_USE_IV; + +  if (c->options.mute_replay_warnings) +    c->c2.crypto_options.flags |= CO_MUTE_REPLAY_WARNINGS; +    /* Initialize packet ID tracking */    if (options->replay)      { -      packet_id_init (&c->c2.packet_id, +      packet_id_init (&c->c2.crypto_options.packet_id,  		      link_socket_proto_connection_oriented (options->ce.proto),  		      options->replay_window,  		      options->replay_time,  		      "STATIC", 0); -      c->c2.crypto_options.packet_id = &c->c2.packet_id;        c->c2.crypto_options.pid_persist = &c->c1.pid_persist;        c->c2.crypto_options.flags |= CO_PACKET_ID_LONG_FORM;        packet_id_persist_load_obj (&c->c1.pid_persist, -				  c->c2.crypto_options.packet_id); +				  &c->c2.crypto_options.packet_id);      } -  if (!key_ctx_bi_defined (&c->c1.ks.static_key)) +  if (!key_ctx_bi_defined (&c->c2.crypto_options.key_ctx_bi))      {        struct key2 key2;        struct key_direction_state kds; @@ -2025,10 +2019,12 @@ do_init_crypto_static (struct context *c, const unsigned int flags)        key_direction_state_init (&kds, options->key_direction);        must_have_n_keys (options->shared_secret_file, "secret", &key2,  			kds.need_keys); -      init_key_ctx (&c->c1.ks.static_key.encrypt, &key2.keys[kds.out_key], -		    &c->c1.ks.key_type, OPENVPN_OP_ENCRYPT, "Static Encrypt"); -      init_key_ctx (&c->c1.ks.static_key.decrypt, &key2.keys[kds.in_key], -		    &c->c1.ks.key_type, OPENVPN_OP_DECRYPT, "Static Decrypt"); +      init_key_ctx (&c->c2.crypto_options.key_ctx_bi.encrypt, +		    &key2.keys[kds.out_key], &c->c1.ks.key_type, +		    OPENVPN_OP_ENCRYPT, "Static Encrypt"); +      init_key_ctx (&c->c2.crypto_options.key_ctx_bi.decrypt, +		    &key2.keys[kds.in_key], &c->c1.ks.key_type, +		    OPENVPN_OP_DECRYPT, "Static Decrypt");        /* Erase the temporary copy of key */        CLEAR (key2); @@ -2038,9 +2034,6 @@ do_init_crypto_static (struct context *c, const unsigned int flags)        msg (M_INFO, "Re-using pre-shared static key");      } -  /* Get key schedule */ -  c->c2.crypto_options.key_ctx_bi = &c->c1.ks.static_key; -    /* Compute MTU parameters */    crypto_adjust_frame_parameters (&c->c2.frame,  				  &c->c1.ks.key_type, @@ -2112,11 +2105,22 @@ do_init_crypto_tls_c1 (struct context *c)  	      flags |= GHK_INLINE;  	      file = options->tls_auth_file_inline;  	    } -	  get_tls_handshake_key (&c->c1.ks.key_type, -				 &c->c1.ks.tls_auth_key, -				 file, -				 options->key_direction, -				 flags); + +	  /* Initialize key_type for tls-auth with auth only */ +	  CLEAR (c->c1.ks.tls_auth_key_type); +	  if (options->authname && options->authname_defined) +	    { +	      c->c1.ks.tls_auth_key_type.digest = md_kt_get (options->authname); +	      c->c1.ks.tls_auth_key_type.hmac_length = +		  md_kt_size (c->c1.ks.tls_auth_key_type.digest); +	    } +	  else +	    { +	      msg (M_FATAL, "ERROR: tls-auth specified, but no valid auth"); +	    } + +	  get_tls_handshake_key (&c->c1.ks.tls_auth_key_type, +	      &c->c1.ks.tls_auth_key, file, options->key_direction, flags);  	}  #if 0 /* was: #if ENABLE_INLINE_FILES --  Note that enabling this code will break restarts */ @@ -2171,6 +2175,12 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)    /* Set all command-line TLS-related options */    CLEAR (to); +  if (options->use_iv) +    to.crypto_flags |= CO_USE_IV; + +  if (options->mute_replay_warnings) +    to.crypto_flags |= CO_MUTE_REPLAY_WARNINGS; +    to.crypto_flags_and = ~(CO_PACKET_ID_LONG_FORM);    if (packet_id_long_form)      to.crypto_flags_or = CO_PACKET_ID_LONG_FORM; @@ -2260,11 +2270,11 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)    /* TLS handshake authentication (--tls-auth) */    if (options->tls_auth_file)      { -      to.tls_auth_key = c->c1.ks.tls_auth_key; +      to.tls_auth.key_ctx_bi = c->c1.ks.tls_auth_key;        to.tls_auth.pid_persist = &c->c1.pid_persist;        to.tls_auth.flags |= CO_PACKET_ID_LONG_FORM;        crypto_adjust_frame_parameters (&to.frame, -				      &c->c1.ks.key_type, +				      &c->c1.ks.tls_auth_key_type,  				      false, false, true, true);      } @@ -2407,7 +2417,7 @@ do_init_frame (struct context *c)     * Fill in the blanks in the frame parameters structure,     * make sure values are rational, etc.     */ -  frame_finalize_options (c, NULL); +  frame_finalize_options (&c->c2.frame, &c->options, CIPHER_ENABLED (c));  #ifdef USE_COMP    /* @@ -2843,8 +2853,13 @@ do_close_tls (struct context *c)  static void  do_close_free_key_schedule (struct context *c, bool free_ssl_ctx)  { +#ifdef ENABLE_CRYPTO    if (!(c->sig->signal_received == SIGUSR1 && c->options.persist_key)) -    key_schedule_free (&c->c1.ks, free_ssl_ctx); +    { +      key_schedule_free (&c->c1.ks, free_ssl_ctx); +      free_key_ctx_bi (&c->c2.crypto_options.key_ctx_bi); +    } +#endif /* ENABLE_CRYPTO */  }  /* @@ -2893,7 +2908,7 @@ static void  do_close_packet_id (struct context *c)  {  #ifdef ENABLE_CRYPTO -  packet_id_free (&c->c2.packet_id); +  packet_id_free (&c->c2.crypto_options.packet_id);    packet_id_persist_save (&c->c1.pid_persist);    if (!(c->sig->signal_received == SIGUSR1))      packet_id_persist_close (&c->c1.pid_persist); @@ -3187,7 +3202,7 @@ managmenet_callback_network_change (void *arg)       reestablishing the connection is required */    socketfd = c->c2.link_socket->sd; -  if (!c->options.pull || c->c2.tls_multi->use_session_id) +  if (!c->options.pull || c->c2.tls_multi->use_peer_id)      return socketfd;    else      return -2; @@ -3780,7 +3795,6 @@ close_context (struct context *c, int sig, unsigned int flags)  }  #ifdef ENABLE_CRYPTO -  /*   * Do a loopback test   * on the crypto subsystem. @@ -3797,23 +3811,21 @@ test_crypto_thread (void *arg)    next_connection_entry(c);    do_init_crypto_static (c, 0); -  frame_finalize_options (c, options); +  frame_finalize_options (&c->c2.frame, options, CIPHER_ENABLED (c));    test_crypto (&c->c2.crypto_options, &c->c2.frame);    key_schedule_free (&c->c1.ks, true); -  packet_id_free (&c->c2.packet_id); +  free_key_ctx_bi (&c->c2.crypto_options.key_ctx_bi); +  packet_id_free (&c->c2.crypto_options.packet_id);    context_gc_free (c);    return NULL;  } -#endif -  bool  do_test_crypto (const struct options *o)  { -#ifdef ENABLE_CRYPTO    if (o->test_crypto)      {        struct context c; @@ -3828,6 +3840,12 @@ do_test_crypto (const struct options *o)        test_crypto_thread ((void *) &c);        return true;      } -#endif    return false;  } +#else +bool +do_test_crypto (const struct options *o) +{ +  return false; +} +#endif /* ENABLE_CRYPTO */ diff --git a/main/openvpn/src/openvpn/mroute.h b/main/openvpn/src/openvpn/mroute.h index 608f70be..60653f96 100644 --- a/main/openvpn/src/openvpn/mroute.h +++ b/main/openvpn/src/openvpn/mroute.h @@ -186,19 +186,23 @@ mroute_addr_hash_len (const struct mroute_addr *a)  static inline void  mroute_extract_in_addr_t (struct mroute_addr *dest, const in_addr_t src)  { +  uint32_t tmp_addr = htonl (src);    dest->type = MR_ADDR_IPV4;    dest->netbits = 0;    dest->len = 4; -  *(in_addr_t*)dest->addr = htonl (src); +  memcpy(dest->addr, &tmp_addr, sizeof(uint32_t));  }  static inline in_addr_t  in_addr_t_from_mroute_addr (const struct mroute_addr *addr)  { -  if ((addr->type & MR_ADDR_MASK) == MR_ADDR_IPV4 && addr->netbits == 0 && addr->len == 4) -    return ntohl(*(in_addr_t*)addr->addr); -  else +  if ((addr->type & MR_ADDR_MASK) == MR_ADDR_IPV4 && addr->netbits == 0 && addr->len == 4) { +    uint32_t tmp = 0; +    memcpy(&tmp, addr->addr, sizeof(uint32_t)); +    return ntohl(tmp); +  } else {      return 0; +  }  }  static inline void diff --git a/main/openvpn/src/openvpn/mudp.c b/main/openvpn/src/openvpn/mudp.c index f6349dbf..8941d896 100644 --- a/main/openvpn/src/openvpn/mudp.c +++ b/main/openvpn/src/openvpn/mudp.c @@ -107,24 +107,22 @@ multi_get_create_instance_udp (struct multi_context *m)        struct hash_bucket *bucket = hash_bucket (hash, hv);        uint8_t* ptr  = BPTR(&m->top.c2.buf);        uint8_t op = ptr[0] >> P_OPCODE_SHIFT; -      uint32_t sess_id; +      uint32_t peer_id;        bool session_forged = false;        if (op == P_DATA_V2)  	{ -	  sess_id = ntohl((*(uint32_t*)ptr)) & 0xFFFFFF; -	  if ((sess_id < m->max_clients) && (m->instances[sess_id])) +	  peer_id = ntohl((*(uint32_t*)ptr)) & 0xFFFFFF; +	  if ((peer_id < m->max_clients) && (m->instances[peer_id]))  	    { -	      mi = m->instances[sess_id]; +	      mi = m->instances[peer_id];  	      if (!link_socket_actual_match(&mi->context.c2.from, &m->top.c2.from))  		{ -		  msg(D_MULTI_MEDIUM, "floating detected from %s to %s (session id: %d)", -		      print_link_socket_actual (&mi->context.c2.from, &gc), -              print_link_socket_actual (&m->top.c2.from, &gc), -              sess_id); +		  msg(D_MULTI_MEDIUM, "floating detected from %s to %s", +		      print_link_socket_actual (&mi->context.c2.from, &gc), print_link_socket_actual (&m->top.c2.from, &gc)); -		  /* session-id is not trusted, so check hmac */ +		  /* peer-id is not trusted, so check hmac */  		  session_forged = !(crypto_test_hmac(&m->top.c2.buf, &mi->context.c2.crypto_options));  		  if (session_forged)  		    { @@ -164,7 +162,7 @@ multi_get_create_instance_udp (struct multi_context *m)  			{  			  if (!m->instances[i])  			    { -			      mi->context.c2.tls_multi->vpn_session_id = i; +			      mi->context.c2.tls_multi->peer_id = i;  			      m->instances[i] = mi;  			      break;  			    } @@ -185,15 +183,6 @@ multi_get_create_instance_udp (struct multi_context *m)  	{  	  const char *status = mi ? "[ok]" : "[failed]"; -	  /* -	  if (he && mi) -	    status = "[succeeded]"; -	  else if (!he && mi) -	    status = "[created]"; -	  else -	    status = "[failed]"; -	  */ -  	  dmsg (D_MULTI_DEBUG, "GET INST BY REAL: %s %s",  	       mroute_addr_print (&real, &gc),  	       status); diff --git a/main/openvpn/src/openvpn/multi.c b/main/openvpn/src/openvpn/multi.c index e55b9778..c585630b 100644 --- a/main/openvpn/src/openvpn/multi.c +++ b/main/openvpn/src/openvpn/multi.c @@ -561,7 +561,7 @@ multi_close_instance (struct multi_context *m,  	}  #endif -      m->instances[mi->context.c2.tls_multi->vpn_session_id] = NULL; +      m->instances[mi->context.c2.tls_multi->peer_id] = NULL;        schedule_remove_entry (m->schedule, (struct schedule_entry *) mi); diff --git a/main/openvpn/src/openvpn/ntlm.c b/main/openvpn/src/openvpn/ntlm.c index 3390bddd..1833cecf 100644 --- a/main/openvpn/src/openvpn/ntlm.c +++ b/main/openvpn/src/openvpn/ntlm.c @@ -73,26 +73,26 @@ create_des_keys(const unsigned char *hash, unsigned char *key)  }  static void -gen_md4_hash (const char* data, int data_len, char *result) +gen_md4_hash (const uint8_t* data, int data_len, uint8_t *result)  {    /* result is 16 byte md4 hash */    const md_kt_t *md4_kt = md_kt_get("MD4"); -  char md[MD4_DIGEST_LENGTH]; +  uint8_t md[MD4_DIGEST_LENGTH];    md_full(md4_kt, data, data_len, md);    memcpy (result, md, MD4_DIGEST_LENGTH);  }  static void -gen_hmac_md5 (const char* data, int data_len, const char* key, int key_len,char *result) +gen_hmac_md5 (const uint8_t *data, int data_len, const uint8_t *key, int key_len, uint8_t *result)  {  	const md_kt_t *md5_kt = md_kt_get("MD5");  	hmac_ctx_t hmac_ctx;  	CLEAR(hmac_ctx);  	hmac_ctx_init(&hmac_ctx, key, key_len, md5_kt); -	hmac_ctx_update(&hmac_ctx, (const unsigned char *)data, data_len); -	hmac_ctx_final(&hmac_ctx, (unsigned char *)result); +	hmac_ctx_update(&hmac_ctx, data, data_len); +	hmac_ctx_final(&hmac_ctx, result);  	hmac_ctx_cleanup(&hmac_ctx);  } @@ -140,7 +140,7 @@ unsigned char *my_strupr(unsigned char *str)  }  static int -unicodize (char *dst, const char *src) +unicodize (uint8_t *dst, const char *src)  {    /* not really unicode... */    int i = 0; @@ -192,20 +192,20 @@ ntlm_phase_3 (const struct http_proxy_info *p, const char *phase_2, struct gc_ar  	 *  	 */ -  char pwbuf[sizeof (p->up.password) * 2]; /* for unicode password */ +  uint8_t pwbuf[sizeof (p->up.password) * 2]; /* for unicode password */    char buf2[128]; /* decoded reply from proxy */    unsigned char phase3[464]; -  char md4_hash[MD4_DIGEST_LENGTH+5]; -  char challenge[8], ntlm_response[24]; +  uint8_t md4_hash[MD4_DIGEST_LENGTH+5]; +  unsigned char challenge[8], ntlm_response[24];    int i, ret_val; -	char ntlmv2_response[144]; -	char userdomain_u[256]; /* for uppercase unicode username and domain */ +	uint8_t ntlmv2_response[144]; +	uint8_t userdomain_u[256]; /* for uppercase unicode username and domain */  	char userdomain[128];   /* the same as previous but ascii */ -	char ntlmv2_hash[MD5_DIGEST_LENGTH]; -	char ntlmv2_hmacmd5[16]; -	char *ntlmv2_blob = ntlmv2_response + 16; /* inside ntlmv2_response, length: 128 */ +	uint8_t ntlmv2_hash[MD5_DIGEST_LENGTH]; +	uint8_t ntlmv2_hmacmd5[16]; +	uint8_t *ntlmv2_blob = ntlmv2_response + 16; /* inside ntlmv2_response, length: 128 */  	int ntlmv2_blob_size=0;  	int phase3_bufpos = 0x40; /* offset to next security buffer data to be added */  	size_t len; diff --git a/main/openvpn/src/openvpn/openvpn.h b/main/openvpn/src/openvpn/openvpn.h index eab8cd5b..57676868 100644 --- a/main/openvpn/src/openvpn/openvpn.h +++ b/main/openvpn/src/openvpn/openvpn.h @@ -59,14 +59,12 @@ struct key_schedule    /* which cipher, HMAC digest, and key sizes are we using? */    struct key_type key_type; -  /* pre-shared static key, read from a file */ -  struct key_ctx_bi static_key; -  #ifdef ENABLE_SSL    /* our global SSL context */    struct tls_root_ctx ssl_ctx;    /* optional authentication HMAC key for TLS control channel */ +  struct key_type tls_auth_key_type;    struct key_ctx_bi tls_auth_key;  #endif				/* ENABLE_SSL */ @@ -366,7 +364,6 @@ struct context_2                                   *   process data channel packet. */    /* used to keep track of data channel packet sequence numbers */ -  struct packet_id packet_id;    struct event_timeout packet_id_persist_interval;  #endif /* ENABLE_CRYPTO */ diff --git a/main/openvpn/src/openvpn/options.c b/main/openvpn/src/openvpn/options.c index da143114..bdab8fea 100644 --- a/main/openvpn/src/openvpn/options.c +++ b/main/openvpn/src/openvpn/options.c @@ -570,6 +570,7 @@ static const char usage_message[] =    "--tls-version-min <version> ['or-highest'] : sets the minimum TLS version we\n"    "    will accept from the peer.  If version is unrecognized and 'or-highest'\n"    "    is specified, require max TLS version supported by SSL implementation.\n" +  "--tls-version-max <version> : sets the maximum TLS version we will use.\n"  #ifndef ENABLE_CRYPTO_POLARSSL    "--pkcs12 file   : PKCS#12 file containing local private key, local certificate\n"    "                  and optionally the root CA certificate.\n" @@ -2145,10 +2146,6 @@ options_postprocess_verify_ce (const struct options *options, const struct conne        (options->shared_secret_file != NULL) > 1)      msg (M_USAGE, "specify only one of --tls-server, --tls-client, or --secret"); -  if (options->tls_server) -    { -      notnull (options->dh_file, "DH file (--dh)"); -    }    if (options->tls_server || options->tls_client)      {  #ifdef ENABLE_PKCS11 @@ -2500,6 +2497,16 @@ options_postprocess_mutate (struct options *o)    for (i = 0; i < o->connection_list->len; ++i)  	options_postprocess_mutate_ce (o, o->connection_list->array[i]); +#ifdef ENABLE_SSL +  if (o->tls_server) +    { +      /* Check that DH file is specified, or explicitly disabled */ +      notnull (o->dh_file, "DH file (--dh)"); +      if (streq (o->dh_file, "none")) +	o->dh_file = NULL; +    } +#endif +  #if ENABLE_MANAGEMENT    if (o->http_proxy_override)  	options_postprocess_http_proxy_override(o); @@ -2991,7 +2998,8 @@ options_string (const struct options *o,  		       o->authname, o->authname_defined,  		       o->keysize, true, false); -	buf_printf (&out, ",cipher %s", cipher_kt_name (kt.cipher)); +	buf_printf (&out, ",cipher %s", +	    translate_cipher_name_to_openvpn(cipher_kt_name (kt.cipher)));  	buf_printf (&out, ",auth %s", md_kt_name (kt.digest));  	buf_printf (&out, ",keysize %d", kt.cipher_length * 8);  	if (o->shared_secret_file) @@ -6568,14 +6576,29 @@ add_option (struct options *options,      {        int ver;        VERIFY_PERMISSION (OPT_P_GENERAL); -      ver = tls_version_min_parse(p[1], p[2]); +      ver = tls_version_parse(p[1], p[2]);        if (ver == TLS_VER_BAD)  	{  	  msg (msglevel, "unknown tls-version-min parameter: %s", p[1]);            goto err;  	} -      options->ssl_flags &= ~(SSLF_TLS_VERSION_MASK << SSLF_TLS_VERSION_SHIFT); -      options->ssl_flags |= (ver << SSLF_TLS_VERSION_SHIFT); +      options->ssl_flags &= +	  ~(SSLF_TLS_VERSION_MIN_MASK << SSLF_TLS_VERSION_MIN_SHIFT); +      options->ssl_flags |= (ver << SSLF_TLS_VERSION_MIN_SHIFT); +    } +  else if (streq (p[0], "tls-version-max") && p[1]) +    { +      int ver; +      VERIFY_PERMISSION (OPT_P_GENERAL); +      ver = tls_version_parse(p[1], NULL); +      if (ver == TLS_VER_BAD) +	{ +	  msg (msglevel, "unknown tls-version-max parameter: %s", p[1]); +          goto err; +	} +      options->ssl_flags &= +	  ~(SSLF_TLS_VERSION_MAX_MASK << SSLF_TLS_VERSION_MAX_SHIFT); +      options->ssl_flags |= (ver << SSLF_TLS_VERSION_MAX_SHIFT);      }  #ifndef ENABLE_CRYPTO_POLARSSL    else if (streq (p[0], "pkcs12") && p[1]) @@ -6976,11 +6999,11 @@ add_option (struct options *options,        options->persist_mode = 1;      }  #endif -  else if (streq (p[0], "session-id")) +  else if (streq (p[0], "peer-id"))      { -      VERIFY_PERMISSION (OPT_P_SESSION_ID); -      options->use_session_id = true; -      options->vpn_session_id = atoi(p[1]); +      VERIFY_PERMISSION (OPT_P_PEER_ID); +      options->use_peer_id = true; +      options->peer_id = atoi(p[1]);      }    else      { diff --git a/main/openvpn/src/openvpn/options.h b/main/openvpn/src/openvpn/options.h index 537b8314..d5f7e95d 100644 --- a/main/openvpn/src/openvpn/options.h +++ b/main/openvpn/src/openvpn/options.h @@ -592,8 +592,8 @@ struct options    int route_method;  #endif -  bool use_session_id; -  uint32_t vpn_session_id; +  bool use_peer_id; +  uint32_t peer_id;  };  #define streq(x, y) (!strcmp((x), (y))) @@ -629,7 +629,7 @@ struct options  #define OPT_P_SOCKBUF         (1<<25)  #define OPT_P_SOCKFLAGS       (1<<26)  #define OPT_P_CONNECTION      (1<<27) -#define OPT_P_SESSION_ID      (1<<28) +#define OPT_P_PEER_ID         (1<<28)  #define OPT_P_DEFAULT   (~(OPT_P_INSTANCE|OPT_P_PULL_MODE)) diff --git a/main/openvpn/src/openvpn/packet_id.c b/main/openvpn/src/openvpn/packet_id.c index baa49664..122830b7 100644 --- a/main/openvpn/src/openvpn/packet_id.c +++ b/main/openvpn/src/openvpn/packet_id.c @@ -99,6 +99,12 @@ packet_id_init (struct packet_id *p, bool tcp_mode, int seq_backtrack, int time_    p->rec.initialized = true;  } +bool +packet_id_initialized (const struct packet_id *pid) +{ +  return pid->rec.initialized; +} +  void  packet_id_free (struct packet_id *p)  { diff --git a/main/openvpn/src/openvpn/packet_id.h b/main/openvpn/src/openvpn/packet_id.h index 3ddaab6a..2c786648 100644 --- a/main/openvpn/src/openvpn/packet_id.h +++ b/main/openvpn/src/openvpn/packet_id.h @@ -213,6 +213,9 @@ struct packet_id  void packet_id_init (struct packet_id *p, bool tcp_mode, int seq_backtrack, int time_backtrack, const char *name, int unit);  void packet_id_free (struct packet_id *p); +/** Is this struct packet_id initialized? */ +bool packet_id_initialized (const struct packet_id *pid); +  /* should we accept an incoming packet id ? */  bool packet_id_test (struct packet_id_rec *p,  		     const struct packet_id_net *pin); diff --git a/main/openvpn/src/openvpn/push.c b/main/openvpn/src/openvpn/push.c index af351763..c7844499 100644 --- a/main/openvpn/src/openvpn/push.c +++ b/main/openvpn/src/openvpn/push.c @@ -303,7 +303,7 @@ send_push_reply (struct context *c)    if (multi_push)      buf_printf (&buf, ",push-continuation 1"); -  /* Send session-id if client supports it */ +  /* Send peer-id if client supports it */    if (c->c2.tls_multi->peer_info)      {        const char* proto_str = strstr(c->c2.tls_multi->peer_info, "IV_PROTO="); @@ -312,7 +312,7 @@ send_push_reply (struct context *c)  	  int proto = 0;  	  int r = sscanf(proto_str, "IV_PROTO=%d", &proto);  	  if ((r == 1) && (proto >= 2)) -	    buf_printf(&buf, ",session-id %d", c->c2.tls_multi->vpn_session_id); +	    buf_printf(&buf, ",peer-id %d", c->c2.tls_multi->peer_id);  	}    } diff --git a/main/openvpn/src/openvpn/ssl.c b/main/openvpn/src/openvpn/ssl.c index e1e0f31d..103a5114 100644 --- a/main/openvpn/src/openvpn/ssl.c +++ b/main/openvpn/src/openvpn/ssl.c @@ -454,7 +454,7 @@ ssl_put_auth_challenge (const char *cr_str)   * return tls_version_max().   */  int -tls_version_min_parse(const char *vstr, const char *extra) +tls_version_parse(const char *vstr, const char *extra)  {    const int max_version = tls_version_max();    if (!strcmp(vstr, "1.0") && TLS_VER_1_0 <= max_version) @@ -483,7 +483,10 @@ init_ssl (const struct options *options, struct tls_root_ctx *new_ctx)    if (options->tls_server)      {        tls_ctx_server_new(new_ctx); -      tls_ctx_load_dh_params(new_ctx, options->dh_file, options->dh_file_inline); + +      if (options->dh_file) +	tls_ctx_load_dh_params(new_ctx, options->dh_file, +			       options->dh_file_inline);      }    else				/* if client */      { @@ -761,11 +764,17 @@ key_state_init (struct tls_session *session, struct key_state *ks)    reliable_set_timeout (ks->send_reliable, session->opt->packet_timeout);    /* init packet ID tracker */ -  packet_id_init (&ks->packet_id, -		  session->opt->tcp_mode, -		  session->opt->replay_window, -		  session->opt->replay_time, -		  "SSL", ks->key_id); +  if (session->opt->replay) +    { +      packet_id_init (&ks->crypto_options.packet_id, session->opt->tcp_mode, +	  session->opt->replay_window, session->opt->replay_time, "SSL", +	  ks->key_id); +    } + +  ks->crypto_options.pid_persist = NULL; +  ks->crypto_options.flags = session->opt->crypto_flags; +  ks->crypto_options.flags &= session->opt->crypto_flags_and; +  ks->crypto_options.flags |= session->opt->crypto_flags_or;  #ifdef MANAGEMENT_DEF_AUTH    ks->mda_key_id = session->opt->mda_context->mda_key_id_counter++; @@ -793,7 +802,7 @@ key_state_free (struct key_state *ks, bool clear)    key_state_ssl_free(&ks->ks_ssl); -  free_key_ctx_bi (&ks->key); +  free_key_ctx_bi (&ks->crypto_options.key_ctx_bi);    free_buf (&ks->plaintext_read_buf);    free_buf (&ks->plaintext_write_buf);    free_buf (&ks->ack_write_buf); @@ -817,7 +826,7 @@ key_state_free (struct key_state *ks, bool clear)    if (ks->key_src)      free (ks->key_src); -  packet_id_free (&ks->packet_id); +  packet_id_free (&ks->crypto_options.packet_id);  #ifdef PLUGIN_DEF_AUTH    key_state_rm_auth_control_file (ks); @@ -832,13 +841,6 @@ key_state_free (struct key_state *ks, bool clear)  /** @} addtogroup control_processor */ -/* - * Must be called if we move a tls_session in memory. - */ -static inline void tls_session_set_self_referential_pointers (struct tls_session* session) { -  session->tls_auth.packet_id = &session->tls_auth_pid; -} -  /**   * Returns whether or not the server should check for username/password   * @@ -911,18 +913,15 @@ tls_session_init (struct tls_multi *multi, struct tls_session *session)    /* Initialize control channel authentication parameters */    session->tls_auth = session->opt->tls_auth; -  /* Set session internal pointers (also called if session object is moved in memory) */ -  tls_session_set_self_referential_pointers (session); -    /* initialize packet ID replay window for --tls-auth */ -  packet_id_init (session->tls_auth.packet_id, +  packet_id_init (&session->tls_auth.packet_id,  		  session->opt->tcp_mode,  		  session->opt->replay_window,  		  session->opt->replay_time,  		  "TLS_AUTH", session->key_id);    /* load most recent packet-id to replay protect on --tls-auth */ -  packet_id_persist_load_obj (session->tls_auth.pid_persist, session->tls_auth.packet_id); +  packet_id_persist_load_obj (session->tls_auth.pid_persist, &session->tls_auth.packet_id);    key_state_init (session, &session->key[KS_PRIMARY]); @@ -949,8 +948,8 @@ tls_session_free (struct tls_session *session, bool clear)  {    int i; -  if (session->tls_auth.packet_id) -    packet_id_free (session->tls_auth.packet_id); +  if (packet_id_initialized(&session->tls_auth.packet_id)) +    packet_id_free (&session->tls_auth.packet_id);    for (i = 0; i < KS_SIZE; ++i)      key_state_free (&session->key[i], false); @@ -981,7 +980,6 @@ move_session (struct tls_multi* multi, int dest, int src, bool reinit_src)    ASSERT (dest >= 0 && dest < TM_SIZE);    tls_session_free (&multi->session[dest], false);    multi->session[dest] = multi->session[src]; -  tls_session_set_self_referential_pointers (&multi->session[dest]);    if (reinit_src)      tls_session_init (multi, &multi->session[src]); @@ -1046,9 +1044,6 @@ tls_multi_init (struct tls_options *tls_options)    /* get command line derived options */    ret->opt = *tls_options; -  /* set up pointer to HMAC object for TLS packet authentication */ -  ret->opt.tls_auth.key_ctx_bi = &ret->opt.tls_auth_key; -    /* set up list of keys to be scanned by data channel encrypt and decrypt routines */    ASSERT (SIZE (ret->key_scan) == 3);    ret->key_scan[0] = &ret->session[TM_ACTIVE].key[KS_PRIMARY]; @@ -1056,7 +1051,7 @@ tls_multi_init (struct tls_options *tls_options)    ret->key_scan[2] = &ret->session[TM_LAME_DUCK].key[KS_LAME_DUCK];    /* By default not use P_DATA_V2 */ -  ret->use_session_id = false; +  ret->use_peer_id = false;    return ret;  } @@ -1087,8 +1082,7 @@ tls_auth_standalone_init (struct tls_options *tls_options,    ALLOC_OBJ_CLEAR_GC (tas, struct tls_auth_standalone, gc);    /* set up pointer to HMAC object for TLS packet authentication */ -  tas->tls_auth_key = tls_options->tls_auth_key; -  tas->tls_auth_options.key_ctx_bi = &tas->tls_auth_key; +  tas->tls_auth_options.key_ctx_bi = tls_options->tls_auth.key_ctx_bi;    tas->tls_auth_options.flags |= CO_PACKET_ID_LONG_FORM;    /* get initial frame parms, still need to finalize */ @@ -1171,11 +1165,11 @@ tls_multi_free (struct tls_multi *multi, bool clear)  static bool  swap_hmac (struct buffer *buf, const struct crypto_options *co, bool incoming)  { -  struct key_ctx *ctx; +  const struct key_ctx *ctx;    ASSERT (co); -  ctx = (incoming ? &co->key_ctx_bi->decrypt : &co->key_ctx_bi->encrypt); +  ctx = (incoming ? &co->key_ctx_bi.decrypt : &co->key_ctx_bi.encrypt);    ASSERT (ctx->hmac);    { @@ -1239,7 +1233,7 @@ write_control_auth (struct tls_session *session,    ASSERT (session_id_write_prepend (&session->session_id, buf));    ASSERT (header = buf_prepend (buf, 1));    *header = ks->key_id | (opcode << P_OPCODE_SHIFT); -  if (session->tls_auth.key_ctx_bi->encrypt.hmac) +  if (session->tls_auth.key_ctx_bi.encrypt.hmac)      {        /* no encryption, only write hmac */        openvpn_encrypt (buf, null, &session->tls_auth, NULL); @@ -1253,12 +1247,12 @@ write_control_auth (struct tls_session *session,   */  static bool  read_control_auth (struct buffer *buf, -		   const struct crypto_options *co, +		   struct crypto_options *co,  		   const struct link_socket_actual *from)  {    struct gc_arena gc = gc_new (); -  if (co->key_ctx_bi->decrypt.hmac) +  if (co->key_ctx_bi.decrypt.hmac)      {        struct buffer null = clear_buf (); @@ -1589,6 +1583,41 @@ generate_key_expansion (struct key_ctx_bi *key,    return ret;  } +/** + * Initialize the implicit IV for a key_ctx_bi based on TLS session ids and + * cipher used. + * + * @param keys			Encrypt/decrypt key context + * @param cipher_kt		Cipher key type info + * @param session_id_local	The local session id for this session + * @param session_id_remote	The remote seession id for this session + * + * @return true on success, false on failure. + */ +static bool +ssl_init_implicit_iv(struct key_ctx_bi *keys, const cipher_kt_t *cipher_kt, +    const struct session_id *session_id_local, +    const struct session_id *session_id_remote) +{ +  ASSERT (NULL != keys); +  ASSERT (NULL != cipher_kt); +  ASSERT (NULL != session_id_local); +  ASSERT (NULL != session_id_remote); + +  if (cipher_kt_mode_aead(cipher_kt)) +    { +      if (!key_ctx_set_implicit_iv(&keys->encrypt, session_id_local->id, +	  SID_SIZE)) +	return false; + +      if (!key_ctx_set_implicit_iv(&keys->decrypt, session_id_remote->id, +	  SID_SIZE)) +	return false; +    } + +  return true; +} +  static bool  random_bytes_to_buf (struct buffer *buf,  		     uint8_t *out, @@ -1778,8 +1807,9 @@ key_method_1_write (struct buffer *buf, struct tls_session *session)        return false;      } -  init_key_ctx (&ks->key.encrypt, &key, &session->opt->key_type, -		OPENVPN_OP_ENCRYPT, "Data Channel Encrypt"); +  init_key_ctx (&ks->crypto_options.key_ctx_bi.encrypt, &key, +		&session->opt->key_type, OPENVPN_OP_ENCRYPT, +		"Data Channel Encrypt");    CLEAR (key);    /* send local options string */ @@ -1935,7 +1965,7 @@ key_method_2_write (struct buffer *buf, struct tls_session *session)      {        if (ks->authenticated)  	{ -	  if (!generate_key_expansion (&ks->key, +	  if (!generate_key_expansion (&ks->crypto_options.key_ctx_bi,  				       &session->opt->key_type,  				       ks->key_src,  				       &ks->session_id_remote, @@ -1945,6 +1975,14 @@ key_method_2_write (struct buffer *buf, struct tls_session *session)  	      msg (D_TLS_ERRORS, "TLS Error: server generate_key_expansion failed");  	      goto error;  	    } + +	  if (!ssl_init_implicit_iv(&ks->crypto_options.key_ctx_bi, +		  session->opt->key_type.cipher, &session->session_id, +		  &ks->session_id_remote)) +	    { +	      msg (D_TLS_ERRORS, "TLS Error: initializing implicit IV failed"); +	      goto error; +	    }  	}        CLEAR (*ks->key_src); @@ -2006,8 +2044,9 @@ key_method_1_read (struct buffer *buf, struct tls_session *session)    buf_clear (buf); -  init_key_ctx (&ks->key.decrypt, &key, &session->opt->key_type, -		OPENVPN_OP_DECRYPT, "Data Channel Decrypt"); +  init_key_ctx (&ks->crypto_options.key_ctx_bi.decrypt, &key, +		&session->opt->key_type, OPENVPN_OP_DECRYPT, +		"Data Channel Decrypt");    CLEAR (key);    ks->authenticated = true;    return true; @@ -2147,7 +2186,7 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi     */    if (!session->opt->server)      { -      if (!generate_key_expansion (&ks->key, +      if (!generate_key_expansion (&ks->crypto_options.key_ctx_bi,  				   &session->opt->key_type,  				   ks->key_src,  				   &session->session_id, @@ -2157,6 +2196,14 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi  	  msg (D_TLS_ERRORS, "TLS Error: client generate_key_expansion failed");  	  goto error;  	} + +      if (!ssl_init_implicit_iv(&ks->crypto_options.key_ctx_bi, +	    session->opt->key_type.cipher, &session->session_id, +	    &ks->session_id_remote)) +	{ +	  msg (D_TLS_ERRORS, "TLS Error: initializing implicit IV failed"); +	  goto error; +	}        CLEAR (*ks->key_src);      } @@ -2219,7 +2266,7 @@ tls_process (struct tls_multi *multi,  	   && ks->n_bytes >= session->opt->renegotiate_bytes)         || (session->opt->renegotiate_packets  	   && ks->n_packets >= session->opt->renegotiate_packets) -       || (packet_id_close_to_wrapping (&ks->packet_id.send)))) +       || (packet_id_close_to_wrapping (&ks->crypto_options.packet_id.send))))      {        msg (D_TLS_DEBUG_LOW,             "TLS: soft reset sec=%d bytes=" counter_format "/%d pkts=" counter_format "/%d", @@ -2773,7 +2820,7 @@ bool  tls_pre_decrypt (struct tls_multi *multi,  		 const struct link_socket_actual *from,  		 struct buffer *buf, -		 struct crypto_options *opt) +		 struct crypto_options **opt)  {    struct gc_arena gc = gc_new ();    bool ret = false; @@ -2820,11 +2867,7 @@ tls_pre_decrypt (struct tls_multi *multi,  		  && link_socket_actual_match (from, &ks->remote_addr))  		{  		  /* return appropriate data channel decrypt key in opt */ -		  opt->key_ctx_bi = &ks->key; -		  opt->packet_id = multi->opt.replay ? &ks->packet_id : NULL; -		  opt->pid_persist = NULL; -		  opt->flags &= multi->opt.crypto_flags_and; -		  opt->flags |= multi->opt.crypto_flags_or; +		  *opt = &ks->crypto_options;  		  ASSERT (buf_advance (buf, 1));  		  if (op == P_DATA_V2) { @@ -3206,10 +3249,7 @@ tls_pre_decrypt (struct tls_multi *multi,   done:    buf->len = 0; -  opt->key_ctx_bi = NULL; -  opt->packet_id = NULL; -  opt->pid_persist = NULL; -  opt->flags &= multi->opt.crypto_flags_and; +  *opt = NULL;    gc_free (&gc);    return ret; @@ -3336,7 +3376,7 @@ tls_pre_decrypt_lite (const struct tls_auth_standalone *tas,  /* Choose the key with which to encrypt a data packet */  void  tls_pre_encrypt (struct tls_multi *multi, -		 struct buffer *buf, struct crypto_options *opt) +		 struct buffer *buf, struct crypto_options **opt)  {    multi->save_ks = NULL;    if (buf->len > 0) @@ -3365,11 +3405,7 @@ tls_pre_encrypt (struct tls_multi *multi,        if (ks_select)  	{ -	  opt->key_ctx_bi = &ks_select->key; -	  opt->packet_id = multi->opt.replay ? &ks_select->packet_id : NULL; -	  opt->pid_persist = NULL; -	  opt->flags &= multi->opt.crypto_flags_and; -	  opt->flags |= multi->opt.crypto_flags_or; +	  *opt = &ks_select->crypto_options;  	  multi->save_ks = ks_select;  	  dmsg (D_TLS_KEYSELECT, "TLS: tls_pre_encrypt: key_id=%d", ks_select->key_id);  	  return; @@ -3384,10 +3420,7 @@ tls_pre_encrypt (struct tls_multi *multi,      }    buf->len = 0; -  opt->key_ctx_bi = NULL; -  opt->packet_id = NULL; -  opt->pid_persist = NULL; -  opt->flags &= multi->opt.crypto_flags_and; +  *opt = NULL;  }  /* Prepend the appropriate opcode to encrypted buffer prior to TCP/UDP send */ @@ -3396,7 +3429,7 @@ tls_post_encrypt (struct tls_multi *multi, struct buffer *buf)  {    struct key_state *ks;    uint8_t *op; -  uint32_t sess; +  uint32_t peer;    ks = multi->save_ks;    multi->save_ks = NULL; @@ -3404,10 +3437,10 @@ tls_post_encrypt (struct tls_multi *multi, struct buffer *buf)      {        ASSERT (ks); -      if (!multi->opt.server && multi->use_session_id) +      if (!multi->opt.server && multi->use_peer_id)  	{ -	  sess = htonl(((P_DATA_V2 << P_OPCODE_SHIFT) | ks->key_id) << 24 | (multi->vpn_session_id & 0xFFFFFF)); -	  ASSERT (buf_write_prepend (buf, &sess, 4)); +	  peer = htonl(((P_DATA_V2 << P_OPCODE_SHIFT) | ks->key_id) << 24 | (multi->peer_id & 0xFFFFFF)); +	  ASSERT (buf_write_prepend (buf, &peer, 4));  	}        else  	{ @@ -3497,7 +3530,7 @@ const struct link_socket_actual *from)    for (i = 0; i < KEY_SCAN_SIZE; ++i)      {        struct key_state *ks = multi->key_scan[i]; -      if (DECRYPT_KEY_ENABLED (multi, ks) && ks->authenticated && link_socket_actual_defined(&ks->remote_addr)) +      if (DECRYPT_KEY_ENABLED (multi, ks) && ks->authenticated && link_socket_actual_defined(&ks->remote_addr))          {  	 if (link_socket_actual_match (from, &ks->remote_addr))  	   continue; diff --git a/main/openvpn/src/openvpn/ssl.h b/main/openvpn/src/openvpn/ssl.h index a53f4aef..cc80043e 100644 --- a/main/openvpn/src/openvpn/ssl.h +++ b/main/openvpn/src/openvpn/ssl.h @@ -60,7 +60,7 @@  #define P_CONTROL_V1                   4     /* control channel packet (usually TLS ciphertext) */  #define P_ACK_V1                       5     /* acknowledgement for packets received */  #define P_DATA_V1                      6     /* data channel packet */ -#define P_DATA_V2                      9     /* data channel packet with session-id */ +#define P_DATA_V2                      9     /* data channel packet with peer-id */  /* indicates key_method >= 2 */  #define P_CONTROL_HARD_RESET_CLIENT_V2 7     /* initial key from client, forget previous state */ @@ -136,7 +136,6 @@   */  struct tls_auth_standalone  { -  struct key_ctx_bi tls_auth_key;    struct crypto_options tls_auth_options;    struct frame frame;  }; @@ -293,9 +292,8 @@ int tls_multi_process (struct tls_multi *multi,   *     of this packet.   * @param from - The source address of the packet.   * @param buf - A buffer structure containing the incoming packet. - * @param opt - A crypto options structure that will be loaded with the - *     appropriate security parameters to handle the packet if it is a - *     data channel packet. + * @param opt - Returns a crypto options structure with the appropriate security + *     parameters to handle the packet if it is a data channel packet.   *   * @return   * @li True if the packet is a control channel packet that has been @@ -306,7 +304,7 @@ int tls_multi_process (struct tls_multi *multi,  bool tls_pre_decrypt (struct tls_multi *multi,  		      const struct link_socket_actual *from,  		      struct buffer *buf, -		      struct crypto_options *opt); +		      struct crypto_options **opt);  /**************************************************************************/ @@ -355,15 +353,15 @@ bool tls_pre_decrypt_lite (const struct tls_auth_standalone *tas,   * @ingroup data_crypto   *   * If no appropriate security parameters can be found, or if some other - * error occurs, then the buffer is set to empty. + * error occurs, then the buffer is set to empty, and the parameters to a NULL + * pointer.   *   * @param multi - The TLS state for this packet's destination VPN tunnel.   * @param buf - The buffer containing the outgoing packet. - * @param opt - The crypto options structure into which the appropriate - *     security parameters should be loaded. + * @param opt - Returns a crypto options structure with the security parameters.   */  void tls_pre_encrypt (struct tls_multi *multi, -		      struct buffer *buf, struct crypto_options *opt); +		      struct buffer *buf, struct crypto_options **opt);  /** diff --git a/main/openvpn/src/openvpn/ssl_backend.h b/main/openvpn/src/openvpn/ssl_backend.h index bfd15496..b0777bf5 100644 --- a/main/openvpn/src/openvpn/ssl_backend.h +++ b/main/openvpn/src/openvpn/ssl_backend.h @@ -109,11 +109,12 @@ void tls_clear_error();   * @return 		One of the TLS_VER_x constants or TLS_VER_BAD   *                      if a parse error should be flagged.   */ -#define TLS_VER_BAD   -1 -#define TLS_VER_1_0    0 /* default */ -#define TLS_VER_1_1    1 -#define TLS_VER_1_2    2 -int tls_version_min_parse(const char *vstr, const char *extra); +#define TLS_VER_BAD    -1 +#define TLS_VER_UNSPEC  0 /* default */ +#define TLS_VER_1_0     1 +#define TLS_VER_1_1     2 +#define TLS_VER_1_2     3 +int tls_version_parse(const char *vstr, const char *extra);  /**   * Return the maximum TLS version (as a TLS_VER_x constant) diff --git a/main/openvpn/src/openvpn/ssl_common.h b/main/openvpn/src/openvpn/ssl_common.h index 3288adf3..748febcf 100644 --- a/main/openvpn/src/openvpn/ssl_common.h +++ b/main/openvpn/src/openvpn/ssl_common.h @@ -160,9 +160,8 @@ struct key_state    int initial_opcode;		/* our initial P_ opcode */    struct session_id session_id_remote;   /* peer's random session ID */    struct link_socket_actual remote_addr; /* peer's IP addr */ -  struct packet_id packet_id;	       /* for data channel, to prevent replay attacks */ -  struct key_ctx_bi key;	       /* data channel keys for encrypt/decrypt/hmac */ +  struct crypto_options crypto_options;/* data channel crypto options */    struct key_source2 *key_src;         /* source entropy for key expansion */ @@ -259,6 +258,7 @@ struct tls_options    bool pass_config_info;    /* struct crypto_option flags */ +  unsigned int crypto_flags;    unsigned int crypto_flags_and;    unsigned int crypto_flags_or; @@ -268,7 +268,6 @@ struct tls_options    /* packet authentication for TLS handshake */    struct crypto_options tls_auth; -  struct key_ctx_bi tls_auth_key;    /* frame parameters for TLS control channel */    struct frame frame; @@ -296,8 +295,10 @@ struct tls_options  # define SSLF_AUTH_USER_PASS_OPTIONAL  (1<<2)  # define SSLF_OPT_VERIFY               (1<<4)  # define SSLF_CRL_VERIFY_DIR           (1<<5) -# define SSLF_TLS_VERSION_SHIFT        6 -# define SSLF_TLS_VERSION_MASK         0xF /* (uses bit positions 6 to 9) */ +# define SSLF_TLS_VERSION_MIN_SHIFT    6 +# define SSLF_TLS_VERSION_MIN_MASK     0xF /* (uses bit positions 6 to 9) */ +# define SSLF_TLS_VERSION_MAX_SHIFT    10 +# define SSLF_TLS_VERSION_MAX_MASK     0xF /* (uses bit positions 10 to 13) */    unsigned int ssl_flags;  #ifdef MANAGEMENT_DEF_AUTH @@ -357,7 +358,6 @@ struct tls_session    /* authenticate control packets */    struct crypto_options tls_auth; -  struct packet_id tls_auth_pid;    int initial_opcode;		/* our initial P_ opcode */    struct session_id session_id;	/* our random session ID */ @@ -496,8 +496,8 @@ struct tls_multi  #endif    /* For P_DATA_V2 */ -  uint32_t vpn_session_id; -  bool use_session_id; +  uint32_t peer_id; +  bool use_peer_id;    /*     * Our session objects. diff --git a/main/openvpn/src/openvpn/ssl_openssl.c b/main/openvpn/src/openvpn/ssl_openssl.c index adf3ae6f..c1a01002 100644 --- a/main/openvpn/src/openvpn/ssl_openssl.c +++ b/main/openvpn/src/openvpn/ssl_openssl.c @@ -104,7 +104,7 @@ tls_ctx_server_new(struct tls_root_ctx *ctx)    ctx->ctx = SSL_CTX_new (SSLv23_server_method ());    if (ctx->ctx == NULL) -    msg (M_SSLERR, "SSL_CTX_new SSLv23_server_method"); +    crypto_msg (M_FATAL, "SSL_CTX_new SSLv23_server_method");  }  void @@ -115,7 +115,7 @@ tls_ctx_client_new(struct tls_root_ctx *ctx)    ctx->ctx = SSL_CTX_new (SSLv23_client_method ());    if (ctx->ctx == NULL) -    msg (M_SSLERR, "SSL_CTX_new SSLv23_client_method"); +    crypto_msg (M_FATAL, "SSL_CTX_new SSLv23_client_method");  }  void @@ -152,7 +152,7 @@ info_callback (INFO_CALLBACK_SSL_CONST SSL * s, int where, int ret)      }    else if (where & SSL_CB_ALERT)      { -      dmsg (D_HANDSHAKE_VERBOSE, "SSL alert (%s): %s: %s", +      dmsg(D_HANDSHAKE_VERBOSE, "SSL alert (%s): %s: %s",  	   where & SSL_CB_READ ? "read" : "write",  	   SSL_alert_type_string_long (ret),  	   SSL_alert_desc_string_long (ret)); @@ -184,15 +184,23 @@ tls_ctx_set_options (struct tls_root_ctx *ctx, unsigned int ssl_flags)    /* process SSL options including minimum TLS version we will accept from peer */    {      long sslopt = SSL_OP_SINGLE_DH_USE | SSL_OP_NO_TICKET | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; -    const int tls_version_min = (ssl_flags >> SSLF_TLS_VERSION_SHIFT) & SSLF_TLS_VERSION_MASK; -    if (tls_version_min > TLS_VER_1_0) +    int tls_ver_max = TLS_VER_UNSPEC; +    const int tls_ver_min = +	(ssl_flags >> SSLF_TLS_VERSION_MIN_SHIFT) & SSLF_TLS_VERSION_MIN_MASK; + +    tls_ver_max = +	(ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT) & SSLF_TLS_VERSION_MAX_MASK; +    if (tls_ver_max <= TLS_VER_UNSPEC) +	tls_ver_max = tls_version_max(); + +    if (tls_ver_min > TLS_VER_1_0 || tls_ver_max < TLS_VER_1_0)        sslopt |= SSL_OP_NO_TLSv1;  #ifdef SSL_OP_NO_TLSv1_1 -    if (tls_version_min > TLS_VER_1_1) +    if (tls_ver_min > TLS_VER_1_1 || tls_ver_max < TLS_VER_1_1)        sslopt |= SSL_OP_NO_TLSv1_1;  #endif  #ifdef SSL_OP_NO_TLSv1_2 -    if (tls_version_min > TLS_VER_1_2) +    if (tls_ver_min > TLS_VER_1_2 || tls_ver_max < TLS_VER_1_2)        sslopt |= SSL_OP_NO_TLSv1_2;  #endif      SSL_CTX_set_options (ctx->ctx, sslopt); @@ -227,7 +235,7 @@ tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers)      {        /* Use sane default (disable export, and unsupported cipher modes) */        if(!SSL_CTX_set_cipher_list(ctx->ctx, "DEFAULT:!EXP:!PSK:!SRP")) -        msg(M_SSLERR, "Failed to set default TLS cipher list."); +	crypto_msg (M_FATAL, "Failed to set default TLS cipher list.");        return;      } @@ -280,7 +288,8 @@ tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers)        // Make sure new cipher name fits in cipher string        if (((sizeof(openssl_ciphers)-1) - openssl_ciphers_len) < current_cipher_len) { -	msg(M_SSLERR, "Failed to set restricted TLS cipher list, too long (>%d).", (int)sizeof(openssl_ciphers)-1); +	  crypto_msg (M_FATAL, "Failed to set restricted TLS cipher list, too " +	      "long (>%d).", (int)sizeof(openssl_ciphers)-1);        }        // Concatenate cipher name to OpenSSL cipher string @@ -297,7 +306,8 @@ tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers)    // Set OpenSSL cipher list    if(!SSL_CTX_set_cipher_list(ctx->ctx, openssl_ciphers)) -    msg(M_SSLERR, "Failed to set restricted TLS cipher list: %s", openssl_ciphers); +    crypto_msg (M_FATAL, "Failed to set restricted TLS cipher list: %s", +	openssl_ciphers);  }  void @@ -313,22 +323,22 @@ tls_ctx_load_dh_params (struct tls_root_ctx *ctx, const char *dh_file,    if (!strcmp (dh_file, INLINE_FILE_TAG) && dh_file_inline)      {        if (!(bio = BIO_new_mem_buf ((char *)dh_file_inline, -1))) -	msg (M_SSLERR, "Cannot open memory BIO for inline DH parameters"); +	crypto_msg (M_FATAL, "Cannot open memory BIO for inline DH parameters");      }    else      {        /* Get Diffie Hellman Parameters */        if (!(bio = BIO_new_file (dh_file, "r"))) -	msg (M_SSLERR, "Cannot open %s for DH parameters", dh_file); +	crypto_msg (M_FATAL, "Cannot open %s for DH parameters", dh_file);      }    dh = PEM_read_bio_DHparams (bio, NULL, NULL, NULL);    BIO_free (bio);    if (!dh) -    msg (M_SSLERR, "Cannot load DH parameters from %s", dh_file); +    crypto_msg (M_FATAL, "Cannot load DH parameters from %s", dh_file);    if (!SSL_CTX_set_tmp_dh (ctx->ctx, dh)) -    msg (M_SSLERR, "SSL_CTX_set_tmp_dh"); +    crypto_msg (M_FATAL, "SSL_CTX_set_tmp_dh");    msg (D_TLS_DEBUG_LOW, "Diffie-Hellman initialized with %d bit key",         8 * DH_size (dh)); @@ -397,7 +407,7 @@ tls_ctx_load_ecdh_params (struct tls_root_ctx *ctx, const char *curve_name      }    if (!SSL_CTX_set_tmp_ecdh(ctx->ctx, ecdh)) -    msg (M_SSLERR, "SSL_CTX_set_tmp_ecdh: cannot add curve"); +    crypto_msg (M_FATAL, "SSL_CTX_set_tmp_ecdh: cannot add curve");    msg (D_TLS_DEBUG_LOW, "ECDH curve %s added", sname); @@ -433,7 +443,7 @@ tls_ctx_load_pkcs12(struct tls_root_ctx *ctx, const char *pkcs12_file,        BIO_push(b64, bio);        p12 = d2i_PKCS12_bio(b64, NULL);        if (!p12) -	msg(M_SSLERR, "Error reading inline PKCS#12 file"); +	crypto_msg (M_FATAL, "Error reading inline PKCS#12 file");        BIO_free(b64);        BIO_free(bio);      } @@ -441,11 +451,11 @@ tls_ctx_load_pkcs12(struct tls_root_ctx *ctx, const char *pkcs12_file,      {        /* Load the PKCS #12 file */        if (!(fp = platform_fopen(pkcs12_file, "rb"))) -	msg(M_SSLERR, "Error opening file %s", pkcs12_file); +	crypto_msg (M_FATAL, "Error opening file %s", pkcs12_file);        p12 = d2i_PKCS12_fp(fp, NULL);        fclose(fp);        if (!p12) -	msg(M_SSLERR, "Error reading PKCS#12 file %s", pkcs12_file); +	crypto_msg (M_FATAL, "Error reading PKCS#12 file %s", pkcs12_file);      }    /* Parse the PKCS #12 file */ @@ -468,16 +478,16 @@ tls_ctx_load_pkcs12(struct tls_root_ctx *ctx, const char *pkcs12_file,    /* Load Certificate */    if (!SSL_CTX_use_certificate (ctx->ctx, cert)) -   msg (M_SSLERR, "Cannot use certificate"); +    crypto_msg (M_FATAL, "Cannot use certificate");    /* Load Private Key */    if (!SSL_CTX_use_PrivateKey (ctx->ctx, pkey)) -   msg (M_SSLERR, "Cannot use private key"); +    crypto_msg (M_FATAL, "Cannot use private key");    warn_if_group_others_accessible (pkcs12_file);    /* Check Private Key */    if (!SSL_CTX_check_private_key (ctx->ctx)) -   msg (M_SSLERR, "Private key does not match the certificate"); +    crypto_msg (M_FATAL, "Private key does not match the certificate");    /* Set Certificate Verification chain */    if (load_ca_file) @@ -491,9 +501,11 @@ tls_ctx_load_pkcs12(struct tls_root_ctx *ctx, const char *pkcs12_file,  	for (i = 0; i < sk_X509_num(ca); i++)  	  {  	    if (!X509_STORE_add_cert(ctx->ctx->cert_store,sk_X509_value(ca, i))) -	      msg (M_SSLERR, "Cannot add certificate to certificate chain (X509_STORE_add_cert)"); +	      crypto_msg (M_FATAL, "Cannot add certificate to certificate chain" +		  " (X509_STORE_add_cert)");  	    if (!SSL_CTX_add_client_CA(ctx->ctx, sk_X509_value(ca, i))) -	      msg (M_SSLERR, "Cannot add certificate to client CA list (SSL_CTX_add_client_CA)"); +	      crypto_msg (M_FATAL, "Cannot add certificate to client CA list " +		  "(SSL_CTX_add_client_CA)");  	  }        }     } else { @@ -507,7 +519,8 @@ tls_ctx_load_pkcs12(struct tls_root_ctx *ctx, const char *pkcs12_file,  	for (i = 0; i < sk_X509_num(ca); i++)  	  {  	    if (!SSL_CTX_add_extra_chain_cert(ctx->ctx,sk_X509_value(ca, i))) -	      msg (M_SSLERR, "Cannot add extra certificate to chain (SSL_CTX_add_extra_chain_cert)"); +	      crypto_msg (M_FATAL, "Cannot add extra certificate to chain " +		  "(SSL_CTX_add_extra_chain_cert)");  	  }        }     } @@ -522,8 +535,8 @@ tls_ctx_load_cryptoapi(struct tls_root_ctx *ctx, const char *cryptoapi_cert)    /* Load Certificate and Private Key */    if (!SSL_CTX_use_CryptoAPI_certificate (ctx->ctx, cryptoapi_cert)) -    msg (M_SSLERR, "Cannot load certificate \"%s\" from Microsoft Certificate Store", -	   cryptoapi_cert); +    crypto_msg (M_SSLERR, "Cannot load certificate \"%s\" from Microsoft " +	"Certificate Store", cryptoapi_cert);  }  #endif /* WIN32 */ @@ -537,9 +550,9 @@ tls_ctx_add_extra_certs (struct tls_root_ctx *ctx, BIO *bio)        if (!PEM_read_bio_X509 (bio, &cert, 0, NULL)) /* takes ownership of cert */          break;        if (!cert) -        msg (M_SSLERR, "Error reading extra certificate"); +	crypto_msg (M_FATAL, "Error reading extra certificate");        if (SSL_CTX_add_extra_chain_cert(ctx->ctx, cert) != 1) -        msg (M_SSLERR, "Error adding extra certificate"); +	crypto_msg (M_FATAL, "Error adding extra certificate");      }  } @@ -587,9 +600,9 @@ end:    if (!ret)      {        if (inline_file) -        msg (M_SSLERR, "Cannot load inline certificate file"); +	crypto_msg (M_FATAL, "Cannot load inline certificate file");        else -        msg (M_SSLERR, "Cannot load certificate file %s", cert_file); +	crypto_msg (M_FATAL, "Cannot load certificate file %s", cert_file);      }    if (in != NULL) @@ -647,14 +660,14 @@ tls_ctx_load_priv_file (struct tls_root_ctx *ctx, const char *priv_key_file,        if (management && (ERR_GET_REASON (ERR_peek_error()) == EVP_R_BAD_DECRYPT))            management_auth_failure (management, UP_TYPE_PRIVATE_KEY, NULL);  #endif -      msg (M_WARN|M_SSL, "Cannot load private key file %s", priv_key_file); +      crypto_msg (M_WARN, "Cannot load private key file %s", priv_key_file);        goto end;      }    warn_if_group_others_accessible (priv_key_file);    /* Check Private Key */    if (!SSL_CTX_check_private_key (ssl_ctx)) -    msg (M_SSLERR, "Private key does not match the certificate"); +    crypto_msg (M_FATAL, "Private key does not match the certificate");    ret = 0;  end: @@ -805,7 +818,7 @@ tls_ctx_use_external_private_key (struct tls_root_ctx *ctx,        if (rsa_meth)  	free(rsa_meth);      } -  msg (M_SSLERR, "Cannot enable SSL external private key capability"); +  crypto_msg (M_FATAL, "Cannot enable SSL external private key capability");    return 0;  } @@ -835,7 +848,8 @@ tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file,    store = SSL_CTX_get_cert_store(ctx->ctx);    if (!store) -    msg(M_SSLERR, "Cannot get certificate store (SSL_CTX_get_cert_store)"); +    crypto_msg (M_FATAL, "Cannot get certificate store " +	"(SSL_CTX_get_cert_store)");    /* Try to add certificates and CRLs from ca_file */    if (ca_file) @@ -858,7 +872,7 @@ tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file,                if (tls_server && !info->x509)                  { -                  msg (M_SSLERR, "X509 name was missing in TLS mode"); +                  crypto_msg (M_FATAL, "X509 name was missing in TLS mode");                  }                if (info->x509) @@ -894,7 +908,8 @@ tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file,                if (tls_server) {                  int cnum = sk_X509_NAME_num (cert_names);                  if (cnum != (prev + 1)) { -                  msg (M_WARN, "Cannot load CA certificate file %s (entry %d did not validate)", np(ca_file), added); +                  crypto_msg (M_WARN, "Cannot load CA certificate file %s " +                      "(entry %d did not validate)", np(ca_file), added);                  }                  prev = cnum;                } @@ -907,12 +922,14 @@ tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file,          SSL_CTX_set_client_CA_list (ctx->ctx, cert_names);        if (!added) -        msg (M_SSLERR, "Cannot load CA certificate file %s (no entries were read)", np(ca_file)); +	crypto_msg (M_FATAL, "Cannot load CA certificate file %s " +	    "(no entries were read)", np(ca_file));        if (tls_server) {          int cnum = sk_X509_NAME_num (cert_names);          if (cnum != added) -          msg (M_SSLERR, "Cannot load CA certificate file %s (only %d of %d entries were valid X509 names)", np(ca_file), cnum, added); +          crypto_msg (M_FATAL, "Cannot load CA certificate file %s (only %d of " +              "%d entries were valid X509 names)", np(ca_file), cnum, added);        }        if (in) @@ -926,7 +943,7 @@ tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file,        if (lookup && X509_LOOKUP_add_dir (lookup, ca_path, X509_FILETYPE_PEM))          msg(M_WARN, "WARNING: experimental option --capath %s", ca_path);        else -        msg(M_SSLERR, "Cannot add lookup at --capath %s", ca_path); +	crypto_msg (M_FATAL, "Cannot add lookup at --capath %s", ca_path);        X509_STORE_set_flags (store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);      }  } @@ -943,7 +960,7 @@ tls_ctx_load_extra_certs (struct tls_root_ctx *ctx, const char *extra_certs_file      in = BIO_new_file (extra_certs_file, "r");    if (in == NULL) -    msg (M_SSLERR, "Cannot load extra-certs file: %s", extra_certs_file); +    crypto_msg (M_FATAL, "Cannot load extra-certs file: %s", extra_certs_file);    else      tls_ctx_add_extra_certs (ctx, in); @@ -1035,7 +1052,7 @@ getbio (BIO_METHOD * type, const char *desc)    BIO *ret;    ret = BIO_new (type);    if (!ret) -    msg (M_SSLERR, "Error creating %s BIO", desc); +    crypto_msg (M_FATAL, "Error creating %s BIO", desc);    return ret;  } @@ -1069,16 +1086,15 @@ bio_write (BIO *bio, const uint8_t *data, int size, const char *desc)  	    }  	  else  	    { -	      msg (D_TLS_ERRORS | M_SSL, "TLS ERROR: BIO write %s error", -		   desc); +	      crypto_msg (D_TLS_ERRORS, "TLS ERROR: BIO write %s error", desc);  	      ret = -1;  	      ERR_clear_error ();  	    }  	}        else if (i != size)  	{ -	  msg (D_TLS_ERRORS | M_SSL, -	       "TLS ERROR: BIO write %s incomplete %d/%d", desc, i, size); +	  crypto_msg (D_TLS_ERRORS, "TLS ERROR: BIO write %s incomplete %d/%d", +	      desc, i, size);  	  ret = -1;  	  ERR_clear_error ();  	} @@ -1144,8 +1160,7 @@ bio_read (BIO *bio, struct buffer *buf, int maxlen, const char *desc)  	    }  	  else  	    { -	      msg (D_TLS_ERRORS | M_SSL, "TLS_ERROR: BIO read %s error", -		   desc); +	      crypto_msg (D_TLS_ERRORS, "TLS_ERROR: BIO read %s error", desc);  	      buf->len = 0;  	      ret = -1;  	      ERR_clear_error (); @@ -1175,7 +1190,7 @@ key_state_ssl_init(struct key_state_ssl *ks_ssl, const struct tls_root_ctx *ssl_    ks_ssl->ssl = SSL_new (ssl_ctx->ctx);    if (!ks_ssl->ssl) -    msg (M_SSLERR, "SSL_new failed"); +    crypto_msg (M_FATAL, "SSL_new failed");    /* put session * in ssl object so we can access it       from verify callback*/ @@ -1350,11 +1365,11 @@ show_available_tls_ciphers (const char *cipher_list)    tls_ctx.ctx = SSL_CTX_new (SSLv23_method ());    if (!tls_ctx.ctx) -    msg (M_SSLERR, "Cannot create SSL_CTX object"); +    crypto_msg (M_FATAL, "Cannot create SSL_CTX object");    ssl = SSL_new (tls_ctx.ctx);    if (!ssl) -    msg (M_SSLERR, "Cannot create SSL object"); +    crypto_msg (M_FATAL, "Cannot create SSL object");    tls_ctx_restrict_ciphers(&tls_ctx, cipher_list); @@ -1395,7 +1410,7 @@ show_available_curves()    curves = OPENSSL_malloc((int)(sizeof(EC_builtin_curve) * crv_len));    if (curves == NULL) -    msg (M_SSLERR, "Cannot create EC_builtin_curve object"); +    crypto_msg (M_FATAL, "Cannot create EC_builtin_curve object");    else    {      if (EC_get_builtin_curves(curves, crv_len)) @@ -1412,7 +1427,7 @@ show_available_curves()      }      else      { -      msg (M_SSLERR, "Cannot get list of builtin curves"); +      crypto_msg (M_FATAL, "Cannot get list of builtin curves");      }      OPENSSL_free(curves);    } @@ -1431,10 +1446,10 @@ get_highest_preference_tls_cipher (char *buf, int size)    ctx = SSL_CTX_new (SSLv23_method ());    if (!ctx) -    msg (M_SSLERR, "Cannot create SSL_CTX object"); +    crypto_msg (M_FATAL, "Cannot create SSL_CTX object");    ssl = SSL_new (ctx);    if (!ssl) -    msg (M_SSLERR, "Cannot create SSL object"); +    crypto_msg (M_FATAL, "Cannot create SSL object");    cipher_name = SSL_get_cipher_list (ssl, 0);    strncpynt (buf, cipher_name, size); diff --git a/main/openvpn/src/openvpn/ssl_polarssl.c b/main/openvpn/src/openvpn/ssl_polarssl.c index 62c110b4..385024e1 100644 --- a/main/openvpn/src/openvpn/ssl_polarssl.c +++ b/main/openvpn/src/openvpn/ssl_polarssl.c @@ -218,13 +218,13 @@ tls_ctx_load_dh_params (struct tls_root_ctx *ctx, const char *dh_file,  {    if (!strcmp (dh_file, INLINE_FILE_TAG) && dh_inline)      { -      if (0 != dhm_parse_dhm(ctx->dhm_ctx, (const unsigned char *) dh_inline, -	  strlen(dh_inline))) +      if (!polar_ok(dhm_parse_dhm(ctx->dhm_ctx, +	  (const unsigned char *) dh_inline, strlen(dh_inline))))  	msg (M_FATAL, "Cannot read inline DH parameters");    }  else    { -    if (0 != dhm_parse_dhmfile(ctx->dhm_ctx, dh_file)) +    if (!polar_ok(dhm_parse_dhmfile(ctx->dhm_ctx, dh_file)))        msg (M_FATAL, "Cannot read DH parameters from file %s", dh_file);    } @@ -268,18 +268,15 @@ tls_ctx_load_cert_file (struct tls_root_ctx *ctx, const char *cert_file,    if (!strcmp (cert_file, INLINE_FILE_TAG) && cert_inline)      { -      if (0 != x509_crt_parse(ctx->crt_chain, -	  (const unsigned char *) cert_inline, strlen(cert_inline))) +      if (!polar_ok(x509_crt_parse(ctx->crt_chain, +	  (const unsigned char *) cert_inline, strlen(cert_inline))))          msg (M_FATAL, "Cannot load inline certificate file");      }    else      { -      int retval = x509_crt_parse_file(ctx->crt_chain, cert_file); -      if (0 != retval) +      if (!polar_ok(x509_crt_parse_file(ctx->crt_chain, cert_file)))  	{ -	  char errstr[128]; -	  polarssl_strerror(retval, errstr, sizeof(errstr)); -	  msg (M_FATAL, "Cannot load certificate file %s (%s)", cert_file, errstr); +	  msg (M_FATAL, "Cannot load certificate file %s", cert_file);  	}      }  } @@ -298,7 +295,7 @@ tls_ctx_load_priv_file (struct tls_root_ctx *ctx, const char *priv_key_file,  	  (const unsigned char *) priv_key_inline, strlen(priv_key_inline),  	  NULL, 0); -      if (POLARSSL_ERR_PEM_PASSWORD_REQUIRED == status) +      if (POLARSSL_ERR_PK_PASSWORD_REQUIRED == status)  	{  	  char passbuf[512] = {0};  	  pem_password_callback(passbuf, 512, 0, NULL); @@ -310,17 +307,17 @@ tls_ctx_load_priv_file (struct tls_root_ctx *ctx, const char *priv_key_file,    else      {        status = pk_parse_keyfile(ctx->priv_key, priv_key_file, NULL); -      if (POLARSSL_ERR_PEM_PASSWORD_REQUIRED == status) +      if (POLARSSL_ERR_PK_PASSWORD_REQUIRED == status)  	{  	  char passbuf[512] = {0};  	  pem_password_callback(passbuf, 512, 0, NULL);  	  status = pk_parse_keyfile(ctx->priv_key, priv_key_file, passbuf);  	}      } -  if (0 != status) +  if (!polar_ok(status))      {  #ifdef ENABLE_MANAGEMENT -      if (management && (POLARSSL_ERR_PEM_PASSWORD_MISMATCH == status)) +      if (management && (POLARSSL_ERR_PK_PASSWORD_MISMATCH == status))  	  management_auth_failure (management, UP_TYPE_PRIVATE_KEY, NULL);  #endif        msg (M_WARN, "Cannot load private key file %s", priv_key_file); @@ -412,7 +409,7 @@ static inline int external_pkcs1_sign( void *ctx_voidptr,        if( md_info == NULL )          return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); -      if( oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) +      if (!polar_ok(oid_get_oid_by_md( md_alg, &oid, &oid_size )))          return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );        hashlen = md_get_size( md_info ); @@ -497,49 +494,43 @@ static inline size_t external_key_len(void *vctx)  #endif  void tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file, -    const char *ca_file_inline, -    const char *ca_path, bool tls_server +    const char *ca_inline, const char *ca_path, bool tls_server      )  {    if (ca_path)        msg(M_FATAL, "ERROR: PolarSSL cannot handle the capath directive"); -  if (ca_file && !strcmp (ca_file, INLINE_FILE_TAG) && ca_file_inline) +  if (ca_file && !strcmp (ca_file, INLINE_FILE_TAG) && ca_inline)      { -      if (0 != x509_crt_parse(ctx->ca_chain, (unsigned char *) ca_file_inline, -	  strlen(ca_file_inline))) +      if (!polar_ok(x509_crt_parse(ctx->ca_chain, +	  (const unsigned char *) ca_inline, strlen(ca_inline))))  	msg (M_FATAL, "Cannot load inline CA certificates");      }    else      {        /* Load CA file for verifying peer supplied certificate */ -      int retval = x509_crt_parse_file(ctx->ca_chain, ca_file); -      if (0 != retval) -	{ -	  char errstr[128]; -	  polarssl_strerror(retval, errstr, sizeof(errstr)); -	  msg (M_FATAL, "Cannot load CA certificate file %s (%s)", ca_file, errstr); -	} +      if (!polar_ok(x509_crt_parse_file(ctx->ca_chain, ca_file))) +	msg (M_FATAL, "Cannot load CA certificate file %s", ca_file);      }  }  void  tls_ctx_load_extra_certs (struct tls_root_ctx *ctx, const char *extra_certs_file, -    const char *extra_certs_file_inline +    const char *extra_certs_inline      )  {    ASSERT(NULL != ctx); -  if (!strcmp (extra_certs_file, INLINE_FILE_TAG) && extra_certs_file_inline) +  if (!strcmp (extra_certs_file, INLINE_FILE_TAG) && extra_certs_inline)      { -      if (0 != x509_crt_parse(ctx->crt_chain, -          (unsigned char *) extra_certs_file_inline, -	  strlen(extra_certs_file_inline))) +      if (!polar_ok(x509_crt_parse(ctx->crt_chain, +          (const unsigned char *) extra_certs_inline, +	  strlen(extra_certs_inline))))          msg (M_FATAL, "Cannot load inline extra-certs file");      }    else      { -      if (0 != x509_crt_parse_file(ctx->crt_chain, extra_certs_file)) +      if (!polar_ok(x509_crt_parse_file(ctx->crt_chain, extra_certs_file)))  	msg (M_FATAL, "Cannot load extra-certs file: %s", extra_certs_file);      }  } @@ -645,10 +636,8 @@ static int endless_buf_write( void *ctx, const unsigned char *in, size_t len )  static void my_debug( void *ctx, int level, const char *str )  { -  if (level == 1) -    { -      dmsg (D_HANDSHAKE_VERBOSE, "PolarSSL alert: %s", str); -    } +  int my_loglevel = (level < 2) ? D_TLS_DEBUG_MED : D_TLS_DEBUG; +  msg (my_loglevel, "PolarSSL alert: %s", str);  }  /* @@ -685,6 +674,40 @@ tls_version_max(void)  #endif  } +/** + * Convert an OpenVPN tls-version variable to PolarSSl format (i.e. a major and + * minor ssl version number). + * + * @param tls_ver	The tls-version variable to convert. + * @param major		Returns the TLS major version in polarssl format. + * 			Must be a valid pointer. + * @param minor		Returns the TLS minor version in polarssl format. + * 			Must be a valid pointer. + */ +static void tls_version_to_major_minor(int tls_ver, int *major, int *minor) { +  ASSERT(major); +  ASSERT(minor); + +  switch (tls_ver) +  { +    case TLS_VER_1_0: +      *major = SSL_MAJOR_VERSION_3; +      *minor = SSL_MINOR_VERSION_1; +      break; +    case TLS_VER_1_1: +      *major = SSL_MAJOR_VERSION_3; +      *minor = SSL_MINOR_VERSION_2; +      break; +    case TLS_VER_1_2: +      *major = SSL_MAJOR_VERSION_3; +      *minor = SSL_MINOR_VERSION_3; +      break; +    default: +      msg(M_FATAL, "%s: invalid TLS version %d", __func__, tls_ver); +      break; +  } +} +  void key_state_ssl_init(struct key_state_ssl *ks_ssl,      const struct tls_root_ctx *ssl_ctx, bool is_server, struct tls_session *session)  { @@ -693,88 +716,91 @@ void key_state_ssl_init(struct key_state_ssl *ks_ssl,    CLEAR(*ks_ssl);    ALLOC_OBJ_CLEAR(ks_ssl->ctx, ssl_context); -  if (0 == ssl_init(ks_ssl->ctx)) -    { -      /* Initialise SSL context */ -      ssl_set_dbg (ks_ssl->ctx, my_debug, NULL); -      ssl_set_endpoint (ks_ssl->ctx, ssl_ctx->endpoint); -      ssl_set_rng (ks_ssl->ctx, ctr_drbg_random, rand_ctx_get()); +  ASSERT (polar_ok(ssl_init(ks_ssl->ctx))); + +  /* Initialise SSL context */ +  ssl_set_dbg (ks_ssl->ctx, my_debug, NULL); +  ssl_set_endpoint (ks_ssl->ctx, ssl_ctx->endpoint); -      if (ssl_ctx->allowed_ciphers) -	ssl_set_ciphersuites (ks_ssl->ctx, ssl_ctx->allowed_ciphers); +  ssl_set_rng (ks_ssl->ctx, ctr_drbg_random, rand_ctx_get()); -      /* Initialise authentication information */ -      if (is_server) -	ssl_set_dh_param_ctx (ks_ssl->ctx, ssl_ctx->dhm_ctx ); +  if (ssl_ctx->allowed_ciphers) +    ssl_set_ciphersuites (ks_ssl->ctx, ssl_ctx->allowed_ciphers); + +  /* Initialise authentication information */ +  if (is_server) +    ASSERT (polar_ok(ssl_set_dh_param_ctx(ks_ssl->ctx, ssl_ctx->dhm_ctx)));  #if defined(ENABLE_PKCS11) -      if (ssl_ctx->priv_key_pkcs11 != NULL) -	ssl_set_own_cert_alt( ks_ssl->ctx, ssl_ctx->crt_chain, -	    ssl_ctx->priv_key_pkcs11, ssl_pkcs11_decrypt, ssl_pkcs11_sign, -	    ssl_pkcs11_key_len ); -      else +  if (ssl_ctx->priv_key_pkcs11 != NULL) +    ASSERT (polar_ok(ssl_set_own_cert_alt(ks_ssl->ctx, ssl_ctx->crt_chain, +	ssl_ctx->priv_key_pkcs11, ssl_pkcs11_decrypt, ssl_pkcs11_sign, +	ssl_pkcs11_key_len))); +  else  #endif  #if defined(MANAGMENT_EXTERNAL_KEY) -      if (ssl_ctx->external_key != NULL) -        ssl_set_own_cert_alt( ks_ssl->ctx, ssl_ctx->crt_chain, -	   ssl_ctx->external_key, NULL, external_pkcs1_sign, -	   external_key_len ); -      else +  if (ssl_ctx->external_key != NULL) +    ASSERT (polar_ok(ssl_set_own_cert_alt(ks_ssl->ctx, ssl_ctx->crt_chain, +       ssl_ctx->external_key, NULL, external_pkcs1_sign, +       external_key_len))); +  else  #endif -	ssl_set_own_cert( ks_ssl->ctx, ssl_ctx->crt_chain, ssl_ctx->priv_key ); +    ASSERT (polar_ok(ssl_set_own_cert( ks_ssl->ctx, ssl_ctx->crt_chain, +	ssl_ctx->priv_key ))); -      /* Initialise SSL verification */ +  /* Initialise SSL verification */  #if P2MP_SERVER -      if (session->opt->ssl_flags & SSLF_CLIENT_CERT_NOT_REQUIRED) -	{ -	  msg (M_WARN, "WARNING: POTENTIALLY DANGEROUS OPTION " -	   "--client-cert-not-required may accept clients which do not present " -	   "a certificate"); -	} -      else +  if (session->opt->ssl_flags & SSLF_CLIENT_CERT_NOT_REQUIRED) +    { +      msg (M_WARN, "WARNING: POTENTIALLY DANGEROUS OPTION " +       "--client-cert-not-required may accept clients which do not present " +       "a certificate"); +    } +  else  #endif -      { -	ssl_set_authmode (ks_ssl->ctx, SSL_VERIFY_REQUIRED); -	ssl_set_verify (ks_ssl->ctx, verify_callback, session); -      } +  { +    ssl_set_authmode (ks_ssl->ctx, SSL_VERIFY_REQUIRED); +    ssl_set_verify (ks_ssl->ctx, verify_callback, session); +  } + +  /* TODO: PolarSSL does not currently support sending the CA chain to the client */ +  ssl_set_ca_chain (ks_ssl->ctx, ssl_ctx->ca_chain, NULL, NULL ); + +  /* Initialize minimum TLS version */ +  { +    const int tls_version_min = +	(session->opt->ssl_flags >> SSLF_TLS_VERSION_MIN_SHIFT) & +	SSLF_TLS_VERSION_MIN_MASK; -      /* TODO: PolarSSL does not currently support sending the CA chain to the client */ -      ssl_set_ca_chain (ks_ssl->ctx, ssl_ctx->ca_chain, NULL, NULL ); +    /* default to TLS 1.0 */ +    int major = SSL_MAJOR_VERSION_3; +    int minor = SSL_MINOR_VERSION_1; -      /* Initialize minimum TLS version */ +    if (tls_version_min > TLS_VER_UNSPEC) +      tls_version_to_major_minor(tls_version_min, &major, &minor); + +    ssl_set_min_version(ks_ssl->ctx, major, minor); +  } + +  /* Initialize maximum TLS version */ +  { +    const int tls_version_max = +	(session->opt->ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT) & +	SSLF_TLS_VERSION_MAX_MASK; + +    if (tls_version_max > TLS_VER_UNSPEC)        { -	const int tls_version_min = (session->opt->ssl_flags >> SSLF_TLS_VERSION_SHIFT) & SSLF_TLS_VERSION_MASK; -	int polar_major; -	int polar_minor; -	switch (tls_version_min) -	  { -	  case TLS_VER_1_0: -	  default: -	    polar_major = SSL_MAJOR_VERSION_3; -	    polar_minor = SSL_MINOR_VERSION_1; -	    break; -#if defined(SSL_MAJOR_VERSION_3) && defined(SSL_MINOR_VERSION_2) -	  case TLS_VER_1_1: -	    polar_major = SSL_MAJOR_VERSION_3; -	    polar_minor = SSL_MINOR_VERSION_2; -	    break; -#endif -#if defined(SSL_MAJOR_VERSION_3) && defined(SSL_MINOR_VERSION_3) -	  case TLS_VER_1_2: -	    polar_major = SSL_MAJOR_VERSION_3; -	    polar_minor = SSL_MINOR_VERSION_3; -	    break; -#endif -	  } -	ssl_set_min_version(ks_ssl->ctx, polar_major, polar_minor); +	int major, minor; +	tls_version_to_major_minor(tls_version_max, &major, &minor); +	ssl_set_max_version(ks_ssl->ctx, major, minor);        } +  } -      /* Initialise BIOs */ -      ALLOC_OBJ_CLEAR (ks_ssl->ct_in, endless_buffer); -      ALLOC_OBJ_CLEAR (ks_ssl->ct_out, endless_buffer); -      ssl_set_bio (ks_ssl->ctx, endless_buf_read, ks_ssl->ct_in, -	  endless_buf_write, ks_ssl->ct_out); -    } +  /* Initialise BIOs */ +  ALLOC_OBJ_CLEAR (ks_ssl->ct_in, endless_buffer); +  ALLOC_OBJ_CLEAR (ks_ssl->ct_out, endless_buffer); +  ssl_set_bio (ks_ssl->ctx, endless_buf_read, ks_ssl->ct_in, +      endless_buf_write, ks_ssl->ct_out);  }  void @@ -821,7 +847,8 @@ key_state_write_plaintext (struct key_state_ssl *ks, struct buffer *buf)        perf_pop ();        if (POLARSSL_ERR_NET_WANT_WRITE == retval || POLARSSL_ERR_NET_WANT_READ == retval)  	return 0; -      msg (D_TLS_ERRORS, "TLS ERROR: write tls_write_plaintext error"); +      polar_log_err(D_TLS_ERRORS, retval, +	  "TLS ERROR: write tls_write_plaintext error");        return -1;      } @@ -868,7 +895,8 @@ key_state_write_plaintext_const (struct key_state_ssl *ks, const uint8_t *data,        perf_pop ();        if (POLARSSL_ERR_NET_WANT_WRITE == retval || POLARSSL_ERR_NET_WANT_READ == retval)  	return 0; -      msg (D_TLS_ERRORS, "TLS ERROR: write tls_write_plaintext_const error"); +      polar_log_err (D_TLS_ERRORS, retval, +	  "TLS ERROR: write tls_write_plaintext_const error");        return -1;      } @@ -894,7 +922,6 @@ key_state_read_ciphertext (struct key_state_ssl *ks, struct buffer *buf,  {    int retval = 0;    int len = 0; -  char error_message[1024];    perf_push (PERF_BIO_READ_CIPHERTEXT); @@ -920,8 +947,8 @@ key_state_read_ciphertext (struct key_state_ssl *ks, struct buffer *buf,        perf_pop ();        if (POLARSSL_ERR_NET_WANT_WRITE == retval || POLARSSL_ERR_NET_WANT_READ == retval)  	return 0; -      error_strerror(retval, error_message, sizeof(error_message)); -      msg (D_TLS_ERRORS, "TLS_ERROR: read tls_read_ciphertext error: %d %s", retval, error_message); +      polar_log_err (D_TLS_ERRORS, retval, +	  "TLS_ERROR: read tls_read_ciphertext error");        buf->len = 0;        return -1;      } @@ -964,7 +991,8 @@ key_state_write_ciphertext (struct key_state_ssl *ks, struct buffer *buf)        if (POLARSSL_ERR_NET_WANT_WRITE == retval || POLARSSL_ERR_NET_WANT_READ == retval)  	return 0; -      msg (D_TLS_ERRORS, "TLS ERROR: write tls_write_ciphertext error"); +      polar_log_err (D_TLS_ERRORS, retval, +	  "TLS ERROR: write tls_write_ciphertext error");        return -1;      } @@ -993,7 +1021,6 @@ key_state_read_plaintext (struct key_state_ssl *ks, struct buffer *buf,  {    int retval = 0;    int len = 0; -  char error_message[1024];    perf_push (PERF_BIO_READ_PLAINTEXT); @@ -1018,8 +1045,8 @@ key_state_read_plaintext (struct key_state_ssl *ks, struct buffer *buf,      {        if (POLARSSL_ERR_NET_WANT_WRITE == retval || POLARSSL_ERR_NET_WANT_READ == retval)  	return 0; -      error_strerror(retval, error_message, sizeof(error_message)); -      msg (D_TLS_ERRORS, "TLS_ERROR: read tls_read_plaintext error: %d %s", retval, error_message); +      polar_log_err (D_TLS_ERRORS, retval, +	  "TLS_ERROR: read tls_read_plaintext error");        buf->len = 0;        perf_pop ();        return -1; diff --git a/main/openvpn/src/openvpn/ssl_verify_openssl.c b/main/openvpn/src/openvpn/ssl_verify_openssl.c index 56e1c11a..33cd757d 100644 --- a/main/openvpn/src/openvpn/ssl_verify_openssl.c +++ b/main/openvpn/src/openvpn/ssl_verify_openssl.c @@ -101,9 +101,7 @@ static  bool extract_x509_extension(X509 *cert, char *fieldname, char *out, int size)  {    bool retval = false; -  X509_EXTENSION *pExt;    char *buf = 0; -  int length = 0;    GENERAL_NAMES *extensions;    int nid = OBJ_txt2nid(fieldname); diff --git a/main/openvpn/src/openvpn/ssl_verify_polarssl.c b/main/openvpn/src/openvpn/ssl_verify_polarssl.c index 2b7c214f..ed0297b3 100644 --- a/main/openvpn/src/openvpn/ssl_verify_polarssl.c +++ b/main/openvpn/src/openvpn/ssl_verify_polarssl.c @@ -131,17 +131,12 @@ backend_x509_get_serial (openvpn_x509_cert_t *cert, struct gc_arena *gc)    char *buf = NULL;    size_t buflen = 0;    mpi serial_mpi = { 0 }; -  int retval = 0;    /* Transform asn1 integer serial into PolarSSL MPI */    mpi_init(&serial_mpi); -  retval = mpi_read_binary(&serial_mpi, cert->serial.p, cert->serial.len); -  if (retval < 0) +  if (!polar_ok(mpi_read_binary(&serial_mpi, cert->serial.p, cert->serial.len)))      { -      char errbuf[128]; -      polarssl_strerror(retval, errbuf, sizeof(errbuf)); - -      msg(M_WARN, "Failed to retrieve serial from certificate: %s.", errbuf); +      msg(M_WARN, "Failed to retrieve serial from certificate.");        return NULL;      } @@ -150,13 +145,9 @@ backend_x509_get_serial (openvpn_x509_cert_t *cert, struct gc_arena *gc)    buf = gc_malloc(buflen, true, gc);    /* Write MPI serial as decimal string into buffer */ -  retval = mpi_write_string(&serial_mpi, 10, buf, &buflen); -  if (retval < 0) +  if (!polar_ok(mpi_write_string(&serial_mpi, 10, buf, &buflen)))      { -      char errbuf[128]; -      polarssl_strerror(retval, errbuf, sizeof(errbuf)); - -      msg(M_WARN, "Failed to write serial to string: %s.", errbuf); +      msg(M_WARN, "Failed to write serial to string.");        return NULL;      } @@ -371,12 +362,9 @@ x509_verify_crl(const char *crl_file, x509_crt *cert, const char *subject)    result_t retval = FAILURE;    x509_crl crl = {0}; -  int polar_retval = x509_crl_parse_file(&crl, crl_file); -  if (polar_retval != 0) +  if (!polar_ok(x509_crl_parse_file(&crl, crl_file)))      { -      char errstr[128]; -      polarssl_strerror(polar_retval, errstr, sizeof(errstr)); -      msg (M_WARN, "CRL: cannot read CRL from file %s (%s)", crl_file, errstr); +      msg (M_WARN, "CRL: cannot read CRL from file %s", crl_file);        goto end;      } @@ -389,7 +377,7 @@ x509_verify_crl(const char *crl_file, x509_crt *cert, const char *subject)        goto end;      } -  if (0 != x509_crt_revoked(cert, &crl)) +  if (!polar_ok(x509_crt_revoked(cert, &crl)))      {        msg (D_HANDSHAKE, "CRL CHECK FAILED: %s is REVOKED", subject);        goto end; diff --git a/main/openvpn/src/openvpn/tun.h b/main/openvpn/src/openvpn/tun.h index 631b53c6..79e2d188 100644 --- a/main/openvpn/src/openvpn/tun.h +++ b/main/openvpn/src/openvpn/tun.h @@ -391,6 +391,19 @@ tuntap_stop (int status)    return false;  } +static inline bool +tuntap_abort(int status) +{ +  /* +   * Typically generated when driver is halted. +   */ +  if (status < 0) +    { +      return openvpn_errno() == ERROR_OPERATION_ABORTED; +    } +  return false; +} +  static inline int  tun_write_win32 (struct tuntap *tt, struct buffer *buf)  { @@ -432,6 +445,12 @@ tuntap_stop (int status)    return false;  } +static inline bool +tuntap_abort(int status) +{ +  return false; +} +  static inline void  tun_standby_init (struct tuntap *tt)  { | 
