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 17 //! Version 1 of the PinWeaver storage daemon interface. 18 19 use crate::util::{serde_fields, serde_zerocopy, SerdeVec}; 20 use std::fmt::Debug; 21 use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout}; 22 23 pub mod request; 24 pub mod response; 25 26 /// The port on the PinWeaver Trusty app that the storage daemon connects to. 27 pub const PORT: &str = "com.android.desktop.security.PinWeaverStorage.V1"; 28 29 // These are also the parameters used currently on ChromeOS devices. 30 31 /// The default height for the hash tree. 32 pub const MAX_TREE_HEIGHT: u8 = 7; 33 34 /// The default number of bits used to index into the tree per level of the tree. 35 pub const MAX_TREE_BITS_PER_LEVEL: u8 = 2; 36 37 /// The number of auxiliary hashes that need to be updated per-request. 38 pub const MAX_AUX_HASHES: u32 = 39 ((1 << MAX_TREE_BITS_PER_LEVEL as u32) - 1) * MAX_TREE_HEIGHT as u32; 40 41 /// Kept in sync with the size of [`wrapped_leaf_data_t`] 42 /// 43 /// [`wrapped_leaf_data_t`]: https://chromium.googlesource.com/chromiumos/platform/pinweaver/+/refs/heads/main/pinweaver.h#88 44 pub const LEAF_SIZE: u32 = 389; 45 46 /// The maximum supported high-entropy key size provided by the client. 47 /// 48 /// Increasing this much further will require protocol restructuring 49 /// as it can't be sent in a single datagram over vsock. 50 pub const MAX_LARGE_SECRET_SIZE: u32 = 1024; 51 52 /// The interface to communicate with the storage daemon. 53 pub trait StorageInterface: 'static + Sync + Send { 54 /// The error while executing a storage request. 55 type Error: Debug; 56 57 /// Execute a storage request. request(&self, request: &StorageRequest) -> Result<StorageResponse, Self::Error>58 fn request(&self, request: &StorageRequest) -> Result<StorageResponse, Self::Error>; 59 } 60 61 pub use request::StorageRequest; 62 pub use response::StorageResponse; 63 64 /// Unaligned `u32` - used for [`IntoBytes`] structs to prevent padding. 65 pub type U32 = zerocopy::byteorder::U32<zerocopy::byteorder::LE>; 66 67 /// A leaf identifier, distinct from a [`Path`] and specific to the Android PinWeaver API. 68 /// 69 /// Both the leaf set and inner ID are client-chosen. 70 /// 71 /// This has a 1:1 mapping with some [`Path`] on this device, 72 /// except when a leaf with some ID is currently being replaced. 73 #[derive(FromBytes, KnownLayout, Immutable, IntoBytes)] 74 #[repr(C)] 75 pub struct LeafId { 76 /// The group this leaf ID belongs to. See `LeafSet.aidl`. 77 pub leaf_set: U32, 78 79 /// The semantic meaning of the `inner_id` is specific to the `leaf_set`. 80 pub inner_id: U32, 81 } 82 83 /// A PinWeaver leaf path, indicating where in the hash tree a leaf is located. 84 #[derive(Clone, Copy, FromBytes, KnownLayout, Immutable, IntoBytes)] 85 #[repr(transparent)] 86 pub struct Path(pub [u8; 8]); 87 88 /// The encrypted contents of a PinWeaver leaf on-disk. 89 pub type LeafContents = SerdeVec<u8, LEAF_SIZE>; 90 91 /// Parameters for a PinWeaver hash tree. 92 #[derive(FromBytes, KnownLayout, Immutable, IntoBytes)] 93 #[repr(C)] 94 pub struct TreeParams { 95 /// The height of the new tree. 96 pub height: u8, 97 98 /// The number of bits in the path used per tree level. 99 /// This is log2(fan-out factor). 100 pub bits_per_level: u8, 101 } 102 103 #[derive(FromBytes, KnownLayout, Immutable, IntoBytes)] 104 #[repr(transparent)] 105 /// A SHA-256 digest. 106 pub struct TreeHash(pub [u8; 32]); 107 108 /// A set of auxiliary hashes for a tree. 109 pub type TreeHashes = SerdeVec<TreeHash, MAX_AUX_HASHES>; 110 111 /// When PinWeaver needs to store a high-entropy secret that is larger than 112 /// 32 bytes, the leaf's secret is an AES key used with these parameters. 113 #[repr(C)] 114 pub struct LargeSecretInfo { 115 /// The IV for the ciphertext/key. Must not be reused. 116 pub iv: LargeSecretIv, 117 118 /// The GCM authentication tag used to verify that the low-entropy secret 119 /// is associated with this ciphertext. 120 pub auth_tag: LargeSecretAuthTag, 121 122 /// The encrypted high-entropy secret, decrypted with the key stored on the PinWeaver leaf. 123 pub secret_ciphertext: SerdeVec<u8, MAX_LARGE_SECRET_SIZE>, 124 } 125 126 /// An AES-256 Initialization Vector. 127 #[derive(FromBytes, KnownLayout, Immutable, IntoBytes)] 128 #[repr(transparent)] 129 pub struct LargeSecretIv(pub [u8; 12]); 130 131 /// The GCM [authentication tag] ensuring integrity of large-secret data. 132 /// 133 /// [authentication tag]: https://en.wikipedia.org/wiki/Authenticated_encryption 134 #[derive(FromBytes, KnownLayout, Immutable, IntoBytes)] 135 #[repr(transparent)] 136 pub struct LargeSecretAuthTag(pub [u8; 4]); 137 138 serde_fields! { 139 LargeSecretInfo { iv, auth_tag, secret_ciphertext }, 140 } 141 serde_zerocopy!(TreeHash, LeafId, Path, LargeSecretAuthTag, LargeSecretIv); 142