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 //! Types and macros for communication between HAL and TA
16 
17 // Allow missing docs in this crate as the types here are generally 1:1 with the HAL
18 // interface definitions.
19 #![allow(missing_docs)]
20 #![no_std]
21 extern crate alloc;
22 
23 use crate::cbor::{cbor_type_error, AsCborValue, CborError};
24 use alloc::{vec, vec::Vec};
25 use authgraph_derive::AsCborValue;
26 use ciborium::value::Value;
27 use enumn::N;
28 
29 pub mod cbor;
30 pub mod fragmentation;
31 
32 #[cfg(test)]
33 mod tests;
34 
35 /// Length of a session identifier in bytes
36 pub const SESSION_ID_LEN: usize = 32;
37 
38 // Request/Response pairs corresponding to each of the methods on the `IAuthGraphKeyExchange`
39 // interface.  Structures that have a single field containing CBOR-encoded data are directly
40 // expanded.
41 
42 #[derive(Debug, Clone, PartialEq, Eq, AsCborValue)]
43 pub struct CreateRequest {}
44 #[derive(Debug, Clone, PartialEq, Eq, AsCborValue)]
45 pub struct CreateResponse {
46     pub ret: SessionInitiationInfo,
47 }
48 #[derive(Debug, Clone, PartialEq, Eq, AsCborValue)]
49 pub struct InitRequest {
50     // Note that the AIDL definition for this field has type `PubKey`, which allows either a
51     // `PlainPubKey` or a `SignedPubKey`, to allow for re-used in identity chains.  However, only
52     // the `PlainPubKey` variant appears here.
53     pub peer_pub_key: Vec<u8>, // PlainPubKey.cddl
54     pub peer_id: Vec<u8>,      // Identity.cddl
55     pub peer_nonce: Vec<u8>,
56     pub peer_version: i32,
57 }
58 #[derive(Debug, Clone, PartialEq, Eq, AsCborValue)]
59 pub struct InitResponse {
60     pub ret: KeInitResult,
61 }
62 #[derive(Debug, Clone, PartialEq, Eq, AsCborValue)]
63 pub struct FinishRequest {
64     // Note that the AIDL definition for this field has type `PubKey`, which allows either a
65     // `PlainPubKey` or a `SignedPubKey`, to allow for re-used in identity chains.  However, only
66     // the `PlainPubKey` variant appears here.
67     pub peer_pub_key: Vec<u8>,   // PlainPubKey.cddl
68     pub peer_id: Vec<u8>,        // Identity.cddl
69     pub peer_signature: Vec<u8>, // SessionIdSignature.cddl
70     pub peer_nonce: Vec<u8>,
71     pub peer_version: i32,
72     pub own_key: Key,
73 }
74 #[derive(Debug, Clone, PartialEq, Eq, AsCborValue)]
75 pub struct FinishResponse {
76     pub ret: SessionInfo,
77 }
78 #[derive(Debug, Clone, PartialEq, Eq, AsCborValue)]
79 pub struct AuthenticationCompleteRequest {
80     pub peer_signature: Vec<u8>,   // SessionIdSignature.cddl
81     pub shared_keys: [Vec<u8>; 2], // Arc.cddl
82 }
83 #[derive(Debug, Clone, PartialEq, Eq, AsCborValue)]
84 pub struct AuthenticationCompleteResponse {
85     pub ret: [Vec<u8>; 2], // Arc.cddl
86 }
87 
88 // Rust `struct`s corresponding to AIDL messages on the `IAuthGraphKeyExchange` interface.
89 // Structures that have a single field containing CBOR-encoded data are directly expanded.
90 
91 #[derive(Debug, Clone, PartialEq, Eq, AsCborValue)]
92 pub struct SessionInitiationInfo {
93     pub ke_key: Key,
94     pub identity: Vec<u8>, // Identity.cddl
95     pub nonce: Vec<u8>,
96     pub version: i32,
97 }
98 
99 #[derive(Debug, Clone, PartialEq, Eq, AsCborValue)]
100 pub struct SessionInfo {
101     pub shared_keys: [Vec<u8>; 2], // Arc.cddl
102     pub session_id: Vec<u8>,
103     pub session_id_signature: Vec<u8>, // SessionIdSignature.cddl
104 }
105 
106 #[derive(Debug, Clone, PartialEq, Eq, AsCborValue)]
107 pub struct KeInitResult {
108     pub session_init_info: SessionInitiationInfo,
109     pub session_info: SessionInfo,
110 }
111 
112 #[derive(Debug, Clone, PartialEq, Eq, AsCborValue)]
113 pub struct Key {
114     // Note that the AIDL definition for this field has type `PubKey`, which allows either a
115     // `PlainPubKey` or a `SignedPubKey`, to allow for re-used in identity chains.  However, only
116     // the `PlainPubKey` variant appears here.
117     pub pub_key: Option<Vec<u8>>,      // PlainPubKey.cddl
118     pub arc_from_pbk: Option<Vec<u8>>, // Arc.cddl
119 }
120 
121 #[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, N)]
122 pub enum AuthGraphOperationCode {
123     Create = 0x10,
124     Init = 0x11,
125     Finish = 0x12,
126     AuthenticationComplete = 0x13,
127 }
128 
129 #[derive(Debug, Clone, PartialEq, Eq)]
130 pub enum PerformOpReq {
131     Create(CreateRequest),
132     Init(InitRequest),
133     Finish(FinishRequest),
134     AuthenticationComplete(AuthenticationCompleteRequest),
135 }
136 
137 impl Code for PerformOpReq {
code(&self) -> AuthGraphOperationCode138     fn code(&self) -> AuthGraphOperationCode {
139         match self {
140             Self::Create(_) => AuthGraphOperationCode::Create,
141             Self::Init(_) => AuthGraphOperationCode::Init,
142             Self::Finish(_) => AuthGraphOperationCode::Finish,
143             Self::AuthenticationComplete(_) => AuthGraphOperationCode::AuthenticationComplete,
144         }
145     }
146 }
147 
148 impl AsCborValue for PerformOpReq {
from_cbor_value(value: Value) -> Result<Self, CborError>149     fn from_cbor_value(value: Value) -> Result<Self, CborError> {
150         let mut a = match value {
151             Value::Array(a) if a.len() == 2 => a,
152             _ => return crate::cbor_type_error(&value, "arr len 2"),
153         };
154         let val = a.remove(1);
155         let code = i32::from_cbor_value(a.remove(0))?;
156         let code = AuthGraphOperationCode::n(code).ok_or(CborError::NonEnumValue)?;
157         Ok(match code {
158             AuthGraphOperationCode::Create => Self::Create(CreateRequest::from_cbor_value(val)?),
159             AuthGraphOperationCode::Init => Self::Init(InitRequest::from_cbor_value(val)?),
160             AuthGraphOperationCode::Finish => Self::Finish(FinishRequest::from_cbor_value(val)?),
161             AuthGraphOperationCode::AuthenticationComplete => {
162                 Self::AuthenticationComplete(AuthenticationCompleteRequest::from_cbor_value(val)?)
163             }
164         })
165     }
to_cbor_value(self) -> Result<Value, CborError>166     fn to_cbor_value(self) -> Result<Value, CborError> {
167         Ok(Value::Array(match self {
168             Self::Create(req) => vec![req.value(), req.to_cbor_value()?],
169             Self::Init(req) => vec![req.value(), req.to_cbor_value()?],
170             Self::Finish(req) => vec![req.value(), req.to_cbor_value()?],
171             Self::AuthenticationComplete(req) => vec![req.value(), req.to_cbor_value()?],
172         }))
173     }
174 }
175 
176 #[derive(Debug, Clone, PartialEq, Eq)]
177 pub enum PerformOpRsp {
178     Create(CreateResponse),
179     Init(InitResponse),
180     Finish(FinishResponse),
181     AuthenticationComplete(AuthenticationCompleteResponse),
182 }
183 
184 impl Code for PerformOpRsp {
code(&self) -> AuthGraphOperationCode185     fn code(&self) -> AuthGraphOperationCode {
186         match self {
187             Self::Create(_) => AuthGraphOperationCode::Create,
188             Self::Init(_) => AuthGraphOperationCode::Init,
189             Self::Finish(_) => AuthGraphOperationCode::Finish,
190             Self::AuthenticationComplete(_) => AuthGraphOperationCode::AuthenticationComplete,
191         }
192     }
193 }
194 
195 impl AsCborValue for PerformOpRsp {
from_cbor_value(value: Value) -> Result<Self, CborError>196     fn from_cbor_value(value: Value) -> Result<Self, CborError> {
197         let mut a = match value {
198             Value::Array(a) if a.len() == 2 => a,
199             _ => return crate::cbor_type_error(&value, "arr len 2"),
200         };
201         let val = a.remove(1);
202         let code = i32::from_cbor_value(a.remove(0))?;
203         let code = AuthGraphOperationCode::n(code).ok_or(CborError::NonEnumValue)?;
204         Ok(match code {
205             AuthGraphOperationCode::Create => Self::Create(CreateResponse::from_cbor_value(val)?),
206             AuthGraphOperationCode::Init => Self::Init(InitResponse::from_cbor_value(val)?),
207             AuthGraphOperationCode::Finish => Self::Finish(FinishResponse::from_cbor_value(val)?),
208             AuthGraphOperationCode::AuthenticationComplete => {
209                 Self::AuthenticationComplete(AuthenticationCompleteResponse::from_cbor_value(val)?)
210             }
211         })
212     }
to_cbor_value(self) -> Result<Value, CborError>213     fn to_cbor_value(self) -> Result<Value, CborError> {
214         Ok(Value::Array(match self {
215             Self::Create(req) => vec![req.value(), req.to_cbor_value()?],
216             Self::Init(req) => vec![req.value(), req.to_cbor_value()?],
217             Self::Finish(req) => vec![req.value(), req.to_cbor_value()?],
218             Self::AuthenticationComplete(req) => vec![req.value(), req.to_cbor_value()?],
219         }))
220     }
221 }
222 
223 // Result of an operation, as an error code and a response message (only present when
224 // `error_code` is zero).
225 #[derive(Debug, Clone, PartialEq, Eq, AsCborValue)]
226 pub struct PerformOpResponse {
227     pub error_code: ErrorCode,
228     pub rsp: Option<PerformOpRsp>,
229 }
230 
231 #[derive(Debug, Clone, Copy, PartialEq, Eq, AsCborValue)]
232 #[repr(i32)]
233 pub enum ErrorCode {
234     // Internal error codes corresponding to values in `Error.aidl`.
235     /// Success
236     Ok = 0,
237     /// Invalid peer nonce for key agreement
238     InvalidPeerNonce = -1,
239     /// Invalid key agreement public key by the peer
240     InvalidPeerKeKey = -2,
241     /// Invalid identity of the peer
242     InvalidIdentity = -3,
243     /// Invalid certificate chain in the identity of the peer
244     InvalidCertChain = -4,
245     /// Invalid signature by the peer
246     InvalidSignature = -5,
247     /// Invalid key agreement key created by a particular party themselves to be used as a handle
248     InvalidKeKey = -6,
249     /// Invalid public key in the `Key` struct
250     InvalidPubKeyInKey = -7,
251     /// Invalid private key arc in the `Key` struct
252     InvalidPrivKeyArcInKey = -8,
253     /// Invalid shared key arcs
254     InvalidSharedKeyArcs = -9,
255     /// Memory allocation failed
256     MemoryAllocationFailed = -10,
257     /// The protocol version negotiated with the sink is incompatible
258     IncompatibleProtocolVersion = -11,
259 
260     // Error codes corresponding to Binder error values.
261     /// Internal processing error
262     InternalError = -12,
263     /// Unimplemented
264     Unimplemented = -13,
265 }
266 
267 /// Trait that associates an [`AuthGraphOperationCode`] with a message.
268 pub trait Code {
269     /// Return the enum value associated with the underlying type of this item.
code(&self) -> AuthGraphOperationCode270     fn code(&self) -> AuthGraphOperationCode;
271 
272     /// Return a [`Value`] holding the enum value.
value(&self) -> Value273     fn value(&self) -> Value {
274         Value::Integer((self.code() as i32).into())
275     }
276 }
277 
278 macro_rules! impl_code {
279     { $req:ident => $code:ident } => {
280         impl Code for $req {
281             fn code(&self) -> AuthGraphOperationCode {
282                 AuthGraphOperationCode::$code
283             }
284         }
285     }
286 }
287 
288 impl_code!(CreateRequest => Create);
289 impl_code!(InitRequest => Init);
290 impl_code!(FinishRequest => Finish);
291 impl_code!(AuthenticationCompleteRequest => AuthenticationComplete);
292 impl_code!(CreateResponse => Create);
293 impl_code!(InitResponse => Init);
294 impl_code!(FinishResponse => Finish);
295 impl_code!(AuthenticationCompleteResponse => AuthenticationComplete);
296