AuthGraph: move code into library

Use the core library's new service implementation, which wraps a
channel to the TA.

In this nonsecure case, the TA is local in-process, so use the core
library's AuthGraphTa, and implement the SerializedChannel as just
a direct invocation of the TA.

Move this code into a _nonsecure library, so the main.rs just has
the code needed to start the executable and register the service.

Test: VtsAidlAuthGraphSessionTest
Bug: 284470121
Change-Id: I738d3876872a8cd248f0ebec708676d1173b6e37
diff --git a/security/authgraph/default/Android.bp b/security/authgraph/default/Android.bp
index c0f2106..ac67136 100644
--- a/security/authgraph/default/Android.bp
+++ b/security/authgraph/default/Android.bp
@@ -22,6 +22,26 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
+rust_library {
+    name: "libauthgraph_nonsecure",
+    crate_name: "authgraph_nonsecure",
+    defaults: [
+        "authgraph_use_latest_hal_aidl_rust",
+    ],
+    vendor_available: true,
+    rustlibs: [
+        "libandroid_logger",
+        "libauthgraph_boringssl",
+        "libauthgraph_core",
+        "libauthgraph_hal",
+        "libbinder_rs",
+        "liblibc",
+        "liblog_rust",
+    ],
+    srcs: ["src/lib.rs"],
+
+}
+
 rust_binary {
     name: "android.hardware.security.authgraph-service.nonsecure",
     relative_install_path: "hw",
@@ -33,10 +53,8 @@
     ],
     rustlibs: [
         "libandroid_logger",
-        "libauthgraph_core",
-        "libauthgraph_boringssl",
         "libauthgraph_hal",
-        "libauthgraph_wire",
+        "libauthgraph_nonsecure",
         "libbinder_rs",
         "liblibc",
         "liblog_rust",
diff --git a/security/authgraph/default/src/lib.rs b/security/authgraph/default/src/lib.rs
new file mode 100644
index 0000000..4cd0cb7
--- /dev/null
+++ b/security/authgraph/default/src/lib.rs
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//! Common functionality for non-secure/testing instance of AuthGraph.
+
+use authgraph_boringssl as boring;
+use authgraph_core::{
+    key::MillisecondsSinceEpoch,
+    ta::{AuthGraphTa, Role},
+    traits,
+};
+use authgraph_hal::channel::SerializedChannel;
+use std::sync::{Arc, Mutex};
+use std::time::Instant;
+
+/// Monotonic clock with an epoch that starts at the point of construction.
+/// (This makes it unsuitable for use outside of testing, because the epoch
+/// will not match that of any other component.)
+pub struct StdClock(Instant);
+
+impl Default for StdClock {
+    fn default() -> Self {
+        Self(Instant::now())
+    }
+}
+
+impl traits::MonotonicClock for StdClock {
+    fn now(&self) -> MillisecondsSinceEpoch {
+        let millis: i64 = self
+            .0
+            .elapsed()
+            .as_millis()
+            .try_into()
+            .expect("failed to fit timestamp in i64");
+        MillisecondsSinceEpoch(millis)
+    }
+}
+
+/// Implementation of the AuthGraph TA that runs locally in-process (and which is therefore
+/// insecure).
+pub struct LocalTa {
+    ta: Arc<Mutex<AuthGraphTa>>,
+}
+
+impl LocalTa {
+    /// Create a new instance.
+    pub fn new() -> Self {
+        Self {
+            ta: Arc::new(Mutex::new(AuthGraphTa::new(
+                boring::trait_impls(
+                    Box::<boring::test_device::AgDevice>::default(),
+                    Some(Box::new(StdClock::default())),
+                ),
+                Role::Both,
+            ))),
+        }
+    }
+}
+
+/// Pretend to be a serialized channel to the TA, but actually just directly invoke the TA with
+/// incoming requests.
+impl SerializedChannel for LocalTa {
+    const MAX_SIZE: usize = usize::MAX;
+
+    fn execute(&mut self, req_data: &[u8]) -> binder::Result<Vec<u8>> {
+        Ok(self.ta.lock().unwrap().process(req_data))
+    }
+}
diff --git a/security/authgraph/default/src/main.rs b/security/authgraph/default/src/main.rs
index dc4a8e4..873eb4e 100644
--- a/security/authgraph/default/src/main.rs
+++ b/security/authgraph/default/src/main.rs
@@ -22,18 +22,10 @@
 //! expose an entrypoint that allowed retrieval of the specific IAuthGraphKeyExchange instance that
 //! is correlated with the component).
 
-use android_hardware_security_authgraph::aidl::android::hardware::security::authgraph::{
-    Arc::Arc, IAuthGraphKeyExchange::BnAuthGraphKeyExchange,
-    IAuthGraphKeyExchange::IAuthGraphKeyExchange, Identity::Identity, KeInitResult::KeInitResult,
-    Key::Key, PubKey::PubKey, SessionIdSignature::SessionIdSignature, SessionInfo::SessionInfo,
-    SessionInitiationInfo::SessionInitiationInfo,
-};
-use authgraph_boringssl as boring;
-use authgraph_core::{key::MillisecondsSinceEpoch, keyexchange as ke, traits};
-use authgraph_hal::{errcode_to_binder, Innto, TryInnto};
+use authgraph_hal::service;
+use authgraph_nonsecure::LocalTa;
 use log::{error, info};
-use std::ffi::CString;
-use std::sync::Mutex;
+use std::sync::{Arc, Mutex};
 
 static SERVICE_NAME: &str = "android.hardware.security.authgraph.IAuthGraphKeyExchange";
 static SERVICE_INSTANCE: &str = "nonsecure";
@@ -73,7 +65,8 @@
     binder::ProcessState::start_thread_pool();
 
     // Register the service
-    let service = AuthGraphService::new_as_binder();
+    let local_ta = LocalTa::new();
+    let service = service::AuthGraphService::new_as_binder(Arc::new(Mutex::new(local_ta)));
     let service_name = format!("{}/{}", SERVICE_NAME, SERVICE_INSTANCE);
     binder::add_service(&service_name, service.as_binder()).map_err(|e| {
         format!(
@@ -87,148 +80,3 @@
     info!("AuthGraph HAL service is terminating."); // should not reach here
     Ok(())
 }
-
-/// Non-secure implementation of the AuthGraph key exchange service.
-struct AuthGraphService {
-    imp: Mutex<traits::TraitImpl>,
-}
-
-impl AuthGraphService {
-    /// Create a new instance.
-    fn new() -> Self {
-        Self {
-            imp: Mutex::new(traits::TraitImpl {
-                aes_gcm: Box::new(boring::BoringAes),
-                ecdh: Box::new(boring::BoringEcDh),
-                ecdsa: Box::new(boring::BoringEcDsa),
-                hmac: Box::new(boring::BoringHmac),
-                hkdf: Box::new(boring::BoringHkdf),
-                sha256: Box::new(boring::BoringSha256),
-                rng: Box::new(boring::BoringRng),
-                device: Box::<boring::test_device::AgDevice>::default(),
-                clock: Some(Box::new(StdClock)),
-            }),
-        }
-    }
-
-    /// Create a new instance wrapped in a proxy object.
-    pub fn new_as_binder() -> binder::Strong<dyn IAuthGraphKeyExchange> {
-        BnAuthGraphKeyExchange::new_binder(Self::new(), binder::BinderFeatures::default())
-    }
-}
-
-impl binder::Interface for AuthGraphService {}
-
-/// Extract (and require) an unsigned public key as bytes from a [`PubKey`].
-fn unsigned_pub_key(pub_key: &PubKey) -> binder::Result<&[u8]> {
-    match pub_key {
-        PubKey::PlainKey(key) => Ok(&key.plainPubKey),
-        PubKey::SignedKey(_) => Err(binder::Status::new_exception(
-            binder::ExceptionCode::ILLEGAL_ARGUMENT,
-            Some(&CString::new("expected unsigned public key").unwrap()),
-        )),
-    }
-}
-
-fn err_to_binder(err: authgraph_core::error::Error) -> binder::Status {
-    if err.0 != authgraph_wire::ErrorCode::Ok && !err.1.is_empty() {
-        error!("failure {:?} message: '{}'", err.0, err.1);
-    }
-    errcode_to_binder(err.0)
-}
-
-/// This nonsecure implementation of the AuthGraph HAL interface directly calls the AuthGraph
-/// reference implementation library code; a real implementation requires the AuthGraph
-/// code to run in a secure environment, not within Android.
-impl IAuthGraphKeyExchange for AuthGraphService {
-    fn create(&self) -> binder::Result<SessionInitiationInfo> {
-        info!("create()");
-        let mut imp = self.imp.lock().unwrap();
-        let info = ke::create(&mut *imp).map_err(err_to_binder)?;
-        Ok(info.innto())
-    }
-    fn init(
-        &self,
-        peer_pub_key: &PubKey,
-        peer_id: &Identity,
-        peer_nonce: &[u8],
-        peer_version: i32,
-    ) -> binder::Result<KeInitResult> {
-        info!("init(v={peer_version})");
-        let mut imp = self.imp.lock().unwrap();
-        let peer_pub_key = unsigned_pub_key(peer_pub_key)?;
-        let result = ke::init(
-            &mut *imp,
-            peer_pub_key,
-            &peer_id.identity,
-            &peer_nonce,
-            peer_version,
-        )
-        .map_err(err_to_binder)?;
-        Ok(result.innto())
-    }
-
-    fn finish(
-        &self,
-        peer_pub_key: &PubKey,
-        peer_id: &Identity,
-        peer_signature: &SessionIdSignature,
-        peer_nonce: &[u8],
-        peer_version: i32,
-        own_key: &Key,
-    ) -> binder::Result<SessionInfo> {
-        info!("finish(v={peer_version})");
-        let mut imp = self.imp.lock().unwrap();
-        let peer_pub_key = unsigned_pub_key(peer_pub_key)?;
-        let own_key: Key = own_key.clone();
-        let own_key: authgraph_core::key::Key = own_key.try_innto()?;
-        let session_info = ke::finish(
-            &mut *imp,
-            peer_pub_key,
-            &peer_id.identity,
-            &peer_signature.signature,
-            &peer_nonce,
-            peer_version,
-            own_key,
-        )
-        .map_err(err_to_binder)?;
-        Ok(session_info.innto())
-    }
-
-    fn authenticationComplete(
-        &self,
-        peer_signature: &SessionIdSignature,
-        shared_keys: &[Arc; 2],
-    ) -> binder::Result<[Arc; 2]> {
-        info!("authComplete()");
-        let mut imp = self.imp.lock().unwrap();
-        let shared_keys = [shared_keys[0].arc.clone(), shared_keys[1].arc.clone()];
-        let arcs = ke::authentication_complete(&mut *imp, &peer_signature.signature, shared_keys)
-            .map_err(err_to_binder)?;
-        Ok(arcs.map(|arc| Arc { arc }))
-    }
-}
-
-/// Monotonic clock.
-#[derive(Default)]
-pub struct StdClock;
-
-impl traits::MonotonicClock for StdClock {
-    fn now(&self) -> authgraph_core::key::MillisecondsSinceEpoch {
-        let mut time = libc::timespec {
-            tv_sec: 0,  // libc::time_t
-            tv_nsec: 0, // libc::c_long
-        };
-        let rc =
-        // Safety: `time` is a valid structure.
-            unsafe { libc::clock_gettime(libc::CLOCK_BOOTTIME, &mut time as *mut libc::timespec) };
-        if rc < 0 {
-            log::warn!("failed to get time!");
-            return MillisecondsSinceEpoch(0);
-        }
-        // The types in `libc::timespec` may be different on different architectures,
-        // so allow conversion to `i64`.
-        #[allow(clippy::unnecessary_cast)]
-        MillisecondsSinceEpoch((time.tv_sec as i64 * 1000) + (time.tv_nsec as i64 / 1000 / 1000))
-    }
-}