xref: /aosp_15_r20/system/secretkeeper/comm/src/data_types/request_response_impl.rs (revision 3f8e9d82f4020c68ad19a99fc5fdc1fc90b79379)
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //! Implementation of request & response like data structures.
18 
19 // derive(N) generates a method that is missing a docstring.
20 #![allow(missing_docs)]
21 
22 use crate::cbor_convert::value_to_integer;
23 use crate::data_types::error::Error;
24 use crate::data_types::error::ERROR_OK;
25 use crate::data_types::request::Request;
26 use crate::data_types::response::Response;
27 use crate::data_types::{Id, Secret};
28 use alloc::boxed::Box;
29 use alloc::vec;
30 use alloc::vec::Vec;
31 use ciborium::Value;
32 use coset::AsCborValue;
33 use enumn::N;
34 
35 /// Set of all possible `Opcode` supported by SecretManagement API of the HAL.
36 /// See `Opcode` in SecretManagement.cddl
37 #[derive(Clone, Copy, Debug, N, PartialEq)]
38 #[non_exhaustive]
39 pub enum Opcode {
40     /// Get version of the SecretManagement API.
41     GetVersion = 1,
42     /// Store a secret
43     StoreSecret = 2,
44     /// Get the secret
45     GetSecret = 3,
46 }
47 
48 /// Corresponds to `GetVersionRequestPacket` defined in SecretManagement.cddl
49 #[derive(Clone, Debug, Eq, PartialEq)]
50 pub struct GetVersionRequest;
51 
52 impl Request for GetVersionRequest {
53     const OPCODE: Opcode = Opcode::GetVersion;
54 
new(args: Vec<Value>) -> Result<Box<Self>, Error>55     fn new(args: Vec<Value>) -> Result<Box<Self>, Error> {
56         if !args.is_empty() {
57             return Err(Error::RequestMalformed);
58         }
59         Ok(Box::new(Self))
60     }
61 
args(&self) -> Vec<Value>62     fn args(&self) -> Vec<Value> {
63         Vec::new()
64     }
65 }
66 
67 /// Success response corresponding to `GetVersionResponsePacket`.
68 #[derive(Clone, Debug, Eq, PartialEq)]
69 pub struct GetVersionResponse {
70     /// Version of SecretManagement API
71     pub version: u64,
72 }
73 
74 impl Response for GetVersionResponse {
new(res: Vec<Value>) -> Result<Box<Self>, Error>75     fn new(res: Vec<Value>) -> Result<Box<Self>, Error> {
76         if res.len() != 2 || value_to_integer(&res[0])? != ERROR_OK.into() {
77             return Err(Error::ResponseMalformed);
78         }
79         let version: u64 = value_to_integer(&res[1])?.try_into()?;
80         Ok(Box::new(Self { version }))
81     }
82 
result(&self) -> Vec<Value>83     fn result(&self) -> Vec<Value> {
84         vec![self.version.into()]
85     }
86 }
87 
88 /// Corresponds to `StoreSecretRequestPacket` in SecretManagement.cddl
89 #[derive(Clone, Debug, Eq, PartialEq)]
90 pub struct StoreSecretRequest {
91     // Unique identifier of the secret
92     pub id: Id,
93     // The secret to be stored :)
94     pub secret: Secret,
95     // The DICE policy to control access to secret
96     pub sealing_policy: Vec<u8>,
97 }
98 
99 impl Request for StoreSecretRequest {
100     const OPCODE: Opcode = Opcode::StoreSecret;
101 
new(args: Vec<Value>) -> Result<Box<Self>, Error>102     fn new(args: Vec<Value>) -> Result<Box<Self>, Error> {
103         let [id, secret, sealing_policy] = args.try_into().map_err(|_| Error::RequestMalformed)?;
104         let id = Id::from_cbor_value(id)?;
105         let secret = Secret::from_cbor_value(secret)?;
106         let sealing_policy = sealing_policy.into_bytes()?;
107         Ok(Box::new(Self { id, secret, sealing_policy }))
108     }
109 
args(&self) -> Vec<Value>110     fn args(&self) -> Vec<Value> {
111         vec![
112             Value::from(self.id.0.as_slice()),
113             Value::from(self.secret.0.as_slice()),
114             Value::from(self.sealing_policy.clone()),
115         ]
116     }
117 }
118 
119 /// Success response corresponding to `StoreSecretResponsePacket`.
120 #[derive(Clone, Debug, Eq, PartialEq)]
121 pub struct StoreSecretResponse {}
122 
123 impl Response for StoreSecretResponse {
new(response_cbor: Vec<Value>) -> Result<Box<Self>, Error>124     fn new(response_cbor: Vec<Value>) -> Result<Box<Self>, Error> {
125         if response_cbor.len() != 1 || (value_to_integer(&response_cbor[0])? != ERROR_OK.into()) {
126             return Err(Error::ResponseMalformed);
127         }
128         Ok(Box::new(Self {}))
129     }
130 }
131 
132 /// Corresponds to `GetSecretRequestPacket` in SecretManagement.cddl
133 #[derive(Clone, Debug, Eq, PartialEq)]
134 pub struct GetSecretRequest {
135     // Unique identifier of the secret.
136     pub id: Id,
137     // The new dice_policy that will replace the existing sealing_policy of the secret.
138     pub updated_sealing_policy: Option<Vec<u8>>,
139 }
140 
141 impl Request for GetSecretRequest {
142     const OPCODE: Opcode = Opcode::GetSecret;
143 
new(args: Vec<Value>) -> Result<Box<Self>, Error>144     fn new(args: Vec<Value>) -> Result<Box<Self>, Error> {
145         let [id, sealing_policy] = args.try_into().map_err(|_| Error::RequestMalformed)?;
146         let id = Id::from_cbor_value(id).map_err(|_| Error::RequestMalformed)?;
147         let updated_sealing_policy =
148             if sealing_policy.is_null() { None } else { Some(sealing_policy.into_bytes()?) };
149         Ok(Box::new(Self { id, updated_sealing_policy }))
150     }
151 
args(&self) -> Vec<Value>152     fn args(&self) -> Vec<Value> {
153         let id = Value::from(self.id.0.as_slice());
154         let policy: Value =
155             self.updated_sealing_policy.as_ref().map_or(Value::Null, |x| x.as_slice().into());
156         vec![id, policy]
157     }
158 }
159 
160 /// Success response corresponding to `GetSecretResponsePacket`.
161 #[derive(Clone, Debug, Eq, PartialEq)]
162 pub struct GetSecretResponse {
163     pub secret: Secret,
164 }
165 
166 impl Response for GetSecretResponse {
new(res: Vec<Value>) -> Result<Box<Self>, Error>167     fn new(res: Vec<Value>) -> Result<Box<Self>, Error> {
168         let [error_code, secret] = res.try_into().map_err(|_| Error::ResponseMalformed)?;
169         if error_code != ERROR_OK.into() {
170             return Err(Error::ResponseMalformed);
171         }
172         let secret = Secret::from_cbor_value(secret).map_err(|_| Error::ResponseMalformed)?;
173         Ok(Box::new(Self { secret }))
174     }
175 
result(&self) -> Vec<Value>176     fn result(&self) -> Vec<Value> {
177         vec![self.secret.0.as_slice().into()]
178     }
179 }
180