Attention is currently required from: flichtenheld, plaisthos.

Hello plaisthos, flichtenheld,

I'd like you to do a code review.
Please visit

    http://gerrit.openvpn.net/c/openvpn/+/725?usp=email

to review the following change.


Change subject: dco-win: support for data_v3 features
......................................................................

dco-win: support for data_v3 features

Since version 1.4, dco-win drivere supports data_v3 features
such as:

 - AEAD tag at the end
 - 64bit pktid

We have to:

 - check in runtime if driver supports data_v3 features (we might be
 running with the older driver)

 - if those features are negotiated, we pass them to the driver
 as bit flags via the (newly added) NEW_KEY_V2 ioctl

Introduce NEW_KEY_V2 ioctl, which accepts a new OVPN_CRYPTO_DATA_V2
structure, which includes a field for bit flags for the new
crypto options.

Make dco_supports_data_v3() implementation platform-dependend (as it
should be) and indicate data_v3 support by dco-win if the driver version
is at least 1.4. Extend the Windows-specific struct dco_context and
store data_v3 support there so that when dco_new_key() is called, we
know which API to use.

Change the dco internal API and pass crypto options flags to dco_new_key().

Change-Id: I2e0c50d33f8a57c023120cf348f95d34acbfcde5
Signed-off-by: Lev Stipakov <l...@openvpn.net>
---
M src/openvpn/dco.c
M src/openvpn/dco.h
M src/openvpn/dco_freebsd.c
M src/openvpn/dco_internal.h
M src/openvpn/dco_linux.c
M src/openvpn/dco_win.c
M src/openvpn/dco_win.h
M src/openvpn/ovpn_dco_win.h
8 files changed, 141 insertions(+), 45 deletions(-)



  git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/25/725/1

diff --git a/src/openvpn/dco.c b/src/openvpn/dco.c
index 7f0d53d..baaeb95 100644
--- a/src/openvpn/dco.c
+++ b/src/openvpn/dco.c
@@ -70,7 +70,7 @@
     int ret = dco_new_key(multi->dco, multi->dco_peer_id, ks->key_id, slot,
                           encrypt_key, encrypt_iv,
                           decrypt_key, decrypt_iv,
-                          ciphername);
+                          ciphername, ks->crypto_options.flags);
     if ((ret == 0) && (multi->dco_keys_installed < 2))
     {
         multi->dco_keys_installed++;
diff --git a/src/openvpn/dco.h b/src/openvpn/dco.h
index 3ce2c31..ec4ec42 100644
--- a/src/openvpn/dco.h
+++ b/src/openvpn/dco.h
@@ -253,11 +253,7 @@
  * Return whether the dco implementation supports the new protocol features of
  * a 64 bit packet counter and AEAD tag at the end.
  */
-static inline bool
-dco_supports_data_v3(struct context *c)
-{
-    return false;
-}
+bool dco_supports_data_v3(struct context *c);

 #else /* if defined(ENABLE_DCO) */

diff --git a/src/openvpn/dco_freebsd.c b/src/openvpn/dco_freebsd.c
index 9a90f5c..0c5e157 100644
--- a/src/openvpn/dco_freebsd.c
+++ b/src/openvpn/dco_freebsd.c
@@ -415,14 +415,14 @@
             dco_key_slot_t slot,
             const uint8_t *encrypt_key, const uint8_t *encrypt_iv,
             const uint8_t *decrypt_key, const uint8_t *decrypt_iv,
-            const char *ciphername)
+            const char *ciphername, int co_flags)
 {
     struct ifdrv drv;
     nvlist_t *nvl;
     int ret;

-    msg(D_DCO_DEBUG, "%s: slot %d, key-id %d, peer-id %d, cipher %s",
-        __func__, slot, keyid, peerid, ciphername);
+    msg(D_DCO_DEBUG, "%s: slot %d, key-id %d, peer-id %d, cipher %s, co_flags 
%d",
+        __func__, slot, keyid, peerid, ciphername, co_flags);

     nvl = nvlist_create(0);

@@ -778,4 +778,11 @@
     return "none:AES-256-GCM:AES-192-GCM:AES-128-GCM:CHACHA20-POLY1305";
 }

