From 192f5b50e32ed14945317325a5465f40abfcc587 Mon Sep 17 00:00:00 2001 From: Arne Schwabe Date: Tue, 28 Oct 2014 23:07:58 +0100 Subject: Update Openssl to aosp/master (includes useless (for OpenVPN)) SSLv3 Fallback fix --HG-- extra : rebase_source : 4ec3b7a7844aa1ca198c4538ecdf28f027ceb1b1 --- main/openssl/Crypto-config-target.mk | 4 + main/openssl/Ssl.mk | 2 + main/openssl/apps/s_client.c | 10 + main/openssl/crypto/err/openssl.ec | 1 + main/openssl/flavor.mk | 4 + main/openssl/include/openssl/dtls1.h | 3 +- main/openssl/include/openssl/ssl.h | 10 + main/openssl/include/openssl/ssl3.h | 7 +- main/openssl/include/openssl/tls1.h | 15 +- main/openssl/patches/README | 5 + main/openssl/ssl/d1_lib.c | 10 + main/openssl/ssl/dtls1.h | 3 +- main/openssl/ssl/s23_clnt.c | 3 + main/openssl/ssl/s23_srvr.c | 3 + main/openssl/ssl/s2_lib.c | 2 + main/openssl/ssl/s3_enc.c | 2 +- main/openssl/ssl/s3_lib.c | 29 +- main/openssl/ssl/ssl.h | 10 + main/openssl/ssl/ssl3.h | 7 +- main/openssl/ssl/ssl_err.c | 2 + main/openssl/ssl/ssl_lib.c | 58 ++- main/openssl/ssl/t1_enc.c | 1 + main/openssl/ssl/tls1.h | 15 +- main/openvpn/config-version.h | 2 +- main/openvpn/config.h | 2 + main/openvpn/configure.ac | 39 +- main/openvpn/doc/openvpn.8 | 20 +- .../sample/sample-config-files/loopback-client | 2 +- .../sample/sample-config-files/loopback-server | 2 +- main/openvpn/src/openvpn/crypto.c | 441 +++++++++++++++------ main/openvpn/src/openvpn/crypto.h | 37 +- main/openvpn/src/openvpn/crypto_backend.h | 84 ++++ main/openvpn/src/openvpn/crypto_openssl.c | 162 ++++++-- main/openvpn/src/openvpn/crypto_openssl.h | 35 ++ main/openvpn/src/openvpn/crypto_polarssl.c | 199 +++++++--- main/openvpn/src/openvpn/crypto_polarssl.h | 43 ++ main/openvpn/src/openvpn/error.c | 29 -- main/openvpn/src/openvpn/error.h | 11 +- main/openvpn/src/openvpn/forward.c | 29 +- main/openvpn/src/openvpn/httpdigest.c | 46 ++- main/openvpn/src/openvpn/httpdigest.h | 2 +- main/openvpn/src/openvpn/init.c | 126 +++--- main/openvpn/src/openvpn/mroute.h | 12 +- main/openvpn/src/openvpn/mudp.c | 27 +- main/openvpn/src/openvpn/multi.c | 2 +- main/openvpn/src/openvpn/ntlm.c | 28 +- main/openvpn/src/openvpn/openvpn.h | 5 +- main/openvpn/src/openvpn/options.c | 47 ++- main/openvpn/src/openvpn/options.h | 6 +- main/openvpn/src/openvpn/packet_id.c | 6 + main/openvpn/src/openvpn/packet_id.h | 3 + main/openvpn/src/openvpn/push.c | 4 +- main/openvpn/src/openvpn/ssl.c | 167 ++++---- main/openvpn/src/openvpn/ssl.h | 18 +- main/openvpn/src/openvpn/ssl_backend.h | 11 +- main/openvpn/src/openvpn/ssl_common.h | 16 +- main/openvpn/src/openvpn/ssl_openssl.c | 123 +++--- main/openvpn/src/openvpn/ssl_polarssl.c | 253 ++++++------ main/openvpn/src/openvpn/ssl_verify_openssl.c | 2 - main/openvpn/src/openvpn/ssl_verify_polarssl.c | 26 +- main/openvpn/src/openvpn/tun.h | 19 + 61 files changed, 1565 insertions(+), 727 deletions(-) create mode 100644 main/openssl/flavor.mk 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; ipsk_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; is3 && (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 @@ -78,6 +78,13 @@ AC_ARG_ENABLE( [enable_crypto_ofb_cfb="yes"] ) +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 @@ -220,6 +232,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. * @@ -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)); + /** * @@ -288,6 +320,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. * @@ -328,6 +369,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 #include #include +#include +#include /* * 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? */ @@ -265,18 +288,21 @@ show_available_ciphers () if (cipher_kt_mode_cbc(cipher) #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)", @@ -482,6 +511,15 @@ cipher_kt_block_size (const EVP_CIPHER *cipher_kt) return EVP_CIPHER_block_size (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) { @@ -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) { @@ -578,6 +636,17 @@ cipher_ctx_reset (EVP_CIPHER_CTX *ctx, uint8_t *iv_buf) return EVP_CipherInit (ctx, NULL, NULL, iv_buf, -1); } +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 +#include #include #include #include @@ -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); @@ -409,6 +407,16 @@ cipher_kt_block_size (const cipher_info_t *cipher_kt) return cipher_kt->block_size; } +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) { @@ -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 -#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 ['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 : 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) { -- cgit v1.2.3