Skip to content

Commit

Permalink
feat: Full p521 support
Browse files Browse the repository at this point in the history
  • Loading branch information
OtaK committed Apr 16, 2024
1 parent 58fed9f commit 7f01620
Show file tree
Hide file tree
Showing 13 changed files with 228 additions and 141 deletions.
1 change: 1 addition & 0 deletions basic_credential/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ serde = "1.0"
ed25519-dalek = { version = "2.0.0-rc.3", features = ["rand_core"] }
p256 = "0.13"
p384 = "0.13"
p521 = "0.13"
secrecy = { version = "0.8", features = ["serde"] }
rand_core = "0.6"
getrandom = { version = "0.2", features = ["js"] }
Expand Down
31 changes: 26 additions & 5 deletions basic_credential/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,14 @@ impl SignatureKeyPair {
let pk = sk.verifying_key().to_encoded_point(false).to_bytes().into();
(sk.to_bytes().to_vec().into(), pk)
}
SignatureScheme::ECDSA_SECP521R1_SHA512 => {
let sk = p521::ecdsa::SigningKey::random(csprng);
let pk = p521::ecdsa::VerifyingKey::from(&sk)
.to_encoded_point(false)
.to_bytes()
.into();
(sk.to_bytes().to_vec().into(), pk)
}
SignatureScheme::ED25519 => {
let sk = ed25519_dalek::SigningKey::generate(csprng);
let pk = sk.verifying_key();
Expand Down Expand Up @@ -159,31 +167,43 @@ impl SignatureKeyPair {
&private[..ed25519_dalek::SECRET_KEY_LENGTH],
)
.map_err(|_| CryptoError::InvalidKey)?;
let pk = ed25519_dalek::VerifyingKey::try_from(&public[..])
let pk = ed25519_dalek::VerifyingKey::try_from(public.as_slice())
.map_err(|_| CryptoError::InvalidKey)?;

if sk.verifying_key() != pk {
return Err(CryptoError::MismatchKeypair);
}
}
SignatureScheme::ECDSA_SECP256R1_SHA256 => {
let sk = p256::ecdsa::SigningKey::try_from(&private[..])
let sk = p256::ecdsa::SigningKey::from_slice(&private)
.map_err(|_| CryptoError::InvalidKey)?;
let pk = p256::ecdsa::VerifyingKey::try_from(&public[..])
let pk = p256::ecdsa::VerifyingKey::from_sec1_bytes(&public)
.map_err(|_| CryptoError::InvalidKey)?;
if sk.verifying_key() != &pk {
return Err(CryptoError::MismatchKeypair);
}
}
SignatureScheme::ECDSA_SECP384R1_SHA384 => {
let sk = p384::ecdsa::SigningKey::try_from(&private[..])
let sk = p384::ecdsa::SigningKey::from_slice(&private)
.map_err(|_| CryptoError::InvalidKey)?;
let pk = p384::ecdsa::VerifyingKey::try_from(&public[..])

let pk = p384::ecdsa::VerifyingKey::from_sec1_bytes(&public)
.map_err(|_| CryptoError::InvalidKey)?;
dbg!(&pk);
if sk.verifying_key() != &pk {
return Err(CryptoError::MismatchKeypair);
}
}
SignatureScheme::ECDSA_SECP521R1_SHA512 => {
let sk = p521::ecdsa::SigningKey::from_slice(&private[..])
.map_err(|_| CryptoError::InvalidKey)?;
let pk = p521::ecdsa::VerifyingKey::from_sec1_bytes(&public[..])
.map_err(|_| CryptoError::InvalidKey)?;
let sk_pk = p521::ecdsa::VerifyingKey::from(&sk);
if sk_pk.to_encoded_point(false) != pk.to_encoded_point(false) {
return Err(CryptoError::MismatchKeypair);
}
}
_ => {}
};

