0
0
mirror of https://github.com/OpenVPN/openvpn3.git synced 2024-09-20 04:02:15 +02:00
openvpn3/openvpn/ssl/datalimit.hpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

210 lines
5.0 KiB
C++
Raw Permalink Normal View History

// OpenVPN -- An application to securely tunnel IP networks
// over a single port, with support for SSL/TLS-based
// session authentication and key exchange,
// packet encryption, packet authentication, and
// packet compression.
//
// Copyright (C) 2012-2022 OpenVPN Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License Version 3
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>.
//
ovpn3 core : Added automatic data limits for Blowfish, Triple DES, and other 64-bit block-size ciphers vulnerable to "Sweet32" birthday attack (CVE-2016-6329). Limit such cipher keys to no more than 64 MB of data encrypted/decrypted. While our overall goal is to limit data-limited keys to 64 MB, we trigger a renegotiation at 48 MB to compensate for possible delays in renegotiation and rollover to the new key. This client-side implementation extends data limit protection to the entire session, even when the server doesn't implement data limits. This capability is advertised to servers via the a peer info setting: IV_BS64DL=1 meaning "Block-Size 64-bit Data Limit". The "1" indicates the implementation version. The implementation currently has some limitations: * Keys are renegotiated at a maximum rate of once per 5 seconds to reduce the likelihood of loss of synchronization between peers. * The maximum renegotiation rate may be further extended if the peer delays rollover from the old to new key after renegotiation. Added N_KEY_LIMIT_RENEG stats counter to count the number of data-limit-triggered renegotiations. Added new stats counter KEY_STATE_ERROR which roughly corresponds to the OpenVPN 2.x error "TLS Error: local/remote TLS keys are out of sync". Prevously, the TLS ack/retransmit timeout was hardcoded to 2 seconds. Now we lower the default to 1 second and make it variable using the (pushable) "tls-timeout" directive. Additionally, the tls-timeout directive can be specified in milliseconds instead of seconds by using the "tls-timeout-ms" form of the directive. Made the "become primary" time duration configurable via the (pushable) "become-primary" directive which accepts a number-of-seconds parameter. become-primary indicates the time delay between renegotiation and rollover to the new key for encryption/transmission. become-primary defaults to the handshake-window which in turn defaults to 60 seconds. Incremented core version to 3.0.20.
2016-09-01 23:19:00 +02:00
#ifndef OPENVPN_SSL_DATALIMIT_H
#define OPENVPN_SSL_DATALIMIT_H
#include <openvpn/common/exception.hpp>
namespace openvpn {
// Helper for handling keys which can have an upper limit
// on maximum amount of data encrypted/decrypted, such
// as Blowfish.
class DataLimit
{
public:
typedef unsigned int size_type;
enum Mode
{
Encrypt = 0,
Decrypt = 1,
};
enum State
{
None = 0,
Green = 1,
Red = 2,
};
struct Parameters
{
size_type encrypt_red_limit = 0;
size_type decrypt_red_limit = 0;
};
DataLimit(const Parameters &p)
: encrypt(p.encrypt_red_limit),
decrypt(p.decrypt_red_limit)
{
}
State update_state(const Mode mode, const State newstate)
{
return elgible(mode, component(mode).update_state(newstate));
}
State add(const Mode mode, const size_type n)
{
return elgible(mode, component(mode).add(n));
}
bool is_decrypt_green()
{
return decrypt.get_state() >= Green;
}
static const char *mode_str(const Mode m)
{
switch (m)
{
case Encrypt:
return "Encrypt";
case Decrypt:
return "Decrypt";
default:
return "Mode_???";
}
}
static const char *state_str(const State s)
{
switch (s)
{
case None:
return "None";
case Green:
return "Green";
case Red:
return "Red";
default:
return "State_???";
}
}
private:
// Don't return Encrypt-Red until Decrypt-Green
// has been received. This confirms that the peer
// is now transmitting on the key ID, making it
// eligible for renegotiation.
State elgible(const Mode mode, const State state)
{
// Bit positions for Encrypt/Decrypt and Green/Red
enum
{
EG = 1 << 0,
ER = 1 << 1,
DG = 1 << 2,
DR = 1 << 3,
};
if (state > None)
{
const unsigned int mask = 1 << ((int(state) - 1) + (int(mode) << 1));
if (!(flags & mask))
{
flags |= mask;
if ((mask & (ER | DG)) && ((flags & (ER | DG)) == (ER | DG)))
return Red;
else if (mask & ER)
return None;
else
return state;
}
}
return None;
}
class Component
{
public:
Component(const size_type red_limit_arg)
: red_limit(red_limit_arg)
{
}
ovpn3 core : Added automatic data limits for Blowfish, Triple DES, and other 64-bit block-size ciphers vulnerable to "Sweet32" birthday attack (CVE-2016-6329). Limit such cipher keys to no more than 64 MB of data encrypted/decrypted. While our overall goal is to limit data-limited keys to 64 MB, we trigger a renegotiation at 48 MB to compensate for possible delays in renegotiation and rollover to the new key. This client-side implementation extends data limit protection to the entire session, even when the server doesn't implement data limits. This capability is advertised to servers via the a peer info setting: IV_BS64DL=1 meaning "Block-Size 64-bit Data Limit". The "1" indicates the implementation version. The implementation currently has some limitations: * Keys are renegotiated at a maximum rate of once per 5 seconds to reduce the likelihood of loss of synchronization between peers. * The maximum renegotiation rate may be further extended if the peer delays rollover from the old to new key after renegotiation. Added N_KEY_LIMIT_RENEG stats counter to count the number of data-limit-triggered renegotiations. Added new stats counter KEY_STATE_ERROR which roughly corresponds to the OpenVPN 2.x error "TLS Error: local/remote TLS keys are out of sync". Prevously, the TLS ack/retransmit timeout was hardcoded to 2 seconds. Now we lower the default to 1 second and make it variable using the (pushable) "tls-timeout" directive. Additionally, the tls-timeout directive can be specified in milliseconds instead of seconds by using the "tls-timeout-ms" form of the directive. Made the "become primary" time duration configurable via the (pushable) "become-primary" directive which accepts a number-of-seconds parameter. become-primary indicates the time delay between renegotiation and rollover to the new key for encryption/transmission. become-primary defaults to the handshake-window which in turn defaults to 60 seconds. Incremented core version to 3.0.20.
2016-09-01 23:19:00 +02:00
State add(const size_type n)
{
bytes += n;
return update_state(transition(state));
}
ovpn3 core : Added automatic data limits for Blowfish, Triple DES, and other 64-bit block-size ciphers vulnerable to "Sweet32" birthday attack (CVE-2016-6329). Limit such cipher keys to no more than 64 MB of data encrypted/decrypted. While our overall goal is to limit data-limited keys to 64 MB, we trigger a renegotiation at 48 MB to compensate for possible delays in renegotiation and rollover to the new key. This client-side implementation extends data limit protection to the entire session, even when the server doesn't implement data limits. This capability is advertised to servers via the a peer info setting: IV_BS64DL=1 meaning "Block-Size 64-bit Data Limit". The "1" indicates the implementation version. The implementation currently has some limitations: * Keys are renegotiated at a maximum rate of once per 5 seconds to reduce the likelihood of loss of synchronization between peers. * The maximum renegotiation rate may be further extended if the peer delays rollover from the old to new key after renegotiation. Added N_KEY_LIMIT_RENEG stats counter to count the number of data-limit-triggered renegotiations. Added new stats counter KEY_STATE_ERROR which roughly corresponds to the OpenVPN 2.x error "TLS Error: local/remote TLS keys are out of sync". Prevously, the TLS ack/retransmit timeout was hardcoded to 2 seconds. Now we lower the default to 1 second and make it variable using the (pushable) "tls-timeout" directive. Additionally, the tls-timeout directive can be specified in milliseconds instead of seconds by using the "tls-timeout-ms" form of the directive. Made the "become primary" time duration configurable via the (pushable) "become-primary" directive which accepts a number-of-seconds parameter. become-primary indicates the time delay between renegotiation and rollover to the new key for encryption/transmission. become-primary defaults to the handshake-window which in turn defaults to 60 seconds. Incremented core version to 3.0.20.
2016-09-01 23:19:00 +02:00
State update_state(const State newstate)
{
State ret = None;
if (newstate > state)
state = ret = newstate;
return ret;
}
ovpn3 core : Added automatic data limits for Blowfish, Triple DES, and other 64-bit block-size ciphers vulnerable to "Sweet32" birthday attack (CVE-2016-6329). Limit such cipher keys to no more than 64 MB of data encrypted/decrypted. While our overall goal is to limit data-limited keys to 64 MB, we trigger a renegotiation at 48 MB to compensate for possible delays in renegotiation and rollover to the new key. This client-side implementation extends data limit protection to the entire session, even when the server doesn't implement data limits. This capability is advertised to servers via the a peer info setting: IV_BS64DL=1 meaning "Block-Size 64-bit Data Limit". The "1" indicates the implementation version. The implementation currently has some limitations: * Keys are renegotiated at a maximum rate of once per 5 seconds to reduce the likelihood of loss of synchronization between peers. * The maximum renegotiation rate may be further extended if the peer delays rollover from the old to new key after renegotiation. Added N_KEY_LIMIT_RENEG stats counter to count the number of data-limit-triggered renegotiations. Added new stats counter KEY_STATE_ERROR which roughly corresponds to the OpenVPN 2.x error "TLS Error: local/remote TLS keys are out of sync". Prevously, the TLS ack/retransmit timeout was hardcoded to 2 seconds. Now we lower the default to 1 second and make it variable using the (pushable) "tls-timeout" directive. Additionally, the tls-timeout directive can be specified in milliseconds instead of seconds by using the "tls-timeout-ms" form of the directive. Made the "become primary" time duration configurable via the (pushable) "become-primary" directive which accepts a number-of-seconds parameter. become-primary indicates the time delay between renegotiation and rollover to the new key for encryption/transmission. become-primary defaults to the handshake-window which in turn defaults to 60 seconds. Incremented core version to 3.0.20.
2016-09-01 23:19:00 +02:00
State get_state() const
{
return state;
}
ovpn3 core : Added automatic data limits for Blowfish, Triple DES, and other 64-bit block-size ciphers vulnerable to "Sweet32" birthday attack (CVE-2016-6329). Limit such cipher keys to no more than 64 MB of data encrypted/decrypted. While our overall goal is to limit data-limited keys to 64 MB, we trigger a renegotiation at 48 MB to compensate for possible delays in renegotiation and rollover to the new key. This client-side implementation extends data limit protection to the entire session, even when the server doesn't implement data limits. This capability is advertised to servers via the a peer info setting: IV_BS64DL=1 meaning "Block-Size 64-bit Data Limit". The "1" indicates the implementation version. The implementation currently has some limitations: * Keys are renegotiated at a maximum rate of once per 5 seconds to reduce the likelihood of loss of synchronization between peers. * The maximum renegotiation rate may be further extended if the peer delays rollover from the old to new key after renegotiation. Added N_KEY_LIMIT_RENEG stats counter to count the number of data-limit-triggered renegotiations. Added new stats counter KEY_STATE_ERROR which roughly corresponds to the OpenVPN 2.x error "TLS Error: local/remote TLS keys are out of sync". Prevously, the TLS ack/retransmit timeout was hardcoded to 2 seconds. Now we lower the default to 1 second and make it variable using the (pushable) "tls-timeout" directive. Additionally, the tls-timeout directive can be specified in milliseconds instead of seconds by using the "tls-timeout-ms" form of the directive. Made the "become primary" time duration configurable via the (pushable) "become-primary" directive which accepts a number-of-seconds parameter. become-primary indicates the time delay between renegotiation and rollover to the new key for encryption/transmission. become-primary defaults to the handshake-window which in turn defaults to 60 seconds. Incremented core version to 3.0.20.
2016-09-01 23:19:00 +02:00
private:
State transition(State s) const
{
switch (s)
{
case None:
if (bytes)
return Green;
else
return None;
case Green:
if (red_limit && bytes >= red_limit)
return Red;
else
return None;
case Red:
default:
return None;
}
}
ovpn3 core : Added automatic data limits for Blowfish, Triple DES, and other 64-bit block-size ciphers vulnerable to "Sweet32" birthday attack (CVE-2016-6329). Limit such cipher keys to no more than 64 MB of data encrypted/decrypted. While our overall goal is to limit data-limited keys to 64 MB, we trigger a renegotiation at 48 MB to compensate for possible delays in renegotiation and rollover to the new key. This client-side implementation extends data limit protection to the entire session, even when the server doesn't implement data limits. This capability is advertised to servers via the a peer info setting: IV_BS64DL=1 meaning "Block-Size 64-bit Data Limit". The "1" indicates the implementation version. The implementation currently has some limitations: * Keys are renegotiated at a maximum rate of once per 5 seconds to reduce the likelihood of loss of synchronization between peers. * The maximum renegotiation rate may be further extended if the peer delays rollover from the old to new key after renegotiation. Added N_KEY_LIMIT_RENEG stats counter to count the number of data-limit-triggered renegotiations. Added new stats counter KEY_STATE_ERROR which roughly corresponds to the OpenVPN 2.x error "TLS Error: local/remote TLS keys are out of sync". Prevously, the TLS ack/retransmit timeout was hardcoded to 2 seconds. Now we lower the default to 1 second and make it variable using the (pushable) "tls-timeout" directive. Additionally, the tls-timeout directive can be specified in milliseconds instead of seconds by using the "tls-timeout-ms" form of the directive. Made the "become primary" time duration configurable via the (pushable) "become-primary" directive which accepts a number-of-seconds parameter. become-primary indicates the time delay between renegotiation and rollover to the new key for encryption/transmission. become-primary defaults to the handshake-window which in turn defaults to 60 seconds. Incremented core version to 3.0.20.
2016-09-01 23:19:00 +02:00
const size_type red_limit;
size_type bytes = 0;
State state = None;
};
Component &component(const Mode m)
{
switch (m)
{
case Encrypt:
return encrypt;
case Decrypt:
return decrypt;
default:
throw Exception("DataLimit::Component: unknown mode");
}
}
Component encrypt;
Component decrypt;
unsigned int flags = 0;
};
} // namespace openvpn
#endif