summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWiktor Kwapisiewicz <wiktor@metacode.biz>2021-05-10 11:26:22 +0200
committerWiktor Kwapisiewicz <wiktor@metacode.biz>2021-05-14 13:41:04 +0200
commita1460fa0d43462ec7648029a9c1ce13a429529e2 (patch)
treef2df38a14fb1fc7b4525c612bb44f24295ff944b
parentc087de178d7fae8753c229ba2a07ff8932c54a76 (diff)
cng: Replace cng with x25519-dalek for ECDH decryption.wiktor-k/fix-windows-25519-decryption
- Apparently CNG decryption using ECDH doesn't work on Windows. - Replace it with x25519-dalek code. - Remove unused code. Co-authored-by: Nikhil Benesch <nikhil.benesch@gmail.com>
-rw-r--r--Cargo.lock12
-rw-r--r--openpgp/Cargo.toml3
-rw-r--r--openpgp/src/crypto/backend/cng/ecdh.rs38
3 files changed, 23 insertions, 30 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 1f02d57f..63b6f6af 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2180,6 +2180,7 @@ dependencies = [
"unicode-normalization",
"win-crypto-ng",
"winapi 0.3.9",
+ "x25519-dalek",
]
[[package]]
@@ -2863,6 +2864,17 @@ dependencies = [
]
[[package]]
+name = "x25519-dalek"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a0c105152107e3b96f6a00a65e86ce82d9b125230e1c4302940eca58ff71f4f"
+dependencies = [
+ "curve25519-dalek",
+ "rand_core 0.5.1",
+ "zeroize",
+]
+
+[[package]]
name = "zbase32"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/openpgp/Cargo.toml b/openpgp/Cargo.toml
index a520645b..942186d4 100644
--- a/openpgp/Cargo.toml
+++ b/openpgp/Cargo.toml
@@ -49,6 +49,7 @@ unicode-normalization = "0.1.9"
win-crypto-ng = { version = "0.4", features = ["rand", "block-cipher"], optional = true }
num-bigint-dig = { version = "0.6", default-features = false, optional = true }
ed25519-dalek = { version = "1", default-features = false, features = ["rand", "u64_backend"], optional = true }
+x25519-dalek = { version = "1", optional = true }
winapi = { version = "0.3.8", default-features = false, features = ["bcrypt"], optional = true }
eax = "0.3"
@@ -68,7 +69,7 @@ criterion = { version = "0.3.4", features = ["html_reports"] }
default = ["compression", "crypto-nettle"]
# TODO(#333): Allow for/implement more backends
crypto-nettle = ["nettle"]
-crypto-cng = ["winapi", "win-crypto-ng", "ed25519-dalek", "num-bigint-dig"]
+crypto-cng = ["winapi", "win-crypto-ng", "ed25519-dalek", "x25519-dalek", "num-bigint-dig"]
# The compression algorithms.
compression = ["compression-deflate", "compression-bzip2"]
diff --git a/openpgp/src/crypto/backend/cng/ecdh.rs b/openpgp/src/crypto/backend/cng/ecdh.rs
index b8f38577..3bfb9648 100644
--- a/openpgp/src/crypto/backend/cng/ecdh.rs
+++ b/openpgp/src/crypto/backend/cng/ecdh.rs
@@ -164,30 +164,19 @@ where
let S: Protected = match curve {
Curve::Cv25519 => {
- // Get the public part V of the ephemeral key.
- let V = e.decode_point(curve)?.0;
+ use x25519_dalek::{PublicKey, StaticSecret};
+ use std::convert::TryInto;
- let provider = AsymmetricAlgorithm::open(AsymmetricAlgorithmId::Ecdh(NamedCurve::Curve25519))?;
- let V = AsymmetricKey::<Ecdh<Curve25519>, Public>::import_from_parts(
- &provider,
- V,
- )?;
+ // Get the public part V of the ephemeral key.
+ let V: [u8; 32] = e.decode_point(curve)?.0.try_into()?;
+ let V = PublicKey::from(V);
- let mut scalar = pad_secret_to(scalar.value(), 32).into_owned();
- // Reverse the scalar. See
- // https://lists.gnupg.org/pipermail/gnupg-devel/2018-February/033437.html.
+ let mut scalar: [u8; 32] = scalar.value().try_into()?;
scalar.reverse();
+ let r = StaticSecret::from(scalar);
- let r = AsymmetricKey::<Ecdh<Curve25519>, Private>::import_from_parts(
- &provider,
- &scalar,
- )?;
-
- let secret = cng::asymmetric::agreement::secret_agreement(&r, &V)?;
- // Returned secret is little-endian, flip it to big-endian
- let mut secret = secret.derive_raw()?;
- secret.reverse();
- secret.into()
+ let secret = r.diffie_hellman(&V);
+ Vec::from(secret.to_bytes()).into()
}
Curve::NistP256 | Curve::NistP384 | Curve::NistP521 => {
@@ -300,12 +289,3 @@ impl AsRef<[u8]> for PaddedSecret<'_> {
}
}
}
-
-impl PaddedSecret<'_> {
- fn into_owned(self) -> Protected {
- match self {
- PaddedSecret::Ref(value) => Protected::from(value),
- PaddedSecret::Own(value) => value,
- }
- }
-}