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