1 // Copyright 2023, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 //! Structs and functions about the types used in DICE.
16 //! This module mirrors the content in open-dice/include/dice/dice.h
17
18 use crate::error::{check_result, Result};
19 pub use open_dice_cbor_bindgen::DiceMode;
20 use open_dice_cbor_bindgen::{
21 DiceConfigType, DiceDeriveCdiCertificateId, DiceDeriveCdiPrivateKeySeed, DiceInputValues,
22 DiceMainFlow, DICE_CDI_SIZE, DICE_HASH_SIZE, DICE_HIDDEN_SIZE, DICE_ID_SIZE,
23 DICE_INLINE_CONFIG_SIZE, DICE_PRIVATE_KEY_SEED_SIZE, DICE_PRIVATE_KEY_SIZE,
24 DICE_PUBLIC_KEY_SIZE, DICE_SIGNATURE_SIZE,
25 };
26 #[cfg(feature = "serde_derive")]
27 use serde_derive::{Deserialize, Serialize};
28 use std::{marker::PhantomData, ptr};
29 use zeroize::{Zeroize, ZeroizeOnDrop};
30
31 /// The size of a DICE hash.
32 pub const HASH_SIZE: usize = DICE_HASH_SIZE as usize;
33 /// The size of the DICE hidden value.
34 pub const HIDDEN_SIZE: usize = DICE_HIDDEN_SIZE as usize;
35 /// The size of a DICE inline config.
36 const INLINE_CONFIG_SIZE: usize = DICE_INLINE_CONFIG_SIZE as usize;
37 /// The size of a CDI.
38 pub const CDI_SIZE: usize = DICE_CDI_SIZE as usize;
39 /// The size of a private key seed.
40 pub const PRIVATE_KEY_SEED_SIZE: usize = DICE_PRIVATE_KEY_SEED_SIZE as usize;
41 /// The size of a private key.
42 pub const PRIVATE_KEY_SIZE: usize = DICE_PRIVATE_KEY_SIZE as usize;
43 /// The size of a public key.
44 pub const PUBLIC_KEY_SIZE: usize = DICE_PUBLIC_KEY_SIZE as usize;
45 /// The size of a signature.
46 pub const SIGNATURE_SIZE: usize = DICE_SIGNATURE_SIZE as usize;
47 /// The size of an ID.
48 pub const ID_SIZE: usize = DICE_ID_SIZE as usize;
49
50 /// Array type of hashes used by DICE.
51 pub type Hash = [u8; HASH_SIZE];
52 /// Array type of additional input.
53 pub type Hidden = [u8; HIDDEN_SIZE];
54 /// Array type of inline configuration values.
55 pub type InlineConfig = [u8; INLINE_CONFIG_SIZE];
56 /// Array type of CDIs.
57 pub type Cdi = [u8; CDI_SIZE];
58 /// Array type of the public key.
59 pub type PublicKey = [u8; PUBLIC_KEY_SIZE];
60 /// Array type of the signature.
61 pub type Signature = [u8; SIGNATURE_SIZE];
62 /// Array type of DICE ID.
63 pub type DiceId = [u8; ID_SIZE];
64
65 /// A trait for types that represent Dice artifacts, which include:
66 ///
67 /// - Attestation CDI
68 /// - Sealing CDI
69 /// - Boot Certificate Chain
70 ///
71 /// Types that implement this trait provide an access these artifacts.
72 pub trait DiceArtifacts {
73 /// Returns a reference to the attestation CDI.
cdi_attest(&self) -> &[u8; CDI_SIZE]74 fn cdi_attest(&self) -> &[u8; CDI_SIZE];
75
76 /// Returns a reference to the sealing CDI.
cdi_seal(&self) -> &[u8; CDI_SIZE]77 fn cdi_seal(&self) -> &[u8; CDI_SIZE];
78
79 /// Returns a reference to the Boot Certificate Chain, if present.
bcc(&self) -> Option<&[u8]>80 fn bcc(&self) -> Option<&[u8]>;
81 }
82
83 /// TODO(b/268587826): Clean up the memory cache after zeroing out the memory
84 /// for sensitive data like CDI values and private key.
85 /// CDI Values.
86 #[derive(Debug, Zeroize, ZeroizeOnDrop, Default)]
87 #[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
88 pub struct CdiValues {
89 /// Attestation CDI.
90 pub cdi_attest: [u8; CDI_SIZE],
91 /// Sealing CDI.
92 pub cdi_seal: [u8; CDI_SIZE],
93 }
94
95 /// Private key seed. The data is zeroed out when the struct is dropped.
96 #[derive(Zeroize, ZeroizeOnDrop, Default)]
97 pub struct PrivateKeySeed([u8; PRIVATE_KEY_SEED_SIZE]);
98
99 impl PrivateKeySeed {
100 /// Returns an array reference of the private key seed.
as_array(&self) -> &[u8; PRIVATE_KEY_SEED_SIZE]101 pub fn as_array(&self) -> &[u8; PRIVATE_KEY_SEED_SIZE] {
102 &self.0
103 }
104
105 /// Returns a mutable pointer to the slice buffer of the private key seed.
as_mut_ptr(&mut self) -> *mut u8106 pub fn as_mut_ptr(&mut self) -> *mut u8 {
107 self.0.as_mut_ptr()
108 }
109 }
110
111 /// Private key. The data is zeroed out when the struct is dropped.
112 #[derive(Zeroize, ZeroizeOnDrop)]
113 pub struct PrivateKey([u8; PRIVATE_KEY_SIZE]);
114
115 impl Default for PrivateKey {
116 /// Creates a new `PrivateKey` instance with all bytes set to 0.
117 ///
118 /// Since the size of the private key array is too large to be initialized
119 /// with a default value, this implementation sets all the bytes in the array
120 /// to 0 using the `[0u8; PRIVATE_KEY_SIZE]` syntax.
default() -> Self121 fn default() -> Self {
122 Self([0u8; PRIVATE_KEY_SIZE])
123 }
124 }
125
126 impl PrivateKey {
127 /// Returns an array reference of the private key.
as_array(&self) -> &[u8; PRIVATE_KEY_SIZE]128 pub fn as_array(&self) -> &[u8; PRIVATE_KEY_SIZE] {
129 &self.0
130 }
131
132 /// Returns a mutable pointer to the slice buffer of the private key.
as_mut_ptr(&mut self) -> *mut u8133 pub fn as_mut_ptr(&mut self) -> *mut u8 {
134 self.0.as_mut_ptr()
135 }
136 }
137
138 /// Configuration descriptor for DICE input values.
139 #[derive(Debug, Clone, PartialEq, Eq)]
140 pub enum Config<'a> {
141 /// Reference to an inline descriptor.
142 Inline(&'a InlineConfig),
143 /// Reference to a free form descriptor that will be hashed by the implementation.
144 Descriptor(&'a [u8]),
145 }
146
147 impl Config<'_> {
dice_config_type(&self) -> DiceConfigType148 fn dice_config_type(&self) -> DiceConfigType {
149 match self {
150 Self::Inline(_) => DiceConfigType::kDiceConfigTypeInline,
151 Self::Descriptor(_) => DiceConfigType::kDiceConfigTypeDescriptor,
152 }
153 }
154
inline_config(&self) -> InlineConfig155 fn inline_config(&self) -> InlineConfig {
156 match self {
157 Self::Inline(inline) => **inline,
158 Self::Descriptor(_) => [0u8; INLINE_CONFIG_SIZE],
159 }
160 }
161
descriptor_ptr(&self) -> *const u8162 fn descriptor_ptr(&self) -> *const u8 {
163 match self {
164 Self::Descriptor(descriptor) => descriptor.as_ptr(),
165 _ => ptr::null(),
166 }
167 }
168
descriptor_size(&self) -> usize169 fn descriptor_size(&self) -> usize {
170 match self {
171 Self::Descriptor(descriptor) => descriptor.len(),
172 _ => 0,
173 }
174 }
175 }
176
177 /// Wrap of `DiceInputValues`.
178 #[derive(Clone, Debug)]
179 pub struct InputValues<'a> {
180 dice_inputs: DiceInputValues,
181 // DiceInputValues contains a pointer to the separate config descriptor, which must therefore
182 // outlive it. Make sure the borrow checker can enforce that.
183 config_descriptor: PhantomData<&'a [u8]>,
184 }
185
186 impl<'a> InputValues<'a> {
187 /// Creates a new `InputValues`.
new( code_hash: Hash, config: Config<'a>, authority_hash: Hash, mode: DiceMode, hidden: Hidden, ) -> Self188 pub fn new(
189 code_hash: Hash,
190 config: Config<'a>,
191 authority_hash: Hash,
192 mode: DiceMode,
193 hidden: Hidden,
194 ) -> Self {
195 Self {
196 dice_inputs: DiceInputValues {
197 code_hash,
198 code_descriptor: ptr::null(),
199 code_descriptor_size: 0,
200 config_type: config.dice_config_type(),
201 config_value: config.inline_config(),
202 config_descriptor: config.descriptor_ptr(),
203 config_descriptor_size: config.descriptor_size(),
204 authority_hash,
205 authority_descriptor: ptr::null(),
206 authority_descriptor_size: 0,
207 mode,
208 hidden,
209 },
210 config_descriptor: PhantomData,
211 }
212 }
213
214 /// Returns a raw pointer to the wrapped `DiceInputValues`.
as_ptr(&self) -> *const DiceInputValues215 pub fn as_ptr(&self) -> *const DiceInputValues {
216 &self.dice_inputs as *const DiceInputValues
217 }
218 }
219
220 /// Derives a CDI private key seed from a `cdi_attest` value.
derive_cdi_private_key_seed(cdi_attest: &Cdi) -> Result<PrivateKeySeed>221 pub fn derive_cdi_private_key_seed(cdi_attest: &Cdi) -> Result<PrivateKeySeed> {
222 let mut seed = PrivateKeySeed::default();
223 check_result(
224 // SAFETY: The function writes to the buffer within the given bounds, and only reads the
225 // input values. The first argument context is not used in this function.
226 unsafe {
227 DiceDeriveCdiPrivateKeySeed(
228 ptr::null_mut(), // context
229 cdi_attest.as_ptr(),
230 seed.as_mut_ptr(),
231 )
232 },
233 seed.0.len(),
234 )?;
235 Ok(seed)
236 }
237
238 /// Derives an ID from the given `cdi_public_key` value.
derive_cdi_certificate_id(cdi_public_key: &[u8]) -> Result<DiceId>239 pub fn derive_cdi_certificate_id(cdi_public_key: &[u8]) -> Result<DiceId> {
240 let mut id = [0u8; ID_SIZE];
241 check_result(
242 // SAFETY: The function writes to the buffer within the given bounds, and only reads the
243 // input values. The first argument context is not used in this function.
244 unsafe {
245 DiceDeriveCdiCertificateId(
246 ptr::null_mut(), // context
247 cdi_public_key.as_ptr(),
248 cdi_public_key.len(),
249 id.as_mut_ptr(),
250 )
251 },
252 id.len(),
253 )?;
254 Ok(id)
255 }
256
257 /// Executes the main DICE flow.
258 ///
259 /// Given a full set of input values and the current CDI values, computes the
260 /// next CDI values and a matching certificate.
261 /// Returns the actual size of the next CDI certificate.
dice_main_flow( current_cdi_attest: &Cdi, current_cdi_seal: &Cdi, input_values: &InputValues, next_cdi_certificate: &mut [u8], next_cdi_values: &mut CdiValues, ) -> Result<usize>262 pub fn dice_main_flow(
263 current_cdi_attest: &Cdi,
264 current_cdi_seal: &Cdi,
265 input_values: &InputValues,
266 next_cdi_certificate: &mut [u8],
267 next_cdi_values: &mut CdiValues,
268 ) -> Result<usize> {
269 let mut next_cdi_certificate_actual_size = 0;
270 check_result(
271 // SAFETY: The function only reads the current CDI values and inputs and writes
272 // to `next_cdi_certificate` and next CDI values within its bounds.
273 // The first argument can be null and is not used in the current implementation.
274 unsafe {
275 DiceMainFlow(
276 ptr::null_mut(), // context
277 current_cdi_attest.as_ptr(),
278 current_cdi_seal.as_ptr(),
279 input_values.as_ptr(),
280 next_cdi_certificate.len(),
281 next_cdi_certificate.as_mut_ptr(),
282 &mut next_cdi_certificate_actual_size,
283 next_cdi_values.cdi_attest.as_mut_ptr(),
284 next_cdi_values.cdi_seal.as_mut_ptr(),
285 )
286 },
287 next_cdi_certificate_actual_size,
288 )?;
289 Ok(next_cdi_certificate_actual_size)
290 }
291