summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2023-01-18 15:47:04 +0100
committerJustus Winter <justus@sequoia-pgp.org>2023-10-10 11:16:07 +0200
commita4c2b9f50a9f6e6539154eb3bcef8a0a062b331f (patch)
treeb6d1724949eebd467d82d8467e7d7eaa4ff67142
parent3c76d468060a02b0aa129308bc413b91d166167b (diff)
openpgp: Add a null crypto backend for fuzzing.
- Fixes #962.
-rw-r--r--.gitlab-ci.yml12
-rw-r--r--openpgp/Cargo.toml1
-rw-r--r--openpgp/build.rs8
-rw-r--r--openpgp/src/crypto/backend.rs12
-rw-r--r--openpgp/src/crypto/backend/fuzzing.rs49
-rw-r--r--openpgp/src/crypto/backend/fuzzing/aead.rs41
-rw-r--r--openpgp/src/crypto/backend/fuzzing/asymmetric.rs169
-rw-r--r--openpgp/src/crypto/backend/fuzzing/ecdh.rs33
-rw-r--r--openpgp/src/crypto/backend/fuzzing/hash.rs65
-rw-r--r--openpgp/src/crypto/backend/fuzzing/symmetric.rs75
-rw-r--r--openpgp/src/crypto/ecdh.rs4
-rw-r--r--openpgp/src/crypto/hash.rs2
12 files changed, 469 insertions, 2 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index d477180b..2a05b371 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -104,6 +104,18 @@ trixie-crypto-botan:
CARGO_TARGET_DIR: /target
CARGO_HOME: /cargo
+trixie-crypto-fuzzing:
+ tags:
+ - linux
+ stage: build
+ interruptible: true
+ image: 192.168.122.1:5000/sequoia-pgp/build-docker-image/trixie-prebuild:latest
+ script:
+ - cargo check --manifest-path openpgp/Cargo.toml --no-default-features --features crypto-fuzzing,compression,allow-experimental-crypto,allow-variable-time-crypto
+ variables:
+ CARGO_TARGET_DIR: /target
+ CARGO_HOME: /cargo
+
all_commits:
# Test each commit up to main, to facilitate bisecting.
stage: test
diff --git a/openpgp/Cargo.toml b/openpgp/Cargo.toml
index 08719619..bdb42247 100644
--- a/openpgp/Cargo.toml
+++ b/openpgp/Cargo.toml
@@ -126,6 +126,7 @@ crypto-cng = [
crypto-openssl = ["openssl", "openssl-sys"]
crypto-botan = ["botan/botan3"]
crypto-botan2 = ["botan"]
+crypto-fuzzing = []
__implicit-crypto-backend-for-tests = []
# Experimental and variable-time cryptographic backends opt-ins
diff --git a/openpgp/build.rs b/openpgp/build.rs
index 57969fd3..c8302fdf 100644
--- a/openpgp/build.rs
+++ b/openpgp/build.rs
@@ -68,6 +68,7 @@ fn crypto_backends_sanity_check() {
any(feature = "crypto-openssl",
feature = "crypto-botan",
feature = "crypto-botan2",
+ feature = "crypto-fuzzing",
feature = "crypto-rust"))))),
Backend {
name: "Nettle",
@@ -80,6 +81,7 @@ fn crypto_backends_sanity_check() {
feature = "crypto-openssl",
feature = "crypto-botan",
feature = "crypto-botan2",
+ feature = "crypto-fuzzing",
feature = "crypto-rust"))))),
Backend {
name: "Windows CNG",
@@ -110,6 +112,12 @@ fn crypto_backends_sanity_check() {
production_ready: true,
constant_time: true,
}),
+ (cfg!(feature = "crypto-fuzzing"),
+ Backend {
+ name: "Fuzzing",
+ production_ready: false,
+ constant_time: false,
+ }),
].into_iter().filter_map(|(selected, backend)| {
if selected { Some(backend) } else { None }
}).collect::<Vec<_>>();
diff --git a/openpgp/src/crypto/backend.rs b/openpgp/src/crypto/backend.rs
index f69d0a10..d6fb9487 100644
--- a/openpgp/src/crypto/backend.rs
+++ b/openpgp/src/crypto/backend.rs
@@ -17,6 +17,7 @@ pub(crate) mod sha1cd;
any(feature = "crypto-openssl",
feature = "crypto-botan",
feature = "crypto-botan2",
+ feature = "crypto-fuzzing",
feature = "crypto-rust")))))]
mod nettle;
#[cfg(all(feature = "crypto-nettle",
@@ -24,6 +25,7 @@ mod nettle;
any(feature = "crypto-openssl",
feature = "crypto-botan",
feature = "crypto-botan2",
+ feature = "crypto-fuzzing",
feature = "crypto-rust")))))]
pub use self::nettle::*;
#[cfg(all(feature = "crypto-nettle",
@@ -48,6 +50,7 @@ pub use self::nettle::Backend;
feature = "crypto-openssl",
feature = "crypto-botan",
feature = "crypto-botan2",
+ feature = "crypto-fuzzing",
feature = "crypto-rust")))))]
mod cng;
#[cfg(all(feature = "crypto-cng",
@@ -56,6 +59,7 @@ mod cng;
feature = "crypto-openssl",
feature = "crypto-botan",
feature = "crypto-botan2",
+ feature = "crypto-fuzzing",
feature = "crypto-rust")))))]
pub use self::cng::*;
#[cfg(all(feature = "crypto-cng",
@@ -64,6 +68,7 @@ pub use self::cng::*;
feature = "crypto-openssl",
feature = "crypto-botan",
feature = "crypto-botan2",
+ feature = "crypto-fuzzing",
feature = "crypto-rust")))))]
pub use self::cng::Backend;
@@ -87,3 +92,10 @@ mod botan;
pub use self::botan::*;
#[cfg(feature = "crypto-botan")]
pub use self::botan::Backend;
+
+#[cfg(feature = "crypto-fuzzing")]
+mod fuzzing;
+#[cfg(feature = "crypto-fuzzing")]
+pub use self::fuzzing::*;
+#[cfg(feature = "crypto-fuzzing")]
+pub use self::fuzzing::Backend;
diff --git a/openpgp/src/crypto/backend/fuzzing.rs b/openpgp/src/crypto/backend/fuzzing.rs
new file mode 100644
index 00000000..e36ee34e
--- /dev/null
+++ b/openpgp/src/crypto/backend/fuzzing.rs
@@ -0,0 +1,49 @@
+//! Implementation of Sequoia crypto API using a fuzzing-friendly null
+//! backend.
+
+use crate::types::*;
+
+#[allow(unused_variables)]
+pub mod aead;
+#[allow(unused_variables)]
+pub mod asymmetric;
+#[allow(unused_variables)]
+pub mod ecdh;
+#[allow(unused_variables)]
+pub mod hash;
+#[allow(unused_variables)]
+pub mod symmetric;
+
+pub struct Backend(());
+
+impl super::interface::Backend for Backend {
+ fn backend() -> String {
+ "Fuzzing".to_string()
+ }
+
+ fn random(buf: &mut [u8]) -> crate::Result<()> {
+ buf.iter_mut().for_each(|b| *b = 4);
+ Ok(())
+ }
+}
+
+impl AEADAlgorithm {
+ /// Returns the best AEAD mode supported by the backend.
+ ///
+ /// This SHOULD return OCB, which is the mandatory-to-implement
+ /// algorithm and the most performing one, but fall back to any
+ /// supported algorithm.
+ pub(crate) const fn const_default() -> AEADAlgorithm {
+ AEADAlgorithm::OCB
+ }
+
+ pub(crate) fn is_supported_by_backend(&self) -> bool {
+ true
+ }
+
+ #[cfg(test)]
+ pub(crate) fn supports_symmetric_algo(&self, _: &SymmetricAlgorithm)
+ -> bool {
+ true
+ }
+}
diff --git a/openpgp/src/crypto/backend/fuzzing/aead.rs b/openpgp/src/crypto/backend/fuzzing/aead.rs
new file mode 100644
index 00000000..0d995c56
--- /dev/null
+++ b/openpgp/src/crypto/backend/fuzzing/aead.rs
@@ -0,0 +1,41 @@
+//! Implementation of AEAD using Nettle cryptographic library.
+
+use crate::Result;
+
+use crate::crypto::aead::{Aead, CipherOp};
+use crate::seal;
+use crate::types::{AEADAlgorithm, SymmetricAlgorithm};
+
+struct NullAEADMode {}
+
+const DIGEST_SIZE: usize = 16;
+
+impl seal::Sealed for NullAEADMode {}
+impl Aead for NullAEADMode {
+ fn encrypt_seal(&mut self, dst: &mut [u8], src: &[u8]) -> Result<()> {
+ let l = dst.len() - DIGEST_SIZE;
+ dst[..l].copy_from_slice(src);
+ dst[l..].iter_mut().for_each(|p| *p = 0x04);
+ Ok(())
+ }
+ fn decrypt_verify(&mut self, dst: &mut [u8], src: &[u8]) -> Result<()> {
+ dst.copy_from_slice(&src[..src.len() - DIGEST_SIZE]);
+ Ok(())
+ }
+ fn digest_size(&self) -> usize {
+ DIGEST_SIZE
+ }
+}
+
+impl AEADAlgorithm {
+ pub(crate) fn context(
+ &self,
+ sym_algo: SymmetricAlgorithm,
+ key: &[u8],
+ aad: &[u8],
+ nonce: &[u8],
+ _op: CipherOp,
+ ) -> Result<Box<dyn Aead>> {
+ Ok(Box::new(NullAEADMode {}))
+ }
+}
diff --git a/openpgp/src/crypto/backend/fuzzing/asymmetric.rs b/openpgp/src/crypto/backend/fuzzing/asymmetric.rs
new file mode 100644
index 00000000..797795e9
--- /dev/null
+++ b/openpgp/src/crypto/backend/fuzzing/asymmetric.rs
@@ -0,0 +1,169 @@
+use crate::{Error, Result};
+
+use crate::packet::{key, Key};
+use crate::crypto::asymmetric::KeyPair;
+use crate::crypto::backend::interface::Asymmetric;
+use crate::crypto::mem::Protected;
+use crate::crypto::mpi::{self, MPI, ProtectedMPI};
+use crate::crypto::SessionKey;
+use crate::types::{Curve, HashAlgorithm, PublicKeyAlgorithm};
+
+impl Asymmetric for super::Backend {
+ fn supports_algo(_: PublicKeyAlgorithm) -> bool {
+ true
+ }
+
+ fn supports_curve(_: &Curve) -> bool {
+ true
+ }
+
+ fn x25519_generate_key() -> Result<(Protected, [u8; 32])> {
+ Ok((vec![4; 32].into(), [4; 32]))
+ }
+
+ fn x25519_derive_public(_: &Protected) -> Result<[u8; 32]> {
+ Ok([4; 32])
+ }
+
+ fn x25519_shared_point(_: &Protected, _: &[u8; 32])
+ -> Result<Protected> {
+ Ok(vec![4; 32].into())
+ }
+
+ fn ed25519_generate_key() -> Result<(Protected, [u8; 32])> {
+ Ok((vec![4; 32].into(), [4; 32]))
+ }
+
+ fn ed25519_derive_public(_: &Protected) -> Result<[u8; 32]> {
+ Ok([4; 32])
+ }
+
+ fn ed25519_sign(_: &Protected, _: &[u8; 32], _: &[u8]) -> Result<[u8; 64]> {
+ Ok([4; 64])
+ }
+
+ fn ed25519_verify(_: &[u8; 32], _: &[u8], _: &[u8; 64]) -> Result<bool> {
+ Ok(true)
+ }
+
+ fn dsa_generate_key(p_bits: usize)
+ -> Result<(MPI, MPI, MPI, MPI, ProtectedMPI)>
+ {
+ let four = MPI::new(&[4]);
+ Ok((four.clone(),
+ four.clone(),
+ four.clone(),
+ four.clone(),
+ vec![4].into()))
+ }
+
+ fn elgamal_generate_key(p_bits: usize)
+ -> Result<(MPI, MPI, MPI, ProtectedMPI)>
+ {
+ let four = MPI::new(&[4]);
+ Ok((four.clone(),
+ four.clone(),
+ four.clone(),
+ vec![4].into()))
+ }
+}
+
+impl KeyPair {
+ pub(crate) fn sign_backend(&self,
+ _: &mpi::SecretKeyMaterial,
+ _: HashAlgorithm,
+ _: &[u8])
+ -> Result<mpi::Signature>
+ {
+ Err(Error::InvalidOperation("not implemented".into()).into())
+ }
+
+ pub(crate) fn decrypt_backend(&self,
+ _: &mpi::SecretKeyMaterial,
+ ciphertext: &mpi::Ciphertext,
+ _: Option<usize>)
+ -> Result<SessionKey>
+ {
+ match ciphertext {
+ mpi::Ciphertext::RSA { c }
+ | mpi::Ciphertext::ElGamal { c, .. } =>
+ Ok(Vec::from(c.value()).into()),
+ mpi::Ciphertext::ECDH { key, .. } =>
+ Ok(Vec::from(&key[..]).into()),
+ _ => Err(Error::InvalidOperation("not implemented".into()).into()),
+ }
+ }
+}
+
+
+impl<P: key::KeyParts, R: key::KeyRole> Key<P, R> {
+ /// Encrypts the given data with this key.
+ pub(crate) fn encrypt_backend(&self, data: &SessionKey) -> Result<mpi::Ciphertext> {
+ use crate::PublicKeyAlgorithm::*;
+
+ #[allow(deprecated)]
+ match self.pk_algo() {
+ RSAEncryptSign | RSAEncrypt =>
+ Ok(mpi::Ciphertext::RSA {
+ c: MPI::new(&data),
+ }),
+ ElGamalEncrypt | ElGamalEncryptSign =>
+ Ok(mpi::Ciphertext::ElGamal {
+ e: MPI::new(&data),
+ c: MPI::new(&data),
+ }),
+ ECDH =>
+ Ok(mpi::Ciphertext::ECDH {
+ e: MPI::new(&data),
+ key: Vec::from(&data[..]).into_boxed_slice(),
+ }),
+ _ => Err(Error::InvalidOperation("not implemented".into()).into()),
+ }
+ }
+
+ /// Verifies the given signature.
+ pub(crate) fn verify_backend(&self, _: &mpi::Signature, _: HashAlgorithm,
+ _: &[u8]) -> Result<()>
+ {
+ let ok = true; // XXX maybe we also want to have bad signatures?
+ if ok {
+ Ok(())
+ } else {
+ Err(Error::ManipulatedMessage.into())
+ }
+ }
+}
+
+use std::time::SystemTime;
+use crate::packet::key::{Key4, SecretParts};
+
+impl<R> Key4<SecretParts, R>
+ where R: key::KeyRole,
+{
+ /// Creates a new OpenPGP public key packet for an existing RSA key.
+ ///
+ /// The RSA key will use public exponent `e` and modulo `n`. The key will
+ /// have it's creation date set to `ctime` or the current time if `None`
+ /// is given.
+ #[allow(clippy::many_single_char_names)]
+ pub fn import_secret_rsa<T>(d: &[u8], p: &[u8], q: &[u8], ctime: T)
+ -> Result<Self> where T: Into<Option<SystemTime>>
+ {
+ Err(Error::InvalidOperation("not implemented".into()).into())
+ }
+
+ /// Generates a new RSA key with a public modulos of size `bits`.
+ pub fn generate_rsa(bits: usize) -> Result<Self> {
+ Err(Error::InvalidOperation("not implemented".into()).into())
+ }
+
+ /// Generates a new ECC key over `curve`.
+ ///
+ /// If `for_signing` is false a ECDH key, if it's true either a
+ /// EdDSA or ECDSA key is generated. Giving `for_signing == true` and
+ /// `curve == Cv25519` will produce an error. Likewise
+ /// `for_signing == false` and `curve == Ed25519` will produce an error.
+ pub fn generate_ecc(for_signing: bool, curve: Curve) -> Result<Self> {
+ Err(Error::InvalidOperation("not implemented".into()).into())
+ }
+}
diff --git a/openpgp/src/crypto/backend/fuzzing/ecdh.rs b/openpgp/src/crypto/backend/fuzzing/ecdh.rs
new file mode 100644
index 00000000..a01eccbb
--- /dev/null
+++ b/openpgp/src/crypto/backend/fuzzing/ecdh.rs
@@ -0,0 +1,33 @@
+//! Elliptic Curve Diffie-Hellman.
+
+use crate::{Error, Result};
+use crate::crypto::SessionKey;
+use crate::crypto::mpi::{MPI, Ciphertext, SecretKeyMaterial};
+use crate::packet::{key, Key};
+
+/// Wraps a session key using Elliptic Curve Diffie-Hellman.
+#[allow(dead_code)]
+pub fn encrypt<R>(recipient: &Key<key::PublicParts, R>,
+ session_key: &SessionKey)
+ -> Result<Ciphertext>
+ where R: key::KeyRole
+{
+ Ok(Ciphertext::ECDH {
+ e: MPI::new(&session_key),
+ key: Vec::from(&session_key[..]).into_boxed_slice(),
+ })
+}
+
+/// Unwraps a session key using Elliptic Curve Diffie-Hellman.
+#[allow(dead_code)]
+pub fn decrypt<R>(recipient: &Key<key::PublicParts, R>,
+ recipient_sec: &SecretKeyMaterial,
+ ciphertext: &Ciphertext)
+ -> Result<SessionKey>
+ where R: key::KeyRole
+{
+ match ciphertext {
+ Ciphertext::ECDH { key, .. } => Ok(Vec::from(&key[..]).into()),
+ _ => Err(Error::InvalidArgument("not a ecdh ciphertext".into()).into()),
+ }
+}
diff --git a/openpgp/src/crypto/backend/fuzzing/hash.rs b/openpgp/src/crypto/backend/fuzzing/hash.rs
new file mode 100644
index 00000000..b854ec89
--- /dev/null
+++ b/openpgp/src/crypto/backend/fuzzing/hash.rs
@@ -0,0 +1,65 @@
+use std::io;
+
+use crate::crypto::hash::Digest;
+use crate::Result;
+use crate::types::{HashAlgorithm};
+
+#[derive(Clone)]
+struct NullHasher(HashAlgorithm);
+
+impl io::Write for NullHasher {
+ fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+ Ok(buf.len())
+ }
+ fn flush(&mut self) -> io::Result<()> {
+ Ok(())
+ }
+}
+
+impl Digest for NullHasher {
+ fn algo(&self) -> HashAlgorithm {
+ self.0
+ }
+
+ fn digest_size(&self) -> usize {
+ match self.0 {
+ HashAlgorithm::SHA1 => 20,
+ HashAlgorithm::SHA224 => 28,
+ HashAlgorithm::SHA256 => 32,
+ HashAlgorithm::SHA384 => 48,
+ HashAlgorithm::SHA512 => 64,
+ HashAlgorithm::RipeMD => 20,
+ HashAlgorithm::MD5 => 16,
+ _ => 32, // Made up.
+ }
+ }
+
+ fn update(&mut self, data: &[u8]) {
+ // Nop.
+ }
+
+ fn digest(&mut self, digest: &mut [u8]) -> Result<()> {
+ digest.iter_mut().enumerate().for_each(|(i, b)| *b = i as u8);
+ Ok(())
+ }
+}
+
+impl HashAlgorithm {
+ /// Whether Sequoia supports this algorithm.
+ pub fn is_supported(self) -> bool {
+ true
+ }
+
+ /// Creates a new hash context for this algorithm.
+ ///
+ /// # Errors
+ ///
+ /// Fails with `Error::UnsupportedHashAlgorithm` if Sequoia does
+ /// not support this algorithm. See
+ /// [`HashAlgorithm::is_supported`].
+ ///
+ /// [`HashAlgorithm::is_supported`]: HashAlgorithm::is_supported()
+ pub(crate) fn new_hasher(self) -> Result<Box<dyn Digest>> {
+ Ok(Box::new(NullHasher(self)))
+ }
+}
diff --git a/openpgp/src/crypto/backend/fuzzing/symmetric.rs b/openpgp/src/crypto/backend/fuzzing/symmetric.rs
new file mode 100644
index 00000000..e92055e7
--- /dev/null
+++ b/openpgp/src/crypto/backend/fuzzing/symmetric.rs
@@ -0,0 +1,75 @@
+use crate::crypto::symmetric::Mode;
+
+use crate::Result;
+use crate::types::SymmetricAlgorithm;
+
+struct NullCipher(usize);
+
+impl Mode for NullCipher {
+ fn block_size(&self) -> usize {
+ self.0
+ }
+
+ fn encrypt(
+ &mut self,
+ dst: &mut [u8],
+ src: &[u8],
+ ) -> Result<()> {
+ dst.copy_from_slice(src);
+ Ok(())
+ }
+
+ fn decrypt(
+ &mut self,
+ dst: &mut [u8],
+ src: &[u8],
+ ) -> Result<()> {
+ dst.copy_from_slice(src);
+ Ok(())
+ }
+}
+
+impl SymmetricAlgorithm {
+ /// Returns whether this algorithm is supported by the crypto backend.
+ ///
+ /// All backends support all the AES variants.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use sequoia_openpgp as openpgp;
+ /// use openpgp::types::SymmetricAlgorithm;
+ ///
+ /// assert!(SymmetricAlgorithm::AES256.is_supported());
+ /// assert!(SymmetricAlgorithm::TripleDES.is_supported());
+ ///
+ /// assert!(!SymmetricAlgorithm::IDEA.is_supported());
+ /// assert!(!SymmetricAlgorithm::Unencrypted.is_supported());
+ /// assert!(!SymmetricAlgorithm::Private(101).is_supported());
+ /// ```
+ pub(crate) fn is_supported_by_backend(&self) -> bool {
+ true
+ }
+
+ /// Creates a Nettle context for encrypting in CFB mode.
+ pub(crate) fn make_encrypt_cfb(self, key: &[u8], iv: Vec<u8>)
+ -> Result<Box<dyn Mode>> {
+ Ok(Box::new(NullCipher(self.block_size().unwrap_or(16))))
+ }
+
+ /// Creates a Nettle context for decrypting in CFB mode.
+ pub(crate) fn make_decrypt_cfb(self, key: &[u8], iv: Vec<u8>)
+ -> Result<Box<dyn Mode>> {
+ Ok(Box::new(NullCipher(self.block_size().unwrap_or(16))))
+ }
+
+ /// Creates a Nettle context for encrypting in ECB mode.
+ pub(crate) fn make_encrypt_ecb(self, key: &[u8]) -> Result<Box<dyn Mode>> {
+ Ok(Box::new(NullCipher(self.block_size().unwrap_or(16))))
+ }
+
+ /// Creates a Nettle context for decrypting in ECB mode.
+ pub(crate) fn make_decrypt_ecb(self, key: &[u8]) -> Result<Box<dyn Mode>> {
+ Ok(Box::new(NullCipher(self.block_size().unwrap_or(16))))
+ }
+}
diff --git a/openpgp/src/crypto/ecdh.rs b/openpgp/src/crypto/ecdh.rs
index 14e1ac1b..3dcf0ed2 100644
--- a/openpgp/src/crypto/ecdh.rs
+++ b/openpgp/src/crypto/ecdh.rs
@@ -20,6 +20,7 @@ use crate::packet::Key;
use crate::types::{Curve, HashAlgorithm, PublicKeyAlgorithm, SymmetricAlgorithm};
use crate::utils::{read_be_u64, write_be_u64};
+#[allow(unused_imports)]
pub(crate) use crate::crypto::backend::ecdh::{encrypt, decrypt};
/// Returns the default ECDH KDF hash function.
@@ -66,7 +67,7 @@ pub(crate) fn default_ecdh_kek_cipher(curve: &Curve) -> SymmetricAlgorithm {
/// `VB` is the ephemeral public key encoded appropriately as MPI
/// (i.e. with the 0x40 prefix for X25519, or 0x04 for the NIST
/// curves), `S` is the shared Diffie-Hellman secret.
-#[allow(non_snake_case)]
+#[allow(non_snake_case, dead_code)]
pub(crate) fn encrypt_wrap<R>(recipient: &Key<key::PublicParts, R>,
session_key: &SessionKey, VB: MPI,
S: &Protected)
@@ -194,6 +195,7 @@ fn kdf(x: &Protected, obits: usize, hash: HashAlgorithm, param: &[u8])
/// See [Section 8 of RFC 6637].
///
/// [Section 8 of RFC 6637]: https://tools.ietf.org/html/rfc6637#section-8
+#[allow(dead_code)]
fn pkcs5_pad(sk: Protected, target_len: usize) -> Result<Protected> {
if sk.len() > target_len {
return Err(Error::InvalidArgument(
diff --git a/openpgp/src/crypto/hash.rs b/openpgp/src/crypto/hash.rs
index d22b0377..79a31f8a 100644
--- a/openpgp/src/crypto/hash.rs
+++ b/openpgp/src/crypto/hash.rs
@@ -194,7 +194,7 @@ impl HashAlgorithm {
/// [`HashAlgorithm::is_supported`]: HashAlgorithm::is_supported()
pub fn context(self) -> Result<Box<dyn Digest>> {
let hasher: Box<dyn Digest> = match self {
- HashAlgorithm::SHA1 =>
+ HashAlgorithm::SHA1 if ! cfg!(feature = "crypto-fuzzing") =>
Box::new(crate::crypto::backend::sha1cd::build()),
_ => self.new_hasher()?,
};