snow/resolvers/
default.rs

1use blake2::{Blake2b, Blake2b512, Blake2s, Blake2s256};
2#[cfg(feature = "xchachapoly")]
3use chacha20poly1305::XChaCha20Poly1305;
4use chacha20poly1305::{aead::AeadInPlace, ChaCha20Poly1305, KeyInit};
5use curve25519_dalek::montgomery::MontgomeryPoint;
6#[cfg(feature = "pqclean_kyber1024")]
7use pqcrypto_kyber::kyber1024;
8#[cfg(feature = "pqclean_kyber1024")]
9use pqcrypto_traits::kem::{Ciphertext, PublicKey, SecretKey, SharedSecret};
10use rand_core::OsRng;
11use sha2::{Digest, Sha256, Sha512};
12
13use super::CryptoResolver;
14#[cfg(feature = "pqclean_kyber1024")]
15use crate::params::KemChoice;
16#[cfg(feature = "pqclean_kyber1024")]
17use crate::types::Kem;
18use crate::{
19    constants::TAGLEN,
20    params::{CipherChoice, DHChoice, HashChoice},
21    types::{Cipher, Dh, Hash, Random},
22    Error,
23};
24
25/// The default resolver provided by snow. This resolver is designed to
26/// support as many of the Noise spec primitives as possible with
27/// pure-Rust (or nearly pure-Rust) implementations.
28#[derive(Default)]
29pub struct DefaultResolver;
30
31impl CryptoResolver for DefaultResolver {
32    fn resolve_rng(&self) -> Option<Box<dyn Random>> {
33        Some(Box::new(OsRng::default()))
34    }
35
36    fn resolve_dh(&self, choice: &DHChoice) -> Option<Box<dyn Dh>> {
37        match *choice {
38            DHChoice::Curve25519 => Some(Box::new(Dh25519::default())),
39            _ => None,
40        }
41    }
42
43    fn resolve_hash(&self, choice: &HashChoice) -> Option<Box<dyn Hash>> {
44        match *choice {
45            HashChoice::SHA256 => Some(Box::new(HashSHA256::default())),
46            HashChoice::SHA512 => Some(Box::new(HashSHA512::default())),
47            HashChoice::Blake2s => Some(Box::new(HashBLAKE2s::default())),
48            HashChoice::Blake2b => Some(Box::new(HashBLAKE2b::default())),
49        }
50    }
51
52    fn resolve_cipher(&self, choice: &CipherChoice) -> Option<Box<dyn Cipher>> {
53        match *choice {
54            CipherChoice::ChaChaPoly => Some(Box::new(CipherChaChaPoly::default())),
55            #[cfg(feature = "xchachapoly")]
56            CipherChoice::XChaChaPoly => Some(Box::new(CipherXChaChaPoly::default())),
57            CipherChoice::AESGCM => Some(Box::new(CipherAesGcm::default())),
58        }
59    }
60
61    #[cfg(feature = "pqclean_kyber1024")]
62    fn resolve_kem(&self, choice: &KemChoice) -> Option<Box<dyn Kem>> {
63        match *choice {
64            KemChoice::Kyber1024 => Some(Box::new(Kyber1024::default())),
65        }
66    }
67}
68
69/// Wraps x25519-dalek.
70#[derive(Default)]
71struct Dh25519 {
72    privkey: [u8; 32],
73    pubkey:  [u8; 32],
74}
75
76/// Wraps `aes-gcm`'s AES256-GCM implementation.
77#[derive(Default)]
78struct CipherAesGcm {
79    key: [u8; 32],
80}
81
82/// Wraps `chacha20_poly1305_aead`'s ChaCha20Poly1305 implementation.
83#[derive(Default)]
84struct CipherChaChaPoly {
85    key: [u8; 32],
86}
87
88/// Wraps `chachapoly1305`'s XChaCha20Poly1305 implementation.
89#[cfg(feature = "xchachapoly")]
90#[derive(Default)]
91struct CipherXChaChaPoly {
92    key: [u8; 32],
93}
94
95/// Wraps `RustCrypto`'s SHA-256 implementation.
96struct HashSHA256 {
97    hasher: Sha256,
98}
99
100/// Wraps `RustCrypto`'s SHA-512 implementation.
101struct HashSHA512 {
102    hasher: Sha512,
103}
104
105/// Wraps `blake2-rfc`'s implementation.
106#[derive(Default)]
107struct HashBLAKE2b {
108    hasher: Blake2b512,
109}
110
111/// Wraps `blake2-rfc`'s implementation.
112#[derive(Default)]
113struct HashBLAKE2s {
114    hasher: Blake2s256,
115}
116
117/// Wraps `kyber1024`'s implementation
118#[cfg(feature = "pqclean_kyber1024")]
119struct Kyber1024 {
120    privkey: kyber1024::SecretKey,
121    pubkey:  kyber1024::PublicKey,
122}
123
124impl Random for OsRng {}
125
126impl Dh25519 {
127    fn derive_pubkey(&mut self) {
128        let point = MontgomeryPoint::mul_base_clamped(self.privkey);
129        self.pubkey = point.to_bytes();
130    }
131}
132
133impl Dh for Dh25519 {
134    fn name(&self) -> &'static str {
135        "25519"
136    }
137
138    fn pub_len(&self) -> usize {
139        32
140    }
141
142    fn priv_len(&self) -> usize {
143        32
144    }
145
146    fn set(&mut self, privkey: &[u8]) {
147        let mut bytes = [0u8; 32];
148        copy_slices!(privkey, bytes);
149        self.privkey = bytes;
150        self.derive_pubkey();
151    }
152
153    fn generate(&mut self, rng: &mut dyn Random) {
154        let mut bytes = [0u8; 32];
155        rng.fill_bytes(&mut bytes);
156        self.privkey = bytes;
157        self.derive_pubkey();
158    }
159
160    fn pubkey(&self) -> &[u8] {
161        &self.pubkey
162    }
163
164    fn privkey(&self) -> &[u8] {
165        &self.privkey
166    }
167
168    fn dh(&self, pubkey: &[u8], out: &mut [u8]) -> Result<(), Error> {
169        let mut pubkey_owned = [0u8; 32];
170        copy_slices!(&pubkey[..32], pubkey_owned);
171        let result = MontgomeryPoint(pubkey_owned).mul_clamped(self.privkey).to_bytes();
172        copy_slices!(result, out);
173        Ok(())
174    }
175}
176
177impl Cipher for CipherAesGcm {
178    fn name(&self) -> &'static str {
179        "AESGCM"
180    }
181
182    fn set(&mut self, key: &[u8]) {
183        copy_slices!(key, &mut self.key)
184    }
185
186    fn encrypt(&self, nonce: u64, authtext: &[u8], plaintext: &[u8], out: &mut [u8]) -> usize {
187        let aead = aes_gcm::Aes256Gcm::new(&self.key.into());
188
189        let mut nonce_bytes = [0u8; 12];
190        copy_slices!(nonce.to_be_bytes(), &mut nonce_bytes[4..]);
191
192        copy_slices!(plaintext, out);
193
194        let tag = aead
195            .encrypt_in_place_detached(&nonce_bytes.into(), authtext, &mut out[0..plaintext.len()])
196            .expect("Encryption failed!");
197
198        copy_slices!(tag, &mut out[plaintext.len()..]);
199
200        plaintext.len() + TAGLEN
201    }
202
203    fn decrypt(
204        &self,
205        nonce: u64,
206        authtext: &[u8],
207        ciphertext: &[u8],
208        out: &mut [u8],
209    ) -> Result<usize, Error> {
210        let aead = aes_gcm::Aes256Gcm::new(&self.key.into());
211
212        let mut nonce_bytes = [0u8; 12];
213        copy_slices!(nonce.to_be_bytes(), &mut nonce_bytes[4..]);
214
215        let message_len = ciphertext.len() - TAGLEN;
216
217        copy_slices!(ciphertext[..message_len], out);
218
219        aead.decrypt_in_place_detached(
220            &nonce_bytes.into(),
221            authtext,
222            &mut out[..message_len],
223            ciphertext[message_len..].into(),
224        )
225        .map(|_| message_len)
226        .map_err(|_| Error::Decrypt)
227    }
228}
229
230impl Cipher for CipherChaChaPoly {
231    fn name(&self) -> &'static str {
232        "ChaChaPoly"
233    }
234
235    fn set(&mut self, key: &[u8]) {
236        copy_slices!(key, &mut self.key);
237    }
238
239    fn encrypt(&self, nonce: u64, authtext: &[u8], plaintext: &[u8], out: &mut [u8]) -> usize {
240        let mut nonce_bytes = [0u8; 12];
241        copy_slices!(nonce.to_le_bytes(), &mut nonce_bytes[4..]);
242
243        copy_slices!(plaintext, out);
244
245        let tag = ChaCha20Poly1305::new(&self.key.into())
246            .encrypt_in_place_detached(&nonce_bytes.into(), authtext, &mut out[0..plaintext.len()])
247            .unwrap();
248
249        copy_slices!(tag, &mut out[plaintext.len()..]);
250
251        plaintext.len() + tag.len()
252    }
253
254    fn decrypt(
255        &self,
256        nonce: u64,
257        authtext: &[u8],
258        ciphertext: &[u8],
259        out: &mut [u8],
260    ) -> Result<usize, Error> {
261        let mut nonce_bytes = [0u8; 12];
262        copy_slices!(nonce.to_le_bytes(), &mut nonce_bytes[4..]);
263
264        let message_len = ciphertext.len() - TAGLEN;
265
266        copy_slices!(ciphertext[..message_len], out);
267
268        ChaCha20Poly1305::new(&self.key.into())
269            .decrypt_in_place_detached(
270                &nonce_bytes.into(),
271                authtext,
272                &mut out[..message_len],
273                ciphertext[message_len..].into(),
274            )
275            .map_err(|_| Error::Decrypt)?;
276
277        Ok(message_len)
278    }
279}
280
281#[cfg(feature = "xchachapoly")]
282impl Cipher for CipherXChaChaPoly {
283    fn name(&self) -> &'static str {
284        "XChaChaPoly"
285    }
286
287    fn set(&mut self, key: &[u8]) {
288        copy_slices!(key, &mut self.key);
289    }
290
291    fn encrypt(&self, nonce: u64, authtext: &[u8], plaintext: &[u8], out: &mut [u8]) -> usize {
292        let mut nonce_bytes = [0u8; 24];
293        copy_slices!(&nonce.to_le_bytes(), &mut nonce_bytes[16..]);
294
295        copy_slices!(plaintext, out);
296
297        let tag = XChaCha20Poly1305::new(&self.key.into())
298            .encrypt_in_place_detached(&nonce_bytes.into(), authtext, &mut out[0..plaintext.len()])
299            .unwrap();
300
301        copy_slices!(tag, &mut out[plaintext.len()..]);
302
303        plaintext.len() + tag.len()
304    }
305
306    fn decrypt(
307        &self,
308        nonce: u64,
309        authtext: &[u8],
310        ciphertext: &[u8],
311        out: &mut [u8],
312    ) -> Result<usize, Error> {
313        let mut nonce_bytes = [0u8; 24];
314        copy_slices!(&nonce.to_le_bytes(), &mut nonce_bytes[16..]);
315
316        let message_len = ciphertext.len() - TAGLEN;
317
318        copy_slices!(ciphertext[..message_len], out);
319
320        XChaCha20Poly1305::new(&self.key.into())
321            .decrypt_in_place_detached(
322                &nonce_bytes.into(),
323                authtext,
324                &mut out[..message_len],
325                ciphertext[message_len..].into(),
326            )
327            .map_err(|_| Error::Decrypt)?;
328
329        Ok(message_len)
330    }
331}
332
333impl Default for HashSHA256 {
334    fn default() -> HashSHA256 {
335        HashSHA256 { hasher: Sha256::new() }
336    }
337}
338
339impl Hash for HashSHA256 {
340    fn block_len(&self) -> usize {
341        64
342    }
343
344    fn hash_len(&self) -> usize {
345        32
346    }
347
348    fn name(&self) -> &'static str {
349        "SHA256"
350    }
351
352    fn reset(&mut self) {
353        self.hasher = Sha256::new();
354    }
355
356    fn input(&mut self, data: &[u8]) {
357        self.hasher.update(data);
358    }
359
360    fn result(&mut self, out: &mut [u8]) {
361        let hash = self.hasher.finalize_reset();
362        copy_slices!(hash.as_slice(), out)
363    }
364}
365
366impl Default for HashSHA512 {
367    fn default() -> HashSHA512 {
368        HashSHA512 { hasher: Sha512::new() }
369    }
370}
371
372impl Hash for HashSHA512 {
373    fn name(&self) -> &'static str {
374        "SHA512"
375    }
376
377    fn block_len(&self) -> usize {
378        128
379    }
380
381    fn hash_len(&self) -> usize {
382        64
383    }
384
385    fn reset(&mut self) {
386        self.hasher = Sha512::new();
387    }
388
389    fn input(&mut self, data: &[u8]) {
390        self.hasher.update(data);
391    }
392
393    fn result(&mut self, out: &mut [u8]) {
394        let hash = self.hasher.finalize_reset();
395        copy_slices!(hash.as_slice(), out)
396    }
397}
398
399impl Hash for HashBLAKE2b {
400    fn name(&self) -> &'static str {
401        "BLAKE2b"
402    }
403
404    fn block_len(&self) -> usize {
405        128
406    }
407
408    fn hash_len(&self) -> usize {
409        64
410    }
411
412    fn reset(&mut self) {
413        self.hasher = Blake2b::default();
414    }
415
416    fn input(&mut self, data: &[u8]) {
417        self.hasher.update(data);
418    }
419
420    fn result(&mut self, out: &mut [u8]) {
421        let hash = self.hasher.finalize_reset();
422        out[..64].copy_from_slice(&hash);
423    }
424}
425
426impl Hash for HashBLAKE2s {
427    fn name(&self) -> &'static str {
428        "BLAKE2s"
429    }
430
431    fn block_len(&self) -> usize {
432        64
433    }
434
435    fn hash_len(&self) -> usize {
436        32
437    }
438
439    fn reset(&mut self) {
440        self.hasher = Blake2s::default();
441    }
442
443    fn input(&mut self, data: &[u8]) {
444        self.hasher.update(data);
445    }
446
447    fn result(&mut self, out: &mut [u8]) {
448        let hash = self.hasher.finalize_reset();
449        out[..32].copy_from_slice(&hash);
450    }
451}
452
453#[cfg(feature = "pqclean_kyber1024")]
454impl Default for Kyber1024 {
455    fn default() -> Self {
456        Kyber1024 {
457            pubkey:  kyber1024::PublicKey::from_bytes(&[0; kyber1024::public_key_bytes()]).unwrap(),
458            privkey: kyber1024::SecretKey::from_bytes(&[0; kyber1024::secret_key_bytes()]).unwrap(),
459        }
460    }
461}
462
463#[cfg(feature = "pqclean_kyber1024")]
464impl Kem for Kyber1024 {
465    fn name(&self) -> &'static str {
466        "Kyber1024"
467    }
468
469    /// The length in bytes of a public key for this primitive.
470    fn pub_len(&self) -> usize {
471        kyber1024::public_key_bytes()
472    }
473
474    /// The length in bytes the Kem cipherthext for this primitive.
475    fn ciphertext_len(&self) -> usize {
476        kyber1024::ciphertext_bytes()
477    }
478
479    /// Shared secret length in bytes that this Kem encapsulates.
480    fn shared_secret_len(&self) -> usize {
481        kyber1024::shared_secret_bytes()
482    }
483
484    /// Generate a new private key.
485    fn generate(&mut self, _rng: &mut dyn Random) {
486        // PQClean uses their own random generator
487        let (pk, sk) = kyber1024::keypair();
488        self.pubkey = pk;
489        self.privkey = sk;
490    }
491
492    /// Get the public key.
493    fn pubkey(&self) -> &[u8] {
494        self.pubkey.as_bytes()
495    }
496
497    /// Generate a shared secret and encapsulate it using this Kem.
498    #[must_use]
499    fn encapsulate(
500        &self,
501        pubkey: &[u8],
502        shared_secret_out: &mut [u8],
503        ciphertext_out: &mut [u8],
504    ) -> Result<(usize, usize), ()> {
505        let pubkey = kyber1024::PublicKey::from_bytes(pubkey).map_err(|_| ())?;
506        let (shared_secret, ciphertext) = kyber1024::encapsulate(&pubkey);
507        shared_secret_out.copy_from_slice(shared_secret.as_bytes());
508        ciphertext_out.copy_from_slice(ciphertext.as_bytes());
509        Ok((shared_secret.as_bytes().len(), ciphertext.as_bytes().len()))
510    }
511
512    /// Decapsulate a ciphertext producing a shared secret.
513    #[must_use]
514    fn decapsulate(&self, ciphertext: &[u8], shared_secret_out: &mut [u8]) -> Result<usize, ()> {
515        let ciphertext = kyber1024::Ciphertext::from_bytes(ciphertext).map_err(|_| ())?;
516        let shared_secret = kyber1024::decapsulate(&ciphertext, &self.privkey);
517        shared_secret_out.copy_from_slice(shared_secret.as_bytes());
518        Ok(shared_secret.as_bytes().len())
519    }
520}
521
522#[cfg(test)]
523mod tests {
524    use super::*;
525    use hex::FromHex;
526
527    #[test]
528    fn test_sha256() {
529        let mut output = [0u8; 32];
530        let mut hasher: HashSHA256 = Default::default();
531        hasher.input(b"abc");
532        hasher.result(&mut output);
533        assert!(
534            hex::encode(output)
535                == "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
536        );
537    }
538
539    #[test]
540    fn test_hmac_sha256_sha512() {
541        let key = Vec::<u8>::from_hex("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").unwrap();
542        let data = Vec::<u8>::from_hex(
543            "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
544        )
545        .unwrap();
546        let mut output1 = [0u8; 32];
547        let mut hasher: HashSHA256 = Default::default();
548        hasher.hmac(&key, &data, &mut output1);
549        assert!(
550            hex::encode(output1)
551                == "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe"
552        );
553
554        let mut output2 = [0u8; 64];
555        let mut hasher: HashSHA512 = Default::default();
556        hasher.hmac(&key, &data, &mut output2);
557        assert!(
558            hex::encode(output2.to_vec())
559                == "fa73b0089d56a284efb0f0756c890be9\
560                                     b1b5dbdd8ee81a3655f83e33b2279d39\
561                                     bf3e848279a722c806b485a47e67c807\
562                                     b946a337bee8942674278859e13292fb"
563        );
564    }
565
566    #[test]
567    fn test_blake2b() {
568        // BLAKE2b test - draft-saarinen-blake2-06
569        let mut output = [0u8; 64];
570        let mut hasher: HashBLAKE2b = Default::default();
571        hasher.input(b"abc");
572        hasher.result(&mut output);
573        assert!(
574            hex::encode(output.to_vec())
575                == "ba80a53f981c4d0d6a2797b69f12f6e9\
576                                    4c212f14685ac4b74b12bb6fdbffa2d1\
577                                    7d87c5392aab792dc252d5de4533cc95\
578                                    18d38aa8dbf1925ab92386edd4009923"
579        );
580    }
581
582    #[test]
583    fn test_blake2s() {
584        // BLAKE2s test - draft-saarinen-blake2-06
585        let mut output = [0u8; 32];
586        let mut hasher: HashBLAKE2s = Default::default();
587        hasher.input(b"abc");
588        hasher.result(&mut output);
589        assert!(
590            hex::encode(output)
591                == "508c5e8c327c14e2e1a72ba34eeb452f\
592                    37458b209ed63a294d999b4c86675982"
593        );
594    }
595
596    #[test]
597    fn test_curve25519() {
598        // Curve25519 test - draft-curves-10
599        let mut keypair: Dh25519 = Default::default();
600        let scalar =
601            Vec::<u8>::from_hex("a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4")
602                .unwrap();
603        keypair.set(&scalar);
604        let public =
605            Vec::<u8>::from_hex("e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c")
606                .unwrap();
607        let mut output = [0u8; 32];
608        keypair.dh(&public, &mut output).unwrap();
609        assert_eq!(
610            hex::encode(output),
611            "c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552"
612        );
613    }
614
615    #[test]
616    fn test_aesgcm() {
617        // AES256-GCM tests - gcm-spec.pdf
618        // Test Case 13
619        let key = [0u8; 32];
620        let nonce = 0u64;
621        let plaintext = [0u8; 0];
622        let authtext = [0u8; 0];
623        let mut ciphertext = [0u8; 16];
624        let mut cipher1: CipherAesGcm = Default::default();
625        cipher1.set(&key);
626        cipher1.encrypt(nonce, &authtext, &plaintext, &mut ciphertext);
627        assert!(hex::encode(ciphertext) == "530f8afbc74536b9a963b4f1c4cb738b");
628
629        let mut resulttext = [0u8; 1];
630        let mut cipher2: CipherAesGcm = Default::default();
631        cipher2.set(&key);
632        cipher2.decrypt(nonce, &authtext, &ciphertext, &mut resulttext).unwrap();
633        assert!(resulttext[0] == 0);
634        ciphertext[0] ^= 1;
635        assert!(cipher2.decrypt(nonce, &authtext, &ciphertext, &mut resulttext).is_err());
636
637        // Test Case 14
638        let plaintext2 = [0u8; 16];
639        let mut ciphertext2 = [0u8; 32];
640        let mut cipher3: CipherAesGcm = Default::default();
641        cipher3.set(&key);
642        cipher3.encrypt(nonce, &authtext, &plaintext2, &mut ciphertext2);
643        assert!(
644            hex::encode(ciphertext2)
645                == "cea7403d4d606b6e074ec5d3baf39d18d0d1c8a799996bf0265b98b5d48ab919"
646        );
647
648        let mut resulttext2 = [1u8; 16];
649        let mut cipher4: CipherAesGcm = Default::default();
650        cipher4.set(&key);
651        cipher4.decrypt(nonce, &authtext, &ciphertext2, &mut resulttext2).unwrap();
652        assert!(plaintext2 == resulttext2);
653        ciphertext2[0] ^= 1;
654        assert!(cipher4.decrypt(nonce, &authtext, &ciphertext2, &mut resulttext2).is_err());
655    }
656
657    #[test]
658    fn test_chachapoly_empty() {
659        //ChaChaPoly round-trip test, empty plaintext
660        let key = [0u8; 32];
661        let nonce = 0u64;
662        let plaintext = [0u8; 0];
663        let authtext = [0u8; 0];
664        let mut ciphertext = [0u8; 16];
665        let mut cipher1: CipherChaChaPoly = Default::default();
666        cipher1.set(&key);
667        cipher1.encrypt(nonce, &authtext, &plaintext, &mut ciphertext);
668
669        let mut resulttext = [0u8; 1];
670        let mut cipher2: CipherChaChaPoly = Default::default();
671        cipher2.set(&key);
672        cipher2.decrypt(nonce, &authtext, &ciphertext, &mut resulttext).unwrap();
673        assert!(resulttext[0] == 0);
674        ciphertext[0] ^= 1;
675        assert!(cipher2.decrypt(nonce, &authtext, &ciphertext, &mut resulttext).is_err());
676    }
677
678    #[test]
679    fn test_chachapoly_nonempty() {
680        //ChaChaPoly round-trip test, non-empty plaintext
681        let key = [0u8; 32];
682        let nonce = 0u64;
683        let plaintext = [0x34u8; 117];
684        let authtext = [0u8; 0];
685        let mut ciphertext = [0u8; 133];
686        let mut cipher1: CipherChaChaPoly = Default::default();
687        cipher1.set(&key);
688        cipher1.encrypt(nonce, &authtext, &plaintext, &mut ciphertext);
689
690        let mut resulttext = [0u8; 117];
691        let mut cipher2: CipherChaChaPoly = Default::default();
692        cipher2.set(&key);
693        cipher2.decrypt(nonce, &authtext, &ciphertext, &mut resulttext).unwrap();
694        assert!(hex::encode(resulttext.to_vec()) == hex::encode(plaintext.to_vec()));
695    }
696
697    #[cfg(feature = "xchachapoly")]
698    #[test]
699    fn test_xchachapoly_nonempty() {
700        //XChaChaPoly round-trip test, non-empty plaintext
701        let key = [0u8; 32];
702        let nonce = 0u64;
703        let plaintext = [0x34u8; 117];
704        let authtext = [0u8; 0];
705        let mut ciphertext = [0u8; 133];
706        let mut cipher1: CipherXChaChaPoly = Default::default();
707        cipher1.set(&key);
708        cipher1.encrypt(nonce, &authtext, &plaintext, &mut ciphertext);
709
710        let mut resulttext = [0u8; 117];
711        let mut cipher2: CipherXChaChaPoly = Default::default();
712        cipher2.set(&key);
713        cipher2.decrypt(nonce, &authtext, &ciphertext, &mut resulttext).unwrap();
714        assert!(hex::encode(resulttext.to_vec()) == hex::encode(plaintext.to_vec()));
715    }
716
717    #[test]
718    fn test_chachapoly_known_answer() {
719        //ChaChaPoly known-answer test - RFC 7539
720        let key = Vec::<u8>::from_hex(
721            "1c9240a5eb55d38af333888604f6b5f0\
722                  473917c1402b80099dca5cbc207075c0",
723        )
724        .unwrap();
725        let nonce = 0x0807060504030201u64;
726        let ciphertext = Vec::<u8>::from_hex(
727            "64a0861575861af460f062c79be643bd\
728                         5e805cfd345cf389f108670ac76c8cb2\
729                         4c6cfc18755d43eea09ee94e382d26b0\
730                         bdb7b73c321b0100d4f03b7f355894cf\
731                         332f830e710b97ce98c8a84abd0b9481\
732                         14ad176e008d33bd60f982b1ff37c855\
733                         9797a06ef4f0ef61c186324e2b350638\
734                         3606907b6a7c02b0f9f6157b53c867e4\
735                         b9166c767b804d46a59b5216cde7a4e9\
736                         9040c5a40433225ee282a1b0a06c523e\
737                         af4534d7f83fa1155b0047718cbc546a\
738                         0d072b04b3564eea1b422273f548271a\
739                         0bb2316053fa76991955ebd63159434e\
740                         cebb4e466dae5a1073a6727627097a10\
741                         49e617d91d361094fa68f0ff77987130\
742                         305beaba2eda04df997b714d6c6f2c29\
743                         a6ad5cb4022b02709b",
744        )
745        .unwrap();
746        let tag = Vec::<u8>::from_hex("eead9d67890cbb22392336fea1851f38").unwrap();
747        let authtext = Vec::<u8>::from_hex("f33388860000000000004e91").unwrap();
748        let mut combined_text = [0u8; 1024];
749        let mut out = [0u8; 1024];
750        copy_slices!(&ciphertext, &mut combined_text);
751        copy_slices!(&tag[0..TAGLEN], &mut combined_text[ciphertext.len()..]);
752
753        let mut cipher: CipherChaChaPoly = Default::default();
754        cipher.set(&key);
755        cipher
756            .decrypt(
757                nonce,
758                &authtext,
759                &combined_text[..ciphertext.len() + TAGLEN],
760                &mut out[..ciphertext.len()],
761            )
762            .unwrap();
763        let desired_plaintext = "496e7465726e65742d44726166747320\
764                                 61726520647261667420646f63756d65\
765                                 6e74732076616c696420666f72206120\
766                                 6d6178696d756d206f6620736978206d\
767                                 6f6e74687320616e64206d6179206265\
768                                 20757064617465642c207265706c6163\
769                                 65642c206f72206f62736f6c65746564\
770                                 206279206f7468657220646f63756d65\
771                                 6e747320617420616e792074696d652e\
772                                 20497420697320696e617070726f7072\
773                                 6961746520746f2075736520496e7465\
774                                 726e65742d4472616674732061732072\
775                                 65666572656e6365206d617465726961\
776                                 6c206f7220746f206369746520746865\
777                                 6d206f74686572207468616e20617320\
778                                 2fe2809c776f726b20696e2070726f67\
779                                 726573732e2fe2809d";
780        assert!(hex::encode(out[..ciphertext.len()].to_owned()) == desired_plaintext);
781    }
782
783    #[test]
784    #[cfg(feature = "pqclean_kyber1024")]
785    fn test_kyber1024() {
786        let mut rng = OsRng::default();
787        let mut kem_1 = Kyber1024::default();
788        let kem_2 = Kyber1024::default();
789
790        let mut shared_secret_1 = vec![0; kem_1.shared_secret_len()];
791        let mut shared_secret_2 = vec![0; kem_2.shared_secret_len()];
792        let mut ciphertext = vec![0; kem_1.ciphertext_len()];
793
794        kem_1.generate(&mut rng);
795        let (ss1_len, ct_len) =
796            kem_2.encapsulate(kem_1.pubkey(), &mut shared_secret_1, &mut ciphertext).unwrap();
797        let ss2_len = kem_1.decapsulate(&mut ciphertext, &mut shared_secret_2).unwrap();
798
799        assert_eq!(shared_secret_1, shared_secret_2);
800        assert_eq!(ss1_len, shared_secret_1.len());
801        assert_eq!(ss2_len, shared_secret_2.len());
802        assert_eq!(ss1_len, ss2_len);
803        assert_eq!(ct_len, ciphertext.len());
804    }
805
806    #[test]
807    #[cfg(feature = "pqclean_kyber1024")]
808    fn test_kyber1024_fail() {
809        let mut rng = OsRng::default();
810        let mut kem_1 = Kyber1024::default();
811        let kem_2 = Kyber1024::default();
812
813        let mut shared_secret_1 = vec![0; kem_1.shared_secret_len()];
814        let mut shared_secret_2 = vec![0; kem_2.shared_secret_len()];
815        let mut ciphertext = vec![0; kem_1.ciphertext_len()];
816        let mut bad_ciphertext = vec![0; kem_1.ciphertext_len()];
817
818        kem_1.generate(&mut rng);
819        let (ss1_len, ct_len) =
820            kem_2.encapsulate(kem_1.pubkey(), &mut shared_secret_1, &mut ciphertext).unwrap();
821        let ss2_len = kem_1.decapsulate(&mut bad_ciphertext, &mut shared_secret_2).unwrap();
822
823        assert_ne!(shared_secret_1, shared_secret_2);
824        assert_eq!(ss1_len, shared_secret_1.len());
825        assert_eq!(ss2_len, shared_secret_2.len());
826        assert_eq!(ss1_len, ss2_len);
827        assert_eq!(ct_len, ciphertext.len());
828    }
829}