1*3f8e9d82SAndroid Build Coastguard Worker /*
2*3f8e9d82SAndroid Build Coastguard Worker * Copyright (C) 2023 The Android Open Source Project
3*3f8e9d82SAndroid Build Coastguard Worker *
4*3f8e9d82SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*3f8e9d82SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*3f8e9d82SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*3f8e9d82SAndroid Build Coastguard Worker *
8*3f8e9d82SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*3f8e9d82SAndroid Build Coastguard Worker *
10*3f8e9d82SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*3f8e9d82SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*3f8e9d82SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*3f8e9d82SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*3f8e9d82SAndroid Build Coastguard Worker * limitations under the License.
15*3f8e9d82SAndroid Build Coastguard Worker */
16*3f8e9d82SAndroid Build Coastguard Worker
17*3f8e9d82SAndroid Build Coastguard Worker //! Rust types used for CBOR-encoded communication between HAL and TA,
18*3f8e9d82SAndroid Build Coastguard Worker //! corresponding to the schema in `comm/InternalHalTaMessages.cddl`.
19*3f8e9d82SAndroid Build Coastguard Worker
20*3f8e9d82SAndroid Build Coastguard Worker #![allow(missing_docs)] // needed for `enumn::N`, sadly
21*3f8e9d82SAndroid Build Coastguard Worker
22*3f8e9d82SAndroid Build Coastguard Worker use alloc::{string::String, vec, vec::Vec};
23*3f8e9d82SAndroid Build Coastguard Worker use ciborium::value::Value;
24*3f8e9d82SAndroid Build Coastguard Worker use coset::{AsCborValue, CborSerializable, CoseError};
25*3f8e9d82SAndroid Build Coastguard Worker use enumn::N;
26*3f8e9d82SAndroid Build Coastguard Worker
27*3f8e9d82SAndroid Build Coastguard Worker /// Wrapper type for communicating requests between the HAL service and the TA.
28*3f8e9d82SAndroid Build Coastguard Worker /// This is an internal implementation detail, and is not visible on the API.
29*3f8e9d82SAndroid Build Coastguard Worker #[derive(Debug, Clone, PartialEq, Eq)]
30*3f8e9d82SAndroid Build Coastguard Worker pub enum PerformOpReq {
31*3f8e9d82SAndroid Build Coastguard Worker /// A secret management request holds a CBOR-encoded `COSE_Encrypt0`.
32*3f8e9d82SAndroid Build Coastguard Worker SecretManagement(Vec<u8>),
33*3f8e9d82SAndroid Build Coastguard Worker
34*3f8e9d82SAndroid Build Coastguard Worker /// A (plaintext) request to delete some `SecretId`s.
35*3f8e9d82SAndroid Build Coastguard Worker DeleteIds(Vec<SecretId>),
36*3f8e9d82SAndroid Build Coastguard Worker
37*3f8e9d82SAndroid Build Coastguard Worker /// A (plaintext) request to delete all data.
38*3f8e9d82SAndroid Build Coastguard Worker DeleteAll,
39*3f8e9d82SAndroid Build Coastguard Worker
40*3f8e9d82SAndroid Build Coastguard Worker GetSecretkeeperIdentity,
41*3f8e9d82SAndroid Build Coastguard Worker }
42*3f8e9d82SAndroid Build Coastguard Worker
43*3f8e9d82SAndroid Build Coastguard Worker impl PerformOpReq {
code(&self) -> OpCode44*3f8e9d82SAndroid Build Coastguard Worker pub fn code(&self) -> OpCode {
45*3f8e9d82SAndroid Build Coastguard Worker match self {
46*3f8e9d82SAndroid Build Coastguard Worker Self::SecretManagement(_) => OpCode::SecretManagement,
47*3f8e9d82SAndroid Build Coastguard Worker Self::DeleteIds(_) => OpCode::DeleteIds,
48*3f8e9d82SAndroid Build Coastguard Worker Self::DeleteAll => OpCode::DeleteAll,
49*3f8e9d82SAndroid Build Coastguard Worker Self::GetSecretkeeperIdentity => OpCode::GetSecretkeeperIdentity,
50*3f8e9d82SAndroid Build Coastguard Worker }
51*3f8e9d82SAndroid Build Coastguard Worker }
52*3f8e9d82SAndroid Build Coastguard Worker }
53*3f8e9d82SAndroid Build Coastguard Worker
54*3f8e9d82SAndroid Build Coastguard Worker impl AsCborValue for PerformOpReq {
to_cbor_value(self) -> Result<Value, CoseError>55*3f8e9d82SAndroid Build Coastguard Worker fn to_cbor_value(self) -> Result<Value, CoseError> {
56*3f8e9d82SAndroid Build Coastguard Worker Ok(Value::Array(match self {
57*3f8e9d82SAndroid Build Coastguard Worker Self::SecretManagement(encrypt0) => {
58*3f8e9d82SAndroid Build Coastguard Worker vec![OpCode::SecretManagement.to_cbor_value()?, Value::Bytes(encrypt0)]
59*3f8e9d82SAndroid Build Coastguard Worker }
60*3f8e9d82SAndroid Build Coastguard Worker Self::DeleteIds(ids) => {
61*3f8e9d82SAndroid Build Coastguard Worker vec![
62*3f8e9d82SAndroid Build Coastguard Worker OpCode::DeleteIds.to_cbor_value()?,
63*3f8e9d82SAndroid Build Coastguard Worker Value::Array(
64*3f8e9d82SAndroid Build Coastguard Worker ids.into_iter().map(|id| Value::Bytes(id.to_vec())).collect::<Vec<Value>>(),
65*3f8e9d82SAndroid Build Coastguard Worker ),
66*3f8e9d82SAndroid Build Coastguard Worker ]
67*3f8e9d82SAndroid Build Coastguard Worker }
68*3f8e9d82SAndroid Build Coastguard Worker Self::DeleteAll => vec![OpCode::DeleteAll.to_cbor_value()?, Value::Null],
69*3f8e9d82SAndroid Build Coastguard Worker Self::GetSecretkeeperIdentity => {
70*3f8e9d82SAndroid Build Coastguard Worker vec![OpCode::GetSecretkeeperIdentity.to_cbor_value()?, Value::Null]
71*3f8e9d82SAndroid Build Coastguard Worker }
72*3f8e9d82SAndroid Build Coastguard Worker }))
73*3f8e9d82SAndroid Build Coastguard Worker }
74*3f8e9d82SAndroid Build Coastguard Worker
from_cbor_value(value: Value) -> Result<Self, CoseError>75*3f8e9d82SAndroid Build Coastguard Worker fn from_cbor_value(value: Value) -> Result<Self, CoseError> {
76*3f8e9d82SAndroid Build Coastguard Worker let mut a = match value {
77*3f8e9d82SAndroid Build Coastguard Worker Value::Array(a) if a.len() == 2 => a,
78*3f8e9d82SAndroid Build Coastguard Worker _ => return cbor_type_error(&value, "arr len 2"),
79*3f8e9d82SAndroid Build Coastguard Worker };
80*3f8e9d82SAndroid Build Coastguard Worker let val = a.remove(1);
81*3f8e9d82SAndroid Build Coastguard Worker let code = OpCode::from_cbor_value(a.remove(0))?;
82*3f8e9d82SAndroid Build Coastguard Worker Ok(match code {
83*3f8e9d82SAndroid Build Coastguard Worker OpCode::SecretManagement => Self::SecretManagement(match val {
84*3f8e9d82SAndroid Build Coastguard Worker Value::Bytes(b) => b,
85*3f8e9d82SAndroid Build Coastguard Worker _ => return cbor_type_error(&val, "bstr"),
86*3f8e9d82SAndroid Build Coastguard Worker }),
87*3f8e9d82SAndroid Build Coastguard Worker OpCode::DeleteIds => {
88*3f8e9d82SAndroid Build Coastguard Worker let ids = match &val {
89*3f8e9d82SAndroid Build Coastguard Worker Value::Array(a) => a,
90*3f8e9d82SAndroid Build Coastguard Worker _ => return cbor_type_error(&val, "arr"),
91*3f8e9d82SAndroid Build Coastguard Worker };
92*3f8e9d82SAndroid Build Coastguard Worker let ids = ids
93*3f8e9d82SAndroid Build Coastguard Worker .iter()
94*3f8e9d82SAndroid Build Coastguard Worker .map(|id| match &id {
95*3f8e9d82SAndroid Build Coastguard Worker Value::Bytes(b) => SecretId::try_from(b.as_slice())
96*3f8e9d82SAndroid Build Coastguard Worker .map_err(|_e| CoseError::OutOfRangeIntegerValue),
97*3f8e9d82SAndroid Build Coastguard Worker _ => cbor_type_error(&val, "bstr"),
98*3f8e9d82SAndroid Build Coastguard Worker })
99*3f8e9d82SAndroid Build Coastguard Worker .collect::<Result<Vec<_>, _>>()?;
100*3f8e9d82SAndroid Build Coastguard Worker Self::DeleteIds(ids)
101*3f8e9d82SAndroid Build Coastguard Worker }
102*3f8e9d82SAndroid Build Coastguard Worker OpCode::DeleteAll => {
103*3f8e9d82SAndroid Build Coastguard Worker if !val.is_null() {
104*3f8e9d82SAndroid Build Coastguard Worker return cbor_type_error(&val, "nil");
105*3f8e9d82SAndroid Build Coastguard Worker }
106*3f8e9d82SAndroid Build Coastguard Worker Self::DeleteAll
107*3f8e9d82SAndroid Build Coastguard Worker }
108*3f8e9d82SAndroid Build Coastguard Worker OpCode::GetSecretkeeperIdentity => {
109*3f8e9d82SAndroid Build Coastguard Worker if !val.is_null() {
110*3f8e9d82SAndroid Build Coastguard Worker return cbor_type_error(&val, "nil");
111*3f8e9d82SAndroid Build Coastguard Worker }
112*3f8e9d82SAndroid Build Coastguard Worker Self::GetSecretkeeperIdentity
113*3f8e9d82SAndroid Build Coastguard Worker }
114*3f8e9d82SAndroid Build Coastguard Worker })
115*3f8e9d82SAndroid Build Coastguard Worker }
116*3f8e9d82SAndroid Build Coastguard Worker }
117*3f8e9d82SAndroid Build Coastguard Worker
118*3f8e9d82SAndroid Build Coastguard Worker impl CborSerializable for PerformOpReq {}
119*3f8e9d82SAndroid Build Coastguard Worker
120*3f8e9d82SAndroid Build Coastguard Worker /// Op code value to distinguish requests.
121*3f8e9d82SAndroid Build Coastguard Worker #[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, N)]
122*3f8e9d82SAndroid Build Coastguard Worker pub enum OpCode {
123*3f8e9d82SAndroid Build Coastguard Worker SecretManagement = 0x10,
124*3f8e9d82SAndroid Build Coastguard Worker DeleteIds = 0x11,
125*3f8e9d82SAndroid Build Coastguard Worker DeleteAll = 0x12,
126*3f8e9d82SAndroid Build Coastguard Worker GetSecretkeeperIdentity = 0x13,
127*3f8e9d82SAndroid Build Coastguard Worker }
128*3f8e9d82SAndroid Build Coastguard Worker
129*3f8e9d82SAndroid Build Coastguard Worker impl AsCborValue for OpCode {
to_cbor_value(self) -> Result<Value, CoseError>130*3f8e9d82SAndroid Build Coastguard Worker fn to_cbor_value(self) -> Result<Value, CoseError> {
131*3f8e9d82SAndroid Build Coastguard Worker Ok(Value::Integer((self as i32).into()))
132*3f8e9d82SAndroid Build Coastguard Worker }
133*3f8e9d82SAndroid Build Coastguard Worker
from_cbor_value(value: Value) -> Result<Self, CoseError>134*3f8e9d82SAndroid Build Coastguard Worker fn from_cbor_value(value: Value) -> Result<Self, CoseError> {
135*3f8e9d82SAndroid Build Coastguard Worker let i = match value {
136*3f8e9d82SAndroid Build Coastguard Worker Value::Integer(i) => i,
137*3f8e9d82SAndroid Build Coastguard Worker _ => return cbor_type_error(&value, "int"),
138*3f8e9d82SAndroid Build Coastguard Worker };
139*3f8e9d82SAndroid Build Coastguard Worker let code: i32 = i.try_into().map_err(|_| CoseError::OutOfRangeIntegerValue)?;
140*3f8e9d82SAndroid Build Coastguard Worker OpCode::n(code).ok_or(CoseError::OutOfRangeIntegerValue)
141*3f8e9d82SAndroid Build Coastguard Worker }
142*3f8e9d82SAndroid Build Coastguard Worker }
143*3f8e9d82SAndroid Build Coastguard Worker
144*3f8e9d82SAndroid Build Coastguard Worker /// Wrapper type for communicating responses between the HAL service and the TA.
145*3f8e9d82SAndroid Build Coastguard Worker /// This is an internal implementation detail, and is not visible on the API.
146*3f8e9d82SAndroid Build Coastguard Worker #[derive(Debug, Clone, PartialEq, Eq)]
147*3f8e9d82SAndroid Build Coastguard Worker pub enum PerformOpResponse {
148*3f8e9d82SAndroid Build Coastguard Worker Success(PerformOpSuccessRsp),
149*3f8e9d82SAndroid Build Coastguard Worker Failure(ApiError),
150*3f8e9d82SAndroid Build Coastguard Worker }
151*3f8e9d82SAndroid Build Coastguard Worker
152*3f8e9d82SAndroid Build Coastguard Worker impl PerformOpResponse {
err_code(&self) -> AidlErrorCode153*3f8e9d82SAndroid Build Coastguard Worker pub fn err_code(&self) -> AidlErrorCode {
154*3f8e9d82SAndroid Build Coastguard Worker match self {
155*3f8e9d82SAndroid Build Coastguard Worker Self::Success(_) => AidlErrorCode::Ok,
156*3f8e9d82SAndroid Build Coastguard Worker Self::Failure(err) => err.err_code,
157*3f8e9d82SAndroid Build Coastguard Worker }
158*3f8e9d82SAndroid Build Coastguard Worker }
159*3f8e9d82SAndroid Build Coastguard Worker }
160*3f8e9d82SAndroid Build Coastguard Worker
161*3f8e9d82SAndroid Build Coastguard Worker impl AsCborValue for PerformOpResponse {
to_cbor_value(self) -> Result<Value, CoseError>162*3f8e9d82SAndroid Build Coastguard Worker fn to_cbor_value(self) -> Result<Value, CoseError> {
163*3f8e9d82SAndroid Build Coastguard Worker Ok(match self {
164*3f8e9d82SAndroid Build Coastguard Worker Self::Success(rsp) => {
165*3f8e9d82SAndroid Build Coastguard Worker Value::Array(vec![Value::Integer(0.into()), rsp.to_cbor_value()?])
166*3f8e9d82SAndroid Build Coastguard Worker }
167*3f8e9d82SAndroid Build Coastguard Worker Self::Failure(err) => Value::Array(vec![
168*3f8e9d82SAndroid Build Coastguard Worker Value::Integer((err.err_code as i32).into()),
169*3f8e9d82SAndroid Build Coastguard Worker Value::Text(err.msg),
170*3f8e9d82SAndroid Build Coastguard Worker ]),
171*3f8e9d82SAndroid Build Coastguard Worker })
172*3f8e9d82SAndroid Build Coastguard Worker }
173*3f8e9d82SAndroid Build Coastguard Worker
from_cbor_value(value: Value) -> Result<Self, CoseError>174*3f8e9d82SAndroid Build Coastguard Worker fn from_cbor_value(value: Value) -> Result<Self, CoseError> {
175*3f8e9d82SAndroid Build Coastguard Worker let mut a = match value {
176*3f8e9d82SAndroid Build Coastguard Worker Value::Array(a) if a.len() == 2 => a,
177*3f8e9d82SAndroid Build Coastguard Worker _ => return cbor_type_error(&value, "arr len 2"),
178*3f8e9d82SAndroid Build Coastguard Worker };
179*3f8e9d82SAndroid Build Coastguard Worker let val = a.remove(1);
180*3f8e9d82SAndroid Build Coastguard Worker let err_code =
181*3f8e9d82SAndroid Build Coastguard Worker a.remove(0).as_integer().ok_or(CoseError::UnexpectedItem("non-int", "int"))?;
182*3f8e9d82SAndroid Build Coastguard Worker let err_code: i32 = err_code.try_into().map_err(|_| CoseError::OutOfRangeIntegerValue)?;
183*3f8e9d82SAndroid Build Coastguard Worker Ok(match err_code {
184*3f8e9d82SAndroid Build Coastguard Worker 0 => Self::Success(PerformOpSuccessRsp::from_cbor_value(val)?),
185*3f8e9d82SAndroid Build Coastguard Worker err_code => {
186*3f8e9d82SAndroid Build Coastguard Worker let msg = match val {
187*3f8e9d82SAndroid Build Coastguard Worker Value::Text(t) => t,
188*3f8e9d82SAndroid Build Coastguard Worker _ => return cbor_type_error(&val, "tstr"),
189*3f8e9d82SAndroid Build Coastguard Worker };
190*3f8e9d82SAndroid Build Coastguard Worker let err_code = AidlErrorCode::n(err_code).unwrap_or(AidlErrorCode::InternalError);
191*3f8e9d82SAndroid Build Coastguard Worker Self::Failure(ApiError { err_code, msg })
192*3f8e9d82SAndroid Build Coastguard Worker }
193*3f8e9d82SAndroid Build Coastguard Worker })
194*3f8e9d82SAndroid Build Coastguard Worker }
195*3f8e9d82SAndroid Build Coastguard Worker }
196*3f8e9d82SAndroid Build Coastguard Worker
197*3f8e9d82SAndroid Build Coastguard Worker impl CborSerializable for PerformOpResponse {}
198*3f8e9d82SAndroid Build Coastguard Worker
199*3f8e9d82SAndroid Build Coastguard Worker /// Inner response type holding the result of a successful request.
200*3f8e9d82SAndroid Build Coastguard Worker #[derive(Debug, Clone, PartialEq, Eq)]
201*3f8e9d82SAndroid Build Coastguard Worker pub enum PerformOpSuccessRsp {
202*3f8e9d82SAndroid Build Coastguard Worker ProtectedResponse(Vec<u8>),
203*3f8e9d82SAndroid Build Coastguard Worker Empty,
204*3f8e9d82SAndroid Build Coastguard Worker }
205*3f8e9d82SAndroid Build Coastguard Worker
206*3f8e9d82SAndroid Build Coastguard Worker impl AsCborValue for PerformOpSuccessRsp {
to_cbor_value(self) -> Result<Value, CoseError>207*3f8e9d82SAndroid Build Coastguard Worker fn to_cbor_value(self) -> Result<Value, CoseError> {
208*3f8e9d82SAndroid Build Coastguard Worker Ok(match self {
209*3f8e9d82SAndroid Build Coastguard Worker Self::ProtectedResponse(data) => Value::Bytes(data),
210*3f8e9d82SAndroid Build Coastguard Worker Self::Empty => Value::Null,
211*3f8e9d82SAndroid Build Coastguard Worker })
212*3f8e9d82SAndroid Build Coastguard Worker }
213*3f8e9d82SAndroid Build Coastguard Worker
from_cbor_value(value: Value) -> Result<Self, CoseError>214*3f8e9d82SAndroid Build Coastguard Worker fn from_cbor_value(value: Value) -> Result<Self, CoseError> {
215*3f8e9d82SAndroid Build Coastguard Worker match value {
216*3f8e9d82SAndroid Build Coastguard Worker Value::Bytes(data) => Ok(Self::ProtectedResponse(data)),
217*3f8e9d82SAndroid Build Coastguard Worker Value::Null => Ok(Self::Empty),
218*3f8e9d82SAndroid Build Coastguard Worker _ => cbor_type_error(&value, "bstr/nil"),
219*3f8e9d82SAndroid Build Coastguard Worker }
220*3f8e9d82SAndroid Build Coastguard Worker }
221*3f8e9d82SAndroid Build Coastguard Worker }
222*3f8e9d82SAndroid Build Coastguard Worker
223*3f8e9d82SAndroid Build Coastguard Worker impl CborSerializable for PerformOpSuccessRsp {}
224*3f8e9d82SAndroid Build Coastguard Worker
225*3f8e9d82SAndroid Build Coastguard Worker /// Return an error indicating that an unexpected CBOR type was encountered.
cbor_type_error<T>(got: &Value, want: &'static str) -> Result<T, CoseError>226*3f8e9d82SAndroid Build Coastguard Worker pub fn cbor_type_error<T>(got: &Value, want: &'static str) -> Result<T, CoseError> {
227*3f8e9d82SAndroid Build Coastguard Worker let got = match got {
228*3f8e9d82SAndroid Build Coastguard Worker Value::Integer(_) => "int",
229*3f8e9d82SAndroid Build Coastguard Worker Value::Bytes(_) => "bstr",
230*3f8e9d82SAndroid Build Coastguard Worker Value::Text(_) => "tstr",
231*3f8e9d82SAndroid Build Coastguard Worker Value::Array(_) => "array",
232*3f8e9d82SAndroid Build Coastguard Worker Value::Map(_) => "map",
233*3f8e9d82SAndroid Build Coastguard Worker Value::Tag(_, _) => "tag",
234*3f8e9d82SAndroid Build Coastguard Worker Value::Float(_) => "float",
235*3f8e9d82SAndroid Build Coastguard Worker Value::Bool(_) => "bool",
236*3f8e9d82SAndroid Build Coastguard Worker Value::Null => "null",
237*3f8e9d82SAndroid Build Coastguard Worker _ => "unknown",
238*3f8e9d82SAndroid Build Coastguard Worker };
239*3f8e9d82SAndroid Build Coastguard Worker Err(CoseError::UnexpectedItem(got, want))
240*3f8e9d82SAndroid Build Coastguard Worker }
241*3f8e9d82SAndroid Build Coastguard Worker
242*3f8e9d82SAndroid Build Coastguard Worker /// Identifier for a secret
243*3f8e9d82SAndroid Build Coastguard Worker pub type SecretId = [u8; 64];
244*3f8e9d82SAndroid Build Coastguard Worker
245*3f8e9d82SAndroid Build Coastguard Worker /// Error information reported visibly on the external API.
246*3f8e9d82SAndroid Build Coastguard Worker #[derive(Debug, Clone, PartialEq, Eq)]
247*3f8e9d82SAndroid Build Coastguard Worker pub struct ApiError {
248*3f8e9d82SAndroid Build Coastguard Worker pub err_code: AidlErrorCode,
249*3f8e9d82SAndroid Build Coastguard Worker pub msg: String,
250*3f8e9d82SAndroid Build Coastguard Worker }
251*3f8e9d82SAndroid Build Coastguard Worker
252*3f8e9d82SAndroid Build Coastguard Worker /// Error codes emitted as service specific errors at the HAL.
253*3f8e9d82SAndroid Build Coastguard Worker /// Keep in sync with the ERROR_ codes in:
254*3f8e9d82SAndroid Build Coastguard Worker /// hardware/interfaces/security/secretkeeper/aidl/
255*3f8e9d82SAndroid Build Coastguard Worker /// android/hardware/security/secretkeeper/ISecretkeeper.aidl
256*3f8e9d82SAndroid Build Coastguard Worker #[derive(Debug, Clone, Copy, PartialEq, Eq, N)]
257*3f8e9d82SAndroid Build Coastguard Worker pub enum AidlErrorCode {
258*3f8e9d82SAndroid Build Coastguard Worker Ok = 0,
259*3f8e9d82SAndroid Build Coastguard Worker UnknownKeyId = 1,
260*3f8e9d82SAndroid Build Coastguard Worker InternalError = 2,
261*3f8e9d82SAndroid Build Coastguard Worker RequestMalformed = 3,
262*3f8e9d82SAndroid Build Coastguard Worker }
263