diff options
Diffstat (limited to 'openpgp/src')
-rw-r--r-- | openpgp/src/crypto/backend/botan.rs | 5 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/botan/kdf.rs | 31 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/cng.rs | 1 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/cng/kdf.rs | 20 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/fuzzing.rs | 2 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/fuzzing/kdf.rs | 18 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/interface.rs | 23 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/nettle.rs | 1 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/nettle/kdf.rs | 25 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/openssl.rs | 1 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/openssl/kdf.rs | 31 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/rust.rs | 1 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/rust/kdf.rs | 20 |
13 files changed, 177 insertions, 2 deletions
diff --git a/openpgp/src/crypto/backend/botan.rs b/openpgp/src/crypto/backend/botan.rs index 3f1ab906..568802de 100644 --- a/openpgp/src/crypto/backend/botan.rs +++ b/openpgp/src/crypto/backend/botan.rs @@ -1,11 +1,14 @@ //! Implementation of Sequoia crypto API using the Botan cryptographic library. -use crate::types::*; +use crate::{ + types::*, +}; pub mod aead; pub mod asymmetric; pub mod ecdh; pub mod hash; +pub mod kdf; pub mod symmetric; pub struct Backend(()); diff --git a/openpgp/src/crypto/backend/botan/kdf.rs b/openpgp/src/crypto/backend/botan/kdf.rs new file mode 100644 index 00000000..942165e2 --- /dev/null +++ b/openpgp/src/crypto/backend/botan/kdf.rs @@ -0,0 +1,31 @@ +use crate::{ + Result, + crypto::{ + SessionKey, + backend::interface::Kdf, + }, +}; + +impl Kdf for super::Backend { + fn hkdf_sha256(ikm: &SessionKey, salt: Option<&[u8]>, info: &[u8], + okm: &mut SessionKey) + -> Result<()> + { + assert!(okm.len() <= 255 * 32); + + const NO_SALT: [u8; 32] = [0; 32]; + let salt = salt.unwrap_or(&NO_SALT); + + // XXX: It'd be nice to write that directly to `okm`, but botan-rs + // does not have such an interface. + let okm_heap: SessionKey = + botan::kdf("HKDF(SHA-256)", okm.len(), &*ikm, salt, info)? + .into(); + + // XXX: Now copy the secret. + let l = okm.len().min(okm_heap.len()); + okm[..l].copy_from_slice(&okm_heap[..l]); + + Ok(()) + } +} diff --git a/openpgp/src/crypto/backend/cng.rs b/openpgp/src/crypto/backend/cng.rs index 9f43958f..557a34c3 100644 --- a/openpgp/src/crypto/backend/cng.rs +++ b/openpgp/src/crypto/backend/cng.rs @@ -8,6 +8,7 @@ pub mod aead; pub mod asymmetric; pub mod ecdh; pub mod hash; +pub mod kdf; pub mod symmetric; pub struct Backend(()); diff --git a/openpgp/src/crypto/backend/cng/kdf.rs b/openpgp/src/crypto/backend/cng/kdf.rs new file mode 100644 index 00000000..ac98a496 --- /dev/null +++ b/openpgp/src/crypto/backend/cng/kdf.rs @@ -0,0 +1,20 @@ +use hkdf::Hkdf; +use sha2::Sha256; + +use crate::{ + Result, + crypto::{ + SessionKey, + backend::interface::Kdf, + }, +}; + +impl Kdf for super::Backend { + fn hkdf_sha256(ikm: &SessionKey, salt: Option<&[u8]>, info: &[u8], + okm: &mut SessionKey) + -> Result<()> + { + Ok(Hkdf::<Sha256>::new(salt, &ikm).expand(info, okm) + .map_err(|e| crate::Error::InvalidOperation(e.to_string()))?) + } +} diff --git a/openpgp/src/crypto/backend/fuzzing.rs b/openpgp/src/crypto/backend/fuzzing.rs index e36ee34e..a10e5002 100644 --- a/openpgp/src/crypto/backend/fuzzing.rs +++ b/openpgp/src/crypto/backend/fuzzing.rs @@ -12,6 +12,8 @@ pub mod ecdh; #[allow(unused_variables)] pub mod hash; #[allow(unused_variables)] +pub mod kdf; +#[allow(unused_variables)] pub mod symmetric; pub struct Backend(()); diff --git a/openpgp/src/crypto/backend/fuzzing/kdf.rs b/openpgp/src/crypto/backend/fuzzing/kdf.rs new file mode 100644 index 00000000..f29f2b25 --- /dev/null +++ b/openpgp/src/crypto/backend/fuzzing/kdf.rs @@ -0,0 +1,18 @@ +use crate::{ + Result, + crypto::{ + SessionKey, + backend::interface::Kdf, + }, +}; + +impl Kdf for super::Backend { + fn hkdf_sha256(ikm: &SessionKey, salt: Option<&[u8]>, info: &[u8], + okm: &mut SessionKey) + -> Result<()> + { + assert!(okm.len() <= 255 * 32); + okm.iter_mut().for_each(|p| *p = 4); + Ok(()) + } +} diff --git a/openpgp/src/crypto/backend/interface.rs b/openpgp/src/crypto/backend/interface.rs index 864b2714..05e56a8c 100644 --- a/openpgp/src/crypto/backend/interface.rs +++ b/openpgp/src/crypto/backend/interface.rs @@ -4,6 +4,7 @@ use crate::{ Error, Result, crypto::{ + SessionKey, mem::Protected, mpi::{MPI, ProtectedMPI}, }, @@ -11,7 +12,7 @@ use crate::{ }; /// Abstracts over the cryptographic backends. -pub trait Backend: Asymmetric { +pub trait Backend: Asymmetric + Kdf { /// Returns a short, human-readable description of the backend. /// /// This starts with the name of the backend, possibly a version, @@ -121,3 +122,23 @@ mod tests { assert_ne!(secret.as_ref(), public); } } + +/// Key-Derivation-Functions. +pub trait Kdf { + /// HKDF instantiated with SHA256. + /// + /// Used to derive message keys from session keys, and key + /// encapsulating keys from S2K mechanisms. In both cases, using + /// a KDF that includes algorithm information in the given `info` + /// provides key space separation between cipher algorithms and + /// modes. + /// + /// `salt`, if given, SHOULD be 32 bytes of salt matching the + /// digest size of the hash function. If it is not give, 32 zeros + /// are used instead. + /// + /// `okm` must not be larger than 255 * 32 (the size of the hash + /// digest). + fn hkdf_sha256(ikm: &SessionKey, salt: Option<&[u8]>, info: &[u8], + okm: &mut SessionKey) -> Result<()>; +} diff --git a/openpgp/src/crypto/backend/nettle.rs b/openpgp/src/crypto/backend/nettle.rs index c0cb767f..04fef2eb 100644 --- a/openpgp/src/crypto/backend/nettle.rs +++ b/openpgp/src/crypto/backend/nettle.rs @@ -8,6 +8,7 @@ pub mod aead; pub mod asymmetric; pub mod ecdh; pub mod hash; +pub mod kdf; pub mod symmetric; pub struct Backend(()); diff --git a/openpgp/src/crypto/backend/nettle/kdf.rs b/openpgp/src/crypto/backend/nettle/kdf.rs new file mode 100644 index 00000000..a016a3a3 --- /dev/null +++ b/openpgp/src/crypto/backend/nettle/kdf.rs @@ -0,0 +1,25 @@ +use nettle::{ + kdf::hkdf, + hash::Sha256, +}; + +use crate::{ + Result, + crypto::{ + SessionKey, + backend::interface::Kdf, + }, +}; + +impl Kdf for super::Backend { + fn hkdf_sha256(ikm: &SessionKey, salt: Option<&[u8]>, info: &[u8], + okm: &mut SessionKey) + -> Result<()> + { + assert!(okm.len() <= 255 * 32); + const NO_SALT: [u8; 32] = [0; 32]; + let salt = salt.unwrap_or(&NO_SALT); + hkdf::<Sha256>(&ikm[..], salt, info, okm); + Ok(()) + } +} diff --git a/openpgp/src/crypto/backend/openssl.rs b/openpgp/src/crypto/backend/openssl.rs index aabf94cf..2bea302b 100644 --- a/openpgp/src/crypto/backend/openssl.rs +++ b/openpgp/src/crypto/backend/openssl.rs @@ -6,6 +6,7 @@ pub mod aead; pub mod asymmetric; pub mod ecdh; pub mod hash; +pub mod kdf; pub mod symmetric; pub struct Backend(()); diff --git a/openpgp/src/crypto/backend/openssl/kdf.rs b/openpgp/src/crypto/backend/openssl/kdf.rs new file mode 100644 index 00000000..11c48667 --- /dev/null +++ b/openpgp/src/crypto/backend/openssl/kdf.rs @@ -0,0 +1,31 @@ +use openssl::{ + md::Md, + pkey::Id, + pkey_ctx::PkeyCtx, +}; + +use crate::{ + Result, + crypto::{ + SessionKey, + backend::interface::Kdf, + }, +}; + +impl Kdf for super::Backend { + fn hkdf_sha256(ikm: &SessionKey, salt: Option<&[u8]>, info: &[u8], + okm: &mut SessionKey) + -> Result<()> + { + let mut pkey = PkeyCtx::new_id(Id::HKDF)?; + pkey.derive_init()?; + pkey.set_hkdf_md(Md::sha256())?; + pkey.set_hkdf_key(&ikm)?; + if let Some(salt) = salt { + pkey.set_hkdf_salt(salt)?; + } + pkey.add_hkdf_info(info)?; + pkey.derive(Some(okm))?; + Ok(()) + } +} diff --git a/openpgp/src/crypto/backend/rust.rs b/openpgp/src/crypto/backend/rust.rs index e373dba3..27370e82 100644 --- a/openpgp/src/crypto/backend/rust.rs +++ b/openpgp/src/crypto/backend/rust.rs @@ -10,6 +10,7 @@ pub mod aead; pub mod asymmetric; pub mod ecdh; pub mod hash; +pub mod kdf; pub mod symmetric; pub struct Backend(()); diff --git a/openpgp/src/crypto/backend/rust/kdf.rs b/openpgp/src/crypto/backend/rust/kdf.rs new file mode 100644 index 00000000..ac98a496 --- /dev/null +++ b/openpgp/src/crypto/backend/rust/kdf.rs @@ -0,0 +1,20 @@ +use hkdf::Hkdf; +use sha2::Sha256; + +use crate::{ + Result, + crypto::{ + SessionKey, + backend::interface::Kdf, + }, +}; + +impl Kdf for super::Backend { + fn hkdf_sha256(ikm: &SessionKey, salt: Option<&[u8]>, info: &[u8], + okm: &mut SessionKey) + -> Result<()> + { + Ok(Hkdf::<Sha256>::new(salt, &ikm).expand(info, okm) + .map_err(|e| crate::Error::InvalidOperation(e.to_string()))?) + } +} |