Skip to content

Commit 49e7588

Browse files
committed
Add AEAD encryption function with explicit sequence number
1 parent 7cc1c33 commit 49e7588

1 file changed

Lines changed: 74 additions & 0 deletions

File tree

src/aead.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)