Re: [Openvpn-devel] OpenVPN Versioning
On 18/06/2013 01:41, Joachim Schipper wrote: From: James Yonan: On 14/06/2013 02:47, Joachim Schipper wrote: >From James Yonan : TLS Protocol Since day 1, OpenVPN has used TLS 1.0 as a control channel and key exchange mechanism. But now we have TLS 1.1 and 1.2, each of which addresses significant shortcomings in its predecessor. Fortunately, SSL/TLS already includes dynamic version negotiation. So I've put together a patch that leverages on this, by allowing OpenVPN client and server to negotiate the TLS version and use the highest version supported by both peers. The patch also adds a new directive "tls- version-min" that allows either client or server to specify a minimum required TLS version from the peer. https://github.com/jamesyonan/openvpn/commit/6ee8faade224cc346d67a7f1 7 1 6df4012782999a [snip: SSL negotiation. Thanks for the explanation; I agree that speaking the highest supported protocol is good.] I'm not sure what purpose the "or-highest" serves. Clients already connect with the newest protocol supported by both client and server; if you want to run a TLSv1.2-only network, just set min-version to 1.2 on the server. (...) Suppose a server admin wants to upgrade to TLS 1.2 over some transition period, to allow time to upgrade existing clients in the field. The overall goal here is to provide tools that allow a controlled rollout of TLS 1.2 that doesn't break any clients during the rollout period, and to upgrade to 1.2 in a way that doesn't create the potential for MiTM version rollback attacks. But no modern SSL protocol allows version rollback attacks: modern implementations will always speak the highest supported/configured protocol version between each other. (Only) SSLv2 allows rollback attacks, which is why the only sane way to deal with SSLv2 in 2013 is to unconditionally disable support. Right, and the patch is able to unconditionally disable support for SSL 2 and 3 since these were never supported by even the earliest versions of OpenVPN. The switch(tls_version_min) needs a default case, just compile the first case/default: unconditionally. There is a default case already -- it's right under "case TLS_VER_1_0:". Yes, but that's #ifdef'ed. I'd be happier if the default case remained present even if PolarSSL foolishly decides to drop TLSv1 support. Agreed -- there shouldn't be any implicit assumption that SSL lib might not implement TLS 1.0. https://github.com/jamesyonan/openvpn/commit/d23005413b0e0f28a3c48a6342f494763d5c9b40 [snip: ciphersuites] Negotiating ciphers might be fatal in some configurations that were a bad idea to begin with. E.g. if you use OpenVPN with a static key and --auth none (which is a bad idea!), adding this negotation could allow an attacker to set the cipher to none or, more dangerously, to a very weak cipher like DES (provided it is mutually supported). An attacker could then bruteforce the key and use his knowledge of 56 bits of the key to attack stronger protocols like AES or 3DES. (Or do we only negotiate in SSL mode? I must admit to being fuzzy on the non-SSL mode.) Static key mode has no negotiation. Agreed that any negotiation model must have constraints placed on the security of the negotiated cipher and HMAC digest. You would probably want to disable "cipher none" or "auth none" on the presumption that users who want a cleartext tunnel would explicitly configure the client and server for this. Sure. Just disabling negotiations unless you have an SSL'd control channel works fine against this. One thing to keep in mind is that OpenVPN protocol negotiation occurs over the already-negotiated TLS session, so it is immune to being tampered with by a MiTM. This is in contrast to SSL/TLS where a MiTM can affect the negotiation. As above, MiTM attackers cannot effect the negotiation step in SSL/TLS protocols after SSLv2, except trivially (by causing the negotiation to fail, possibly a couple of protocol steps later, e.g. by dropping all packets.) Aha, that's good to know. Apparently browsers are still vulnerable to version rollback attacks due to compatibility fallback mechanisms, but that's great that SSL/TLS protocols are immune above SSL 3. There's a good writeup on the subject here: http://www.carbonwind.net/blog/post/Random-SSLTLS-101%E2%80%93SSLTLS-version-rollbacks-and-browsers.aspx James
Re: [Openvpn-devel] OpenVPN Versioning
On 17/06/2013 01:58, Steffan Karger wrote: On 06/14/2013 09:53 PM, James Yonan wrote: To get the adaptive versioning behavior in OpenSSL, you have to use SSLv23_server_method() or SSLv23_client_method() and then explicitly disable the versions you don't want to consider, i.e. SSL_OP_NO_SSLv2, SSL_OP_NO_SSLv3, SSL_OP_NO_TLSv1, SSL_OP_NO_TLSv1_1, etc. Wow, so SSLv23_{client,server}_method() is the 'wildcard' you need to dynamically negotiate the version. Yet it sounds like something completely broken that should be avoided at all cost. OpenSSL keeps amazing me. It really shows OpenSSL's age, doesn't it? But aside from the cruftiness, I wouldn't say that it's broken. It's arguably a more flexible mechanism than PolarSSL because it allows you to cherry-pick the SSL/TLS versions you want to support, rather than just give a min/max range. Does the change to key_state_ssl_init() do anything? I had to add ssl_flags (containing tls-version-min parameter) to key_state_ssl_init because that seems like the most appropriate place to configure tls-version-min for PolarSSL. For OpenSSL, tls_ctx_set_options is the right place to configure tls-version-min. The ssl_flags are already available through the tls session that is passed as the fourth parameter. To make this a bit more clear, commit b97e2c3 changed the type of session to struct tls session* (see https://github.com/OpenVPN/openvpn/commit/b97e2c3c90afdbb1a24bc1357ec6b94d626defcd). Right, I've rebased the patch against master and now use session->opt->ssl_flags This simplifies the patch because now it's no longer necessary to pass ssl_flags to key_state_ssl_init https://github.com/jamesyonan/openvpn/commit/03a5599202bdc3ba07983dc4efdae387fb8fb436 James
Re: [Openvpn-devel] OpenVPN Versioning
From: James Yonan: > On 14/06/2013 02:47, Joachim Schipper wrote: > >>From James Yonan : > >> TLS Protocol > >> > >> > >> Since day 1, OpenVPN has used TLS 1.0 as a control channel and key > >> exchange mechanism. But now we have TLS 1.1 and 1.2, each of which > >> addresses significant shortcomings in its predecessor. Fortunately, > >> SSL/TLS already includes dynamic version negotiation. So I've put > >> together a patch that leverages on this, by allowing OpenVPN client > >> and server to negotiate the TLS version and use the highest version > >> supported by both peers. The patch also adds a new directive "tls- > >> version-min" that allows either client or server to specify a > minimum > >> required TLS version from the peer. > >> > >> > https://github.com/jamesyonan/openvpn/commit/6ee8faade224cc346d67a7f1 > >> 7 > >> 1 > >> 6df4012782999a [snip: SSL negotiation. Thanks for the explanation; I agree that speaking the highest supported protocol is good.] > > I'm not sure what purpose the "or-highest" serves. Clients already > connect with the newest protocol supported by both client and server; > if you want to run a TLSv1.2-only network, just set min-version to 1.2 > on the server. (...) > > Suppose a server admin wants to upgrade to TLS 1.2 over some transition > period, to allow time to upgrade existing clients in the field. > The overall goal here is to provide tools that allow a controlled > rollout of TLS 1.2 that doesn't break any clients during the rollout > period, and to upgrade to 1.2 in a way that doesn't create the > potential for MiTM version rollback attacks. But no modern SSL protocol allows version rollback attacks: modern implementations will always speak the highest supported/configured protocol version between each other. (Only) SSLv2 allows rollback attacks, which is why the only sane way to deal with SSLv2 in 2013 is to unconditionally disable support. > > The switch(tls_version_min) needs a default case, just compile the > first case/default: unconditionally. > > There is a default case already -- it's right under "case > TLS_VER_1_0:". Yes, but that's #ifdef'ed. I'd be happier if the default case remained present even if PolarSSL foolishly decides to drop TLSv1 support. [snip: ciphersuites] > > Negotiating ciphers might be fatal in some configurations that were a > > bad idea to begin with. E.g. if you use OpenVPN with a static key and > > --auth none (which is a bad idea!), adding this negotation could > allow > > an attacker to set the cipher to none or, more dangerously, to a very > > weak cipher like DES (provided it is mutually supported). An attacker > > could then bruteforce the key and use his knowledge of 56 bits of the > > key to attack stronger protocols like AES or 3DES. (Or do we only > > negotiate in SSL mode? I must admit to being fuzzy on the non-SSL > > mode.) > > Static key mode has no negotiation. > > Agreed that any negotiation model must have constraints placed on the > security of the negotiated cipher and HMAC digest. You would probably > want to disable "cipher none" or "auth none" on the presumption that > users who want a cleartext tunnel would explicitly configure the client > and server for this. Sure. Just disabling negotiations unless you have an SSL'd control channel works fine against this. > One thing to keep in mind is that OpenVPN protocol negotiation occurs > over the already-negotiated TLS session, so it is immune to being > tampered with by a MiTM. This is in contrast to SSL/TLS where a MiTM > can affect the negotiation. As above, MiTM attackers cannot effect the negotiation step in SSL/TLS protocols after SSLv2, except trivially (by causing the negotiation to fail, possibly a couple of protocol steps later, e.g. by dropping all packets.) Joachim
Re: [Openvpn-devel] OpenVPN Versioning
On 06/14/2013 09:53 PM, James Yonan wrote: > To get the adaptive versioning behavior in OpenSSL, you have to use > SSLv23_server_method() or SSLv23_client_method() and then explicitly > disable the versions you don't want to consider, i.e. SSL_OP_NO_SSLv2, > SSL_OP_NO_SSLv3, SSL_OP_NO_TLSv1, SSL_OP_NO_TLSv1_1, etc. > Wow, so SSLv23_{client,server}_method() is the 'wildcard' you need to dynamically negotiate the version. Yet it sounds like something completely broken that should be avoided at all cost. OpenSSL keeps amazing me. >> Does the change to key_state_ssl_init() do anything? > > I had to add ssl_flags (containing tls-version-min parameter) to > key_state_ssl_init because that seems like the most appropriate place to > configure tls-version-min for PolarSSL. > > For OpenSSL, tls_ctx_set_options is the right place to configure > tls-version-min. > The ssl_flags are already available through the tls session that is passed as the fourth parameter. To make this a bit more clear, commit b97e2c3 changed the type of session to struct tls session* (see https://github.com/OpenVPN/openvpn/commit/b97e2c3c90afdbb1a24bc1357ec6b94d626defcd). -Steffan
Re: [Openvpn-devel] OpenVPN Versioning
>From James Yonan: > TLS Protocol > > > Since day 1, OpenVPN has used TLS 1.0 as a control channel and key > exchange mechanism. But now we have TLS 1.1 and 1.2, each of which > addresses significant shortcomings in its predecessor. Fortunately, > SSL/TLS already includes dynamic version negotiation. So I've put > together a patch that leverages on this, by allowing OpenVPN client > and server to negotiate the TLS version and use the highest version > supported by both peers. The patch also adds a new directive "tls- > version-min" that allows either client or server to specify a minimum > required TLS version from the peer. > > https://github.com/jamesyonan/openvpn/commit/6ee8faade224cc346d67a7f17 > 1 > 6df4012782999a Some comments on the design and implementation here. (I've just looked at the code, not tested it.) I'm confused by your comments about TLS/SSL versions used. Our own builds using PolarSSL do negotiate TLSv1.1 and TLSv1.2 between themselves and when interoperating with OpenSSL, logging "Control Channel: TLSv1.1, cipher XXX" or even "Control Channel: TLSv1.2, cipher XXX". In general, the highest version supported by both client and server is used, as is normally the case with SSL. However, stock Ubuntu OpenVPN seems to negotiate TLSv1. Huh? I'm not sure what purpose the "or-highest" serves. Clients already connect with the newest protocol supported by both client and server; if you want to run a TLSv1.2-only network, just set min-version to 1.2 on the server. If you're an especially competent and paranoid user, you might want to set min-version on the client, but in that case you hardly need an "or-highest", since you know which cipher suites your client supports. Some of the whitespace looks odd/wrong. Does the change to key_state_ssl_init() do anything? The variables polar_{major,minor} in ssl_polarssl.c should be renamed, probably to something like ssl_{major,minor}_version - it's not a PolarSSL version. The switch(tls_version_min) needs a default case, just compile the first case/default: unconditionally. > OpenVPN Protocol > > [Handshaking] could be used to negotiate other protocol capabilities > such as cipher and HMAC digest: > >IV_CIPHER=BF-CBC,AES-128-CBC >IV_AUTH=SHA1,SHA256,SHA512 > > (...) There > is also the issue of the size of the Client Capabilities List. The > IV_CIPHER and IV_AUTH lists might grow to be quite long (...) To > reduce the size, we might > consider: > > (a) use a single character designation for ciphers and HMAC digests, > such as: > > Cipher Codes: > A : BF-CBC > B : AES-128-CBC > . . . > > Then communicate IV_CIPHER using the cipher codes: > >IV_CIPHER=AB > > This would require that the OpenVPN Project standardize on set of > codes for ciphers and HMAC digests. This is a good idea in general, but why not use SSL cipher suites (which already have standardized binary representations)? That has the added advantage of itting AEAD suites like AES-GCM, which are getting more important. (We may need to add some, but note that the { 0xff, X } "namespace" is available for "local and experimental" cipher suites.) Negotiating ciphers might be fatal in some configurations that were a bad idea to begin with. E.g. if you use OpenVPN with a static key and --auth none (which is a bad idea!), adding this negotation could allow an attacker to set the cipher to none or, more dangerously, to a very weak cipher like DES (provided it is mutually supported). An attacker could then bruteforce the key and use his knowledge of 56 bits of the key to attack stronger protocols like AES or 3DES. (Or do we only negotiate in SSL mode? I must admit to being fuzzy on the non-SSL mode.) Joachim
Re: [Openvpn-devel] OpenVPN Versioning
On 12/06/2013 15:08, Arne Schwabe wrote: Am 12.06.13 21:38, schrieb James Yonan: About finding out which cipher client and server use. I am not really familiar with this code so forgive my stupid question. TLS somehow also does this "select the best cipher to use" dance. Why can't we use the TLS mechanism but have to use our own IV_CIPHER? TLS includes a handshake mechanism for TLS version and ciphersuite selection. In TLS, a single ciphersuite specifies a set of cipher, mode, keysize, MAC digest, etc., while in OpenVPN the cipher and HMAC digest are separately selected by cipher and auth directives. Historically, OpenVPN has never implemented any interaction between the TLS ciphersuite selection and the cipher/auth selection for the OpenVPN protocol -- they are completely decoupled from one another, so using TLS negotiation isn't going to have any effect on OpenVPN cipher/auth. But you raise an interesting point that we might want to explore, i.e. looking at the TLS ciphersuite that ends up getting negotiated, and extract the cipher/auth directive from that since you know it will be consistent on both client and server. Suppose I want to put this directive in the config files I distribute to clients, but have it be ignored by older clients that don't recognize it. I could do this as follows on the client: setenv opt tls-version-min 1.2 I suppose this a good idea too also support older client. I would to *additionally* add a way to support this in a nicer way for future release. Like also adding an option ignore-unknown-options tls-version new-cool-option so newer can some day can still be written with having to use "setenv opt" Sure, that makes sense. Loosly related this would also allow to give use a "default" set of options that can be ignored (ip-win32 on *nix) Deciding whether or not to ignore options is tricky. With the new 3.0 core, it was necessary to ignore some options because they are simply not implemented, and raising an error for every unimplemented option would make it very difficult upgrade to 3.0 in a way that maintains reasonable config file compatibility with 2.x. So the approach I took for 3.0 was to only raise an error on unimplemented options where ignoring the option might compromise security. Initially tls-remote fell under this category, but it has since been implemented in the 3.0 core. James