mirror of
https://github.com/OpenVPN/openvpn3.git
synced 2024-09-20 04:02:15 +02:00
662bf7833e
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.
149 lines
4.1 KiB
C++
149 lines
4.1 KiB
C++
// 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-2015 OpenVPN Technologies, 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/>.
|
|
|
|
// Sender side of reliability layer
|
|
|
|
#ifndef OPENVPN_RELIABLE_RELSEND_H
|
|
#define OPENVPN_RELIABLE_RELSEND_H
|
|
|
|
#include <openvpn/common/size.hpp>
|
|
#include <openvpn/common/exception.hpp>
|
|
#include <openvpn/common/msgwin.hpp>
|
|
#include <openvpn/time/time.hpp>
|
|
#include <openvpn/reliable/relcommon.hpp>
|
|
|
|
namespace openvpn {
|
|
|
|
template <typename PACKET>
|
|
class ReliableSendTemplate
|
|
{
|
|
public:
|
|
typedef reliable::id_t id_t;
|
|
|
|
class Message : public ReliableMessageBase<PACKET>
|
|
{
|
|
friend class ReliableSendTemplate;
|
|
using ReliableMessageBase<PACKET>::defined;
|
|
|
|
public:
|
|
bool ready_retransmit(const Time& now) const
|
|
{
|
|
return defined() && now >= retransmit_at_;
|
|
}
|
|
|
|
Time::Duration until_retransmit(const Time& now) const
|
|
{
|
|
Time::Duration ret;
|
|
if (now < retransmit_at_)
|
|
ret = retransmit_at_ - now;
|
|
return ret;
|
|
}
|
|
|
|
void reset_retransmit(const Time& now, const Time::Duration& tls_timeout)
|
|
{
|
|
retransmit_at_ = now + tls_timeout;
|
|
}
|
|
|
|
private:
|
|
Time retransmit_at_;
|
|
};
|
|
|
|
ReliableSendTemplate() : next(0) {}
|
|
ReliableSendTemplate(const id_t span) { init(span); }
|
|
|
|
void init(const id_t span)
|
|
{
|
|
next = 0;
|
|
window_.init(next, span);
|
|
}
|
|
|
|
// Return the id that the object at the head of the queue
|
|
// would have (even if it isn't defined yet).
|
|
id_t head_id() const { return window_.head_id(); }
|
|
|
|
// Return the ID of one past the end of the window
|
|
id_t tail_id() const { return window_.tail_id(); }
|
|
|
|
// Return the window size
|
|
id_t span() const { return window_.span(); }
|
|
|
|
// Return a reference to M object at id, throw exception
|
|
// if id is not in current window
|
|
Message& ref_by_id(const id_t id)
|
|
{
|
|
return window_.ref_by_id(id);
|
|
}
|
|
|
|
// Return the shortest duration for any pending retransmissions
|
|
Time::Duration until_retransmit(const Time& now)
|
|
{
|
|
Time::Duration ret = Time::Duration::infinite();
|
|
for (id_t i = head_id(); i < tail_id(); ++i)
|
|
{
|
|
const Message& msg = ref_by_id(i);
|
|
if (msg.defined())
|
|
{
|
|
Time::Duration ut = msg.until_retransmit(now);
|
|
if (ut < ret)
|
|
ret = ut;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// Return number of unacknowleged packets in send queue
|
|
unsigned int n_unacked()
|
|
{
|
|
unsigned int ret = 0;
|
|
for (id_t i = head_id(); i < tail_id(); ++i)
|
|
{
|
|
if (ref_by_id(i).defined())
|
|
++ret;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// Return a fresh Message object that can be used to
|
|
// construct the next packet in the sequence. Don't call
|
|
// unless ready() returns true.
|
|
Message& send(const Time& now, const Time::Duration& tls_timeout)
|
|
{
|
|
Message& msg = window_.ref_by_id(next);
|
|
msg.id_ = next++;
|
|
msg.reset_retransmit(now, tls_timeout);
|
|
return msg;
|
|
}
|
|
|
|
// Return true if send queue is ready to receive another packet
|
|
bool ready() const { return window_.in_window(next); }
|
|
|
|
// Remove a message from send queue that has been acknowledged
|
|
void ack(const id_t id) { window_.rm_by_id(id); }
|
|
|
|
private:
|
|
id_t next;
|
|
MessageWindow<Message, id_t> window_;
|
|
};
|
|
|
|
} // namespace openvpn
|
|
|
|
#endif // OPENVPN_RELIABLE_RELSEND_H
|