Expand Down Expand Up @@ -238,6 +258,7 @@ pub mod tests {
SignatureScheme::ED25519,
SignatureScheme::ECDSA_SECP256R1_SHA256,
SignatureScheme::ECDSA_SECP384R1_SHA384,
SignatureScheme::ECDSA_SECP521R1_SHA512,
];
for scheme in schemes {
let kp = SignatureKeyPair::new(scheme, &mut rand::thread_rng()).unwrap();
Expand Down
1 change: 1 addition & 0 deletions openmls/src/group/public_group/diff/compute_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ impl<'a> PublicGroupDiff<'a> {
Ciphersuite::MLS_128_DHKEMP256_AES128GCM_SHA256_P256,
Ciphersuite::MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519,
Ciphersuite::MLS_256_DHKEMP384_AES256GCM_SHA384_P384,
Ciphersuite::MLS_256_DHKEMP521_AES256GCM_SHA512_P521,
Ciphersuite::MLS_128_X25519KYBER768DRAFT00_AES128GCM_SHA256_Ed25519,
]),
Some(&[]),
Expand Down
29 changes: 7 additions & 22 deletions openmls/src/group/tests/test_proposal_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1455,28 +1455,13 @@ async fn test_valsem107(ciphersuite: Ciphersuite, backend: &impl OpenMlsCryptoPr
// expected.
let bob_leaf_index = bob_group.own_leaf_index();

let ref_propose = {
// We first go the manual route
let (ref_propose1, _) = alice_group
.propose_remove_member(
backend,
&alice_credential_with_key_and_signer.signer,
bob_leaf_index,
)
.unwrap();

let (ref_propose2, _) = alice_group
.propose_remove_member(
backend,
&alice_credential_with_key_and_signer.signer,
bob_leaf_index,
)
.unwrap();

assert_eq!(ref_propose1, ref_propose2);

ref_propose1
};
let (ref_propose, _) = alice_group
.propose_remove_member(
backend,
&alice_credential_with_key_and_signer.signer,
bob_leaf_index,
)
.unwrap();

// While this shouldn't fail, it should produce a valid commit, i.e. one
// that contains only one remove proposal.
Expand Down
4 changes: 4 additions & 0 deletions openmls/src/test_utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,9 @@ pub async fn backends(backend: &impl OpenMlsCryptoProvider) {}
case::MLS_256_DHKEMP384_AES256GCM_SHA384_P384(
Ciphersuite::MLS_256_DHKEMP384_AES256GCM_SHA384_P384
),
case::MLS_256_DHKEMP521_AES256GCM_SHA512_P521(
Ciphersuite::MLS_256_DHKEMP521_AES256GCM_SHA512_P521
),
case::MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519(
Ciphersuite::MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519
),
Expand All @@ -247,6 +250,7 @@ pub async fn ciphersuites(ciphersuite: Ciphersuite) {}
case::rust_crypto_MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519(Ciphersuite::MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519, &OpenMlsRustCrypto::default()),
case::rust_crypto_MLS_128_DHKEMP256_AES128GCM_SHA256_P256(Ciphersuite::MLS_128_DHKEMP256_AES128GCM_SHA256_P256, &OpenMlsRustCrypto::default()),
case::rust_crypto_MLS_256_DHKEMP384_AES256GCM_SHA384_P384(Ciphersuite::MLS_256_DHKEMP384_AES256GCM_SHA384_P384, &OpenMlsRustCrypto::default()),
case::rust_crypto_MLS_256_DHKEMP521_AES256GCM_SHA512_P521(Ciphersuite::MLS_256_DHKEMP521_AES256GCM_SHA512_P521, &OpenMlsRustCrypto::default()),
case::rust_crypto_MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519(Ciphersuite::MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519, &OpenMlsRustCrypto::default()),
case::rust_crypto_MLS_128_X25519KYBER768DRAFT00_AES128GCM_SHA256_Ed25519(Ciphersuite::MLS_128_X25519KYBER768DRAFT00_AES128GCM_SHA256_Ed25519, &OpenMlsRustCrypto::default()),
)
Expand Down
146 changes: 65 additions & 81 deletions openmls/src/tree/tests_and_kats/kats/kat_message_protection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,28 +82,44 @@ use crate::{
pub struct MessageProtectionTest {
cipher_suite: u16,

group_id: String,
#[serde(with = "hex::serde")]
group_id: Vec<u8>,
epoch: u64,
tree_hash: String,
confirmed_transcript_hash: String,

signature_priv: String,
signature_pub: String,

encryption_secret: String,
sender_data_secret: String,
membership_key: String,

proposal: String,
proposal_pub: String,
proposal_priv: String,

commit: String,
commit_pub: String,
commit_priv: String,

application: String,
application_priv: String,
#[serde(with = "hex::serde")]
tree_hash: Vec<u8>,
#[serde(with = "hex::serde")]
confirmed_transcript_hash: Vec<u8>,

#[serde(with = "hex::serde")]
signature_priv: Vec<u8>,
#[serde(with = "hex::serde")]
signature_pub: Vec<u8>,

#[serde(with = "hex::serde")]
encryption_secret: Vec<u8>,
#[serde(with = "hex::serde")]
sender_data_secret: Vec<u8>,
#[serde(with = "hex::serde")]
membership_key: Vec<u8>,

#[serde(with = "hex::serde")]
proposal: Vec<u8>,
#[serde(with = "hex::serde")]
proposal_pub: Vec<u8>,
#[serde(with = "hex::serde")]
proposal_priv: Vec<u8>,

#[serde(with = "hex::serde")]
commit: Vec<u8>,
#[serde(with = "hex::serde")]
commit_pub: Vec<u8>,
#[serde(with = "hex::serde")]
commit_priv: Vec<u8>,

#[serde(with = "hex::serde")]
application: Vec<u8>,
#[serde(with = "hex::serde")]
application_priv: Vec<u8>,
}

async fn generate_credential(
Expand Down Expand Up @@ -200,36 +216,24 @@ pub async fn run_test_vector(
.supported_ciphersuites()
.contains(&ciphersuite)
{
log::debug!("Skipping unsupported ciphersuite {:?}", ciphersuite);
log::warn!("Skipping unsupported ciphersuite {:?}", ciphersuite);
return Ok(());
}
log::debug!("Testing tv with ciphersuite {:?}", ciphersuite);
log::info!("Testing tv with ciphersuite {:?}", ciphersuite);

let group_context = GroupContext::new(
ciphersuite,
GroupId::from_slice(&hex_to_bytes(&test.group_id)),
GroupId::from_slice(&test.group_id),
test.epoch,
hex_to_bytes(&test.tree_hash),
hex_to_bytes(&test.confirmed_transcript_hash),
test.tree_hash.clone(),
test.confirmed_transcript_hash.clone(),
Extensions::empty(),
);

let sender_index = LeafNodeIndex::new(1);

// Set up the group, unfortunately we can't do without.
let signature_private_key = match ciphersuite {
Ciphersuite::MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519
| Ciphersuite::MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519 => {
let mut private = hex_to_bytes(&test.signature_priv);
private.append(&mut hex_to_bytes(&test.signature_pub));
private
}
Ciphersuite::MLS_128_DHKEMP256_AES128GCM_SHA256_P256
| Ciphersuite::MLS_256_DHKEMP384_AES256GCM_SHA384_P384 => {
hex_to_bytes(&test.signature_priv)
}
_ => unimplemented!(),
};
let signature_private_key = test.signature_priv.clone();
let random_own_signature_key = SignatureKeyPair::new(
ciphersuite.signature_algorithm(),
&mut *backend.rand().borrow_rand().unwrap(),
Expand All @@ -251,28 +255,16 @@ pub async fn run_test_vector(
) -> CoreGroup {
let group_context = GroupContext::new(
ciphersuite,
GroupId::from_slice(&hex_to_bytes(&test.group_id)),
GroupId::from_slice(&test.group_id),
test.epoch,
hex_to_bytes(&test.tree_hash),
hex_to_bytes(&test.confirmed_transcript_hash),
test.tree_hash.clone(),
test.confirmed_transcript_hash.clone(),
Extensions::empty(),
);

// Set up the group, unfortunately we can't do without.
let credential = Credential::new_basic(b"This is not needed".to_vec());
let signature_private_key = match ciphersuite {
Ciphersuite::MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519
| Ciphersuite::MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519 => {
let mut private = hex_to_bytes(&test.signature_priv);
private.append(&mut hex_to_bytes(&test.signature_pub));
private
}
Ciphersuite::MLS_128_DHKEMP256_AES128GCM_SHA256_P256
| Ciphersuite::MLS_256_DHKEMP384_AES256GCM_SHA384_P384 => {
hex_to_bytes(&test.signature_priv)
}
_ => unimplemented!(),
};

let random_own_signature_key = SignatureKeyPair::new(
ciphersuite.signature_algorithm(),
&mut *backend.rand().borrow_rand().unwrap(),
Expand All @@ -281,7 +273,7 @@ pub async fn run_test_vector(
let random_own_signature_key = random_own_signature_key.public();
let signer = SignatureKeyPair::from_raw(
ciphersuite.signature_algorithm(),
signature_private_key,
test.signature_priv.clone(),
random_own_signature_key.to_vec(),
);

Expand Down Expand Up @@ -309,7 +301,7 @@ pub async fn run_test_vector(
ciphersuite,
CredentialWithKey {
credential,
signature_key: hex_to_bytes(&test.signature_pub).into(),
signature_key: test.signature_pub.clone().into(),
},
)
.await;
Expand Down Expand Up @@ -347,7 +339,7 @@ pub async fn run_test_vector(
// Inject the test values into the group

let encryption_secret = EncryptionSecret::from_slice(
&hex_to_bytes(&test.encryption_secret),
&&test.encryption_secret,
group_context.protocol_version(),
ciphersuite,
);
Expand All @@ -372,12 +364,12 @@ pub async fn run_test_vector(
}
message_secrets.set_serialized_context(serialized_group_context);
*message_secrets.sender_data_secret_mut() = SenderDataSecret::from_slice(
&hex_to_bytes(&test.sender_data_secret),
&&test.sender_data_secret,
ProtocolVersion::Mls10,
ciphersuite,
);
message_secrets.set_membership_key(Secret::from_slice(
&hex_to_bytes(&test.membership_key),
&&test.membership_key,
ProtocolVersion::Mls10,
ciphersuite,
));
Expand All @@ -387,11 +379,9 @@ pub async fn run_test_vector(

// Proposal
{
let proposal = ProposalIn::tls_deserialize_exact(hex_to_bytes(&test.proposal)).unwrap();
let proposal_pub =
MlsMessageIn::tls_deserialize_exact(hex_to_bytes(&test.proposal_pub)).unwrap();
let proposal_priv =
MlsMessageIn::tls_deserialize_exact(hex_to_bytes(&test.proposal_priv)).unwrap();
let proposal = ProposalIn::tls_deserialize_exact(&test.proposal).unwrap();
let proposal_pub = MlsMessageIn::tls_deserialize_exact(&test.proposal_pub).unwrap();
let proposal_priv = MlsMessageIn::tls_deserialize_exact(&test.proposal_priv).unwrap();

async fn test_proposal_pub(
mut group: CoreGroup,
Expand Down Expand Up @@ -533,11 +523,9 @@ pub async fn run_test_vector(

// Commit
{
let commit = CommitIn::tls_deserialize_exact(hex_to_bytes(&test.commit)).unwrap();
let commit_pub =
MlsMessageIn::tls_deserialize_exact(hex_to_bytes(&test.commit_pub)).unwrap();
let commit_priv =
MlsMessageIn::tls_deserialize_exact(hex_to_bytes(&test.commit_priv)).unwrap();
let commit = CommitIn::tls_deserialize_exact(&test.commit).unwrap();
let commit_pub = MlsMessageIn::tls_deserialize_exact(&test.commit_pub).unwrap();
let commit_priv = MlsMessageIn::tls_deserialize_exact(&test.commit_priv).unwrap();

async fn test_commit_pub(
mut group: CoreGroup,
Expand Down Expand Up @@ -704,9 +692,8 @@ pub async fn run_test_vector(

// Application
{
let application = hex_to_bytes(&test.application);
let application_priv =
MlsMessageIn::tls_deserialize_exact(hex_to_bytes(&test.application_priv)).unwrap();
let application = &test.application;
let application_priv = MlsMessageIn::tls_deserialize_exact(&test.application_priv).unwrap();

async fn test_application_priv(
mut group: CoreGroup,
Expand Down Expand Up @@ -762,23 +749,20 @@ pub async fn run_test_vector(
.await;
}

log::trace!("Finished test verification");
log::info!("Finished test verification");

Ok(())
}

#[apply(backends)]
async fn read_test_vectors_mp(backend: &impl OpenMlsCryptoProvider) {
let _ = pretty_env_logger::try_init();
log::debug!("Reading test vectors ...");
log::info!("Reading test vectors ...");

let tests: Vec<MessageProtectionTest> = read("test_vectors/message-protection.json");

for test_vector in tests {
match run_test_vector(test_vector, backend).await {
Ok(_) => {}
Err(e) => panic!("Error while checking message protection test vector.\n{e:?}"),
}
for test_vector in tests.into_iter() {
run_test_vector(test_vector, backend).await.unwrap();
}
log::trace!("Finished test vector verification");
log::info!("Finished test vector verification");
}
Loading

0 comments on commit 7f01620

Please sign in to comment.