Skip to main content

lib_q_core/
algorithm_registry.rs

1//! Algorithm registry for lib-Q
2//!
3//! This module provides a centralized registry of all supported algorithms,
4//! eliminating the need for manual enumeration and providing better maintainability.
5
6#[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/// Algorithm metadata
24#[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/// Central registry of all algorithms
35#[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    /// Create a new algorithm registry
44    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    /// Register all supported algorithms
54    fn register_all(&mut self) {
55        // KEM algorithms
56        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: 4,
78            name: "ML-KEM-1024",
79            description: "CRYSTALS-ML-KEM Level 4 (256-bit security)",
80            enabled: true,
81        });
82
83        // CB-KEM algorithms
84        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: 4,
106            name: "CB-KEM 6688128",
107            description: "CB-KEM Level 4 (256-bit security)",
108            enabled: true,
109        });
110
111        self.register(AlgorithmMetadata {
112            algorithm: Algorithm::CbKem6960119,
113            category: AlgorithmCategory::Kem,
114            security_level: 4,
115            name: "CB-KEM 6960119",
116            description: "CB-KEM Level 4 (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        // HQC algorithms
130        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: 4,
152            name: "HQC-256",
153            description: "HQC Level 4 (256-bit security)",
154            enabled: true,
155        });
156
157        // Signature algorithms
158        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: 4,
180            name: "ML-DSA-87",
181            description: "CRYSTALS-ML-DSA Level 4 (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 (FIPS 206) - 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        // SLH-DSA algorithms
213        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: 4,
235            name: "SLH-DSA-SHA256-256f-Robust",
236            description: "SLH-DSA SHA256 Level 4 (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: 4,
262            name: "SLH-DSA-SHAKE256-256f-Robust",
263            description: "SLH-DSA SHAKE256 Level 4 (256-bit security)",
264            enabled: true,
265        });
266
267        // Reserved diversity signature: registered but DISABLED. FAEST (VOLE-in-the-Head) rests on
268        // symmetric-only assumptions — a hedge against a structured-lattice break of ML-DSA. Large
269        // and slow vs ML-DSA, so never a default; activate only on a lattice-cryptanalysis event.
270        // Identifier only (no implementation). Supersedes Picnic. See lib-q-sig/docs/FAEST_EVALUATION.md.
271        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        // Hash algorithms
281        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        // SHA-3 algorithms
318        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        // KMAC algorithms
355        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        // TupleHash algorithms
374        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        // ParallelHash algorithms
393        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        // Keccak algorithms
412        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        // RFC 9861 KangarooTwelve instances
449        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        // SHA-2 algorithms
468        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        // TurboSHAKE algorithms
523        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        // AEAD algorithms
542        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        // Privacy-oriented protocol identifiers (implementations: lib-q-lattice-zkp, lib-q-ring-sig)
606        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    /// Register an algorithm
673    fn register(&mut self, metadata: AlgorithmMetadata) {
674        self.algorithms.insert(metadata.algorithm, metadata);
675    }
676
677    /// Get all supported algorithms
678    #[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        // In no_std mode, return a static slice of enabled algorithms
690        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    /// Get algorithms by category
705    #[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        // In no_std mode, return a static slice based on category
717        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    /// Get algorithms by security level
761    #[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        // In no_std mode, return a static slice based on security level
773        match level {
774            1 => &[
775                Algorithm::MlKem512,
776                Algorithm::MlDsa44,
777                Algorithm::FnDsa,
778                Algorithm::FnDsa512,
779                Algorithm::Saturnin,
780                Algorithm::Shake256Aead,
781                Algorithm::RomulusN,
782                Algorithm::RomulusM,
783            ],
784            3 => &[
785                Algorithm::MlKem768,
786                Algorithm::MlDsa65,
787                Algorithm::LatticeRingSignature,
788                Algorithm::LatticeBlindIssuance,
789                Algorithm::LatticeAnonymousToken,
790                Algorithm::LatticeNullifierRegistry,
791                Algorithm::LatticeWitnessNullifier,
792                Algorithm::LatticeDualRingLb,
793                Algorithm::MixOnionRouting,
794                Algorithm::SessionResumptionBinding,
795            ],
796            4 => &[
797                Algorithm::MlKem1024,
798                Algorithm::MlDsa87,
799                Algorithm::DuplexSpongeAead,
800                Algorithm::TweakAead,
801            ],
802            5 => &[Algorithm::FnDsa1024],
803            _ => &[],
804        }
805    }
806
807    /// Get algorithm metadata
808    pub fn get_metadata(&self, algorithm: &Algorithm) -> Option<&AlgorithmMetadata> {
809        self.algorithms.get(algorithm)
810    }
811
812    /// Check if algorithm is enabled
813    pub fn is_enabled(&self, algorithm: &Algorithm) -> bool {
814        self.algorithms
815            .get(algorithm)
816            .map(|meta| meta.enabled)
817            .unwrap_or(false)
818    }
819
820    /// Enable/disable an algorithm
821    pub fn set_enabled(&mut self, algorithm: Algorithm, enabled: bool) -> Result<()> {
822        if let Some(metadata) = self.algorithms.get_mut(&algorithm) {
823            metadata.enabled = enabled;
824            Ok(())
825        } else {
826            #[cfg(feature = "alloc")]
827            {
828                Err(crate::Error::UnsupportedAlgorithm {
829                    algorithm: "unsupported algorithm".to_string(),
830                })
831            }
832            #[cfg(not(feature = "alloc"))]
833            {
834                Err(crate::Error::UnsupportedAlgorithm {
835                    algorithm: "unsupported algorithm",
836                })
837            }
838        }
839    }
840}
841
842#[cfg(any(feature = "std", feature = "alloc"))]
843impl Default for AlgorithmRegistry {
844    fn default() -> Self {
845        Self::new()
846    }
847}
848
849// Global algorithm registry instance
850// Note: AlgorithmRegistry requires alloc (uses HashMap/BTreeMap)
851#[cfg(all(feature = "alloc", feature = "std"))]
852static REGISTRY: once_cell::sync::Lazy<AlgorithmRegistry> =
853    once_cell::sync::Lazy::new(AlgorithmRegistry::new);
854
855#[cfg(all(feature = "alloc", not(feature = "std"), feature = "spin"))]
856static REGISTRY: spin::Once<AlgorithmRegistry> = spin::Once::new();
857
858/// Get the global algorithm registry
859/// Requires alloc feature (registry uses HashMap/BTreeMap internally)
860#[cfg(all(feature = "alloc", feature = "std"))]
861pub fn registry() -> &'static AlgorithmRegistry {
862    &REGISTRY
863}
864
865#[cfg(all(feature = "alloc", not(feature = "std"), feature = "spin"))]
866pub fn registry() -> &'static AlgorithmRegistry {
867    REGISTRY.call_once(AlgorithmRegistry::new)
868}
869
870// registry() is not available in no_alloc mode
871// Use supported_algorithms() etc. which return static slices directly
872
873/// Get all supported algorithms
874#[cfg(all(feature = "alloc", any(feature = "std", feature = "spin")))]
875pub fn supported_algorithms() -> Vec<Algorithm> {
876    registry().supported_algorithms()
877}
878
879#[cfg(all(feature = "alloc", not(any(feature = "std", feature = "spin"))))]
880pub fn supported_algorithms() -> Vec<Algorithm> {
881    AlgorithmRegistry::new().supported_algorithms()
882}
883
884#[cfg(not(feature = "alloc"))]
885pub fn supported_algorithms() -> &'static [Algorithm] {
886    // In no_alloc mode, return static slice directly without using registry
887    static ALGORITHMS: &[Algorithm] = &[
888        Algorithm::MlKem512,
889        Algorithm::MlKem768,
890        Algorithm::MlKem1024,
891        Algorithm::MlDsa44,
892        Algorithm::MlDsa65,
893        Algorithm::MlDsa87,
894        Algorithm::FnDsa,
895        Algorithm::FnDsa512,
896        Algorithm::FnDsa1024,
897    ];
898    ALGORITHMS
899}
900
901/// Get algorithms by category
902#[cfg(all(feature = "alloc", any(feature = "std", feature = "spin")))]
903pub fn algorithms_by_category(category: AlgorithmCategory) -> Vec<Algorithm> {
904    registry().algorithms_by_category(category)
905}
906
907#[cfg(all(feature = "alloc", not(any(feature = "std", feature = "spin"))))]
908pub fn algorithms_by_category(category: AlgorithmCategory) -> Vec<Algorithm> {
909    AlgorithmRegistry::new().algorithms_by_category(category)
910}
911
912#[cfg(not(feature = "alloc"))]
913pub fn algorithms_by_category(category: AlgorithmCategory) -> &'static [Algorithm] {
914    // In no_alloc mode, return static slice directly without using registry
915    match category {
916        AlgorithmCategory::Kem => &[
917            Algorithm::MlKem512,
918            Algorithm::MlKem768,
919            Algorithm::MlKem1024,
920        ],
921        AlgorithmCategory::Signature => &[
922            Algorithm::MlDsa44,
923            Algorithm::MlDsa65,
924            Algorithm::MlDsa87,
925            Algorithm::FnDsa,
926            Algorithm::FnDsa512,
927            Algorithm::FnDsa1024,
928        ],
929        AlgorithmCategory::Hash => &[
930            Algorithm::Sha224,
931            Algorithm::Sha256,
932            Algorithm::Sha384,
933            Algorithm::Sha512,
934        ],
935        AlgorithmCategory::Aead => &[
936            Algorithm::Saturnin,
937            Algorithm::Shake256Aead,
938            Algorithm::DuplexSpongeAead,
939            Algorithm::TweakAead,
940            Algorithm::RomulusN,
941            Algorithm::RomulusM,
942        ],
943        AlgorithmCategory::PrivacyProtocol => &[
944            Algorithm::LatticeRingSignature,
945            Algorithm::LatticeBlindIssuance,
946            Algorithm::LatticeAnonymousToken,
947            Algorithm::LatticeNullifierRegistry,
948            Algorithm::LatticeWitnessNullifier,
949            Algorithm::LatticeDualRingLb,
950            Algorithm::MixOnionRouting,
951            Algorithm::SessionResumptionBinding,
952        ],
953    }
954}
955
956/// Get algorithms by security level
957#[cfg(all(feature = "alloc", any(feature = "std", feature = "spin")))]
958pub fn algorithms_by_security_level(level: u32) -> Vec<Algorithm> {
959    registry().algorithms_by_security_level(level)
960}
961
962#[cfg(all(feature = "alloc", not(any(feature = "std", feature = "spin"))))]
963pub fn algorithms_by_security_level(level: u32) -> Vec<Algorithm> {
964    AlgorithmRegistry::new().algorithms_by_security_level(level)
965}
966
967#[cfg(not(feature = "alloc"))]
968pub fn algorithms_by_security_level(level: u32) -> &'static [Algorithm] {
969    // In no_alloc mode, return static slice directly without using registry
970    match level {
971        1 => &[
972            Algorithm::MlKem512,
973            Algorithm::MlDsa44,
974            Algorithm::FnDsa,
975            Algorithm::FnDsa512,
976            Algorithm::Saturnin,
977            Algorithm::Shake256Aead,
978            Algorithm::RomulusN,
979            Algorithm::RomulusM,
980        ],
981        3 => &[
982            Algorithm::MlKem768,
983            Algorithm::MlDsa65,
984            Algorithm::LatticeRingSignature,
985            Algorithm::LatticeBlindIssuance,
986            Algorithm::LatticeAnonymousToken,
987            Algorithm::LatticeNullifierRegistry,
988            Algorithm::LatticeWitnessNullifier,
989            Algorithm::LatticeDualRingLb,
990            Algorithm::MixOnionRouting,
991            Algorithm::SessionResumptionBinding,
992        ],
993        4 => &[
994            Algorithm::MlKem1024,
995            Algorithm::MlDsa87,
996            Algorithm::DuplexSpongeAead,
997            Algorithm::TweakAead,
998        ],
999        5 => &[Algorithm::FnDsa1024],
1000        _ => &[],
1001    }
1002}
1003
1004#[cfg(test)]
1005mod tests {
1006    use super::*;
1007
1008    #[test]
1009    fn test_algorithm_registry() {
1010        let registry = AlgorithmRegistry::new();
1011
1012        // Test that we have algorithms
1013        let algorithms = registry.supported_algorithms();
1014        assert!(!algorithms.is_empty());
1015
1016        // Test category filtering
1017        let kem_algorithms = registry.algorithms_by_category(AlgorithmCategory::Kem);
1018        assert!(!kem_algorithms.is_empty());
1019
1020        // Test security level filtering
1021        let level1_algorithms = registry.algorithms_by_security_level(1);
1022        assert!(!level1_algorithms.is_empty());
1023
1024        // Test metadata retrieval
1025        let metadata = registry.get_metadata(&Algorithm::MlKem512);
1026        assert!(metadata.is_some());
1027        assert_eq!(metadata.unwrap().name, "ML-KEM-512");
1028    }
1029
1030    #[test]
1031    fn test_global_registry() {
1032        let algorithms = supported_algorithms();
1033        assert!(!algorithms.is_empty());
1034
1035        let kem_algorithms = algorithms_by_category(AlgorithmCategory::Kem);
1036        assert!(!kem_algorithms.is_empty());
1037    }
1038}