Loading security/authgraph/aidl/vts/functional/lib.rs +7 −41 Original line number Diff line number Diff line Loading @@ -24,22 +24,19 @@ use android_hardware_security_authgraph::aidl::android::hardware::security::auth PlainPubKey::PlainPubKey, PubKey::PubKey, SessionIdSignature::SessionIdSignature, }; use authgraph_boringssl as boring; use authgraph_core::keyexchange as ke; use authgraph_core::{arc, key, traits}; use authgraph_nonsecure::StdClock; use authgraph_core::{error::Error as AgError, keyexchange as ke}; use coset::CborSerializable; pub mod sink; pub mod source; /// Return a collection of AuthGraph trait implementations suitable for testing. pub fn test_impls() -> traits::TraitImpl { // Note that the local implementation is using a clock with a potentially different epoch than // the implementation under test. boring::trait_impls( /// Return an AuthGraphParticipant suitable for testing. pub fn test_ag_participant() -> Result<ke::AuthGraphParticipant, AgError> { Ok(ke::AuthGraphParticipant::new( boring::crypto_trait_impls(), Box::<boring::test_device::AgDevice>::default(), Some(Box::new(StdClock::default())), ) ke::MAX_OPENED_SESSIONS, )?) } fn build_plain_pub_key(pub_key: &Option<Vec<u8>>) -> PubKey { Loading @@ -56,14 +53,6 @@ fn extract_plain_pub_key(pub_key: &Option<PubKey>) -> &PlainPubKey { } } fn verification_key_from_identity(impls: &traits::TraitImpl, identity: &[u8]) -> key::EcVerifyKey { let identity = key::Identity::from_slice(identity).expect("invalid identity CBOR"); impls .device .process_peer_cert_chain(&identity.cert_chain, &*impls.ecdsa) .expect("failed to extract signing key") } fn vec_to_identity(data: &[u8]) -> Identity { Identity { identity: data.to_vec(), Loading @@ -75,26 +64,3 @@ fn vec_to_signature(data: &[u8]) -> SessionIdSignature { signature: data.to_vec(), } } /// Decrypt a pair of AES-256 keys encrypted with the AuthGraph PBK. pub fn decipher_aes_keys(imp: &traits::TraitImpl, arc: &[Vec<u8>; 2]) -> [key::AesKey; 2] { [ decipher_aes_key(imp, &arc[0]), decipher_aes_key(imp, &arc[1]), ] } /// Decrypt an AES-256 key encrypted with the AuthGraph PBK. pub fn decipher_aes_key(imp: &traits::TraitImpl, arc: &[u8]) -> key::AesKey { let pbk = imp.device.get_per_boot_key().expect("no PBK available"); let arc::ArcContent { payload, protected_headers: _, unprotected_headers: _, } = arc::decipher_arc(&pbk, arc, &*imp.aes_gcm).expect("failed to decrypt arc"); assert_eq!(payload.0.len(), 32); let mut key = key::AesKey([0; 32]); key.0.copy_from_slice(&payload.0); assert_ne!(key.0, [0; 32], "agreed AES-256 key should be non-zero"); key } security/authgraph/aidl/vts/functional/role_test.rs +12 −12 Original line number Diff line number Diff line Loading @@ -48,31 +48,31 @@ macro_rules! require_nonsecure { #[test] fn test_nonsecure_source_mainline() { let mut impls = vts::test_impls(); vts::source::test_mainline(&mut impls, require_nonsecure!()); let mut sink = vts::test_ag_participant().expect("failed to create a local sink"); vts::source::test_mainline(&mut sink, require_nonsecure!()); } #[test] fn test_nonsecure_source_corrupt_sig() { let mut impls = vts::test_impls(); vts::source::test_corrupt_sig(&mut impls, require_nonsecure!()); let mut sink = vts::test_ag_participant().expect("failed to create a local sink"); vts::source::test_corrupt_sig(&mut sink, require_nonsecure!()); } #[test] fn test_nonsecure_source_corrupt_keys() { let mut impls = vts::test_impls(); vts::source::test_corrupt_key(&mut impls, require_nonsecure!()); let mut sink = vts::test_ag_participant().expect("failed to create a local sink"); vts::source::test_corrupt_key(&mut sink, require_nonsecure!()); } #[test] fn test_nonsecure_sink_mainline() { let mut impls = vts::test_impls(); vts::sink::test_mainline(&mut impls, require_nonsecure!()); let mut source = vts::test_ag_participant().expect("failed to create a local source"); vts::sink::test_mainline(&mut source, require_nonsecure!()); } #[test] fn test_nonsecure_sink_corrupt_sig() { let mut impls = vts::test_impls(); vts::sink::test_corrupt_sig(&mut impls, require_nonsecure!()); let mut source = vts::test_ag_participant().expect("failed to create a local source"); vts::sink::test_corrupt_sig(&mut source, require_nonsecure!()); } #[test] fn test_nonsecure_sink_corrupt_keys() { let mut impls = vts::test_impls(); vts::sink::test_corrupt_keys(&mut impls, require_nonsecure!()); let mut source = vts::test_ag_participant().expect("failed to create a local source"); vts::sink::test_corrupt_keys(&mut source, require_nonsecure!()); } security/authgraph/aidl/vts/functional/sink.rs +80 −61 Original line number Diff line number Diff line Loading @@ -16,23 +16,28 @@ //! VTS tests for sinks use super::*; use authgraph_core::traits; use authgraph_core::{key, keyexchange as ke}; /// Run AuthGraph tests against the provided sink, using a local test source implementation. pub fn test(impls: &mut traits::TraitImpl, sink: binder::Strong<dyn IAuthGraphKeyExchange>) { test_mainline(impls, sink.clone()); test_corrupt_sig(impls, sink.clone()); test_corrupt_keys(impls, sink); pub fn test( local_source: &mut ke::AuthGraphParticipant, sink: binder::Strong<dyn IAuthGraphKeyExchange>, ) { test_mainline(local_source, sink.clone()); test_corrupt_sig(local_source, sink.clone()); test_corrupt_keys(local_source, sink); } /// Perform mainline AuthGraph key exchange with the provided sink and local implementation. /// Return the agreed AES keys in plaintext. pub fn test_mainline( impls: &mut traits::TraitImpl, local_source: &mut ke::AuthGraphParticipant, sink: binder::Strong<dyn IAuthGraphKeyExchange>, ) -> [key::AesKey; 2] { // Step 1: create an ephemeral ECDH key at the (local) source. let source_init_info = ke::create(impls).expect("failed to create() with local impl"); let source_init_info = local_source .create() .expect("failed to create() with local impl"); // Step 2: pass the source's ECDH public key and other session info to the (remote) sink. let init_result = sink Loading @@ -50,20 +55,21 @@ pub fn test_mainline( assert!(!sink_info.sessionId.is_empty()); // The AuthGraph core library will verify the session ID signature, but do it here too. let sink_verification_key = verification_key_from_identity(&impls, &sink_init_info.identity.identity); ke::verify_signature_on_session_id( let sink_verification_key = local_source .peer_verification_key_from_identity(&sink_init_info.identity.identity) .expect("failed to get peer verification from identity"); local_source .verify_signature_on_session_id( &sink_verification_key, &sink_info.sessionId, &sink_info.signature.signature, &*impls.ecdsa, ) .expect("failed verification of signed session ID"); // Step 3: pass the sink's ECDH public key and other session info to the (local) source, so it // can calculate the same pair of symmetric keys. let source_info = ke::finish( impls, let source_info = local_source .finish( &sink_pub_key.plainPubKey, &sink_init_info.identity.identity, &sink_info.signature.signature, Loading @@ -75,13 +81,15 @@ pub fn test_mainline( assert!(!source_info.session_id.is_empty()); // The AuthGraph core library will verify the session ID signature, but do it here too. let source_verification_key = verification_key_from_identity(&impls, &source_init_info.identity); ke::verify_signature_on_session_id( let source_verification_key = key::Identity::from_slice(&source_init_info.identity) .expect("invalid identity CBOR") .cert_chain .root_key; local_source .verify_signature_on_session_id( &source_verification_key, &source_info.session_id, &source_info.session_id_signature, &*impls.ecdsa, ) .expect("failed verification of signed session ID"); Loading @@ -96,19 +104,28 @@ pub fn test_mainline( &sink_info.sharedKeys, ) .expect("failed to authenticationComplete() with remote sink"); // Decrypt and return the session keys. decipher_aes_keys(&impls, &source_info.shared_keys) let decrypted_shared_keys = local_source .decipher_shared_keys_from_arcs(&source_info.shared_keys) .expect("failed to decrypt shared key arcs") .try_into(); let decrypted_shared_keys_array = match decrypted_shared_keys { Ok(array) => array, Err(_) => panic!("wrong number of decrypted shared key arcs"), }; decrypted_shared_keys_array } /// Perform mainline AuthGraph key exchange with the provided sink, but provide an invalid /// session ID signature. pub fn test_corrupt_sig( impls: &mut traits::TraitImpl, local_source: &mut ke::AuthGraphParticipant, sink: binder::Strong<dyn IAuthGraphKeyExchange>, ) { // Step 1: create an ephemeral ECDH key at the (local) source. let source_init_info = ke::create(impls).expect("failed to create() with local impl"); let source_init_info = local_source .create() .expect("failed to create() with local impl"); // Step 2: pass the source's ECDH public key and other session info to the (remote) sink. let init_result = sink Loading @@ -127,8 +144,8 @@ pub fn test_corrupt_sig( // Step 3: pass the sink's ECDH public key and other session info to the (local) source, so it // can calculate the same pair of symmetric keys. let source_info = ke::finish( impls, let source_info = local_source .finish( &sink_pub_key.plainPubKey, &sink_init_info.identity.identity, &sink_info.signature.signature, Loading Loading @@ -158,11 +175,13 @@ pub fn test_corrupt_sig( /// Perform mainline AuthGraph key exchange with the provided sink, but provide an invalid /// Arc for the sink's key. pub fn test_corrupt_keys( impls: &mut traits::TraitImpl, local_source: &mut ke::AuthGraphParticipant, sink: binder::Strong<dyn IAuthGraphKeyExchange>, ) { // Step 1: create an ephemeral ECDH key at the (local) source. let source_init_info = ke::create(impls).expect("failed to create() with local impl"); let source_init_info = local_source .create() .expect("failed to create() with local impl"); // Step 2: pass the source's ECDH public key and other session info to the (remote) sink. let init_result = sink Loading @@ -181,8 +200,8 @@ pub fn test_corrupt_keys( // Step 3: pass the sink's ECDH public key and other session info to the (local) source, so it // can calculate the same pair of symmetric keys. let source_info = ke::finish( impls, let source_info = local_source .finish( &sink_pub_key.plainPubKey, &sink_init_info.identity.identity, &sink_info.signature.signature, Loading security/authgraph/aidl/vts/functional/source.rs +79 −65 Original line number Diff line number Diff line Loading @@ -16,19 +16,22 @@ //! VTS tests for sources use super::*; use authgraph_core::traits; use authgraph_core::{key, keyexchange as ke}; /// Run AuthGraph tests against the provided source, using a local test sink implementation. pub fn test(impls: &mut traits::TraitImpl, source: binder::Strong<dyn IAuthGraphKeyExchange>) { test_mainline(impls, source.clone()); test_corrupt_sig(impls, source.clone()); test_corrupt_key(impls, source); pub fn test( local_sink: &mut ke::AuthGraphParticipant, source: binder::Strong<dyn IAuthGraphKeyExchange>, ) { test_mainline(local_sink, source.clone()); test_corrupt_sig(local_sink, source.clone()); test_corrupt_key(local_sink, source); } /// Perform mainline AuthGraph key exchange with the provided source. /// Return the agreed AES keys in plaintext. pub fn test_mainline( impls: &mut traits::TraitImpl, local_sink: &mut ke::AuthGraphParticipant, source: binder::Strong<dyn IAuthGraphKeyExchange>, ) -> [key::AesKey; 2] { // Step 1: create an ephemeral ECDH key at the (remote) source. Loading @@ -40,8 +43,8 @@ pub fn test_mainline( let source_pub_key = extract_plain_pub_key(&source_init_info.key.pubKey); // Step 2: pass the source's ECDH public key and other session info to the (local) sink. let init_result = ke::init( impls, let init_result = local_sink .init( &source_pub_key.plainPubKey, &source_init_info.identity.identity, &source_init_info.nonce, Loading @@ -58,12 +61,15 @@ pub fn test_mainline( assert!(!sink_info.session_id.is_empty()); // The AuthGraph core library will verify the session ID signature, but do it here too. let sink_verification_key = verification_key_from_identity(&impls, &sink_init_info.identity); ke::verify_signature_on_session_id( let sink_verification_key = key::Identity::from_slice(&sink_init_info.identity) .expect("invalid identity CBOR") .cert_chain .root_key; local_sink .verify_signature_on_session_id( &sink_verification_key, &sink_info.session_id, &sink_info.session_id_signature, &*impls.ecdsa, ) .expect("failed verification of signed session ID"); Loading @@ -86,13 +92,14 @@ pub fn test_mainline( assert!(!source_info.sessionId.is_empty()); // The AuthGraph core library will verify the session ID signature, but do it here too. let source_verification_key = verification_key_from_identity(&impls, &source_init_info.identity.identity); ke::verify_signature_on_session_id( let source_verification_key = local_sink .peer_verification_key_from_identity(&source_init_info.identity.identity) .expect("failed to get peer verification from identity"); local_sink .verify_signature_on_session_id( &source_verification_key, &source_info.sessionId, &source_info.signature.signature, &*impls.ecdsa, ) .expect("failed verification of signed session ID"); Loading @@ -101,21 +108,25 @@ pub fn test_mainline( // Step 4: pass the (remote) source's session ID signature back to the sink, so it can check it // and update the symmetric keys so they're marked as authentication complete. let sink_arcs = ke::authentication_complete( impls, &source_info.signature.signature, sink_info.shared_keys, ) let sink_arcs = local_sink .authentication_complete(&source_info.signature.signature, sink_info.shared_keys) .expect("failed to authenticationComplete() with local sink"); // Decrypt and return the session keys. decipher_aes_keys(&impls, &sink_arcs) let decrypted_shared_keys = local_sink .decipher_shared_keys_from_arcs(&sink_arcs) .expect("failed to decrypt shared key arcs") .try_into(); let decrypted_shared_keys_array = match decrypted_shared_keys { Ok(array) => array, Err(_) => panic!("wrong number of decrypted shared key arcs"), }; decrypted_shared_keys_array } /// Perform mainline AuthGraph key exchange with the provided source, but provide an invalid session /// ID signature. pub fn test_corrupt_sig( impls: &mut traits::TraitImpl, local_sink: &mut ke::AuthGraphParticipant, source: binder::Strong<dyn IAuthGraphKeyExchange>, ) { // Step 1: create an ephemeral ECDH key at the (remote) source. Loading @@ -127,8 +138,8 @@ pub fn test_corrupt_sig( let source_pub_key = extract_plain_pub_key(&source_init_info.key.pubKey); // Step 2: pass the source's ECDH public key and other session info to the (local) sink. let init_result = ke::init( impls, let init_result = local_sink .init( &source_pub_key.plainPubKey, &source_init_info.identity.identity, &source_init_info.nonce, Loading Loading @@ -172,7 +183,7 @@ pub fn test_corrupt_sig( /// Perform mainline AuthGraph key exchange with the provided source, but give it back /// a corrupted key. pub fn test_corrupt_key( impls: &mut traits::TraitImpl, local_sink: &mut ke::AuthGraphParticipant, source: binder::Strong<dyn IAuthGraphKeyExchange>, ) { // Step 1: create an ephemeral ECDH key at the (remote) source. Loading @@ -184,8 +195,8 @@ pub fn test_corrupt_key( let source_pub_key = extract_plain_pub_key(&source_init_info.key.pubKey); // Step 2: pass the source's ECDH public key and other session info to the (local) sink. let init_result = ke::init( impls, let init_result = local_sink .init( &source_pub_key.plainPubKey, &source_init_info.identity.identity, &source_init_info.nonce, Loading @@ -202,12 +213,15 @@ pub fn test_corrupt_key( assert!(!sink_info.session_id.is_empty()); // The AuthGraph core library will verify the session ID signature, but do it here too. let sink_verification_key = verification_key_from_identity(&impls, &sink_init_info.identity); ke::verify_signature_on_session_id( let sink_verification_key = key::Identity::from_slice(&sink_init_info.identity) .expect("invalid identity CBOR") .cert_chain .root_key; local_sink .verify_signature_on_session_id( &sink_verification_key, &sink_info.session_id, &sink_info.session_id_signature, &*impls.ecdsa, ) .expect("failed verification of signed session ID"); Loading security/authgraph/default/src/fuzzer.rs +1 −1 Original line number Diff line number Diff line Loading @@ -25,7 +25,7 @@ use libfuzzer_sys::fuzz_target; use std::sync::{Arc, Mutex}; fuzz_target!(|data: &[u8]| { let local_ta = LocalTa::new(); let local_ta = LocalTa::new().expect("Failed to create an AuthGraph local TA."); let service = AuthGraphService::new_as_binder(Arc::new(Mutex::new(local_ta))); fuzz_service(&mut service.as_binder(), data); }); Loading
security/authgraph/aidl/vts/functional/lib.rs +7 −41 Original line number Diff line number Diff line Loading @@ -24,22 +24,19 @@ use android_hardware_security_authgraph::aidl::android::hardware::security::auth PlainPubKey::PlainPubKey, PubKey::PubKey, SessionIdSignature::SessionIdSignature, }; use authgraph_boringssl as boring; use authgraph_core::keyexchange as ke; use authgraph_core::{arc, key, traits}; use authgraph_nonsecure::StdClock; use authgraph_core::{error::Error as AgError, keyexchange as ke}; use coset::CborSerializable; pub mod sink; pub mod source; /// Return a collection of AuthGraph trait implementations suitable for testing. pub fn test_impls() -> traits::TraitImpl { // Note that the local implementation is using a clock with a potentially different epoch than // the implementation under test. boring::trait_impls( /// Return an AuthGraphParticipant suitable for testing. pub fn test_ag_participant() -> Result<ke::AuthGraphParticipant, AgError> { Ok(ke::AuthGraphParticipant::new( boring::crypto_trait_impls(), Box::<boring::test_device::AgDevice>::default(), Some(Box::new(StdClock::default())), ) ke::MAX_OPENED_SESSIONS, )?) } fn build_plain_pub_key(pub_key: &Option<Vec<u8>>) -> PubKey { Loading @@ -56,14 +53,6 @@ fn extract_plain_pub_key(pub_key: &Option<PubKey>) -> &PlainPubKey { } } fn verification_key_from_identity(impls: &traits::TraitImpl, identity: &[u8]) -> key::EcVerifyKey { let identity = key::Identity::from_slice(identity).expect("invalid identity CBOR"); impls .device .process_peer_cert_chain(&identity.cert_chain, &*impls.ecdsa) .expect("failed to extract signing key") } fn vec_to_identity(data: &[u8]) -> Identity { Identity { identity: data.to_vec(), Loading @@ -75,26 +64,3 @@ fn vec_to_signature(data: &[u8]) -> SessionIdSignature { signature: data.to_vec(), } } /// Decrypt a pair of AES-256 keys encrypted with the AuthGraph PBK. pub fn decipher_aes_keys(imp: &traits::TraitImpl, arc: &[Vec<u8>; 2]) -> [key::AesKey; 2] { [ decipher_aes_key(imp, &arc[0]), decipher_aes_key(imp, &arc[1]), ] } /// Decrypt an AES-256 key encrypted with the AuthGraph PBK. pub fn decipher_aes_key(imp: &traits::TraitImpl, arc: &[u8]) -> key::AesKey { let pbk = imp.device.get_per_boot_key().expect("no PBK available"); let arc::ArcContent { payload, protected_headers: _, unprotected_headers: _, } = arc::decipher_arc(&pbk, arc, &*imp.aes_gcm).expect("failed to decrypt arc"); assert_eq!(payload.0.len(), 32); let mut key = key::AesKey([0; 32]); key.0.copy_from_slice(&payload.0); assert_ne!(key.0, [0; 32], "agreed AES-256 key should be non-zero"); key }
security/authgraph/aidl/vts/functional/role_test.rs +12 −12 Original line number Diff line number Diff line Loading @@ -48,31 +48,31 @@ macro_rules! require_nonsecure { #[test] fn test_nonsecure_source_mainline() { let mut impls = vts::test_impls(); vts::source::test_mainline(&mut impls, require_nonsecure!()); let mut sink = vts::test_ag_participant().expect("failed to create a local sink"); vts::source::test_mainline(&mut sink, require_nonsecure!()); } #[test] fn test_nonsecure_source_corrupt_sig() { let mut impls = vts::test_impls(); vts::source::test_corrupt_sig(&mut impls, require_nonsecure!()); let mut sink = vts::test_ag_participant().expect("failed to create a local sink"); vts::source::test_corrupt_sig(&mut sink, require_nonsecure!()); } #[test] fn test_nonsecure_source_corrupt_keys() { let mut impls = vts::test_impls(); vts::source::test_corrupt_key(&mut impls, require_nonsecure!()); let mut sink = vts::test_ag_participant().expect("failed to create a local sink"); vts::source::test_corrupt_key(&mut sink, require_nonsecure!()); } #[test] fn test_nonsecure_sink_mainline() { let mut impls = vts::test_impls(); vts::sink::test_mainline(&mut impls, require_nonsecure!()); let mut source = vts::test_ag_participant().expect("failed to create a local source"); vts::sink::test_mainline(&mut source, require_nonsecure!()); } #[test] fn test_nonsecure_sink_corrupt_sig() { let mut impls = vts::test_impls(); vts::sink::test_corrupt_sig(&mut impls, require_nonsecure!()); let mut source = vts::test_ag_participant().expect("failed to create a local source"); vts::sink::test_corrupt_sig(&mut source, require_nonsecure!()); } #[test] fn test_nonsecure_sink_corrupt_keys() { let mut impls = vts::test_impls(); vts::sink::test_corrupt_keys(&mut impls, require_nonsecure!()); let mut source = vts::test_ag_participant().expect("failed to create a local source"); vts::sink::test_corrupt_keys(&mut source, require_nonsecure!()); }
security/authgraph/aidl/vts/functional/sink.rs +80 −61 Original line number Diff line number Diff line Loading @@ -16,23 +16,28 @@ //! VTS tests for sinks use super::*; use authgraph_core::traits; use authgraph_core::{key, keyexchange as ke}; /// Run AuthGraph tests against the provided sink, using a local test source implementation. pub fn test(impls: &mut traits::TraitImpl, sink: binder::Strong<dyn IAuthGraphKeyExchange>) { test_mainline(impls, sink.clone()); test_corrupt_sig(impls, sink.clone()); test_corrupt_keys(impls, sink); pub fn test( local_source: &mut ke::AuthGraphParticipant, sink: binder::Strong<dyn IAuthGraphKeyExchange>, ) { test_mainline(local_source, sink.clone()); test_corrupt_sig(local_source, sink.clone()); test_corrupt_keys(local_source, sink); } /// Perform mainline AuthGraph key exchange with the provided sink and local implementation. /// Return the agreed AES keys in plaintext. pub fn test_mainline( impls: &mut traits::TraitImpl, local_source: &mut ke::AuthGraphParticipant, sink: binder::Strong<dyn IAuthGraphKeyExchange>, ) -> [key::AesKey; 2] { // Step 1: create an ephemeral ECDH key at the (local) source. let source_init_info = ke::create(impls).expect("failed to create() with local impl"); let source_init_info = local_source .create() .expect("failed to create() with local impl"); // Step 2: pass the source's ECDH public key and other session info to the (remote) sink. let init_result = sink Loading @@ -50,20 +55,21 @@ pub fn test_mainline( assert!(!sink_info.sessionId.is_empty()); // The AuthGraph core library will verify the session ID signature, but do it here too. let sink_verification_key = verification_key_from_identity(&impls, &sink_init_info.identity.identity); ke::verify_signature_on_session_id( let sink_verification_key = local_source .peer_verification_key_from_identity(&sink_init_info.identity.identity) .expect("failed to get peer verification from identity"); local_source .verify_signature_on_session_id( &sink_verification_key, &sink_info.sessionId, &sink_info.signature.signature, &*impls.ecdsa, ) .expect("failed verification of signed session ID"); // Step 3: pass the sink's ECDH public key and other session info to the (local) source, so it // can calculate the same pair of symmetric keys. let source_info = ke::finish( impls, let source_info = local_source .finish( &sink_pub_key.plainPubKey, &sink_init_info.identity.identity, &sink_info.signature.signature, Loading @@ -75,13 +81,15 @@ pub fn test_mainline( assert!(!source_info.session_id.is_empty()); // The AuthGraph core library will verify the session ID signature, but do it here too. let source_verification_key = verification_key_from_identity(&impls, &source_init_info.identity); ke::verify_signature_on_session_id( let source_verification_key = key::Identity::from_slice(&source_init_info.identity) .expect("invalid identity CBOR") .cert_chain .root_key; local_source .verify_signature_on_session_id( &source_verification_key, &source_info.session_id, &source_info.session_id_signature, &*impls.ecdsa, ) .expect("failed verification of signed session ID"); Loading @@ -96,19 +104,28 @@ pub fn test_mainline( &sink_info.sharedKeys, ) .expect("failed to authenticationComplete() with remote sink"); // Decrypt and return the session keys. decipher_aes_keys(&impls, &source_info.shared_keys) let decrypted_shared_keys = local_source .decipher_shared_keys_from_arcs(&source_info.shared_keys) .expect("failed to decrypt shared key arcs") .try_into(); let decrypted_shared_keys_array = match decrypted_shared_keys { Ok(array) => array, Err(_) => panic!("wrong number of decrypted shared key arcs"), }; decrypted_shared_keys_array } /// Perform mainline AuthGraph key exchange with the provided sink, but provide an invalid /// session ID signature. pub fn test_corrupt_sig( impls: &mut traits::TraitImpl, local_source: &mut ke::AuthGraphParticipant, sink: binder::Strong<dyn IAuthGraphKeyExchange>, ) { // Step 1: create an ephemeral ECDH key at the (local) source. let source_init_info = ke::create(impls).expect("failed to create() with local impl"); let source_init_info = local_source .create() .expect("failed to create() with local impl"); // Step 2: pass the source's ECDH public key and other session info to the (remote) sink. let init_result = sink Loading @@ -127,8 +144,8 @@ pub fn test_corrupt_sig( // Step 3: pass the sink's ECDH public key and other session info to the (local) source, so it // can calculate the same pair of symmetric keys. let source_info = ke::finish( impls, let source_info = local_source .finish( &sink_pub_key.plainPubKey, &sink_init_info.identity.identity, &sink_info.signature.signature, Loading Loading @@ -158,11 +175,13 @@ pub fn test_corrupt_sig( /// Perform mainline AuthGraph key exchange with the provided sink, but provide an invalid /// Arc for the sink's key. pub fn test_corrupt_keys( impls: &mut traits::TraitImpl, local_source: &mut ke::AuthGraphParticipant, sink: binder::Strong<dyn IAuthGraphKeyExchange>, ) { // Step 1: create an ephemeral ECDH key at the (local) source. let source_init_info = ke::create(impls).expect("failed to create() with local impl"); let source_init_info = local_source .create() .expect("failed to create() with local impl"); // Step 2: pass the source's ECDH public key and other session info to the (remote) sink. let init_result = sink Loading @@ -181,8 +200,8 @@ pub fn test_corrupt_keys( // Step 3: pass the sink's ECDH public key and other session info to the (local) source, so it // can calculate the same pair of symmetric keys. let source_info = ke::finish( impls, let source_info = local_source .finish( &sink_pub_key.plainPubKey, &sink_init_info.identity.identity, &sink_info.signature.signature, Loading
security/authgraph/aidl/vts/functional/source.rs +79 −65 Original line number Diff line number Diff line Loading @@ -16,19 +16,22 @@ //! VTS tests for sources use super::*; use authgraph_core::traits; use authgraph_core::{key, keyexchange as ke}; /// Run AuthGraph tests against the provided source, using a local test sink implementation. pub fn test(impls: &mut traits::TraitImpl, source: binder::Strong<dyn IAuthGraphKeyExchange>) { test_mainline(impls, source.clone()); test_corrupt_sig(impls, source.clone()); test_corrupt_key(impls, source); pub fn test( local_sink: &mut ke::AuthGraphParticipant, source: binder::Strong<dyn IAuthGraphKeyExchange>, ) { test_mainline(local_sink, source.clone()); test_corrupt_sig(local_sink, source.clone()); test_corrupt_key(local_sink, source); } /// Perform mainline AuthGraph key exchange with the provided source. /// Return the agreed AES keys in plaintext. pub fn test_mainline( impls: &mut traits::TraitImpl, local_sink: &mut ke::AuthGraphParticipant, source: binder::Strong<dyn IAuthGraphKeyExchange>, ) -> [key::AesKey; 2] { // Step 1: create an ephemeral ECDH key at the (remote) source. Loading @@ -40,8 +43,8 @@ pub fn test_mainline( let source_pub_key = extract_plain_pub_key(&source_init_info.key.pubKey); // Step 2: pass the source's ECDH public key and other session info to the (local) sink. let init_result = ke::init( impls, let init_result = local_sink .init( &source_pub_key.plainPubKey, &source_init_info.identity.identity, &source_init_info.nonce, Loading @@ -58,12 +61,15 @@ pub fn test_mainline( assert!(!sink_info.session_id.is_empty()); // The AuthGraph core library will verify the session ID signature, but do it here too. let sink_verification_key = verification_key_from_identity(&impls, &sink_init_info.identity); ke::verify_signature_on_session_id( let sink_verification_key = key::Identity::from_slice(&sink_init_info.identity) .expect("invalid identity CBOR") .cert_chain .root_key; local_sink .verify_signature_on_session_id( &sink_verification_key, &sink_info.session_id, &sink_info.session_id_signature, &*impls.ecdsa, ) .expect("failed verification of signed session ID"); Loading @@ -86,13 +92,14 @@ pub fn test_mainline( assert!(!source_info.sessionId.is_empty()); // The AuthGraph core library will verify the session ID signature, but do it here too. let source_verification_key = verification_key_from_identity(&impls, &source_init_info.identity.identity); ke::verify_signature_on_session_id( let source_verification_key = local_sink .peer_verification_key_from_identity(&source_init_info.identity.identity) .expect("failed to get peer verification from identity"); local_sink .verify_signature_on_session_id( &source_verification_key, &source_info.sessionId, &source_info.signature.signature, &*impls.ecdsa, ) .expect("failed verification of signed session ID"); Loading @@ -101,21 +108,25 @@ pub fn test_mainline( // Step 4: pass the (remote) source's session ID signature back to the sink, so it can check it // and update the symmetric keys so they're marked as authentication complete. let sink_arcs = ke::authentication_complete( impls, &source_info.signature.signature, sink_info.shared_keys, ) let sink_arcs = local_sink .authentication_complete(&source_info.signature.signature, sink_info.shared_keys) .expect("failed to authenticationComplete() with local sink"); // Decrypt and return the session keys. decipher_aes_keys(&impls, &sink_arcs) let decrypted_shared_keys = local_sink .decipher_shared_keys_from_arcs(&sink_arcs) .expect("failed to decrypt shared key arcs") .try_into(); let decrypted_shared_keys_array = match decrypted_shared_keys { Ok(array) => array, Err(_) => panic!("wrong number of decrypted shared key arcs"), }; decrypted_shared_keys_array } /// Perform mainline AuthGraph key exchange with the provided source, but provide an invalid session /// ID signature. pub fn test_corrupt_sig( impls: &mut traits::TraitImpl, local_sink: &mut ke::AuthGraphParticipant, source: binder::Strong<dyn IAuthGraphKeyExchange>, ) { // Step 1: create an ephemeral ECDH key at the (remote) source. Loading @@ -127,8 +138,8 @@ pub fn test_corrupt_sig( let source_pub_key = extract_plain_pub_key(&source_init_info.key.pubKey); // Step 2: pass the source's ECDH public key and other session info to the (local) sink. let init_result = ke::init( impls, let init_result = local_sink .init( &source_pub_key.plainPubKey, &source_init_info.identity.identity, &source_init_info.nonce, Loading Loading @@ -172,7 +183,7 @@ pub fn test_corrupt_sig( /// Perform mainline AuthGraph key exchange with the provided source, but give it back /// a corrupted key. pub fn test_corrupt_key( impls: &mut traits::TraitImpl, local_sink: &mut ke::AuthGraphParticipant, source: binder::Strong<dyn IAuthGraphKeyExchange>, ) { // Step 1: create an ephemeral ECDH key at the (remote) source. Loading @@ -184,8 +195,8 @@ pub fn test_corrupt_key( let source_pub_key = extract_plain_pub_key(&source_init_info.key.pubKey); // Step 2: pass the source's ECDH public key and other session info to the (local) sink. let init_result = ke::init( impls, let init_result = local_sink .init( &source_pub_key.plainPubKey, &source_init_info.identity.identity, &source_init_info.nonce, Loading @@ -202,12 +213,15 @@ pub fn test_corrupt_key( assert!(!sink_info.session_id.is_empty()); // The AuthGraph core library will verify the session ID signature, but do it here too. let sink_verification_key = verification_key_from_identity(&impls, &sink_init_info.identity); ke::verify_signature_on_session_id( let sink_verification_key = key::Identity::from_slice(&sink_init_info.identity) .expect("invalid identity CBOR") .cert_chain .root_key; local_sink .verify_signature_on_session_id( &sink_verification_key, &sink_info.session_id, &sink_info.session_id_signature, &*impls.ecdsa, ) .expect("failed verification of signed session ID"); Loading
security/authgraph/default/src/fuzzer.rs +1 −1 Original line number Diff line number Diff line Loading @@ -25,7 +25,7 @@ use libfuzzer_sys::fuzz_target; use std::sync::{Arc, Mutex}; fuzz_target!(|data: &[u8]| { let local_ta = LocalTa::new(); let local_ta = LocalTa::new().expect("Failed to create an AuthGraph local TA."); let service = AuthGraphService::new_as_binder(Arc::new(Mutex::new(local_ta))); fuzz_service(&mut service.as_binder(), data); });