+bool
+dco_supports_data_v3(struct context *c)
+{
+    /* not implemented */
+    return false;
+}
+
 #endif /* defined(ENABLE_DCO) && defined(TARGET_FREEBSD) */
diff --git a/src/openvpn/dco_internal.h b/src/openvpn/dco_internal.h
index 624c110..90d383b 100644
--- a/src/openvpn/dco_internal.h
+++ b/src/openvpn/dco_internal.h
@@ -70,7 +70,7 @@
                 dco_key_slot_t slot,
                 const uint8_t *encrypt_key, const uint8_t *encrypt_iv,
                 const uint8_t *decrypt_key, const uint8_t *decrypt_iv,
-                const char *ciphername);
+                const char *ciphername, int co_flags);

 int dco_del_key(dco_context_t *dco, unsigned int peerid, dco_key_slot_t slot);

diff --git a/src/openvpn/dco_linux.c b/src/openvpn/dco_linux.c
index 277cd64..25603e6 100644
--- a/src/openvpn/dco_linux.c
+++ b/src/openvpn/dco_linux.c
@@ -557,10 +557,10 @@
             dco_key_slot_t slot,
             const uint8_t *encrypt_key, const uint8_t *encrypt_iv,
             const uint8_t *decrypt_key, const uint8_t *decrypt_iv,
-            const char *ciphername)
+            const char *ciphername, int co_flags)
 {
-    msg(D_DCO_DEBUG, "%s: slot %d, key-id %d, peer-id %d, cipher %s",
-        __func__, slot, keyid, peerid, ciphername);
+    msg(D_DCO_DEBUG, "%s: slot %d, key-id %d, peer-id %d, cipher %s, co_flags 
%d",
+        __func__, slot, keyid, peerid, ciphername, co_flags);

     const size_t key_len = cipher_kt_key_size(ciphername);
     const int nonce_tail_len = 8;
@@ -1058,4 +1058,11 @@
     return "AES-128-GCM:AES-256-GCM:AES-192-GCM:CHACHA20-POLY1305";
 }

+bool
+dco_supports_data_v3(struct context *c)
+{
+    /* not implemented */
+    return false;
+}
+
 #endif /* defined(ENABLE_DCO) && defined(TARGET_LINUX) */
diff --git a/src/openvpn/dco_win.c b/src/openvpn/dco_win.c
index 3ec946f..06e3545 100644
--- a/src/openvpn/dco_win.c
+++ b/src/openvpn/dco_win.c
@@ -55,6 +55,9 @@
 bool
 ovpn_dco_init(int mode, dco_context_t *dco)
 {
+    dco->supports_data_v3 = dco_supports_data_v3(NULL);
+    msg(D_DCO_DEBUG, "dco supports data_v3: %d", dco->supports_data_v3);
+
     return true;
 }

@@ -291,47 +294,85 @@
     return 0;
 }

-int
-dco_new_key(dco_context_t *dco, unsigned int peerid, int keyid,
-            dco_key_slot_t slot,
-            const uint8_t *encrypt_key, const uint8_t *encrypt_iv,
-            const uint8_t *decrypt_key, const uint8_t *decrypt_iv,
-            const char *ciphername)
+static int
+dco_new_key_v1(HANDLE handle, OVPN_CRYPTO_DATA *crypto_data)
 {
-    msg(D_DCO_DEBUG, "%s: slot %d, key-id %d, peer-id %d, cipher %s",
-        __func__, slot, keyid, peerid, ciphername);
-
-    const int nonce_len = 8;
-    size_t key_len = cipher_kt_key_size(ciphername);
-
-    OVPN_CRYPTO_DATA crypto_data;
-    ZeroMemory(&crypto_data, sizeof(crypto_data));
-
-    crypto_data.CipherAlg = dco_get_cipher(ciphername);
-    crypto_data.KeyId = keyid;
-    crypto_data.PeerId = peerid;
-    crypto_data.KeySlot = slot;
-
-    CopyMemory(crypto_data.Encrypt.Key, encrypt_key, key_len);
-    crypto_data.Encrypt.KeyLen = (char)key_len;
-    CopyMemory(crypto_data.Encrypt.NonceTail, encrypt_iv, nonce_len);
-
-    CopyMemory(crypto_data.Decrypt.Key, decrypt_key, key_len);
-    crypto_data.Decrypt.KeyLen = (char)key_len;
-    CopyMemory(crypto_data.Decrypt.NonceTail, decrypt_iv, nonce_len);
-
-    ASSERT(crypto_data.CipherAlg > 0);
-
     DWORD bytes_returned = 0;

-    if (!DeviceIoControl(dco->tt->hand, OVPN_IOCTL_NEW_KEY, &crypto_data,
-                         sizeof(crypto_data), NULL, 0, &bytes_returned, NULL))
+    if (!DeviceIoControl(handle, OVPN_IOCTL_NEW_KEY, crypto_data, 
sizeof(*crypto_data), NULL, 0, &bytes_returned, NULL))
     {
         msg(M_ERR, "DeviceIoControl(OVPN_IOCTL_NEW_KEY) failed");
         return -1;
     }
     return 0;
 }
