1 // Copyright 2023 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 ////////////////////////////////////////////////////////////////////////////////
16
17 //! Crate that holds common code for an AuthGraph HAL service.
18
19 use android_hardware_security_authgraph::aidl::android::hardware::security::authgraph::{
20 Arc::Arc, Identity::Identity, KeInitResult::KeInitResult, Key::Key, PlainPubKey::PlainPubKey,
21 PubKey::PubKey, SessionIdSignature::SessionIdSignature, SessionInfo::SessionInfo,
22 SessionInitiationInfo::SessionInitiationInfo,
23 };
24 use authgraph_wire as wire;
25 use log::warn;
26
27 pub mod channel;
28 pub mod service;
29
30 // Neither the AIDL types nor the `authgraph_core` types are local to this crate, which means that
31 // Rust's orphan rule means we cannot implement the standard conversion traits. So instead define
32 // our own equivalent conversion traits that are local, and for which we're allowed to provide
33 // implementations. Give them an odd name to avoid confusion with the standard traits.
34
35 /// Local equivalent of `From` trait, with a different name to avoid clashes.
36 pub trait Fromm<T>: Sized {
37 /// Convert `val` into type `Self`.
fromm(val: T) -> Self38 fn fromm(val: T) -> Self;
39 }
40 /// Local equivalent of `TryFrom` trait, with a different name to avoid clashes.
41 pub trait TryFromm<T>: Sized {
42 /// Error type emitted on conversion failure.
43 type Error;
44 /// Try to convert `val` into type `Self`.
try_fromm(val: T) -> Result<Self, Self::Error>45 fn try_fromm(val: T) -> Result<Self, Self::Error>;
46 }
47 /// Local equivalent of `Into` trait, with a different name to avoid clashes.
48 pub trait Innto<T> {
49 /// Convert `self` into type `T`.
innto(self) -> T50 fn innto(self) -> T;
51 }
52 /// Local equivalent of `TryInto` trait, with a different name to avoid clashes.
53 pub trait TryInnto<T> {
54 /// Error type emitted on conversion failure.
55 type Error;
56 /// Try to convert `self` into type `T`.
try_innto(self) -> Result<T, Self::Error>57 fn try_innto(self) -> Result<T, Self::Error>;
58 }
59 /// Blanket implementation of `Innto` from `Fromm`
60 impl<T, U> Innto<U> for T
61 where
62 U: Fromm<T>,
63 {
innto(self) -> U64 fn innto(self) -> U {
65 U::fromm(self)
66 }
67 }
68 /// Blanket implementation of `TryInnto` from `TryFromm`
69 impl<T, U> TryInnto<U> for T
70 where
71 U: TryFromm<T>,
72 {
73 type Error = U::Error;
try_innto(self) -> Result<U, Self::Error>74 fn try_innto(self) -> Result<U, Self::Error> {
75 U::try_fromm(self)
76 }
77 }
78
79 // Conversions from internal types to HAL-defined types.
80
81 impl Fromm<wire::SessionInitiationInfo> for SessionInitiationInfo {
fromm(val: wire::SessionInitiationInfo) -> Self82 fn fromm(val: wire::SessionInitiationInfo) -> Self {
83 Self {
84 key: val.ke_key.innto(),
85 identity: Identity { identity: val.identity },
86 nonce: val.nonce,
87 version: val.version,
88 }
89 }
90 }
91
92 impl Fromm<wire::Key> for Key {
fromm(val: wire::Key) -> Self93 fn fromm(val: wire::Key) -> Self {
94 Self {
95 pubKey: val
96 .pub_key
97 .map(|pub_key| PubKey::PlainKey(PlainPubKey { plainPubKey: pub_key })),
98 arcFromPBK: val.arc_from_pbk.map(|arc| Arc { arc }),
99 }
100 }
101 }
102
103 impl Fromm<wire::KeInitResult> for KeInitResult {
fromm(val: wire::KeInitResult) -> Self104 fn fromm(val: wire::KeInitResult) -> Self {
105 Self {
106 sessionInitiationInfo: val.session_init_info.innto(),
107 sessionInfo: val.session_info.innto(),
108 }
109 }
110 }
111
112 impl Fromm<wire::SessionInfo> for SessionInfo {
fromm(val: wire::SessionInfo) -> Self113 fn fromm(val: wire::SessionInfo) -> Self {
114 Self {
115 sharedKeys: val.shared_keys.map(|arc| Arc { arc }),
116 sessionId: val.session_id,
117 signature: SessionIdSignature { signature: val.session_id_signature },
118 }
119 }
120 }
121
122 // Conversions from HAL-defined types to internal types.
123
124 impl TryFromm<Key> for wire::Key {
125 type Error = binder::Status;
try_fromm(aidl: Key) -> Result<Self, Self::Error>126 fn try_fromm(aidl: Key) -> Result<Self, Self::Error> {
127 let pub_key = match aidl.pubKey {
128 None => None,
129 Some(PubKey::PlainKey(k)) => Some(k.plainPubKey),
130 Some(PubKey::SignedKey(_)) => return Err(arg_err("expect plain pubkey")),
131 };
132 Ok(Self { pub_key, arc_from_pbk: aidl.arcFromPBK.map(|a| a.arc) })
133 }
134 }
135
136 /// Generate a binder illegal argument error with the given message.
arg_err(msg: &str) -> binder::Status137 fn arg_err(msg: &str) -> binder::Status {
138 binder::Status::new_exception(
139 binder::ExceptionCode::ILLEGAL_ARGUMENT,
140 Some(&std::ffi::CString::new(msg).unwrap()),
141 )
142 }
143
144 /// Convert a [`wire::ErrorCore`] into a binder error.
errcode_to_binder(err: wire::ErrorCode) -> binder::Status145 pub fn errcode_to_binder(err: wire::ErrorCode) -> binder::Status {
146 warn!("operation failed: {err:?}");
147 // Translate the internal errors for `Unimplemented` and `InternalError` to their counterparts
148 // in binder errors to have uniformity in the Android HAL layer
149 match err {
150 wire::ErrorCode::Unimplemented => {
151 binder::Status::new_exception(binder::ExceptionCode::UNSUPPORTED_OPERATION, None)
152 }
153 wire::ErrorCode::InternalError => {
154 binder::Status::new_exception(binder::ExceptionCode::SERVICE_SPECIFIC, None)
155 }
156 _ => binder::Status::new_service_specific_error(err as i32, None),
157 }
158 }
159