Skip to content

Commit 3473397

Browse files
Fix P2P epoch MTU accounting
P2P NCP stores the negotiated epoch flag in the live TLS session. Pass the active data-channel crypto flags through frame-overhead calculation so P2P uses the actual packet-ID format without writing session state back into the main options structure. Keep pre-negotiation calculations on their existing imported flags. Add focused coverage for epoch and non-epoch P2P overhead. Related: #1074 Signed-off-by: Darren Carreras <carrerasdarren@gmail.com>
1 parent d110697 commit 3473397

11 files changed

Lines changed: 101 additions & 39 deletions

File tree

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,8 @@ if (BUILD_TESTING)
842842
src/openvpn/crypto_mbedtls.c
843843
src/openvpn/crypto_openssl.c
844844
src/openvpn/crypto.c
845+
src/openvpn/mss.c
846+
src/openvpn/mtu.c
845847
src/openvpn/otime.c
846848
src/openvpn/packet_id.c
847849
src/openvpn/ssl_util.c

src/openvpn/init.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2856,7 +2856,8 @@ get_frame_mtu(struct context *c, const struct options *o)
28562856
ASSERT(o->ce.link_mtu_defined);
28572857
/* if we have a link mtu defined we calculate what the old code
28582858
* would have come up with as tun-mtu */
2859-
size_t overhead = frame_calculate_protocol_header_size(&c->c1.ks.key_type, o, true);
2859+
size_t overhead = frame_calculate_protocol_header_size(
2860+
&c->c1.ks.key_type, o, o->imported_protocol_flags, true);
28602861
mtu = o->ce.link_mtu - overhead;
28612862
}
28622863
else
@@ -3745,7 +3746,7 @@ do_init_fragment(struct context *c)
37453746
c->c2.frame_fragment = c->c2.frame;
37463747

37473748
frame_calculate_dynamic(&c->c2.frame_fragment, &c->c1.ks.key_type, &c->options,
3748-
get_link_socket_info(c));
3749+
c->options.imported_protocol_flags, get_link_socket_info(c));
37493750
fragment_frame_init(c->c2.fragment, &c->c2.frame_fragment);
37503751
}
37513752
#endif
@@ -4656,6 +4657,7 @@ init_instance(struct context *c, const struct env_set *env, const unsigned int f
46564657
for (int i = 0; i < c->c1.link_sockets_num; i++)
46574658
{
46584659
frame_calculate_dynamic(&c->c2.frame, &c->c1.ks.key_type, &c->options,
4660+
c->options.imported_protocol_flags,
46594661
&c->c2.link_sockets[i]->info);
46604662
}
46614663
}

