1#![no_std]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3#![doc = include_str!("../README.md")]
4#![doc(
5 html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg",
6 html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg"
7)]
8#![allow(
9 clippy::cast_possible_truncation,
10 clippy::cast_possible_wrap,
11 clippy::cast_sign_loss,
12 clippy::doc_markdown,
13 clippy::integer_division_remainder_used,
14 clippy::missing_errors_doc,
15 clippy::trivially_copy_pass_by_ref,
16 clippy::undocumented_unsafe_blocks,
17 reason = "TODO"
18)]
19
20#[cfg(not(any(
84 feature = "efrodo640aes",
85 feature = "frodo640aes",
86 feature = "efrodo976aes",
87 feature = "frodo976aes",
88 feature = "efrodo1344aes",
89 feature = "frodo1344aes",
90 feature = "efrodo640shake",
91 feature = "frodo640shake",
92 feature = "efrodo976shake",
93 feature = "frodo976shake",
94 feature = "efrodo1344shake",
95 feature = "frodo1344shake",
96)))]
97compile_error!("no algorithm feature enabled");
98
99#[macro_use]
100extern crate alloc;
101#[cfg(feature = "std")]
102extern crate std;
103
104#[cfg(feature = "hazmat")]
105pub mod hazmat;
106#[cfg(not(feature = "hazmat"))]
107mod hazmat;
108
109mod error;
110pub use error::*;
111
112use alloc::vec::Vec;
113use core::marker::PhantomData;
114use hazmat::*;
115use rand_core::CryptoRng;
116use subtle::{Choice, ConstantTimeEq};
117use zeroize::{Zeroize, ZeroizeOnDrop};
118
119#[cfg(feature = "serde")]
120use alloc::string::{String, ToString};
121
122macro_rules! serde_impl {
123 ($name:ident, $from_method:ident) => {
124 #[cfg(feature = "serde")]
125 impl serde::Serialize for $name {
126 fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
127 where
128 S: serde::Serializer,
129 {
130 if s.is_human_readable() {
131 use serde::ser::SerializeStruct;
132
133 let mut map = s.serialize_struct(stringify!($name), 2)?;
134 map.serialize_field("algorithm", &self.algorithm.to_string())?;
135 map.serialize_field("value", &hex::encode(&self.value))?;
136 map.end()
137 } else {
138 let mut seq = vec![u8::from(self.algorithm)];
139 seq.extend_from_slice(self.value.as_slice());
140 s.serialize_bytes(&seq)
141 }
142 }
143 }
144
145 #[cfg(feature = "serde")]
146 impl<'de> serde::Deserialize<'de> for $name {
147 fn deserialize<D>(d: D) -> Result<Self, D::Error>
148 where
149 D: serde::Deserializer<'de>,
150 {
151 if d.is_human_readable() {
152 struct FieldVisitor;
153 #[derive(serde::Deserialize)]
154 #[serde(field_identifier, rename_all = "snake_case")]
155 enum Field {
156 Algorithm,
157 Value,
158 }
159
160 impl<'de> serde::de::Visitor<'de> for FieldVisitor {
161 type Value = $name;
162
163 fn expecting(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
164 write!(f, "a struct with two fields")
165 }
166
167 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
168 where
169 A: serde::de::MapAccess<'de>,
170 {
171 let mut algorithm = Option::<Algorithm>::None;
172 let mut value = Option::<String>::None;
173 while let Some(key) = map.next_key()? {
174 match key {
175 Field::Algorithm => {
176 if algorithm.is_some() {
177 return Err(serde::de::Error::duplicate_field(
178 "algorithm",
179 ));
180 }
181 algorithm = Some(map.next_value()?);
182 }
183 Field::Value => {
184 if value.is_some() {
185 return Err(serde::de::Error::duplicate_field("value"));
186 }
187 value = Some(map.next_value()?);
188 }
189 }
190 }
191
192 let algorithm = algorithm
193 .ok_or_else(|| serde::de::Error::missing_field("algorithm"))?;
194 let value =
195 value.ok_or_else(|| serde::de::Error::missing_field("value"))?;
196 let value = hex::decode(&value).map_err(serde::de::Error::custom)?;
197 algorithm
198 .$from_method(&value)
199 .map_err(serde::de::Error::custom)
200 }
201 }
202 const FIELDS: &[&str] = &["algorithm", "value"];
203 d.deserialize_struct("Ciphertext", FIELDS, FieldVisitor)
204 } else {
205 struct BytesVisitor;
206
207 impl<'de> serde::de::Visitor<'de> for BytesVisitor {
208 type Value = $name;
209
210 fn expecting(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
211 write!(f, "a byte sequence")
212 }
213
214 fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
215 where
216 E: serde::de::Error,
217 {
218 let (&tag, value) = v
219 .split_first()
220 .ok_or_else(|| serde::de::Error::custom("empty input"))?;
221 let algorithm =
222 Algorithm::try_from(tag).map_err(serde::de::Error::custom)?;
223 algorithm
224 .$from_method(value)
225 .map_err(serde::de::Error::custom)
226 }
227 }
228
229 d.deserialize_bytes(BytesVisitor)
230 }
231 }
232 }
233 };
234}
235
236macro_rules! ct_eq_imp {
237 ($name:ident) => {
238 impl ConstantTimeEq for $name {
239 fn ct_eq(&self, other: &Self) -> Choice {
240 self.algorithm.ct_eq(&other.algorithm) & self.value.ct_eq(&other.value)
241 }
242 }
243
244 impl Eq for $name {}
245
246 impl PartialEq for $name {
247 fn eq(&self, other: &Self) -> bool {
248 self.ct_eq(other).unwrap_u8() == 1
249 }
250 }
251 };
252}
253
254#[derive(Debug, Clone, Default)]
256pub struct Ciphertext {
257 pub(crate) algorithm: Algorithm,
258 pub(crate) value: Vec<u8>,
259}
260
261impl AsRef<[u8]> for Ciphertext {
262 fn as_ref(&self) -> &[u8] {
263 self.value.as_ref()
264 }
265}
266
267ct_eq_imp!(Ciphertext);
268
269serde_impl!(Ciphertext, ciphertext_from_bytes);
270
271impl Ciphertext {
272 #[must_use]
274 pub fn algorithm(&self) -> Algorithm {
275 self.algorithm
276 }
277
278 #[must_use]
280 pub fn value(&self) -> &[u8] {
281 self.value.as_slice()
282 }
283
284 pub fn from_bytes<B: AsRef<[u8]>>(algorithm: Algorithm, value: B) -> FrodoResult<Self> {
286 algorithm.ciphertext_from_bytes(value.as_ref())
287 }
288}
289
290#[derive(Debug, Clone, Default)]
292pub struct EncryptionKey {
293 pub(crate) algorithm: Algorithm,
294 pub(crate) value: Vec<u8>,
295}
296
297impl AsRef<[u8]> for EncryptionKey {
298 fn as_ref(&self) -> &[u8] {
299 self.value.as_ref()
300 }
301}
302
303impl From<&DecryptionKey> for EncryptionKey {
304 fn from(secret_key: &DecryptionKey) -> Self {
305 secret_key
306 .algorithm
307 .encryption_key_from_decryption_key(secret_key)
308 }
309}
310
311ct_eq_imp!(EncryptionKey);
312
313serde_impl!(EncryptionKey, encryption_key_from_bytes);
314
315impl EncryptionKey {
316 #[must_use]
318 pub fn algorithm(&self) -> Algorithm {
319 self.algorithm
320 }
321
322 #[must_use]
324 pub fn value(&self) -> &[u8] {
325 self.value.as_slice()
326 }
327
328 pub fn from_bytes<B: AsRef<[u8]>>(algorithm: Algorithm, value: B) -> FrodoResult<Self> {
330 algorithm.encryption_key_from_bytes(value.as_ref())
331 }
332
333 pub fn encapsulate_with_rng<R: CryptoRng + ?Sized>(
335 &self,
336 rng: &mut R,
337 ) -> FrodoResult<(Ciphertext, SharedSecret)> {
338 self.algorithm.encapsulate_with_rng(self, rng)
339 }
340
341 pub fn encapsulate<B: AsRef<[u8]>, S: AsRef<[u8]>>(
347 &self,
348 message: B,
349 salt: S,
350 ) -> FrodoResult<(Ciphertext, SharedSecret)> {
351 self.algorithm.encapsulate(self, message, salt)
352 }
353}
354
355#[derive(Debug, Clone, Default)]
357pub struct DecryptionKey {
358 pub(crate) algorithm: Algorithm,
359 pub(crate) value: Vec<u8>,
360}
361
362impl AsRef<[u8]> for DecryptionKey {
363 fn as_ref(&self) -> &[u8] {
364 self.value.as_ref()
365 }
366}
367
368ct_eq_imp!(DecryptionKey);
369
370serde_impl!(DecryptionKey, decryption_key_from_bytes);
371
372impl Zeroize for DecryptionKey {
373 fn zeroize(&mut self) {
374 self.value.zeroize();
375 }
376}
377
378impl ZeroizeOnDrop for DecryptionKey {}
379
380impl DecryptionKey {
381 #[must_use]
383 pub fn algorithm(&self) -> Algorithm {
384 self.algorithm
385 }
386
387 #[must_use]
389 pub fn value(&self) -> &[u8] {
390 self.value.as_slice()
391 }
392
393 pub fn from_bytes<B: AsRef<[u8]>>(algorithm: Algorithm, value: B) -> FrodoResult<Self> {
395 algorithm.decryption_key_from_bytes(value.as_ref())
396 }
397
398 pub fn decapsulate<B: AsRef<[u8]>>(
401 &self,
402 ciphertext: &Ciphertext,
403 ) -> FrodoResult<(SharedSecret, Vec<u8>)> {
404 self.algorithm.decapsulate(self, ciphertext)
405 }
406}
407
408#[derive(Debug, Clone, Default)]
410pub struct SharedSecret {
411 pub(crate) algorithm: Algorithm,
412 pub(crate) value: Vec<u8>,
413}
414
415impl AsRef<[u8]> for SharedSecret {
416 fn as_ref(&self) -> &[u8] {
417 self.value.as_ref()
418 }
419}
420
421ct_eq_imp!(SharedSecret);
422
423serde_impl!(SharedSecret, shared_secret_from_bytes);
424
425impl Zeroize for SharedSecret {
426 fn zeroize(&mut self) {
427 self.value.zeroize();
428 }
429}
430
431impl ZeroizeOnDrop for SharedSecret {}
432
433impl SharedSecret {
434 #[must_use]
436 pub fn algorithm(&self) -> Algorithm {
437 self.algorithm
438 }
439
440 #[must_use]
442 pub fn value(&self) -> &[u8] {
443 self.value.as_slice()
444 }
445
446 pub fn from_bytes<B: AsRef<[u8]>>(algorithm: Algorithm, value: B) -> FrodoResult<Self> {
448 algorithm.shared_secret_from_bytes(value.as_ref())
449 }
450}
451
452#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
454pub enum Algorithm {
455 #[cfg(feature = "frodo640aes")]
456 FrodoKem640Aes,
458 #[cfg(feature = "frodo976aes")]
459 FrodoKem976Aes,
461 #[cfg(feature = "frodo1344aes")]
462 FrodoKem1344Aes,
464 #[cfg(feature = "frodo640shake")]
465 FrodoKem640Shake,
467 #[cfg(feature = "frodo976shake")]
468 FrodoKem976Shake,
470 #[cfg(feature = "frodo1344shake")]
471 FrodoKem1344Shake,
473 #[cfg(feature = "efrodo640aes")]
474 EphemeralFrodoKem640Aes,
476 #[cfg(feature = "efrodo976aes")]
477 EphemeralFrodoKem976Aes,
479 #[cfg(feature = "efrodo1344aes")]
480 EphemeralFrodoKem1344Aes,
482 #[cfg(feature = "efrodo640shake")]
483 EphemeralFrodoKem640Shake,
485 #[cfg(feature = "efrodo976shake")]
486 EphemeralFrodoKem976Shake,
488 #[cfg(feature = "efrodo1344shake")]
489 EphemeralFrodoKem1344Shake,
491}
492
493impl ConstantTimeEq for Algorithm {
494 fn ct_eq(&self, other: &Self) -> Choice {
495 match (self, other) {
496 #[cfg(feature = "efrodo640aes")]
497 (Self::EphemeralFrodoKem640Aes, Self::EphemeralFrodoKem640Aes) => Choice::from(1),
498 #[cfg(feature = "efrodo976aes")]
499 (Self::EphemeralFrodoKem976Aes, Self::EphemeralFrodoKem976Aes) => Choice::from(1),
500 #[cfg(feature = "efrodo1344aes")]
501 (Self::EphemeralFrodoKem1344Aes, Self::EphemeralFrodoKem1344Aes) => Choice::from(1),
502 #[cfg(feature = "efrodo640shake")]
503 (Self::EphemeralFrodoKem640Shake, Self::EphemeralFrodoKem640Shake) => Choice::from(1),
504 #[cfg(feature = "efrodo976shake")]
505 (Self::EphemeralFrodoKem976Shake, Self::EphemeralFrodoKem976Shake) => Choice::from(1),
506 #[cfg(feature = "efrodo1344shake")]
507 (Self::EphemeralFrodoKem1344Shake, Self::EphemeralFrodoKem1344Shake) => Choice::from(1),
508 #[cfg(feature = "frodo640aes")]
509 (Self::FrodoKem640Aes, Self::FrodoKem640Aes) => Choice::from(1),
510 #[cfg(feature = "frodo976aes")]
511 (Self::FrodoKem976Aes, Self::FrodoKem976Aes) => Choice::from(1),
512 #[cfg(feature = "frodo1344aes")]
513 (Self::FrodoKem1344Aes, Self::FrodoKem1344Aes) => Choice::from(1),
514 #[cfg(feature = "frodo640shake")]
515 (Self::FrodoKem640Shake, Self::FrodoKem640Shake) => Choice::from(1),
516 #[cfg(feature = "frodo976shake")]
517 (Self::FrodoKem976Shake, Self::FrodoKem976Shake) => Choice::from(1),
518 #[cfg(feature = "frodo1344shake")]
519 (Self::FrodoKem1344Shake, Self::FrodoKem1344Shake) => Choice::from(1),
520 #[allow(unreachable_patterns)]
521 _ => Choice::from(0),
522 }
523 }
524}
525
526impl Default for Algorithm {
527 fn default() -> Self {
528 Self::enabled_algorithms()[0]
529 }
530}
531
532#[cfg(feature = "std")]
533impl core::fmt::Display for Algorithm {
534 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
535 static ALGORITHMS: std::sync::LazyLock<std::collections::HashMap<Algorithm, String>> =
536 std::sync::LazyLock::new(|| {
537 let mut set = std::collections::HashMap::new();
538 #[cfg(feature = "frodo640aes")]
539 set.insert(
540 Algorithm::FrodoKem640Aes,
541 FrodoKem640Aes::default().algorithm(),
542 );
543 #[cfg(feature = "frodo976aes")]
544 set.insert(
545 Algorithm::FrodoKem976Aes,
546 FrodoKem976Aes::default().algorithm(),
547 );
548 #[cfg(feature = "frodo1344aes")]
549 set.insert(
550 Algorithm::FrodoKem1344Aes,
551 FrodoKem1344Aes::default().algorithm(),
552 );
553 #[cfg(feature = "frodo640shake")]
554 set.insert(
555 Algorithm::FrodoKem640Shake,
556 FrodoKem640Shake::default().algorithm(),
557 );
558 #[cfg(feature = "frodo976shake")]
559 set.insert(
560 Algorithm::FrodoKem976Shake,
561 FrodoKem976Shake::default().algorithm(),
562 );
563 #[cfg(feature = "frodo1344shake")]
564 set.insert(
565 Algorithm::FrodoKem1344Shake,
566 FrodoKem1344Shake::default().algorithm(),
567 );
568 #[cfg(feature = "efrodo640aes")]
569 set.insert(
570 Algorithm::EphemeralFrodoKem640Aes,
571 EphemeralFrodoKem640Aes::default().algorithm(),
572 );
573 #[cfg(feature = "efrodo976aes")]
574 set.insert(
575 Algorithm::EphemeralFrodoKem976Aes,
576 EphemeralFrodoKem976Aes::default().algorithm(),
577 );
578 #[cfg(feature = "efrodo1344aes")]
579 set.insert(
580 Algorithm::EphemeralFrodoKem1344Aes,
581 EphemeralFrodoKem1344Aes::default().algorithm(),
582 );
583 #[cfg(feature = "efrodo640shake")]
584 set.insert(
585 Algorithm::EphemeralFrodoKem640Shake,
586 EphemeralFrodoKem640Shake::default().algorithm(),
587 );
588 #[cfg(feature = "efrodo976shake")]
589 set.insert(
590 Algorithm::EphemeralFrodoKem976Shake,
591 EphemeralFrodoKem976Shake::default().algorithm(),
592 );
593 #[cfg(feature = "efrodo1344shake")]
594 set.insert(
595 Algorithm::EphemeralFrodoKem1344Shake,
596 EphemeralFrodoKem1344Shake::default().algorithm(),
597 );
598
599 set
600 });
601 let ss = &(*ALGORITHMS)[self];
602 write!(f, "{}", ss)
603 }
604}
605
606#[cfg(feature = "std")]
607impl core::str::FromStr for Algorithm {
608 type Err = Error;
609
610 fn from_str(s: &str) -> Result<Self, Self::Err> {
611 static ALGORITHMS: std::sync::LazyLock<std::collections::HashMap<String, Algorithm>> =
612 std::sync::LazyLock::new(|| {
613 let mut set = std::collections::HashMap::new();
614 #[cfg(feature = "frodo640aes")]
615 set.insert(
616 FrodoKem640Aes::default().algorithm(),
617 Algorithm::FrodoKem640Aes,
618 );
619 #[cfg(feature = "frodo976aes")]
620 set.insert(
621 FrodoKem976Aes::default().algorithm(),
622 Algorithm::FrodoKem976Aes,
623 );
624 #[cfg(feature = "frodo1344aes")]
625 set.insert(
626 FrodoKem1344Aes::default().algorithm(),
627 Algorithm::FrodoKem1344Aes,
628 );
629 #[cfg(feature = "frodo640shake")]
630 set.insert(
631 FrodoKem640Shake::default().algorithm(),
632 Algorithm::FrodoKem640Shake,
633 );
634 #[cfg(feature = "frodo976shake")]
635 set.insert(
636 FrodoKem976Shake::default().algorithm(),
637 Algorithm::FrodoKem976Shake,
638 );
639 #[cfg(feature = "frodo1344shake")]
640 set.insert(
641 FrodoKem1344Shake::default().algorithm(),
642 Algorithm::FrodoKem1344Shake,
643 );
644 #[cfg(feature = "efrodo640aes")]
645 set.insert(
646 EphemeralFrodoKem640Aes::default().algorithm(),
647 Algorithm::EphemeralFrodoKem640Aes,
648 );
649 #[cfg(feature = "efrodo976aes")]
650 set.insert(
651 EphemeralFrodoKem976Aes::default().algorithm(),
652 Algorithm::EphemeralFrodoKem976Aes,
653 );
654 #[cfg(feature = "efrodo1344aes")]
655 set.insert(
656 EphemeralFrodoKem1344Aes::default().algorithm(),
657 Algorithm::EphemeralFrodoKem1344Aes,
658 );
659 #[cfg(feature = "efrodo640shake")]
660 set.insert(
661 EphemeralFrodoKem640Shake::default().algorithm(),
662 Algorithm::EphemeralFrodoKem640Shake,
663 );
664 #[cfg(feature = "efrodo976shake")]
665 set.insert(
666 EphemeralFrodoKem976Shake::default().algorithm(),
667 Algorithm::EphemeralFrodoKem976Shake,
668 );
669 #[cfg(feature = "efrodo1344shake")]
670 set.insert(
671 EphemeralFrodoKem1344Shake::default().algorithm(),
672 Algorithm::EphemeralFrodoKem1344Shake,
673 );
674
675 set
676 });
677 (*ALGORITHMS)
678 .get(s)
679 .copied()
680 .ok_or(Error::UnsupportedAlgorithm)
681 }
682}
683
684impl From<Algorithm> for u8 {
685 fn from(alg: Algorithm) -> u8 {
686 match alg {
687 #[cfg(feature = "frodo640aes")]
688 Algorithm::FrodoKem640Aes => 1,
689 #[cfg(feature = "frodo976aes")]
690 Algorithm::FrodoKem976Aes => 2,
691 #[cfg(feature = "frodo1344aes")]
692 Algorithm::FrodoKem1344Aes => 3,
693 #[cfg(feature = "frodo640shake")]
694 Algorithm::FrodoKem640Shake => 4,
695 #[cfg(feature = "frodo976shake")]
696 Algorithm::FrodoKem976Shake => 5,
697 #[cfg(feature = "frodo1344shake")]
698 Algorithm::FrodoKem1344Shake => 6,
699 #[cfg(feature = "efrodo640aes")]
700 Algorithm::EphemeralFrodoKem640Aes => 7,
701 #[cfg(feature = "efrodo976aes")]
702 Algorithm::EphemeralFrodoKem976Aes => 8,
703 #[cfg(feature = "efrodo1344aes")]
704 Algorithm::EphemeralFrodoKem1344Aes => 9,
705 #[cfg(feature = "efrodo640shake")]
706 Algorithm::EphemeralFrodoKem640Shake => 10,
707 #[cfg(feature = "efrodo976shake")]
708 Algorithm::EphemeralFrodoKem976Shake => 11,
709 #[cfg(feature = "efrodo1344shake")]
710 Algorithm::EphemeralFrodoKem1344Shake => 12,
711 }
712 }
713}
714
715impl From<Algorithm> for u16 {
716 fn from(alg: Algorithm) -> u16 {
717 u16::from(u8::from(alg))
718 }
719}
720
721impl From<Algorithm> for u32 {
722 fn from(alg: Algorithm) -> u32 {
723 u32::from(u8::from(alg))
724 }
725}
726
727impl From<Algorithm> for u64 {
728 fn from(alg: Algorithm) -> u64 {
729 u64::from(u8::from(alg))
730 }
731}
732
733#[cfg(target_pointer_width = "64")]
734impl From<Algorithm> for u128 {
735 fn from(alg: Algorithm) -> u128 {
736 u128::from(u8::from(alg))
737 }
738}
739
740impl From<Algorithm> for usize {
741 fn from(alg: Algorithm) -> usize {
742 u8::from(alg) as usize
743 }
744}
745
746impl TryFrom<u8> for Algorithm {
747 type Error = Error;
748
749 fn try_from(value: u8) -> Result<Self, Self::Error> {
750 match value {
751 #[cfg(feature = "frodo640aes")]
752 1 => Ok(Algorithm::FrodoKem640Aes),
753 #[cfg(feature = "frodo976aes")]
754 2 => Ok(Algorithm::FrodoKem976Aes),
755 #[cfg(feature = "frodo1344aes")]
756 3 => Ok(Algorithm::FrodoKem1344Aes),
757 #[cfg(feature = "frodo640shake")]
758 4 => Ok(Algorithm::FrodoKem640Shake),
759 #[cfg(feature = "frodo976shake")]
760 5 => Ok(Algorithm::FrodoKem976Shake),
761 #[cfg(feature = "frodo1344shake")]
762 6 => Ok(Algorithm::FrodoKem1344Shake),
763 #[cfg(feature = "efrodo640aes")]
764 7 => Ok(Algorithm::EphemeralFrodoKem640Aes),
765 #[cfg(feature = "efrodo976aes")]
766 8 => Ok(Algorithm::EphemeralFrodoKem976Aes),
767 #[cfg(feature = "efrodo1344aes")]
768 9 => Ok(Algorithm::EphemeralFrodoKem1344Aes),
769 #[cfg(feature = "efrodo640shake")]
770 10 => Ok(Algorithm::EphemeralFrodoKem640Shake),
771 #[cfg(feature = "efrodo976shake")]
772 11 => Ok(Algorithm::EphemeralFrodoKem976Shake),
773 #[cfg(feature = "efrodo1344shake")]
774 12 => Ok(Algorithm::EphemeralFrodoKem1344Shake),
775 _ => Err(Error::UnsupportedAlgorithm),
776 }
777 }
778}
779
780impl TryFrom<u16> for Algorithm {
781 type Error = Error;
782
783 fn try_from(value: u16) -> Result<Self, Self::Error> {
784 let v = u8::try_from(value).map_err(|_| Error::UnsupportedAlgorithm)?;
785 v.try_into()
786 }
787}
788
789impl TryFrom<u32> for Algorithm {
790 type Error = Error;
791
792 fn try_from(value: u32) -> Result<Self, Self::Error> {
793 let v = u8::try_from(value).map_err(|_| Error::UnsupportedAlgorithm)?;
794 v.try_into()
795 }
796}
797
798impl TryFrom<u64> for Algorithm {
799 type Error = Error;
800
801 fn try_from(value: u64) -> Result<Self, Self::Error> {
802 let v = u8::try_from(value).map_err(|_| Error::UnsupportedAlgorithm)?;
803 v.try_into()
804 }
805}
806
807#[cfg(target_pointer_width = "64")]
808impl TryFrom<u128> for Algorithm {
809 type Error = Error;
810
811 fn try_from(value: u128) -> Result<Self, Self::Error> {
812 let v = u8::try_from(value).map_err(|_| Error::UnsupportedAlgorithm)?;
813 v.try_into()
814 }
815}
816
817impl TryFrom<usize> for Algorithm {
818 type Error = Error;
819
820 fn try_from(value: usize) -> Result<Self, Self::Error> {
821 let v = u8::try_from(value).map_err(|_| Error::UnsupportedAlgorithm)?;
822 v.try_into()
823 }
824}
825
826#[cfg(feature = "serde")]
827impl serde::Serialize for Algorithm {
828 fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
829 where
830 S: serde::Serializer,
831 {
832 if s.is_human_readable() {
833 s.serialize_str(&self.to_string())
834 } else {
835 s.serialize_u8(u8::from(*self))
836 }
837 }
838}
839
840#[cfg(feature = "serde")]
841impl<'de> serde::Deserialize<'de> for Algorithm {
842 fn deserialize<D>(d: D) -> Result<Algorithm, D::Error>
843 where
844 D: serde::Deserializer<'de>,
845 {
846 if d.is_human_readable() {
847 let s = String::deserialize(d)?;
848 s.parse().map_err(serde::de::Error::custom)
849 } else {
850 let v = u8::deserialize(d)?;
851 v.try_into().map_err(serde::de::Error::custom)
852 }
853 }
854}
855
856impl Algorithm {
857 #[must_use]
859 pub fn enabled_algorithms() -> &'static [Algorithm] {
860 &[
861 #[cfg(feature = "frodo640aes")]
862 Self::FrodoKem640Aes,
863 #[cfg(feature = "frodo976aes")]
864 Self::FrodoKem976Aes,
865 #[cfg(feature = "frodo1344aes")]
866 Self::FrodoKem1344Aes,
867 #[cfg(feature = "frodo640shake")]
868 Self::FrodoKem640Shake,
869 #[cfg(feature = "frodo976shake")]
870 Self::FrodoKem976Shake,
871 #[cfg(feature = "frodo1344shake")]
872 Self::FrodoKem1344Shake,
873 #[cfg(feature = "efrodo640aes")]
874 Self::EphemeralFrodoKem640Aes,
875 #[cfg(feature = "efrodo976aes")]
876 Self::EphemeralFrodoKem976Aes,
877 #[cfg(feature = "efrodo1344aes")]
878 Self::EphemeralFrodoKem1344Aes,
879 #[cfg(feature = "efrodo640shake")]
880 Self::EphemeralFrodoKem640Shake,
881 #[cfg(feature = "efrodo976shake")]
882 Self::EphemeralFrodoKem976Shake,
883 #[cfg(feature = "efrodo1344shake")]
884 Self::EphemeralFrodoKem1344Shake,
885 ]
886 }
887
888 #[must_use]
890 pub const fn params(&self) -> AlgorithmParams {
891 match self {
892 #[cfg(feature = "frodo640aes")]
893 Self::FrodoKem640Aes => self.inner_params::<FrodoKem640Aes>(),
894 #[cfg(feature = "frodo976aes")]
895 Self::FrodoKem976Aes => self.inner_params::<FrodoKem976Aes>(),
896 #[cfg(feature = "frodo1344aes")]
897 Self::FrodoKem1344Aes => self.inner_params::<FrodoKem1344Aes>(),
898 #[cfg(feature = "frodo640shake")]
899 Self::FrodoKem640Shake => self.inner_params::<FrodoKem640Shake>(),
900 #[cfg(feature = "frodo976shake")]
901 Self::FrodoKem976Shake => self.inner_params::<FrodoKem976Shake>(),
902 #[cfg(feature = "frodo1344shake")]
903 Self::FrodoKem1344Shake => self.inner_params::<FrodoKem1344Shake>(),
904 #[cfg(feature = "efrodo640aes")]
905 Self::EphemeralFrodoKem640Aes => self.inner_params::<EphemeralFrodoKem640Aes>(),
906 #[cfg(feature = "efrodo976aes")]
907 Self::EphemeralFrodoKem976Aes => self.inner_params::<EphemeralFrodoKem976Aes>(),
908 #[cfg(feature = "efrodo1344aes")]
909 Self::EphemeralFrodoKem1344Aes => self.inner_params::<EphemeralFrodoKem1344Aes>(),
910 #[cfg(feature = "efrodo640shake")]
911 Self::EphemeralFrodoKem640Shake => self.inner_params::<EphemeralFrodoKem640Shake>(),
912 #[cfg(feature = "efrodo976shake")]
913 Self::EphemeralFrodoKem976Shake => self.inner_params::<EphemeralFrodoKem976Shake>(),
914 #[cfg(feature = "efrodo1344shake")]
915 Self::EphemeralFrodoKem1344Shake => self.inner_params::<EphemeralFrodoKem1344Shake>(),
916 }
917 }
918
919 const fn inner_params<B: Params>(&self) -> AlgorithmParams {
920 AlgorithmParams {
921 n: B::N,
922 n_bar: B::N_BAR,
923 log_q: B::LOG_Q,
924 q: B::Q,
925 extracted_bits: B::EXTRACTED_BITS,
926 stripe_step: B::STRIPE_STEP,
927 bytes_seed_a: B::BYTES_SEED_A,
928 bytes_pk_hash: B::BYTES_PK_HASH,
929 cdf_table: B::CDF_TABLE,
930 claimed_nist_level: B::CLAIMED_NIST_LEVEL,
931 shared_secret_length: B::SHARED_SECRET_LENGTH,
932 message_length: B::BYTES_MU,
933 salt_length: B::BYTES_SALT,
934 encryption_key_length: B::PUBLIC_KEY_LENGTH,
935 decryption_key_length: B::SECRET_KEY_LENGTH,
936 ciphertext_length: B::CIPHERTEXT_LENGTH,
937 }
938 }
939
940 #[must_use]
942 pub fn encryption_key_from_decryption_key(&self, secret_key: &DecryptionKey) -> EncryptionKey {
943 match self {
944 #[cfg(feature = "frodo640aes")]
945 Self::FrodoKem640Aes => {
946 self.inner_encryption_key_from_decryption_key::<FrodoKem640Aes>(secret_key)
947 }
948 #[cfg(feature = "frodo976aes")]
949 Self::FrodoKem976Aes => {
950 self.inner_encryption_key_from_decryption_key::<FrodoKem976Aes>(secret_key)
951 }
952 #[cfg(feature = "frodo1344aes")]
953 Self::FrodoKem1344Aes => {
954 self.inner_encryption_key_from_decryption_key::<FrodoKem1344Aes>(secret_key)
955 }
956 #[cfg(feature = "frodo640shake")]
957 Self::FrodoKem640Shake => {
958 self.inner_encryption_key_from_decryption_key::<FrodoKem640Shake>(secret_key)
959 }
960 #[cfg(feature = "frodo976shake")]
961 Self::FrodoKem976Shake => {
962 self.inner_encryption_key_from_decryption_key::<FrodoKem976Shake>(secret_key)
963 }
964 #[cfg(feature = "frodo1344shake")]
965 Self::FrodoKem1344Shake => {
966 self.inner_encryption_key_from_decryption_key::<FrodoKem1344Shake>(secret_key)
967 }
968 #[cfg(feature = "efrodo640aes")]
969 Self::EphemeralFrodoKem640Aes => {
970 self.inner_encryption_key_from_decryption_key::<EphemeralFrodoKem640Aes>(secret_key)
971 }
972 #[cfg(feature = "efrodo976aes")]
973 Self::EphemeralFrodoKem976Aes => {
974 self.inner_encryption_key_from_decryption_key::<EphemeralFrodoKem976Aes>(secret_key)
975 }
976 #[cfg(feature = "efrodo1344aes")]
977 Self::EphemeralFrodoKem1344Aes => self
978 .inner_encryption_key_from_decryption_key::<EphemeralFrodoKem1344Aes>(secret_key),
979 #[cfg(feature = "efrodo640shake")]
980 Self::EphemeralFrodoKem640Shake => self
981 .inner_encryption_key_from_decryption_key::<EphemeralFrodoKem640Shake>(secret_key),
982 #[cfg(feature = "efrodo976shake")]
983 Self::EphemeralFrodoKem976Shake => self
984 .inner_encryption_key_from_decryption_key::<EphemeralFrodoKem976Shake>(secret_key),
985 #[cfg(feature = "efrodo1344shake")]
986 Self::EphemeralFrodoKem1344Shake => self
987 .inner_encryption_key_from_decryption_key::<EphemeralFrodoKem1344Shake>(secret_key),
988 }
989 }
990
991 fn inner_encryption_key_from_decryption_key<B: Params>(
992 &self,
993 secret_key: &DecryptionKey,
994 ) -> EncryptionKey {
995 let sk = DecryptionKeyRef::<B>(secret_key.value.as_slice(), PhantomData);
996 EncryptionKey {
997 algorithm: *self,
998 value: sk.public_key().to_vec(),
999 }
1000 }
1001
1002 pub fn decryption_key_from_bytes<B: AsRef<[u8]>>(&self, buf: B) -> FrodoResult<DecryptionKey> {
1006 let buf = buf.as_ref();
1007 match self {
1008 #[cfg(feature = "frodo640aes")]
1009 Self::FrodoKem640Aes => self.inner_decryption_key_from_bytes::<FrodoKem640Aes>(buf),
1010 #[cfg(feature = "frodo976aes")]
1011 Self::FrodoKem976Aes => self.inner_decryption_key_from_bytes::<FrodoKem976Aes>(buf),
1012 #[cfg(feature = "frodo1344aes")]
1013 Self::FrodoKem1344Aes => self.inner_decryption_key_from_bytes::<FrodoKem1344Aes>(buf),
1014 #[cfg(feature = "frodo640shake")]
1015 Self::FrodoKem640Shake => self.inner_decryption_key_from_bytes::<FrodoKem640Shake>(buf),
1016 #[cfg(feature = "frodo976shake")]
1017 Self::FrodoKem976Shake => self.inner_decryption_key_from_bytes::<FrodoKem976Shake>(buf),
1018 #[cfg(feature = "frodo1344shake")]
1019 Self::FrodoKem1344Shake => {
1020 self.inner_decryption_key_from_bytes::<FrodoKem1344Shake>(buf)
1021 }
1022 #[cfg(feature = "efrodo640aes")]
1023 Self::EphemeralFrodoKem640Aes => {
1024 self.inner_decryption_key_from_bytes::<EphemeralFrodoKem640Aes>(buf)
1025 }
1026 #[cfg(feature = "efrodo976aes")]
1027 Self::EphemeralFrodoKem976Aes => {
1028 self.inner_decryption_key_from_bytes::<EphemeralFrodoKem976Aes>(buf)
1029 }
1030 #[cfg(feature = "efrodo1344aes")]
1031 Self::EphemeralFrodoKem1344Aes => {
1032 self.inner_decryption_key_from_bytes::<EphemeralFrodoKem1344Aes>(buf)
1033 }
1034 #[cfg(feature = "efrodo640shake")]
1035 Self::EphemeralFrodoKem640Shake => {
1036 self.inner_decryption_key_from_bytes::<EphemeralFrodoKem640Shake>(buf)
1037 }
1038 #[cfg(feature = "efrodo976shake")]
1039 Self::EphemeralFrodoKem976Shake => {
1040 self.inner_decryption_key_from_bytes::<EphemeralFrodoKem976Shake>(buf)
1041 }
1042 #[cfg(feature = "efrodo1344shake")]
1043 Self::EphemeralFrodoKem1344Shake => {
1044 self.inner_decryption_key_from_bytes::<EphemeralFrodoKem1344Shake>(buf)
1045 }
1046 }
1047 }
1048
1049 fn inner_decryption_key_from_bytes<P: Params>(&self, buf: &[u8]) -> FrodoResult<DecryptionKey> {
1050 hazmat::DecryptionKey::<P>::from_slice(buf).map(|s| DecryptionKey {
1051 algorithm: *self,
1052 value: s.0,
1053 })
1054 }
1055
1056 pub fn encryption_key_from_bytes<B: AsRef<[u8]>>(&self, buf: B) -> FrodoResult<EncryptionKey> {
1060 let buf = buf.as_ref();
1061 match self {
1062 #[cfg(feature = "frodo640aes")]
1063 Self::FrodoKem640Aes => self.inner_encryption_key_from_bytes::<FrodoKem640Aes>(buf),
1064 #[cfg(feature = "frodo976aes")]
1065 Self::FrodoKem976Aes => self.inner_encryption_key_from_bytes::<FrodoKem976Aes>(buf),
1066 #[cfg(feature = "frodo1344aes")]
1067 Self::FrodoKem1344Aes => self.inner_encryption_key_from_bytes::<FrodoKem1344Aes>(buf),
1068 #[cfg(feature = "frodo640shake")]
1069 Self::FrodoKem640Shake => self.inner_encryption_key_from_bytes::<FrodoKem640Shake>(buf),
1070 #[cfg(feature = "frodo976shake")]
1071 Self::FrodoKem976Shake => self.inner_encryption_key_from_bytes::<FrodoKem976Shake>(buf),
1072 #[cfg(feature = "frodo1344shake")]
1073 Self::FrodoKem1344Shake => {
1074 self.inner_encryption_key_from_bytes::<FrodoKem1344Shake>(buf)
1075 }
1076 #[cfg(feature = "efrodo640aes")]
1077 Self::EphemeralFrodoKem640Aes => {
1078 self.inner_encryption_key_from_bytes::<EphemeralFrodoKem640Aes>(buf)
1079 }
1080 #[cfg(feature = "efrodo976aes")]
1081 Self::EphemeralFrodoKem976Aes => {
1082 self.inner_encryption_key_from_bytes::<EphemeralFrodoKem976Aes>(buf)
1083 }
1084 #[cfg(feature = "efrodo1344aes")]
1085 Self::EphemeralFrodoKem1344Aes => {
1086 self.inner_encryption_key_from_bytes::<EphemeralFrodoKem1344Aes>(buf)
1087 }
1088 #[cfg(feature = "efrodo640shake")]
1089 Self::EphemeralFrodoKem640Shake => {
1090 self.inner_encryption_key_from_bytes::<EphemeralFrodoKem640Shake>(buf)
1091 }
1092 #[cfg(feature = "efrodo976shake")]
1093 Self::EphemeralFrodoKem976Shake => {
1094 self.inner_encryption_key_from_bytes::<EphemeralFrodoKem976Shake>(buf)
1095 }
1096 #[cfg(feature = "efrodo1344shake")]
1097 Self::EphemeralFrodoKem1344Shake => {
1098 self.inner_encryption_key_from_bytes::<EphemeralFrodoKem1344Shake>(buf)
1099 }
1100 }
1101 }
1102
1103 fn inner_encryption_key_from_bytes<P: Params>(&self, buf: &[u8]) -> FrodoResult<EncryptionKey> {
1104 hazmat::EncryptionKey::<P>::from_slice(buf).map(|s| EncryptionKey {
1105 algorithm: *self,
1106 value: s.0,
1107 })
1108 }
1109
1110 pub fn ciphertext_from_bytes(&self, buf: &[u8]) -> FrodoResult<Ciphertext> {
1114 match self {
1115 #[cfg(feature = "frodo640aes")]
1116 Self::FrodoKem640Aes => {
1117 hazmat::Ciphertext::<FrodoKem640Aes>::from_slice(buf).map(|s| Ciphertext {
1118 algorithm: *self,
1119 value: s.0,
1120 })
1121 }
1122 #[cfg(feature = "frodo976aes")]
1123 Self::FrodoKem976Aes => {
1124 hazmat::Ciphertext::<FrodoKem976Aes>::from_slice(buf).map(|s| Ciphertext {
1125 algorithm: *self,
1126 value: s.0,
1127 })
1128 }
1129 #[cfg(feature = "frodo1344aes")]
1130 Self::FrodoKem1344Aes => {
1131 hazmat::Ciphertext::<FrodoKem1344Aes>::from_slice(buf).map(|s| Ciphertext {
1132 algorithm: *self,
1133 value: s.0,
1134 })
1135 }
1136 #[cfg(feature = "frodo640shake")]
1137 Self::FrodoKem640Shake => {
1138 hazmat::Ciphertext::<FrodoKem640Shake>::from_slice(buf).map(|s| Ciphertext {
1139 algorithm: *self,
1140 value: s.0,
1141 })
1142 }
1143 #[cfg(feature = "frodo976shake")]
1144 Self::FrodoKem976Shake => {
1145 hazmat::Ciphertext::<FrodoKem976Shake>::from_slice(buf).map(|s| Ciphertext {
1146 algorithm: *self,
1147 value: s.0,
1148 })
1149 }
1150 #[cfg(feature = "frodo1344shake")]
1151 Self::FrodoKem1344Shake => hazmat::Ciphertext::<FrodoKem1344Shake>::from_slice(buf)
1152 .map(|s| Ciphertext {
1153 algorithm: *self,
1154 value: s.0,
1155 }),
1156 #[cfg(feature = "efrodo640aes")]
1157 Self::EphemeralFrodoKem640Aes => {
1158 hazmat::Ciphertext::<EphemeralFrodoKem640Aes>::from_slice(buf).map(|s| Ciphertext {
1159 algorithm: *self,
1160 value: s.0,
1161 })
1162 }
1163 #[cfg(feature = "efrodo976aes")]
1164 Self::EphemeralFrodoKem976Aes => {
1165 hazmat::Ciphertext::<EphemeralFrodoKem976Aes>::from_slice(buf).map(|s| Ciphertext {
1166 algorithm: *self,
1167 value: s.0,
1168 })
1169 }
1170 #[cfg(feature = "efrodo1344aes")]
1171 Self::EphemeralFrodoKem1344Aes => {
1172 hazmat::Ciphertext::<EphemeralFrodoKem1344Aes>::from_slice(buf).map(|s| {
1173 Ciphertext {
1174 algorithm: *self,
1175 value: s.0,
1176 }
1177 })
1178 }
1179 #[cfg(feature = "efrodo640shake")]
1180 Self::EphemeralFrodoKem640Shake => {
1181 hazmat::Ciphertext::<EphemeralFrodoKem640Shake>::from_slice(buf).map(|s| {
1182 Ciphertext {
1183 algorithm: *self,
1184 value: s.0,
1185 }
1186 })
1187 }
1188 #[cfg(feature = "efrodo976shake")]
1189 Self::EphemeralFrodoKem976Shake => {
1190 hazmat::Ciphertext::<EphemeralFrodoKem976Shake>::from_slice(buf).map(|s| {
1191 Ciphertext {
1192 algorithm: *self,
1193 value: s.0,
1194 }
1195 })
1196 }
1197 #[cfg(feature = "efrodo1344shake")]
1198 Self::EphemeralFrodoKem1344Shake => {
1199 hazmat::Ciphertext::<EphemeralFrodoKem1344Shake>::from_slice(buf).map(|s| {
1200 Ciphertext {
1201 algorithm: *self,
1202 value: s.0,
1203 }
1204 })
1205 }
1206 }
1207 }
1208
1209 pub fn shared_secret_from_bytes(&self, buf: &[u8]) -> FrodoResult<SharedSecret> {
1213 match self {
1214 #[cfg(feature = "frodo640aes")]
1215 Self::FrodoKem640Aes => {
1216 hazmat::SharedSecret::<FrodoKem640Aes>::from_slice(buf).map(|s| SharedSecret {
1217 algorithm: *self,
1218 value: s.0,
1219 })
1220 }
1221 #[cfg(feature = "frodo976aes")]
1222 Self::FrodoKem976Aes => {
1223 hazmat::SharedSecret::<FrodoKem976Aes>::from_slice(buf).map(|s| SharedSecret {
1224 algorithm: *self,
1225 value: s.0,
1226 })
1227 }
1228 #[cfg(feature = "frodo1344aes")]
1229 Self::FrodoKem1344Aes => {
1230 hazmat::SharedSecret::<FrodoKem1344Aes>::from_slice(buf).map(|s| SharedSecret {
1231 algorithm: *self,
1232 value: s.0,
1233 })
1234 }
1235 #[cfg(feature = "frodo640shake")]
1236 Self::FrodoKem640Shake => hazmat::SharedSecret::<FrodoKem640Shake>::from_slice(buf)
1237 .map(|s| SharedSecret {
1238 algorithm: *self,
1239 value: s.0,
1240 }),
1241 #[cfg(feature = "frodo976shake")]
1242 Self::FrodoKem976Shake => hazmat::SharedSecret::<FrodoKem976Shake>::from_slice(buf)
1243 .map(|s| SharedSecret {
1244 algorithm: *self,
1245 value: s.0,
1246 }),
1247 #[cfg(feature = "frodo1344shake")]
1248 Self::FrodoKem1344Shake => hazmat::SharedSecret::<FrodoKem1344Shake>::from_slice(buf)
1249 .map(|s| SharedSecret {
1250 algorithm: *self,
1251 value: s.0,
1252 }),
1253 #[cfg(feature = "efrodo640aes")]
1254 Self::EphemeralFrodoKem640Aes => {
1255 hazmat::SharedSecret::<EphemeralFrodoKem640Aes>::from_slice(buf).map(|s| {
1256 SharedSecret {
1257 algorithm: *self,
1258 value: s.0,
1259 }
1260 })
1261 }
1262 #[cfg(feature = "efrodo976aes")]
1263 Self::EphemeralFrodoKem976Aes => {
1264 hazmat::SharedSecret::<EphemeralFrodoKem976Aes>::from_slice(buf).map(|s| {
1265 SharedSecret {
1266 algorithm: *self,
1267 value: s.0,
1268 }
1269 })
1270 }
1271 #[cfg(feature = "efrodo1344aes")]
1272 Self::EphemeralFrodoKem1344Aes => {
1273 hazmat::SharedSecret::<EphemeralFrodoKem1344Aes>::from_slice(buf).map(|s| {
1274 SharedSecret {
1275 algorithm: *self,
1276 value: s.0,
1277 }
1278 })
1279 }
1280 #[cfg(feature = "efrodo640shake")]
1281 Self::EphemeralFrodoKem640Shake => {
1282 hazmat::SharedSecret::<EphemeralFrodoKem640Shake>::from_slice(buf).map(|s| {
1283 SharedSecret {
1284 algorithm: *self,
1285 value: s.0,
1286 }
1287 })
1288 }
1289 #[cfg(feature = "efrodo976shake")]
1290 Self::EphemeralFrodoKem976Shake => {
1291 hazmat::SharedSecret::<EphemeralFrodoKem976Shake>::from_slice(buf).map(|s| {
1292 SharedSecret {
1293 algorithm: *self,
1294 value: s.0,
1295 }
1296 })
1297 }
1298 #[cfg(feature = "efrodo1344shake")]
1299 Self::EphemeralFrodoKem1344Shake => {
1300 hazmat::SharedSecret::<EphemeralFrodoKem1344Shake>::from_slice(buf).map(|s| {
1301 SharedSecret {
1302 algorithm: *self,
1303 value: s.0,
1304 }
1305 })
1306 }
1307 }
1308 }
1309
1310 pub fn generate_keypair<R: CryptoRng + ?Sized>(
1312 &self,
1313 rng: &mut R,
1314 ) -> (EncryptionKey, DecryptionKey) {
1315 match self {
1316 #[cfg(feature = "frodo640aes")]
1317 Self::FrodoKem640Aes => self.inner_generate_keypair::<FrodoKem640Aes, R>(rng),
1318 #[cfg(feature = "frodo976aes")]
1319 Self::FrodoKem976Aes => self.inner_generate_keypair::<FrodoKem976Aes, R>(rng),
1320 #[cfg(feature = "frodo1344aes")]
1321 Self::FrodoKem1344Aes => self.inner_generate_keypair::<FrodoKem1344Aes, R>(rng),
1322 #[cfg(feature = "frodo640shake")]
1323 Self::FrodoKem640Shake => self.inner_generate_keypair::<FrodoKem640Shake, R>(rng),
1324 #[cfg(feature = "frodo976shake")]
1325 Self::FrodoKem976Shake => self.inner_generate_keypair::<FrodoKem976Shake, R>(rng),
1326 #[cfg(feature = "frodo1344shake")]
1327 Self::FrodoKem1344Shake => self.inner_generate_keypair::<FrodoKem1344Shake, R>(rng),
1328 #[cfg(feature = "efrodo640aes")]
1329 Self::EphemeralFrodoKem640Aes => {
1330 self.inner_generate_keypair::<EphemeralFrodoKem640Aes, R>(rng)
1331 }
1332 #[cfg(feature = "efrodo976aes")]
1333 Self::EphemeralFrodoKem976Aes => {
1334 self.inner_generate_keypair::<EphemeralFrodoKem976Aes, R>(rng)
1335 }
1336 #[cfg(feature = "efrodo1344aes")]
1337 Self::EphemeralFrodoKem1344Aes => {
1338 self.inner_generate_keypair::<EphemeralFrodoKem1344Aes, R>(rng)
1339 }
1340 #[cfg(feature = "efrodo640shake")]
1341 Self::EphemeralFrodoKem640Shake => {
1342 self.inner_generate_keypair::<EphemeralFrodoKem640Shake, R>(rng)
1343 }
1344 #[cfg(feature = "efrodo976shake")]
1345 Self::EphemeralFrodoKem976Shake => {
1346 self.inner_generate_keypair::<EphemeralFrodoKem976Shake, R>(rng)
1347 }
1348 #[cfg(feature = "efrodo1344shake")]
1349 Self::EphemeralFrodoKem1344Shake => {
1350 self.inner_generate_keypair::<EphemeralFrodoKem1344Shake, R>(rng)
1351 }
1352 }
1353 }
1354
1355 fn inner_generate_keypair<K: Kem, R: CryptoRng + ?Sized>(
1356 &self,
1357 rng: &mut R,
1358 ) -> (EncryptionKey, DecryptionKey) {
1359 let (pk, sk) = K::default().generate_keypair(rng);
1360 (
1361 EncryptionKey {
1362 algorithm: *self,
1363 value: pk.0,
1364 },
1365 DecryptionKey {
1366 algorithm: *self,
1367 value: sk.0,
1368 },
1369 )
1370 }
1371
1372 pub fn encapsulate<B: AsRef<[u8]>, S: AsRef<[u8]>>(
1378 &self,
1379 public_key: &EncryptionKey,
1380 msg: B,
1381 salt: S,
1382 ) -> FrodoResult<(Ciphertext, SharedSecret)> {
1383 let msg = msg.as_ref();
1384 let salt = salt.as_ref();
1385 match self {
1386 #[cfg(feature = "frodo640aes")]
1387 Self::FrodoKem640Aes => self.inner_encapsulate::<FrodoKem640Aes>(public_key, msg, salt),
1388 #[cfg(feature = "frodo976aes")]
1389 Self::FrodoKem976Aes => self.inner_encapsulate::<FrodoKem976Aes>(public_key, msg, salt),
1390 #[cfg(feature = "frodo1344aes")]
1391 Self::FrodoKem1344Aes => {
1392 self.inner_encapsulate::<FrodoKem1344Aes>(public_key, msg, salt)
1393 }
1394 #[cfg(feature = "frodo640shake")]
1395 Self::FrodoKem640Shake => {
1396 self.inner_encapsulate::<FrodoKem640Shake>(public_key, msg, salt)
1397 }
1398 #[cfg(feature = "frodo976shake")]
1399 Self::FrodoKem976Shake => {
1400 self.inner_encapsulate::<FrodoKem976Shake>(public_key, msg, salt)
1401 }
1402 #[cfg(feature = "frodo1344shake")]
1403 Self::FrodoKem1344Shake => {
1404 self.inner_encapsulate::<FrodoKem1344Shake>(public_key, msg, salt)
1405 }
1406 #[cfg(feature = "efrodo640aes")]
1407 Self::EphemeralFrodoKem640Aes => {
1408 self.inner_encapsulate::<EphemeralFrodoKem640Aes>(public_key, msg, salt)
1409 }
1410 #[cfg(feature = "efrodo976aes")]
1411 Self::EphemeralFrodoKem976Aes => {
1412 self.inner_encapsulate::<EphemeralFrodoKem976Aes>(public_key, msg, salt)
1413 }
1414 #[cfg(feature = "efrodo1344aes")]
1415 Self::EphemeralFrodoKem1344Aes => {
1416 self.inner_encapsulate::<EphemeralFrodoKem1344Aes>(public_key, msg, salt)
1417 }
1418 #[cfg(feature = "efrodo640shake")]
1419 Self::EphemeralFrodoKem640Shake => {
1420 self.inner_encapsulate::<EphemeralFrodoKem640Shake>(public_key, msg, salt)
1421 }
1422 #[cfg(feature = "efrodo976shake")]
1423 Self::EphemeralFrodoKem976Shake => {
1424 self.inner_encapsulate::<EphemeralFrodoKem976Shake>(public_key, msg, salt)
1425 }
1426 #[cfg(feature = "efrodo1344shake")]
1427 Self::EphemeralFrodoKem1344Shake => {
1428 self.inner_encapsulate::<EphemeralFrodoKem1344Shake>(public_key, msg, salt)
1429 }
1430 }
1431 }
1432
1433 fn inner_encapsulate<K: Kem>(
1434 &self,
1435 encryption_key: &EncryptionKey,
1436 msg: &[u8],
1437 salt: &[u8],
1438 ) -> FrodoResult<(Ciphertext, SharedSecret)> {
1439 if K::BYTES_MU != msg.len() {
1440 return Err(Error::InvalidMessageLength(msg.len()));
1441 }
1442 let pk = EncryptionKeyRef::from_slice(encryption_key.value.as_slice())?;
1443 let (ct, ss) = K::default().encapsulate(pk, msg, salt);
1444 Ok((
1445 Ciphertext {
1446 algorithm: *self,
1447 value: ct.0,
1448 },
1449 SharedSecret {
1450 algorithm: *self,
1451 value: ss.0,
1452 },
1453 ))
1454 }
1455
1456 pub fn encapsulate_with_rng<R: CryptoRng + ?Sized>(
1458 &self,
1459 public_key: &EncryptionKey,
1460 rng: &mut R,
1461 ) -> FrodoResult<(Ciphertext, SharedSecret)> {
1462 match self {
1463 #[cfg(feature = "frodo640aes")]
1464 Self::FrodoKem640Aes => {
1465 self.inner_encapsulate_with_rng::<FrodoKem640Aes, R>(public_key, rng)
1466 }
1467 #[cfg(feature = "frodo976aes")]
1468 Self::FrodoKem976Aes => {
1469 self.inner_encapsulate_with_rng::<FrodoKem976Aes, R>(public_key, rng)
1470 }
1471 #[cfg(feature = "frodo1344aes")]
1472 Self::FrodoKem1344Aes => {
1473 self.inner_encapsulate_with_rng::<FrodoKem1344Aes, R>(public_key, rng)
1474 }
1475 #[cfg(feature = "frodo640shake")]
1476 Self::FrodoKem640Shake => {
1477 self.inner_encapsulate_with_rng::<FrodoKem640Shake, R>(public_key, rng)
1478 }
1479 #[cfg(feature = "frodo976shake")]
1480 Self::FrodoKem976Shake => {
1481 self.inner_encapsulate_with_rng::<FrodoKem976Shake, R>(public_key, rng)
1482 }
1483 #[cfg(feature = "frodo1344shake")]
1484 Self::FrodoKem1344Shake => {
1485 self.inner_encapsulate_with_rng::<FrodoKem1344Shake, R>(public_key, rng)
1486 }
1487 #[cfg(feature = "efrodo640aes")]
1488 Self::EphemeralFrodoKem640Aes => {
1489 self.inner_encapsulate_with_rng::<EphemeralFrodoKem640Aes, R>(public_key, rng)
1490 }
1491 #[cfg(feature = "efrodo976aes")]
1492 Self::EphemeralFrodoKem976Aes => {
1493 self.inner_encapsulate_with_rng::<EphemeralFrodoKem976Aes, R>(public_key, rng)
1494 }
1495 #[cfg(feature = "efrodo1344aes")]
1496 Self::EphemeralFrodoKem1344Aes => {
1497 self.inner_encapsulate_with_rng::<EphemeralFrodoKem1344Aes, R>(public_key, rng)
1498 }
1499 #[cfg(feature = "efrodo640shake")]
1500 Self::EphemeralFrodoKem640Shake => {
1501 self.inner_encapsulate_with_rng::<EphemeralFrodoKem640Shake, R>(public_key, rng)
1502 }
1503 #[cfg(feature = "efrodo976shake")]
1504 Self::EphemeralFrodoKem976Shake => {
1505 self.inner_encapsulate_with_rng::<EphemeralFrodoKem976Shake, R>(public_key, rng)
1506 }
1507 #[cfg(feature = "efrodo1344shake")]
1508 Self::EphemeralFrodoKem1344Shake => {
1509 self.inner_encapsulate_with_rng::<EphemeralFrodoKem1344Shake, R>(public_key, rng)
1510 }
1511 }
1512 }
1513
1514 fn inner_encapsulate_with_rng<K: Kem, R: CryptoRng + ?Sized>(
1515 &self,
1516 encryption_key: &EncryptionKey,
1517 rng: &mut R,
1518 ) -> FrodoResult<(Ciphertext, SharedSecret)> {
1519 let pk = EncryptionKeyRef::from_slice(encryption_key.value.as_slice())?;
1520 let (ct, ss) = K::default().encapsulate_with_rng(pk, rng);
1521 Ok((
1522 Ciphertext {
1523 algorithm: *self,
1524 value: ct.0,
1525 },
1526 SharedSecret {
1527 algorithm: *self,
1528 value: ss.0,
1529 },
1530 ))
1531 }
1532
1533 pub fn decapsulate(
1536 &self,
1537 secret_key: &DecryptionKey,
1538 ciphertext: &Ciphertext,
1539 ) -> FrodoResult<(SharedSecret, Vec<u8>)> {
1540 match self {
1541 #[cfg(feature = "frodo640aes")]
1542 Self::FrodoKem640Aes => {
1543 self.inner_decapsulate::<FrodoKem640Aes>(secret_key, ciphertext)
1544 }
1545 #[cfg(feature = "frodo976aes")]
1546 Self::FrodoKem976Aes => {
1547 self.inner_decapsulate::<FrodoKem976Aes>(secret_key, ciphertext)
1548 }
1549 #[cfg(feature = "frodo1344aes")]
1550 Self::FrodoKem1344Aes => {
1551 self.inner_decapsulate::<FrodoKem1344Aes>(secret_key, ciphertext)
1552 }
1553 #[cfg(feature = "frodo640shake")]
1554 Self::FrodoKem640Shake => {
1555 self.inner_decapsulate::<FrodoKem640Shake>(secret_key, ciphertext)
1556 }
1557 #[cfg(feature = "frodo976shake")]
1558 Self::FrodoKem976Shake => {
1559 self.inner_decapsulate::<FrodoKem976Shake>(secret_key, ciphertext)
1560 }
1561 #[cfg(feature = "frodo1344shake")]
1562 Self::FrodoKem1344Shake => {
1563 self.inner_decapsulate::<FrodoKem1344Shake>(secret_key, ciphertext)
1564 }
1565 #[cfg(feature = "efrodo640aes")]
1566 Self::EphemeralFrodoKem640Aes => {
1567 self.inner_decapsulate::<EphemeralFrodoKem640Aes>(secret_key, ciphertext)
1568 }
1569 #[cfg(feature = "efrodo976aes")]
1570 Self::EphemeralFrodoKem976Aes => {
1571 self.inner_decapsulate::<EphemeralFrodoKem976Aes>(secret_key, ciphertext)
1572 }
1573 #[cfg(feature = "efrodo1344aes")]
1574 Self::EphemeralFrodoKem1344Aes => {
1575 self.inner_decapsulate::<EphemeralFrodoKem1344Aes>(secret_key, ciphertext)
1576 }
1577 #[cfg(feature = "efrodo640shake")]
1578 Self::EphemeralFrodoKem640Shake => {
1579 self.inner_decapsulate::<EphemeralFrodoKem640Shake>(secret_key, ciphertext)
1580 }
1581 #[cfg(feature = "efrodo976shake")]
1582 Self::EphemeralFrodoKem976Shake => {
1583 self.inner_decapsulate::<EphemeralFrodoKem976Shake>(secret_key, ciphertext)
1584 }
1585 #[cfg(feature = "efrodo1344shake")]
1586 Self::EphemeralFrodoKem1344Shake => {
1587 self.inner_decapsulate::<EphemeralFrodoKem1344Shake>(secret_key, ciphertext)
1588 }
1589 }
1590 }
1591
1592 fn inner_decapsulate<K: Kem>(
1593 &self,
1594 secret_key: &DecryptionKey,
1595 ciphertext: &Ciphertext,
1596 ) -> FrodoResult<(SharedSecret, Vec<u8>)> {
1597 let sk = DecryptionKeyRef::from_slice(secret_key.value.as_slice())?;
1598 let ct = CiphertextRef::from_slice(ciphertext.value.as_slice())?;
1599 let (ss, mu) = K::default().decapsulate(sk, ct);
1600 Ok((
1601 SharedSecret {
1602 algorithm: *self,
1603 value: ss.0,
1604 },
1605 mu,
1606 ))
1607 }
1608}
1609
1610#[derive(Debug, Clone, Copy)]
1612pub struct AlgorithmParams {
1613 pub n: usize,
1615 pub n_bar: usize,
1617 pub log_q: usize,
1619 pub q: usize,
1621 pub extracted_bits: usize,
1624 pub stripe_step: usize,
1626 pub bytes_seed_a: usize,
1628 pub bytes_pk_hash: usize,
1630 pub cdf_table: &'static [u16],
1632 pub claimed_nist_level: usize,
1634 pub shared_secret_length: usize,
1636 pub message_length: usize,
1638 pub salt_length: usize,
1640 pub encryption_key_length: usize,
1642 pub decryption_key_length: usize,
1644 pub ciphertext_length: usize,
1646}
1647
1648#[cfg(test)]
1649#[allow(clippy::unwrap_used)]
1650mod tests {
1651 use super::*;
1652 use rand_core::{Rng, SeedableRng};
1653 use rstest::*;
1654
1655 #[rstest]
1656 #[case::aes640(Algorithm::FrodoKem640Aes)]
1657 #[case::aes976(Algorithm::FrodoKem976Aes)]
1658 #[case::aes1344(Algorithm::FrodoKem1344Aes)]
1659 #[case::shake640(Algorithm::FrodoKem640Shake)]
1660 #[case::shake976(Algorithm::FrodoKem976Shake)]
1661 #[case::shake1344(Algorithm::FrodoKem1344Shake)]
1662 fn works(#[case] alg: Algorithm) {
1663 let mut rng = chacha20::ChaCha8Rng::from_seed([1u8; 32]);
1664 let (our_pk, our_sk) = alg.generate_keypair(&mut rng);
1665
1666 let mut mu = vec![0u8; alg.params().message_length];
1667 rng.fill_bytes(&mut mu);
1668 let mut salt = vec![0u8; alg.params().salt_length];
1669 rng.fill_bytes(&mut salt);
1670 let (our_ct, our_ess) = alg.encapsulate(&our_pk, &mu, &salt).unwrap();
1671 let (our_dss, mu_prime) = alg.decapsulate(&our_sk, &our_ct).unwrap();
1672 assert_eq!(our_ess.value, our_dss.value);
1673 assert_eq!(mu, mu_prime);
1674 }
1675
1676 macro_rules! serde_test {
1677 ($name:ident, $ser:path, $de:path) => {
1678 #[cfg(feature = "serde")]
1679 #[rstest]
1680 #[case::aes640(Algorithm::FrodoKem640Aes)]
1681 #[case::aes976(Algorithm::FrodoKem976Aes)]
1682 #[case::aes1344(Algorithm::FrodoKem1344Aes)]
1683 #[case::shake640(Algorithm::FrodoKem640Shake)]
1684 #[case::shake976(Algorithm::FrodoKem976Shake)]
1685 #[case::shake1344(Algorithm::FrodoKem1344Shake)]
1686 #[case::aes640(Algorithm::EphemeralFrodoKem640Aes)]
1687 #[case::aes976(Algorithm::EphemeralFrodoKem976Aes)]
1688 #[case::aes1344(Algorithm::EphemeralFrodoKem1344Aes)]
1689 #[case::shake640(Algorithm::EphemeralFrodoKem640Shake)]
1690 #[case::shake976(Algorithm::EphemeralFrodoKem976Shake)]
1691 #[case::shake1344(Algorithm::EphemeralFrodoKem1344Shake)]
1692 fn $name(#[case] alg: Algorithm) {
1693 let mut rng = chacha20::ChaCha8Rng::from_seed([3u8; 32]);
1694 let (pk, sk) = alg.generate_keypair(&mut rng);
1695 let (ct, ss) = alg.encapsulate_with_rng(&pk, &mut rng).unwrap();
1696
1697 let pk_str = $ser(&pk);
1698 let sk_str = $ser(&sk);
1699 let ct_str = $ser(&ct);
1700 let ss_str = $ser(&ss);
1701
1702 assert!(pk_str.is_ok());
1703 assert!(sk_str.is_ok());
1704 assert!(ct_str.is_ok());
1705 assert!(ss_str.is_ok());
1706
1707 let pk_str = pk_str.unwrap();
1708 let sk_str = sk_str.unwrap();
1709 let ct_str = ct_str.unwrap();
1710 let ss_str = ss_str.unwrap();
1711
1712 let pk2 = $de(&pk_str);
1713 let sk2 = $de(&sk_str);
1714 let ct2 = $de(&ct_str);
1715 let ss2 = $de(&ss_str);
1716
1717 assert!(pk2.is_ok());
1718 assert!(sk2.is_ok());
1719 assert!(ct2.is_ok());
1720 assert!(ss2.is_ok());
1721
1722 let pk2 = pk2.unwrap();
1723 let sk2 = sk2.unwrap();
1724 let ct2 = ct2.unwrap();
1725 let ss2 = ss2.unwrap();
1726
1727 assert_eq!(pk, pk2);
1728 assert_eq!(sk, sk2);
1729 assert_eq!(ct, ct2);
1730 assert_eq!(ss, ss2);
1731 }
1732 };
1733 }
1734
1735 serde_test!(
1736 serialization_json,
1737 serde_json::to_string,
1738 serde_json::from_str
1739 );
1740 serde_test!(serialization_toml, toml::to_string, toml::from_str);
1741 serde_test!(
1742 serialization_yaml,
1743 serde_yaml::to_string,
1744 serde_yaml::from_str
1745 );
1746 serde_test!(
1747 serialization_bare,
1748 serde_bare::to_vec,
1749 serde_bare::from_slice
1750 );
1751 serde_test!(
1752 serialization_cbor,
1753 serde_cbor::to_vec,
1754 serde_cbor::from_slice
1755 );
1756 serde_test!(
1757 serialization_postcard,
1758 postcard::to_stdvec,
1759 postcard::from_bytes
1760 );
1761}