mirror of
https://github.com/OpenVPN/openvpn.git
synced 2025-05-10 05:59:10 +08:00

OpenVPN currently uses its own (based on TLS 1.0) key derivation mechanism to generate the 256 bytes key data in key2 struct that are then used used to generate encryption/hmac/iv vectors. While this mechanism is still secure, it is not state of the art. Instead of modernising our own approach, this commit implements key derivation using the Keying Material Exporters API introduced by RFC 5705. We also use an opportunistic approach of negotiating the use of EKM (exported key material) through an IV_PROTO flag and prefer EKM to our own PRF if both client and server support it. The use of EKM is pushed to the client as part of NCP as key-derivation tls-ekm. We still exchange the random data (112 bytes from client to server and 64 byte from server to client) for the OpenVPN PRF but do not use it. Removing that exchange would break the handshake and make a key-method 3 or similar necessary. As a side effect, this makes a little bit easier to have a FIPS compatible version of OpenVPN since we do not rely on calling MD5 anymore. Side note: this commit breaks the (not yet merged) WolfSSL support as it claims to support EKM in the OpenSSL compat API but always returns an error if you try to use it. Patch v2: rebase/change to V2 of EKM refactoring Patch v3: add Changes.rst Patch v4: Rebase on master. Patch v5: Refuse internal label to be used with --keying-material-exporter, polishing/fixes suggested by Steffan integrated Signed-off-by: Arne Schwabe <arne@rfc2549.org> Acked-by: Steffan Karger <steffan.karger@foxcrypto.com> Message-Id: <20201009115453.4279-1-arne@rfc2549.org> URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg21187.html Signed-off-by: Gert Doering <gert@greenie.muc.de>
159 lines
7.2 KiB
C
159 lines
7.2 KiB
C
/*
|
|
* OpenVPN -- An application to securely tunnel IP networks
|
|
* over a single TCP/UDP port, with support for SSL/TLS-based
|
|
* session authentication and key exchange,
|
|
* packet encryption, packet authentication, and
|
|
* packet compression.
|
|
*
|
|
* Copyright (C) 2010-2018 Fox Crypto B.V. <openvpn@fox-it.com>
|
|
*
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2
|
|
* 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 General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
/**
|
|
* @file
|
|
* Key generation documentation file.
|
|
*/
|
|
|
|
/**
|
|
* @page key_generation Data channel %key generation
|
|
*
|
|
* This section describes how OpenVPN peers generate and exchange %key
|
|
* material necessary for the security operations performed on data
|
|
* channel packets.
|
|
*
|
|
* The %key generation and exchange process between OpenVPN client and
|
|
* server occurs every time data channel security parameters are
|
|
* negotiated, for example during the initial setup of a VPN tunnel or
|
|
* when the active security parameters expire. In source code terms, this
|
|
* is when a new key_state structure is initialized.
|
|
*
|
|
* @section key_generation_method Key methods
|
|
*
|
|
* OpenVPN supports two different ways of generating and exchanging %key
|
|
* material between client and server. These are known as %key method 1
|
|
* and %key method 2. %Key method 2 is the recommended method. Both are
|
|
* explained below.
|
|
*
|
|
* @subsection key_generation_method_1 Key method 1
|
|
*
|
|
* -# Each host generates its own random material.
|
|
* -# Each host uses its locally generated random material as %key data
|
|
* for encrypting and signing packets sent to the remote peer.
|
|
* -# Each host then sends its random material to the remote peer, so that
|
|
* the remote peer can use that %key data for authenticating and
|
|
* decrypting received packets.
|
|
*
|
|
* @subsection key_generation_method_2 Key method 2
|
|
*
|
|
* There are two methods for generating key data when using key method 2
|
|
* the first is OpenVPN's traditional approach that exchanges random
|
|
* data and uses a PRF and the other is using the RFC5705 keying material
|
|
* exporter to generate the key material. For both methods the random
|
|
* data is exchange but only used in the traditional method.
|
|
*
|
|
* -# The client generates random material in the following amounts:
|
|
* - Pre-master secret: 48 bytes
|
|
* - Client's PRF seed for master secret: 32 bytes
|
|
* - Client's PRF seed for %key expansion: 32 bytes
|
|
* -# The client sends its share of random material to the server.
|
|
* -# The server generates random material in the following amounts:
|
|
* - Server's PRF seed for master secret: 32 bytes
|
|
* - Server's PRF seed for %key expansion: 32 bytes
|
|
* -# The server computes the %key expansion using its own and the
|
|
* client's random material.
|
|
* -# The server sends its share of random material to the client.
|
|
* -# The client computes the %key expansion using its own and the
|
|
* server's random material.
|
|
*
|
|
* %Key method 2 %key expansion is performed by the \c
|
|
* generate_key_expansion_openvpn_prf() function. Please refer to its source
|
|
* code for details of the %key expansion process.
|
|
*
|
|
* When the client sends the IV_PROTO_TLS_KEY_EXPORT flag and the server replies
|
|
* with `key-derivation tls-ekm` the RFC5705 key material exporter with the
|
|
* label EXPORTER-OpenVPN-datakeys is used for the key data.
|
|
*
|
|
* @subsection key_generation_random Source of random material
|
|
*
|
|
* OpenVPN uses the either the OpenSSL library or the mbed TLS library as its
|
|
* source of random material.
|
|
*
|
|
* In OpenSSL, the \c RAND_bytes() function is called
|
|
* to supply cryptographically strong pseudo-random data. The following links
|
|
* contain more information on this subject:
|
|
* - For OpenSSL's \c RAND_bytes() function:
|
|
* http://www.openssl.org/docs/crypto/RAND_bytes.html
|
|
* - For OpenSSL's pseudo-random number generating system:
|
|
* http://www.openssl.org/docs/crypto/rand.html
|
|
* - For OpenSSL's support for external crypto modules:
|
|
* http://www.openssl.org/docs/crypto/engine.html
|
|
*
|
|
* In mbed TLS, the Havege random number generator is used. For details, see
|
|
* the mbed TLS documentation.
|
|
*
|
|
* @section key_generation_exchange Key exchange:
|
|
*
|
|
* The %key exchange process is initiated by the OpenVPN process running
|
|
* in client mode. After the initial three-way handshake has successfully
|
|
* completed, the client sends its share of random material to the server,
|
|
* after which the server responds with its part. This process is
|
|
* depicted below:
|
|
*
|
|
@verbatim
|
|
Client Client Server Server
|
|
State Action Action State
|
|
---------- -------------------- -------------------- ----------
|
|
|
|
... waiting until three-way handshake complete ...
|
|
S_START S_START
|
|
key_method_?_write()
|
|
send to server --> --> --> --> receive from client
|
|
S_SENT_KEY key_method_?_read()
|
|
S_GOT_KEY
|
|
key_method_?_write()
|
|
receive from server <-- <-- <-- <-- send to client
|
|
key_method_?_read() S_SENT_KEY
|
|
S_GOT_KEY
|
|
... waiting until control channel fully synchronized ...
|
|
S_ACTIVE S_ACTIVE
|
|
@endverbatim
|
|
*
|
|
* For more information about the client and server state values, see the
|
|
* \link control_processor Control Channel Processor module\endlink.
|
|
*
|
|
* Depending on which %key method is used, the \c ? in the function names
|
|
* of the diagram above is a \c 1 or a \c 2. For example, if %key method
|
|
* 2 is used, that %key exchange would be started by the client calling \c
|
|
* key_method_2_write(). These functions are called from the \link
|
|
* control_processor Control Channel Processor module's\endlink \c
|
|
* tls_process() function and control the %key generation and exchange
|
|
* process as follows:
|
|
* - %Key method 1 has been removed in OpenVPN 2.5
|
|
* - %Key method 2:
|
|
* - \c key_method_2_write(): generate random material locally, and if
|
|
* in server mode generate %key expansion.
|
|
* - \c key_method_2_read(): read random material received from remote
|
|
* peer, and if in client mode generate %key expansion.
|
|
*
|
|
* @subsection key_generation_encapsulation Transmission of key material
|
|
*
|
|
* The OpenVPN client and server communicate with each other through their
|
|
* control channel. This means that all of the data transmitted over the
|
|
* network, such as random material for %key generation, is encapsulated
|
|
* in a TLS layer. For more details, see the \link control_tls Control
|
|
* Channel TLS module\endlink documentation.
|
|
*/
|