summaryrefslogtreecommitdiffstats
path: root/openpgp
diff options
context:
space:
mode:
Diffstat (limited to 'openpgp')
-rw-r--r--openpgp/Cargo.toml6
-rw-r--r--openpgp/src/crypto/backend/botan.rs5
-rw-r--r--openpgp/src/crypto/backend/botan/kdf.rs31
-rw-r--r--openpgp/src/crypto/backend/cng.rs1
-rw-r--r--openpgp/src/crypto/backend/cng/kdf.rs20
-rw-r--r--openpgp/src/crypto/backend/interface.rs23
-rw-r--r--openpgp/src/crypto/backend/nettle.rs1
-rw-r--r--openpgp/src/crypto/backend/nettle/kdf.rs25
-rw-r--r--openpgp/src/crypto/backend/openssl.rs1
-rw-r--r--openpgp/src/crypto/backend/openssl/kdf.rs31
-rw-r--r--openpgp/src/crypto/backend/rust.rs1
-rw-r--r--openpgp/src/crypto/backend/rust/kdf.rs20
12 files changed, 161 insertions, 4 deletions
diff --git a/openpgp/Cargo.toml b/openpgp/Cargo.toml
index 22f91b19..49bf4452 100644
--- a/openpgp/Cargo.toml
+++ b/openpgp/Cargo.toml
@@ -81,6 +81,8 @@ ecdsa = { version = "0.16", optional = true, features = ["hazmat", "arithmetic"]
# std::error::Error.
ed25519 = { version = "2", default-features = false, features = ["std"], optional = true }
ed25519-dalek = { version = "2", features = ["rand_core", "zeroize"], optional = true }
+generic-array = { version = "0.14.4", optional = true }
+hkdf = { version = "0.12", optional = true }
idea = { version = "0.5", optional = true, features = ["zeroize"] }
md-5 = { version = "0.10", features = ["oid"], optional = true }
num-bigint-dig = { version = "0.8", default-features = false, optional = true }
@@ -119,11 +121,11 @@ crypto-rust = [
"md-5", "num-bigint-dig", "ripemd", "rsa", "sha2",
"sha1collisiondetection/digest-trait", "sha1collisiondetection/oid",
"twofish", "typenum", "x25519-dalek", "p256",
- "rand_core", "rand_core/getrandom", "ecdsa", "aes-gcm", "dsa"
+ "rand_core", "rand_core/getrandom", "ecdsa", "aes-gcm", "dsa", "hkdf"
]
crypto-cng = [
"cipher", "eax", "winapi", "win-crypto-ng", "ed25519", "ed25519-dalek",
- "num-bigint-dig", "aes-gcm", "rand_core"
+ "num-bigint-dig", "aes-gcm", "rand_core", "hkdf", "sha2"
]
crypto-openssl = ["openssl", "openssl-sys"]
crypto-botan = ["botan/botan3"]
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/interface.rs b/openpgp/src/crypto/backend/interface.rs
index bf6f876a..bc7c7f4b 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,
@@ -105,3 +106,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()))?)
+ }
+}