Merge changes from topic "authgraph-hal" into main am: 93439a212b

Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/2786800

Change-Id: I1dd6ab8030654352f455838bb12b7a99b2336b5e
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/compatibility_matrices/compatibility_matrix.9.xml b/compatibility_matrices/compatibility_matrix.9.xml
index c79c68f..5ae169c 100644
--- a/compatibility_matrices/compatibility_matrix.9.xml
+++ b/compatibility_matrices/compatibility_matrix.9.xml
@@ -513,7 +513,7 @@
         <version>1</version>
         <interface>
             <name>IAuthGraphKeyExchange</name>
-            <instance>default</instance>
+            <instance>nonsecure</instance>
         </interface>
     </hal>
     <hal format="aidl" optional="true" updatable-via-apex="true">
diff --git a/security/authgraph/default/Android.bp b/security/authgraph/default/Android.bp
new file mode 100644
index 0000000..9de3bc1
--- /dev/null
+++ b/security/authgraph/default/Android.bp
@@ -0,0 +1,46 @@
+//
+// 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.
+//
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+rust_binary {
+    name: "android.hardware.security.authgraph-service.nonsecure",
+    relative_install_path: "hw",
+    vendor: true,
+    init_rc: ["authgraph.rc"],
+    vintf_fragments: ["authgraph.xml"],
+    defaults: [
+        "authgraph_use_latest_hal_aidl_rust",
+    ],
+    rustlibs: [
+        "libandroid_logger",
+        "libauthgraph_core",
+        "libauthgraph_boringssl",
+        "libauthgraph_hal",
+        "libbinder_rs",
+        "liblibc",
+        "liblog_rust",
+    ],
+    srcs: [
+        "src/main.rs",
+    ],
+}
diff --git a/security/authgraph/default/authgraph.rc b/security/authgraph/default/authgraph.rc
new file mode 100644
index 0000000..0222994
--- /dev/null
+++ b/security/authgraph/default/authgraph.rc
@@ -0,0 +1,5 @@
+service vendor.authgraph /vendor/bin/hw/android.hardware.security.authgraph-service.nonsecure
+    interface aidl android.hardware.security.authgraph.IAuthGraph/nonsecure
+    class hal
+    user nobody
+    group nobody
diff --git a/security/authgraph/default/authgraph.xml b/security/authgraph/default/authgraph.xml
new file mode 100644
index 0000000..9529a0a
--- /dev/null
+++ b/security/authgraph/default/authgraph.xml
@@ -0,0 +1,10 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.security.authgraph</name>
+        <version>1</version>
+        <interface>
+            <name>IAuthGraphKeyExchange</name>
+            <instance>nonsecure</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/security/authgraph/default/src/main.rs b/security/authgraph/default/src/main.rs
new file mode 100644
index 0000000..2112e58
--- /dev/null
+++ b/security/authgraph/default/src/main.rs
@@ -0,0 +1,227 @@
+/*
+ * 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.
+ */
+
+//! Default implementation of the AuthGraph key exchange HAL.
+//!
+//! This implementation of the HAL is only intended to allow testing and policy compliance.  A real
+//! implementation of the AuthGraph HAL would be implemented in a secure environment, and would not
+//! be independently registered with service manager (a secure component that uses AuthGraph would
+//! 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::{err_to_binder, Innto, TryInnto};
+use log::{error, info};
+use std::ffi::CString;
+use std::sync::Mutex;
+
+static SERVICE_NAME: &str = "android.hardware.security.authgraph.IAuthGraphKeyExchange";
+static SERVICE_INSTANCE: &str = "nonsecure";
+
+/// Local error type for failures in the HAL service.
+#[derive(Debug, Clone)]
+struct HalServiceError(String);
+
+impl From<String> for HalServiceError {
+    fn from(s: String) -> Self {
+        Self(s)
+    }
+}
+
+fn main() {
+    if let Err(e) = inner_main() {
+        panic!("HAL service failed: {:?}", e);
+    }
+}
+
+fn inner_main() -> Result<(), HalServiceError> {
+    // Initialize Android logging.
+    android_logger::init_once(
+        android_logger::Config::default()
+            .with_tag("authgraph-hal-nonsecure")
+            .with_min_level(log::Level::Info)
+            .with_log_id(android_logger::LogId::System),
+    );
+    // Redirect panic messages to logcat.
+    std::panic::set_hook(Box::new(|panic_info| {
+        error!("{}", panic_info);
+    }));
+
+    info!("Insecure AuthGraph key exchange HAL service is starting.");
+
+    info!("Starting thread pool now.");
+    binder::ProcessState::start_thread_pool();
+
+    // Register the service
+    let service = AuthGraphService::new_as_binder();
+    let service_name = format!("{}/{}", SERVICE_NAME, SERVICE_INSTANCE);
+    binder::add_service(&service_name, service.as_binder()).map_err(|e| {
+        format!(
+            "Failed to register service {} because of {:?}.",
+            service_name, e
+        )
+    })?;
+
+    info!("Successfully registered AuthGraph HAL services.");
+    binder::ProcessState::join_thread_pool();
+    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()),
+        )),
+    }
+}
+
+/// 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))
+    }
+}