Skip to content

Commit 2cd3cee

Browse files
core: Add helpers for checking mechanisms at compile time
To be able to compare mechanism variants in const contexts, we use add a const_eq function. And to be able to indicate which mechanism is potentially missing, we add a const panic method that includes the mechanism variant in the panic message. To reduce the boilerplate code, we use a macro to generate the enum.
1 parent 5cba648 commit 2cd3cee

File tree

1 file changed

+108
-122
lines changed

1 file changed

+108
-122
lines changed

core/src/types.rs

Lines changed: 108 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -452,163 +452,149 @@ impl Client {
452452
];
453453
}
454454

455-
#[derive(Copy, Clone, Eq, PartialEq, Debug, Serialize, Deserialize)]
456-
#[non_exhaustive]
457-
pub enum Mechanism {
458-
#[cfg(feature = "aes256-cbc")]
459-
Aes256Cbc,
460-
#[cfg(feature = "chacha8-poly1305")]
461-
Chacha8Poly1305,
462-
#[cfg(feature = "ed255")]
463-
Ed255,
464-
#[cfg(feature = "hmac-blake2s")]
465-
HmacBlake2s,
466-
#[cfg(feature = "hmac-sha1")]
467-
HmacSha1,
468-
#[cfg(feature = "hmac-sha256")]
469-
HmacSha256,
470-
#[cfg(feature = "hmac-sha512")]
471-
HmacSha512,
472-
// P256XSha256,
473-
#[cfg(feature = "p256")]
474-
P256,
475-
#[cfg(feature = "p256")]
476-
P256Prehashed,
477-
#[cfg(feature = "p384")]
478-
P384,
479-
#[cfg(feature = "p384")]
480-
P384Prehashed,
481-
#[cfg(feature = "p521")]
482-
P521,
483-
#[cfg(feature = "p521")]
484-
P521Prehashed,
485-
#[cfg(feature = "brainpoolp256r1")]
486-
BrainpoolP256R1,
487-
#[cfg(feature = "brainpoolp256r1")]
488-
BrainpoolP256R1Prehashed,
489-
#[cfg(feature = "brainpoolp384r1")]
490-
BrainpoolP384R1,
491-
#[cfg(feature = "brainpoolp384r1")]
492-
BrainpoolP384R1Prehashed,
493-
#[cfg(feature = "brainpoolp512r1")]
494-
BrainpoolP512R1,
495-
#[cfg(feature = "brainpoolp512r1")]
496-
BrainpoolP512R1Prehashed,
497-
#[cfg(feature = "secp256k1")]
498-
Secp256k1,
499-
#[cfg(feature = "secp256k1")]
500-
Secp256k1Prehashed,
501-
// clients can also do hashing by themselves
502-
#[cfg(feature = "sha256")]
503-
Sha256,
504-
#[cfg(feature = "tdes")]
505-
Tdes,
506-
#[cfg(feature = "totp")]
507-
Totp,
508-
#[cfg(feature = "trng")]
509-
Trng,
510-
#[cfg(feature = "x255")]
511-
X255,
512-
/// Used to serialize the output of a diffie-hellman
513-
#[cfg(feature = "shared-secret")]
514-
SharedSecret,
515-
516-
/// Exposes the Raw RSA encryption/decryption primitive. Be aware this is dangerous.
517-
/// Not having any padding can allow an attacker to obtain plaintexts and forge signatures.
518-
/// It should only be used if absolutely necessary.
519-
#[cfg(feature = "rsa2048")]
520-
Rsa2048Raw,
521-
/// Exposes the Raw RSA encryption/decryption primitive. Be aware this is dangerous.
522-
/// Not having any padding can allow an attacker to obtain plaintexts and forge signatures.
523-
/// It should only be used if absolutely necessary.
524-
#[cfg(feature = "rsa3072")]
525-
Rsa3072Raw,
526-
/// Exposes the Raw RSA encryption/decryption primitive. Be aware this is dangerous.
527-
/// Not having any padding can allow an attacker to obtain plaintexts and forge signatures.
528-
/// It should only be used if absolutely necessary.
529-
#[cfg(feature = "rsa4096")]
530-
Rsa4096Raw,
531-
532-
#[cfg(feature = "rsa2048")]
533-
Rsa2048Pkcs1v15,
534-
#[cfg(feature = "rsa3072")]
535-
Rsa3072Pkcs1v15,
536-
#[cfg(feature = "rsa4096")]
537-
Rsa4096Pkcs1v15,
455+
macro_rules! generate_mechanism {
456+
(
457+
$(#[$outer:meta])*
458+
$vis:vis enum $name:ident {
459+
$(
460+
#[cfg($($cfg_cond:tt)*)]
461+
$(#[$inner:meta])*
462+
$variant:ident,
463+
)*
464+
}
465+
) => {
466+
$(#[$outer])*
467+
$vis enum $name {
468+
$(
469+
#[cfg($($cfg_cond)*)]
470+
$(#[$inner])*
471+
$variant,
472+
)*
473+
}
474+
475+
impl $name {
476+
/// All enabled mechanisms.
477+
///
478+
/// The contents of this constant depends on the enabled features.
479+
pub const ENABLED: &[Self] = &[
480+
$(
481+
#[cfg($($cfg_cond)*)]
482+
Self::$variant,
483+
)*
484+
];
485+
486+
/// Check equality in a const-friendly way.
487+
pub const fn const_eq(&self, other: Self) -> bool {
488+
let _ = other;
489+
match *self {
490+
$(
491+
#[cfg($($cfg_cond)*)]
492+
Self::$variant => matches!(other, Self::$variant),
493+
)*
494+
}
495+
}
496+
497+
/// Panic with a message contain this mechanism.
498+
///
499+
/// This is intended for compile time checks that don’t have a direct way to indicate
500+
/// a missing mechanism in a panic message.
501+
pub const fn panic(&self) -> ! {
502+
match *self {
503+
$(
504+
#[cfg($($cfg_cond)*)]
505+
Self::$variant => panic!(concat!("panic for mechanism: ", stringify!($variant))),
506+
)*
507+
}
508+
}
509+
}
510+
}
538511
}
539512

540-
impl Mechanism {
541-
/// All enabled mechanisms.
542-
///
543-
/// The contents of this constant depends on the enabled features.
544-
pub const ENABLED: &[Self] = &[
513+
generate_mechanism! {
514+
#[derive(Copy, Clone, Eq, PartialEq, Debug, Serialize, Deserialize)]
515+
#[non_exhaustive]
516+
pub enum Mechanism {
545517
#[cfg(feature = "aes256-cbc")]
546-
Self::Aes256Cbc,
518+
Aes256Cbc,
547519
#[cfg(feature = "chacha8-poly1305")]
548-
Self::Chacha8Poly1305,
520+
Chacha8Poly1305,
549521
#[cfg(feature = "ed255")]
550-
Self::Ed255,
522+
Ed255,
551523
#[cfg(feature = "hmac-blake2s")]
552-
Self::HmacBlake2s,
524+
HmacBlake2s,
553525
#[cfg(feature = "hmac-sha1")]
554-
Self::HmacSha1,
526+
HmacSha1,
555527
#[cfg(feature = "hmac-sha256")]
556-
Self::HmacSha256,
528+
HmacSha256,
557529
#[cfg(feature = "hmac-sha512")]
558-
Self::HmacSha512,
530+
HmacSha512,
531+
// P256XSha256,
559532
#[cfg(feature = "p256")]
560-
Self::P256,
533+
P256,
561534
#[cfg(feature = "p256")]
562-
Self::P256Prehashed,
535+
P256Prehashed,
563536
#[cfg(feature = "p384")]
564-
Self::P384,
537+
P384,
565538
#[cfg(feature = "p384")]
566-
Self::P384Prehashed,
539+
P384Prehashed,
567540
#[cfg(feature = "p521")]
568-
Self::P521,
541+
P521,
569542
#[cfg(feature = "p521")]
570-
Self::P521Prehashed,
543+
P521Prehashed,
571544
#[cfg(feature = "brainpoolp256r1")]
572-
Self::BrainpoolP256R1,
545+
BrainpoolP256R1,
573546
#[cfg(feature = "brainpoolp256r1")]
574-
Self::BrainpoolP256R1Prehashed,
547+
BrainpoolP256R1Prehashed,
575548
#[cfg(feature = "brainpoolp384r1")]
576-
Self::BrainpoolP384R1,
549+
BrainpoolP384R1,
577550
#[cfg(feature = "brainpoolp384r1")]
578-
Self::BrainpoolP384R1Prehashed,
551+
BrainpoolP384R1Prehashed,
579552
#[cfg(feature = "brainpoolp512r1")]
580-
Self::BrainpoolP512R1,
553+
BrainpoolP512R1,
581554
#[cfg(feature = "brainpoolp512r1")]
582-
Self::BrainpoolP512R1Prehashed,
555+
BrainpoolP512R1Prehashed,
583556
#[cfg(feature = "secp256k1")]
584-
Self::Secp256k1,
557+
Secp256k1,
585558
#[cfg(feature = "secp256k1")]
586-
Self::Secp256k1Prehashed,
559+
Secp256k1Prehashed,
560+
// clients can also do hashing by themselves
587561
#[cfg(feature = "sha256")]
588-
Self::Sha256,
562+
Sha256,
589563
#[cfg(feature = "tdes")]
590-
Self::Tdes,
564+
Tdes,
591565
#[cfg(feature = "totp")]
592-
Self::Totp,
566+
Totp,
593567
#[cfg(feature = "trng")]
594-
Self::Trng,
568+
Trng,
595569
#[cfg(feature = "x255")]
596-
Self::X255,
570+
X255,
597571
#[cfg(feature = "shared-secret")]
598-
Self::SharedSecret,
572+
/// Used to serialize the output of a diffie-hellman
573+
SharedSecret,
574+
599575
#[cfg(feature = "rsa2048")]
600-
Self::Rsa2048Raw,
576+
/// Exposes the Raw RSA encryption/decryption primitive. Be aware this is dangerous.
577+
/// Not having any padding can allow an attacker to obtain plaintexts and forge signatures.
578+
/// It should only be used if absolutely necessary.
579+
Rsa2048Raw,
601580
#[cfg(feature = "rsa3072")]
602-
Self::Rsa3072Raw,
581+
/// Exposes the Raw RSA encryption/decryption primitive. Be aware this is dangerous.
582+
/// Not having any padding can allow an attacker to obtain plaintexts and forge signatures.
583+
/// It should only be used if absolutely necessary.
584+
Rsa3072Raw,
603585
#[cfg(feature = "rsa4096")]
604-
Self::Rsa4096Raw,
586+
/// Exposes the Raw RSA encryption/decryption primitive. Be aware this is dangerous.
587+
/// Not having any padding can allow an attacker to obtain plaintexts and forge signatures.
588+
/// It should only be used if absolutely necessary.
589+
Rsa4096Raw,
590+
605591
#[cfg(feature = "rsa2048")]
606-
Self::Rsa2048Pkcs1v15,
592+
Rsa2048Pkcs1v15,
607593
#[cfg(feature = "rsa3072")]
608-
Self::Rsa3072Pkcs1v15,
594+
Rsa3072Pkcs1v15,
609595
#[cfg(feature = "rsa4096")]
610-
Self::Rsa4096Pkcs1v15,
611-
];
596+
Rsa4096Pkcs1v15,
597+
}
612598
}
613599

614600
#[derive(Copy, Clone, Eq, PartialEq, Debug)]

0 commit comments

Comments
 (0)