blob: 199e1a9f036388fd8eb9964a9faf323d9a51b2c5 [file] [log] [blame]
Alice Wang9c40eca2023-02-03 13:10:24 +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
Andrew Scull0275aa52023-08-18 18:03:11 +000015//! This module mirrors the content in open-dice/include/dice/android.h
Alice Wang9c40eca2023-02-03 13:10:24 +000016
Alice Wang4d3059a2023-02-15 10:24:33 +000017use crate::dice::{Cdi, CdiValues, DiceArtifacts, InputValues, CDI_SIZE};
Alice Wang1a933a82023-02-14 11:02:51 +000018use crate::error::{check_result, DiceError, Result};
Andrew Scull0275aa52023-08-18 18:03:11 +000019use open_dice_android_bindgen::{
20 DiceAndroidConfigValues, DiceAndroidFormatConfigDescriptor, DiceAndroidHandoverMainFlow,
21 DiceAndroidHandoverParse, DiceAndroidMainFlow, DICE_ANDROID_CONFIG_COMPONENT_NAME,
22 DICE_ANDROID_CONFIG_COMPONENT_VERSION, DICE_ANDROID_CONFIG_RESETTABLE,
Alan Stokes82b12392023-08-22 14:39:29 +010023 DICE_ANDROID_CONFIG_SECURITY_VERSION,
Alice Wang9c40eca2023-02-03 13:10:24 +000024};
25use std::{ffi::CStr, ptr};
26
Alan Stokes82b12392023-08-22 14:39:29 +010027/// Contains the input values used to construct the Android Profile for DICE
28/// configuration descriptor.
29#[derive(Default, Debug)]
30pub struct DiceConfigValues<'a> {
31 /// Name of the component.
32 pub component_name: Option<&'a CStr>,
33 /// Version of the component.
34 pub component_version: Option<u64>,
35 /// Whether the key changes on factory reset.
36 pub resettable: bool,
37 /// Monotonically increasing version of the component.
38 pub security_version: Option<u64>,
39}
40
Andrew Scull0275aa52023-08-18 18:03:11 +000041/// Formats a configuration descriptor following the Android Profile for DICE specification.
Alan Stokes82b12392023-08-22 14:39:29 +010042/// See https://pigweed.googlesource.com/open-dice/+/refs/heads/main/docs/android.md.
43pub fn bcc_format_config_descriptor(values: &DiceConfigValues, buffer: &mut [u8]) -> Result<usize> {
Andrew Scull0275aa52023-08-18 18:03:11 +000044 let mut configs = 0;
Alan Stokes82b12392023-08-22 14:39:29 +010045
46 let component_name = values.component_name.map_or(ptr::null(), |name| {
Andrew Scull0275aa52023-08-18 18:03:11 +000047 configs |= DICE_ANDROID_CONFIG_COMPONENT_NAME;
Alan Stokes82b12392023-08-22 14:39:29 +010048 name.as_ptr()
49 });
50 let component_version = values.component_version.map_or(0, |version| {
Andrew Scull0275aa52023-08-18 18:03:11 +000051 configs |= DICE_ANDROID_CONFIG_COMPONENT_VERSION;
Alan Stokes82b12392023-08-22 14:39:29 +010052 version
53 });
54 if values.resettable {
Andrew Scull0275aa52023-08-18 18:03:11 +000055 configs |= DICE_ANDROID_CONFIG_RESETTABLE;
Alice Wang9c40eca2023-02-03 13:10:24 +000056 }
Alan Stokes82b12392023-08-22 14:39:29 +010057 let security_version = values.security_version.map_or(0, |version| {
58 configs |= DICE_ANDROID_CONFIG_SECURITY_VERSION;
59 version
60 });
Alice Wang9c40eca2023-02-03 13:10:24 +000061
Alan Stokes82b12392023-08-22 14:39:29 +010062 let values =
63 DiceAndroidConfigValues { configs, component_name, component_version, security_version };
Alice Wang9c40eca2023-02-03 13:10:24 +000064
65 let mut buffer_size = 0;
Alice Wangef999242023-05-22 11:14:59 +000066 check_result(
Andrew Walbran7f30e542023-07-07 13:42:25 +010067 // SAFETY: The function writes to the buffer, within the given bounds, and only reads the
68 // input values. It writes its result to buffer_size.
Alice Wangef999242023-05-22 11:14:59 +000069 unsafe {
Andrew Scull0275aa52023-08-18 18:03:11 +000070 DiceAndroidFormatConfigDescriptor(
71 &values,
72 buffer.len(),
73 buffer.as_mut_ptr(),
74 &mut buffer_size,
75 )
Alice Wangef999242023-05-22 11:14:59 +000076 },
77 buffer_size,
78 )?;
Alice Wang9c40eca2023-02-03 13:10:24 +000079 Ok(buffer_size)
80}
Alice Wangf4bd1c62023-02-08 08:38:44 +000081
Andrew Scull0275aa52023-08-18 18:03:11 +000082/// Executes the main Android DICE flow.
Alice Wangf4bd1c62023-02-08 08:38:44 +000083///
Andrew Scull0275aa52023-08-18 18:03:11 +000084/// Given a full set of input values along with the current DICE chain and CDI values,
85/// computes the next CDI values and matching updated DICE chain.
Alice Wangf4bd1c62023-02-08 08:38:44 +000086pub fn bcc_main_flow(
87 current_cdi_attest: &Cdi,
88 current_cdi_seal: &Cdi,
Andrew Scull0275aa52023-08-18 18:03:11 +000089 current_chain: &[u8],
Alice Wangf4bd1c62023-02-08 08:38:44 +000090 input_values: &InputValues,
91 next_cdi_values: &mut CdiValues,
Andrew Scull0275aa52023-08-18 18:03:11 +000092 next_chain: &mut [u8],
Alice Wangf4bd1c62023-02-08 08:38:44 +000093) -> Result<usize> {
Andrew Scull0275aa52023-08-18 18:03:11 +000094 let mut next_chain_size = 0;
Alice Wangef999242023-05-22 11:14:59 +000095 check_result(
Andrew Scull0275aa52023-08-18 18:03:11 +000096 // SAFETY: `DiceAndroidMainFlow` only reads the `current_chain` and CDI values and writes
97 // to `next_chain` and next CDI values within its bounds. It also reads `input_values` as a
98 // constant input and doesn't store any pointer.
Andrew Walbran7f30e542023-07-07 13:42:25 +010099 // The first argument can be null and is not used in the current implementation.
Alice Wangef999242023-05-22 11:14:59 +0000100 unsafe {
Andrew Scull0275aa52023-08-18 18:03:11 +0000101 DiceAndroidMainFlow(
Alice Wangef999242023-05-22 11:14:59 +0000102 ptr::null_mut(), // context
103 current_cdi_attest.as_ptr(),
104 current_cdi_seal.as_ptr(),
Andrew Scull0275aa52023-08-18 18:03:11 +0000105 current_chain.as_ptr(),
106 current_chain.len(),
Alice Wangef999242023-05-22 11:14:59 +0000107 input_values.as_ptr(),
Andrew Scull0275aa52023-08-18 18:03:11 +0000108 next_chain.len(),
109 next_chain.as_mut_ptr(),
110 &mut next_chain_size,
Alice Wangef999242023-05-22 11:14:59 +0000111 next_cdi_values.cdi_attest.as_mut_ptr(),
112 next_cdi_values.cdi_seal.as_mut_ptr(),
113 )
114 },
Andrew Scull0275aa52023-08-18 18:03:11 +0000115 next_chain_size,
Alice Wangef999242023-05-22 11:14:59 +0000116 )?;
Andrew Scull0275aa52023-08-18 18:03:11 +0000117 Ok(next_chain_size)
Alice Wangf4bd1c62023-02-08 08:38:44 +0000118}
Alice Wang9b2c38e2023-02-14 08:53:31 +0000119
Andrew Scull0275aa52023-08-18 18:03:11 +0000120/// Executes the main Android DICE handover flow.
Alice Wang9b2c38e2023-02-14 08:53:31 +0000121///
Andrew Scull0275aa52023-08-18 18:03:11 +0000122/// A handover combines the DICE chain and CDIs in a single CBOR object.
123/// This function takes the current boot stage's handover bundle and produces a
Alice Wang9b2c38e2023-02-14 08:53:31 +0000124/// bundle for the next stage.
125pub fn bcc_handover_main_flow(
Andrew Scull0275aa52023-08-18 18:03:11 +0000126 current_handover: &[u8],
Alice Wang9b2c38e2023-02-14 08:53:31 +0000127 input_values: &InputValues,
Andrew Scull0275aa52023-08-18 18:03:11 +0000128 next_handover: &mut [u8],
Alice Wang9b2c38e2023-02-14 08:53:31 +0000129) -> Result<usize> {
Andrew Scull0275aa52023-08-18 18:03:11 +0000130 let mut next_handover_size = 0;
Alice Wangef999242023-05-22 11:14:59 +0000131 check_result(
Andrew Scull0275aa52023-08-18 18:03:11 +0000132 // SAFETY: The function only reads `current_handover` and writes to `next_handover`
Andrew Walbran7f30e542023-07-07 13:42:25 +0100133 // within its bounds,
134 // It also reads `input_values` as a constant input and doesn't store any pointer.
135 // The first argument can be null and is not used in the current implementation.
Alice Wangef999242023-05-22 11:14:59 +0000136 unsafe {
Andrew Scull0275aa52023-08-18 18:03:11 +0000137 DiceAndroidHandoverMainFlow(
Alice Wangef999242023-05-22 11:14:59 +0000138 ptr::null_mut(), // context
Andrew Scull0275aa52023-08-18 18:03:11 +0000139 current_handover.as_ptr(),
140 current_handover.len(),
Alice Wangef999242023-05-22 11:14:59 +0000141 input_values.as_ptr(),
Andrew Scull0275aa52023-08-18 18:03:11 +0000142 next_handover.len(),
143 next_handover.as_mut_ptr(),
144 &mut next_handover_size,
Alice Wangef999242023-05-22 11:14:59 +0000145 )
146 },
Andrew Scull0275aa52023-08-18 18:03:11 +0000147 next_handover_size,
Alice Wangef999242023-05-22 11:14:59 +0000148 )?;
Alice Wang9b2c38e2023-02-14 08:53:31 +0000149
Andrew Scull0275aa52023-08-18 18:03:11 +0000150 Ok(next_handover_size)
Alice Wang9b2c38e2023-02-14 08:53:31 +0000151}
Alice Wang1a933a82023-02-14 11:02:51 +0000152
Andrew Scull0275aa52023-08-18 18:03:11 +0000153/// An Android DICE handover object combines the DICE chain and CDIs in a single CBOR object.
154/// This struct is used as return of the function `android_dice_handover_parse`, its lifetime is
155/// tied to the lifetime of the raw handover slice.
Alice Wangacee4fb2023-02-15 09:42:07 +0000156#[derive(Debug)]
Alice Wang1a933a82023-02-14 11:02:51 +0000157pub struct BccHandover<'a> {
158 /// Attestation CDI.
Alice Wang4d3059a2023-02-15 10:24:33 +0000159 cdi_attest: &'a [u8; CDI_SIZE],
Alice Wang1a933a82023-02-14 11:02:51 +0000160 /// Sealing CDI.
Alice Wang4d3059a2023-02-15 10:24:33 +0000161 cdi_seal: &'a [u8; CDI_SIZE],
Andrew Scull0275aa52023-08-18 18:03:11 +0000162 /// DICE chain.
Alice Wang4d3059a2023-02-15 10:24:33 +0000163 bcc: Option<&'a [u8]>,
164}
165
166impl<'a> DiceArtifacts for BccHandover<'a> {
167 fn cdi_attest(&self) -> &[u8; CDI_SIZE] {
168 self.cdi_attest
169 }
170
171 fn cdi_seal(&self) -> &[u8; CDI_SIZE] {
172 self.cdi_seal
173 }
174
175 fn bcc(&self) -> Option<&[u8]> {
176 self.bcc
177 }
Alice Wang1a933a82023-02-14 11:02:51 +0000178}
179
Andrew Scull0275aa52023-08-18 18:03:11 +0000180/// This function parses the `handover` to extracts the DICE chain and CDIs.
181/// The lifetime of the returned `DiceAndroidHandover` is tied to the given `handover` slice.
182pub fn bcc_handover_parse(handover: &[u8]) -> Result<BccHandover> {
Alice Wang1a933a82023-02-14 11:02:51 +0000183 let mut cdi_attest: *const u8 = ptr::null();
184 let mut cdi_seal: *const u8 = ptr::null();
Andrew Scull0275aa52023-08-18 18:03:11 +0000185 let mut chain: *const u8 = ptr::null();
186 let mut chain_size = 0;
Alice Wangef999242023-05-22 11:14:59 +0000187 check_result(
Andrew Scull0275aa52023-08-18 18:03:11 +0000188 // SAFETY: The `handover` is only read and never stored and the returned pointers should
189 // all point within the address range of the `handover` or be NULL.
Alice Wangef999242023-05-22 11:14:59 +0000190 unsafe {
Andrew Scull0275aa52023-08-18 18:03:11 +0000191 DiceAndroidHandoverParse(
192 handover.as_ptr(),
193 handover.len(),
Alice Wangef999242023-05-22 11:14:59 +0000194 &mut cdi_attest,
195 &mut cdi_seal,
Andrew Scull0275aa52023-08-18 18:03:11 +0000196 &mut chain,
197 &mut chain_size,
Alice Wangef999242023-05-22 11:14:59 +0000198 )
199 },
Andrew Scull0275aa52023-08-18 18:03:11 +0000200 chain_size,
Alice Wangef999242023-05-22 11:14:59 +0000201 )?;
Andrew Scull0275aa52023-08-18 18:03:11 +0000202 let cdi_attest = sub_slice(handover, cdi_attest, CDI_SIZE)?;
203 let cdi_seal = sub_slice(handover, cdi_seal, CDI_SIZE)?;
204 let bcc = sub_slice(handover, chain, chain_size).ok();
Alice Wang1a933a82023-02-14 11:02:51 +0000205 Ok(BccHandover {
206 cdi_attest: cdi_attest.try_into().map_err(|_| DiceError::PlatformError)?,
207 cdi_seal: cdi_seal.try_into().map_err(|_| DiceError::PlatformError)?,
208 bcc,
209 })
210}
211
212/// Gets a slice the `addr` points to and of length `len`.
213/// The slice should be contained in the buffer.
214fn sub_slice(buffer: &[u8], addr: *const u8, len: usize) -> Result<&[u8]> {
215 if addr.is_null() || !buffer.as_ptr_range().contains(&addr) {
216 return Err(DiceError::PlatformError);
217 }
218 // SAFETY: This is safe because addr is not null and is within the range of the buffer.
219 let start: usize = unsafe {
220 addr.offset_from(buffer.as_ptr()).try_into().map_err(|_| DiceError::PlatformError)?
221 };
Alice Wangacee4fb2023-02-15 09:42:07 +0000222 start.checked_add(len).and_then(|end| buffer.get(start..end)).ok_or(DiceError::PlatformError)
Alice Wang1a933a82023-02-14 11:02:51 +0000223}