summaryrefslogtreecommitdiffstats
path: root/openpgp/src/crypto/backend/cng/ecdh.rs
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2021-06-04 18:52:28 +0200
committerJustus Winter <justus@sequoia-pgp.org>2021-06-07 12:29:18 +0200
commitb1ddb1f3c03e3340c461f1d90a64616884f11ceb (patch)
treec2f89589202ea63452807d5d80e6aa8325ce5870 /openpgp/src/crypto/backend/cng/ecdh.rs
parent9478f48e6b692d06c83126e93b77ce581cf979bf (diff)
openpgp: Clamp cv25519 secrets for use with CNG.
- Some bits of cv25519 keys must be clamped. However, some implementations may not do that at key generation time. Nettle implicitly clamps the secrets, and hence gracefully works with these keys. CNG, however, does not. Clamp the bits right before use with CNG. - Fixes #715.
Diffstat (limited to 'openpgp/src/crypto/backend/cng/ecdh.rs')
-rw-r--r--openpgp/src/crypto/backend/cng/ecdh.rs14
1 files changed, 14 insertions, 0 deletions
diff --git a/openpgp/src/crypto/backend/cng/ecdh.rs b/openpgp/src/crypto/backend/cng/ecdh.rs
index b8f38577..c115ca88 100644
--- a/openpgp/src/crypto/backend/cng/ecdh.rs
+++ b/openpgp/src/crypto/backend/cng/ecdh.rs
@@ -15,6 +15,8 @@ use cng::asymmetric::{Public, Private, AsymmetricAlgorithm, AsymmetricAlgorithmI
use cng::asymmetric::ecc::{NamedCurve, NistP256, NistP384, NistP521, Curve25519};
use cng::key_blob::{EccKeyPublicPayload, EccKeyPrivatePayload};
+const CURVE25519_SIZE: usize = 32;
+
/// Wraps a session key using Elliptic Curve Diffie-Hellman.
#[allow(non_snake_case)]
pub fn encrypt<R>(
@@ -178,6 +180,18 @@ where
// https://lists.gnupg.org/pipermail/gnupg-devel/2018-February/033437.html.
scalar.reverse();
+ // Some bits must be clamped. Usually, this is done
+ // during key creation. However, if that is not done, we
+ // should do that before handing it to CNG. See
+ // Curve25519 Paper, Sec. 3:
+ //
+ // > A user can, for example, generate 32 uniform random
+ // > bytes, clear bits 0, 1, 2 of the first byte, clear bit
+ // > 7 of the last byte, and set bit 6 of the last byte.
+ scalar[0] &= 0b1111_1000;
+ scalar[CURVE25519_SIZE - 1] &= !0b1000_0000;
+ scalar[CURVE25519_SIZE - 1] |= 0b0100_0000;
+
let r = AsymmetricKey::<Ecdh<Curve25519>, Private>::import_from_parts(
&provider,
&scalar,