+
+static int
+dco_new_key_v2(HANDLE handle, OVPN_CRYPTO_DATA_V2 *crypto_data, int co_flags)
+{
+    if (co_flags & CO_AEAD_TAG_AT_THE_END)
+    {
+        crypto_data->CryptoOptions |= CRYPTO_OPTIONS_AEAD_TAG_END;
+    }
+
+    if (co_flags & CO_64_BIT_PKT_ID)
+    {
+        crypto_data->CryptoOptions |= CRYPTO_OPTIONS_64BIT_PKTID;
+    }
+
+    DWORD bytes_returned = 0;
+    if (!DeviceIoControl(handle, OVPN_IOCTL_NEW_KEY_V2, crypto_data, 
sizeof(*crypto_data), NULL, 0, &bytes_returned, NULL))
+    {
+        msg(M_ERR, "DeviceIoControl(OVPN_IOCTL_NEW_KEY_V2) failed");
+        return -1;
+    }
+
+    return 0;
+}
+
+int
+dco_new_key(dco_context_t *dco, unsigned int peerid, int keyid,
+            dco_key_slot_t slot,
+            const uint8_t *encrypt_key, const uint8_t *encrypt_iv,
+            const uint8_t *decrypt_key, const uint8_t *decrypt_iv,
+            const char *ciphername, int co_flags)
+{
+    msg(D_DCO_DEBUG, "%s: slot %d, key-id %d, peer-id %d, cipher %s, co_flags 
%d",
+        __func__, slot, keyid, peerid, ciphername, co_flags);
+
+    const int nonce_len = 8;
+    size_t key_len = cipher_kt_key_size(ciphername);
+
+    OVPN_CRYPTO_DATA_V2 crypto_data_v2;
+    ZeroMemory(&crypto_data_v2, sizeof(crypto_data_v2));
+
+    OVPN_CRYPTO_DATA *crypto_data = &crypto_data_v2.V1;
+
+    crypto_data->CipherAlg = dco_get_cipher(ciphername);
+    crypto_data->KeyId = keyid;
+    crypto_data->PeerId = peerid;
+    crypto_data->KeySlot = slot;
+
+    CopyMemory(crypto_data->Encrypt.Key, encrypt_key, key_len);
+    crypto_data->Encrypt.KeyLen = (char)key_len;
+    CopyMemory(crypto_data->Encrypt.NonceTail, encrypt_iv, nonce_len);
+
+    CopyMemory(crypto_data->Decrypt.Key, decrypt_key, key_len);
+    crypto_data->Decrypt.KeyLen = (char)key_len;
+    CopyMemory(crypto_data->Decrypt.NonceTail, decrypt_iv, nonce_len);
+
+    ASSERT(crypto_data->CipherAlg > 0);
+
+    if (dco->supports_data_v3)
+    {
+        return dco_new_key_v2(dco->tt->hand, &crypto_data_v2, co_flags);
+    }
+    else
+    {
+        return dco_new_key_v1(dco->tt->hand, crypto_data);
+    }
+}
+
 int
 dco_del_key(dco_context_t *dco, unsigned int peerid, dco_key_slot_t slot)
 {
@@ -494,4 +535,39 @@
     }
 }

