Am 09.10.20 um 11:23 schrieb Steffan Karger:
> Hi,
> 
> On 25-08-2020 09:36, Arne Schwabe wrote:
>> 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.
> 
> Thanks! I'm glad to see you're picking up the work I haven't been able
> to find time for.
> 
>> 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.
>>
>> Signed-off-by: Arne Schwabe <a...@rfc2549.org>
> 
> Signed off two times.
> 
>> Patch v2: rebase/change to V2 of EKM refactoring
>>
>> Patch v3: add Changes.rst
>>
>> Signed-off-by: Arne Schwabe <a...@rfc2549.org>
>> ---
>>  Changes.rst                      | 11 +++++++
>>  doc/doxygen/doc_key_generation.h | 14 +++++++--
>>  src/openvpn/crypto.h             |  4 +++
>>  src/openvpn/init.c               |  1 +
>>  src/openvpn/multi.c              |  4 +++
>>  src/openvpn/options.c            | 14 +++++++++
>>  src/openvpn/options.h            |  3 ++
>>  src/openvpn/push.c               |  5 ++-
>>  src/openvpn/ssl.c                | 54 ++++++++++++++++++++++++++++----
>>  src/openvpn/ssl.h                |  2 ++
>>  src/openvpn/ssl_backend.h        |  2 ++
>>  src/openvpn/ssl_mbedtls.c        |  7 ++---
>>  12 files changed, 107 insertions(+), 14 deletions(-)
>>
>> diff --git a/Changes.rst b/Changes.rst
>> index f67e1d76..2a2829e7 100644
>> --- a/Changes.rst
>> +++ b/Changes.rst
>> @@ -1,3 +1,14 @@
>> +Overview of changes in 2.6
>> +==========================
>> +
>> +
>> +New features
>> +------------
>> +Keying Material Exporters (RFC 5705) based key generation
>> +    As part of the cipher negotiation OpenVPN will automatically prefer
>> +    the RFC5705 based key material generation to the current custom
>> +    OpenVPN PRF. This feature requires OpenSSL or mbed TLS 2.18+.
>> +
>>  Overview of changes in 2.5
>>  ==========================
>>  
>> diff --git a/doc/doxygen/doc_key_generation.h 
>> b/doc/doxygen/doc_key_generation.h
>> index 4bb9c708..cef773a9 100644
>> --- a/doc/doxygen/doc_key_generation.h
>> +++ b/doc/doxygen/doc_key_generation.h
>> @@ -58,6 +58,12 @@
>>   *
>>   * @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
>> @@ -73,8 +79,12 @@
>>   *    server's random material.
>>   *
>>   * %Key method 2 %key expansion is performed by the \c
>> - * generate_key_expansion() function.  Please refer to its source code for
>> - * details of the %key expansion process.
>> + * 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.
> 
> Did you request this label with IANA?

It is not really described well how this actually works, from what I
interpreted you need to write to the mailing list, which I did:
https://mailarchive.ietf.org/arch/msg/tls/IWFb5hLsqNlCcIMnEDDuPAkzXvg/

but I am lost what the next step would be.

> 
> Also, a user could now use --keying-material-exporter to export the data
> channel keys to a plugin. I'm inclined to say we should prevent that, by
> rejecting our internal label as a user label.



> 
>>   * @subsection key_generation_random Source of random material
>>   *
>> diff --git a/src/openvpn/crypto.h b/src/openvpn/crypto.h
>> index 999f643e..ec935ca5 100644
>> --- a/src/openvpn/crypto.h
>> +++ b/src/openvpn/crypto.h
>> @@ -254,6 +254,10 @@ struct crypto_options
>>  #define CO_MUTE_REPLAY_WARNINGS (1<<2)
>>      /**< Bit-flag indicating not to display
>>       *   replay warnings. */
>> +#define CO_USE_TLS_KEY_MATERIAL_EXPORT  (1<<3)
>> +    /**< Bit-flag indicating that key derivation
> 
> Sugestion: "data channel key derivation".
> 
>> +     * is done using TLS keying material export [RFC5705]
>> +     */
>>      unsigned int flags;         /**< Bit-flags determining behavior of
>>                                   *   security operation functions. */
>>  };
>> diff --git a/src/openvpn/init.c b/src/openvpn/init.c
>> index a785934a..dff090b1 100644
>> --- a/src/openvpn/init.c
>> +++ b/src/openvpn/init.c
>> @@ -676,6 +676,7 @@ restore_ncp_options(struct context *c)
>>      c->options.ciphername = c->c1.ciphername;
>>      c->options.authname = c->c1.authname;
>>      c->options.keysize = c->c1.keysize;
>> +    c->options.data_channel_use_ekm = false;
>>  }
>>  
>>  void
>> diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c
>> index 13738180..a5862020 100644
>> --- a/src/openvpn/multi.c
>> +++ b/src/openvpn/multi.c
>> @@ -1817,6 +1817,10 @@ multi_client_set_protocol_options(struct context *c)
>>          c->c2.push_request_received = true;
>>      }
>>  
>> +#ifdef HAVE_EXPORT_KEYING_MATERIAL
>> +    o->data_channel_use_ekm = (proto & IV_PROTO_TLS_KEY_EXPORT);
>> +#endif
>> +
>>      /* Select cipher if client supports Negotiable Crypto Parameters */
>>      if (!o->ncp_enabled)
>>      {
>> diff --git a/src/openvpn/options.c b/src/openvpn/options.c
>> index 8bf82c57..90e78a7b 100644
>> --- a/src/openvpn/options.c
>> +++ b/src/openvpn/options.c
>> @@ -7947,6 +7947,20 @@ add_option(struct options *options,
>>          }
>>          options->ncp_ciphers = p[1];
>>      }
>> +    else if (streq(p[0], "key-derivation") && p[1])
>> +    {
>> +        VERIFY_PERMISSION(OPT_P_NCP)
>> +#ifdef HAVE_EXPORT_KEYING_MATERIAL
>> +        if (streq(p[1], "tls-ekm"))
>> +        {
>> +            options->data_channel_use_ekm = true;
>> +        }
>> +        else
>> +#endif
>> +        {
>> +            msg(msglevel, "Unknown key-derivation method %s", p[1]);
>> +        }
>> +    }
> 
> This option is also accepted on the command line or config file, but is
> not documented in the man page or --help text. It would probably be best
> to not accept is on the command line or config file, but I'm not sure we
> have the infra in place for that.

Sadly, we don't. Other options like peer-id or echo are also accepted
from command line or config. Or we have it and nobody is aware of how to
use it.

> 
> So, looks good in general, but needs a bit more polishing :)
>

I will do the polishing and send a new version :)

Thanks for reviewing.

Arne

Attachment: signature.asc
Description: OpenPGP digital signature

_______________________________________________
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel

Reply via email to