1#![no_std]
120#![forbid(unsafe_code)]
121
122use core::fmt;
123use core::sync::atomic::{AtomicU8, Ordering};
124
125#[derive(Debug, Clone, Copy, PartialEq, Eq)]
127#[repr(u8)]
128pub enum State {
129 PowerOff = 0,
131 SelfTest = 1,
134 Operational = 2,
137 Error = 3,
143}
144
145impl State {
146 const fn from_u8(raw: u8) -> Self {
147 match raw {
148 0 => Self::PowerOff,
149 1 => Self::SelfTest,
150 2 => Self::Operational,
151 _ => Self::Error,
157 }
158 }
159}
160
161impl fmt::Display for State {
162 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
163 let s = match self {
164 Self::PowerOff => "PowerOff",
165 Self::SelfTest => "SelfTest",
166 Self::Operational => "Operational",
167 Self::Error => "Error",
168 };
169 f.write_str(s)
170 }
171}
172
173static STATE: AtomicU8 = AtomicU8::new(State::PowerOff as u8);
176
177pub fn state() -> State {
179 State::from_u8(STATE.load(Ordering::Acquire))
180}
181
182pub fn is_operational() -> bool {
185 state() == State::Operational
186}
187
188pub fn require_operational() -> Result<(), Error> {
193 let current = state();
194 if current == State::Operational {
195 Ok(())
196 } else {
197 Err(Error::NotOperational { current })
198 }
199}
200
201#[derive(Debug, Clone, Copy, PartialEq, Eq)]
208pub enum Error {
209 NotOperational {
212 current: State,
214 },
215 SelfTestFailed {
218 test: &'static str,
221 },
222 ConditionalTestFailed {
225 reason: &'static str,
227 },
228 AlreadyInitialized,
234 InvalidInput,
242 AlgorithmRestricted {
248 service: Service,
250 },
251 NotImplemented,
258}
259
260impl fmt::Display for Error {
261 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
262 match self {
263 Self::NotOperational { current } => {
264 write!(f, "FIPS module not operational (state = {current})")
265 }
266 Self::SelfTestFailed { test } => {
267 write!(f, "FIPS power-up self-test failed: {test}")
268 }
269 Self::ConditionalTestFailed { reason } => {
270 write!(f, "FIPS conditional self-test failed: {reason}")
271 }
272 Self::AlreadyInitialized => f.write_str("FIPS module already initialized"),
273 Self::InvalidInput => f.write_str("invalid input to FIPS service"),
274 Self::AlgorithmRestricted { service } => {
275 write!(
276 f,
277 "algorithm {service} is not permitted under the {} profile",
278 active_profile()
279 )
280 }
281 Self::NotImplemented => f.write_str("algorithm not yet implemented"),
282 }
283 }
284}
285
286#[derive(Debug, Clone, Copy, PartialEq, Eq)]
295pub struct SelfTestFailure;
296
297impl fmt::Display for SelfTestFailure {
298 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
299 f.write_str("self-test failure")
300 }
301}
302
303pub trait SelfTest {
315 const NAME: &'static str;
318
319 fn run() -> Result<(), SelfTestFailure>;
323}
324
325#[derive(Debug, Clone, Copy)]
338pub struct KatEntry {
339 pub name: &'static str,
343 pub run: fn() -> Result<(), SelfTestFailure>,
345}
346
347pub fn initialize() -> Result<(), Error> {
356 initialize_with_tests(&[])
357}
358
359pub fn initialize_with_tests(tests: &[KatEntry]) -> Result<(), Error> {
378 let cas = STATE.compare_exchange(
381 State::PowerOff as u8,
382 State::SelfTest as u8,
383 Ordering::AcqRel,
384 Ordering::Acquire,
385 );
386 if cas.is_err() {
387 while STATE.load(Ordering::Acquire) == State::SelfTest as u8 {
392 core::hint::spin_loop();
393 }
394 return Err(Error::AlreadyInitialized);
395 }
396
397 for entry in tests {
398 let result = (entry.run)();
399 if result.is_err() {
400 STATE.store(State::Error as u8, Ordering::Release);
404 return Err(Error::SelfTestFailed { test: entry.name });
405 }
406 }
407
408 STATE.store(State::Operational as u8, Ordering::Release);
409 Ok(())
410}
411
412pub fn enter_error_state(_reason: &'static str) {
424 STATE.store(State::Error as u8, Ordering::Release);
425}
426
427#[derive(Debug, Clone, Copy, PartialEq, Eq)]
441#[repr(u8)]
442pub enum AlgorithmProfile {
443 Unrestricted = 0,
447 Cnsa2 = 1,
453 Cnsa1 = 2,
456}
457
458impl AlgorithmProfile {
459 const fn from_u8(raw: u8) -> Self {
460 match raw {
461 0 => Self::Unrestricted,
462 2 => Self::Cnsa1,
463 _ => Self::Cnsa2,
466 }
467 }
468}
469
470impl fmt::Display for AlgorithmProfile {
471 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
472 let s = match self {
473 Self::Unrestricted => "Unrestricted",
474 Self::Cnsa2 => "CNSA 2.0",
475 Self::Cnsa1 => "CNSA 1.0",
476 };
477 f.write_str(s)
478 }
479}
480
481static PROFILE: AtomicU8 = AtomicU8::new(AlgorithmProfile::Unrestricted as u8);
484
485pub fn active_profile() -> AlgorithmProfile {
487 AlgorithmProfile::from_u8(PROFILE.load(Ordering::Acquire))
488}
489
490pub fn initialize_with_profile(tests: &[KatEntry], profile: AlgorithmProfile) -> Result<(), Error> {
502 PROFILE.store(profile as u8, Ordering::Release);
506 initialize_with_tests(tests)
507}
508
509#[derive(Debug, Clone, Copy, PartialEq, Eq)]
520#[repr(u16)]
521#[allow(missing_docs)]
522pub enum Service {
523 Sha1 = 0,
525 Sha224 = 1,
526 Sha256 = 2,
527 Sha384 = 3,
528 Sha512 = 4,
529 Sha512_224 = 5,
530 Sha512_256 = 6,
531
532 Sha3_224 = 10,
533 Sha3_256 = 11,
534 Sha3_384 = 12,
535 Sha3_512 = 13,
536
537 Shake128 = 20,
539 Shake256 = 21,
540 CShake128 = 22,
541 CShake256 = 23,
542 Kmac128 = 24,
543 Kmac256 = 25,
544 KmacXof128 = 26,
545 KmacXof256 = 27,
546 TupleHash128 = 28,
547 TupleHash256 = 29,
548 TupleHashXof128 = 30,
549 TupleHashXof256 = 31,
550 ParallelHash128 = 32,
551 ParallelHash256 = 33,
552 ParallelHashXof128 = 34,
553 ParallelHashXof256 = 35,
554
555 HmacSha1 = 40,
557 HmacSha224 = 41,
558 HmacSha256 = 42,
559 HmacSha384 = 43,
560 HmacSha512 = 44,
561 HmacSha512_224 = 45,
562 HmacSha512_256 = 46,
563 HmacSha3_224 = 47,
564 HmacSha3_256 = 48,
565 HmacSha3_384 = 49,
566 HmacSha3_512 = 50,
567
568 CmacAes128 = 60,
570 CmacAes192 = 61,
571 CmacAes256 = 62,
572
573 Aes128Ecb = 70,
575 Aes128Cbc = 71,
576 Aes128Ctr = 72,
577 Aes128Gcm = 73,
578 Aes128Ccm = 74,
579 Aes128Kw = 75,
580 Aes128Kwp = 76,
581 Aes192Ecb = 80,
582 Aes192Cbc = 81,
583 Aes192Ctr = 82,
584 Aes192Gcm = 83,
585 Aes192Ccm = 84,
586 Aes192Kw = 85,
587 Aes192Kwp = 86,
588 Aes256Ecb = 90,
589 Aes256Cbc = 91,
590 Aes256Ctr = 92,
591 Aes256Gcm = 93,
592 Aes256Ccm = 94,
593 Aes256Kw = 95,
594 Aes256Kwp = 96,
595
596 Aes128 = 97,
603 Aes192 = 98,
605 Aes256 = 99,
607
608 CtrDrbgAes128 = 100,
610 CtrDrbgAes192 = 101,
611 CtrDrbgAes256 = 102,
612 HashDrbgSha256 = 103,
613 HashDrbgSha384 = 104,
614 HashDrbgSha512 = 105,
615 HmacDrbgSha256 = 106,
616 HmacDrbgSha384 = 107,
617 HmacDrbgSha512 = 108,
618
619 HkdfSha1 = 120,
621 HkdfSha256 = 121,
622 HkdfSha384 = 122,
623 HkdfSha512 = 123,
624 KbkdfHmacSha256 = 130,
625 KbkdfHmacSha384 = 131,
626 KbkdfHmacSha512 = 132,
627 KbkdfCmacAes128 = 133,
628 KbkdfCmacAes192 = 134,
629 KbkdfCmacAes256 = 135,
630 Pbkdf2HmacSha1 = 140,
631 Pbkdf2HmacSha224 = 141,
632 Pbkdf2HmacSha256 = 142,
633 Pbkdf2HmacSha384 = 143,
634 Pbkdf2HmacSha512 = 144,
635
636 RsaKeygen2048 = 150,
638 RsaPkcs1v15Sign2048 = 151,
639 RsaPssSign2048 = 152,
640 RsaOaep2048 = 153,
641 RsaPkcs1v15Verify2048 = 154,
642 RsaPssVerify2048 = 155,
643 RsaKeygen3072 = 160,
644 RsaPkcs1v15Sign3072 = 161,
645 RsaPssSign3072 = 162,
646 RsaOaep3072 = 163,
647 RsaPkcs1v15Verify3072 = 164,
648 RsaPssVerify3072 = 165,
649 RsaKeygen4096 = 170,
650 RsaPkcs1v15Sign4096 = 171,
651 RsaPssSign4096 = 172,
652 RsaOaep4096 = 173,
653 RsaPkcs1v15Verify4096 = 174,
654 RsaPssVerify4096 = 175,
655
656 EcdsaP256Sign = 200,
658 EcdsaP256Verify = 201,
659 EcdsaP256Keygen = 202,
660 EcdsaP384Sign = 210,
661 EcdsaP384Verify = 211,
662 EcdsaP384Keygen = 212,
663
664 EcdhP256 = 220,
666 EcdhP384 = 221,
667
668 Ed25519Sign = 230,
670 Ed25519Verify = 231,
671 Ed25519Keygen = 232,
672
673 Tls12Kdf = 240,
675 Tls13Kdf = 241,
676
677 MlKem1024Encaps = 300,
679 MlKem1024Decaps = 301,
680 MlKem1024Keygen = 302,
681 MlKem512Encaps = 303,
682 MlKem512Decaps = 304,
683 MlKem512Keygen = 305,
684 MlKem768Encaps = 306,
685 MlKem768Decaps = 307,
686 MlKem768Keygen = 308,
687
688 MlDsa87Sign = 310,
690 MlDsa87Verify = 311,
691 MlDsa87Keygen = 312,
692 MlDsa44Sign = 313,
693 MlDsa44Verify = 314,
694 MlDsa44Keygen = 315,
695 MlDsa65Sign = 316,
696 MlDsa65Verify = 317,
697 MlDsa65Keygen = 318,
698
699 SlhDsaSha2256sKeygen = 320,
703 SlhDsaSha2256sSign = 321,
704 SlhDsaSha2256sVerify = 322,
705 SlhDsaSha2128sKeygen = 323,
706 SlhDsaSha2128sSign = 324,
707 SlhDsaSha2128sVerify = 325,
708 SlhDsaSha2128fKeygen = 326,
709 SlhDsaSha2128fSign = 327,
710 SlhDsaSha2128fVerify = 328,
711 SlhDsaSha2192sKeygen = 329,
712 SlhDsaSha2192sSign = 330,
713 SlhDsaSha2192sVerify = 331,
714 SlhDsaSha2192fKeygen = 332,
715 SlhDsaSha2192fSign = 333,
716 SlhDsaSha2192fVerify = 334,
717 SlhDsaSha2256fKeygen = 335,
718 SlhDsaSha2256fSign = 336,
719 SlhDsaSha2256fVerify = 337,
720 SlhDsaShake128sKeygen = 338,
721 SlhDsaShake128sSign = 339,
722 SlhDsaShake128sVerify = 340,
723 SlhDsaShake128fKeygen = 341,
724 SlhDsaShake128fSign = 342,
725 SlhDsaShake128fVerify = 343,
726 SlhDsaShake192sKeygen = 344,
727 SlhDsaShake192sSign = 345,
728 SlhDsaShake192sVerify = 346,
729 SlhDsaShake192fKeygen = 347,
730 SlhDsaShake192fSign = 348,
731 SlhDsaShake192fVerify = 349,
732 SlhDsaShake256sKeygen = 350,
733 SlhDsaShake256sSign = 351,
734 SlhDsaShake256sVerify = 352,
735 SlhDsaShake256fKeygen = 353,
736 SlhDsaShake256fSign = 354,
737 SlhDsaShake256fVerify = 355,
738
739 LmsSha256M32H5W1Sign = 500,
749 LmsSha256M32H5W1Verify = 501,
750 LmsSha256M32H5W2Sign = 502,
751 LmsSha256M32H5W2Verify = 503,
752 LmsSha256M32H5W4Sign = 504,
753 LmsSha256M32H5W4Verify = 505,
754 LmsSha256M32H5W8Sign = 506,
755 LmsSha256M32H5W8Verify = 507,
756 LmsSha256M32H10W1Sign = 508,
757 LmsSha256M32H10W1Verify = 509,
758 LmsSha256M32H10W2Sign = 510,
759 LmsSha256M32H10W2Verify = 511,
760 LmsSha256M32H10W4Sign = 512, LmsSha256M32H10W4Verify = 513, LmsSha256M32H10W8Sign = 514, LmsSha256M32H10W8Verify = 515, LmsSha256M32H15W1Sign = 516,
765 LmsSha256M32H15W1Verify = 517,
766 LmsSha256M32H15W2Sign = 518,
767 LmsSha256M32H15W2Verify = 519,
768 LmsSha256M32H15W4Sign = 520, LmsSha256M32H15W4Verify = 521, LmsSha256M32H15W8Sign = 522, LmsSha256M32H15W8Verify = 523, LmsSha256M32H20W1Sign = 524,
773 LmsSha256M32H20W1Verify = 525,
774 LmsSha256M32H20W2Sign = 526,
775 LmsSha256M32H20W2Verify = 527,
776 LmsSha256M32H20W4Sign = 528, LmsSha256M32H20W4Verify = 529, LmsSha256M32H20W8Sign = 530, LmsSha256M32H20W8Verify = 531, LmsSha256M32H25W1Sign = 532,
781 LmsSha256M32H25W1Verify = 533,
782 LmsSha256M32H25W2Sign = 534,
783 LmsSha256M32H25W2Verify = 535,
784 LmsSha256M32H25W4Sign = 536, LmsSha256M32H25W4Verify = 537, LmsSha256M32H25W8Sign = 538, LmsSha256M32H25W8Verify = 539, LmsSha256M24H5W1Sign = 540,
791 LmsSha256M24H5W1Verify = 541,
792 LmsSha256M24H5W2Sign = 542,
793 LmsSha256M24H5W2Verify = 543,
794 LmsSha256M24H5W4Sign = 544,
795 LmsSha256M24H5W4Verify = 545,
796 LmsSha256M24H5W8Sign = 546,
797 LmsSha256M24H5W8Verify = 547,
798 LmsSha256M24H10W1Sign = 548,
799 LmsSha256M24H10W1Verify = 549,
800 LmsSha256M24H10W2Sign = 550,
801 LmsSha256M24H10W2Verify = 551,
802 LmsSha256M24H10W4Sign = 552,
803 LmsSha256M24H10W4Verify = 553,
804 LmsSha256M24H10W8Sign = 554,
805 LmsSha256M24H10W8Verify = 555,
806 LmsSha256M24H15W1Sign = 556,
807 LmsSha256M24H15W1Verify = 557,
808 LmsSha256M24H15W2Sign = 558,
809 LmsSha256M24H15W2Verify = 559,
810 LmsSha256M24H15W4Sign = 560,
811 LmsSha256M24H15W4Verify = 561,
812 LmsSha256M24H15W8Sign = 562,
813 LmsSha256M24H15W8Verify = 563,
814 LmsSha256M24H20W1Sign = 564,
815 LmsSha256M24H20W1Verify = 565,
816 LmsSha256M24H20W2Sign = 566,
817 LmsSha256M24H20W2Verify = 567,
818 LmsSha256M24H20W4Sign = 568,
819 LmsSha256M24H20W4Verify = 569,
820 LmsSha256M24H20W8Sign = 570,
821 LmsSha256M24H20W8Verify = 571,
822 LmsSha256M24H25W1Sign = 572,
823 LmsSha256M24H25W1Verify = 573,
824 LmsSha256M24H25W2Sign = 574,
825 LmsSha256M24H25W2Verify = 575,
826 LmsSha256M24H25W4Sign = 576,
827 LmsSha256M24H25W4Verify = 577,
828 LmsSha256M24H25W8Sign = 578,
829 LmsSha256M24H25W8Verify = 579,
830
831 LmsShakeM32H5W1Sign = 580,
833 LmsShakeM32H5W1Verify = 581,
834 LmsShakeM32H5W2Sign = 582,
835 LmsShakeM32H5W2Verify = 583,
836 LmsShakeM32H5W4Sign = 584,
837 LmsShakeM32H5W4Verify = 585,
838 LmsShakeM32H5W8Sign = 586,
839 LmsShakeM32H5W8Verify = 587,
840 LmsShakeM32H10W1Sign = 588,
841 LmsShakeM32H10W1Verify = 589,
842 LmsShakeM32H10W2Sign = 590,
843 LmsShakeM32H10W2Verify = 591,
844 LmsShakeM32H10W4Sign = 592,
845 LmsShakeM32H10W4Verify = 593,
846 LmsShakeM32H10W8Sign = 594,
847 LmsShakeM32H10W8Verify = 595,
848 LmsShakeM32H15W1Sign = 596,
849 LmsShakeM32H15W1Verify = 597,
850 LmsShakeM32H15W2Sign = 598,
851 LmsShakeM32H15W2Verify = 599,
852 LmsShakeM32H15W4Sign = 600,
853 LmsShakeM32H15W4Verify = 601,
854 LmsShakeM32H15W8Sign = 602,
855 LmsShakeM32H15W8Verify = 603,
856 LmsShakeM32H20W1Sign = 604,
857 LmsShakeM32H20W1Verify = 605,
858 LmsShakeM32H20W2Sign = 606,
859 LmsShakeM32H20W2Verify = 607,
860 LmsShakeM32H20W4Sign = 608,
861 LmsShakeM32H20W4Verify = 609,
862 LmsShakeM32H20W8Sign = 610,
863 LmsShakeM32H20W8Verify = 611,
864 LmsShakeM32H25W1Sign = 612,
865 LmsShakeM32H25W1Verify = 613,
866 LmsShakeM32H25W2Sign = 614,
867 LmsShakeM32H25W2Verify = 615,
868 LmsShakeM32H25W4Sign = 616,
869 LmsShakeM32H25W4Verify = 617,
870 LmsShakeM32H25W8Sign = 618,
871 LmsShakeM32H25W8Verify = 619,
872
873 LmsShakeM24H5W1Sign = 620,
875 LmsShakeM24H5W1Verify = 621,
876 LmsShakeM24H5W2Sign = 622,
877 LmsShakeM24H5W2Verify = 623,
878 LmsShakeM24H5W4Sign = 624,
879 LmsShakeM24H5W4Verify = 625,
880 LmsShakeM24H5W8Sign = 626,
881 LmsShakeM24H5W8Verify = 627,
882 LmsShakeM24H10W1Sign = 628,
883 LmsShakeM24H10W1Verify = 629,
884 LmsShakeM24H10W2Sign = 630,
885 LmsShakeM24H10W2Verify = 631,
886 LmsShakeM24H10W4Sign = 632,
887 LmsShakeM24H10W4Verify = 633,
888 LmsShakeM24H10W8Sign = 634,
889 LmsShakeM24H10W8Verify = 635,
890 LmsShakeM24H15W1Sign = 636,
891 LmsShakeM24H15W1Verify = 637,
892 LmsShakeM24H15W2Sign = 638,
893 LmsShakeM24H15W2Verify = 639,
894 LmsShakeM24H15W4Sign = 640,
895 LmsShakeM24H15W4Verify = 641,
896 LmsShakeM24H15W8Sign = 642,
897 LmsShakeM24H15W8Verify = 643,
898 LmsShakeM24H20W1Sign = 644,
899 LmsShakeM24H20W1Verify = 645,
900 LmsShakeM24H20W2Sign = 646,
901 LmsShakeM24H20W2Verify = 647,
902 LmsShakeM24H20W4Sign = 648,
903 LmsShakeM24H20W4Verify = 649,
904 LmsShakeM24H20W8Sign = 650,
905 LmsShakeM24H20W8Verify = 651,
906 LmsShakeM24H25W1Sign = 652,
907 LmsShakeM24H25W1Verify = 653,
908 LmsShakeM24H25W2Sign = 654,
909 LmsShakeM24H25W2Verify = 655,
910 LmsShakeM24H25W4Sign = 656,
911 LmsShakeM24H25W4Verify = 657,
912 LmsShakeM24H25W8Sign = 658,
913 LmsShakeM24H25W8Verify = 659,
914
915 XmssSign = 370,
918 XmssVerify = 371,
919
920 Dh3072 = 380,
923}
924
925impl fmt::Display for Service {
926 #[allow(clippy::too_many_lines)]
930 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
931 let name = match self {
932 Self::Sha1 => "SHA-1",
933 Self::Sha224 => "SHA-224",
934 Self::Sha256 => "SHA-256",
935 Self::Sha384 => "SHA-384",
936 Self::Sha512 => "SHA-512",
937 Self::Sha512_224 => "SHA-512/224",
938 Self::Sha512_256 => "SHA-512/256",
939 Self::Sha3_224 => "SHA3-224",
940 Self::Sha3_256 => "SHA3-256",
941 Self::Sha3_384 => "SHA3-384",
942 Self::Sha3_512 => "SHA3-512",
943 Self::Shake128 => "SHAKE128",
944 Self::Shake256 => "SHAKE256",
945 Self::CShake128 => "cSHAKE128",
946 Self::CShake256 => "cSHAKE256",
947 Self::Kmac128 => "KMAC128",
948 Self::Kmac256 => "KMAC256",
949 Self::KmacXof128 => "KMACXOF128",
950 Self::KmacXof256 => "KMACXOF256",
951 Self::TupleHash128 => "TupleHash128",
952 Self::TupleHash256 => "TupleHash256",
953 Self::TupleHashXof128 => "TupleHashXOF128",
954 Self::TupleHashXof256 => "TupleHashXOF256",
955 Self::ParallelHash128 => "ParallelHash128",
956 Self::ParallelHash256 => "ParallelHash256",
957 Self::ParallelHashXof128 => "ParallelHashXOF128",
958 Self::ParallelHashXof256 => "ParallelHashXOF256",
959 Self::HmacSha1 => "HMAC-SHA-1",
960 Self::HmacSha224 => "HMAC-SHA-224",
961 Self::HmacSha256 => "HMAC-SHA-256",
962 Self::HmacSha384 => "HMAC-SHA-384",
963 Self::HmacSha512 => "HMAC-SHA-512",
964 Self::HmacSha512_224 => "HMAC-SHA-512/224",
965 Self::HmacSha512_256 => "HMAC-SHA-512/256",
966 Self::HmacSha3_224 => "HMAC-SHA3-224",
967 Self::HmacSha3_256 => "HMAC-SHA3-256",
968 Self::HmacSha3_384 => "HMAC-SHA3-384",
969 Self::HmacSha3_512 => "HMAC-SHA3-512",
970 Self::CmacAes128 => "CMAC-AES-128",
971 Self::CmacAes192 => "CMAC-AES-192",
972 Self::CmacAes256 => "CMAC-AES-256",
973 Self::Aes128Ecb => "AES-128-ECB",
974 Self::Aes128Cbc => "AES-128-CBC",
975 Self::Aes128Ctr => "AES-128-CTR",
976 Self::Aes128Gcm => "AES-128-GCM",
977 Self::Aes128Ccm => "AES-128-CCM",
978 Self::Aes128Kw => "AES-128-KW",
979 Self::Aes128Kwp => "AES-128-KWP",
980 Self::Aes192Ecb => "AES-192-ECB",
981 Self::Aes192Cbc => "AES-192-CBC",
982 Self::Aes192Ctr => "AES-192-CTR",
983 Self::Aes192Gcm => "AES-192-GCM",
984 Self::Aes192Ccm => "AES-192-CCM",
985 Self::Aes192Kw => "AES-192-KW",
986 Self::Aes192Kwp => "AES-192-KWP",
987 Self::Aes256Ecb => "AES-256-ECB",
988 Self::Aes256Cbc => "AES-256-CBC",
989 Self::Aes256Ctr => "AES-256-CTR",
990 Self::Aes256Gcm => "AES-256-GCM",
991 Self::Aes256Ccm => "AES-256-CCM",
992 Self::Aes256Kw => "AES-256-KW",
993 Self::Aes256Kwp => "AES-256-KWP",
994 Self::Aes128 => "AES-128",
995 Self::Aes192 => "AES-192",
996 Self::Aes256 => "AES-256",
997 Self::CtrDrbgAes128 => "CTR_DRBG-AES-128",
998 Self::CtrDrbgAes192 => "CTR_DRBG-AES-192",
999 Self::CtrDrbgAes256 => "CTR_DRBG-AES-256",
1000 Self::HashDrbgSha256 => "Hash_DRBG-SHA-256",
1001 Self::HashDrbgSha384 => "Hash_DRBG-SHA-384",
1002 Self::HashDrbgSha512 => "Hash_DRBG-SHA-512",
1003 Self::HmacDrbgSha256 => "HMAC_DRBG-SHA-256",
1004 Self::HmacDrbgSha384 => "HMAC_DRBG-SHA-384",
1005 Self::HmacDrbgSha512 => "HMAC_DRBG-SHA-512",
1006 Self::HkdfSha1 => "HKDF-SHA-1",
1007 Self::HkdfSha256 => "HKDF-SHA-256",
1008 Self::HkdfSha384 => "HKDF-SHA-384",
1009 Self::HkdfSha512 => "HKDF-SHA-512",
1010 Self::KbkdfHmacSha256 => "KBKDF-HMAC-SHA-256",
1011 Self::KbkdfHmacSha384 => "KBKDF-HMAC-SHA-384",
1012 Self::KbkdfHmacSha512 => "KBKDF-HMAC-SHA-512",
1013 Self::KbkdfCmacAes128 => "KBKDF-CMAC-AES-128",
1014 Self::KbkdfCmacAes192 => "KBKDF-CMAC-AES-192",
1015 Self::KbkdfCmacAes256 => "KBKDF-CMAC-AES-256",
1016 Self::Pbkdf2HmacSha1 => "PBKDF2-HMAC-SHA-1",
1017 Self::Pbkdf2HmacSha224 => "PBKDF2-HMAC-SHA-224",
1018 Self::Pbkdf2HmacSha256 => "PBKDF2-HMAC-SHA-256",
1019 Self::Pbkdf2HmacSha384 => "PBKDF2-HMAC-SHA-384",
1020 Self::Pbkdf2HmacSha512 => "PBKDF2-HMAC-SHA-512",
1021 Self::RsaKeygen2048 => "RSA-2048 keygen",
1022 Self::RsaPkcs1v15Sign2048 => "RSA-PKCS1v1.5-Sign-2048",
1023 Self::RsaPssSign2048 => "RSA-PSS-Sign-2048",
1024 Self::RsaOaep2048 => "RSA-OAEP-2048",
1025 Self::RsaPkcs1v15Verify2048 => "RSA-PKCS1v1.5-Verify-2048",
1026 Self::RsaPssVerify2048 => "RSA-PSS-Verify-2048",
1027 Self::RsaKeygen3072 => "RSA-3072 keygen",
1028 Self::RsaPkcs1v15Sign3072 => "RSA-PKCS1v1.5-Sign-3072",
1029 Self::RsaPssSign3072 => "RSA-PSS-Sign-3072",
1030 Self::RsaOaep3072 => "RSA-OAEP-3072",
1031 Self::RsaPkcs1v15Verify3072 => "RSA-PKCS1v1.5-Verify-3072",
1032 Self::RsaPssVerify3072 => "RSA-PSS-Verify-3072",
1033 Self::RsaKeygen4096 => "RSA-4096 keygen",
1034 Self::RsaPkcs1v15Sign4096 => "RSA-PKCS1v1.5-Sign-4096",
1035 Self::RsaPssSign4096 => "RSA-PSS-Sign-4096",
1036 Self::RsaOaep4096 => "RSA-OAEP-4096",
1037 Self::RsaPkcs1v15Verify4096 => "RSA-PKCS1v1.5-Verify-4096",
1038 Self::RsaPssVerify4096 => "RSA-PSS-Verify-4096",
1039 Self::EcdsaP256Sign => "ECDSA-P256 sign",
1040 Self::EcdsaP256Verify => "ECDSA-P256 verify",
1041 Self::EcdsaP256Keygen => "ECDSA-P256 keygen",
1042 Self::EcdsaP384Sign => "ECDSA-P384 sign",
1043 Self::EcdsaP384Verify => "ECDSA-P384 verify",
1044 Self::EcdsaP384Keygen => "ECDSA-P384 keygen",
1045 Self::EcdhP256 => "ECDH-P256",
1046 Self::EcdhP384 => "ECDH-P384",
1047 Self::Ed25519Sign => "Ed25519 sign",
1048 Self::Ed25519Verify => "Ed25519 verify",
1049 Self::Ed25519Keygen => "Ed25519 keygen",
1050 Self::Tls12Kdf => "TLS 1.2 KDF",
1051 Self::Tls13Kdf => "TLS 1.3 KDF",
1052 Self::MlKem1024Encaps => "ML-KEM-1024 encaps",
1053 Self::MlKem1024Decaps => "ML-KEM-1024 decaps",
1054 Self::MlKem1024Keygen => "ML-KEM-1024 keygen",
1055 Self::MlKem512Encaps => "ML-KEM-512 encaps",
1056 Self::MlKem512Decaps => "ML-KEM-512 decaps",
1057 Self::MlKem512Keygen => "ML-KEM-512 keygen",
1058 Self::MlKem768Encaps => "ML-KEM-768 encaps",
1059 Self::MlKem768Decaps => "ML-KEM-768 decaps",
1060 Self::MlKem768Keygen => "ML-KEM-768 keygen",
1061 Self::MlDsa87Sign => "ML-DSA-87 sign",
1062 Self::MlDsa87Verify => "ML-DSA-87 verify",
1063 Self::MlDsa87Keygen => "ML-DSA-87 keygen",
1064 Self::MlDsa44Sign => "ML-DSA-44 sign",
1065 Self::MlDsa44Verify => "ML-DSA-44 verify",
1066 Self::MlDsa44Keygen => "ML-DSA-44 keygen",
1067 Self::MlDsa65Sign => "ML-DSA-65 sign",
1068 Self::MlDsa65Verify => "ML-DSA-65 verify",
1069 Self::MlDsa65Keygen => "ML-DSA-65 keygen",
1070 Self::SlhDsaSha2256sKeygen => "SLH-DSA-SHA2-256s keygen",
1071 Self::SlhDsaSha2256sSign => "SLH-DSA-SHA2-256s sign",
1072 Self::SlhDsaSha2256sVerify => "SLH-DSA-SHA2-256s verify",
1073 Self::SlhDsaSha2128sKeygen => "SLH-DSA-SHA2-128s keygen",
1074 Self::SlhDsaSha2128sSign => "SLH-DSA-SHA2-128s sign",
1075 Self::SlhDsaSha2128sVerify => "SLH-DSA-SHA2-128s verify",
1076 Self::SlhDsaSha2128fKeygen => "SLH-DSA-SHA2-128f keygen",
1077 Self::SlhDsaSha2128fSign => "SLH-DSA-SHA2-128f sign",
1078 Self::SlhDsaSha2128fVerify => "SLH-DSA-SHA2-128f verify",
1079 Self::SlhDsaSha2192sKeygen => "SLH-DSA-SHA2-192s keygen",
1080 Self::SlhDsaSha2192sSign => "SLH-DSA-SHA2-192s sign",
1081 Self::SlhDsaSha2192sVerify => "SLH-DSA-SHA2-192s verify",
1082 Self::SlhDsaSha2192fKeygen => "SLH-DSA-SHA2-192f keygen",
1083 Self::SlhDsaSha2192fSign => "SLH-DSA-SHA2-192f sign",
1084 Self::SlhDsaSha2192fVerify => "SLH-DSA-SHA2-192f verify",
1085 Self::SlhDsaSha2256fKeygen => "SLH-DSA-SHA2-256f keygen",
1086 Self::SlhDsaSha2256fSign => "SLH-DSA-SHA2-256f sign",
1087 Self::SlhDsaSha2256fVerify => "SLH-DSA-SHA2-256f verify",
1088 Self::SlhDsaShake128sKeygen => "SLH-DSA-SHAKE-128s keygen",
1089 Self::SlhDsaShake128sSign => "SLH-DSA-SHAKE-128s sign",
1090 Self::SlhDsaShake128sVerify => "SLH-DSA-SHAKE-128s verify",
1091 Self::SlhDsaShake128fKeygen => "SLH-DSA-SHAKE-128f keygen",
1092 Self::SlhDsaShake128fSign => "SLH-DSA-SHAKE-128f sign",
1093 Self::SlhDsaShake128fVerify => "SLH-DSA-SHAKE-128f verify",
1094 Self::SlhDsaShake192sKeygen => "SLH-DSA-SHAKE-192s keygen",
1095 Self::SlhDsaShake192sSign => "SLH-DSA-SHAKE-192s sign",
1096 Self::SlhDsaShake192sVerify => "SLH-DSA-SHAKE-192s verify",
1097 Self::SlhDsaShake192fKeygen => "SLH-DSA-SHAKE-192f keygen",
1098 Self::SlhDsaShake192fSign => "SLH-DSA-SHAKE-192f sign",
1099 Self::SlhDsaShake192fVerify => "SLH-DSA-SHAKE-192f verify",
1100 Self::SlhDsaShake256sKeygen => "SLH-DSA-SHAKE-256s keygen",
1101 Self::SlhDsaShake256sSign => "SLH-DSA-SHAKE-256s sign",
1102 Self::SlhDsaShake256sVerify => "SLH-DSA-SHAKE-256s verify",
1103 Self::SlhDsaShake256fKeygen => "SLH-DSA-SHAKE-256f keygen",
1104 Self::SlhDsaShake256fSign => "SLH-DSA-SHAKE-256f sign",
1105 Self::SlhDsaShake256fVerify => "SLH-DSA-SHAKE-256f verify",
1106 Self::LmsSha256M32H5W1Sign => "LMS SHA-256 M=32 H=5 W=1 sign",
1107 Self::LmsSha256M32H5W1Verify => "LMS SHA-256 M=32 H=5 W=1 verify",
1108 Self::LmsSha256M32H5W2Sign => "LMS SHA-256 M=32 H=5 W=2 sign",
1109 Self::LmsSha256M32H5W2Verify => "LMS SHA-256 M=32 H=5 W=2 verify",
1110 Self::LmsSha256M32H5W4Sign => "LMS SHA-256 M=32 H=5 W=4 sign",
1111 Self::LmsSha256M32H5W4Verify => "LMS SHA-256 M=32 H=5 W=4 verify",
1112 Self::LmsSha256M32H5W8Sign => "LMS SHA-256 M=32 H=5 W=8 sign",
1113 Self::LmsSha256M32H5W8Verify => "LMS SHA-256 M=32 H=5 W=8 verify",
1114 Self::LmsSha256M32H10W1Sign => "LMS SHA-256 M=32 H=10 W=1 sign",
1115 Self::LmsSha256M32H10W1Verify => "LMS SHA-256 M=32 H=10 W=1 verify",
1116 Self::LmsSha256M32H10W2Sign => "LMS SHA-256 M=32 H=10 W=2 sign",
1117 Self::LmsSha256M32H10W2Verify => "LMS SHA-256 M=32 H=10 W=2 verify",
1118 Self::LmsSha256M32H10W4Sign => "LMS SHA-256 M=32 H=10 W=4 sign",
1119 Self::LmsSha256M32H10W4Verify => "LMS SHA-256 M=32 H=10 W=4 verify",
1120 Self::LmsSha256M32H10W8Sign => "LMS SHA-256 M=32 H=10 W=8 sign",
1121 Self::LmsSha256M32H10W8Verify => "LMS SHA-256 M=32 H=10 W=8 verify",
1122 Self::LmsSha256M32H15W1Sign => "LMS SHA-256 M=32 H=15 W=1 sign",
1123 Self::LmsSha256M32H15W1Verify => "LMS SHA-256 M=32 H=15 W=1 verify",
1124 Self::LmsSha256M32H15W2Sign => "LMS SHA-256 M=32 H=15 W=2 sign",
1125 Self::LmsSha256M32H15W2Verify => "LMS SHA-256 M=32 H=15 W=2 verify",
1126 Self::LmsSha256M32H15W4Sign => "LMS SHA-256 M=32 H=15 W=4 sign",
1127 Self::LmsSha256M32H15W4Verify => "LMS SHA-256 M=32 H=15 W=4 verify",
1128 Self::LmsSha256M32H15W8Sign => "LMS SHA-256 M=32 H=15 W=8 sign",
1129 Self::LmsSha256M32H15W8Verify => "LMS SHA-256 M=32 H=15 W=8 verify",
1130 Self::LmsSha256M32H20W1Sign => "LMS SHA-256 M=32 H=20 W=1 sign",
1131 Self::LmsSha256M32H20W1Verify => "LMS SHA-256 M=32 H=20 W=1 verify",
1132 Self::LmsSha256M32H20W2Sign => "LMS SHA-256 M=32 H=20 W=2 sign",
1133 Self::LmsSha256M32H20W2Verify => "LMS SHA-256 M=32 H=20 W=2 verify",
1134 Self::LmsSha256M32H20W4Sign => "LMS SHA-256 M=32 H=20 W=4 sign",
1135 Self::LmsSha256M32H20W4Verify => "LMS SHA-256 M=32 H=20 W=4 verify",
1136 Self::LmsSha256M32H20W8Sign => "LMS SHA-256 M=32 H=20 W=8 sign",
1137 Self::LmsSha256M32H20W8Verify => "LMS SHA-256 M=32 H=20 W=8 verify",
1138 Self::LmsSha256M32H25W1Sign => "LMS SHA-256 M=32 H=25 W=1 sign",
1139 Self::LmsSha256M32H25W1Verify => "LMS SHA-256 M=32 H=25 W=1 verify",
1140 Self::LmsSha256M32H25W2Sign => "LMS SHA-256 M=32 H=25 W=2 sign",
1141 Self::LmsSha256M32H25W2Verify => "LMS SHA-256 M=32 H=25 W=2 verify",
1142 Self::LmsSha256M32H25W4Sign => "LMS SHA-256 M=32 H=25 W=4 sign",
1143 Self::LmsSha256M32H25W4Verify => "LMS SHA-256 M=32 H=25 W=4 verify",
1144 Self::LmsSha256M32H25W8Sign => "LMS SHA-256 M=32 H=25 W=8 sign",
1145 Self::LmsSha256M32H25W8Verify => "LMS SHA-256 M=32 H=25 W=8 verify",
1146 Self::LmsSha256M24H5W1Sign => "LMS SHA-256 M=24 H=5 W=1 sign",
1147 Self::LmsSha256M24H5W1Verify => "LMS SHA-256 M=24 H=5 W=1 verify",
1148 Self::LmsSha256M24H5W2Sign => "LMS SHA-256 M=24 H=5 W=2 sign",
1149 Self::LmsSha256M24H5W2Verify => "LMS SHA-256 M=24 H=5 W=2 verify",
1150 Self::LmsSha256M24H5W4Sign => "LMS SHA-256 M=24 H=5 W=4 sign",
1151 Self::LmsSha256M24H5W4Verify => "LMS SHA-256 M=24 H=5 W=4 verify",
1152 Self::LmsSha256M24H5W8Sign => "LMS SHA-256 M=24 H=5 W=8 sign",
1153 Self::LmsSha256M24H5W8Verify => "LMS SHA-256 M=24 H=5 W=8 verify",
1154 Self::LmsSha256M24H10W1Sign => "LMS SHA-256 M=24 H=10 W=1 sign",
1155 Self::LmsSha256M24H10W1Verify => "LMS SHA-256 M=24 H=10 W=1 verify",
1156 Self::LmsSha256M24H10W2Sign => "LMS SHA-256 M=24 H=10 W=2 sign",
1157 Self::LmsSha256M24H10W2Verify => "LMS SHA-256 M=24 H=10 W=2 verify",
1158 Self::LmsSha256M24H10W4Sign => "LMS SHA-256 M=24 H=10 W=4 sign",
1159 Self::LmsSha256M24H10W4Verify => "LMS SHA-256 M=24 H=10 W=4 verify",
1160 Self::LmsSha256M24H10W8Sign => "LMS SHA-256 M=24 H=10 W=8 sign",
1161 Self::LmsSha256M24H10W8Verify => "LMS SHA-256 M=24 H=10 W=8 verify",
1162 Self::LmsSha256M24H15W1Sign => "LMS SHA-256 M=24 H=15 W=1 sign",
1163 Self::LmsSha256M24H15W1Verify => "LMS SHA-256 M=24 H=15 W=1 verify",
1164 Self::LmsSha256M24H15W2Sign => "LMS SHA-256 M=24 H=15 W=2 sign",
1165 Self::LmsSha256M24H15W2Verify => "LMS SHA-256 M=24 H=15 W=2 verify",
1166 Self::LmsSha256M24H15W4Sign => "LMS SHA-256 M=24 H=15 W=4 sign",
1167 Self::LmsSha256M24H15W4Verify => "LMS SHA-256 M=24 H=15 W=4 verify",
1168 Self::LmsSha256M24H15W8Sign => "LMS SHA-256 M=24 H=15 W=8 sign",
1169 Self::LmsSha256M24H15W8Verify => "LMS SHA-256 M=24 H=15 W=8 verify",
1170 Self::LmsSha256M24H20W1Sign => "LMS SHA-256 M=24 H=20 W=1 sign",
1171 Self::LmsSha256M24H20W1Verify => "LMS SHA-256 M=24 H=20 W=1 verify",
1172 Self::LmsSha256M24H20W2Sign => "LMS SHA-256 M=24 H=20 W=2 sign",
1173 Self::LmsSha256M24H20W2Verify => "LMS SHA-256 M=24 H=20 W=2 verify",
1174 Self::LmsSha256M24H20W4Sign => "LMS SHA-256 M=24 H=20 W=4 sign",
1175 Self::LmsSha256M24H20W4Verify => "LMS SHA-256 M=24 H=20 W=4 verify",
1176 Self::LmsSha256M24H20W8Sign => "LMS SHA-256 M=24 H=20 W=8 sign",
1177 Self::LmsSha256M24H20W8Verify => "LMS SHA-256 M=24 H=20 W=8 verify",
1178 Self::LmsSha256M24H25W1Sign => "LMS SHA-256 M=24 H=25 W=1 sign",
1179 Self::LmsSha256M24H25W1Verify => "LMS SHA-256 M=24 H=25 W=1 verify",
1180 Self::LmsSha256M24H25W2Sign => "LMS SHA-256 M=24 H=25 W=2 sign",
1181 Self::LmsSha256M24H25W2Verify => "LMS SHA-256 M=24 H=25 W=2 verify",
1182 Self::LmsSha256M24H25W4Sign => "LMS SHA-256 M=24 H=25 W=4 sign",
1183 Self::LmsSha256M24H25W4Verify => "LMS SHA-256 M=24 H=25 W=4 verify",
1184 Self::LmsSha256M24H25W8Sign => "LMS SHA-256 M=24 H=25 W=8 sign",
1185 Self::LmsSha256M24H25W8Verify => "LMS SHA-256 M=24 H=25 W=8 verify",
1186 Self::LmsShakeM32H5W1Sign => "LMS SHAKE M=32 H=5 W=1 sign",
1187 Self::LmsShakeM32H5W1Verify => "LMS SHAKE M=32 H=5 W=1 verify",
1188 Self::LmsShakeM32H5W2Sign => "LMS SHAKE M=32 H=5 W=2 sign",
1189 Self::LmsShakeM32H5W2Verify => "LMS SHAKE M=32 H=5 W=2 verify",
1190 Self::LmsShakeM32H5W4Sign => "LMS SHAKE M=32 H=5 W=4 sign",
1191 Self::LmsShakeM32H5W4Verify => "LMS SHAKE M=32 H=5 W=4 verify",
1192 Self::LmsShakeM32H5W8Sign => "LMS SHAKE M=32 H=5 W=8 sign",
1193 Self::LmsShakeM32H5W8Verify => "LMS SHAKE M=32 H=5 W=8 verify",
1194 Self::LmsShakeM32H10W1Sign => "LMS SHAKE M=32 H=10 W=1 sign",
1195 Self::LmsShakeM32H10W1Verify => "LMS SHAKE M=32 H=10 W=1 verify",
1196 Self::LmsShakeM32H10W2Sign => "LMS SHAKE M=32 H=10 W=2 sign",
1197 Self::LmsShakeM32H10W2Verify => "LMS SHAKE M=32 H=10 W=2 verify",
1198 Self::LmsShakeM32H10W4Sign => "LMS SHAKE M=32 H=10 W=4 sign",
1199 Self::LmsShakeM32H10W4Verify => "LMS SHAKE M=32 H=10 W=4 verify",
1200 Self::LmsShakeM32H10W8Sign => "LMS SHAKE M=32 H=10 W=8 sign",
1201 Self::LmsShakeM32H10W8Verify => "LMS SHAKE M=32 H=10 W=8 verify",
1202 Self::LmsShakeM32H15W1Sign => "LMS SHAKE M=32 H=15 W=1 sign",
1203 Self::LmsShakeM32H15W1Verify => "LMS SHAKE M=32 H=15 W=1 verify",
1204 Self::LmsShakeM32H15W2Sign => "LMS SHAKE M=32 H=15 W=2 sign",
1205 Self::LmsShakeM32H15W2Verify => "LMS SHAKE M=32 H=15 W=2 verify",
1206 Self::LmsShakeM32H15W4Sign => "LMS SHAKE M=32 H=15 W=4 sign",
1207 Self::LmsShakeM32H15W4Verify => "LMS SHAKE M=32 H=15 W=4 verify",
1208 Self::LmsShakeM32H15W8Sign => "LMS SHAKE M=32 H=15 W=8 sign",
1209 Self::LmsShakeM32H15W8Verify => "LMS SHAKE M=32 H=15 W=8 verify",
1210 Self::LmsShakeM32H20W1Sign => "LMS SHAKE M=32 H=20 W=1 sign",
1211 Self::LmsShakeM32H20W1Verify => "LMS SHAKE M=32 H=20 W=1 verify",
1212 Self::LmsShakeM32H20W2Sign => "LMS SHAKE M=32 H=20 W=2 sign",
1213 Self::LmsShakeM32H20W2Verify => "LMS SHAKE M=32 H=20 W=2 verify",
1214 Self::LmsShakeM32H20W4Sign => "LMS SHAKE M=32 H=20 W=4 sign",
1215 Self::LmsShakeM32H20W4Verify => "LMS SHAKE M=32 H=20 W=4 verify",
1216 Self::LmsShakeM32H20W8Sign => "LMS SHAKE M=32 H=20 W=8 sign",
1217 Self::LmsShakeM32H20W8Verify => "LMS SHAKE M=32 H=20 W=8 verify",
1218 Self::LmsShakeM32H25W1Sign => "LMS SHAKE M=32 H=25 W=1 sign",
1219 Self::LmsShakeM32H25W1Verify => "LMS SHAKE M=32 H=25 W=1 verify",
1220 Self::LmsShakeM32H25W2Sign => "LMS SHAKE M=32 H=25 W=2 sign",
1221 Self::LmsShakeM32H25W2Verify => "LMS SHAKE M=32 H=25 W=2 verify",
1222 Self::LmsShakeM32H25W4Sign => "LMS SHAKE M=32 H=25 W=4 sign",
1223 Self::LmsShakeM32H25W4Verify => "LMS SHAKE M=32 H=25 W=4 verify",
1224 Self::LmsShakeM32H25W8Sign => "LMS SHAKE M=32 H=25 W=8 sign",
1225 Self::LmsShakeM32H25W8Verify => "LMS SHAKE M=32 H=25 W=8 verify",
1226 Self::LmsShakeM24H5W1Sign => "LMS SHAKE M=24 H=5 W=1 sign",
1227 Self::LmsShakeM24H5W1Verify => "LMS SHAKE M=24 H=5 W=1 verify",
1228 Self::LmsShakeM24H5W2Sign => "LMS SHAKE M=24 H=5 W=2 sign",
1229 Self::LmsShakeM24H5W2Verify => "LMS SHAKE M=24 H=5 W=2 verify",
1230 Self::LmsShakeM24H5W4Sign => "LMS SHAKE M=24 H=5 W=4 sign",
1231 Self::LmsShakeM24H5W4Verify => "LMS SHAKE M=24 H=5 W=4 verify",
1232 Self::LmsShakeM24H5W8Sign => "LMS SHAKE M=24 H=5 W=8 sign",
1233 Self::LmsShakeM24H5W8Verify => "LMS SHAKE M=24 H=5 W=8 verify",
1234 Self::LmsShakeM24H10W1Sign => "LMS SHAKE M=24 H=10 W=1 sign",
1235 Self::LmsShakeM24H10W1Verify => "LMS SHAKE M=24 H=10 W=1 verify",
1236 Self::LmsShakeM24H10W2Sign => "LMS SHAKE M=24 H=10 W=2 sign",
1237 Self::LmsShakeM24H10W2Verify => "LMS SHAKE M=24 H=10 W=2 verify",
1238 Self::LmsShakeM24H10W4Sign => "LMS SHAKE M=24 H=10 W=4 sign",
1239 Self::LmsShakeM24H10W4Verify => "LMS SHAKE M=24 H=10 W=4 verify",
1240 Self::LmsShakeM24H10W8Sign => "LMS SHAKE M=24 H=10 W=8 sign",
1241 Self::LmsShakeM24H10W8Verify => "LMS SHAKE M=24 H=10 W=8 verify",
1242 Self::LmsShakeM24H15W1Sign => "LMS SHAKE M=24 H=15 W=1 sign",
1243 Self::LmsShakeM24H15W1Verify => "LMS SHAKE M=24 H=15 W=1 verify",
1244 Self::LmsShakeM24H15W2Sign => "LMS SHAKE M=24 H=15 W=2 sign",
1245 Self::LmsShakeM24H15W2Verify => "LMS SHAKE M=24 H=15 W=2 verify",
1246 Self::LmsShakeM24H15W4Sign => "LMS SHAKE M=24 H=15 W=4 sign",
1247 Self::LmsShakeM24H15W4Verify => "LMS SHAKE M=24 H=15 W=4 verify",
1248 Self::LmsShakeM24H15W8Sign => "LMS SHAKE M=24 H=15 W=8 sign",
1249 Self::LmsShakeM24H15W8Verify => "LMS SHAKE M=24 H=15 W=8 verify",
1250 Self::LmsShakeM24H20W1Sign => "LMS SHAKE M=24 H=20 W=1 sign",
1251 Self::LmsShakeM24H20W1Verify => "LMS SHAKE M=24 H=20 W=1 verify",
1252 Self::LmsShakeM24H20W2Sign => "LMS SHAKE M=24 H=20 W=2 sign",
1253 Self::LmsShakeM24H20W2Verify => "LMS SHAKE M=24 H=20 W=2 verify",
1254 Self::LmsShakeM24H20W4Sign => "LMS SHAKE M=24 H=20 W=4 sign",
1255 Self::LmsShakeM24H20W4Verify => "LMS SHAKE M=24 H=20 W=4 verify",
1256 Self::LmsShakeM24H20W8Sign => "LMS SHAKE M=24 H=20 W=8 sign",
1257 Self::LmsShakeM24H20W8Verify => "LMS SHAKE M=24 H=20 W=8 verify",
1258 Self::LmsShakeM24H25W1Sign => "LMS SHAKE M=24 H=25 W=1 sign",
1259 Self::LmsShakeM24H25W1Verify => "LMS SHAKE M=24 H=25 W=1 verify",
1260 Self::LmsShakeM24H25W2Sign => "LMS SHAKE M=24 H=25 W=2 sign",
1261 Self::LmsShakeM24H25W2Verify => "LMS SHAKE M=24 H=25 W=2 verify",
1262 Self::LmsShakeM24H25W4Sign => "LMS SHAKE M=24 H=25 W=4 sign",
1263 Self::LmsShakeM24H25W4Verify => "LMS SHAKE M=24 H=25 W=4 verify",
1264 Self::LmsShakeM24H25W8Sign => "LMS SHAKE M=24 H=25 W=8 sign",
1265 Self::LmsShakeM24H25W8Verify => "LMS SHAKE M=24 H=25 W=8 verify",
1266 Self::XmssSign => "XMSS sign",
1267 Self::XmssVerify => "XMSS verify",
1268 Self::Dh3072 => "DH-3072",
1269 };
1270 f.write_str(name)
1271 }
1272}
1273
1274pub fn require_allowed(service: Service) -> Result<(), Error> {
1290 let profile = active_profile();
1291 if is_allowed(profile, service) {
1292 Ok(())
1293 } else {
1294 Err(Error::AlgorithmRestricted { service })
1295 }
1296}
1297
1298const fn is_allowed(profile: AlgorithmProfile, service: Service) -> bool {
1301 match profile {
1302 AlgorithmProfile::Unrestricted => true,
1303 AlgorithmProfile::Cnsa2 => is_cnsa2_allowed(service),
1304 AlgorithmProfile::Cnsa1 => is_cnsa1_allowed(service),
1305 }
1306}
1307
1308const fn is_cnsa2_allowed(service: Service) -> bool {
1311 matches!(
1312 service,
1313 Service::Aes256Ecb
1315 | Service::Aes256Cbc
1316 | Service::Aes256Ctr
1317 | Service::Aes256Gcm
1318 | Service::Aes256Ccm
1319 | Service::Aes256Kw
1320 | Service::Aes256Kwp
1321 | Service::Aes256
1322 | Service::Sha384
1324 | Service::Sha512
1325 | Service::Sha3_384
1327 | Service::Sha3_512
1328 | Service::Shake256
1330 | Service::CShake256
1332 | Service::Kmac256
1333 | Service::KmacXof256
1334 | Service::TupleHash256
1335 | Service::TupleHashXof256
1336 | Service::ParallelHash256
1337 | Service::ParallelHashXof256
1338 | Service::HmacSha384
1340 | Service::HmacSha512
1341 | Service::HmacSha3_384
1342 | Service::HmacSha3_512
1343 | Service::CmacAes256
1345 | Service::CtrDrbgAes256
1347 | Service::HashDrbgSha384
1348 | Service::HashDrbgSha512
1349 | Service::HmacDrbgSha384
1350 | Service::HmacDrbgSha512
1351 | Service::HkdfSha384
1353 | Service::HkdfSha512
1354 | Service::KbkdfHmacSha384
1355 | Service::KbkdfHmacSha512
1356 | Service::KbkdfCmacAes256
1357 | Service::Pbkdf2HmacSha384
1358 | Service::Pbkdf2HmacSha512
1359 | Service::Tls13Kdf
1361 | Service::MlKem1024Encaps
1363 | Service::MlKem1024Decaps
1364 | Service::MlKem1024Keygen
1365 | Service::MlDsa87Sign
1366 | Service::MlDsa87Verify
1367 | Service::MlDsa87Keygen
1368 | Service::SlhDsaSha2256sKeygen
1373 | Service::SlhDsaSha2256sSign
1374 | Service::SlhDsaSha2256sVerify
1375 | Service::LmsSha256M32H10W4Sign
1380 | Service::LmsSha256M32H10W4Verify
1381 | Service::LmsSha256M32H10W8Sign
1382 | Service::LmsSha256M32H10W8Verify
1383 | Service::LmsSha256M32H15W4Sign
1384 | Service::LmsSha256M32H15W4Verify
1385 | Service::LmsSha256M32H15W8Sign
1386 | Service::LmsSha256M32H15W8Verify
1387 | Service::LmsSha256M32H20W4Sign
1388 | Service::LmsSha256M32H20W4Verify
1389 | Service::LmsSha256M32H20W8Sign
1390 | Service::LmsSha256M32H20W8Verify
1391 | Service::LmsSha256M32H25W4Sign
1392 | Service::LmsSha256M32H25W4Verify
1393 | Service::LmsSha256M32H25W8Sign
1394 | Service::LmsSha256M32H25W8Verify
1395 | Service::XmssSign
1396 | Service::XmssVerify
1397 )
1398}
1399
1400const fn is_cnsa1_allowed(service: Service) -> bool {
1407 matches!(
1408 service,
1409 Service::Aes256Ecb
1411 | Service::Aes256Cbc
1412 | Service::Aes256Ctr
1413 | Service::Aes256Gcm
1414 | Service::Aes256Ccm
1415 | Service::Aes256Kw
1416 | Service::Aes256Kwp
1417 | Service::Aes256
1418 | Service::Sha256
1420 | Service::Sha384
1421 | Service::Sha512
1422 | Service::Sha3_256
1424 | Service::Sha3_384
1425 | Service::Sha3_512
1426 | Service::Shake256
1428 | Service::CShake256
1430 | Service::Kmac256
1431 | Service::KmacXof256
1432 | Service::TupleHash256
1433 | Service::TupleHashXof256
1434 | Service::ParallelHash256
1435 | Service::ParallelHashXof256
1436 | Service::HmacSha256
1438 | Service::HmacSha384
1439 | Service::HmacSha512
1440 | Service::HmacSha3_256
1441 | Service::HmacSha3_384
1442 | Service::HmacSha3_512
1443 | Service::CmacAes256
1445 | Service::CtrDrbgAes256
1447 | Service::HashDrbgSha256
1448 | Service::HashDrbgSha384
1449 | Service::HashDrbgSha512
1450 | Service::HmacDrbgSha256
1451 | Service::HmacDrbgSha384
1452 | Service::HmacDrbgSha512
1453 | Service::HkdfSha256
1455 | Service::HkdfSha384
1456 | Service::HkdfSha512
1457 | Service::KbkdfHmacSha256
1458 | Service::KbkdfHmacSha384
1459 | Service::KbkdfHmacSha512
1460 | Service::KbkdfCmacAes256
1461 | Service::Pbkdf2HmacSha256
1462 | Service::Pbkdf2HmacSha384
1463 | Service::Pbkdf2HmacSha512
1464 | Service::EcdsaP384Sign
1466 | Service::EcdsaP384Verify
1467 | Service::EcdsaP384Keygen
1468 | Service::EcdhP384
1469 | Service::RsaKeygen3072
1471 | Service::RsaPkcs1v15Sign3072
1472 | Service::RsaPssSign3072
1473 | Service::RsaOaep3072
1474 | Service::RsaPkcs1v15Verify3072
1475 | Service::RsaPssVerify3072
1476 | Service::RsaKeygen4096
1477 | Service::RsaPkcs1v15Sign4096
1478 | Service::RsaPssSign4096
1479 | Service::RsaOaep4096
1480 | Service::RsaPkcs1v15Verify4096
1481 | Service::RsaPssVerify4096
1482 | Service::Dh3072
1484 | Service::Tls13Kdf
1488 | Service::MlKem1024Encaps
1490 | Service::MlKem1024Decaps
1491 | Service::MlKem1024Keygen
1492 | Service::MlDsa87Sign
1493 | Service::MlDsa87Verify
1494 | Service::MlDsa87Keygen
1495 | Service::LmsSha256M32H10W4Sign
1499 | Service::LmsSha256M32H10W4Verify
1500 | Service::LmsSha256M32H10W8Sign
1501 | Service::LmsSha256M32H10W8Verify
1502 | Service::LmsSha256M32H15W4Sign
1503 | Service::LmsSha256M32H15W4Verify
1504 | Service::LmsSha256M32H15W8Sign
1505 | Service::LmsSha256M32H15W8Verify
1506 | Service::LmsSha256M32H20W4Sign
1507 | Service::LmsSha256M32H20W4Verify
1508 | Service::LmsSha256M32H20W8Sign
1509 | Service::LmsSha256M32H20W8Verify
1510 | Service::LmsSha256M32H25W4Sign
1511 | Service::LmsSha256M32H25W4Verify
1512 | Service::LmsSha256M32H25W8Sign
1513 | Service::LmsSha256M32H25W8Verify
1514 | Service::XmssSign
1515 | Service::XmssVerify
1516 )
1517}
1518
1519#[cfg(test)]
1529fn reset_for_test() {
1530 STATE.store(State::PowerOff as u8, Ordering::Release);
1531 PROFILE.store(AlgorithmProfile::Unrestricted as u8, Ordering::Release);
1532}
1533
1534#[cfg(test)]
1535extern crate alloc;
1536
1537#[cfg(test)]
1538#[allow(clippy::unwrap_used, clippy::panic)]
1539mod tests {
1540 use super::{
1541 AlgorithmProfile, Error, KatEntry, SelfTest, SelfTestFailure, Service, State,
1542 active_profile, enter_error_state, initialize, initialize_with_profile,
1543 initialize_with_tests, is_allowed, is_operational, require_allowed, require_operational,
1544 reset_for_test, state,
1545 };
1546 use alloc::string::ToString;
1547
1548 #[allow(clippy::unnecessary_wraps)]
1552 fn always_pass() -> Result<(), SelfTestFailure> {
1553 Ok(())
1554 }
1555 fn always_fail() -> Result<(), SelfTestFailure> {
1556 Err(SelfTestFailure)
1557 }
1558
1559 #[test]
1564 fn initial_state_is_power_off() {
1565 reset_for_test();
1566 assert_eq!(state(), State::PowerOff);
1567 assert!(!is_operational());
1568 }
1569
1570 #[test]
1571 fn initialize_transitions_to_operational() {
1572 reset_for_test();
1573 initialize().unwrap();
1574 assert_eq!(state(), State::Operational);
1575 assert!(is_operational());
1576 require_operational().unwrap();
1577 }
1578
1579 #[test]
1580 fn second_initialize_reports_already_initialized() {
1581 reset_for_test();
1582 initialize().unwrap();
1583 match initialize() {
1584 Err(Error::AlreadyInitialized) => {}
1585 other => panic!("expected AlreadyInitialized, got {other:?}"),
1586 }
1587 }
1588
1589 #[test]
1590 fn require_operational_rejects_power_off() {
1591 reset_for_test();
1592 match require_operational() {
1593 Err(Error::NotOperational {
1594 current: State::PowerOff,
1595 }) => {}
1596 other => panic!("expected NotOperational{{PowerOff}}, got {other:?}"),
1597 }
1598 }
1599
1600 #[test]
1601 fn enter_error_state_is_terminal_for_require_operational() {
1602 reset_for_test();
1603 initialize().unwrap();
1604 assert!(is_operational());
1605 enter_error_state("unit-test forced failure");
1606 assert_eq!(state(), State::Error);
1607 match require_operational() {
1608 Err(Error::NotOperational {
1609 current: State::Error,
1610 }) => {}
1611 other => panic!("expected NotOperational{{Error}}, got {other:?}"),
1612 }
1613 }
1614
1615 #[test]
1616 fn state_display_is_stable() {
1617 assert_eq!(State::PowerOff.to_string(), "PowerOff");
1620 assert_eq!(State::SelfTest.to_string(), "SelfTest");
1621 assert_eq!(State::Operational.to_string(), "Operational");
1622 assert_eq!(State::Error.to_string(), "Error");
1623 }
1624
1625 #[test]
1626 fn registry_runs_passing_tests_and_reaches_operational() {
1627 reset_for_test();
1628 let tests = [
1629 KatEntry {
1630 name: "dummy-pass-a",
1631 run: always_pass,
1632 },
1633 KatEntry {
1634 name: "dummy-pass-b",
1635 run: always_pass,
1636 },
1637 ];
1638 initialize_with_tests(&tests).unwrap();
1639 assert_eq!(state(), State::Operational);
1640 }
1641
1642 #[test]
1643 fn registry_failing_test_latches_error_and_returns_name() {
1644 reset_for_test();
1645 let tests = [
1646 KatEntry {
1647 name: "dummy-pass",
1648 run: always_pass,
1649 },
1650 KatEntry {
1651 name: "dummy-fail",
1652 run: always_fail,
1653 },
1654 KatEntry {
1656 name: "dummy-unreached",
1657 run: always_pass,
1658 },
1659 ];
1660 match initialize_with_tests(&tests) {
1661 Err(Error::SelfTestFailed { test: "dummy-fail" }) => {}
1662 other => panic!("expected SelfTestFailed{{dummy-fail}}, got {other:?}"),
1663 }
1664 assert_eq!(state(), State::Error);
1665 assert!(matches!(
1667 require_operational(),
1668 Err(Error::NotOperational {
1669 current: State::Error
1670 })
1671 ));
1672 }
1673
1674 struct DummyTest;
1677 impl SelfTest for DummyTest {
1678 const NAME: &'static str = "dummy-trait-vector";
1679 fn run() -> Result<(), SelfTestFailure> {
1680 Ok(())
1681 }
1682 }
1683
1684 #[test]
1685 fn dummy_self_test_trait_is_usable() {
1686 assert_eq!(DummyTest::NAME, "dummy-trait-vector");
1687 DummyTest::run().unwrap();
1688 }
1689
1690 #[test]
1695 fn default_profile_is_unrestricted() {
1696 reset_for_test();
1697 assert_eq!(active_profile(), AlgorithmProfile::Unrestricted);
1698 }
1699
1700 #[test]
1701 fn initialize_with_profile_sets_cnsa2() {
1702 reset_for_test();
1703 initialize_with_profile(&[], AlgorithmProfile::Cnsa2).unwrap();
1704 assert_eq!(active_profile(), AlgorithmProfile::Cnsa2);
1705 assert!(is_operational());
1706 }
1707
1708 #[test]
1709 fn initialize_with_profile_sets_cnsa1() {
1710 reset_for_test();
1711 initialize_with_profile(&[], AlgorithmProfile::Cnsa1).unwrap();
1712 assert_eq!(active_profile(), AlgorithmProfile::Cnsa1);
1713 assert!(is_operational());
1714 }
1715
1716 #[test]
1717 fn unrestricted_allows_all_services() {
1718 let spot = [
1720 Service::Sha1,
1721 Service::Sha256,
1722 Service::Aes128Ecb,
1723 Service::Aes256Gcm,
1724 Service::CtrDrbgAes128,
1725 Service::EcdsaP256Sign,
1726 Service::Ed25519Sign,
1727 Service::RsaPssSign2048,
1728 Service::MlKem1024Encaps,
1729 Service::LmsSha256M32H10W4Sign,
1730 Service::Dh3072,
1731 Service::SlhDsaSha2256sSign,
1732 Service::Tls12Kdf,
1733 Service::Tls13Kdf,
1734 ];
1735 for svc in spot {
1736 assert!(
1737 is_allowed(AlgorithmProfile::Unrestricted, svc),
1738 "{svc} should be allowed in Unrestricted"
1739 );
1740 }
1741 }
1742
1743 #[test]
1744 fn cnsa2_allows_aes256_and_pq() {
1745 let allowed = [
1746 Service::Aes256Gcm,
1747 Service::Aes256Cbc,
1748 Service::Sha384,
1749 Service::Sha512,
1750 Service::Sha3_384,
1751 Service::Sha3_512,
1752 Service::HmacSha384,
1753 Service::HmacSha512,
1754 Service::CtrDrbgAes256,
1755 Service::HashDrbgSha384,
1756 Service::HmacDrbgSha512,
1757 Service::Kmac256,
1758 Service::KmacXof256,
1759 Service::MlKem1024Encaps,
1760 Service::MlKem1024Decaps,
1761 Service::MlKem1024Keygen,
1762 Service::MlDsa87Sign,
1763 Service::MlDsa87Verify,
1764 Service::MlDsa87Keygen,
1765 Service::LmsSha256M32H10W4Sign,
1766 Service::LmsSha256M32H10W4Verify,
1767 Service::XmssSign,
1768 Service::XmssVerify,
1769 Service::Tls13Kdf,
1770 ];
1771 for svc in allowed {
1772 assert!(
1773 is_allowed(AlgorithmProfile::Cnsa2, svc),
1774 "{svc} should be allowed in CNSA 2.0"
1775 );
1776 }
1777 }
1778
1779 #[test]
1780 fn cnsa2_blocks_classical_and_small_keys() {
1781 let blocked = [
1782 Service::Sha1,
1783 Service::Sha224,
1784 Service::Sha256,
1785 Service::Sha512_224,
1786 Service::Sha512_256,
1787 Service::Sha3_224,
1788 Service::Sha3_256,
1789 Service::Shake128,
1790 Service::Kmac128,
1791 Service::Aes128Ecb,
1792 Service::Aes128Gcm,
1793 Service::Aes192Cbc,
1794 Service::CtrDrbgAes128,
1795 Service::CtrDrbgAes192,
1796 Service::HashDrbgSha256,
1797 Service::HmacDrbgSha256,
1798 Service::HmacSha1,
1799 Service::HmacSha256,
1800 Service::CmacAes128,
1801 Service::CmacAes192,
1802 Service::EcdsaP256Sign,
1803 Service::EcdsaP256Verify,
1804 Service::EcdhP256,
1805 Service::Ed25519Sign,
1806 Service::Ed25519Verify,
1807 Service::RsaPssSign2048,
1808 Service::RsaOaep2048,
1809 Service::Tls12Kdf,
1810 Service::SlhDsaSha2128sSign,
1813 Service::MlDsa44Sign,
1814 Service::MlDsa44Verify,
1815 Service::MlDsa44Keygen,
1816 Service::MlDsa65Sign,
1817 Service::MlDsa65Verify,
1818 Service::MlDsa65Keygen,
1819 ];
1820 for svc in blocked {
1821 assert!(
1822 !is_allowed(AlgorithmProfile::Cnsa2, svc),
1823 "{svc} should be BLOCKED in CNSA 2.0"
1824 );
1825 }
1826 }
1827
1828 #[test]
1829 fn cnsa1_allows_p384_rsa3072_and_pq() {
1830 let allowed = [
1831 Service::Aes256Gcm,
1832 Service::Sha384,
1833 Service::Sha256,
1834 Service::EcdsaP384Sign,
1835 Service::EcdsaP384Verify,
1836 Service::EcdsaP384Keygen,
1837 Service::EcdhP384,
1838 Service::RsaPssSign3072,
1839 Service::RsaOaep3072,
1840 Service::RsaPssSign4096,
1841 Service::Dh3072,
1842 Service::MlKem1024Encaps,
1843 Service::LmsSha256M32H10W4Sign,
1844 Service::Tls13Kdf,
1845 ];
1846 for svc in allowed {
1847 assert!(
1848 is_allowed(AlgorithmProfile::Cnsa1, svc),
1849 "{svc} should be allowed in CNSA 1.0"
1850 );
1851 }
1852 }
1853
1854 #[test]
1855 fn cnsa1_blocks_small_keys_and_ed25519() {
1856 let blocked = [
1857 Service::Sha1,
1858 Service::Sha224,
1859 Service::Aes128Ecb,
1860 Service::Aes192Gcm,
1861 Service::CtrDrbgAes128,
1862 Service::EcdsaP256Sign,
1863 Service::EcdhP256,
1864 Service::Ed25519Sign,
1865 Service::Ed25519Verify,
1866 Service::RsaPssSign2048,
1867 Service::RsaOaep2048,
1868 Service::Tls12Kdf,
1869 ];
1870 for svc in blocked {
1871 assert!(
1872 !is_allowed(AlgorithmProfile::Cnsa1, svc),
1873 "{svc} should be BLOCKED in CNSA 1.0"
1874 );
1875 }
1876 }
1877
1878 #[test]
1879 #[allow(clippy::too_many_lines)]
1884 fn lms_gating_is_exhaustive_across_all_160_variants() {
1885 let all_160 = [
1894 Service::LmsSha256M32H5W1Sign,
1896 Service::LmsSha256M32H5W1Verify,
1897 Service::LmsSha256M32H5W2Sign,
1898 Service::LmsSha256M32H5W2Verify,
1899 Service::LmsSha256M32H5W4Sign,
1900 Service::LmsSha256M32H5W4Verify,
1901 Service::LmsSha256M32H5W8Sign,
1902 Service::LmsSha256M32H5W8Verify,
1903 Service::LmsSha256M32H10W1Sign,
1904 Service::LmsSha256M32H10W1Verify,
1905 Service::LmsSha256M32H10W2Sign,
1906 Service::LmsSha256M32H10W2Verify,
1907 Service::LmsSha256M32H10W4Sign,
1908 Service::LmsSha256M32H10W4Verify,
1909 Service::LmsSha256M32H10W8Sign,
1910 Service::LmsSha256M32H10W8Verify,
1911 Service::LmsSha256M32H15W1Sign,
1912 Service::LmsSha256M32H15W1Verify,
1913 Service::LmsSha256M32H15W2Sign,
1914 Service::LmsSha256M32H15W2Verify,
1915 Service::LmsSha256M32H15W4Sign,
1916 Service::LmsSha256M32H15W4Verify,
1917 Service::LmsSha256M32H15W8Sign,
1918 Service::LmsSha256M32H15W8Verify,
1919 Service::LmsSha256M32H20W1Sign,
1920 Service::LmsSha256M32H20W1Verify,
1921 Service::LmsSha256M32H20W2Sign,
1922 Service::LmsSha256M32H20W2Verify,
1923 Service::LmsSha256M32H20W4Sign,
1924 Service::LmsSha256M32H20W4Verify,
1925 Service::LmsSha256M32H20W8Sign,
1926 Service::LmsSha256M32H20W8Verify,
1927 Service::LmsSha256M32H25W1Sign,
1928 Service::LmsSha256M32H25W1Verify,
1929 Service::LmsSha256M32H25W2Sign,
1930 Service::LmsSha256M32H25W2Verify,
1931 Service::LmsSha256M32H25W4Sign,
1932 Service::LmsSha256M32H25W4Verify,
1933 Service::LmsSha256M32H25W8Sign,
1934 Service::LmsSha256M32H25W8Verify,
1935 Service::LmsSha256M24H5W1Sign,
1937 Service::LmsSha256M24H5W1Verify,
1938 Service::LmsSha256M24H5W2Sign,
1939 Service::LmsSha256M24H5W2Verify,
1940 Service::LmsSha256M24H5W4Sign,
1941 Service::LmsSha256M24H5W4Verify,
1942 Service::LmsSha256M24H5W8Sign,
1943 Service::LmsSha256M24H5W8Verify,
1944 Service::LmsSha256M24H10W1Sign,
1945 Service::LmsSha256M24H10W1Verify,
1946 Service::LmsSha256M24H10W2Sign,
1947 Service::LmsSha256M24H10W2Verify,
1948 Service::LmsSha256M24H10W4Sign,
1949 Service::LmsSha256M24H10W4Verify,
1950 Service::LmsSha256M24H10W8Sign,
1951 Service::LmsSha256M24H10W8Verify,
1952 Service::LmsSha256M24H15W1Sign,
1953 Service::LmsSha256M24H15W1Verify,
1954 Service::LmsSha256M24H15W2Sign,
1955 Service::LmsSha256M24H15W2Verify,
1956 Service::LmsSha256M24H15W4Sign,
1957 Service::LmsSha256M24H15W4Verify,
1958 Service::LmsSha256M24H15W8Sign,
1959 Service::LmsSha256M24H15W8Verify,
1960 Service::LmsSha256M24H20W1Sign,
1961 Service::LmsSha256M24H20W1Verify,
1962 Service::LmsSha256M24H20W2Sign,
1963 Service::LmsSha256M24H20W2Verify,
1964 Service::LmsSha256M24H20W4Sign,
1965 Service::LmsSha256M24H20W4Verify,
1966 Service::LmsSha256M24H20W8Sign,
1967 Service::LmsSha256M24H20W8Verify,
1968 Service::LmsSha256M24H25W1Sign,
1969 Service::LmsSha256M24H25W1Verify,
1970 Service::LmsSha256M24H25W2Sign,
1971 Service::LmsSha256M24H25W2Verify,
1972 Service::LmsSha256M24H25W4Sign,
1973 Service::LmsSha256M24H25W4Verify,
1974 Service::LmsSha256M24H25W8Sign,
1975 Service::LmsSha256M24H25W8Verify,
1976 Service::LmsShakeM32H5W1Sign,
1978 Service::LmsShakeM32H5W1Verify,
1979 Service::LmsShakeM32H5W2Sign,
1980 Service::LmsShakeM32H5W2Verify,
1981 Service::LmsShakeM32H5W4Sign,
1982 Service::LmsShakeM32H5W4Verify,
1983 Service::LmsShakeM32H5W8Sign,
1984 Service::LmsShakeM32H5W8Verify,
1985 Service::LmsShakeM32H10W1Sign,
1986 Service::LmsShakeM32H10W1Verify,
1987 Service::LmsShakeM32H10W2Sign,
1988 Service::LmsShakeM32H10W2Verify,
1989 Service::LmsShakeM32H10W4Sign,
1990 Service::LmsShakeM32H10W4Verify,
1991 Service::LmsShakeM32H10W8Sign,
1992 Service::LmsShakeM32H10W8Verify,
1993 Service::LmsShakeM32H15W1Sign,
1994 Service::LmsShakeM32H15W1Verify,
1995 Service::LmsShakeM32H15W2Sign,
1996 Service::LmsShakeM32H15W2Verify,
1997 Service::LmsShakeM32H15W4Sign,
1998 Service::LmsShakeM32H15W4Verify,
1999 Service::LmsShakeM32H15W8Sign,
2000 Service::LmsShakeM32H15W8Verify,
2001 Service::LmsShakeM32H20W1Sign,
2002 Service::LmsShakeM32H20W1Verify,
2003 Service::LmsShakeM32H20W2Sign,
2004 Service::LmsShakeM32H20W2Verify,
2005 Service::LmsShakeM32H20W4Sign,
2006 Service::LmsShakeM32H20W4Verify,
2007 Service::LmsShakeM32H20W8Sign,
2008 Service::LmsShakeM32H20W8Verify,
2009 Service::LmsShakeM32H25W1Sign,
2010 Service::LmsShakeM32H25W1Verify,
2011 Service::LmsShakeM32H25W2Sign,
2012 Service::LmsShakeM32H25W2Verify,
2013 Service::LmsShakeM32H25W4Sign,
2014 Service::LmsShakeM32H25W4Verify,
2015 Service::LmsShakeM32H25W8Sign,
2016 Service::LmsShakeM32H25W8Verify,
2017 Service::LmsShakeM24H5W1Sign,
2019 Service::LmsShakeM24H5W1Verify,
2020 Service::LmsShakeM24H5W2Sign,
2021 Service::LmsShakeM24H5W2Verify,
2022 Service::LmsShakeM24H5W4Sign,
2023 Service::LmsShakeM24H5W4Verify,
2024 Service::LmsShakeM24H5W8Sign,
2025 Service::LmsShakeM24H5W8Verify,
2026 Service::LmsShakeM24H10W1Sign,
2027 Service::LmsShakeM24H10W1Verify,
2028 Service::LmsShakeM24H10W2Sign,
2029 Service::LmsShakeM24H10W2Verify,
2030 Service::LmsShakeM24H10W4Sign,
2031 Service::LmsShakeM24H10W4Verify,
2032 Service::LmsShakeM24H10W8Sign,
2033 Service::LmsShakeM24H10W8Verify,
2034 Service::LmsShakeM24H15W1Sign,
2035 Service::LmsShakeM24H15W1Verify,
2036 Service::LmsShakeM24H15W2Sign,
2037 Service::LmsShakeM24H15W2Verify,
2038 Service::LmsShakeM24H15W4Sign,
2039 Service::LmsShakeM24H15W4Verify,
2040 Service::LmsShakeM24H15W8Sign,
2041 Service::LmsShakeM24H15W8Verify,
2042 Service::LmsShakeM24H20W1Sign,
2043 Service::LmsShakeM24H20W1Verify,
2044 Service::LmsShakeM24H20W2Sign,
2045 Service::LmsShakeM24H20W2Verify,
2046 Service::LmsShakeM24H20W4Sign,
2047 Service::LmsShakeM24H20W4Verify,
2048 Service::LmsShakeM24H20W8Sign,
2049 Service::LmsShakeM24H20W8Verify,
2050 Service::LmsShakeM24H25W1Sign,
2051 Service::LmsShakeM24H25W1Verify,
2052 Service::LmsShakeM24H25W2Sign,
2053 Service::LmsShakeM24H25W2Verify,
2054 Service::LmsShakeM24H25W4Sign,
2055 Service::LmsShakeM24H25W4Verify,
2056 Service::LmsShakeM24H25W8Sign,
2057 Service::LmsShakeM24H25W8Verify,
2058 ];
2059 assert_eq!(all_160.len(), 160, "LMS enumeration drift");
2060
2061 let cnsa_allowed_set = [
2063 Service::LmsSha256M32H10W4Sign,
2064 Service::LmsSha256M32H10W4Verify,
2065 Service::LmsSha256M32H10W8Sign,
2066 Service::LmsSha256M32H10W8Verify,
2067 Service::LmsSha256M32H15W4Sign,
2068 Service::LmsSha256M32H15W4Verify,
2069 Service::LmsSha256M32H15W8Sign,
2070 Service::LmsSha256M32H15W8Verify,
2071 Service::LmsSha256M32H20W4Sign,
2072 Service::LmsSha256M32H20W4Verify,
2073 Service::LmsSha256M32H20W8Sign,
2074 Service::LmsSha256M32H20W8Verify,
2075 Service::LmsSha256M32H25W4Sign,
2076 Service::LmsSha256M32H25W4Verify,
2077 Service::LmsSha256M32H25W8Sign,
2078 Service::LmsSha256M32H25W8Verify,
2079 ];
2080 assert_eq!(cnsa_allowed_set.len(), 16, "CNSA permitted-set drift");
2081
2082 for svc in all_160 {
2083 assert!(
2085 is_allowed(AlgorithmProfile::Unrestricted, svc),
2086 "{svc} must be allowed in Unrestricted"
2087 );
2088
2089 let expected = cnsa_allowed_set.contains(&svc);
2090
2091 let actual_cnsa2 = is_allowed(AlgorithmProfile::Cnsa2, svc);
2094 assert_eq!(
2095 actual_cnsa2, expected,
2096 "{svc} CNSA 2.0 gating mismatch (expected={expected}, actual={actual_cnsa2})"
2097 );
2098
2099 let actual_cnsa1 = is_allowed(AlgorithmProfile::Cnsa1, svc);
2101 assert_eq!(
2102 actual_cnsa1, expected,
2103 "{svc} CNSA 1.0 gating mismatch (expected={expected}, actual={actual_cnsa1})"
2104 );
2105 }
2106 }
2107
2108 #[test]
2109 fn slh_dsa_gating_is_exhaustive_across_all_36_variants() {
2110 let all_36 = [
2119 Service::SlhDsaSha2256sKeygen,
2121 Service::SlhDsaSha2256sSign,
2122 Service::SlhDsaSha2256sVerify,
2123 Service::SlhDsaSha2128sKeygen,
2124 Service::SlhDsaSha2128sSign,
2125 Service::SlhDsaSha2128sVerify,
2126 Service::SlhDsaSha2128fKeygen,
2127 Service::SlhDsaSha2128fSign,
2128 Service::SlhDsaSha2128fVerify,
2129 Service::SlhDsaSha2192sKeygen,
2130 Service::SlhDsaSha2192sSign,
2131 Service::SlhDsaSha2192sVerify,
2132 Service::SlhDsaSha2192fKeygen,
2133 Service::SlhDsaSha2192fSign,
2134 Service::SlhDsaSha2192fVerify,
2135 Service::SlhDsaSha2256fKeygen,
2136 Service::SlhDsaSha2256fSign,
2137 Service::SlhDsaSha2256fVerify,
2138 Service::SlhDsaShake128sKeygen,
2140 Service::SlhDsaShake128sSign,
2141 Service::SlhDsaShake128sVerify,
2142 Service::SlhDsaShake128fKeygen,
2143 Service::SlhDsaShake128fSign,
2144 Service::SlhDsaShake128fVerify,
2145 Service::SlhDsaShake192sKeygen,
2146 Service::SlhDsaShake192sSign,
2147 Service::SlhDsaShake192sVerify,
2148 Service::SlhDsaShake192fKeygen,
2149 Service::SlhDsaShake192fSign,
2150 Service::SlhDsaShake192fVerify,
2151 Service::SlhDsaShake256sKeygen,
2152 Service::SlhDsaShake256sSign,
2153 Service::SlhDsaShake256sVerify,
2154 Service::SlhDsaShake256fKeygen,
2155 Service::SlhDsaShake256fSign,
2156 Service::SlhDsaShake256fVerify,
2157 ];
2158 assert_eq!(all_36.len(), 36, "SLH-DSA enumeration drift");
2159
2160 let cnsa2_allowed_set = [
2161 Service::SlhDsaSha2256sKeygen,
2162 Service::SlhDsaSha2256sSign,
2163 Service::SlhDsaSha2256sVerify,
2164 ];
2165
2166 for svc in all_36 {
2167 assert!(
2169 is_allowed(AlgorithmProfile::Unrestricted, svc),
2170 "{svc} must be allowed in Unrestricted"
2171 );
2172
2173 assert!(
2175 !is_allowed(AlgorithmProfile::Cnsa1, svc),
2176 "{svc} must be BLOCKED in CNSA 1.0"
2177 );
2178
2179 let expected_cnsa2 = cnsa2_allowed_set.contains(&svc);
2182 let actual_cnsa2 = is_allowed(AlgorithmProfile::Cnsa2, svc);
2183 assert_eq!(
2184 actual_cnsa2, expected_cnsa2,
2185 "{svc} CNSA 2.0 gating mismatch (expected={expected_cnsa2}, actual={actual_cnsa2})"
2186 );
2187 }
2188 }
2189
2190 #[test]
2191 fn require_allowed_returns_restricted_error_under_cnsa2() {
2192 reset_for_test();
2193 initialize_with_profile(&[], AlgorithmProfile::Cnsa2).unwrap();
2194 match require_allowed(Service::Aes128Ecb) {
2195 Err(Error::AlgorithmRestricted {
2196 service: Service::Aes128Ecb,
2197 }) => {}
2198 other => panic!("expected AlgorithmRestricted(Aes128Ecb), got {other:?}"),
2199 }
2200 }
2201
2202 #[test]
2203 fn require_allowed_passes_permitted_services() {
2204 reset_for_test();
2205 initialize_with_profile(&[], AlgorithmProfile::Cnsa2).unwrap();
2206 require_allowed(Service::Aes256Gcm).unwrap();
2207 require_allowed(Service::Sha384).unwrap();
2208 require_allowed(Service::MlKem1024Encaps).unwrap();
2209 }
2210
2211 #[test]
2212 fn require_allowed_passes_everything_in_unrestricted() {
2213 reset_for_test();
2214 initialize().unwrap();
2215 require_allowed(Service::Sha1).unwrap();
2217 require_allowed(Service::Aes128Ecb).unwrap();
2218 require_allowed(Service::Ed25519Sign).unwrap();
2219 require_allowed(Service::MlKem1024Encaps).unwrap();
2220 }
2221
2222 #[test]
2223 fn algorithm_profile_display() {
2224 assert_eq!(AlgorithmProfile::Unrestricted.to_string(), "Unrestricted");
2225 assert_eq!(AlgorithmProfile::Cnsa2.to_string(), "CNSA 2.0");
2226 assert_eq!(AlgorithmProfile::Cnsa1.to_string(), "CNSA 1.0");
2227 }
2228
2229 #[test]
2230 fn algorithm_restricted_error_display() {
2231 reset_for_test();
2232 initialize_with_profile(&[], AlgorithmProfile::Cnsa2).unwrap();
2233 let err = Error::AlgorithmRestricted {
2234 service: Service::Aes128Ecb,
2235 };
2236 let msg = err.to_string();
2237 assert!(msg.contains("AES-128-ECB"), "got: {msg}");
2238 assert!(msg.contains("CNSA 2.0"), "got: {msg}");
2239 }
2240
2241 #[test]
2242 fn not_implemented_error_display() {
2243 let err = Error::NotImplemented;
2244 assert_eq!(err.to_string(), "algorithm not yet implemented");
2245 }
2246
2247 #[test]
2248 fn service_display_is_stable() {
2249 assert_eq!(Service::Sha256.to_string(), "SHA-256");
2251 assert_eq!(Service::Aes256Gcm.to_string(), "AES-256-GCM");
2252 assert_eq!(Service::MlKem1024Encaps.to_string(), "ML-KEM-1024 encaps");
2253 assert_eq!(Service::Ed25519Sign.to_string(), "Ed25519 sign");
2254 }
2255}