diff options
author | Igor Matuszewski <igor@sequoia-pgp.org> | 2020-06-17 00:57:53 +0200 |
---|---|---|
committer | Igor Matuszewski <xanewok@gmail.com> | 2020-07-29 15:24:51 +0000 |
commit | 5d7b4f63acb7c21e5837f22b926fda48d2e02796 (patch) | |
tree | 197315182d130aca239993e6a5a1ec3dcd128426 /openpgp/src/crypto/backend | |
parent | 8a44967d2d10ad293f7c0743e6eb46619be494fd (diff) |
openpgp: Move some ECDH helper functions to backend-agnostic module
Diffstat (limited to 'openpgp/src/crypto/backend')
-rw-r--r-- | openpgp/src/crypto/backend/nettle/ecdh.rs | 130 |
1 files changed, 2 insertions, 128 deletions
diff --git a/openpgp/src/crypto/backend/nettle/ecdh.rs b/openpgp/src/crypto/backend/nettle/ecdh.rs index f3f820b5..d6062789 100644 --- a/openpgp/src/crypto/backend/nettle/ecdh.rs +++ b/openpgp/src/crypto/backend/nettle/ecdh.rs @@ -4,11 +4,11 @@ use nettle::{curve25519, ecc, ecdh, random::Yarrow}; use crate::{Error, Result}; use crate::crypto::SessionKey; -use crate::crypto::ecdh::{aes_key_wrap, aes_key_unwrap, kdf, pkcs5_pad, pkcs5_unpad}; +use crate::crypto::ecdh::{encrypt_shared, decrypt_shared}; use crate::crypto::mem::Protected; use crate::crypto::mpi::{MPI, PublicKey, SecretKeyMaterial, Ciphertext}; use crate::packet::{key, Key}; -use crate::types::{Curve, HashAlgorithm, SymmetricAlgorithm, PublicKeyAlgorithm}; +use crate::types::Curve; /// Wraps a session key using Elliptic Curve Diffie-Hellman. #[allow(non_snake_case)] @@ -118,54 +118,6 @@ pub fn encrypt<R>(recipient: &Key<key::PublicParts, R>, } } -/// Wraps a session key. -/// -/// After using Elliptic Curve Diffie-Hellman to compute a shared -/// secret, this function deterministically encrypts the given session -/// key. -/// -/// `VB` is the ephemeral public key (with 0x40 prefix), `S` is the -/// shared Diffie-Hellman secret. -#[allow(non_snake_case)] -pub fn encrypt_shared<R>(recipient: &Key<key::PublicParts, R>, - session_key: &SessionKey, VB: MPI, - S: &Protected) - -> Result<Ciphertext> - where R: key::KeyRole -{ - match recipient.mpis() { - &PublicKey::ECDH{ ref curve, ref hash, ref sym,.. } => { - // m = sym_alg_ID || session key || checksum || pkcs5_padding; - let mut m = Vec::with_capacity(40); - m.extend_from_slice(session_key); - let m = pkcs5_pad(m.into(), 40)?; - // Note: We always pad up to 40 bytes to obfuscate the - // length of the symmetric key. - - // Compute KDF input. - let param = make_param(recipient, curve, hash, sym); - - // Z_len = the key size for the KEK_alg_ID used with AESKeyWrap - // Compute Z = KDF( S, Z_len, Param ); - #[allow(non_snake_case)] - let Z = kdf(S, sym.key_size()?, *hash, ¶m)?; - - // Compute C = AESKeyWrap( Z, m ) as per [RFC3394] - #[allow(non_snake_case)] - let C = aes_key_wrap(*sym, &Z, &m)?; - - // Output (MPI(VB) || len(C) || C). - Ok(Ciphertext::ECDH { - e: VB, - key: C.into_boxed_slice(), - }) - } - - _ => - Err(Error::InvalidArgument("Expected an ECDHPublicKey".into()).into()), - } -} - /// Unwraps a session key using Elliptic Curve Diffie-Hellman. #[allow(non_snake_case)] pub fn decrypt<R>(recipient: &Key<key::PublicParts, R>, @@ -273,81 +225,3 @@ pub fn decrypt<R>(recipient: &Key<key::PublicParts, R>, Err(Error::InvalidArgument("Expected an ECDHPublicKey".into()).into()), } } - -/// Unwraps a session key. -/// -/// After using Elliptic Curve Diffie-Hellman to compute the shared -/// secret, this function decrypts the given encrypted session key. -/// -/// `recipient` is the message receiver's public key, `S` is the -/// shared Diffie-Hellman secret used to encrypt `ciphertext`. -#[allow(non_snake_case)] -pub fn decrypt_shared<R>(recipient: &Key<key::PublicParts, R>, - S: &Protected, - ciphertext: &Ciphertext) - -> Result<SessionKey> - where R: key::KeyRole -{ - match (recipient.mpis(), ciphertext) { - (PublicKey::ECDH { ref curve, ref hash, ref sym, ..}, - Ciphertext::ECDH { ref key, .. }) => { - // Compute KDF input. - let param = make_param(recipient, curve, hash, sym); - - // Z_len = the key size for the KEK_alg_ID used with AESKeyWrap - // Compute Z = KDF( S, Z_len, Param ); - #[allow(non_snake_case)] - let Z = kdf(&S, sym.key_size()?, *hash, ¶m)?; - - // Compute m = AESKeyUnwrap( Z, C ) as per [RFC3394] - let m = aes_key_unwrap(*sym, &Z, key)?; - let cipher = SymmetricAlgorithm::from(m[0]); - let m = pkcs5_unpad(m, 1 + cipher.key_size()? + 2)?; - - Ok(m.into()) - }, - - _ => - Err(Error::InvalidArgument( - "Expected an ECDH key and ciphertext".into()).into()), - } -} - -fn make_param<P, R>(recipient: &Key<P, R>, - curve: &Curve, hash: &HashAlgorithm, - sym: &SymmetricAlgorithm) - -> Vec<u8> - where P: key::KeyParts, - R: key::KeyRole -{ - // Param = curve_OID_len || curve_OID || - // public_key_alg_ID || 03 || 01 || KDF_hash_ID || - // KEK_alg_ID for AESKeyWrap || "Anonymous Sender " || - // recipient_fingerprint; - let fp = recipient.fingerprint(); - - let mut param = Vec::with_capacity( - 1 + curve.oid().len() // Length and Curve OID, - + 1 // Public key algorithm ID, - + 4 // KDF parameters, - + 20 // "Anonymous Sender ", - + fp.as_bytes().len()); // Recipients key fingerprint. - - param.push(curve.oid().len() as u8); - param.extend_from_slice(curve.oid()); - param.push(PublicKeyAlgorithm::ECDH.into()); - param.push(3); - param.push(1); - param.push((*hash).into()); - param.push((*sym).into()); - param.extend_from_slice(b"Anonymous Sender "); - param.extend_from_slice(fp.as_bytes()); - assert_eq!(param.len(), - 1 + curve.oid().len() // Length and Curve OID, - + 1 // Public key algorithm ID, - + 4 // KDF parameters, - + 20 // "Anonymous Sender ", - + fp.as_bytes().len()); // Recipients key fingerprint. - - param -} |