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