Starting from 2.8.0, dco-win driver supports epoch data channel.
This commit adds missing userspace part to query DCO drivers for epoch
data format support (always "false" for now for Linux and FreeBSD, true
if Win-DCO driver is 2.8 or later), and pass "CRYPTO_OPTIONS_EPOCH"
flag via a new OVPN_IOCTL_NEW_KEY_V2 ioctl() to windows driver to turn
it on, if negotiated.
Change-Id: Ib5ed5969dcd405a47e34ed8479b7ffaaa5c43080
Signed-off-by: Lev Stipakov <lev@openvpn.net>
Acked-by: Arne Schwabe <arne-openvpn@rfc2549.org>
Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1219
Message-Id: <20251008123757.18670-1-gert@greenie.muc.de>
URL: https://sourceforge.net/p/openvpn/mailman/message/59243920/
Signed-off-by: Gert Doering <gert@greenie.muc.de>
| ... | ... |
@@ -56,8 +56,9 @@ dco_install_key(struct tls_multi *multi, struct key_state *ks, const uint8_t *en |
| 56 | 56 |
const char *ciphername) |
| 57 | 57 |
|
| 58 | 58 |
{
|
| 59 |
- msg(D_DCO_DEBUG, "%s: peer_id=%d keyid=%d, currently %d keys installed", __func__, |
|
| 60 |
- multi->dco_peer_id, ks->key_id, multi->dco_keys_installed); |
|
| 59 |
+ bool epoch = ks->crypto_options.flags & CO_EPOCH_DATA_KEY_FORMAT; |
|
| 60 |
+ msg(D_DCO_DEBUG, "%s: peer_id=%d keyid=%d epoch=%d, currently %d keys installed", __func__, |
|
| 61 |
+ multi->dco_peer_id, ks->key_id, multi->dco_keys_installed, epoch); |
|
| 61 | 62 |
|
| 62 | 63 |
/* Install a key in the PRIMARY slot only when no other key exist. |
| 63 | 64 |
* From that moment on, any new key will be installed in the SECONDARY |
| ... | ... |
@@ -71,7 +72,7 @@ dco_install_key(struct tls_multi *multi, struct key_state *ks, const uint8_t *en |
| 71 | 71 |
} |
| 72 | 72 |
|
| 73 | 73 |
int ret = dco_new_key(multi->dco, multi->dco_peer_id, ks->key_id, slot, encrypt_key, encrypt_iv, |
| 74 |
- decrypt_key, decrypt_iv, ciphername); |
|
| 74 |
+ decrypt_key, decrypt_iv, ciphername, epoch); |
|
| 75 | 75 |
if ((ret == 0) && (multi->dco_keys_installed < 2)) |
| 76 | 76 |
{
|
| 77 | 77 |
multi->dco_keys_installed++; |
| ... | ... |
@@ -251,11 +251,8 @@ const char *dco_get_supported_ciphers(void); |
| 251 | 251 |
* Return whether the dco implementation supports the new protocol features of |
| 252 | 252 |
* a 64 bit packet counter and AEAD tag at the end. |
| 253 | 253 |
*/ |
| 254 |
-static inline bool |
|
| 255 |
-dco_supports_epoch_data(struct context *c) |
|
| 256 |
-{
|
|
| 257 |
- return false; |
|
| 258 |
-} |
|
| 254 |
+bool |
|
| 255 |
+dco_supports_epoch_data(struct context *c); |
|
| 259 | 256 |
#else /* if defined(ENABLE_DCO) */ |
| 260 | 257 |
|
| 261 | 258 |
typedef void *dco_context_t; |
| ... | ... |
@@ -487,14 +487,14 @@ start_tun(dco_context_t *dco) |
| 487 | 487 |
int |
| 488 | 488 |
dco_new_key(dco_context_t *dco, unsigned int peerid, int keyid, dco_key_slot_t slot, |
| 489 | 489 |
const uint8_t *encrypt_key, const uint8_t *encrypt_iv, const uint8_t *decrypt_key, |
| 490 |
- const uint8_t *decrypt_iv, const char *ciphername) |
|
| 490 |
+ const uint8_t *decrypt_iv, const char *ciphername, bool epoch) |
|
| 491 | 491 |
{
|
| 492 | 492 |
struct ifdrv drv; |
| 493 | 493 |
nvlist_t *nvl, *encrypt_nvl, *decrypt_nvl; |
| 494 | 494 |
int ret; |
| 495 | 495 |
|
| 496 |
- msg(D_DCO_DEBUG, "%s: slot %d, key-id %d, peer-id %d, cipher %s", __func__, slot, keyid, peerid, |
|
| 497 |
- ciphername); |
|
| 496 |
+ msg(D_DCO_DEBUG, "%s: slot %d, key-id %d, peer-id %d, cipher %s, epoch %d", __func__, slot, keyid, peerid, |
|
| 497 |
+ ciphername, epoch); |
|
| 498 | 498 |
|
| 499 | 499 |
nvl = nvlist_create(0); |
| 500 | 500 |
|
| ... | ... |
@@ -876,4 +876,10 @@ dco_get_supported_ciphers(void) |
| 876 | 876 |
return "none:AES-256-GCM:AES-192-GCM:AES-128-GCM:CHACHA20-POLY1305"; |
| 877 | 877 |
} |
| 878 | 878 |
|
| 879 |
+bool |
|
| 880 |
+dco_supports_epoch_data(struct context *c) |
|
| 881 |
+{
|
|
| 882 |
+ return false; |
|
| 883 |
+} |
|
| 884 |
+ |
|
| 879 | 885 |
#endif /* defined(ENABLE_DCO) && defined(TARGET_FREEBSD) */ |
| ... | ... |
@@ -66,7 +66,7 @@ int dco_del_peer(dco_context_t *dco, unsigned int peerid); |
| 66 | 66 |
|
| 67 | 67 |
int dco_new_key(dco_context_t *dco, unsigned int peerid, int keyid, dco_key_slot_t slot, |
| 68 | 68 |
const uint8_t *encrypt_key, const uint8_t *encrypt_iv, const uint8_t *decrypt_key, |
| 69 |
- const uint8_t *decrypt_iv, const char *ciphername); |
|
| 69 |
+ const uint8_t *decrypt_iv, const char *ciphername, bool epoch); |
|
| 70 | 70 |
|
| 71 | 71 |
int dco_del_key(dco_context_t *dco, unsigned int peerid, dco_key_slot_t slot); |
| 72 | 72 |
|
| ... | ... |
@@ -596,10 +596,10 @@ nla_put_failure: |
| 596 | 596 |
int |
| 597 | 597 |
dco_new_key(dco_context_t *dco, unsigned int peerid, int keyid, dco_key_slot_t slot, |
| 598 | 598 |
const uint8_t *encrypt_key, const uint8_t *encrypt_iv, const uint8_t *decrypt_key, |
| 599 |
- const uint8_t *decrypt_iv, const char *ciphername) |
|
| 599 |
+ const uint8_t *decrypt_iv, const char *ciphername, bool epoch) |
|
| 600 | 600 |
{
|
| 601 |
- msg(D_DCO_DEBUG, "%s: slot %d, key-id %d, peer-id %d, cipher %s", __func__, slot, keyid, peerid, |
|
| 602 |
- ciphername); |
|
| 601 |
+ msg(D_DCO_DEBUG, "%s: slot %d, key-id %d, peer-id %d, cipher %s, epoch %d", __func__, slot, keyid, peerid, |
|
| 602 |
+ ciphername, epoch); |
|
| 603 | 603 |
|
| 604 | 604 |
const int key_len = cipher_kt_key_size(ciphername); |
| 605 | 605 |
const int nonce_tail_len = 8; |
| ... | ... |
@@ -1298,4 +1298,10 @@ dco_get_supported_ciphers(void) |
| 1298 | 1298 |
return "AES-128-GCM:AES-256-GCM:AES-192-GCM:CHACHA20-POLY1305"; |
| 1299 | 1299 |
} |
| 1300 | 1300 |
|
| 1301 |
+bool |
|
| 1302 |
+dco_supports_epoch_data(struct context *c) |
|
| 1303 |
+{
|
|
| 1304 |
+ return false; |
|
| 1305 |
+} |
|
| 1306 |
+ |
|
| 1301 | 1307 |
#endif /* defined(ENABLE_DCO) && defined(TARGET_LINUX) */ |
| ... | ... |
@@ -528,7 +528,7 @@ dco_set_peer(dco_context_t *dco, unsigned int peerid, int keepalive_interval, in |
| 528 | 528 |
int |
| 529 | 529 |
dco_new_key(dco_context_t *dco, unsigned int peerid, int keyid, dco_key_slot_t slot, |
| 530 | 530 |
const uint8_t *encrypt_key, const uint8_t *encrypt_iv, const uint8_t *decrypt_key, |
| 531 |
- const uint8_t *decrypt_iv, const char *ciphername) |
|
| 531 |
+ const uint8_t *decrypt_iv, const char *ciphername, bool epoch) |
|
| 532 | 532 |
{
|
| 533 | 533 |
msg(D_DCO_DEBUG, "%s: slot %d, key-id %d, peer-id %d, cipher %s", __func__, slot, keyid, peerid, |
| 534 | 534 |
ciphername); |
| ... | ... |
@@ -537,29 +537,42 @@ dco_new_key(dco_context_t *dco, unsigned int peerid, int keyid, dco_key_slot_t s |
| 537 | 537 |
size_t key_len = cipher_kt_key_size(ciphername); |
| 538 | 538 |
ASSERT(key_len <= 32); |
| 539 | 539 |
|
| 540 |
- OVPN_CRYPTO_DATA crypto_data; |
|
| 540 |
+ OVPN_CRYPTO_DATA_V2 crypto_data; |
|
| 541 | 541 |
ZeroMemory(&crypto_data, sizeof(crypto_data)); |
| 542 | 542 |
|
| 543 |
- crypto_data.CipherAlg = dco_get_cipher(ciphername); |
|
| 543 |
+ OVPN_CRYPTO_DATA *v1 = &crypto_data.V1; |
|
| 544 |
+ |
|
| 545 |
+ v1->CipherAlg = dco_get_cipher(ciphername); |
|
| 544 | 546 |
ASSERT(keyid >= 0 && keyid <= UCHAR_MAX); |
| 545 |
- crypto_data.KeyId = (unsigned char)keyid; |
|
| 546 |
- crypto_data.PeerId = peerid; |
|
| 547 |
- crypto_data.KeySlot = slot; |
|
| 547 |
+ v1->KeyId = (unsigned char)keyid; |
|
| 548 |
+ v1->PeerId = peerid; |
|
| 549 |
+ v1->KeySlot = slot; |
|
| 548 | 550 |
|
| 549 |
- CopyMemory(crypto_data.Encrypt.Key, encrypt_key, key_len); |
|
| 550 |
- crypto_data.Encrypt.KeyLen = (unsigned char)key_len; |
|
| 551 |
- CopyMemory(crypto_data.Encrypt.NonceTail, encrypt_iv, nonce_len); |
|
| 551 |
+ /* for epoch we use key material as a seed, no as actual key */ |
|
| 552 |
+ CopyMemory(v1->Encrypt.Key, encrypt_key, epoch ? 32 : key_len); |
|
| 553 |
+ v1->Encrypt.KeyLen = (unsigned char)key_len; |
|
| 554 |
+ CopyMemory(v1->Encrypt.NonceTail, encrypt_iv, nonce_len); |
|
| 552 | 555 |
|
| 553 |
- CopyMemory(crypto_data.Decrypt.Key, decrypt_key, key_len); |
|
| 554 |
- crypto_data.Decrypt.KeyLen = (unsigned char)key_len; |
|
| 555 |
- CopyMemory(crypto_data.Decrypt.NonceTail, decrypt_iv, nonce_len); |
|
| 556 |
+ CopyMemory(v1->Decrypt.Key, decrypt_key, epoch ? 32 : key_len); |
|
| 557 |
+ v1->Decrypt.KeyLen = (unsigned char)key_len; |
|
| 558 |
+ CopyMemory(v1->Decrypt.NonceTail, decrypt_iv, nonce_len); |
|
| 556 | 559 |
|
| 557 |
- ASSERT(crypto_data.CipherAlg > 0); |
|
| 560 |
+ ASSERT(v1->CipherAlg > 0); |
|
| 561 |
+ |
|
| 562 |
+ DWORD ioctl = OVPN_IOCTL_NEW_KEY; |
|
| 563 |
+ VOID *buf = &crypto_data.V1; |
|
| 564 |
+ DWORD bufSize = sizeof(crypto_data.V1); |
|
| 565 |
+ if (epoch) |
|
| 566 |
+ {
|
|
| 567 |
+ ioctl = OVPN_IOCTL_NEW_KEY_V2; |
|
| 568 |
+ crypto_data.CryptoOptions |= CRYPTO_OPTIONS_EPOCH; |
|
| 569 |
+ buf = &crypto_data; |
|
| 570 |
+ bufSize = sizeof(crypto_data); |
|
| 571 |
+ } |
|
| 558 | 572 |
|
| 559 | 573 |
DWORD bytes_returned = 0; |
| 560 | 574 |
|
| 561 |
- if (!DeviceIoControl(dco->tt->hand, OVPN_IOCTL_NEW_KEY, &crypto_data, sizeof(crypto_data), NULL, |
|
| 562 |
- 0, &bytes_returned, NULL)) |
|
| 575 |
+ if (!DeviceIoControl(dco->tt->hand, ioctl, buf, bufSize, NULL, 0, &bytes_returned, NULL)) |
|
| 563 | 576 |
{
|
| 564 | 577 |
msg(M_ERR, "DeviceIoControl(OVPN_IOCTL_NEW_KEY) failed"); |
| 565 | 578 |
return -1; |
| ... | ... |
@@ -1076,4 +1089,11 @@ dco_win_del_iroute_ipv6(dco_context_t *dco, struct in6_addr dst, unsigned int ne |
| 1076 | 1076 |
gc_free(&gc); |
| 1077 | 1077 |
} |
| 1078 | 1078 |
|
| 1079 |
+bool |
|
| 1080 |
+dco_supports_epoch_data(struct context *c) |
|
| 1081 |
+{
|
|
| 1082 |
+ OVPN_VERSION ver = { 0 };
|
|
| 1083 |
+ return dco_get_version(&ver) && ((ver.Major == 2 && ver.Minor >= 8) || (ver.Major > 2)); |
|
| 1084 |
+} |
|
| 1085 |
+ |
|
| 1079 | 1086 |
#endif /* defined(_WIN32) */ |
| ... | ... |
@@ -118,6 +118,13 @@ typedef struct _OVPN_CRYPTO_DATA {
|
| 118 | 118 |
int PeerId; |
| 119 | 119 |
} OVPN_CRYPTO_DATA, * POVPN_CRYPTO_DATA; |
| 120 | 120 |
|
| 121 |
+#define CRYPTO_OPTIONS_EPOCH (1<<1) |
|
| 122 |
+ |
|
| 123 |
+typedef struct _OVPN_CRYPTO_DATA_V2 {
|
|
| 124 |
+ OVPN_CRYPTO_DATA V1; |
|
| 125 |
+ UINT32 CryptoOptions; |
|
| 126 |
+} OVPN_CRYPTO_DATA_V2, * POVPN_CRYPTO_DATA_V2; |
|
| 127 |
+ |
|
| 121 | 128 |
typedef struct _OVPN_MP_SET_PEER {
|
| 122 | 129 |
int PeerId; |
| 123 | 130 |
LONG KeepaliveInterval; |