• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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