Client-specific tls-crypt keys (--tls-crypt-v2)
PATCH v6 7/7 tls-crypt-v2: add script hook to verify metadata
In reply to Steffan KargerTo allow rejecting incoming connections very early in the handshake, add a --tls-crypt-v2-verify option that allows administators to run an external command to verify the metadata from the client key. See doc/tls-crypt-v2.txt for more details.
Because of the extra dependencies, this requires adding a mock parse_line() to the tls-crypt unit tests. Also, this turns tls_wrap_free into a static inline function, so that we don't need to compile in ssl.c (and all of it's dependencies) with the unit tests.
---
v3: rebase on curent master / v3 patch set
v4: fix memory leak (metadata buffer was not free'd for tls_wrap_tmp)
v5: rebase on v5 patch set, textual fixes in man page
v6: fix memory leak in unit tests, code style fixes
Changes.rst | 6 +++ doc/openvpn.8 | 35 ++++++++++++++-- src/openvpn/init.c | 1 + src/openvpn/options.c | 7 ++++ src/openvpn/options.h | 2 + src/openvpn/ssl.c | 34 +++++---------- src/openvpn/ssl.h | 18 ++++++++ src/openvpn/ssl_common.h | 1 + src/openvpn/tls_crypt.c | 69 ++++++++++++++++++++++++++++++- src/openvpn/tls_crypt.h | 3 +- tests/unit_tests/openvpn/Makefile.am | 12 ++++-- tests/unit_tests/openvpn/test_tls_crypt.c | 19 ++++++++- 12 files changed, 175 insertions(+), 32 deletions(-)
Changes.rst +6 -0
@@ -3,6 +3,12 @@ Overview of changes in 2.5 New features ------------ +Client-specific tls-crypt keys (``--tls-crypt-v2``) + ``tls-crypt-v2`` adds the ability to supply each client with a unique + tls-crypt key. This allows large organisations and VPN providers to profit + from the same DoS and TLS stack protection that small deployments can + already achieve using ``tls-auth`` or ``tls-crypt``. + ChaCha20-Poly1305 cipher support Added support for using the ChaCha20-Poly1305 cipher in the OpenVPN data channel.
doc/openvpn.8 +32 -3
@@ -5296,9 +5296,38 @@ If supplied, include the supplied in the wrapped client key. This metadata must be supplied in base64\-encoded form. The metadata must be at most 735 bytes long (980 bytes in base64). -.B TODO -Metadata handling is not yet implemented. This text will be updated by the -commit that introduces metadata handling. +If no metadata is supplied, OpenVPN will use a 64\-bit unix timestamp +representing the current time in UTC, encoded in network order, as metadata for +the generated key. + +Servers can use +.B \-\-tls\-crypt\-v2\-verify +to specify a metadata verification command. +.\"********************************************************* +.TP +.B \-\-tls\-crypt\-v2\-verify cmd + +Run command +.B cmd +to verify the metadata of the client\-specific tls\-crypt\-v2 key of a +connecting client. This allows server administrators to reject client +connections, before exposing the TLS stack (including the notoriously dangerous +X.509 and ASN.1 stacks) to the connecting client. + +OpenVPN supplies the following env vars to the command: +.RS +.IP \[bu] 2 +script_type is set to "tls\-crypt\-v2\-verify" +.IP \[bu] +metadata_type is set to "0" if the metadata was user supplied, or "1" if it's a +64\-bit unix timestamp representing the key creation time. +.IP \[bu] +metadata_file contains the filename of a temporary file that contains the client +metadata. +.RE + +.IP +The command can reject the connection by exiting with a non-zero exit code. .\"********************************************************* .TP .B \-\-askpass [file]
src/openvpn/init.c +1 -0
@@ -2902,6 +2902,7 @@ do_init_crypto_tls(struct context *c, const unsigned int flags)if (options->tls_server) { to.tls_wrap.tls_crypt_v2_server_key = c->c1.ks.tls_crypt_v2_server_key; + to.tls_crypt_v2_verify_script = c->options.tls_crypt_v2_verify_script; } }
src/openvpn/options.c +7 -0
@@ -629,6 +629,8 @@ static const char usage_message[] ="--tls-crypt-v2-genkey client|server keyfile [base64 metadata]: Generate a\n" " fresh tls-crypt-v2 client or server key, and store to\n" " keyfile. If supplied, include metadata in wrapped key.\n" +"--tls-crypt-v2-verify cmd : Run command cmd to verify the metadata of the\n" +" client-supplied tls-crypt-v2 client key\n" "--askpass [file]: Get PEM password from controlling tty before we daemonize.\n" "--auth-nocache : Don't cache --askpass or --auth-user-pass passwords.\n" "--crl-verify crl ['dir']: Check peer certificate against a CRL.\n"
@@ -8185,6 +8187,11 @@ add_option(struct options *options, options->tls_crypt_v2_metadata = p[3 ]; } } +else if (streq (p[0 ],"tls-crypt-v2-verify" ) && p[1 ] && !p[2 ]) + { +VERIFY_PERMISSION (OPT_P_GENERAL ); + options->tls_crypt_v2_verify_script = p[1 ]; + }else if (streq (p[0 ],"key-method" ) && p[1 ] && !p[2 ]) {int key_method;
src/openvpn/options.h +2 -0
@@ -590,6 +590,8 @@ struct optionsconst char *tls_crypt_v2_genkey_file;const char *tls_crypt_v2_metadata; +const char *tls_crypt_v2_verify_script; +/* Allow only one session */ bool single_session;
src/openvpn/ssl.c +11 -23
@@ -1047,23 +1047,6 @@ tls_session_user_pass_enabled(struct tls_session *session)/** @addtogroup control_processor * @{ */ -/** Free the elements of a tls_wrap_ctx structure */ -static void tls_wrap_free (struct tls_wrap_ctx *tls_wrap) -{ -if (packet_id_initialized (&tls_wrap->opt.packet_id)) - { -packet_id_free (&tls_wrap->opt.packet_id); - } - -if (tls_wrap->cleanup_key_ctx) - { -free_key_ctx_bi (&tls_wrap->opt.key_ctx_bi); - } - -free_buf (&tls_wrap->tls_crypt_v2_metadata); -free_buf (&tls_wrap->work); -} -/** @name Functions for initialization and cleanup of tls_session structures * @{ */
@@ -1533,14 +1516,15 @@ write_control_auth(struct tls_session *session,static bool read_control_auth (struct buffer *buf,struct tls_wrap_ctx *ctx, -const struct link_socket_actual *from) +const struct link_socket_actual *from, +const struct tls_options *opt) {struct gc_arena gc =gc_new ();bool ret = false;const uint8_t opcode = *(BPTR (buf)) >>P_OPCODE_SHIFT ;if (opcode ==P_CONTROL_HARD_RESET_CLIENT_V3 - && !tls_crypt_v2_extract_client_key (buf, ctx)) + && !tls_crypt_v2_extract_client_key (buf, ctx, opt)) { msg (D_TLS_ERRORS, "TLS Error: can not extract tls-crypt-v2 client key from %s",
@@ -3621,7 +3605,8 @@ tls_pre_decrypt(struct tls_multi *multi, goto error; } -if (!read_control_auth (buf, &session->tls_wrap, from)) +if (!read_control_auth (buf, &session->tls_wrap, from, + session->opt)) { goto error; }
@@ -3674,7 +3659,8 @@ tls_pre_decrypt(struct tls_multi *multi,if (op ==P_CONTROL_SOFT_RESET_V1 &&DECRYPT_KEY_ENABLED (multi, ks)) { -if (!read_control_auth (buf, &session->tls_wrap, from)) +if (!read_control_auth (buf, &session->tls_wrap, from, + session->opt)) { goto error; }
@@ -3695,7 +3681,8 @@ tls_pre_decrypt(struct tls_multi *multi, do_burst = true; } -if (!read_control_auth (buf, &session->tls_wrap, from)) +if (!read_control_auth (buf, &session->tls_wrap, from, + session->opt)) { goto error; }
@@ -3897,8 +3884,9 @@ tls_pre_decrypt_lite(const struct tls_auth_standalone *tas,bool status;/* HMAC test, if --tls-auth was specified */ - status =read_control_auth (&newbuf, &tls_wrap_tmp, from); + status =read_control_auth (&newbuf, &tls_wrap_tmp, from,NULL );free_buf (&newbuf); +free_buf (&tls_wrap_tmp.tls_crypt_v2_metadata);if (tls_wrap_tmp.cleanup_key_ctx) {free_key_ctx_bi (&tls_wrap_tmp.opt.key_ctx_bi);
src/openvpn/ssl.h +18 -0
@@ -527,6 +527,24 @@ bool tls_item_in_cipher_list(const char *item, const char *list);* inline functions */ +/** Free the elements of a tls_wrap_ctx structure */ +static inline void +tls_wrap_free (struct tls_wrap_ctx *tls_wrap) +{ +if (packet_id_initialized (&tls_wrap->opt.packet_id)) + { +packet_id_free (&tls_wrap->opt.packet_id); + } + +if (tls_wrap->cleanup_key_ctx) + { +free_key_ctx_bi (&tls_wrap->opt.key_ctx_bi); + } + +free_buf (&tls_wrap->tls_crypt_v2_metadata); +free_buf (&tls_wrap->work); +} +static inline bool tls_initial_packet_received (const struct tls_multi *multi) {
src/openvpn/ssl_common.h +1 -0
@@ -293,6 +293,7 @@ struct tls_optionsbool ncp_enabled;bool tls_crypt_v2; +const char *tls_crypt_v2_verify_script;/** TLS handshake wrapping state */ struct tls_wrap_ctx tls_wrap;
src/openvpn/tls_crypt.c +68 -1
92 lines not on this page · raw message
src/openvpn/tls_crypt.h +2 -1
@@ -195,7 +195,8 @@ void tls_crypt_v2_init_client_key(struct key_ctx_bi *key,* @returns true if a key was successfully extracted. */ bool tls_crypt_v2_extract_client_key (struct buffer *buf, -struct tls_wrap_ctx *ctx); +struct tls_wrap_ctx *ctx, +const struct tls_options *opt);/** * Generate a tls-crypt-v2 server key, and write to file.
tests/unit_tests/openvpn/Makefile.am +9 -3
@@ -6,7 +6,10 @@ if HAVE_LD_WRAP_SUPPORT check_PROGRAMS += argv_testdriver buffer_testdriver endif -check_PROGRAMS += crypto_testdriver packet_id_testdriver tls_crypt_testdriver +check_PROGRAMS += crypto_testdriver packet_id_testdriver +if HAVE_LD_WRAP_SUPPORT +check_PROGRAMS += tls_crypt_testdriver +endif TESTS = $(check_PROGRAMS)
@@ -52,13 +55,16 @@ packet_id_testdriver_SOURCES = test_packet_id.c mock_msg.c \ tls_crypt_testdriver_CFLAGS = @TEST_CFLAGS@ \ -I$(openvpn_includedir) -I$(compat_srcdir) -I$(openvpn_srcdir) -tls_crypt_testdriver_LDFLAGS = @TEST_LDFLAGS@ +tls_crypt_testdriver_LDFLAGS = @TEST_LDFLAGS@ -Wl,--wrap=parse_line tls_crypt_testdriver_SOURCES = test_tls_crypt.c mock_msg.c \ + $(openvpn_srcdir)/argv.c \ $(openvpn_srcdir)/base64.c \ $(openvpn_srcdir)/buffer.c \ $(openvpn_srcdir)/crypto.c \ $(openvpn_srcdir)/crypto_mbedtls.c \ $(openvpn_srcdir)/crypto_openssl.c \ + $(openvpn_srcdir)/env_set.c \ $(openvpn_srcdir)/otime.c \ $(openvpn_srcdir)/packet_id.c \ - $(openvpn_srcdir)/platform.c + $(openvpn_srcdir)/platform.c \ + $(openvpn_srcdir)/run_command.c
tests/unit_tests/openvpn/test_tls_crypt.c +18 -1
@@ -43,8 +43,24 @@#define TESTBUF_SIZE 128 +/* Defines for use in the tests and the mock parse_line() */ +#define PATH1 "/s p a c e" +#define PATH2 "/foo bar/baz" +#define PARAM1 "param1" +#define PARAM2 "param two" +const char plaintext_short[1 ]; +int +__wrap_parse_line (const char *line,char **p,const int n,const char *file, +const int line_num,int msglevel,struct gc_arena *gc) +{ + p[0] = PATH1 PATH2; + p[1 ] =PARAM1 ; + p[2 ] =PARAM2 ; +return 3 ; +} +struct test_tls_crypt_context {struct crypto_options co;struct key_type kt;
@@ -351,7 +367,8 @@ tls_crypt_v2_wrap_unwrap_max_metadata(void **state) { .mode = TLS_WRAP_CRYPT, .tls_crypt_v2_server_key = ctx->server_keys.encrypt, }; -assert_true (tls_crypt_v2_extract_client_key (&ctx->wkc, &wrap_ctx)); +assert_true (tls_crypt_v2_extract_client_key (&ctx->wkc, &wrap_ctx,NULL )); +tls_wrap_free (&wrap_ctx); }/**
Signature · 1 line
2.7.4
PATCH v7 2/7 tls-crypt-v2: add specification to doc/
In reply to Steffan KargerThis is a preliminary description of tls-crypt-v2. It should give a good impression about the reasoning and design behind tls-crypt-v2, but might need some polishing and updating.
---
v3: Include length in WKc
v4: Clarify metadata handling
v5: Typo fixes (thanks tincanteksup)
v6: Change WKc length to ciphertext length (was plaintext), textual fixes
v7: Textual fixes irt review
doc/tls-crypt-v2.txt | 189 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 doc/tls-crypt-v2.txt
doc/tls-crypt-v2.txt new file +189 -0
@@ -0,0 +1,189 @@ +Client-specific tls-crypt keys (--tls-crypt-v2) +=============================================== + +This document describes the ``--tls-crypt-v2`` option, which enables OpenVPN +to use client-specific ``--tls-crypt`` keys. + +Rationale +--------- + +``--tls-auth`` and ``tls-crypt`` use a pre-shared group key, which is shared +among all clients and servers in an OpenVPN deployment. If any client or +server is compromised, the attacker will have access to this shared key, and it +will no longer provide any security. To reduce the risk of losing pre-shared +keys, ``tls-crypt-v2`` adds the ability to supply each client with a unique +tls-crypt key. This allows large organisations and VPN providers to profit +from the same DoS and TLS stack protection that small deployments can already +achieve using ``tls-auth`` or ``tls-crypt``. + +Also, for ``tls-crypt``, even if all these peers succeed in keeping the key +secret, the key lifetime is limited to roughly 8000 years, divided by the +number of clients (see the ``--tls-crypt`` section of the man page). Using +client-specific keys, we lift this lifetime requirement to roughly 8000 years +for each client key (which "Should Be Enough For Everybody (tm)"). + + +Introduction +------------ + +``tls-crypt-v2`` uses an encrypted cookie mechanism to introduce +client-specific tls-crypt keys without introducing a lot of server-side state. +The client-specific key is encrypted using a server key. The server key is the +same for all servers in a group. When a client connects, it first sends the +encrypted key to the server, such that the server can decrypt the key and all +messages can thereafter be encrypted using the client-specific key. + +A wrapped (encrypted and authenticated) client-specific key can also contain +metadata. The metadata is wrapped together with the key, and can be used to +allow servers to identify clients and/or key validity. This allows the server +to abort the connection immediately after receiving the first packet, rather +than performing an entire TLS handshake. Aborting the connection this early +greatly improves the DoS resilience and reduces attack service against +malicious clients that have the ``tls-crypt`` or ``tls-auth`` key. This is +particularly relevant for large deployments (think lost key or disgruntled +employee) and VPN providers (clients are not trusted). + +To allow for a smooth transition, ``tls-crypt-v2`` is designed such that a +server can enable both ``tls-crypt-v2`` and either ``tls-crypt`` or +``tls-auth``. This is achieved by introducing a P_CONTROL_HARD_RESET_CLIENT_V3 +opcode, that indicates that the client wants to use ``tls-crypt-v2`` for the +current connection. + +For an exact specification and more details, read the Implementation section. + + +Implementation +-------------- + +When setting up a tls-crypt-v2 group (similar to generating a tls-crypt or +tls-auth key previously): + +1. Generate a tls-crypt-v2 server key using OpenVPN's ``--genkey``. This key + contains 2 512-bit keys, of which we use: + + * the first 256 bits of key 1 as AES-256-CTR encryption key ``Ke`` + * the first 256 bits of key 2 as HMAC-SHA-256 authentication key ``Ka`` + + This fomat is similar to the format for regular ``tls-crypt``/``tls-auth`` + and data channel keys, which allows us to reuse code. + +2. Add the tls-crypt-v2 server key to all server configs + (``tls-crypt-v2 /path/to/server.key``) + + +When provisioning a client, create a client-specific tls-crypt key: + +1. Generate 2048 bits client-specific key ``Kc`` + +2. Optionally generate metadata + + The first byte of the metadata determines the type. The initial + implementation supports the following types: + + 0x00 (USER): User-defined free-form data. + 0x01 (TIMESTAMP): 64-bit network order unix timestamp of key generation. + + The timestamp can be used to reject too-old tls-crypt-v2 client keys. + + User metadata could for example contain the users certificate serial, such + that the incoming connection can be verified against a CRL. + + If no metadata is supplied during key generation, openvpn defaults to the + TIMESTAMP metadata type. + +3. Create a wrapped client key ``WKc``, using the same nonce-misuse-resistant + SIV construction we use for tls-crypt: + + ``len = len(WKc)`` (16 bit, network byte order) + + ``T = HMAC-SHA256(Ka, len || Kc || metadata)`` + + ``IV = 128 most significant bits of T`` + + ``WKc = T || AES-256-CTR(Ke, IV, Kc || metadata) || len`` + + Note that the length of ``WKc`` can be computed before composing ``WKc``, + because the length of each component is known (and AES-256-CTR does not add + any padding). + +4. Create a tls-crypt-v2 client key: PEM-encode ``Kc || WKc`` and store in a + file, using the header ``-----BEGIN OpenVPN tls-crypt-v2 client key-----`` + and the footer ``-----END OpenVPN tls-crypt-v2 client key-----``. (The PEM + format is simple, and following PEM allows us to use the crypto lib function + for en/decoding.) + +5. Add the tls-crypt-v2 client key to the client config + (``tls-crypt-v2 /path/to/client-specific.key``) + + +When setting up the openvpn connection: + +1. The client reads the tls-crypt-v2 key from its config, and: + + 1. loads ``Kc`` as its tls-crypt key, + 2. stores ``WKc`` in memory for sending to the server. + +2. To start the connection, the client creates a P_CONTROL_HARD_RESET_CLIENT_V3 + message, wraps it with tls-crypt using ``Kc`` as the key, and appends + ``WKc``. (``WKc`` must not be encrypted, to prevent a chicken-and-egg + problem.) + +3. The server receives the P_CONTROL_HARD_RESET_CLIENT_V3 message, and + + 1. reads the WKc length field from the end of the message, and extracts WKc + from the message + 2. unwraps ``WKc`` + 3. uses unwrapped ``Kc`` to verify the remaining + P_CONTROL_HARD_RESET_CLIENT_V3 message's (encryption and) authentication. + + The message is dropped and no error response is sent when either 3.1, 3.2 or + 3.3 fails (DoS protection). + +4. Server optionally checks metadata using a --tls-crypt-v2-verify script + + This allows early abort of connection, *before* we expose any of the + notoriously dangerous TLS, X.509 and ASN.1 parsers and thereby reduces the + attack surface of the server. + + The metadata is checked *after* the OpenVPN three-way handshake has + completed, to prevent DoS attacks. (That is, once the client has proved to + the server that it possesses Kc, by authenticating a packet that contains the + session ID picked by the server.) + + A server should not send back any error messages if metadata verification + fails, to reduce attack surface and maximize DoS resilience. + +6. Client and server use ``Kc`` for (un)wrapping any following control channel + messages. + + +Considerations +-------------- + +To allow for a smooth transition, the server implementation allows +``tls-crypt`` or ``tls-auth`` to be used simultaneously with ``tls-crypt-v2``. +This specification does not allow simultaneously using ``tls-crypt-v2`` and +connections without any control channel wrapping, because that would break DoS +resilience. + +WKc includes a length field, so we leave the option for future extension of the +P_CONTROL_HEAD_RESET_CLIENT_V3 message open. (E.g. add payload to the reset to +indicate low-level protocol features.) + +``tls-crypt-v2`` uses fixed crypto algorithms, because: + + * The crypto is used before we can do any negotiation, so the algorithms have + to be predefined. + * The crypto primitives are chosen conservatively, making problems with these + primitives unlikely. + * Making anything configurable adds complexity, both in implementation and + usage. We should not add any more complexity than is absolutely necessary. + +Potential ``tls-crypt-v2`` risks: + + * Slightly more work on first connection (``WKc`` unwrap + hard reset unwrap) + than with ``tls-crypt`` (hard reset unwrap) or ``tls-auth`` (hard reset auth). + * Flexible metadata allow mistakes + (So we should make it easy to do it right. Provide tooling to create client + keys based on cert serial + CA fingerprint, provide script that uses CRL (if + available) to drop revoked keys.)
Signature · 1 line
2.7.4
Re: [Openvpn-devel] [PATCH v7 2/7] tls-crypt-v2: add specification to doc/
Two typos only .. probably can be fixed on the fly
Quoted 53 lines · Steffan Karger
This is a preliminary description of tls-crypt-v2. It should give a good impression about the reasoning and design behind tls-crypt-v2, but might need some polishing and updating.
Signed-off-by Steffan Karger <[email protected]...>---
v3: Include length in WKc
v4: Clarify metadata handling
v5: Typo fixes (thanks tincanteksup)
v6: Change WKc length to ciphertext length (was plaintext), textual fixes
v7: Textual fixes irt reviewdoc/tls-crypt-v2.txt | 189 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+)create mode 100644
doc/tls-crypt-v2.txtdoc/tls-crypt-v2.txt new file +31
-0@@ -0,0 +1,189 @@ +Client-specific tls-crypt keys (--tls-crypt-v2) +=============================================== + +This document describes the ``--tls-crypt-v2`` option, which enables OpenVPN +to use client-specific ``--tls-crypt`` keys. + +Rationale +--------- + +``--tls-auth`` and ``tls-crypt`` use a pre-shared group key, which is shared +among all clients and servers in an OpenVPN deployment. If any client or +server is compromised, the attacker will have access to this shared key, and it +will no longer provide any security. To reduce the risk of losing pre-shared +keys, ``tls-crypt-v2`` adds the ability to supply each client with a unique +tls-crypt key. This allows large organisations and VPN providers to profit +from the same DoS and TLS stack protection that small deployments can already +achieve using ``tls-auth`` or ``tls-crypt``. + +Also, for ``tls-crypt``, even if all these peers succeed in keeping the key +secret, the key lifetime is limited to roughly 8000 years, divided by the +number of clients (see the ``--tls-crypt`` section of the man page). Using +client-specific keys, we lift this lifetime requirement to roughly 8000 years +for each client key (which "Should Be Enough For Everybody (tm)"). + + +Introduction +------------ + +``tls-crypt-v2`` uses an encrypted cookie mechanism to introduce +client-specific tls-crypt keys without introducing a lot of server-side state. +The client-specific key is encrypted using a server key. The server key is the
doc/tls-crypt-v2.txt line 41
Quoted 10 lines
doc/tls-crypt-v2.txt new file +10
-0+same for all servers in a group. When a client connects, it first sends the +encrypted key to the server, such that the server can decrypt the key and all +messages can thereafter be encrypted using the client-specific key. + +A wrapped (encrypted and authenticated) client-specific key can also contain +metadata. The metadata is wrapped together with the key, and can be used to +allow servers to identify clients and/or key validity. This allows the server +to abort the connection immediately after receiving the first packet, rather +than performing an entire TLS handshake. Aborting the connection this early +greatly improves the DoS resilience and reduces attack service against
"attack surface"
Quoted 16 lines
doc/tls-crypt-v2.txt new file +16
-0+malicious clients that have the ``tls-crypt`` or ``tls-auth`` key. This is +particularly relevant for large deployments (think lost key or disgruntled +employee) and VPN providers (clients are not trusted). + +To allow for a smooth transition, ``tls-crypt-v2`` is designed such that a +server can enable both ``tls-crypt-v2`` and either ``tls-crypt`` or +``tls-auth``. This is achieved by introducing a P_CONTROL_HARD_RESET_CLIENT_V3 +opcode, that indicates that the client wants to use ``tls-crypt-v2`` for the +current connection. + +For an exact specification and more details, read the Implementation section. + + +Implementation +-------------- +
doc/tls-crypt-v2.txt line 67
Quoted 10 lines
doc/tls-crypt-v2.txt new file +10
-0+When setting up a tls-crypt-v2 group (similar to generating a tls-crypt or +tls-auth key previously): + +1. Generate a tls-crypt-v2 server key using OpenVPN's ``--genkey``. This key + contains 2 512-bit keys, of which we use: + + * the first 256 bits of key 1 as AES-256-CTR encryption key ``Ke`` + * the first 256 bits of key 2 as HMAC-SHA-256 authentication key ``Ka`` + + This fomat is similar to the format for regular ``tls-crypt``/``tls-auth``
fomat -> format
Quoted 123 lines
doc/tls-crypt-v2.txt new file +122
-0+ and data channel keys, which allows us to reuse code. + +2. Add the tls-crypt-v2 server key to all server configs + (``tls-crypt-v2 /path/to/server.key``) + + +When provisioning a client, create a client-specific tls-crypt key: + +1. Generate 2048 bits client-specific key ``Kc`` + +2. Optionally generate metadata + + The first byte of the metadata determines the type. The initial + implementation supports the following types: + + 0x00 (USER): User-defined free-form data. + 0x01 (TIMESTAMP): 64-bit network order unix timestamp of key generation. + + The timestamp can be used to reject too-old tls-crypt-v2 client keys. + + User metadata could for example contain the users certificate serial, such + that the incoming connection can be verified against a CRL. + + If no metadata is supplied during key generation, openvpn defaults to the + TIMESTAMP metadata type. + +3. Create a wrapped client key ``WKc``, using the same nonce-misuse-resistant + SIV construction we use for tls-crypt: + + ``len = len(WKc)`` (16 bit, network byte order) + + ``T = HMAC-SHA256(Ka, len || Kc || metadata)`` + + ``IV = 128 most significant bits of T`` + + ``WKc = T || AES-256-CTR(Ke, IV, Kc || metadata) || len`` + + Note that the length of ``WKc`` can be computed before composing ``WKc``, + because the length of each component is known (and AES-256-CTR does not add + any padding). + +4. Create a tls-crypt-v2 client key: PEM-encode ``Kc || WKc`` and store in a + file, using the header ``-----BEGIN OpenVPN tls-crypt-v2 client key-----`` + and the footer ``-----END OpenVPN tls-crypt-v2 client key-----``. (The PEM + format is simple, and following PEM allows us to use the crypto lib function + for en/decoding.) + +5. Add the tls-crypt-v2 client key to the client config + (``tls-crypt-v2 /path/to/client-specific.key``) + + +When setting up the openvpn connection: + +1. The client reads the tls-crypt-v2 key from its config, and: + + 1. loads ``Kc`` as its tls-crypt key, + 2. stores ``WKc`` in memory for sending to the server. + +2. To start the connection, the client creates a P_CONTROL_HARD_RESET_CLIENT_V3 + message, wraps it with tls-crypt using ``Kc`` as the key, and appends + ``WKc``. (``WKc`` must not be encrypted, to prevent a chicken-and-egg + problem.) + +3. The server receives the P_CONTROL_HARD_RESET_CLIENT_V3 message, and + + 1. reads the WKc length field from the end of the message, and extracts WKc + from the message + 2. unwraps ``WKc`` + 3. uses unwrapped ``Kc`` to verify the remaining + P_CONTROL_HARD_RESET_CLIENT_V3 message's (encryption and) authentication. + + The message is dropped and no error response is sent when either 3.1, 3.2 or + 3.3 fails (DoS protection). + +4. Server optionally checks metadata using a --tls-crypt-v2-verify script + + This allows early abort of connection, *before* we expose any of the + notoriously dangerous TLS, X.509 and ASN.1 parsers and thereby reduces the + attack surface of the server. + + The metadata is checked *after* the OpenVPN three-way handshake has + completed, to prevent DoS attacks. (That is, once the client has proved to + the server that it possesses Kc, by authenticating a packet that contains the + session ID picked by the server.) + + A server should not send back any error messages if metadata verification + fails, to reduce attack surface and maximize DoS resilience. + +6. Client and server use ``Kc`` for (un)wrapping any following control channel + messages. + + +Considerations +-------------- + +To allow for a smooth transition, the server implementation allows +``tls-crypt`` or ``tls-auth`` to be used simultaneously with ``tls-crypt-v2``. +This specification does not allow simultaneously using ``tls-crypt-v2`` and +connections without any control channel wrapping, because that would break DoS +resilience. + +WKc includes a length field, so we leave the option for future extension of the +P_CONTROL_HEAD_RESET_CLIENT_V3 message open. (E.g. add payload to the reset to +indicate low-level protocol features.) + +``tls-crypt-v2`` uses fixed crypto algorithms, because: + + * The crypto is used before we can do any negotiation, so the algorithms have + to be predefined. + * The crypto primitives are chosen conservatively, making problems with these + primitives unlikely. + * Making anything configurable adds complexity, both in implementation and + usage. We should not add any more complexity than is absolutely necessary. + +Potential ``tls-crypt-v2`` risks: + + * Slightly more work on first connection (``WKc`` unwrap + hard reset unwrap) + than with ``tls-crypt`` (hard reset unwrap) or ``tls-auth`` (hard reset auth). + * Flexible metadata allow mistakes + (So we should make it easy to do it right. Provide tooling to create client + keys based on cert serial + CA fingerprint, provide script that uses CRL (if + available) to drop revoked keys.)
Re: [Openvpn-devel] [PATCH v7 2/7] tls-crypt-v2: add specification to doc/
In reply to Steffan KargerHi,
one little typ0 and one addition below:
Quoted 73 lines · Steffan Karger
This is a preliminary description of tls-crypt-v2. It should give a good impression about the reasoning and design behind tls-crypt-v2, but might need some polishing and updating.
Signed-off-by Steffan Karger <[email protected]...>---
v3: Include length in WKc
v4: Clarify metadata handling
v5: Typo fixes (thanks tincanteksup)
v6: Change WKc length to ciphertext length (was plaintext), textual fixes
v7: Textual fixes irt reviewdoc/tls-crypt-v2.txt | 189 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 doc/tls-crypt-v2.txtdoc/tls-crypt-v2.txt new file +51
-0@@ -0,0 +1,189 @@ +Client-specific tls-crypt keys (--tls-crypt-v2) +=============================================== + +This document describes the ``--tls-crypt-v2`` option, which enables OpenVPN +to use client-specific ``--tls-crypt`` keys. + +Rationale +--------- + +``--tls-auth`` and ``tls-crypt`` use a pre-shared group key, which is shared +among all clients and servers in an OpenVPN deployment. If any client or +server is compromised, the attacker will have access to this shared key, and it +will no longer provide any security. To reduce the risk of losing pre-shared +keys, ``tls-crypt-v2`` adds the ability to supply each client with a unique +tls-crypt key. This allows large organisations and VPN providers to profit +from the same DoS and TLS stack protection that small deployments can already +achieve using ``tls-auth`` or ``tls-crypt``. + +Also, for ``tls-crypt``, even if all these peers succeed in keeping the key +secret, the key lifetime is limited to roughly 8000 years, divided by the +number of clients (see the ``--tls-crypt`` section of the man page). Using +client-specific keys, we lift this lifetime requirement to roughly 8000 years +for each client key (which "Should Be Enough For Everybody (tm)"). + + +Introduction +------------ + +``tls-crypt-v2`` uses an encrypted cookie mechanism to introduce +client-specific tls-crypt keys without introducing a lot of server-side state. +The client-specific key is encrypted using a server key. The server key is the +same for all servers in a group. When a client connects, it first sends the +encrypted key to the server, such that the server can decrypt the key and all +messages can thereafter be encrypted using the client-specific key. + +A wrapped (encrypted and authenticated) client-specific key can also contain +metadata. The metadata is wrapped together with the key, and can be used to +allow servers to identify clients and/or key validity. This allows the server +to abort the connection immediately after receiving the first packet, rather +than performing an entire TLS handshake. Aborting the connection this early +greatly improves the DoS resilience and reduces attack service against +malicious clients that have the ``tls-crypt`` or ``tls-auth`` key. This is +particularly relevant for large deployments (think lost key or disgruntled +employee) and VPN providers (clients are not trusted). + +To allow for a smooth transition, ``tls-crypt-v2`` is designed such that a +server can enable both ``tls-crypt-v2`` and either ``tls-crypt`` or +``tls-auth``. This is achieved by introducing a P_CONTROL_HARD_RESET_CLIENT_V3 +opcode, that indicates that the client wants to use ``tls-crypt-v2`` for the +current connection. +
doc/tls-crypt-v2.txt line 61
Quoted 10 lines
doc/tls-crypt-v2.txt new file +10
-0+For an exact specification and more details, read the Implementation section. + + +Implementation +-------------- + +When setting up a tls-crypt-v2 group (similar to generating a tls-crypt or +tls-auth key previously): + +1. Generate a tls-crypt-v2 server key using OpenVPN's ``--genkey``. This key
typ0:
``--genkey`` should be ``--tls-crypt-v2-genkey server``
Quoted 5 lines
doc/tls-crypt-v2.txt new file +5
-0+ contains 2 512-bit keys, of which we use: + + * the first 256 bits of key 1 as AES-256-CTR encryption key ``Ke`` + * the first 256 bits of key 2 as HMAC-SHA-256 authentication key ``Ka`` +
doc/tls-crypt-v2.txt line 76
Quoted 10 lines
doc/tls-crypt-v2.txt new file +10
-0+ This fomat is similar to the format for regular ``tls-crypt``/``tls-auth`` + and data channel keys, which allows us to reuse code. + +2. Add the tls-crypt-v2 server key to all server configs + (``tls-crypt-v2 /path/to/server.key``) + + +When provisioning a client, create a client-specific tls-crypt key: + +1. Generate 2048 bits client-specific key ``Kc``
I would add something like the paragraph about the server key:
... using OpenVPN's ``--tls-crypt-v2-genkey client``
Quoted 104 lines
doc/tls-crypt-v2.txt new file +103
-0+ +2. Optionally generate metadata + + The first byte of the metadata determines the type. The initial + implementation supports the following types: + + 0x00 (USER): User-defined free-form data. + 0x01 (TIMESTAMP): 64-bit network order unix timestamp of key generation. + + The timestamp can be used to reject too-old tls-crypt-v2 client keys. + + User metadata could for example contain the users certificate serial, such + that the incoming connection can be verified against a CRL. + + If no metadata is supplied during key generation, openvpn defaults to the + TIMESTAMP metadata type. + +3. Create a wrapped client key ``WKc``, using the same nonce-misuse-resistant + SIV construction we use for tls-crypt: + + ``len = len(WKc)`` (16 bit, network byte order) + + ``T = HMAC-SHA256(Ka, len || Kc || metadata)`` + + ``IV = 128 most significant bits of T`` + + ``WKc = T || AES-256-CTR(Ke, IV, Kc || metadata) || len`` + + Note that the length of ``WKc`` can be computed before composing ``WKc``, + because the length of each component is known (and AES-256-CTR does not add + any padding). + +4. Create a tls-crypt-v2 client key: PEM-encode ``Kc || WKc`` and store in a + file, using the header ``-----BEGIN OpenVPN tls-crypt-v2 client key-----`` + and the footer ``-----END OpenVPN tls-crypt-v2 client key-----``. (The PEM + format is simple, and following PEM allows us to use the crypto lib function + for en/decoding.) + +5. Add the tls-crypt-v2 client key to the client config + (``tls-crypt-v2 /path/to/client-specific.key``) + + +When setting up the openvpn connection: + +1. The client reads the tls-crypt-v2 key from its config, and: + + 1. loads ``Kc`` as its tls-crypt key, + 2. stores ``WKc`` in memory for sending to the server. + +2. To start the connection, the client creates a P_CONTROL_HARD_RESET_CLIENT_V3 + message, wraps it with tls-crypt using ``Kc`` as the key, and appends + ``WKc``. (``WKc`` must not be encrypted, to prevent a chicken-and-egg + problem.) + +3. The server receives the P_CONTROL_HARD_RESET_CLIENT_V3 message, and + + 1. reads the WKc length field from the end of the message, and extracts WKc + from the message + 2. unwraps ``WKc`` + 3. uses unwrapped ``Kc`` to verify the remaining + P_CONTROL_HARD_RESET_CLIENT_V3 message's (encryption and) authentication. + + The message is dropped and no error response is sent when either 3.1, 3.2 or + 3.3 fails (DoS protection). + +4. Server optionally checks metadata using a --tls-crypt-v2-verify script + + This allows early abort of connection, *before* we expose any of the + notoriously dangerous TLS, X.509 and ASN.1 parsers and thereby reduces the + attack surface of the server. + + The metadata is checked *after* the OpenVPN three-way handshake has + completed, to prevent DoS attacks. (That is, once the client has proved to + the server that it possesses Kc, by authenticating a packet that contains the + session ID picked by the server.) + + A server should not send back any error messages if metadata verification + fails, to reduce attack surface and maximize DoS resilience. + +6. Client and server use ``Kc`` for (un)wrapping any following control channel + messages. + + +Considerations +-------------- + +To allow for a smooth transition, the server implementation allows +``tls-crypt`` or ``tls-auth`` to be used simultaneously with ``tls-crypt-v2``. +This specification does not allow simultaneously using ``tls-crypt-v2`` and +connections without any control channel wrapping, because that would break DoS +resilience. + +WKc includes a length field, so we leave the option for future extension of the +P_CONTROL_HEAD_RESET_CLIENT_V3 message open. (E.g. add payload to the reset to +indicate low-level protocol features.) + +``tls-crypt-v2`` uses fixed crypto algorithms, because: + + * The crypto is used before we can do any negotiation, so the algorithms have + to be predefined. + * The crypto primitives are chosen conservatively, making problems with these + primitives unlikely. + * Making anything configurable adds complexity, both in implementation and
doc/tls-crypt-v2.txt line 189
Quoted 10 lines
doc/tls-crypt-v2.txt new file +10
-0+ usage. We should not add any more complexity than is absolutely necessary. + +Potential ``tls-crypt-v2`` risks: + + * Slightly more work on first connection (``WKc`` unwrap + hard reset unwrap) + than with ``tls-crypt`` (hard reset unwrap) or ``tls-auth`` (hard reset auth). + * Flexible metadata allow mistakes + (So we should make it easy to do it right. Provide tooling to create client + keys based on cert serial + CA fingerprint, provide script that uses CRL (if + available) to drop revoked keys.)
I hope they can be fixed on the fly. Other than that:
Signature · 1 line
Antonio Quartulli
PATCH v7 3/7 tls-crypt-v2: generate tls-crypt-v2 keys
In reply to Steffan KargerAs a first step towards a full tls-crypt-v2 implementation, add functionality to generate tls-crypt-v2 client and server keys.
---
v3: Include length in WKc
v4: Fix option verification (use ce->tls_*, not options->ce.tls_*)
v5: Rebase on patch set v5
v6:
- Reword commit message
- Fix base64 length calculation
- Change WKc length to ciphertext length (instead of plaintext length)
v7: fix cast style (no space between cast and variable)
doc/openvpn.8 | 51 +++++++++ src/openvpn/base64.h | 4 + src/openvpn/init.c | 33 +++++- src/openvpn/integer.h | 10 ++ src/openvpn/options.c | 69 +++++++++++- src/openvpn/options.h | 14 +++ src/openvpn/tls_crypt.c | 290 ++++++++++++++++++++++++++++++++++++++++++++++++ src/openvpn/tls_crypt.h | 83 ++++++++++++-- tests/t_lpback.sh | 40 ++++++- 9 files changed, 574 insertions(+), 20 deletions(-)
doc/openvpn.8 +51 -0
@@ -5262,6 +5262,57 @@ degrading to the same security as using That is, the control channel still benefits from the extra protection against active man\-in\-the\-middle\-attacks and DoS attacks, but may no longer offer extra privacy and post\-quantum security on top of what TLS itself offers. + +For large setups or setups where clients are not trusted, consider using +.B \-\-tls\-crypt\-v2 +instead. That uses per\-client unique keys, and thereby improves the bounds to +\fR'rotate a client key at least once per 8000 years'. +.\"********************************************************* +.TP +.B \-\-tls\-crypt\-v2 keyfile + +Use client\-specific tls\-crypt keys. + +For clients, +.B keyfile +is a client\-specific tls\-crypt key. Such a key can be generated using the +.B \-\-tls\-crypt\-v2\-genkey +option. + +For servers, +.B keyfile +is used to unwrap client\-specific keys supplied by the client during connection +setup. This key must be the same as the key used to generate the +client\-specific key (see +.B \-\-tls\-crypt\-v2\-genkey\fR). + +On servers, this option can be used together with the +.B \-\-tls\-auth +or +.B \-\-tls\-crypt +option. In that case, the server will detect whether the client is using +client\-specific keys, and automatically select the right mode. +.\"********************************************************* +.TP +.B \-\-tls\-crypt\-v2\-genkey client|server keyfile [metadata] + +If the first parameter equals "server", generate a \-\-tls\-crypt\-v2 server +key and store the key in +.B keyfile\fR. + + +If the first parameter equals "client", generate a \-\-tls\-crypt\-v2 client +key, and store the key in +.B keyfile\fR. + +If supplied, include the supplied +.B metadata +in the wrapped client key. This metadata must be supplied in base64\-encoded +form. The metadata must be at most 735 bytes long (980 bytes in base64). + +.B TODO +Metadata handling is not yet implemented. This text will be updated by the +commit that introduces metadata handling. .\"********************************************************* .TP .B \-\-askpass [file]
src/openvpn/base64.h +4 -0
@@ -34,6 +34,10 @@#ifndef _BASE64_H_#define _BASE64_H_ +/** Compute resulting base64 length. 6 bits per byte, padded to 4 bytes. */ +#define OPENVPN_BASE64_LENGTH (binary_length) \ + ((((8 * binary_length) / 6) + 3) & ~3) +int openvpn_base64_encode (const void *data,int size,char **str);int openvpn_base64_decode (const char *str,void *data,int size);
src/openvpn/init.c +28 -5
@@ -1052,6 +1052,11 @@ print_openssl_info(const struct options *options)bool do_genkey (const struct options *options) { +/* should we disable paging? */ +if (options->mlock && (options->genkey || options->tls_crypt_v2_genkey_file)) + { +platform_mlockall (true); + }if (options->genkey) {int nbits_written;
@@ -1059,11 +1064,6 @@ do_genkey(const struct options *options)notnull (options->shared_secret_file,"shared secret output file (--secret)" ); -if (options->mlock)/* should we disable paging? */ - { -platform_mlockall (true); - } - nbits_written =write_key_file (2 , options->shared_secret_file);if (nbits_written <0 ) {
@@ -1075,6 +1075,29 @@ do_genkey(const struct options *options) options->shared_secret_file);return true; } +if (options->tls_crypt_v2_genkey_type) + { +if (!strcmp (options->tls_crypt_v2_genkey_type,"server" )) + { +tls_crypt_v2_write_server_key_file (options->tls_crypt_v2_genkey_file); +return true; + } +if (options->tls_crypt_v2_genkey_type + && !strcmp (options->tls_crypt_v2_genkey_type,"client" )) + { +if (!options->tls_crypt_v2_file) + { +msg (M_USAGE ,"--tls-crypt-v2-gen-client-key requires a server key to be set via --tls-crypt-v2" ); + } + +tls_crypt_v2_write_client_key_file (options->tls_crypt_v2_genkey_file, + options->tls_crypt_v2_metadata, options->tls_crypt_v2_file, + options->tls_crypt_v2_inline); +return true; + } + +msg (M_USAGE ,"--tls-crypt-v2-genkey type should be \"client\" or \"server\"" ); + }return false; }
src/openvpn/integer.h +10 -0
@@ -26,6 +26,16 @@#include "error.h" +#ifndef htonll +#define htonll (x) ((1==htonl(1)) ? (x) : \ + ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32)) +#endif + +#ifndef ntohll +#define ntohll (x) ((1==ntohl(1)) ? (x) : \ + ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32)) +#endif +/* * min/max functions */
src/openvpn/options.c +65 -4
128 lines not on this page · raw message
src/openvpn/options.h +14 -0
@@ -139,6 +139,11 @@ struct connection_entry/* Shared secret used for TLS control channel authenticated encryption */ const char *tls_crypt_file;const char *tls_crypt_inline; + +/* Client-specific secret or server key used for TLS control channel +* authenticated encryption v2 */ +const char *tls_crypt_v2_file; +const char *tls_crypt_v2_inline; };struct remote_entry
@@ -577,6 +582,15 @@ struct optionsconst char *tls_crypt_file;const char *tls_crypt_inline; +/* Client-specific secret or server key used for TLS control channel +* authenticated encryption v2 */ +const char *tls_crypt_v2_file; +const char *tls_crypt_v2_inline; + +const char *tls_crypt_v2_genkey_type; +const char *tls_crypt_v2_genkey_file; +const char *tls_crypt_v2_metadata; +/* Allow only one session */ bool single_session;
src/openvpn/tls_crypt.c +290 -0
304 lines not on this page · raw message
src/openvpn/tls_crypt.h +75 -8
136 lines not on this page · raw message
tests/t_lpback.sh +37 -3
@@ -21,8 +21,8 @@ set -eu top_builddir="${top_builddir:-..}" -trap "rm -f key.$$ log.$$ ; trap 0 ; exit 77" 1 2 15 -trap "rm -f key.$$ log.$$ ; exit 1" 0 3 +trap "rm -f key.$$ tc-server-key.$$ tc-client-key.$$ log.$$ ; trap 0 ; exit 77" 1 2 15 +trap "rm -f key.$$ tc-server-key.$$ tc-client-key.$$ log.$$ ; exit 1" 0 3 # Get list of supported ciphers from openvpn --show-ciphers output CIPHERS=$(${top_builddir}/src/openvpn/openvpn --show-ciphers | \
@@ -55,6 +55,40 @@ do fi done -rm key.$$ log.$$ +echo -n "Testing tls-crypt-v2 server key generation..." +"${top_builddir}/src/openvpn/openvpn" \ + --tls-crypt-v2-genkey server tc-server-key.$$ >log.$$ 2>&1 +if [ $? != 0 ] ; then + echo "FAILED" + cat log.$$ + e=1 +else + echo "OK" +fi + +echo -n "Testing tls-crypt-v2 key generation (no metadata)..." +"${top_builddir}/src/openvpn/openvpn" --tls-crypt-v2 tc-server-key.$$ \ + --tls-crypt-v2-genkey client tc-client-key.$$ >log.$$ 2>&1 +if [ $? != 0 ] ; then + echo "FAILED" + cat log.$$ + e=1 +else + echo "OK" +fi + +echo -n "Testing tls-crypt-v2 key generation (max length metadata)..." +"${top_builddir}/src/openvpn/openvpn" --tls-crypt-v2 tc-server-key.$$ \ + --tls-crypt-v2-genkey client tc-client-key.$$ \ + $(head -c732 /dev/zero | base64 -w0) >log.$$ 2>&1 +if [ $? != 0 ] ; then + echo "FAILED" + cat log.$$ + e=1 +else + echo "OK" +fi + +rm key.$$ tc-server-key.$$ tc-client-key.$$ log.$$ trap 0 exit $e
Signature · 1 line
2.7.4
Re: [Openvpn-devel] [PATCH v7 3/7] tls-crypt-v2: generate tls-crypt-v2 keys
Hi,
Quoted 4 lines · Steffan Karger
As a first step towards a full tls-crypt-v2 implementation, add functionality to generate tls-crypt-v2 client and server keys.
Signed-off-by Steffan Karger <[email protected]...>
Signature · 1 line
Antonio Quartulli
PATCH v7 4/7 tls-crypt-v2: add unwrap_client_key
In reply to Steffan KargerAdd helper functions to unwrap tls-crypt-v2 client keys.
---
v3: Include length in WKc
v4: Rebase on v4 patch set
v5: Rebase on v5 patch set
v6: Change WKc length to ciphertext length (was plaintext)
v7: rebase on patch set v7
src/openvpn/buffer.h | 7 + src/openvpn/tls_crypt.c | 121 ++++++++++++++ tests/unit_tests/openvpn/test_tls_crypt.c | 254 +++++++++++++++++++++++++++--- 3 files changed, 362 insertions(+), 20 deletions(-)
src/openvpn/buffer.h +7 -0
@@ -837,6 +837,13 @@ buf_read_u32(struct buffer *buf, bool *good) } } +/** Return true if buffer contents are equal */ +static inline bool +buf_equal (const struct buffer *a,const struct buffer *b) +{ +return BLEN (a) ==BLEN (b) &&0 ==memcmp (BPTR (a),BPTR (b),BLEN (a)); +} +/** * Compare src buffer contents with match. * *NOT* constant time. Do not use when comparing HMACs.
src/openvpn/tls_crypt.c +121 -0
133 lines not on this page · raw message
tests/unit_tests/openvpn/test_tls_crypt.c +234 -20
335 lines not on this page · raw message
Signature · 1 line
2.7.4
Re: [Openvpn-devel] [PATCH v7 4/7] tls-crypt-v2: add unwrap_client_key
Hi,
Quoted 3 lines · Steffan Karger
Add helper functions to unwrap tls-crypt-v2 client keys.
Signed-off-by Steffan Karger <[email protected]...>
Signature · 1 line
Antonio Quartulli
PATCH v7 5/7 tls-crypt-v2: add P_CONTROL_HARD_RESET_CLIENT_V3 opcode
In reply to Steffan KargerNot used yet, but prepare for sending and receiving tls-crypt-v2 handshake messages.
---
v3: rebase on curent master / v3 patch set
v4: rebase on v4 patch set
v5: rebase on v5 patch set
v6: rebase on v6 patch set
v7: rebase on v7 patch set
src/openvpn/ps.c | 3 ++- src/openvpn/ssl.c | 23 ++++++++++++++++++----- src/openvpn/ssl.h | 5 ++++- src/openvpn/ssl_common.h | 2 ++ 4 files changed, 26 insertions(+), 7 deletions(-)
src/openvpn/ps.c +2 -1
@@ -985,7 +985,8 @@ is_openvpn_protocol(const struct buffer *buf) {return p[0 ] ==0 && p[1 ] >=14 - && p[2 ] == (P_CONTROL_HARD_RESET_CLIENT_V2 <<P_OPCODE_SHIFT ); + && (p[2 ] == (P_CONTROL_HARD_RESET_CLIENT_V2 <<P_OPCODE_SHIFT ) + || p[2 ] == (P_CONTROL_HARD_RESET_CLIENT_V3 <<P_OPCODE_SHIFT )); } else if (len >= 2) {
src/openvpn/ssl.c +18 -5
@@ -785,6 +785,9 @@ packet_opcode_name(int op)case P_CONTROL_HARD_RESET_SERVER_V2 :return "P_CONTROL_HARD_RESET_SERVER_V2" ; +case P_CONTROL_HARD_RESET_CLIENT_V3 : +return "P_CONTROL_HARD_RESET_CLIENT_V3" ; +case P_CONTROL_SOFT_RESET_V1 :return "P_CONTROL_SOFT_RESET_V1" ;
@@ -857,7 +860,8 @@ is_hard_reset(int op, int key_method)if (!key_method || key_method >=2 ) { -if (op ==P_CONTROL_HARD_RESET_CLIENT_V2 || op ==P_CONTROL_HARD_RESET_SERVER_V2 ) +if (op ==P_CONTROL_HARD_RESET_CLIENT_V2 || op ==P_CONTROL_HARD_RESET_SERVER_V2 + || op ==P_CONTROL_HARD_RESET_CLIENT_V3 ) {return true; }
@@ -1088,8 +1092,15 @@ tls_session_init(struct tls_multi *multi, struct tls_session *session) }else /* session->opt->key_method >= 2 */ { - session->initial_opcode = session->opt->server ? -P_CONTROL_HARD_RESET_SERVER_V2 :P_CONTROL_HARD_RESET_CLIENT_V2 ; +if (session->opt->server) + { + session->initial_opcode =P_CONTROL_HARD_RESET_SERVER_V2 ; + } +else + { + session->initial_opcode = session->opt->tls_crypt_v2 ? +P_CONTROL_HARD_RESET_CLIENT_V3 :P_CONTROL_HARD_RESET_CLIENT_V2 ; + } }/* Initialize control channel authentication parameters */
@@ -3420,7 +3431,8 @@ tls_pre_decrypt(struct tls_multi *multi, {/* verify client -> server or server -> client connection */ if (((op ==P_CONTROL_HARD_RESET_CLIENT_V1 - || op ==P_CONTROL_HARD_RESET_CLIENT_V2 ) && !multi->opt.server) + || op ==P_CONTROL_HARD_RESET_CLIENT_V2 + || op ==P_CONTROL_HARD_RESET_CLIENT_V3 ) && !multi->opt.server) || ((op ==P_CONTROL_HARD_RESET_SERVER_V1 || op ==P_CONTROL_HARD_RESET_SERVER_V2 ) && multi->opt.server)) {
@@ -3805,7 +3817,8 @@ tls_pre_decrypt_lite(const struct tls_auth_standalone *tas,/* this packet is from an as-yet untrusted source, so * scrutinize carefully */ -if (op !=P_CONTROL_HARD_RESET_CLIENT_V2 ) +if (op !=P_CONTROL_HARD_RESET_CLIENT_V2 + && op !=P_CONTROL_HARD_RESET_CLIENT_V3 ) {/* * This can occur due to bogus data or DoS packets.
src/openvpn/ssl.h +4 -1
@@ -63,9 +63,12 @@#define P_CONTROL_HARD_RESET_CLIENT_V2 7/* initial key from client, forget previous state */ #define P_CONTROL_HARD_RESET_SERVER_V2 8/* initial key from server, forget previous state */ +/* indicates key_method >= 2 and client-specific tls-crypt key */ +#define P_CONTROL_HARD_RESET_CLIENT_V3 10/* initial key from client, forget previous state */ +/* define the range of legal opcodes */ #define P_FIRST_OPCODE 1 -#define P_LAST_OPCODE 9 +#define P_LAST_OPCODE 10/* * Set the max number of acknowledgments that can "hitch a ride" on an outgoing
src/openvpn/ssl_common.h +2 -0
@@ -286,6 +286,8 @@ struct tls_optionsconst char *config_authname;bool ncp_enabled; +bool tls_crypt_v2; +/** TLS handshake wrapping state */ struct tls_wrap_ctx tls_wrap;
Signature · 1 line
2.7.4
Re: [Openvpn-devel] [PATCH v7 5/7] tls-crypt-v2: add P_CONTROL_HARD_RESET_CLIENT_V3 opcode
Hi,
Quoted 4 lines · Steffan Karger
Not used yet, but prepare for sending and receiving tls-crypt-v2 handshake messages.
Signed-off-by Steffan Karger <[email protected]...>
Signature · 1 line
Antonio Quartulli
PATCH v7 6/7 tls-crypt-v2: implement tls-crypt-v2 handshake
In reply to Steffan KargerThis makes clients send-and-use, and servers receive-unwrap-and-use tls-crypt-v2 client keys, which completes the on-the-wire work.
---
v3: include length in WKc, rebase on curent master / v3 patch set
v4: resolve merge conflict (fixes memory leak)
v5: rebase on v5 patch set
v6: rebase on v6 patch set
v7: rebase on v7 patch set
src/openvpn/init.c | 39 ++++++++++++++- src/openvpn/openvpn.h | 2 + src/openvpn/ssl.c | 79 ++++++++++++++++++++++++------- src/openvpn/ssl_common.h | 6 +++ src/openvpn/tls_crypt.c | 57 ++++++++++++++++++++++ src/openvpn/tls_crypt.h | 14 ++++++ tests/unit_tests/openvpn/test_tls_crypt.c | 6 +++ 7 files changed, 186 insertions(+), 17 deletions(-)
src/openvpn/init.c +38 -1
@@ -2464,6 +2464,7 @@ key_schedule_free(struct key_schedule *ks, bool free_ssl_ctx)if (tls_ctx_initialised (&ks->ssl_ctx) && free_ssl_ctx) {tls_ctx_free (&ks->ssl_ctx); +free_key_ctx (&ks->tls_crypt_v2_server_key); }CLEAR (*ks); }
@@ -2647,6 +2648,24 @@ do_init_crypto_tls_c1(struct context *c)/* initialize tls-auth/crypt key */ do_init_tls_wrap_key (c); +/* tls-crypt with client-specific keys (--tls-crypt-v2) */ +if (options->tls_crypt_v2_file) + { +if (options->tls_server) + { +tls_crypt_v2_init_server_key (&c->c1.ks.tls_crypt_v2_server_key, + true, options->tls_crypt_v2_file, + options->tls_crypt_v2_inline); + } +else + { +tls_crypt_v2_init_client_key (&c->c1.ks.tls_wrap_key, + &c->c1.ks.tls_crypt_v2_wkc, + options->tls_crypt_v2_file, + options->tls_crypt_v2_inline); + } + } +#if 0 /* was: #if ENABLE_INLINE_FILES -- Note that enabling this code will break restarts */ if (options->priv_key_file_inline) {
@@ -2863,13 +2882,28 @@ do_init_crypto_tls(struct context *c, const unsigned int flags) }/* TLS handshake encryption (--tls-crypt) */ -if (options->ce.tls_crypt_file) +if (options->ce.tls_crypt_file + || (options->ce.tls_crypt_v2_file && options->tls_client)) { to.tls_wrap.mode =TLS_WRAP_CRYPT ; to.tls_wrap.opt.key_ctx_bi = c->c1.ks.tls_wrap_key; to.tls_wrap.opt.pid_persist = &c->c1.pid_persist; to.tls_wrap.opt.flags |=CO_PACKET_ID_LONG_FORM ;tls_crypt_adjust_frame_parameters (&to.frame); + +if (options->tls_crypt_v2_file) + { + to.tls_wrap.tls_crypt_v2_wkc = &c->c1.ks.tls_crypt_v2_wkc; + } + } + +if (options->tls_crypt_v2_file) + { + to.tls_crypt_v2 = true; +if (options->tls_server) + { + to.tls_wrap.tls_crypt_v2_server_key = c->c1.ks.tls_crypt_v2_server_key; + } }/* If we are running over TCP, allow for
@@ -3473,6 +3507,8 @@ do_close_free_key_schedule(struct context *c, bool free_ssl_ctx)*/ free_key_ctx_bi (&c->c1.ks.tls_wrap_key);CLEAR (c->c1.ks.tls_wrap_key); +buf_clear (&c->c1.ks.tls_crypt_v2_wkc); +free_buf (&c->c1.ks.tls_crypt_v2_wkc);if (!(c->sig->signal_received ==SIGUSR1 && c->options.persist_key)) {
@@ -4408,6 +4444,7 @@ inherit_context_child(struct context *dest, dest->c1.ks.ssl_ctx = src->c1.ks.ssl_ctx; dest->c1.ks.tls_wrap_key = src->c1.ks.tls_wrap_key; dest->c1.ks.tls_auth_key_type = src->c1.ks.tls_auth_key_type; + dest->c1.ks.tls_crypt_v2_server_key = src->c1.ks.tls_crypt_v2_server_key;/* inherit pre-NCP ciphers */ dest->c1.ciphername = src->c1.ciphername; dest->c1.authname = src->c1.authname;
src/openvpn/openvpn.h +2 -0
@@ -66,6 +66,8 @@ struct key_schedule/* optional TLS control channel wrapping */ struct key_type tls_auth_key_type;struct key_ctx_bi tls_wrap_key; +struct key_ctx tls_crypt_v2_server_key; +struct buffer tls_crypt_v2_wkc;/**< Wrapped client key */ };/*
src/openvpn/ssl.c +63 -16
126 lines not on this page · raw message
src/openvpn/ssl_common.h +6 -0
@@ -213,6 +213,12 @@ struct tls_wrap_ctx } mode;/**< Control channel wrapping mode */ struct crypto_options opt;/**< Crypto state */ struct buffer work;/**< Work buffer (only for --tls-crypt) */ +struct key_ctx tls_crypt_v2_server_key;/**< Decrypts client keys */ +const struct buffer *tls_crypt_v2_wkc;/**< Wrapped client key, +sent to server */ +struct buffer tls_crypt_v2_metadata;/**< Received from client */ +bool cleanup_key_ctx;/**< opt.key_ctx_bi is owned by +this context */ };/*
src/openvpn/tls_crypt.c +57 -0
69 lines not on this page · raw message
src/openvpn/tls_crypt.h +14 -0
@@ -84,6 +84,7 @@#include "buffer.h" #include "crypto.h" #include "session_id.h" +#include "ssl_common.h" #define TLS_CRYPT_TAG_SIZE (256/8)#define TLS_CRYPT_PID_SIZE (sizeof(packet_id_type) + sizeof(net_time_t))
@@ -184,6 +185,19 @@ void tls_crypt_v2_init_client_key(struct key_ctx_bi *key, const char *key_inline);/** +* Extract a tls-crypt-v2 client key from a P_CONTROL_HARD_RESET_CLIENT_V3 +* message, and load the key into the supplied tls wrap context. +* +* @param buf Buffer containing a received P_CONTROL_HARD_RESET_CLIENT_V3 +* message. +* @param ctx tls-wrap context to be initialized with the client key. +* +* @returns true if a key was successfully extracted. +*/ +bool tls_crypt_v2_extract_client_key (struct buffer *buf, +struct tls_wrap_ctx *ctx); + +/** * Generate a tls-crypt-v2 server key, and write to file. * * @param filename Filename of the server key file to create.
tests/unit_tests/openvpn/test_tls_crypt.c +6 -0
@@ -346,6 +346,12 @@ tls_crypt_v2_wrap_unwrap_max_metadata(void **state) {assert_true (0 ==memcmp (ctx->client_key2.keys, unwrapped_client_key2.keys,sizeof (ctx->client_key2.keys)));assert_true (buf_equal (&ctx->metadata, &unwrap_metadata)); + +struct tls_wrap_ctx wrap_ctx = { + .mode =TLS_WRAP_CRYPT , + .tls_crypt_v2_server_key = ctx->server_keys.encrypt, + }; +assert_true (tls_crypt_v2_extract_client_key (&ctx->wkc, &wrap_ctx)); }/**
Signature · 1 line
2.7.4
Re: [Openvpn-devel] [PATCH v7 6/7] tls-crypt-v2: implement tls-crypt-v2 handshake
Hi,
Quoted 4 lines · Steffan Karger
This makes clients send-and-use, and servers receive-unwrap-and-use tls-crypt-v2 client keys, which completes the on-the-wire work.
Signed-off-by Steffan Karger <[email protected]...>
Signature · 1 line
Antonio Quartulli
PATCH v7 7/7 tls-crypt-v2: add script hook to verify metadata
In reply to Steffan KargerTo allow rejecting incoming connections very early in the handshake, add a --tls-crypt-v2-verify option that allows administators to run an external command to verify the metadata from the client key. See doc/tls-crypt-v2.txt for more details.
Because of the extra dependencies, this requires adding a mock parse_line() to the tls-crypt unit tests. Also, this turns tls_wrap_free into a static inline function, so that we don't need to compile in ssl.c (and all of it's dependencies) with the unit tests.
---
v3: rebase on curent master / v3 patch set
v4: fix memory leak (metadata buffer was not free'd for tls_wrap_tmp)
v5: rebase on v5 patch set, textual fixes in man page
v6: fix memory leak in unit tests, code style fixes
v7: rebase on patch set v7
Changes.rst | 6 +++ doc/openvpn.8 | 35 ++++++++++++++-- src/openvpn/init.c | 1 + src/openvpn/options.c | 7 ++++ src/openvpn/options.h | 2 + src/openvpn/ssl.c | 34 +++++---------- src/openvpn/ssl.h | 18 ++++++++ src/openvpn/ssl_common.h | 1 + src/openvpn/tls_crypt.c | 69 ++++++++++++++++++++++++++++++- src/openvpn/tls_crypt.h | 3 +- tests/unit_tests/openvpn/Makefile.am | 12 ++++-- tests/unit_tests/openvpn/test_tls_crypt.c | 19 ++++++++- 12 files changed, 175 insertions(+), 32 deletions(-)
Changes.rst +6 -0
@@ -3,6 +3,12 @@ Overview of changes in 2.5 New features ------------ +Client-specific tls-crypt keys (``--tls-crypt-v2``) + ``tls-crypt-v2`` adds the ability to supply each client with a unique + tls-crypt key. This allows large organisations and VPN providers to profit + from the same DoS and TLS stack protection that small deployments can + already achieve using ``tls-auth`` or ``tls-crypt``. + ChaCha20-Poly1305 cipher support Added support for using the ChaCha20-Poly1305 cipher in the OpenVPN data channel.
doc/openvpn.8 +32 -3
@@ -5310,9 +5310,38 @@ If supplied, include the supplied in the wrapped client key. This metadata must be supplied in base64\-encoded form. The metadata must be at most 735 bytes long (980 bytes in base64). -.B TODO -Metadata handling is not yet implemented. This text will be updated by the -commit that introduces metadata handling. +If no metadata is supplied, OpenVPN will use a 64\-bit unix timestamp +representing the current time in UTC, encoded in network order, as metadata for +the generated key. + +Servers can use +.B \-\-tls\-crypt\-v2\-verify +to specify a metadata verification command. +.\"********************************************************* +.TP +.B \-\-tls\-crypt\-v2\-verify cmd + +Run command +.B cmd +to verify the metadata of the client\-specific tls\-crypt\-v2 key of a +connecting client. This allows server administrators to reject client +connections, before exposing the TLS stack (including the notoriously dangerous +X.509 and ASN.1 stacks) to the connecting client. + +OpenVPN supplies the following env vars to the command: +.RS +.IP \[bu] 2 +script_type is set to "tls\-crypt\-v2\-verify" +.IP \[bu] +metadata_type is set to "0" if the metadata was user supplied, or "1" if it's a +64\-bit unix timestamp representing the key creation time. +.IP \[bu] +metadata_file contains the filename of a temporary file that contains the client +metadata. +.RE + +.IP +The command can reject the connection by exiting with a non-zero exit code. .\"********************************************************* .TP .B \-\-askpass [file]
src/openvpn/init.c +1 -0
@@ -2903,6 +2903,7 @@ do_init_crypto_tls(struct context *c, const unsigned int flags)if (options->tls_server) { to.tls_wrap.tls_crypt_v2_server_key = c->c1.ks.tls_crypt_v2_server_key; + to.tls_crypt_v2_verify_script = c->options.tls_crypt_v2_verify_script; } }
src/openvpn/options.c +7 -0
@@ -629,6 +629,8 @@ static const char usage_message[] ="--tls-crypt-v2-genkey client|server keyfile [base64 metadata]: Generate a\n" " fresh tls-crypt-v2 client or server key, and store to\n" " keyfile. If supplied, include metadata in wrapped key.\n" +"--tls-crypt-v2-verify cmd : Run command cmd to verify the metadata of the\n" +" client-supplied tls-crypt-v2 client key\n" "--askpass [file]: Get PEM password from controlling tty before we daemonize.\n" "--auth-nocache : Don't cache --askpass or --auth-user-pass passwords.\n" "--crl-verify crl ['dir']: Check peer certificate against a CRL.\n"
@@ -8131,6 +8133,11 @@ add_option(struct options *options, options->tls_crypt_v2_metadata = p[3 ]; } } +else if (streq (p[0 ],"tls-crypt-v2-verify" ) && p[1 ] && !p[2 ]) + { +VERIFY_PERMISSION (OPT_P_GENERAL ); + options->tls_crypt_v2_verify_script = p[1 ]; + }else if (streq (p[0 ],"key-method" ) && p[1 ] && !p[2 ]) {int key_method;
src/openvpn/options.h +2 -0
@@ -591,6 +591,8 @@ struct optionsconst char *tls_crypt_v2_genkey_file;const char *tls_crypt_v2_metadata; +const char *tls_crypt_v2_verify_script; +/* Allow only one session */ bool single_session;
src/openvpn/ssl.c +11 -23
@@ -1048,23 +1048,6 @@ tls_session_user_pass_enabled(struct tls_session *session)/** @addtogroup control_processor * @{ */ -/** Free the elements of a tls_wrap_ctx structure */ -static void tls_wrap_free (struct tls_wrap_ctx *tls_wrap) -{ -if (packet_id_initialized (&tls_wrap->opt.packet_id)) - { -packet_id_free (&tls_wrap->opt.packet_id); - } - -if (tls_wrap->cleanup_key_ctx) - { -free_key_ctx_bi (&tls_wrap->opt.key_ctx_bi); - } - -free_buf (&tls_wrap->tls_crypt_v2_metadata); -free_buf (&tls_wrap->work); -} -/** @name Functions for initialization and cleanup of tls_session structures * @{ */
@@ -1534,14 +1517,15 @@ write_control_auth(struct tls_session *session,static bool read_control_auth (struct buffer *buf,struct tls_wrap_ctx *ctx, -const struct link_socket_actual *from) +const struct link_socket_actual *from, +const struct tls_options *opt) {struct gc_arena gc =gc_new ();bool ret = false;const uint8_t opcode = *(BPTR (buf)) >>P_OPCODE_SHIFT ;if (opcode ==P_CONTROL_HARD_RESET_CLIENT_V3 - && !tls_crypt_v2_extract_client_key (buf, ctx)) + && !tls_crypt_v2_extract_client_key (buf, ctx, opt)) { msg (D_TLS_ERRORS, "TLS Error: can not extract tls-crypt-v2 client key from %s",
@@ -3622,7 +3606,8 @@ tls_pre_decrypt(struct tls_multi *multi, goto error; } -if (!read_control_auth (buf, &session->tls_wrap, from)) +if (!read_control_auth (buf, &session->tls_wrap, from, + session->opt)) { goto error; }
@@ -3675,7 +3660,8 @@ tls_pre_decrypt(struct tls_multi *multi,if (op ==P_CONTROL_SOFT_RESET_V1 &&DECRYPT_KEY_ENABLED (multi, ks)) { -if (!read_control_auth (buf, &session->tls_wrap, from)) +if (!read_control_auth (buf, &session->tls_wrap, from, + session->opt)) { goto error; }
@@ -3696,7 +3682,8 @@ tls_pre_decrypt(struct tls_multi *multi, do_burst = true; } -if (!read_control_auth (buf, &session->tls_wrap, from)) +if (!read_control_auth (buf, &session->tls_wrap, from, + session->opt)) { goto error; }
@@ -3898,8 +3885,9 @@ tls_pre_decrypt_lite(const struct tls_auth_standalone *tas,bool status;/* HMAC test, if --tls-auth was specified */ - status =read_control_auth (&newbuf, &tls_wrap_tmp, from); + status =read_control_auth (&newbuf, &tls_wrap_tmp, from,NULL );free_buf (&newbuf); +free_buf (&tls_wrap_tmp.tls_crypt_v2_metadata);if (tls_wrap_tmp.cleanup_key_ctx) {free_key_ctx_bi (&tls_wrap_tmp.opt.key_ctx_bi);
src/openvpn/ssl.h +18 -0
@@ -527,6 +527,24 @@ bool tls_item_in_cipher_list(const char *item, const char *list);* inline functions */ +/** Free the elements of a tls_wrap_ctx structure */ +static inline void +tls_wrap_free (struct tls_wrap_ctx *tls_wrap) +{ +if (packet_id_initialized (&tls_wrap->opt.packet_id)) + { +packet_id_free (&tls_wrap->opt.packet_id); + } + +if (tls_wrap->cleanup_key_ctx) + { +free_key_ctx_bi (&tls_wrap->opt.key_ctx_bi); + } + +free_buf (&tls_wrap->tls_crypt_v2_metadata); +free_buf (&tls_wrap->work); +} +static inline bool tls_initial_packet_received (const struct tls_multi *multi) {
src/openvpn/ssl_common.h +1 -0
@@ -293,6 +293,7 @@ struct tls_optionsbool ncp_enabled;bool tls_crypt_v2; +const char *tls_crypt_v2_verify_script;/** TLS handshake wrapping state */ struct tls_wrap_ctx tls_wrap;
src/openvpn/tls_crypt.c +68 -1
92 lines not on this page · raw message
src/openvpn/tls_crypt.h +2 -1
@@ -195,7 +195,8 @@ void tls_crypt_v2_init_client_key(struct key_ctx_bi *key,* @returns true if a key was successfully extracted. */ bool tls_crypt_v2_extract_client_key (struct buffer *buf, -struct tls_wrap_ctx *ctx); +struct tls_wrap_ctx *ctx, +const struct tls_options *opt);/** * Generate a tls-crypt-v2 server key, and write to file.
tests/unit_tests/openvpn/Makefile.am +9 -3
@@ -6,7 +6,10 @@ if HAVE_LD_WRAP_SUPPORT check_PROGRAMS += argv_testdriver buffer_testdriver endif -check_PROGRAMS += crypto_testdriver packet_id_testdriver tls_crypt_testdriver +check_PROGRAMS += crypto_testdriver packet_id_testdriver +if HAVE_LD_WRAP_SUPPORT +check_PROGRAMS += tls_crypt_testdriver +endif TESTS = $(check_PROGRAMS)
@@ -52,13 +55,16 @@ packet_id_testdriver_SOURCES = test_packet_id.c mock_msg.c \ tls_crypt_testdriver_CFLAGS = @TEST_CFLAGS@ \ -I$(openvpn_includedir) -I$(compat_srcdir) -I$(openvpn_srcdir) -tls_crypt_testdriver_LDFLAGS = @TEST_LDFLAGS@ +tls_crypt_testdriver_LDFLAGS = @TEST_LDFLAGS@ -Wl,--wrap=parse_line tls_crypt_testdriver_SOURCES = test_tls_crypt.c mock_msg.c \ + $(openvpn_srcdir)/argv.c \ $(openvpn_srcdir)/base64.c \ $(openvpn_srcdir)/buffer.c \ $(openvpn_srcdir)/crypto.c \ $(openvpn_srcdir)/crypto_mbedtls.c \ $(openvpn_srcdir)/crypto_openssl.c \ + $(openvpn_srcdir)/env_set.c \ $(openvpn_srcdir)/otime.c \ $(openvpn_srcdir)/packet_id.c \ - $(openvpn_srcdir)/platform.c + $(openvpn_srcdir)/platform.c \ + $(openvpn_srcdir)/run_command.c
tests/unit_tests/openvpn/test_tls_crypt.c +18 -1
@@ -43,8 +43,24 @@#define TESTBUF_SIZE 128 +/* Defines for use in the tests and the mock parse_line() */ +#define PATH1 "/s p a c e" +#define PATH2 "/foo bar/baz" +#define PARAM1 "param1" +#define PARAM2 "param two" +const char plaintext_short[1 ]; +int +__wrap_parse_line (const char *line,char **p,const int n,const char *file, +const int line_num,int msglevel,struct gc_arena *gc) +{ + p[0] = PATH1 PATH2; + p[1 ] =PARAM1 ; + p[2 ] =PARAM2 ; +return 3 ; +} +struct test_tls_crypt_context {struct crypto_options co;struct key_type kt;
@@ -351,7 +367,8 @@ tls_crypt_v2_wrap_unwrap_max_metadata(void **state) { .mode = TLS_WRAP_CRYPT, .tls_crypt_v2_server_key = ctx->server_keys.encrypt, }; -assert_true (tls_crypt_v2_extract_client_key (&ctx->wkc, &wrap_ctx)); +assert_true (tls_crypt_v2_extract_client_key (&ctx->wkc, &wrap_ctx,NULL )); +tls_wrap_free (&wrap_ctx); }/**
Signature · 1 line
2.7.4
Re: [Openvpn-devel] [PATCH v7 7/7] tls-crypt-v2: add script hook to verify metadata
Hi,
Quoted 5 lines · Steffan Karger
To allow rejecting incoming connections very early in the handshake, add a --tls-crypt-v2-verify option that allows administators to run an external command to verify the metadata from the client key. See
doc/tls-crypt-v2.txtfor more details.
Quoted 7 lines
Because of the extra dependencies, this requires adding a mock
parse_line()to the tls-crypt unit tests. Also, this turnstls_wrap_freeinto a static inline function, so that we don't need to compile inssl.c(and all of it's dependencies) with the unit tests.Signed-off-by Antonio Quartulli <[email protected]...>Signed-off-by Steffan Karger <[email protected]...>
Signature · 1 line
Antonio Quartulli
Hi all,
I am happy to say that finally I couldn't find anything wrong in the last version of this patches.
Other then reviewing and providing feedback to Steffan, I have also tested the code in various setups, including the usage of custom metadata and its verify script.
On top of that, I used the documentation provided by Steffan to port this feature to the OpenVPN 3 codebase and I can say that my implementation happily co-operates with OpenVPN 2.
This makes me think that Steffan's code follows the doc properly (or that both implementations have the same mistakes :-P but it is quite unlikely).
I have ack'd the various patches one by one and I believe they are ready to be merged into master.
The ball now goes to the repo maintainers.
Regards,
Quoted 21 lines · Steffan Karger
Hi,
The following patch set adds support for client-specific tls-crypt keys.
For a rationale, description and specification see patch 2/10, which adds all that to
doc/tls-crypt-v2.txt.This set is also available as a branch in my github fork:
https://github.com/syzzer/openvpn/tree/tls-crypt-v2-preview4-Steffan
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Openvpn-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/openvpn-devel
Signature · 1 line
Antonio Quartulli