22
22
//! [`crypto.cipher.AEAD`]: https://golang.org/pkg/crypto/cipher/#AEAD
23
23
24
24
use self :: block:: { Block , BLOCK_LEN } ;
25
- use crate :: { constant_time, cpu, error, hkdf, polyfill} ;
25
+ use crate :: { constant_time, cpu, error, hkdf, polyfill, rand } ;
26
26
use core:: ops:: RangeFrom ;
27
27
28
28
pub use self :: {
@@ -445,18 +445,58 @@ impl hkdf::KeyType for &'static Algorithm {
445
445
}
446
446
}
447
447
448
+ mod sealed {
449
+ pub trait NonceGeneration {
450
+ const VALUE : Self ;
451
+ }
452
+ }
453
+
454
+ /// A nonce generation strategy for `LesssSafeKey`; either `ExplicitNonces` or
455
+ /// `RandomNonces`.
456
+ pub trait NonceGeneration : sealed:: NonceGeneration { }
457
+ impl < T > NonceGeneration for T where T : sealed:: NonceGeneration { }
458
+
459
+ /// A nonce generation strategy where random nonces are used.
460
+ ///
461
+ /// These algorithms are *NOT* nonce-misuse-resistant. They use nonces small
462
+ /// enough where birthday collisions need to be considered, so even ensuring
463
+ /// perfectly-random generation of nonces isn't sufficient to prevent nonce
464
+ /// reuse.
465
+ pub struct RandomNonces ( ( ) ) ;
466
+ impl sealed:: NonceGeneration for RandomNonces {
467
+ const VALUE : Self = Self ( ( ) ) ;
468
+ }
469
+
470
+ /// A nonce generation strategy where explicitly-constructed nonces are used.
471
+ pub struct ExplicitNonces ( ( ) ) ;
472
+ impl sealed:: NonceGeneration for ExplicitNonces {
473
+ const VALUE : Self = Self ( ( ) ) ;
474
+ }
475
+
448
476
/// Immutable keys for use in situations where `OpeningKey`/`SealingKey` and
449
477
/// `NonceSequence` cannot reasonably be used.
450
478
///
451
- /// Prefer to use `OpeningKey`/`SealingKey` and `NonceSequence` when practical.
452
- pub struct LessSafeKey {
479
+ /// These algorithms are *NOT* nonce-misuse-resistant. They use nonces small
480
+ /// enough where the likelihood of collisions must be carefully considered.
481
+ pub struct LessSafeKey < N = ExplicitNonces >
482
+ where
483
+ N : NonceGeneration ,
484
+ {
453
485
key : UnboundKey ,
486
+ _nonce_generation : N ,
454
487
}
455
488
456
- impl LessSafeKey {
489
+ impl < N > LessSafeKey < N >
490
+ where
491
+ N : NonceGeneration ,
492
+ {
457
493
/// Constructs a `LessSafeKey` from an `UnboundKey`.
494
+ #[ inline]
458
495
pub fn new ( key : UnboundKey ) -> Self {
459
- Self { key }
496
+ Self {
497
+ key,
498
+ _nonce_generation : N :: VALUE ,
499
+ }
460
500
}
461
501
462
502
/// Like [`OpeningKey::open_in_place()`], except it accepts an arbitrary nonce.
@@ -492,6 +532,14 @@ impl LessSafeKey {
492
532
open_within_ ( & self . key , nonce, aad, in_out, ciphertext_and_tag)
493
533
}
494
534
535
+ /// The key's AEAD algorithm.
536
+ #[ inline]
537
+ pub fn algorithm ( & self ) -> & ' static Algorithm {
538
+ & self . key . algorithm
539
+ }
540
+ }
541
+
542
+ impl LessSafeKey < ExplicitNonces > {
495
543
/// Deprecated. Renamed to [`seal_in_place_append_tag()`].
496
544
#[ deprecated( note = "Renamed to `seal_in_place_append_tag`." ) ]
497
545
#[ inline]
@@ -523,6 +571,9 @@ impl LessSafeKey {
523
571
A : AsRef < [ u8 ] > ,
524
572
InOut : AsMut < [ u8 ] > + for < ' in_out > Extend < & ' in_out u8 > ,
525
573
{
574
+ // Overwrite the plaintext with the ciphertext before extending `in_out`
575
+ // so that if the `extend()` causes a reallocation, the ciphertext (not
576
+ // the plaintext) will be in the old deallocated buffer.
526
577
self . seal_in_place_separate_tag ( nonce, aad, in_out. as_mut ( ) )
527
578
. map ( |tag| in_out. extend ( tag. as_ref ( ) ) )
528
579
}
@@ -543,15 +594,63 @@ impl LessSafeKey {
543
594
{
544
595
seal_in_place_separate_tag_ ( & self . key , nonce, Aad :: from ( aad. as_ref ( ) ) , in_out)
545
596
}
597
+ }
546
598
547
- /// The key's AEAD algorithm.
599
+ impl LessSafeKey < RandomNonces > {
600
+ /// Like [`SealingKey::seal_in_place_append_tag()`], except the nonce is
601
+ /// randomly generated.
602
+ ///
603
+ /// The randomly-generated nonce is returned on success.
548
604
#[ inline]
549
- pub fn algorithm ( & self ) -> & ' static Algorithm {
550
- & self . key . algorithm
605
+ pub fn seal_with_random_nonce_in_place_append_tag < A , InOut > (
606
+ & self ,
607
+ aad : Aad < A > ,
608
+ in_out : & mut InOut ,
609
+ rng : & dyn rand:: SecureRandom ,
610
+ ) -> Result < Nonce , error:: Unspecified >
611
+ where
612
+ A : AsRef < [ u8 ] > ,
613
+ InOut : AsMut < [ u8 ] > + for < ' in_out > Extend < & ' in_out u8 > ,
614
+ {
615
+ // Overwrite the plaintext with the ciphertext before extending `in_out`
616
+ // so that if the `extend()` causes a reallocation, the ciphertext (not
617
+ // the plaintext) will be in the old deallocated buffer.
618
+ self . seal_with_random_nonce_in_place_separate_tag ( aad, in_out. as_mut ( ) , rng)
619
+ . map ( |( nonce, tag) | {
620
+ in_out. extend ( tag. as_ref ( ) ) ;
621
+ nonce
622
+ } )
623
+ }
624
+
625
+ /// Like [`SealingKey::seal_in_place_separate_tag()`], except the nonce is
626
+ /// randomly generated.
627
+ ///
628
+ /// The randomly-generated nonce and the tag are returned on success.
629
+ #[ inline]
630
+ pub fn seal_with_random_nonce_in_place_separate_tag < A > (
631
+ & self ,
632
+ aad : Aad < A > ,
633
+ in_out : & mut [ u8 ] ,
634
+ rng : & dyn rand:: SecureRandom ,
635
+ ) -> Result < ( Nonce , Tag ) , error:: Unspecified >
636
+ where
637
+ A : AsRef < [ u8 ] > ,
638
+ {
639
+ let nonce = Nonce :: assume_unique_for_key ( rand:: generate ( rng) ?. expose ( ) ) ;
640
+ seal_in_place_separate_tag_ (
641
+ & self . key ,
642
+ Nonce :: assume_unique_for_key ( * nonce. as_ref ( ) ) ,
643
+ Aad :: from ( aad. as_ref ( ) ) ,
644
+ in_out,
645
+ )
646
+ . map ( |tag| ( nonce, tag) )
551
647
}
552
648
}
553
649
554
- impl core:: fmt:: Debug for LessSafeKey {
650
+ impl < N > core:: fmt:: Debug for LessSafeKey < N >
651
+ where
652
+ N : NonceGeneration ,
653
+ {
555
654
fn fmt ( & self , f : & mut core:: fmt:: Formatter ) -> Result < ( ) , core:: fmt:: Error > {
556
655
f. debug_struct ( "LessSafeKey" )
557
656
. field ( "algorithm" , self . algorithm ( ) )
0 commit comments