src/openvpn/mss.c

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -240,12 +240,12 @@ get_ip_encap_overhead(const struct options *options, const struct link_socket_in
240240

241241
static void
242242
frame_calculate_fragment(struct frame *frame, struct key_type *kt, const struct options *options,
243-
struct link_socket_info *lsi)
243+
unsigned int crypto_flags, struct link_socket_info *lsi)
244244
{
245245
#if defined(ENABLE_FRAGMENT)
246246
size_t overhead;
247247

248-
overhead = frame_calculate_protocol_header_size(kt, options, false);
248+
overhead = frame_calculate_protocol_header_size(kt, options, crypto_flags, false);
249249

250250
if (options->ce.fragment_encap)
251251
{
@@ -263,14 +263,14 @@ frame_calculate_fragment(struct frame *frame, struct key_type *kt, const struct
263263
{
264264
/* The packet id gets added to *each* fragment in CBC mode, so we need
265265
* to account for it */
266-
frame->max_fragment_size -= calc_packet_id_size_dc(options, kt);
266+
frame->max_fragment_size -= calc_packet_id_size_dc(options, kt, crypto_flags);
267267
}
268268
#endif
269269
}
270270

271271
static void
272272
frame_calculate_mssfix(struct frame *frame, struct key_type *kt, const struct options *options,
273-
struct link_socket_info *lsi)
273+
unsigned int crypto_flags, struct link_socket_info *lsi)
274274
{
275275
if (options->ce.mssfix_fixed)
276276
{
@@ -282,11 +282,12 @@ frame_calculate_mssfix(struct frame *frame, struct key_type *kt, const struct op
282282

283283
size_t overhead, payload_overhead;
284284

285-
overhead = frame_calculate_protocol_header_size(kt, options, false);
285+
overhead = frame_calculate_protocol_header_size(kt, options, crypto_flags, false);
286286

287287
/* Calculate the number of bytes that the payload differs from the payload
288288
* MTU. This are fragment/compression/ethernet headers */
289-
payload_overhead = frame_calculate_payload_overhead(frame->extra_tun, options, kt);
289+
payload_overhead =
290+
frame_calculate_payload_overhead(frame->extra_tun, options, kt, crypto_flags);
290291

291292
/* We are in a "liberal" position with respect to MSS,
292293
* i.e. we assume that MSS can be calculated from MTU
@@ -315,16 +316,16 @@ frame_calculate_mssfix(struct frame *frame, struct key_type *kt, const struct op
315316

316317
void
317318
frame_calculate_dynamic(struct frame *frame, struct key_type *kt, const struct options *options,
318-
struct link_socket_info *lsi)
319+
unsigned int crypto_flags, struct link_socket_info *lsi)
319320
{
320321
if (options->ce.fragment > 0)
321322
{
322-
frame_calculate_fragment(frame, kt, options, lsi);
323+
frame_calculate_fragment(frame, kt, options, crypto_flags, lsi);
323324
}
324325

325326
if (options->ce.mssfix > 0)
326327
{
327-
frame_calculate_mssfix(frame, kt, options, lsi);
328+
frame_calculate_mssfix(frame, kt, options, crypto_flags, lsi);
328329
}
329330
}
330331

@@ -354,7 +355,8 @@ frame_adjust_path_mtu(struct context *c)
354355
o->ce.mssfix, mtustr, pmtu);
355356
o->ce.mssfix = pmtu;
356357
o->ce.mssfix_encap = true;
357-
frame_calculate_dynamic(&c->c2.frame, &c->c1.ks.key_type, o, lsi);
358+
frame_calculate_dynamic(&c->c2.frame, &c->c1.ks.key_type, o,
359+
c->c2.crypto_options.flags, lsi);
358360
}
359361

360362
#if defined(ENABLE_FRAGMENT)
@@ -367,7 +369,8 @@ frame_adjust_path_mtu(struct context *c)
367369
o->ce.fragment, mtustr, pmtu);
368370
o->ce.fragment = pmtu;
369371
o->ce.fragment_encap = true;
370-
frame_calculate_dynamic(&c->c2.frame_fragment, &c->c1.ks.key_type, o, lsi);
372+
frame_calculate_dynamic(&c->c2.frame_fragment, &c->c1.ks.key_type, o,
373+
c->c2.crypto_options.flags, lsi);
371374
}
372375
#endif
373376
}

src/openvpn/mss.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,12 @@ void mss_fixup_ipv6(struct buffer *buf, uint16_t maxmss);
3535

3636
void mss_fixup_dowork(struct buffer *buf, uint16_t maxmss);
3737

38-
/** Set the --mssfix option. */
38+
/**
39+
* Recalculate dynamic frame parameters using the active data-channel flags.
40+
*/
3941
void frame_calculate_dynamic(struct frame *frame, struct key_type *kt,
40-
const struct options *options, struct link_socket_info *lsi);
42+
const struct options *options, unsigned int crypto_flags,
43+
struct link_socket_info *lsi);
4144

4245
/**
4346
* Checks and adjusts the fragment and mssfix value according to the

src/openvpn/mtu.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,11 @@ alloc_buf_sock_tun(struct buffer *buf, const struct frame *frame)
4949
}
5050

5151
unsigned int
52-
calc_packet_id_size_dc(const struct options *options, const struct key_type *kt)
52+
calc_packet_id_size_dc(const struct options *options, const struct key_type *kt,
53+
unsigned int crypto_flags)
5354
{
5455
bool tlsmode = options->tls_server || options->tls_client;
55-
bool epoch = options->imported_protocol_flags & CO_EPOCH_DATA_KEY_FORMAT;
56+
bool epoch = crypto_flags & CO_EPOCH_DATA_KEY_FORMAT;
5657

5758
/* epoch format uses a 64-bit packet id: 16 bit epoch + 48 bit per-epoch counter */
5859
if (epoch)
@@ -67,7 +68,7 @@ calc_packet_id_size_dc(const struct options *options, const struct key_type *kt)
6768

6869
size_t
6970
frame_calculate_protocol_header_size(const struct key_type *kt, const struct options *options,
70-
bool occ)
71+
unsigned int crypto_flags, bool occ)
7172
{
7273
/* Sum of all the overhead that reduces the usable packet size */
7374
size_t header_size = 0;
@@ -93,7 +94,7 @@ frame_calculate_protocol_header_size(const struct key_type *kt, const struct opt
9394
header_size += options->use_peer_id ? 4 : 1;
9495
}
9596

96-
unsigned int pkt_id_size = calc_packet_id_size_dc(options, kt);
97+
unsigned int pkt_id_size = calc_packet_id_size_dc(options, kt, crypto_flags);
9798

9899
/* For figuring out the crypto overhead, we need the size of the payload
99100
* including all headers that also get encrypted as part of the payload */
@@ -104,7 +105,7 @@ frame_calculate_protocol_header_size(const struct key_type *kt, const struct opt
104105

105106
size_t
106107
frame_calculate_payload_overhead(size_t extra_tun, const struct options *options,
107-
const struct key_type *kt)
108+
const struct key_type *kt, unsigned int crypto_flags)
108109
{
109110
size_t overhead = 0;
110111

@@ -136,7 +137,7 @@ frame_calculate_payload_overhead(size_t extra_tun, const struct options *options
136137
/* The packet id is part of the plain text payload instead of the
137138
* cleartext protocol header and needs to be included in the payload
138139
* overhead instead of the protocol header */
139-
overhead += calc_packet_id_size_dc(options, kt);
140+
overhead += calc_packet_id_size_dc(options, kt, crypto_flags);
140141
}
141142

142143
return overhead;
@@ -147,7 +148,8 @@ frame_calculate_payload_size(const struct frame *frame, const struct options *op
147148
const struct key_type *kt)
148149
{
149150
size_t payload_size = options->ce.tun_mtu;
150-
payload_size += frame_calculate_payload_overhead(frame->extra_tun, options, kt);
151+
payload_size += frame_calculate_payload_overhead(frame->extra_tun, options, kt,
152+
options->imported_protocol_flags);
151153
return payload_size;
152154
}
153155

@@ -189,7 +191,7 @@ calc_options_string_link_mtu(const struct options *o, const struct frame *frame)
189191
init_key_type(&occ_kt, ciphername, o->authname, true, false);
190192

191193
size_t payload = frame_calculate_payload_size(frame, o, &occ_kt);
192-
overhead += frame_calculate_protocol_header_size(&occ_kt, o, true);
194+
overhead += frame_calculate_protocol_header_size(&occ_kt, o, o->imported_protocol_flags, true);
193195

194196
return payload + overhead;
195197
}

src/openvpn/mtu.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ size_t frame_calculate_payload_size(const struct frame *frame, const struct opti
229229
* * [IP][UDP][OPENVPN PROTOCOL HEADER][ **PAYLOAD incl compression header** ]
230230
*/
231231
size_t frame_calculate_payload_overhead(size_t extra_tun, const struct options *options,
232-
const struct key_type *kt);
232+
const struct key_type *kt, unsigned int crypto_flags);
233233

234234

235235
/**
@@ -244,11 +244,13 @@ size_t frame_calculate_payload_overhead(size_t extra_tun, const struct options *
244244
*
245245
* @param kt the key_type to use to calculate the crypto overhead
246246
* @param options the options struct to be used to calculate
247+
* @param crypto_flags the active data-channel crypto flags
247248
* @param occ Use the calculation for the OCC link-mtu
248249
* @return size of the overhead in bytes
249250
*/
250251
size_t frame_calculate_protocol_header_size(const struct key_type *kt,
251-
const struct options *options, bool occ);
252+
const struct options *options,
253+
unsigned int crypto_flags, bool occ);
252254

253255
/**
254256
* Calculate the link-mtu to advertise to our peer. The actual value is not
@@ -260,10 +262,11 @@ size_t frame_calculate_protocol_header_size(const struct key_type *kt,
260262
size_t calc_options_string_link_mtu(const struct options *options, const struct frame *frame);
261263

262264
/**
263-
* Return the size of the packet ID size that is currently in use by cipher and
264-
* options for the data channel.
265+
* Return the packet ID size currently in use by the cipher, options, and active
266+
* data-channel crypto flags.
265267
*/
266-
unsigned int calc_packet_id_size_dc(const struct options *options, const struct key_type *kt);
268+
unsigned int calc_packet_id_size_dc(const struct options *options, const struct key_type *kt,
269+
unsigned int crypto_flags);
267270

268271
/*
269272
* allocate a buffer for socket or tun layer

src/openvpn/occ.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,8 +198,8 @@ check_send_occ_load_test_dowork(struct context *c)
198198
c->c2.occ_op = entry->op;
199199
size_t payload_size =
200200
frame_calculate_payload_size(&c->c2.frame, &c->options, &c->c1.ks.key_type);
201-
size_t header_size =
202-
frame_calculate_protocol_header_size(&c->c1.ks.key_type, &c->options, false);
201+
size_t header_size = frame_calculate_protocol_header_size(
202+
&c->c1.ks.key_type, &c->options, c->c2.crypto_options.flags, false);
203203

204204
c->c2.occ_mtu_load_size = payload_size + header_size;
205205
}
@@ -303,10 +303,12 @@ check_send_occ_msg_dowork(struct context *c)
303303
const struct key_type *kt = &c->c1.ks.key_type;
304304

305305
/* OCC message have comp/fragment headers but not ethernet headers */
306-
payload_hdr = frame_calculate_payload_overhead(0, &c->options, kt);
306+
payload_hdr =
307+
frame_calculate_payload_overhead(0, &c->options, kt, c->c2.crypto_options.flags);
307308

308309
/* Since we do not know the payload size we just pass 0 as size here */
309-
proto_hdr = frame_calculate_protocol_header_size(kt, &c->options, false);
310+
proto_hdr = frame_calculate_protocol_header_size(
311+
kt, &c->options, c->c2.crypto_options.flags, false);
310312

311313
need_to_add = min_int(c->c2.occ_mtu_load_size, c->c2.frame.buf.payload_size)
312314
- OCC_STRING_SIZE - sizeof(uint8_t) /* occ opcode */

src/openvpn/ssl.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1592,7 +1592,8 @@ tls_session_update_crypto_params_do_work(struct tls_multi *multi, struct tls_ses
15921592
session->opt->crypto_flags |= CO_PACKET_ID_LONG_FORM;
15931593
}
15941594

1595-
frame_calculate_dynamic(frame, &session->opt->key_type, options, lsi);
1595+
frame_calculate_dynamic(frame, &session->opt->key_type, options, session->opt->crypto_flags,
1596+
lsi);
15961597

15971598
frame_print(frame, D_MTU_INFO, "Data Channel MTU parms");
15981599

@@ -1605,7 +1606,8 @@ tls_session_update_crypto_params_do_work(struct tls_multi *multi, struct tls_ses
16051606

16061607
if (frame_fragment)
16071608
{
1608-
frame_calculate_dynamic(frame_fragment, &session->opt->key_type, options, lsi);
1609+
frame_calculate_dynamic(frame_fragment, &session->opt->key_type, options,
1610+
session->opt->crypto_flags, lsi);
16091611
frame_print(frame_fragment, D_MTU_INFO, "Fragmentation MTU parms");
16101612
}
16111613

tests/unit_tests/openvpn/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,8 @@ ncp_testdriver_SOURCES = test_ncp.c \
341341
$(top_srcdir)/src/openvpn/crypto_mbedtls.c \
342342
$(top_srcdir)/src/openvpn/crypto_mbedtls_legacy.c \
343343
$(top_srcdir)/src/openvpn/crypto_openssl.c \
344+
$(top_srcdir)/src/openvpn/mss.c \
345+
$(top_srcdir)/src/openvpn/mtu.c \
344346
$(top_srcdir)/src/openvpn/otime.c \
345347
$(top_srcdir)/src/openvpn/packet_id.c \
346348
$(top_srcdir)/src/openvpn/platform.c \

tests/unit_tests/openvpn/test_crypto.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ test_mssfix_mtu_calculation(void **state)
363363
init_key_type(&kt, o.ciphername, o.authname, false, false);
364364

365365
/* No encryption, just packet id (8) + TCP payload(20) + IP payload(20) */
366-
frame_calculate_dynamic(&f, &kt, &o, NULL);
366+
frame_calculate_dynamic(&f, &kt, &o, o.imported_protocol_flags, NULL);
367367
assert_int_equal(f.mss_fix, 952);
368368

369369
/* Static key OCC examples */
@@ -373,7 +373,7 @@ test_mssfix_mtu_calculation(void **state)
373373
o.ciphername = "none";
374374
o.authname = "none";
375375
init_key_type(&kt, o.ciphername, o.authname, false, false);
376-
frame_calculate_dynamic(&f, &kt, &o, NULL);
376+
frame_calculate_dynamic(&f, &kt, &o, o.imported_protocol_flags, NULL);
377377
assert_int_equal(f.mss_fix, 952);
378378

379379
/* secret, cipher AES-128-CBC, auth none */
@@ -387,7 +387,7 @@ test_mssfix_mtu_calculation(void **state)
387387
* all result in the same CBC block size/padding and <= 991 and >=1008
388388
* should be one block less and more respectively */
389389
o.ce.mssfix = i;
390-
frame_calculate_dynamic(&f, &kt, &o, NULL);
390+
frame_calculate_dynamic(&f, &kt, &o, o.imported_protocol_flags, NULL);
391391
if (i <= 991)
392392
{
393393
assert_int_equal(f.mss_fix, 911);
@@ -413,7 +413,7 @@ test_mssfix_mtu_calculation(void **state)
413413
* all result in the same CBC block size/padding and <= 991 and >=1008
414414
* should be one block less and more respectively */
415415
o.ce.mssfix = i;
416-
frame_calculate_dynamic(&f, &kt, &o, NULL);
416+
frame_calculate_dynamic(&f, &kt, &o, o.imported_protocol_flags, NULL);
417417
if (i <= 991)
418418
{
419419
assert_int_equal(f.mss_fix, 910);
@@ -443,7 +443,7 @@ test_mssfix_mtu_calculation(void **state)
443443
/* For stream ciphers, the value should not be influenced by block
444444
* sizes or similar but always have the same difference */
445445
o.ce.mssfix = i;
446-
frame_calculate_dynamic(&f, &kt, &o, NULL);
446+
frame_calculate_dynamic(&f, &kt, &o, o.imported_protocol_flags, NULL);
447447

448448
/* 4 byte opcode/peerid, 4 byte pkt ID, 16 byte tag, 40 TCP+IP */
449449
assert_int_equal(f.mss_fix, i - 4 - 4 - 16 - 40);

0 commit comments

Comments
 (0)