1#[cfg(all(not(feature = "std"), feature = "alloc"))]
7use alloc::collections::BTreeMap as HashMap;
8#[cfg(feature = "alloc")]
9use alloc::string::ToString;
10#[cfg(feature = "alloc")]
11use alloc::vec::Vec;
12#[cfg(feature = "std")]
13#[allow(clippy::disallowed_types)]
14use std::collections::HashMap;
15
16#[cfg(any(feature = "std", feature = "alloc"))]
17use crate::Result;
18use crate::{
19 Algorithm,
20 AlgorithmCategory,
21};
22
23#[derive(Debug, Clone)]
25pub struct AlgorithmMetadata {
26 pub algorithm: Algorithm,
27 pub category: AlgorithmCategory,
28 pub security_level: u32,
29 pub name: &'static str,
30 pub description: &'static str,
31 pub enabled: bool,
32}
33
34#[cfg(any(feature = "std", feature = "alloc"))]
36pub struct AlgorithmRegistry {
37 #[allow(clippy::disallowed_types)]
38 algorithms: HashMap<Algorithm, AlgorithmMetadata>,
39}
40
41#[cfg(any(feature = "std", feature = "alloc"))]
42impl AlgorithmRegistry {
43 pub fn new() -> Self {
45 let mut registry = Self {
46 #[allow(clippy::disallowed_types)]
47 algorithms: HashMap::new(),
48 };
49 registry.register_all();
50 registry
51 }
52
53 fn register_all(&mut self) {
55 self.register(AlgorithmMetadata {
57 algorithm: Algorithm::MlKem512,
58 category: AlgorithmCategory::Kem,
59 security_level: 1,
60 name: "ML-KEM-512",
61 description: "CRYSTALS-ML-KEM Level 1 (128-bit security)",
62 enabled: true,
63 });
64
65 self.register(AlgorithmMetadata {
66 algorithm: Algorithm::MlKem768,
67 category: AlgorithmCategory::Kem,
68 security_level: 3,
69 name: "ML-KEM-768",
70 description: "CRYSTALS-ML-KEM Level 3 (192-bit security)",
71 enabled: true,
72 });
73
74 self.register(AlgorithmMetadata {
75 algorithm: Algorithm::MlKem1024,
76 category: AlgorithmCategory::Kem,
77 security_level: 5,
78 name: "ML-KEM-1024",
79 description: "CRYSTALS-ML-KEM Level 5 (256-bit security)",
80 enabled: true,
81 });
82
83 self.register(AlgorithmMetadata {
85 algorithm: Algorithm::CbKem348864,
86 category: AlgorithmCategory::Kem,
87 security_level: 1,
88 name: "CB-KEM 348864",
89 description: "CB-KEM Level 1 (128-bit security)",
90 enabled: true,
91 });
92
93 self.register(AlgorithmMetadata {
94 algorithm: Algorithm::CbKem460896,
95 category: AlgorithmCategory::Kem,
96 security_level: 3,
97 name: "CB-KEM 460896",
98 description: "CB-KEM Level 3 (192-bit security)",
99 enabled: true,
100 });
101
102 self.register(AlgorithmMetadata {
103 algorithm: Algorithm::CbKem6688128,
104 category: AlgorithmCategory::Kem,
105 security_level: 5,
106 name: "CB-KEM 6688128",
107 description: "CB-KEM Level 5 (256-bit security)",
108 enabled: true,
109 });
110
111 self.register(AlgorithmMetadata {
112 algorithm: Algorithm::CbKem6960119,
113 category: AlgorithmCategory::Kem,
114 security_level: 5,
115 name: "CB-KEM 6960119",
116 description: "CB-KEM Level 5 (256-bit security)",
117 enabled: true,
118 });
119
120 self.register(AlgorithmMetadata {
121 algorithm: Algorithm::CbKem8192128,
122 category: AlgorithmCategory::Kem,
123 security_level: 5,
124 name: "CB-KEM 8192128",
125 description: "CB-KEM Level 5 (256-bit security, higher performance)",
126 enabled: true,
127 });
128
129 self.register(AlgorithmMetadata {
131 algorithm: Algorithm::Hqc128,
132 category: AlgorithmCategory::Kem,
133 security_level: 1,
134 name: "HQC-128",
135 description: "HQC Level 1 (128-bit security)",
136 enabled: true,
137 });
138
139 self.register(AlgorithmMetadata {
140 algorithm: Algorithm::Hqc192,
141 category: AlgorithmCategory::Kem,
142 security_level: 3,
143 name: "HQC-192",
144 description: "HQC Level 3 (192-bit security)",
145 enabled: true,
146 });
147
148 self.register(AlgorithmMetadata {
149 algorithm: Algorithm::Hqc256,
150 category: AlgorithmCategory::Kem,
151 security_level: 5,
152 name: "HQC-256",
153 description: "HQC Level 5 (256-bit security)",
154 enabled: true,
155 });
156
157 self.register(AlgorithmMetadata {
159 algorithm: Algorithm::MlDsa44,
160 category: AlgorithmCategory::Signature,
161 security_level: 1,
162 name: "ML-DSA-44",
163 description: "CRYSTALS-ML-DSA Level 1 (128-bit security)",
164 enabled: true,
165 });
166
167 self.register(AlgorithmMetadata {
168 algorithm: Algorithm::MlDsa65,
169 category: AlgorithmCategory::Signature,
170 security_level: 3,
171 name: "ML-DSA-65",
172 description: "CRYSTALS-ML-DSA Level 3 (192-bit security)",
173 enabled: true,
174 });
175
176 self.register(AlgorithmMetadata {
177 algorithm: Algorithm::MlDsa87,
178 category: AlgorithmCategory::Signature,
179 security_level: 5,
180 name: "ML-DSA-87",
181 description: "CRYSTALS-ML-DSA Level 5 (256-bit security)",
182 enabled: true,
183 });
184
185 self.register(AlgorithmMetadata {
186 algorithm: Algorithm::FnDsa,
187 category: AlgorithmCategory::Signature,
188 security_level: 1,
189 name: "FN-DSA",
190 description: "FN-DSA (NIST-selected; FIPS 206 not yet published) - Fast Fourier Transform over NTRU-Lattice-Based Digital Signature Algorithm",
191 enabled: true,
192 });
193
194 self.register(AlgorithmMetadata {
195 algorithm: Algorithm::FnDsa512,
196 category: AlgorithmCategory::Signature,
197 security_level: 1,
198 name: "FN-DSA-512",
199 description: "FN-DSA Level 1 (128-bit security) - n=512",
200 enabled: true,
201 });
202
203 self.register(AlgorithmMetadata {
204 algorithm: Algorithm::FnDsa1024,
205 category: AlgorithmCategory::Signature,
206 security_level: 5,
207 name: "FN-DSA-1024",
208 description: "FN-DSA Level 5 (256-bit security) - n=1024",
209 enabled: true,
210 });
211
212 self.register(AlgorithmMetadata {
214 algorithm: Algorithm::SlhDsaSha256128fRobust,
215 category: AlgorithmCategory::Signature,
216 security_level: 1,
217 name: "SLH-DSA-SHA256-128f-Robust",
218 description: "SLH-DSA SHA256 Level 1 (128-bit security)",
219 enabled: true,
220 });
221
222 self.register(AlgorithmMetadata {
223 algorithm: Algorithm::SlhDsaSha256192fRobust,
224 category: AlgorithmCategory::Signature,
225 security_level: 3,
226 name: "SLH-DSA-SHA256-192f-Robust",
227 description: "SLH-DSA SHA256 Level 3 (192-bit security)",
228 enabled: true,
229 });
230
231 self.register(AlgorithmMetadata {
232 algorithm: Algorithm::SlhDsaSha256256fRobust,
233 category: AlgorithmCategory::Signature,
234 security_level: 5,
235 name: "SLH-DSA-SHA256-256f-Robust",
236 description: "SLH-DSA SHA256 Level 5 (256-bit security)",
237 enabled: true,
238 });
239
240 self.register(AlgorithmMetadata {
241 algorithm: Algorithm::SlhDsaShake256128fRobust,
242 category: AlgorithmCategory::Signature,
243 security_level: 1,
244 name: "SLH-DSA-SHAKE256-128f-Robust",
245 description: "SLH-DSA SHAKE256 Level 1 (128-bit security)",
246 enabled: true,
247 });
248
249 self.register(AlgorithmMetadata {
250 algorithm: Algorithm::SlhDsaShake256192fRobust,
251 category: AlgorithmCategory::Signature,
252 security_level: 3,
253 name: "SLH-DSA-SHAKE256-192f-Robust",
254 description: "SLH-DSA SHAKE256 Level 3 (192-bit security)",
255 enabled: true,
256 });
257
258 self.register(AlgorithmMetadata {
259 algorithm: Algorithm::SlhDsaShake256256fRobust,
260 category: AlgorithmCategory::Signature,
261 security_level: 5,
262 name: "SLH-DSA-SHAKE256-256f-Robust",
263 description: "SLH-DSA SHAKE256 Level 5 (256-bit security)",
264 enabled: true,
265 });
266
267 self.register(AlgorithmMetadata {
272 algorithm: Algorithm::FaestReserved,
273 category: AlgorithmCategory::Signature,
274 security_level: 3,
275 name: "FAEST-Reserved",
276 description: "RESERVED FAEST/VOLE-in-the-Head diversity signature (symmetric assumptions); disabled — activate only on a lattice-cryptanalysis event",
277 enabled: false,
278 });
279
280 self.register(AlgorithmMetadata {
282 algorithm: Algorithm::Shake128,
283 category: AlgorithmCategory::Hash,
284 security_level: 0,
285 name: "SHAKE128",
286 description: "SHAKE128 hash function",
287 enabled: true,
288 });
289
290 self.register(AlgorithmMetadata {
291 algorithm: Algorithm::Shake256,
292 category: AlgorithmCategory::Hash,
293 security_level: 0,
294 name: "SHAKE256",
295 description: "SHAKE256 hash function",
296 enabled: true,
297 });
298
299 self.register(AlgorithmMetadata {
300 algorithm: Algorithm::CShake128,
301 category: AlgorithmCategory::Hash,
302 security_level: 0,
303 name: "cSHAKE128",
304 description: "cSHAKE128 customizable hash function",
305 enabled: true,
306 });
307
308 self.register(AlgorithmMetadata {
309 algorithm: Algorithm::CShake256,
310 category: AlgorithmCategory::Hash,
311 security_level: 0,
312 name: "cSHAKE256",
313 description: "cSHAKE256 customizable hash function",
314 enabled: true,
315 });
316
317 self.register(AlgorithmMetadata {
319 algorithm: Algorithm::Sha3_224,
320 category: AlgorithmCategory::Hash,
321 security_level: 0,
322 name: "SHA3-224",
323 description: "SHA3-224 hash function",
324 enabled: true,
325 });
326
327 self.register(AlgorithmMetadata {
328 algorithm: Algorithm::Sha3_256,
329 category: AlgorithmCategory::Hash,
330 security_level: 0,
331 name: "SHA3-256",
332 description: "SHA3-256 hash function",
333 enabled: true,
334 });
335
336 self.register(AlgorithmMetadata {
337 algorithm: Algorithm::Sha3_384,
338 category: AlgorithmCategory::Hash,
339 security_level: 0,
340 name: "SHA3-384",
341 description: "SHA3-384 hash function",
342 enabled: true,
343 });
344
345 self.register(AlgorithmMetadata {
346 algorithm: Algorithm::Sha3_512,
347 category: AlgorithmCategory::Hash,
348 security_level: 0,
349 name: "SHA3-512",
350 description: "SHA3-512 hash function",
351 enabled: true,
352 });
353
354 self.register(AlgorithmMetadata {
356 algorithm: Algorithm::Kmac128,
357 category: AlgorithmCategory::Hash,
358 security_level: 0,
359 name: "KMAC128",
360 description: "KMAC128 keyed hash function",
361 enabled: true,
362 });
363
364 self.register(AlgorithmMetadata {
365 algorithm: Algorithm::Kmac256,
366 category: AlgorithmCategory::Hash,
367 security_level: 0,
368 name: "KMAC256",
369 description: "KMAC256 keyed hash function",
370 enabled: true,
371 });
372
373 self.register(AlgorithmMetadata {
375 algorithm: Algorithm::TupleHash128,
376 category: AlgorithmCategory::Hash,
377 security_level: 0,
378 name: "TupleHash128",
379 description: "TupleHash128 tuple hashing",
380 enabled: true,
381 });
382
383 self.register(AlgorithmMetadata {
384 algorithm: Algorithm::TupleHash256,
385 category: AlgorithmCategory::Hash,
386 security_level: 0,
387 name: "TupleHash256",
388 description: "TupleHash256 tuple hashing",
389 enabled: true,
390 });
391
392 self.register(AlgorithmMetadata {
394 algorithm: Algorithm::ParallelHash128,
395 category: AlgorithmCategory::Hash,
396 security_level: 0,
397 name: "ParallelHash128",
398 description: "ParallelHash128 parallel hashing",
399 enabled: true,
400 });
401
402 self.register(AlgorithmMetadata {
403 algorithm: Algorithm::ParallelHash256,
404 category: AlgorithmCategory::Hash,
405 security_level: 0,
406 name: "ParallelHash256",
407 description: "ParallelHash256 parallel hashing",
408 enabled: true,
409 });
410
411 self.register(AlgorithmMetadata {
413 algorithm: Algorithm::Keccak224,
414 category: AlgorithmCategory::Hash,
415 security_level: 0,
416 name: "Keccak-224",
417 description: "Keccak-224 hash function",
418 enabled: true,
419 });
420
421 self.register(AlgorithmMetadata {
422 algorithm: Algorithm::Keccak256,
423 category: AlgorithmCategory::Hash,
424 security_level: 0,
425 name: "Keccak-256",
426 description: "Keccak-256 hash function",
427 enabled: true,
428 });
429
430 self.register(AlgorithmMetadata {
431 algorithm: Algorithm::Keccak384,
432 category: AlgorithmCategory::Hash,
433 security_level: 0,
434 name: "Keccak-384",
435 description: "Keccak-384 hash function",
436 enabled: true,
437 });
438
439 self.register(AlgorithmMetadata {
440 algorithm: Algorithm::Keccak512,
441 category: AlgorithmCategory::Hash,
442 security_level: 0,
443 name: "Keccak-512",
444 description: "Keccak-512 hash function",
445 enabled: true,
446 });
447
448 self.register(AlgorithmMetadata {
450 algorithm: Algorithm::Kt128,
451 category: AlgorithmCategory::Hash,
452 security_level: 0,
453 name: "KT128",
454 description: "KangarooTwelve with TurboSHAKE128 (RFC 9861)",
455 enabled: true,
456 });
457
458 self.register(AlgorithmMetadata {
459 algorithm: Algorithm::Kt256,
460 category: AlgorithmCategory::Hash,
461 security_level: 0,
462 name: "KT256",
463 description: "KangarooTwelve with TurboSHAKE256 (RFC 9861)",
464 enabled: true,
465 });
466
467 self.register(AlgorithmMetadata {
469 algorithm: Algorithm::Sha224,
470 category: AlgorithmCategory::Hash,
471 security_level: 0,
472 name: "SHA-224",
473 description: "SHA-224 hash function",
474 enabled: true,
475 });
476
477 self.register(AlgorithmMetadata {
478 algorithm: Algorithm::Sha256,
479 category: AlgorithmCategory::Hash,
480 security_level: 0,
481 name: "SHA-256",
482 description: "SHA-256 hash function",
483 enabled: true,
484 });
485
486 self.register(AlgorithmMetadata {
487 algorithm: Algorithm::Sha384,
488 category: AlgorithmCategory::Hash,
489 security_level: 0,
490 name: "SHA-384",
491 description: "SHA-384 hash function",
492 enabled: true,
493 });
494
495 self.register(AlgorithmMetadata {
496 algorithm: Algorithm::Sha512,
497 category: AlgorithmCategory::Hash,
498 security_level: 0,
499 name: "SHA-512",
500 description: "SHA-512 hash function",
501 enabled: true,
502 });
503
504 self.register(AlgorithmMetadata {
505 algorithm: Algorithm::Sha512_224,
506 category: AlgorithmCategory::Hash,
507 security_level: 0,
508 name: "SHA-512/224",
509 description: "SHA-512/224 hash function (truncated)",
510 enabled: true,
511 });
512
513 self.register(AlgorithmMetadata {
514 algorithm: Algorithm::Sha512_256,
515 category: AlgorithmCategory::Hash,
516 security_level: 0,
517 name: "SHA-512/256",
518 description: "SHA-512/256 hash function (truncated)",
519 enabled: true,
520 });
521
522 self.register(AlgorithmMetadata {
524 algorithm: Algorithm::TurboShake128,
525 category: AlgorithmCategory::Hash,
526 security_level: 0,
527 name: "TurboSHAKE128",
528 description: "TurboSHAKE128 extendable-output function",
529 enabled: true,
530 });
531
532 self.register(AlgorithmMetadata {
533 algorithm: Algorithm::TurboShake256,
534 category: AlgorithmCategory::Hash,
535 security_level: 0,
536 name: "TurboSHAKE256",
537 description: "TurboSHAKE256 extendable-output function",
538 enabled: true,
539 });
540
541 self.register(AlgorithmMetadata {
543 algorithm: Algorithm::Saturnin,
544 category: AlgorithmCategory::Aead,
545 security_level: 1,
546 name: "Saturnin",
547 description: "Saturnin - Lightweight post-quantum symmetric algorithm suite for IoT and constrained devices",
548 enabled: true,
549 });
550
551 self.register(AlgorithmMetadata {
552 algorithm: Algorithm::Shake256Aead,
553 category: AlgorithmCategory::Aead,
554 security_level: 1,
555 name: "SHAKE256-AEAD",
556 description: "SHAKE256-based AEAD construction using post-quantum hash function",
557 enabled: true,
558 });
559
560 self.register(AlgorithmMetadata {
561 algorithm: Algorithm::DuplexSpongeAead,
562 category: AlgorithmCategory::Aead,
563 security_level: 4,
564 name: "Duplex-Sponge-AEAD",
565 description: "Keccak-f[1600] duplex-sponge authenticated encryption (SHA-3 family permutation)",
566 enabled: true,
567 });
568
569 self.register(AlgorithmMetadata {
570 algorithm: Algorithm::TweakAead,
571 category: AlgorithmCategory::Aead,
572 security_level: 4,
573 name: "Tweak-AEAD",
574 description: "Parallel tweakable-block CTR AEAD over Keccak-f[1600] with independent 32-byte blocks",
575 enabled: true,
576 });
577
578 self.register(AlgorithmMetadata {
579 algorithm: Algorithm::RomulusN,
580 category: AlgorithmCategory::Aead,
581 security_level: 1,
582 name: "Romulus-N",
583 description: "Romulus-N nonce-based AEAD (SKINNY-128-384+), LWC v1.3",
584 enabled: true,
585 });
586
587 self.register(AlgorithmMetadata {
588 algorithm: Algorithm::RomulusM,
589 category: AlgorithmCategory::Aead,
590 security_level: 1,
591 name: "Romulus-M",
592 description: "Romulus-M misuse-resistant AEAD (SKINNY-128-384+), LWC v1.3",
593 enabled: true,
594 });
595
596 self.register(AlgorithmMetadata {
597 algorithm: Algorithm::RoccaS,
598 category: AlgorithmCategory::Aead,
599 security_level: 1,
600 name: "Rocca-S",
601 description: "Rocca-S high-throughput AES-round AEAD (IETF draft-nakano-rocca-s); 256-bit key/tag, 128-bit nonce",
602 enabled: true,
603 });
604
605 self.register(AlgorithmMetadata {
607 algorithm: Algorithm::LatticeRingSignature,
608 category: AlgorithmCategory::PrivacyProtocol,
609 security_level: 3,
610 name: "Lattice federation ring signature",
611 description: "Federation ring-style opening proofs over Ajtai commitments (lib-q-ring-sig)",
612 enabled: true,
613 });
614 self.register(AlgorithmMetadata {
615 algorithm: Algorithm::LatticeBlindIssuance,
616 category: AlgorithmCategory::PrivacyProtocol,
617 security_level: 3,
618 name: "Lattice blind issuance",
619 description: "CRS blind issuance plumbing and issuer attestation (lib-q-lattice-zkp/blind)",
620 enabled: true,
621 });
622 self.register(AlgorithmMetadata {
623 algorithm: Algorithm::LatticeAnonymousToken,
624 category: AlgorithmCategory::PrivacyProtocol,
625 security_level: 3,
626 name: "Lattice anonymous token",
627 description: "Commitment-backed anonymous token and spending proof (lib-q-lattice-zkp/token)",
628 enabled: true,
629 });
630 self.register(AlgorithmMetadata {
631 algorithm: Algorithm::LatticeNullifierRegistry,
632 category: AlgorithmCategory::PrivacyProtocol,
633 security_level: 3,
634 name: "Lattice nullifier registry",
635 description: "SHAKE256 nullifier binding for Sybil-evidence style proofs (lib-q-lattice-zkp/sigma/uniqueness)",
636 enabled: true,
637 });
638 self.register(AlgorithmMetadata {
639 algorithm: Algorithm::LatticeWitnessNullifier,
640 category: AlgorithmCategory::PrivacyProtocol,
641 security_level: 3,
642 name: "Lattice witness nullifier",
643 description: "Witness-derived SHAKE256 nullifier and opening binding (lib-q-lattice-zkp/sigma/uniqueness)",
644 enabled: true,
645 });
646 self.register(AlgorithmMetadata {
647 algorithm: Algorithm::LatticeDualRingLb,
648 category: AlgorithmCategory::PrivacyProtocol,
649 security_level: 3,
650 name: "Lattice DualRing-LB pilot",
651 description: "DualRing-LB (CCS 2021 Alg. 3) aggregated opening verify over Ajtai ring (lib-q-ring-sig/dualring_lb)",
652 enabled: true,
653 });
654 self.register(AlgorithmMetadata {
655 algorithm: Algorithm::MixOnionRouting,
656 category: AlgorithmCategory::PrivacyProtocol,
657 security_level: 3,
658 name: "Mix-layer onion routing",
659 description: "ML-KEM-768 layered encapsulation with Saturnin AEAD per hop",
660 enabled: true,
661 });
662 self.register(AlgorithmMetadata {
663 algorithm: Algorithm::SessionResumptionBinding,
664 category: AlgorithmCategory::PrivacyProtocol,
665 security_level: 3,
666 name: "Session resumption binding",
667 description: "SHAKE256 session token and stateless retry-cookie derivation",
668 enabled: true,
669 });
670 }
671
672 fn register(&mut self, metadata: AlgorithmMetadata) {
674 self.algorithms.insert(metadata.algorithm, metadata);
675 }
676
677 #[cfg(feature = "alloc")]
679 pub fn supported_algorithms(&self) -> Vec<Algorithm> {
680 self.algorithms
681 .values()
682 .filter(|meta| meta.enabled)
683 .map(|meta| meta.algorithm)
684 .collect()
685 }
686
687 #[cfg(not(feature = "alloc"))]
688 pub fn supported_algorithms(&self) -> &'static [Algorithm] {
689 static ALGORITHMS: &[Algorithm] = &[
691 Algorithm::MlKem512,
692 Algorithm::MlKem768,
693 Algorithm::MlKem1024,
694 Algorithm::MlDsa44,
695 Algorithm::MlDsa65,
696 Algorithm::MlDsa87,
697 Algorithm::FnDsa,
698 Algorithm::FnDsa512,
699 Algorithm::FnDsa1024,
700 ];
701 ALGORITHMS
702 }
703
704 #[cfg(feature = "alloc")]
706 pub fn algorithms_by_category(&self, category: AlgorithmCategory) -> Vec<Algorithm> {
707 self.algorithms
708 .values()
709 .filter(|meta| meta.enabled && meta.category == category)
710 .map(|meta| meta.algorithm)
711 .collect()
712 }
713
714 #[cfg(not(feature = "alloc"))]
715 pub fn algorithms_by_category(&self, category: AlgorithmCategory) -> &'static [Algorithm] {
716 match category {
718 AlgorithmCategory::Kem => &[
719 Algorithm::MlKem512,
720 Algorithm::MlKem768,
721 Algorithm::MlKem1024,
722 ],
723 AlgorithmCategory::Signature => &[
724 Algorithm::MlDsa44,
725 Algorithm::MlDsa65,
726 Algorithm::MlDsa87,
727 Algorithm::FnDsa,
728 Algorithm::FnDsa512,
729 Algorithm::FnDsa1024,
730 ],
731 AlgorithmCategory::Hash => &[
732 Algorithm::Sha224,
733 Algorithm::Sha256,
734 Algorithm::Sha384,
735 Algorithm::Sha512,
736 Algorithm::Sha512_224,
737 Algorithm::Sha512_256,
738 ],
739 AlgorithmCategory::Aead => &[
740 Algorithm::Saturnin,
741 Algorithm::Shake256Aead,
742 Algorithm::DuplexSpongeAead,
743 Algorithm::TweakAead,
744 Algorithm::RomulusN,
745 Algorithm::RomulusM,
746 ],
747 AlgorithmCategory::PrivacyProtocol => &[
748 Algorithm::LatticeRingSignature,
749 Algorithm::LatticeBlindIssuance,
750 Algorithm::LatticeAnonymousToken,
751 Algorithm::LatticeNullifierRegistry,
752 Algorithm::LatticeWitnessNullifier,
753 Algorithm::LatticeDualRingLb,
754 Algorithm::MixOnionRouting,
755 Algorithm::SessionResumptionBinding,
756 ],
757 }
758 }
759
760 #[cfg(feature = "alloc")]
762 pub fn algorithms_by_security_level(&self, level: u32) -> Vec<Algorithm> {
763 self.algorithms
764 .values()
765 .filter(|meta| meta.enabled && meta.security_level == level)
766 .map(|meta| meta.algorithm)
767 .collect()
768 }
769
770 #[cfg(not(feature = "alloc"))]
771 pub fn algorithms_by_security_level(&self, level: u32) -> &'static [Algorithm] {
772 security_level_algorithms(level)
773 }
774
775 pub fn get_metadata(&self, algorithm: &Algorithm) -> Option<&AlgorithmMetadata> {
777 self.algorithms.get(algorithm)
778 }
779
780 pub fn is_enabled(&self, algorithm: &Algorithm) -> bool {
782 self.algorithms
783 .get(algorithm)
784 .map(|meta| meta.enabled)
785 .unwrap_or(false)
786 }
787
788 pub fn set_enabled(&mut self, algorithm: Algorithm, enabled: bool) -> Result<()> {
790 if let Some(metadata) = self.algorithms.get_mut(&algorithm) {
791 metadata.enabled = enabled;
792 Ok(())
793 } else {
794 #[cfg(feature = "alloc")]
795 {
796 Err(crate::Error::UnsupportedAlgorithm {
797 algorithm: "unsupported algorithm".to_string(),
798 })
799 }
800 #[cfg(not(feature = "alloc"))]
801 {
802 Err(crate::Error::UnsupportedAlgorithm {
803 algorithm: "unsupported algorithm",
804 })
805 }
806 }
807 }
808}
809
810#[cfg(any(feature = "std", feature = "alloc"))]
811impl Default for AlgorithmRegistry {
812 fn default() -> Self {
813 Self::new()
814 }
815}
816
817#[cfg(all(feature = "alloc", feature = "std"))]
820static REGISTRY: once_cell::sync::Lazy<AlgorithmRegistry> =
821 once_cell::sync::Lazy::new(AlgorithmRegistry::new);
822
823#[cfg(all(feature = "alloc", not(feature = "std"), feature = "spin"))]
824static REGISTRY: spin::Once<AlgorithmRegistry> = spin::Once::new();
825
826#[cfg(all(feature = "alloc", feature = "std"))]
829pub fn registry() -> &'static AlgorithmRegistry {
830 ®ISTRY
831}
832
833#[cfg(all(feature = "alloc", not(feature = "std"), feature = "spin"))]
834pub fn registry() -> &'static AlgorithmRegistry {
835 REGISTRY.call_once(AlgorithmRegistry::new)
836}
837
838#[cfg(all(feature = "alloc", any(feature = "std", feature = "spin")))]
843pub fn supported_algorithms() -> Vec<Algorithm> {
844 registry().supported_algorithms()
845}
846
847#[cfg(all(feature = "alloc", not(any(feature = "std", feature = "spin"))))]
848pub fn supported_algorithms() -> Vec<Algorithm> {
849 AlgorithmRegistry::new().supported_algorithms()
850}
851
852#[cfg(not(feature = "alloc"))]
853pub fn supported_algorithms() -> &'static [Algorithm] {
854 static ALGORITHMS: &[Algorithm] = &[
856 Algorithm::MlKem512,
857 Algorithm::MlKem768,
858 Algorithm::MlKem1024,
859 Algorithm::MlDsa44,
860 Algorithm::MlDsa65,
861 Algorithm::MlDsa87,
862 Algorithm::FnDsa,
863 Algorithm::FnDsa512,
864 Algorithm::FnDsa1024,
865 ];
866 ALGORITHMS
867}
868
869#[cfg(all(feature = "alloc", any(feature = "std", feature = "spin")))]
871pub fn algorithms_by_category(category: AlgorithmCategory) -> Vec<Algorithm> {
872 registry().algorithms_by_category(category)
873}
874
875#[cfg(all(feature = "alloc", not(any(feature = "std", feature = "spin"))))]
876pub fn algorithms_by_category(category: AlgorithmCategory) -> Vec<Algorithm> {
877 AlgorithmRegistry::new().algorithms_by_category(category)
878}
879
880#[cfg(not(feature = "alloc"))]
881pub fn algorithms_by_category(category: AlgorithmCategory) -> &'static [Algorithm] {
882 match category {
884 AlgorithmCategory::Kem => &[
885 Algorithm::MlKem512,
886 Algorithm::MlKem768,
887 Algorithm::MlKem1024,
888 ],
889 AlgorithmCategory::Signature => &[
890 Algorithm::MlDsa44,
891 Algorithm::MlDsa65,
892 Algorithm::MlDsa87,
893 Algorithm::FnDsa,
894 Algorithm::FnDsa512,
895 Algorithm::FnDsa1024,
896 ],
897 AlgorithmCategory::Hash => &[
898 Algorithm::Sha224,
899 Algorithm::Sha256,
900 Algorithm::Sha384,
901 Algorithm::Sha512,
902 ],
903 AlgorithmCategory::Aead => &[
904 Algorithm::Saturnin,
905 Algorithm::Shake256Aead,
906 Algorithm::DuplexSpongeAead,
907 Algorithm::TweakAead,
908 Algorithm::RomulusN,
909 Algorithm::RomulusM,
910 ],
911 AlgorithmCategory::PrivacyProtocol => &[
912 Algorithm::LatticeRingSignature,
913 Algorithm::LatticeBlindIssuance,
914 Algorithm::LatticeAnonymousToken,
915 Algorithm::LatticeNullifierRegistry,
916 Algorithm::LatticeWitnessNullifier,
917 Algorithm::LatticeDualRingLb,
918 Algorithm::MixOnionRouting,
919 Algorithm::SessionResumptionBinding,
920 ],
921 }
922}
923
924#[cfg(all(feature = "alloc", any(feature = "std", feature = "spin")))]
926pub fn algorithms_by_security_level(level: u32) -> Vec<Algorithm> {
927 registry().algorithms_by_security_level(level)
928}
929
930#[cfg(all(feature = "alloc", not(any(feature = "std", feature = "spin"))))]
931pub fn algorithms_by_security_level(level: u32) -> Vec<Algorithm> {
932 AlgorithmRegistry::new().algorithms_by_security_level(level)
933}
934
935#[cfg(any(not(feature = "alloc"), test))]
952const SECURITY_LEVEL_1_ALGORITHMS: &[Algorithm] = &[
953 Algorithm::MlKem512,
954 Algorithm::CbKem348864,
955 Algorithm::Hqc128,
956 Algorithm::MlDsa44,
957 Algorithm::FnDsa,
958 Algorithm::FnDsa512,
959 Algorithm::SlhDsaSha256128fRobust,
960 Algorithm::SlhDsaShake256128fRobust,
961 Algorithm::Saturnin,
962 Algorithm::Shake256Aead,
963 Algorithm::RomulusN,
964 Algorithm::RomulusM,
965 Algorithm::RoccaS,
966];
967
968#[cfg(any(not(feature = "alloc"), test))]
969const SECURITY_LEVEL_3_ALGORITHMS: &[Algorithm] = &[
970 Algorithm::MlKem768,
971 Algorithm::CbKem460896,
972 Algorithm::Hqc192,
973 Algorithm::MlDsa65,
974 Algorithm::SlhDsaSha256192fRobust,
975 Algorithm::SlhDsaShake256192fRobust,
976 Algorithm::LatticeRingSignature,
977 Algorithm::LatticeBlindIssuance,
978 Algorithm::LatticeAnonymousToken,
979 Algorithm::LatticeNullifierRegistry,
980 Algorithm::LatticeWitnessNullifier,
981 Algorithm::LatticeDualRingLb,
982 Algorithm::MixOnionRouting,
983 Algorithm::SessionResumptionBinding,
984];
985
986#[cfg(any(not(feature = "alloc"), test))]
991const SECURITY_LEVEL_4_ALGORITHMS: &[Algorithm] =
992 &[Algorithm::DuplexSpongeAead, Algorithm::TweakAead];
993
994#[cfg(any(not(feature = "alloc"), test))]
995const SECURITY_LEVEL_5_ALGORITHMS: &[Algorithm] = &[
996 Algorithm::MlKem1024,
997 Algorithm::CbKem6688128,
998 Algorithm::CbKem6960119,
999 Algorithm::CbKem8192128,
1000 Algorithm::Hqc256,
1001 Algorithm::MlDsa87,
1002 Algorithm::FnDsa1024,
1003 Algorithm::SlhDsaSha256256fRobust,
1004 Algorithm::SlhDsaShake256256fRobust,
1005];
1006
1007#[cfg(any(not(feature = "alloc"), test))]
1008fn security_level_algorithms(level: u32) -> &'static [Algorithm] {
1009 match level {
1010 1 => SECURITY_LEVEL_1_ALGORITHMS,
1011 3 => SECURITY_LEVEL_3_ALGORITHMS,
1012 4 => SECURITY_LEVEL_4_ALGORITHMS,
1013 5 => SECURITY_LEVEL_5_ALGORITHMS,
1014 _ => &[],
1015 }
1016}
1017
1018#[cfg(not(feature = "alloc"))]
1019pub fn algorithms_by_security_level(level: u32) -> &'static [Algorithm] {
1020 security_level_algorithms(level)
1021}
1022
1023#[cfg(test)]
1024mod tests {
1025 use super::*;
1026
1027 #[test]
1028 fn test_algorithm_registry() {
1029 let registry = AlgorithmRegistry::new();
1030
1031 let algorithms = registry.supported_algorithms();
1033 assert!(!algorithms.is_empty());
1034
1035 let kem_algorithms = registry.algorithms_by_category(AlgorithmCategory::Kem);
1037 assert!(!kem_algorithms.is_empty());
1038
1039 let level1_algorithms = registry.algorithms_by_security_level(1);
1041 assert!(!level1_algorithms.is_empty());
1042
1043 let metadata = registry.get_metadata(&Algorithm::MlKem512);
1045 assert!(metadata.is_some());
1046 assert_eq!(metadata.unwrap().name, "ML-KEM-512");
1047 }
1048
1049 #[test]
1050 fn test_global_registry() {
1051 let algorithms = supported_algorithms();
1052 assert!(!algorithms.is_empty());
1053
1054 let kem_algorithms = algorithms_by_category(AlgorithmCategory::Kem);
1055 assert!(!kem_algorithms.is_empty());
1056 }
1057
1058 #[test]
1084 fn test_security_levels_match_documented_nist_category() {
1085 let registry = AlgorithmRegistry::new();
1086
1087 let expected: &[(Algorithm, u32)] = &[
1088 (Algorithm::MlKem512, 1),
1089 (Algorithm::MlKem768, 3),
1090 (Algorithm::MlKem1024, 5),
1091 (Algorithm::CbKem348864, 1),
1092 (Algorithm::CbKem460896, 3),
1093 (Algorithm::CbKem6688128, 5),
1094 (Algorithm::CbKem6960119, 5),
1095 (Algorithm::CbKem8192128, 5),
1096 (Algorithm::Hqc128, 1),
1097 (Algorithm::Hqc192, 3),
1098 (Algorithm::Hqc256, 5),
1099 (Algorithm::MlDsa65, 3),
1100 (Algorithm::MlDsa87, 5),
1101 (Algorithm::FnDsa, 1),
1102 (Algorithm::FnDsa512, 1),
1103 (Algorithm::FnDsa1024, 5),
1104 (Algorithm::SlhDsaSha256128fRobust, 1),
1105 (Algorithm::SlhDsaSha256192fRobust, 3),
1106 (Algorithm::SlhDsaSha256256fRobust, 5),
1107 (Algorithm::SlhDsaShake256128fRobust, 1),
1108 (Algorithm::SlhDsaShake256192fRobust, 3),
1109 (Algorithm::SlhDsaShake256256fRobust, 5),
1110 ];
1111
1112 for (algorithm, expected_level) in expected {
1113 let metadata = registry
1114 .get_metadata(algorithm)
1115 .unwrap_or_else(|| panic!("{algorithm:?} missing from registry"));
1116 assert_eq!(
1117 metadata.security_level, *expected_level,
1118 "{algorithm:?} is registered at security_level {}, but its spec claims NIST \
1119 Category {expected_level}",
1120 metadata.security_level
1121 );
1122 }
1123 }
1124
1125 #[test]
1144 fn no_std_security_level_lists_match_the_registry() {
1145 let registry = AlgorithmRegistry::new();
1146
1147 let mut levels_checked = 0usize;
1148 for level in [1u32, 3, 4, 5] {
1149 let mut expected: Vec<Algorithm> = registry
1150 .algorithms
1151 .values()
1152 .filter(|meta| meta.enabled && meta.security_level == level)
1153 .map(|meta| meta.algorithm)
1154 .collect();
1155 let mut actual: Vec<Algorithm> = security_level_algorithms(level).to_vec();
1156
1157 assert!(
1158 !expected.is_empty(),
1159 "level {level}: the metadata table has no enabled entry, so this comparison would pass while checking nothing"
1160 );
1161
1162 expected.sort_by_key(|a| format!("{a:?}"));
1163 actual.sort_by_key(|a| format!("{a:?}"));
1164 assert_eq!(
1165 actual, expected,
1166 "level {level}: the no_std static list disagrees with the metadata table. These are duplicate copies of one table and must be changed together."
1167 );
1168 levels_checked += 1;
1169 }
1170
1171 assert_eq!(
1172 levels_checked, 4,
1173 "expected to compare all four populated levels"
1174 );
1175
1176 assert!(security_level_algorithms(2).is_empty());
1179 assert!(security_level_algorithms(99).is_empty());
1180 }
1181
1182 #[test]
1183 fn registry_and_types_agree_on_every_security_level() {
1184 let registry = AlgorithmRegistry::new();
1185 let algorithms = registry.supported_algorithms();
1186 assert!(
1187 !algorithms.is_empty(),
1188 "supported_algorithms() is empty, so this test would pass while checking nothing"
1189 );
1190
1191 let mut checked = 0usize;
1192 for algorithm in algorithms.iter() {
1193 let Some(metadata) = registry.get_metadata(algorithm) else {
1194 continue;
1195 };
1196 if metadata.security_level == 0 {
1199 continue;
1200 }
1201 assert_eq!(
1202 metadata.security_level,
1203 algorithm.security_level(),
1204 "{algorithm:?}: the registry says security_level {}, but \
1205 lib_q_types::Algorithm::security_level() says {}. These are duplicate copies of \
1206 one table and must be changed together.",
1207 metadata.security_level,
1208 algorithm.security_level()
1209 );
1210 checked += 1;
1211 }
1212
1213 assert!(
1214 checked > 0,
1215 "no algorithm carried a non-zero security level, so nothing was actually compared"
1216 );
1217 }
1218}