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