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#[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#[derive(Default)]
71struct Dh25519 {
72 privkey: [u8; 32],
73 pubkey: [u8; 32],
74}
75
76#[derive(Default)]
78struct CipherAesGcm {
79 key: [u8; 32],
80}
81
82#[derive(Default)]
84struct CipherChaChaPoly {
85 key: [u8; 32],
86}
87
88#[cfg(feature = "xchachapoly")]
90#[derive(Default)]
91struct CipherXChaChaPoly {
92 key: [u8; 32],
93}
94
95struct HashSHA256 {
97 hasher: Sha256,
98}
99
100struct HashSHA512 {
102 hasher: Sha512,
103}
104
105#[derive(Default)]
107struct HashBLAKE2b {
108 hasher: Blake2b512,
109}
110
111#[derive(Default)]
113struct HashBLAKE2s {
114 hasher: Blake2s256,
115}
116
117#[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 fn pub_len(&self) -> usize {
471 kyber1024::public_key_bytes()
472 }
473
474 fn ciphertext_len(&self) -> usize {
476 kyber1024::ciphertext_bytes()
477 }
478
479 fn shared_secret_len(&self) -> usize {
481 kyber1024::shared_secret_bytes()
482 }
483
484 fn generate(&mut self, _rng: &mut dyn Random) {
486 let (pk, sk) = kyber1024::keypair();
488 self.pubkey = pk;
489 self.privkey = sk;
490 }
491
492 fn pubkey(&self) -> &[u8] {
494 self.pubkey.as_bytes()
495 }
496
497 #[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 #[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 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 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 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 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 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 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 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 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 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}