1 /* 2 * Copyright (c) 2024, 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 //! v1 storage response 17 18 use super::{LargeSecretInfo, LeafContents, LeafId, Path, TreeHash, TreeHashes, TreeParams, U32}; 19 use crate::util::{serde_enums, serde_fields, serde_zerocopy, SerdeOption}; 20 use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout}; 21 22 /// The response from the storage daemon. 23 pub struct StorageResponse { 24 /// Header info that is serialized contiguously. 25 pub header: StorageResponseHeader, 26 27 /// The operation-specific data for a storage response. 28 pub op_data: StorageResponseData, 29 } 30 31 /// The header for [`StorageResponse`]. 32 #[derive(FromBytes, KnownLayout, Immutable, IntoBytes)] 33 #[repr(C)] 34 pub struct StorageResponseHeader { 35 /// The status of executing the request; check this first. 36 pub status: ResponseStatus, 37 38 /// The current root hash for the tree. 39 pub root_hash: TreeHash, 40 } 41 42 /// The response when getting the status of PinWeaver. 43 #[derive(FromBytes, KnownLayout, Immutable, IntoBytes)] 44 #[repr(C)] 45 pub struct GetStatusResponse { 46 /// The parameters for the hash tree, as understood by the storage daemon. 47 pub tree_params: TreeParams, 48 } 49 50 /// The status of a storage daemon operation. 51 #[derive(FromBytes, KnownLayout, Immutable, IntoBytes)] 52 #[repr(transparent)] 53 pub struct ResponseStatus(u8); 54 55 #[allow(non_upper_case_globals)] 56 impl ResponseStatus { 57 /// Success. 58 pub const Ok: Self = Self(0); 59 60 /// An unknown internal error occurred. 61 pub const ErrUnknown: Self = Self(1); 62 } 63 64 /// The response when initializing PinWeaver on disk. 65 #[derive(FromBytes, KnownLayout, Immutable, IntoBytes)] 66 #[repr(C)] 67 pub struct InitializeResponse { 68 /// The total number of leaves in this tree. 69 pub num_hashes: U32, 70 } 71 72 /// The response when starting an operation in PinWeaver. 73 pub struct StartOpResponse { 74 /// The path of the currently operating leaf. 75 pub path: Path, 76 77 /// The current tree hashes for the specified leaf. 78 pub tree_hashes: TreeHashes, 79 80 /// The response data specific to this operation. 81 pub op_data: StartOpResponseData, 82 } 83 84 /// The response when committing an operation in PinWeaver. 85 pub struct CommitOpResponse { 86 /// The path of the leaf that was just updated. 87 pub path: Path, 88 89 /// The response data specific to this operation. 90 pub op_data: CommitOpResponseData, 91 } 92 93 serde_enums! { 94 /// The operation-specific data for a storage response. 95 pub enum StorageResponseData { 96 /// The response when getting the status of PinWeaver. 97 GetStatus(GetStatusResponse) = 0, 98 99 /// The response when initializing PinWeaver. 100 Initialize(InitializeResponse) = 1, 101 102 /// The response when starting an operation in PinWeaver. 103 StartOp(StartOpResponse) = 2, 104 105 /// The response when committing an operation in PinWeaver. 106 CommitOp(CommitOpResponse) = 3, 107 } 108 109 /// The suboperation-specific data for a start-operation response. 110 pub enum StartOpResponseData { 111 /// The response when starting insert of a new leaf. 112 Insert(StartInsertResponseData) = 0, 113 114 /// The response when starting removal of a leaf. 115 Remove(StartRemoveResponseData) = 1, 116 117 /// The response when starting to authenticate the low-entropy secret in a leaf. 118 TryAuth(StartTryAuthResponseData) = 2, 119 } 120 121 /// The suboperation-specific data for a commit-operation response. 122 pub enum CommitOpResponseData { 123 /// This suboperation has no more specific data. 124 None = 0, 125 126 /// The response when committing that a leaf replacement has finished the insert stage. 127 /// 128 /// An insert that replaces a leaf takes place in multiple stages: 129 /// 130 /// 1. Start the insert of a new leaf. 131 /// 2. Insert the leaf in the GSC. 132 /// 3. Commit the insert of that leaf to disk, and transition to the removal stage. 133 /// 4. Remove the replaced leaf in the GSC. 134 /// 5. Commit the removal of the replaced leaf to disk. 135 /// 136 /// This is the response to stage 3, containing info about the leaf to delete. 137 InsertReplace(RemoveHashes) = 1, 138 139 /// Info about the next leaf to delete. 140 RemoveBulk(CommitRemoveBulkResponseData) = 2, 141 } 142 143 /// Info about the next leaf to delete after committing the delete of a leaf. 144 pub enum CommitRemoveBulkResponseData { 145 /// Finished with bulk removal. 146 Finished = 0, 147 148 /// There are more bulk removals to perform. 149 Continue(ContinueRemoveBulkResponse) = 1, 150 } 151 } 152 153 /// The response when starting insert of a new leaf. 154 pub struct StartInsertResponseData { 155 /// The leaf path that is being replaced and will be deleted, if any. 156 pub replacing_path: SerdeOption<Path>, 157 } 158 159 /// The response when starting removal of a leaf. 160 #[derive(FromBytes, KnownLayout, Immutable, IntoBytes)] 161 #[repr(C)] 162 pub struct StartRemoveResponseData { 163 /// The HMAC of the leaf to remove. 164 pub leaf_hmac: TreeHash, 165 } 166 167 /// The response when starting to authenticate the low-entropy secret in a leaf. 168 pub struct StartTryAuthResponseData { 169 /// The size of the high-entropy secret stored by the client in bytes. 170 pub secret_size: u32, 171 172 /// The encrypted leaf contents stored on disk. 173 pub leaf_contents: LeafContents, 174 175 /// Info necessary to access a larger key than can fit in `leaf_contents`. 176 /// A large key is only used when `secret_size > 32`. 177 pub large_key_info: SerdeOption<LargeSecretInfo>, 178 } 179 180 /// Header for [`ContinueRemoveBulkResponse`]. 181 #[derive(FromBytes, KnownLayout, Immutable, IntoBytes)] 182 #[repr(C)] 183 pub struct ContinueRemoveBulkResponseHeader { 184 /// The next leaf to remove as part of this bulk removal. 185 pub id: LeafId, 186 187 /// The path of that leaf. 188 pub path: Path, 189 } 190 191 /// Response when committing the bulk removal of one leaf, 192 /// and there are more leaves to remove. 193 pub struct ContinueRemoveBulkResponse { 194 /// Header info that is serialized contiguously. 195 pub header: ContinueRemoveBulkResponseHeader, 196 197 /// Tree info about this leaf necessary to do the deletion. 198 pub hashes: RemoveHashes, 199 } 200 201 /// Response when a leaf should be removed after a commit operation. 202 pub struct RemoveHashes { 203 /// The HMAC for the leaf to remove removed. 204 pub leaf_hmac: TreeHash, 205 206 /// The tree hashes for the leaf to remove. 207 pub tree_hashes: TreeHashes, 208 } 209 210 serde_fields! { 211 StorageResponse { header, op_data }, 212 StartOpResponse { path, tree_hashes, op_data }, 213 CommitOpResponse { path, op_data }, 214 StartInsertResponseData { replacing_path }, 215 StartTryAuthResponseData { secret_size, leaf_contents, large_key_info }, 216 ContinueRemoveBulkResponse { header, hashes }, 217 RemoveHashes { leaf_hmac, tree_hashes }, 218 } 219 220 serde_zerocopy!( 221 StorageResponseHeader, 222 GetStatusResponse, 223 InitializeResponse, 224 StartRemoveResponseData, 225 ContinueRemoveBulkResponseHeader, 226 ); 227