blob: e42e373b41e7d5e3be090dc0c7ee7e70d56d6b6d [file] [log] [blame]
Alice Wang0b9e1102023-02-02 09:57:06 +00001// 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
Alice Wang7cc59562023-02-08 13:17:10 +000018use crate::error::{check_result, Result};
Alice Wang9c40eca2023-02-03 13:10:24 +000019pub use open_dice_cbor_bindgen::DiceMode;
Alice Wang0b9e1102023-02-02 09:57:06 +000020use open_dice_cbor_bindgen::{
Alice Wang7cc59562023-02-08 13:17:10 +000021 DiceConfigType, DiceDeriveCdiCertificateId, DiceDeriveCdiPrivateKeySeed, DiceInputValues,
Alice Wang44f48b22023-02-09 09:51:22 +000022 DiceMainFlow, DICE_CDI_SIZE, DICE_HASH_SIZE, DICE_HIDDEN_SIZE, DICE_ID_SIZE,
Alice Wang8722d9e2023-02-13 14:56:56 +000023 DICE_INLINE_CONFIG_SIZE, DICE_PRIVATE_KEY_SEED_SIZE, DICE_PRIVATE_KEY_SIZE,
24 DICE_PUBLIC_KEY_SIZE, DICE_SIGNATURE_SIZE,
Alice Wang0b9e1102023-02-02 09:57:06 +000025};
Alan Stokes3194c462023-05-03 17:39:01 +010026use std::{marker::PhantomData, ptr};
Alice Wangf4bd1c62023-02-08 08:38:44 +000027use zeroize::{Zeroize, ZeroizeOnDrop};
Alice Wang0b9e1102023-02-02 09:57:06 +000028
29/// The size of a DICE hash.
30pub const HASH_SIZE: usize = DICE_HASH_SIZE as usize;
31/// The size of the DICE hidden value.
32pub const HIDDEN_SIZE: usize = DICE_HIDDEN_SIZE as usize;
33/// The size of a DICE inline config.
34const INLINE_CONFIG_SIZE: usize = DICE_INLINE_CONFIG_SIZE as usize;
Alice Wang3213d492023-02-03 15:52:18 +000035/// The size of a CDI.
36pub const CDI_SIZE: usize = DICE_CDI_SIZE as usize;
Alice Wang7cc59562023-02-08 13:17:10 +000037/// The size of a private key seed.
38pub const PRIVATE_KEY_SEED_SIZE: usize = DICE_PRIVATE_KEY_SEED_SIZE as usize;
Alice Wang8722d9e2023-02-13 14:56:56 +000039/// The size of a private key.
40pub const PRIVATE_KEY_SIZE: usize = DICE_PRIVATE_KEY_SIZE as usize;
41/// The size of a public key.
42pub const PUBLIC_KEY_SIZE: usize = DICE_PUBLIC_KEY_SIZE as usize;
43/// The size of a signature.
44pub const SIGNATURE_SIZE: usize = DICE_SIGNATURE_SIZE as usize;
Alice Wang7cc59562023-02-08 13:17:10 +000045/// The size of an ID.
46pub const ID_SIZE: usize = DICE_ID_SIZE as usize;
Alice Wang0b9e1102023-02-02 09:57:06 +000047
48/// Array type of hashes used by DICE.
49pub type Hash = [u8; HASH_SIZE];
50/// Array type of additional input.
51pub type Hidden = [u8; HIDDEN_SIZE];
52/// Array type of inline configuration values.
53pub type InlineConfig = [u8; INLINE_CONFIG_SIZE];
Alice Wang3213d492023-02-03 15:52:18 +000054/// Array type of CDIs.
55pub type Cdi = [u8; CDI_SIZE];
Alice Wang8722d9e2023-02-13 14:56:56 +000056/// Array type of the public key.
57pub type PublicKey = [u8; PUBLIC_KEY_SIZE];
58/// Array type of the signature.
59pub type Signature = [u8; SIGNATURE_SIZE];
Alice Wang7cc59562023-02-08 13:17:10 +000060/// Array type of DICE ID.
61pub type DiceId = [u8; ID_SIZE];
Alice Wang0b9e1102023-02-02 09:57:06 +000062
Alice Wang4d3059a2023-02-15 10:24:33 +000063/// 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.
70pub trait DiceArtifacts {
71 /// Returns a reference to the attestation CDI.
72 fn cdi_attest(&self) -> &[u8; CDI_SIZE];
73
74 /// Returns a reference to the sealing CDI.
75 fn cdi_seal(&self) -> &[u8; CDI_SIZE];
76
77 /// Returns a reference to the Boot Certificate Chain, if present.
78 fn bcc(&self) -> Option<&[u8]>;
79}
80
Alice Wangf59662d2023-02-10 16:07:56 +000081/// TODO(b/268587826): Clean up the memory cache after zeroing out the memory
82/// for sensitive data like CDI values and private key.
Alice Wangf4bd1c62023-02-08 08:38:44 +000083/// CDI Values.
Alice Wangacee4fb2023-02-15 09:42:07 +000084#[derive(Debug, Zeroize, ZeroizeOnDrop, Default)]
Alice Wangf4bd1c62023-02-08 08:38:44 +000085pub struct CdiValues {
86 /// Attestation CDI.
Alice Wang4d3059a2023-02-15 10:24:33 +000087 pub cdi_attest: [u8; CDI_SIZE],
Alice Wangf4bd1c62023-02-08 08:38:44 +000088 /// Sealing CDI.
Alice Wang4d3059a2023-02-15 10:24:33 +000089 pub cdi_seal: [u8; CDI_SIZE],
Alice Wangf4bd1c62023-02-08 08:38:44 +000090}
91
Alice Wangf59662d2023-02-10 16:07:56 +000092/// Private key seed. The data is zeroed out when the struct is dropped.
93#[derive(Zeroize, ZeroizeOnDrop, Default)]
94pub struct PrivateKeySeed([u8; PRIVATE_KEY_SEED_SIZE]);
95
96impl PrivateKeySeed {
97 /// Returns an array reference of the private key seed.
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.
103 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)]
110pub struct PrivateKey([u8; PRIVATE_KEY_SIZE]);
111
112impl 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.
118 fn default() -> Self {
119 Self([0u8; PRIVATE_KEY_SIZE])
120 }
121}
122
123impl PrivateKey {
124 /// Returns an array reference of the private key.
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.
130 pub fn as_mut_ptr(&mut self) -> *mut u8 {
131 self.0.as_mut_ptr()
132 }
133}
134
Alice Wang0b9e1102023-02-02 09:57:06 +0000135/// Configuration descriptor for DICE input values.
136#[derive(Debug, Clone, PartialEq, Eq)]
137pub 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
144impl Config<'_> {
145 fn dice_config_type(&self) -> DiceConfigType {
146 match self {
147 Self::Inline(_) => DiceConfigType::kDiceConfigTypeInline,
148 Self::Descriptor(_) => DiceConfigType::kDiceConfigTypeDescriptor,
149 }
150 }
151
152 fn inline_config(&self) -> InlineConfig {
153 match self {
154 Self::Inline(inline) => **inline,
155 Self::Descriptor(_) => [0u8; INLINE_CONFIG_SIZE],
156 }
157 }
158
159 fn descriptor_ptr(&self) -> *const u8 {
160 match self {
161 Self::Descriptor(descriptor) => descriptor.as_ptr(),
162 _ => ptr::null(),
163 }
164 }
165
166 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)]
Alan Stokes3194c462023-05-03 17:39:01 +0100176pub struct InputValues<'a> {
177 dice_inputs: DiceInputValues,
178 // DiceInputValues contains a pointer to the separate config descriptor, which must therefore
179 // outlive it. Make sure the borrow checker can enforce that.
180 config_descriptor: PhantomData<&'a [u8]>,
181}
Alice Wang0b9e1102023-02-02 09:57:06 +0000182
Alan Stokes3194c462023-05-03 17:39:01 +0100183impl<'a> InputValues<'a> {
Alice Wang0b9e1102023-02-02 09:57:06 +0000184 /// Creates a new `InputValues`.
185 pub fn new(
Alice Wangb68814b2023-02-02 13:15:32 +0000186 code_hash: Hash,
Alan Stokes3194c462023-05-03 17:39:01 +0100187 config: Config<'a>,
Alice Wangb68814b2023-02-02 13:15:32 +0000188 authority_hash: Hash,
Alice Wang0b9e1102023-02-02 09:57:06 +0000189 mode: DiceMode,
Alice Wangb68814b2023-02-02 13:15:32 +0000190 hidden: Hidden,
Alice Wang0b9e1102023-02-02 09:57:06 +0000191 ) -> Self {
Alan Stokes3194c462023-05-03 17:39:01 +0100192 Self {
193 dice_inputs: DiceInputValues {
194 code_hash,
195 code_descriptor: ptr::null(),
196 code_descriptor_size: 0,
197 config_type: config.dice_config_type(),
198 config_value: config.inline_config(),
199 config_descriptor: config.descriptor_ptr(),
200 config_descriptor_size: config.descriptor_size(),
201 authority_hash,
202 authority_descriptor: ptr::null(),
203 authority_descriptor_size: 0,
204 mode,
205 hidden,
206 },
207 config_descriptor: PhantomData,
208 }
Alice Wang0b9e1102023-02-02 09:57:06 +0000209 }
210
211 /// Returns a raw pointer to the wrapped `DiceInputValues`.
212 pub fn as_ptr(&self) -> *const DiceInputValues {
Alan Stokes3194c462023-05-03 17:39:01 +0100213 &self.dice_inputs as *const DiceInputValues
Alice Wang0b9e1102023-02-02 09:57:06 +0000214 }
215}
Alice Wang7cc59562023-02-08 13:17:10 +0000216
217/// Derives a CDI private key seed from a `cdi_attest` value.
218pub fn derive_cdi_private_key_seed(cdi_attest: &Cdi) -> Result<PrivateKeySeed> {
Alice Wangf59662d2023-02-10 16:07:56 +0000219 let mut seed = PrivateKeySeed::default();
Alice Wangef999242023-05-22 11:14:59 +0000220 check_result(
Andrew Walbran7f30e542023-07-07 13:42:25 +0100221 // SAFETY: The function writes to the buffer within the given bounds, and only reads the
222 // input values. The first argument context is not used in this function.
Alice Wangef999242023-05-22 11:14:59 +0000223 unsafe {
224 DiceDeriveCdiPrivateKeySeed(
225 ptr::null_mut(), // context
226 cdi_attest.as_ptr(),
227 seed.as_mut_ptr(),
228 )
229 },
230 seed.0.len(),
231 )?;
Alice Wang7cc59562023-02-08 13:17:10 +0000232 Ok(seed)
233}
234
235/// Derives an ID from the given `cdi_public_key` value.
236pub fn derive_cdi_certificate_id(cdi_public_key: &[u8]) -> Result<DiceId> {
237 let mut id = [0u8; ID_SIZE];
Alice Wangef999242023-05-22 11:14:59 +0000238 check_result(
Andrew Walbran7f30e542023-07-07 13:42:25 +0100239 // SAFETY: The function writes to the buffer within the given bounds, and only reads the
240 // input values. The first argument context is not used in this function.
Alice Wangef999242023-05-22 11:14:59 +0000241 unsafe {
242 DiceDeriveCdiCertificateId(
243 ptr::null_mut(), // context
244 cdi_public_key.as_ptr(),
245 cdi_public_key.len(),
246 id.as_mut_ptr(),
247 )
248 },
249 id.len(),
250 )?;
Alice Wang7cc59562023-02-08 13:17:10 +0000251 Ok(id)
252}
Alice Wang44f48b22023-02-09 09:51:22 +0000253
254/// Executes the main DICE flow.
255///
256/// Given a full set of input values and the current CDI values, computes the
257/// next CDI values and a matching certificate.
258/// Returns the actual size of the next CDI certificate.
259pub fn dice_main_flow(
260 current_cdi_attest: &Cdi,
261 current_cdi_seal: &Cdi,
262 input_values: &InputValues,
263 next_cdi_certificate: &mut [u8],
264 next_cdi_values: &mut CdiValues,
265) -> Result<usize> {
266 let mut next_cdi_certificate_actual_size = 0;
Alice Wangef999242023-05-22 11:14:59 +0000267 check_result(
Andrew Walbran7f30e542023-07-07 13:42:25 +0100268 // SAFETY: The function only reads the current CDI values and inputs and writes
269 // to `next_cdi_certificate` and next CDI values within its bounds.
270 // The first argument can be null and is not used in the current implementation.
Alice Wangef999242023-05-22 11:14:59 +0000271 unsafe {
272 DiceMainFlow(
273 ptr::null_mut(), // context
274 current_cdi_attest.as_ptr(),
275 current_cdi_seal.as_ptr(),
276 input_values.as_ptr(),
277 next_cdi_certificate.len(),
278 next_cdi_certificate.as_mut_ptr(),
279 &mut next_cdi_certificate_actual_size,
280 next_cdi_values.cdi_attest.as_mut_ptr(),
281 next_cdi_values.cdi_seal.as_mut_ptr(),
282 )
283 },
284 next_cdi_certificate_actual_size,
285 )?;
Alice Wang44f48b22023-02-09 09:51:22 +0000286 Ok(next_cdi_certificate_actual_size)
287}