Skip to content

Commit

Permalink
Add P384 suport for RustCrypto (#190)
Browse files Browse the repository at this point in the history
* Add P384 suport for RustCrypto

* Bump version

---------

Co-authored-by: Marta Mularczyk <mulmarta@amazon.com>
  • Loading branch information
mulmarta and Marta Mularczyk authored Sep 19, 2024
1 parent a7b0422 commit b3f2ed4
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 3 deletions.
3 changes: 2 additions & 1 deletion mls-rs-crypto-rustcrypto/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mls-rs-crypto-rustcrypto"
version = "0.11.0"
version = "0.11.1"
edition = "2021"
description = "RustCrypto based CryptoProvider for mls-rs"
homepage = "https://github.com/awslabs/mls-rs"
Expand Down Expand Up @@ -53,6 +53,7 @@ hkdf = { version = "0.12", default-features = false }

# KEM
p256 = { version = "0.13", default-features = false, features = ["alloc", "ecdh", "ecdsa", "pem"] }
p384 = { version = "0.13", default-features = false, features = ["alloc", "ecdh", "ecdsa", "pem"] }
x25519-dalek = { version = "2", default-features = false, features = ["alloc", "static_secrets"] }
ed25519-dalek = { version = "2", default-features = false, features = ["alloc", "rand_core"] }
sec1 = { version = "0.7", default-features = false, features = ["alloc"] }
Expand Down
63 changes: 63 additions & 0 deletions mls-rs-crypto-rustcrypto/src/ec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@ pub enum EcPublicKey {
X25519(x25519_dalek::PublicKey),
Ed25519(ed25519_dalek::VerifyingKey),
P256(p256::PublicKey),
P384(p384::PublicKey),
}

pub enum EcPrivateKey {
X25519(x25519_dalek::StaticSecret),
Ed25519(ed25519_dalek::SigningKey),
P256(p256::SecretKey),
P384(p384::SecretKey),
}

#[derive(Debug)]
Expand Down Expand Up @@ -85,6 +87,7 @@ impl core::fmt::Debug for EcPrivateKey {
Self::X25519(_) => f.write_str("X25519 Secret Key"),
Self::Ed25519(_) => f.write_str("Ed25519 Secret Key"),
Self::P256(_) => f.write_str("P256 Secret Key"),
Self::P384(_) => f.write_str("P384 Secret Key"),
}
}
}
Expand All @@ -109,6 +112,17 @@ pub fn pub_key_from_uncompressed(bytes: &[u8], curve: Curve) -> Result<EcPublicK
Curve::Ed25519 => Ok(EcPublicKey::Ed25519(
ed25519_dalek::VerifyingKey::from_bytes(bytes.try_into()?)?,
)),
Curve::P384 => {
let encoded_point =
p384::EncodedPoint::from_bytes(bytes).map_err(|_| EcError::EcKeyInvalidKeyData)?;

let key_option: Option<p384::PublicKey> =
p384::PublicKey::from_encoded_point(&encoded_point).into();

let key = key_option.ok_or_else(|| EcError::EcKeyInvalidKeyData)?;

Ok(EcPublicKey::P384(key))
}
_ => Err(EcError::UnsupportedCurve),
}
}
Expand All @@ -118,6 +132,7 @@ pub fn pub_key_to_uncompressed(key: &EcPublicKey) -> Result<Vec<u8>, EcError> {
EcPublicKey::X25519(key) => Ok(key.to_bytes().to_vec()),
EcPublicKey::Ed25519(key) => Ok(key.to_bytes().to_vec()),
EcPublicKey::P256(key) => Ok(key.as_affine().to_encoded_point(false).as_bytes().to_vec()),
EcPublicKey::P384(key) => Ok(key.as_affine().to_encoded_point(false).as_bytes().to_vec()),
}
}

Expand All @@ -130,6 +145,7 @@ pub fn generate_private_key(curve: Curve) -> Result<EcPrivateKey, EcError> {
Curve::Ed25519 => Ok(EcPrivateKey::Ed25519(ed25519_dalek::SigningKey::generate(
&mut OsRng,
))),
Curve::P384 => Ok(EcPrivateKey::P384(p384::SecretKey::random(&mut OsRng))),
_ => Err(EcError::UnsupportedCurve),
}
}
Expand All @@ -144,6 +160,9 @@ pub fn private_key_from_bytes(bytes: &[u8], curve: Curve) -> Result<EcPrivateKey
.map_err(|_| EcError::EcKeyInvalidKeyData)
.map(|bytes: &[u8; 32]| EcPrivateKey::X25519(x25519_dalek::StaticSecret::from(*bytes))),
Curve::Ed25519 => ed25519_private_from_bytes(bytes),
Curve::P384 => p384::SecretKey::from_slice(bytes)
.map_err(|_| EcError::EcKeyInvalidKeyData)
.map(EcPrivateKey::P384),
_ => Err(EcError::UnsupportedCurve),
}
}
Expand All @@ -158,6 +177,7 @@ pub fn private_key_to_bytes(key: &EcPrivateKey) -> Result<Vec<u8>, EcError> {
EcPrivateKey::X25519(key) => Ok(key.to_bytes().to_vec()),
EcPrivateKey::Ed25519(key) => Ok(key.to_keypair_bytes().to_vec()),
EcPrivateKey::P256(key) => Ok(key.to_bytes().to_vec()),
EcPrivateKey::P384(key) => Ok(key.to_bytes().to_vec()),
}
}

