• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 use std::ptr;
27 use zeroize::{Zeroize, ZeroizeOnDrop};
28 
29 /// The size of a DICE hash.
30 pub const HASH_SIZE: usize = DICE_HASH_SIZE as usize;
31 /// The size of the DICE hidden value.
32 pub const HIDDEN_SIZE: usize = DICE_HIDDEN_SIZE as usize;
33 /// The size of a DICE inline config.
34 const INLINE_CONFIG_SIZE: usize = DICE_INLINE_CONFIG_SIZE as usize;
35 /// The size of a CDI.
36 pub const CDI_SIZE: usize = DICE_CDI_SIZE as usize;
37 /// The size of a private key seed.
38 pub const PRIVATE_KEY_SEED_SIZE: usize = DICE_PRIVATE_KEY_SEED_SIZE as usize;
39 /// The size of a private key.
40 pub const PRIVATE_KEY_SIZE: usize = DICE_PRIVATE_KEY_SIZE as usize;
41 /// The size of a public key.
42 pub const PUBLIC_KEY_SIZE: usize = DICE_PUBLIC_KEY_SIZE as usize;
43 /// The size of a signature.
44 pub const SIGNATURE_SIZE: usize = DICE_SIGNATURE_SIZE as usize;
45 /// The size of an ID.
46 pub const ID_SIZE: usize = DICE_ID_SIZE as usize;
47 
48 /// Array type of hashes used by DICE.
49 pub type Hash = [u8; HASH_SIZE];
50 /// Array type of additional input.
51 pub type Hidden = [u8; HIDDEN_SIZE];
52 /// Array type of inline configuration values.
53 pub type InlineConfig = [u8; INLINE_CONFIG_SIZE];
54 /// Array type of CDIs.
55 pub type Cdi = [u8; CDI_SIZE];
56 /// Array type of the public key.
57 pub type PublicKey = [u8; PUBLIC_KEY_SIZE];
58 /// Array type of the signature.
59 pub type Signature = [u8; SIGNATURE_SIZE];
60 /// Array type of DICE ID.
61 pub type DiceId = [u8; ID_SIZE];
62 
63 /// A trait for types that represent Dice artifacts, which include:
64 ///
65 /// - Attestation CDI
66 /// - Sealing CDI
67 /// - Boot Certificate Chain
68 ///
69 /// Types that implement this trait provide an access these artifacts.
70 pub trait DiceArtifacts {
71     /// Returns a reference to the attestation CDI.
cdi_attest(&self) -> &[u8; CDI_SIZE]72     fn cdi_attest(&self) -> &[u8; CDI_SIZE];
73 
74     /// Returns a reference to the sealing CDI.
cdi_seal(&self) -> &[u8; CDI_SIZE]75     fn cdi_seal(&self) -> &[u8; CDI_SIZE];
76 
77     /// Returns a reference to the Boot Certificate Chain, if present.
bcc(&self) -> Option<&[u8]>78     fn bcc(&self) -> Option<&[u8]>;
79 }
80 
81 /// TODO(b/268587826): Clean up the memory cache after zeroing out the memory
82 /// for sensitive data like CDI values and private key.
83 /// CDI Values.
84 #[derive(Debug, Zeroize, ZeroizeOnDrop, Default)]
85 pub struct CdiValues {
86     /// Attestation CDI.
87     pub cdi_attest: [u8; CDI_SIZE],
88     /// Sealing CDI.
89     pub cdi_seal: [u8; CDI_SIZE],
90 }
91 
92 /// Private key seed. The data is zeroed out when the struct is dropped.
93 #[derive(Zeroize, ZeroizeOnDrop, Default)]
94 pub struct PrivateKeySeed([u8; PRIVATE_KEY_SEED_SIZE]);
95 
96 impl PrivateKeySeed {
97     /// Returns an array reference of the private key seed.
as_array(&self) -> &[u8; PRIVATE_KEY_SEED_SIZE]98     pub fn as_array(&self) -> &[u8; PRIVATE_KEY_SEED_SIZE] {
99         &self.0
100     }
101 
102     /// Returns a mutable pointer to the slice buffer of the private key seed.
as_mut_ptr(&mut self) -> *mut u8103     pub fn as_mut_ptr(&mut self) -> *mut u8 {
104         self.0.as_mut_ptr()
105     }
106 }
107 
108 /// Private key. The data is zeroed out when the struct is dropped.
109 #[derive(Zeroize, ZeroizeOnDrop)]
110 pub struct PrivateKey([u8; PRIVATE_KEY_SIZE]);
111 
112 impl Default for PrivateKey {
113     /// Creates a new `PrivateKey` instance with all bytes set to 0.
114     ///
115     /// Since the size of the private key array is too large to be initialized
116     /// with a default value, this implementation sets all the bytes in the array
117     /// to 0 using the `[0u8; PRIVATE_KEY_SIZE]` syntax.
default() -> Self118     fn default() -> Self {
119         Self([0u8; PRIVATE_KEY_SIZE])
120     }
121 }
122 
123 impl PrivateKey {
124     /// Returns an array reference of the private key.
as_array(&self) -> &[u8; PRIVATE_KEY_SIZE]125     pub fn as_array(&self) -> &[u8; PRIVATE_KEY_SIZE] {
126         &self.0
127     }
128 
129     /// Returns a mutable pointer to the slice buffer of the private key.
as_mut_ptr(&mut self) -> *mut u8130     pub fn as_mut_ptr(&mut self) -> *mut u8 {
131         self.0.as_mut_ptr()
132     }
133 }
134 
135 /// Configuration descriptor for DICE input values.
136 #[derive(Debug, Clone, PartialEq, Eq)]
137 pub enum Config<'a> {
138     /// Reference to an inline descriptor.
139     Inline(&'a InlineConfig),
140     /// Reference to a free form descriptor that will be hashed by the implementation.
141     Descriptor(&'a [u8]),
142 }
143 
144 impl Config<'_> {
dice_config_type(&self) -> DiceConfigType145     fn dice_config_type(&self) -> DiceConfigType {
146         match self {
147             Self::Inline(_) => DiceConfigType::kDiceConfigTypeInline,
148             Self::Descriptor(_) => DiceConfigType::kDiceConfigTypeDescriptor,
149         }
150     }
151 
inline_config(&self) -> InlineConfig152     fn inline_config(&self) -> InlineConfig {
153         match self {
154             Self::Inline(inline) => **inline,
155             Self::Descriptor(_) => [0u8; INLINE_CONFIG_SIZE],
156         }
157     }
158 
descriptor_ptr(&self) -> *const u8159     fn descriptor_ptr(&self) -> *const u8 {
160         match self {
161             Self::Descriptor(descriptor) => descriptor.as_ptr(),
162             _ => ptr::null(),
163         }
164     }
165 
descriptor_size(&self) -> usize166     fn descriptor_size(&self) -> usize {
167         match self {
168             Self::Descriptor(descriptor) => descriptor.len(),
169             _ => 0,
170         }
171     }
172 }
173 
174 /// Wrap of `DiceInputValues`.
175 #[derive(Clone, Debug)]
176 pub struct InputValues(DiceInputValues);
177 
178 impl InputValues {
179     /// Creates a new `InputValues`.
new( code_hash: Hash, config: Config, authority_hash: Hash, mode: DiceMode, hidden: Hidden, ) -> Self180     pub fn new(
181         code_hash: Hash,
182         config: Config,
183         authority_hash: Hash,
184         mode: DiceMode,
185         hidden: Hidden,
186     ) -> Self {
187         Self(DiceInputValues {
188             code_hash,
189             code_descriptor: ptr::null(),
190             code_descriptor_size: 0,
191             config_type: config.dice_config_type(),
192             config_value: config.inline_config(),
193             config_descriptor: config.descriptor_ptr(),
194             config_descriptor_size: config.descriptor_size(),
195             authority_hash,
196             authority_descriptor: ptr::null(),
197             authority_descriptor_size: 0,
198             mode,
199             hidden,
200         })
201     }
202 
203     /// Returns a raw pointer to the wrapped `DiceInputValues`.
as_ptr(&self) -> *const DiceInputValues204     pub fn as_ptr(&self) -> *const DiceInputValues {
205         &self.0 as *const DiceInputValues
206     }
207 }
208 
209 /// Derives a CDI private key seed from a `cdi_attest` value.
derive_cdi_private_key_seed(cdi_attest: &Cdi) -> Result<PrivateKeySeed>210 pub fn derive_cdi_private_key_seed(cdi_attest: &Cdi) -> Result<PrivateKeySeed> {
211     let mut seed = PrivateKeySeed::default();
212     // SAFETY: The function writes to the buffer within the given bounds, and only reads the
213     // input values. The first argument context is not used in this function.
214     check_result(unsafe {
215         DiceDeriveCdiPrivateKeySeed(
216             ptr::null_mut(), // context
217             cdi_attest.as_ptr(),
218             seed.as_mut_ptr(),
219         )
220     })?;
221     Ok(seed)
222 }
223 
224 /// Derives an ID from the given `cdi_public_key` value.
derive_cdi_certificate_id(cdi_public_key: &[u8]) -> Result<DiceId>225 pub fn derive_cdi_certificate_id(cdi_public_key: &[u8]) -> Result<DiceId> {
226     let mut id = [0u8; ID_SIZE];
227     // SAFETY: The function writes to the buffer within the given bounds, and only reads the
228     // input values. The first argument context is not used in this function.
229     check_result(unsafe {
230         DiceDeriveCdiCertificateId(
231             ptr::null_mut(), // context
232             cdi_public_key.as_ptr(),
233             cdi_public_key.len(),
234             id.as_mut_ptr(),
235         )
236     })?;
237     Ok(id)
238 }
239 
240 /// Executes the main DICE flow.
241 ///
242 /// Given a full set of input values and the current CDI values, computes the
243 /// next CDI values and a matching certificate.
244 /// 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>245 pub fn dice_main_flow(
246     current_cdi_attest: &Cdi,
247     current_cdi_seal: &Cdi,
248     input_values: &InputValues,
249     next_cdi_certificate: &mut [u8],
250     next_cdi_values: &mut CdiValues,
251 ) -> Result<usize> {
252     let mut next_cdi_certificate_actual_size = 0;
253     // SAFETY: The function only reads the current CDI values and inputs and writes
254     // to `next_cdi_certificate` and next CDI values within its bounds.
255     // The first argument can be null and is not used in the current implementation.
256     check_result(unsafe {
257         DiceMainFlow(
258             ptr::null_mut(), // context
259             current_cdi_attest.as_ptr(),
260             current_cdi_seal.as_ptr(),
261             input_values.as_ptr(),
262             next_cdi_certificate.len(),
263             next_cdi_certificate.as_mut_ptr(),
264             &mut next_cdi_certificate_actual_size,
265             next_cdi_values.cdi_attest.as_mut_ptr(),
266             next_cdi_values.cdi_seal.as_mut_ptr(),
267         )
268     })?;
269     Ok(next_cdi_certificate_actual_size)
270 }
271