diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2023-05-12 18:53:49 +0200 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2023-05-22 12:00:11 +0200 |
commit | d1fb7c0582058ccbe262b6650ca43f627ed8d628 (patch) | |
tree | b9901e5542a8dc85adf389100ab31c07b5db5d8b | |
parent | 995a7cff7fa0cd3273d8dad8080f6b50de79eaa9 (diff) |
openpgp: Formalize reporting of supported algorithms.
-rw-r--r-- | openpgp/src/crypto/backend/botan.rs | 29 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/botan/asymmetric.rs | 25 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/cng.rs | 25 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/cng/asymmetric.rs | 21 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/interface.rs | 17 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/nettle.rs | 25 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/nettle/asymmetric.rs | 21 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/openssl.rs | 33 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/openssl/asymmetric.rs | 28 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/rust.rs | 31 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/rust/asymmetric.rs | 27 | ||||
-rw-r--r-- | openpgp/src/types/mod.rs | 6 |
12 files changed, 143 insertions, 145 deletions
diff --git a/openpgp/src/crypto/backend/botan.rs b/openpgp/src/crypto/backend/botan.rs index cf5e295e..3f1ab906 100644 --- a/openpgp/src/crypto/backend/botan.rs +++ b/openpgp/src/crypto/backend/botan.rs @@ -22,35 +22,6 @@ impl super::interface::Backend for Backend { } } -impl PublicKeyAlgorithm { - pub(crate) fn is_supported_by_backend(&self) -> bool { - use PublicKeyAlgorithm::*; - #[allow(deprecated)] - match &self { - RSAEncryptSign | RSAEncrypt | RSASign | DSA | ECDH | ECDSA | EdDSA | - ElGamalEncrypt | ElGamalEncryptSign - => true, - Private(_) | Unknown(_) - => false, - } - } -} - -impl Curve { - pub(crate) fn is_supported_by_backend(&self) -> bool { - use self::Curve::*; - match &self { - NistP256 | NistP384 | NistP521 | Ed25519 | Cv25519 | - BrainpoolP256 | BrainpoolP512 - => true, - Unknown(_) if self.is_brainpoolp384() // XXX - => true, - Unknown(_) - => false, - } - } -} - impl AEADAlgorithm { /// Returns the best AEAD mode supported by the backend. /// diff --git a/openpgp/src/crypto/backend/botan/asymmetric.rs b/openpgp/src/crypto/backend/botan/asymmetric.rs index d9f989ad..c817aafd 100644 --- a/openpgp/src/crypto/backend/botan/asymmetric.rs +++ b/openpgp/src/crypto/backend/botan/asymmetric.rs @@ -34,6 +34,31 @@ use crate::{ }; impl Asymmetric for super::Backend { + fn supports_algo(algo: PublicKeyAlgorithm) -> bool { + use PublicKeyAlgorithm::*; + #[allow(deprecated)] + match algo { + RSAEncryptSign | RSAEncrypt | RSASign | DSA | ECDH | ECDSA | EdDSA | + ElGamalEncrypt | ElGamalEncryptSign + => true, + Private(_) | Unknown(_) + => false, + } + } + + fn supports_curve(curve: &Curve) -> bool { + use Curve::*; + match curve { + NistP256 | NistP384 | NistP521 | Ed25519 | Cv25519 | + BrainpoolP256 | BrainpoolP512 + => true, + Unknown(_) if curve.is_brainpoolp384() // XXX + => true, + Unknown(_) + => false, + } + } + fn x25519_generate_key() -> Result<(Protected, [u8; 32])> { let mut rng = RandomNumberGenerator::new_userspace()?; let secret = Privkey::create("Curve25519", "", &mut rng)?; diff --git a/openpgp/src/crypto/backend/cng.rs b/openpgp/src/crypto/backend/cng.rs index d40b904b..9f43958f 100644 --- a/openpgp/src/crypto/backend/cng.rs +++ b/openpgp/src/crypto/backend/cng.rs @@ -25,31 +25,6 @@ impl super::interface::Backend for Backend { } } -impl PublicKeyAlgorithm { - pub(crate) fn is_supported_by_backend(&self) -> bool { - use PublicKeyAlgorithm::*; - #[allow(deprecated)] - match &self { - RSAEncryptSign | RSAEncrypt | RSASign | DSA | ECDH | ECDSA | EdDSA - => true, - ElGamalEncrypt | ElGamalEncryptSign | Private(_) | Unknown(_) - => false, - } - } -} - -impl Curve { - pub(crate) fn is_supported_by_backend(&self) -> bool { - use self::Curve::*; - match &self { - NistP256 | NistP384 | NistP521 | Ed25519 | Cv25519 - => true, - BrainpoolP256 | BrainpoolP512 | Unknown(_) - => false, - } - } -} - impl AEADAlgorithm { /// Returns the best AEAD mode supported by the backend. /// diff --git a/openpgp/src/crypto/backend/cng/asymmetric.rs b/openpgp/src/crypto/backend/cng/asymmetric.rs index 91c7700c..38eb1905 100644 --- a/openpgp/src/crypto/backend/cng/asymmetric.rs +++ b/openpgp/src/crypto/backend/cng/asymmetric.rs @@ -23,6 +23,27 @@ use win_crypto_ng as cng; const CURVE25519_SIZE: usize = 32; impl Asymmetric for super::Backend { + fn supports_algo(algo: PublicKeyAlgorithm) -> bool { + use PublicKeyAlgorithm::*; + #[allow(deprecated)] + match algo { + RSAEncryptSign | RSAEncrypt | RSASign | DSA | ECDH | ECDSA | EdDSA + => true, + ElGamalEncrypt | ElGamalEncryptSign | Private(_) | Unknown(_) + => false, + } + } + + fn supports_curve(curve: &Curve) -> bool { + use Curve::*; + match curve { + NistP256 | NistP384 | NistP521 | Ed25519 | Cv25519 + => true, + BrainpoolP256 | BrainpoolP512 | Unknown(_) + => false, + } + } + fn x25519_generate_key() -> Result<(Protected, [u8; 32])> { use cng::asymmetric::{Ecdh, AsymmetricKey, Export}; use cng::asymmetric::ecc::Curve25519; diff --git a/openpgp/src/crypto/backend/interface.rs b/openpgp/src/crypto/backend/interface.rs index 21034862..ad539b16 100644 --- a/openpgp/src/crypto/backend/interface.rs +++ b/openpgp/src/crypto/backend/interface.rs @@ -3,6 +3,7 @@ use crate::{ Result, crypto::mem::Protected, + types::{Curve, PublicKeyAlgorithm}, }; /// Abstracts over the cryptographic backends. @@ -25,6 +26,22 @@ pub trait Backend: Asymmetric { /// Public-key cryptography interface. pub trait Asymmetric { + /// Returns whether the given public key cryptography algorithm is + /// supported by this backend. + /// + /// Note: when implementing this function, match exhaustively on + /// `algo`, do not use a catch-all. This way, when new algorithms + /// are introduced, we will see where we may need to add support. + fn supports_algo(algo: PublicKeyAlgorithm) -> bool; + + /// Returns whether the given elliptic curve is supported by this + /// backend. + /// + /// Note: when implementing this function, match exhaustively on + /// `curve`, do not use a catch-all. This way, when new algorithms + /// are introduced, we will see where we may need to add support. + fn supports_curve(curve: &Curve) -> bool; + /// Generates an X25519 key pair. /// /// Returns a tuple containing the secret and public key. diff --git a/openpgp/src/crypto/backend/nettle.rs b/openpgp/src/crypto/backend/nettle.rs index cf144f26..a8624513 100644 --- a/openpgp/src/crypto/backend/nettle.rs +++ b/openpgp/src/crypto/backend/nettle.rs @@ -29,31 +29,6 @@ impl super::interface::Backend for Backend { } } -impl PublicKeyAlgorithm { - pub(crate) fn is_supported_by_backend(&self) -> bool { - use PublicKeyAlgorithm::*; - #[allow(deprecated)] - match &self { - RSAEncryptSign | RSAEncrypt | RSASign | DSA | ECDH | ECDSA | EdDSA - => true, - ElGamalEncrypt | ElGamalEncryptSign | Private(_) | Unknown(_) - => false, - } - } -} - -impl Curve { - pub(crate) fn is_supported_by_backend(&self) -> bool { - use self::Curve::*; - match &self { - NistP256 | NistP384 | NistP521 | Ed25519 | Cv25519 - => true, - BrainpoolP256 | BrainpoolP512 | Unknown(_) - => false, - } - } -} - impl AEADAlgorithm { /// Returns the best AEAD mode supported by the backend. /// diff --git a/openpgp/src/crypto/backend/nettle/asymmetric.rs b/openpgp/src/crypto/backend/nettle/asymmetric.rs index 06dcf2aa..2e631edd 100644 --- a/openpgp/src/crypto/backend/nettle/asymmetric.rs +++ b/openpgp/src/crypto/backend/nettle/asymmetric.rs @@ -16,6 +16,27 @@ use crate::crypto::SessionKey; use crate::types::{Curve, HashAlgorithm}; impl Asymmetric for super::Backend { + fn supports_algo(algo: PublicKeyAlgorithm) -> bool { + use PublicKeyAlgorithm::*; + #[allow(deprecated)] + match algo { + RSAEncryptSign | RSAEncrypt | RSASign | DSA | ECDH | ECDSA | EdDSA + => true, + ElGamalEncrypt | ElGamalEncryptSign | Private(_) | Unknown(_) + => false, + } + } + + fn supports_curve(curve: &Curve) -> bool { + use Curve::*; + match curve { + NistP256 | NistP384 | NistP521 | Ed25519 | Cv25519 + => true, + BrainpoolP256 | BrainpoolP512 | Unknown(_) + => false, + } + } + fn x25519_generate_key() -> Result<(Protected, [u8; 32])> { debug_assert_eq!(curve25519::CURVE25519_SIZE, 32); let mut rng = Yarrow::default(); diff --git a/openpgp/src/crypto/backend/openssl.rs b/openpgp/src/crypto/backend/openssl.rs index 70d20de4..96679e2d 100644 --- a/openpgp/src/crypto/backend/openssl.rs +++ b/openpgp/src/crypto/backend/openssl.rs @@ -1,5 +1,4 @@ //! Implementation of Sequoia crypto API using the OpenSSL cryptographic library. -use std::convert::TryFrom; use crate::types::*; @@ -22,38 +21,6 @@ impl super::interface::Backend for Backend { } } -impl PublicKeyAlgorithm { - pub(crate) fn is_supported_by_backend(&self) -> bool { - use PublicKeyAlgorithm::*; - #[allow(deprecated)] - match self { - RSAEncryptSign | RSAEncrypt | RSASign => true, - DSA => true, - ECDH | ECDSA | EdDSA => true, - ElGamalEncrypt | ElGamalEncryptSign | - Private(_) | Unknown(_) - => false, - } - } -} - -impl Curve { - pub(crate) fn is_supported_by_backend(&self) -> bool { - if matches!(self, Curve::Ed25519 | Curve::Cv25519) { - // 25519-based algorithms are special-cased and supported - true - } else { - // the rest of EC algorithms are supported via the same - // codepath - if let Ok(nid) = openssl::nid::Nid::try_from(self) { - openssl::ec::EcGroup::from_curve_name(nid).is_ok() - } else { - false - } - } - } -} - impl AEADAlgorithm { /// Returns the best AEAD mode supported by the backend. /// diff --git a/openpgp/src/crypto/backend/openssl/asymmetric.rs b/openpgp/src/crypto/backend/openssl/asymmetric.rs index 396ab0f1..61a0b735 100644 --- a/openpgp/src/crypto/backend/openssl/asymmetric.rs +++ b/openpgp/src/crypto/backend/openssl/asymmetric.rs @@ -24,6 +24,34 @@ use openssl::sign::Signer as OpenSslSigner; use openssl::sign::Verifier; impl Asymmetric for super::Backend { + fn supports_algo(algo: PublicKeyAlgorithm) -> bool { + use PublicKeyAlgorithm::*; + #[allow(deprecated)] + match algo { + RSAEncryptSign | RSAEncrypt | RSASign => true, + DSA => true, + ECDH | ECDSA | EdDSA => true, + ElGamalEncrypt | ElGamalEncryptSign | + Private(_) | Unknown(_) + => false, + } + } + + fn supports_curve(curve: &Curve) -> bool { + if matches!(curve, Curve::Ed25519 | Curve::Cv25519) { + // 25519-based algorithms are special-cased and supported + true + } else { + // the rest of EC algorithms are supported via the same + // codepath + if let Ok(nid) = openssl::nid::Nid::try_from(curve) { + openssl::ec::EcGroup::from_curve_name(nid).is_ok() + } else { + false + } + } + } + fn x25519_generate_key() -> Result<(Protected, [u8; 32])> { let pair = openssl::pkey::PKey::generate_x25519()?; Ok((pair.raw_private_key()?.into(), diff --git a/openpgp/src/crypto/backend/rust.rs b/openpgp/src/crypto/backend/rust.rs index 3a4d098a..41e95492 100644 --- a/openpgp/src/crypto/backend/rust.rs +++ b/openpgp/src/crypto/backend/rust.rs @@ -60,37 +60,6 @@ impl<T, N: ArrayLength<T>> GenericArrayExt<T, N> for GenericArray<T, N> { const LEN: usize = N::USIZE; } -impl PublicKeyAlgorithm { - pub(crate) fn is_supported_by_backend(&self) -> bool { - use PublicKeyAlgorithm::*; - #[allow(deprecated)] - match &self { - RSAEncryptSign | RSAEncrypt | RSASign | ECDH | EdDSA | ECDSA - => true, - DSA - => false, - ElGamalEncrypt | ElGamalEncryptSign | Private(_) | Unknown(_) - => false, - } - } -} - -impl Curve { - pub(crate) fn is_supported_by_backend(&self) -> bool { - use self::Curve::*; - match &self { - NistP256 - => true, - NistP384 | NistP521 - => false, - Ed25519 | Cv25519 - => true, - BrainpoolP256 | BrainpoolP512 | Unknown(_) - => false, - } - } -} - impl AEADAlgorithm { /// Returns the best AEAD mode supported by the backend. /// diff --git a/openpgp/src/crypto/backend/rust/asymmetric.rs b/openpgp/src/crypto/backend/rust/asymmetric.rs index d6729e3d..44163e2d 100644 --- a/openpgp/src/crypto/backend/rust/asymmetric.rs +++ b/openpgp/src/crypto/backend/rust/asymmetric.rs @@ -28,6 +28,33 @@ use super::GenericArrayExt; const CURVE25519_SIZE: usize = 32; impl Asymmetric for super::Backend { + fn supports_algo(algo: PublicKeyAlgorithm) -> bool { + use PublicKeyAlgorithm::*; + #[allow(deprecated)] + match algo { + RSAEncryptSign | RSAEncrypt | RSASign | ECDH | EdDSA | ECDSA + => true, + DSA + => false, + ElGamalEncrypt | ElGamalEncryptSign | Private(_) | Unknown(_) + => false, + } + } + + fn supports_curve(curve: &Curve) -> bool { + use self::Curve::*; + match curve { + NistP256 + => true, + NistP384 | NistP521 + => false, + Ed25519 | Cv25519 + => true, + BrainpoolP256 | BrainpoolP512 | Unknown(_) + => false, + } + } + fn x25519_generate_key() -> Result<(Protected, [u8; 32])> { use x25519_dalek::{StaticSecret, PublicKey}; diff --git a/openpgp/src/types/mod.rs b/openpgp/src/types/mod.rs index 64fd174e..88fe1505 100644 --- a/openpgp/src/types/mod.rs +++ b/openpgp/src/types/mod.rs @@ -207,7 +207,8 @@ impl PublicKeyAlgorithm { /// assert!(!PublicKeyAlgorithm::Private(101).is_supported()); /// ``` pub fn is_supported(&self) -> bool { - self.is_supported_by_backend() + use crate::crypto::backend::{Backend, interface::Asymmetric}; + Backend::supports_algo(*self) } /// Returns an iterator over all valid variants. @@ -605,7 +606,8 @@ impl Curve { /// assert!(!Curve::Unknown(Box::new([0x2B, 0x11])).is_supported()); /// ``` pub fn is_supported(&self) -> bool { - self.is_supported_by_backend() + use crate::crypto::backend::{Backend, interface::Asymmetric}; + Backend::supports_curve(self) } } |