Expand All @@ -166,6 +186,7 @@ pub fn private_key_to_public(private_key: &EcPrivateKey) -> Result<EcPublicKey,
EcPrivateKey::X25519(key) => Ok(EcPublicKey::X25519(x25519_dalek::PublicKey::from(key))),
EcPrivateKey::Ed25519(key) => Ok(EcPublicKey::Ed25519(key.verifying_key())),
EcPrivateKey::P256(key) => Ok(EcPublicKey::P256(key.public_key())),
EcPrivateKey::P384(key) => Ok(EcPublicKey::P384(key.public_key())),
}
}

Expand All @@ -181,6 +202,18 @@ fn ecdh_p256(
Ok(shared_secret.raw_secret_bytes().to_vec())
}

fn ecdh_p384(
private_key: &p384::SecretKey,
public_key: &p384::PublicKey,
) -> Result<Vec<u8>, EcError> {
let shared_secret = p384::elliptic_curve::ecdh::diffie_hellman(
private_key.to_nonzero_scalar(),
public_key.as_affine(),
);

Ok(shared_secret.raw_secret_bytes().to_vec())
}

fn ecdh_x25519(
private_key: &x25519_dalek::StaticSecret,
public_key: &x25519_dalek::PublicKey,
Expand Down Expand Up @@ -208,6 +241,13 @@ pub fn private_key_ecdh(
Err(EcError::EcdhKeyTypeMismatch)
}
}
EcPrivateKey::P384(private_key) => {
if let EcPublicKey::P384(remote_public) = remote_public {
ecdh_p384(private_key, remote_public)
} else {
Err(EcError::EcdhKeyTypeMismatch)
}
}
}?;

Ok(shared_secret)
Expand All @@ -222,6 +262,15 @@ pub fn sign_p256(private_key: &p256::SecretKey, data: &[u8]) -> Result<Vec<u8>,
Ok(signature.to_der().to_bytes().to_vec())
}

pub fn sign_p384(private_key: &p384::SecretKey, data: &[u8]) -> Result<Vec<u8>, EcError> {
let signing_key = p384::ecdsa::SigningKey::from(private_key);

let signature: p384::ecdsa::Signature =
p384::ecdsa::signature::Signer::sign(&signing_key, data);

Ok(signature.to_der().to_bytes().to_vec())
}

pub fn sign_ed25519(key: &ed25519_dalek::SigningKey, data: &[u8]) -> Result<Vec<u8>, EcError> {
Ok(key.sign(data).to_bytes().to_vec())
}
Expand All @@ -240,6 +289,20 @@ pub fn verify_p256(
Ok(is_valid)
}

pub fn verify_p384(
public_key: &p384::PublicKey,
signature: &[u8],
data: &[u8],
) -> Result<bool, EcError> {
let verifying_key = p384::ecdsa::VerifyingKey::from(public_key);
let signature = p384::ecdsa::Signature::from_der(signature)?;

let is_valid =
p384::ecdsa::signature::Verifier::verify(&verifying_key, data, &signature).is_ok();

Ok(is_valid)
}

pub fn verify_ed25519(
public_key: &ed25519_dalek::VerifyingKey,
signature: &[u8],
Expand Down
4 changes: 4 additions & 0 deletions mls-rs-crypto-rustcrypto/src/ec_for_x509.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ pub fn pub_key_to_spki(key: &EcPublicKey) -> Result<Vec<u8>, EcX509Error> {
.to_public_key_der()
.map_err(|_| EcX509Error::NistSpkiError)?
.to_vec()),
EcPublicKey::P384(key) => Ok(key
.to_public_key_der()
.map_err(|_| EcX509Error::NistSpkiError)?
.to_vec()),
}
}

Expand Down
6 changes: 4 additions & 2 deletions mls-rs-crypto-rustcrypto/src/ec_signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

use crate::ec::{
generate_keypair, private_key_bytes_to_public, private_key_from_bytes,
pub_key_from_uncompressed, sign_ed25519, sign_p256, verify_ed25519, verify_p256, EcError,
EcPrivateKey, EcPublicKey,
pub_key_from_uncompressed, sign_ed25519, sign_p256, sign_p384, verify_ed25519, verify_p256,
verify_p384, EcError, EcPrivateKey, EcPublicKey,
};
use alloc::vec::Vec;
use core::ops::Deref;
Expand Down Expand Up @@ -74,6 +74,7 @@ impl EcSigner {
EcPrivateKey::X25519(_) => Err(EcSignerError::EcKeyNotSignature),
EcPrivateKey::Ed25519(private_key) => Ok(sign_ed25519(&private_key, data)?),
EcPrivateKey::P256(private_key) => Ok(sign_p256(&private_key, data)?),
EcPrivateKey::P384(private_key) => Ok(sign_p384(&private_key, data)?),
}
}

Expand All @@ -89,6 +90,7 @@ impl EcSigner {
EcPublicKey::X25519(_) => Err(EcSignerError::EcKeyNotSignature),
EcPublicKey::Ed25519(key) => Ok(verify_ed25519(&key, signature, data)?),
EcPublicKey::P256(key) => Ok(verify_p256(&key, signature, data)?),
EcPublicKey::P384(key) => Ok(verify_p384(&key, signature, data)?),
}?;

ver.then_some(()).ok_or(EcSignerError::InvalidSignature)
Expand Down
1 change: 1 addition & 0 deletions mls-rs-crypto-rustcrypto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ impl RustCryptoProvider {
pub fn all_supported_cipher_suites() -> Vec<CipherSuite> {
vec![
CipherSuite::P256_AES128,
CipherSuite::P384_AES256,
CipherSuite::CURVE25519_AES128,
CipherSuite::CURVE25519_CHACHA,
]
Expand Down

0 comments on commit b3f2ed4

Please sign in to comment.