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>
This commit is contained in:
commit
ab608a60ec
5 changed files with 289 additions and 1 deletions
|
@ -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">
|
||||
|
|
46
security/authgraph/default/Android.bp
Normal file
46
security/authgraph/default/Android.bp
Normal file
|
@ -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",
|
||||
],
|
||||
}
|
5
security/authgraph/default/authgraph.rc
Normal file
5
security/authgraph/default/authgraph.rc
Normal file
|
@ -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
|
10
security/authgraph/default/authgraph.xml
Normal file
10
security/authgraph/default/authgraph.xml
Normal file
|
@ -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>
|
227
security/authgraph/default/src/main.rs
Normal file
227
security/authgraph/default/src/main.rs
Normal file
|
@ -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))
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue