@@ -363,14 +363,108 @@ do_data_channel_round_trip(struct crypto_options *co)
363
363
/* compare */
364
364
assert_int_equal (buf .len , src .len );
365
365
assert_memory_equal (BPTR (& src ), BPTR (& buf ), i );
366
-
367
366
}
368
367
gc_free (& gc );
369
368
}
370
369
370
+ static void
371
+ encrypt_one_packet (struct crypto_options * co , int len )
372
+ {
373
+ struct frame frame ;
374
+ init_frame_parameters (& frame );
375
+
376
+ struct gc_arena gc = gc_new ();
377
+ struct buffer encrypt_workspace = alloc_buf_gc (BUF_SIZE (& frame ), & gc );
378
+ struct buffer decrypt_workspace = alloc_buf_gc (BUF_SIZE (& frame ), & gc );
379
+ struct buffer work = alloc_buf_gc (BUF_SIZE (& frame ), & gc );
380
+ struct buffer buf = clear_buf ();
381
+ struct buffer src = alloc_buf_gc (frame .buf .payload_size , & gc );
382
+ void * buf_p ;
383
+
384
+ ASSERT (buf_init (& work , frame .buf .headroom ));
385
+
386
+ /*
387
+ * Load src with random data.
388
+ */
389
+ ASSERT (buf_init (& src , 0 ));
390
+ ASSERT (len <= src .capacity );
391
+ src .len = len ;
392
+ ASSERT (rand_bytes (BPTR (& src ), BLEN (& src )));
371
393
394
+ /* copy source to input buf */
395
+ buf = work ;
396
+ buf_p = buf_write_alloc (& buf , BLEN (& src ));
397
+ ASSERT (buf_p );
398
+ memcpy (buf_p , BPTR (& src ), BLEN (& src ));
399
+
400
+ ASSERT (buf_init (& encrypt_workspace , frame .buf .headroom ));
401
+ openvpn_encrypt (& buf , encrypt_workspace , co );
402
+
403
+ /* decrypt */
404
+ openvpn_decrypt (& buf , decrypt_workspace , co , & frame , BPTR (& buf ));
405
+
406
+ /* compare */
407
+ assert_int_equal (buf .len , src .len );
408
+ assert_memory_equal (BPTR (& src ), BPTR (& buf ), len );
372
409
373
- struct crypto_options
410
+ gc_free (& gc );
411
+ }
412
+
413
+
414
+ static void
415
+ check_aead_limits (struct crypto_options * co , bool chachapoly )
416
+ {
417
+
418
+ /* Check that we correctly react when we have a nearing AEAD limits */
419
+
420
+ /* manually increase the send counter to be past
421
+ * the GCM usage limit */
422
+ co -> key_ctx_bi .encrypt .plaintext_blocks = 0x1ull << 40 ;
423
+
424
+
425
+ bool epoch = (co -> flags & CO_EPOCH_DATA_KEY_FORMAT );
426
+
427
+ int expected_epoch = epoch ? 4 : 0 ;
428
+
429
+ /* Ensure that we are still on the initial key (our init_crypto_options
430
+ * unit test method iterates the initial key to 4) or that it is 0 when
431
+ * epoch is not in use
432
+ */
433
+ assert_int_equal (co -> key_ctx_bi .encrypt .epoch , expected_epoch );
434
+
435
+ encrypt_one_packet (co , 1000 );
436
+
437
+ /* either epoch key has been updated or warning is enabled */
438
+ if (epoch && !chachapoly )
439
+ {
440
+ expected_epoch ++ ;
441
+ }
442
+
443
+ assert_int_equal (co -> key_ctx_bi .encrypt .epoch , expected_epoch );
444
+
445
+ if (!epoch )
446
+ {
447
+ /* Check always against the GCM usage limit here to see if that
448
+ * check works */
449
+ assert_true (aead_usage_limit_reached ((1ull << 36 ),
450
+ & co -> key_ctx_bi .encrypt ,
451
+ co -> packet_id .send .id ));
452
+ return ;
453
+ }
454
+
455
+ /* Move to the end of the epoch data key send PID range, ChachaPoly
456
+ * should now also move to a new epoch data key */
457
+ co -> packet_id .send .id = PACKET_ID_EPOCH_MAX ;
458
+
459
+ encrypt_one_packet (co , 1000 );
460
+ encrypt_one_packet (co , 1000 );
461
+
462
+ expected_epoch ++ ;
463
+ assert_int_equal (co -> key_ctx_bi .encrypt .epoch , expected_epoch );
464
+ }
465
+
466
+
467
+ static struct crypto_options
374
468
init_crypto_options (const char * cipher , const char * auth , bool epoch ,
375
469
struct key2 * statickey )
376
470
{
@@ -428,16 +522,21 @@ uninit_crypto_options(struct crypto_options *co)
428
522
static void
429
523
run_data_channel_with_cipher_epoch (const char * cipher )
430
524
{
525
+ bool ischacha = !strcmp (cipher , "ChaCha20-Poly1305" );
526
+
431
527
struct crypto_options co = init_crypto_options (cipher , "none" , true, NULL );
432
528
do_data_channel_round_trip (& co );
529
+ check_aead_limits (& co , ischacha );
433
530
uninit_crypto_options (& co );
434
531
}
435
532
436
533
static void
437
534
run_data_channel_with_cipher (const char * cipher , const char * auth )
438
535
{
536
+ bool ischacha = !strcmp (cipher , "ChaCha20-Poly1305" );
439
537
struct crypto_options co = init_crypto_options (cipher , auth , false, NULL );
440
538
do_data_channel_round_trip (& co );
539
+ check_aead_limits (& co , ischacha );
441
540
uninit_crypto_options (& co );
442
541
}
443
542
0 commit comments