@@ -590,6 +590,51 @@ impl Aead {
590590 Ok ( ct)
591591 }
592592
593+ /// Encrypt with an explicit sequence number. Mirrors `open`'s nonce
594+ /// construction: the final nonce is `nonce_base XOR encode_be(seq)` over
595+ /// the trailing 8 bytes. The NSS PKCS#11 context's internal counter is
596+ /// not used (CKG_NO_GENERATE). The caller must never reuse
597+ /// `(nonce_base, seq)` with the same key.
598+ pub fn encrypt_with_seq (
599+ & mut self ,
600+ aad : & [ u8 ] ,
601+ seq : SequenceNumber ,
602+ pt : & [ u8 ] ,
603+ ) -> Result < Vec < u8 > , Error > {
604+ crate :: init ( ) ?;
605+
606+ assert_eq ! ( self . mode, Mode :: Encrypt ) ;
607+ let mut nonce = self . nonce_base ;
608+ for ( i, n) in nonce. iter_mut ( ) . rev ( ) . take ( COUNTER_LEN ) . enumerate ( ) {
609+ * n ^= u8:: try_from ( ( seq >> ( 8 * i) ) & 0xff ) . unwrap ( ) ;
610+ }
611+ let mut ct = vec ! [ 0 ; pt. len( ) + TAG_LEN ] ;
612+ let mut ct_len: c_int = 0 ;
613+ let mut tag = vec ! [ 0 ; TAG_LEN ] ;
614+ secstatus_to_res ( unsafe {
615+ PK11_AEADOp (
616+ * self . ctx ,
617+ CK_GENERATOR_FUNCTION :: from ( CKG_NO_GENERATE ) ,
618+ 0 ,
619+ nonce. as_mut_ptr ( ) ,
620+ c_int_len ( nonce. len ( ) ) ?,
621+ aad. as_ptr ( ) ,
622+ c_int_len ( aad. len ( ) ) ?,
623+ ct. as_mut_ptr ( ) ,
624+ & mut ct_len,
625+ c_int_len ( ct. len ( ) ) ?,
626+ tag. as_mut_ptr ( ) ,
627+ c_int_len ( tag. len ( ) ) ?,
628+ pt. as_ptr ( ) ,
629+ c_int_len ( pt. len ( ) ) ?,
630+ )
631+ } ) ?;
632+ ct. truncate ( usize:: try_from ( ct_len) . unwrap ( ) ) ;
633+ debug_assert_eq ! ( ct. len( ) , pt. len( ) ) ;
634+ ct. append ( & mut tag) ;
635+ Ok ( ct)
636+ }
637+
593638 pub fn decrypt (
594639 & mut self ,
595640 aad : & [ u8 ] ,
@@ -767,4 +812,33 @@ mod test {
767812 // Now use the real nonce and sequence number from the example.
768813 decrypt ( ALG , KEY , NONCE_BASE , 654_360_564 , AAD , PT , CT ) ;
769814 }
815+
816+ fn roundtrip_seal_with_seq ( algorithm : AeadAlgorithms , key : & [ u8 ] ) {
817+ fixture_init ( ) ;
818+
819+ const NONCE_BASE : [ u8 ; NONCE_LEN ] = [ 0 ; NONCE_LEN ] ;
820+ const AAD : & [ u8 ] = b"associated" ;
821+ const PT : & [ u8 ] = b"hello sframe" ;
822+ const SEQ : SequenceNumber = 0x0123_4567_89ab ;
823+
824+ let k = Aead :: import_key ( algorithm, key) . unwrap ( ) ;
825+ let mut enc = Aead :: new ( Mode :: Encrypt , algorithm, & k, NONCE_BASE ) . unwrap ( ) ;
826+ let ct = enc. encrypt_with_seq ( AAD , SEQ , PT ) . unwrap ( ) ;
827+
828+ let mut dec = Aead :: new ( Mode :: Decrypt , algorithm, & k, NONCE_BASE ) . unwrap ( ) ;
829+ let pt = dec. decrypt ( AAD , SEQ , & ct) . unwrap ( ) ;
830+ assert_eq ! ( & pt[ ..] , PT ) ;
831+ }
832+
833+ #[ test]
834+ fn seal_with_seq_aes128gcm ( ) {
835+ const KEY : & [ u8 ] = & [ 0x42 ; 16 ] ;
836+ roundtrip_seal_with_seq ( AeadAlgorithms :: Aes128Gcm , KEY ) ;
837+ }
838+
839+ #[ test]
840+ fn seal_with_seq_aes256gcm ( ) {
841+ const KEY : & [ u8 ] = & [ 0x42 ; 32 ] ;
842+ roundtrip_seal_with_seq ( AeadAlgorithms :: Aes256Gcm , KEY ) ;
843+ }
770844}
0 commit comments