+bool
+dco_supports_data_v3(struct context *c)
+{
+    bool res = false;
+
+    HANDLE h = CreateFile("\\\\.\\ovpn-dco-ver", GENERIC_READ,
+                          0, NULL, OPEN_EXISTING, 0, NULL);
+
+    if (h == INVALID_HANDLE_VALUE)
+    {
+        goto done;
+    }
+
+    OVPN_VERSION version;
+    ZeroMemory(&version, sizeof(OVPN_VERSION));
+
+    DWORD bytes_returned = 0;
+    if (!DeviceIoControl(h, OVPN_IOCTL_GET_VERSION, NULL, 0,
+                         &version, sizeof(version), &bytes_returned, NULL))
+    {
+        goto done;
+    }
+
+    /* data_v3 is supported starting from 1.4 */
+    res = (version.Major > 1) || (version.Minor >= 4);
+
+done:
+    if (h != INVALID_HANDLE_VALUE)
+    {
+        CloseHandle(h);
+    }
+
+    return res;
+}
+
 #endif /* defined(_WIN32) */
diff --git a/src/openvpn/dco_win.h b/src/openvpn/dco_win.h
index 4883629..f58488f 100644
--- a/src/openvpn/dco_win.h
+++ b/src/openvpn/dco_win.h
@@ -33,6 +33,7 @@

 struct dco_context {
     struct tuntap *tt;
+    bool supports_data_v3;
 };

 typedef struct dco_context dco_context_t;
diff --git a/src/openvpn/ovpn_dco_win.h b/src/openvpn/ovpn_dco_win.h
index ea2a733..9e437f0 100644
--- a/src/openvpn/ovpn_dco_win.h
+++ b/src/openvpn/ovpn_dco_win.h
@@ -94,6 +94,14 @@
        int PeerId;
 } OVPN_CRYPTO_DATA, * POVPN_CRYPTO_DATA;

+#define CRYPTO_OPTIONS_AEAD_TAG_END (1<<1)
+#define CRYPTO_OPTIONS_64BIT_PKTID  (1<<2)
+
+typedef struct _OVPN_CRYPTO_DATA_V2 {
+    OVPN_CRYPTO_DATA V1;
+    UINT32 CryptoOptions;
+} OVPN_CRYPTO_DATA_V2, * POVPN_CRYPTO_DATA_V2;
+
 typedef struct _OVPN_SET_PEER {
        LONG KeepaliveInterval;
        LONG KeepaliveTimeout;
@@ -114,3 +122,4 @@
 #define OVPN_IOCTL_START_VPN    CTL_CODE(FILE_DEVICE_UNKNOWN, 6, 
METHOD_BUFFERED, FILE_ANY_ACCESS)
 #define OVPN_IOCTL_DEL_PEER     CTL_CODE(FILE_DEVICE_UNKNOWN, 7, 
METHOD_BUFFERED, FILE_ANY_ACCESS)
 #define OVPN_IOCTL_GET_VERSION  CTL_CODE(FILE_DEVICE_UNKNOWN, 8, 
METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define OVPN_IOCTL_NEW_KEY_V2   CTL_CODE(FILE_DEVICE_UNKNOWN, 9, 
METHOD_BUFFERED, FILE_ANY_ACCESS)

--
To view, visit http://gerrit.openvpn.net/c/openvpn/+/725?usp=email
To unsubscribe, or for help writing mail filters, visit 
http://gerrit.openvpn.net/settings

Gerrit-Project: openvpn
Gerrit-Branch: master
Gerrit-Change-Id: I2e0c50d33f8a57c023120cf348f95d34acbfcde5
Gerrit-Change-Number: 725
Gerrit-PatchSet: 1
Gerrit-Owner: stipa <lstipa...@gmail.com>
Gerrit-Reviewer: flichtenheld <fr...@lichtenheld.com>
Gerrit-Reviewer: plaisthos <arne-open...@rfc2549.org>
Gerrit-CC: openvpn-devel <openvpn-devel@lists.sourceforge.net>
Gerrit-Attention: plaisthos <arne-open...@rfc2549.org>
Gerrit-Attention: flichtenheld <fr...@lichtenheld.com>
Gerrit-MessageType: newchange
_______________________________________________
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel

Reply via email to