blob: b33378199bb9e763641a597e00c9cd760eeaa14b [file] [log] [blame]
Pierre-Clément Tosi8edf72e2022-12-06 16:02:57 +00001/*
2 * Copyright 2022 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//! Wrapper around dice/android/bcc.h.
18
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +000019use core::ffi::CStr;
Pierre-Clément Tosi8edf72e2022-12-06 16:02:57 +000020use core::mem;
21use core::ptr;
22
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +000023use open_dice_bcc_bindgen::BccConfigValues;
24use open_dice_bcc_bindgen::BccFormatConfigDescriptor;
25use open_dice_bcc_bindgen::BccHandoverMainFlow;
Pierre-Clément Tosi8edf72e2022-12-06 16:02:57 +000026use open_dice_bcc_bindgen::BccHandoverParse;
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +000027use open_dice_bcc_bindgen::BCC_INPUT_COMPONENT_NAME;
28use open_dice_bcc_bindgen::BCC_INPUT_COMPONENT_VERSION;
29use open_dice_bcc_bindgen::BCC_INPUT_RESETTABLE;
Pierre-Clément Tosi8edf72e2022-12-06 16:02:57 +000030
Alice Wanga7e4ce02023-02-03 13:37:14 +000031use crate::check_result;
Pierre-Clément Tosi8edf72e2022-12-06 16:02:57 +000032use crate::Cdi;
Alice Wanga7e4ce02023-02-03 13:37:14 +000033use crate::DiceError;
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +000034use crate::InputValues;
Pierre-Clément Tosi8edf72e2022-12-06 16:02:57 +000035use crate::Result;
36
37/// Boot Chain Certificate handover format combining the BCC and CDIs in a single CBOR object.
38#[derive(Clone, Debug)]
39pub struct Handover<'a> {
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +000040 buffer: &'a [u8],
Pierre-Clément Tosi8edf72e2022-12-06 16:02:57 +000041 /// Attestation CDI.
42 pub cdi_attest: &'a Cdi,
43 /// Sealing CDI.
44 pub cdi_seal: &'a Cdi,
45 /// Boot Chain Certificate (optional).
46 pub bcc: Option<&'a [u8]>,
47}
48
49impl<'a> Handover<'a> {
50 /// Validates and extracts the fields of a BCC handover buffer.
51 pub fn new(buffer: &'a [u8]) -> Result<Self> {
52 let mut cdi_attest: *const u8 = ptr::null();
53 let mut cdi_seal: *const u8 = ptr::null();
54 let mut bcc: *const u8 = ptr::null();
55 let mut bcc_size: usize = 0;
56
57 // SAFETY - The buffer is only read and never stored and the returned pointers should all
58 // point within the address range of the buffer or be NULL.
Alice Wanga7e4ce02023-02-03 13:37:14 +000059 check_result(unsafe {
Pierre-Clément Tosi8edf72e2022-12-06 16:02:57 +000060 BccHandoverParse(
61 buffer.as_ptr(),
62 buffer.len(),
63 &mut cdi_attest as *mut *const u8,
64 &mut cdi_seal as *mut *const u8,
65 &mut bcc as *mut *const u8,
66 &mut bcc_size as *mut usize,
67 )
68 })?;
69
70 let cdi_attest = {
Alice Wanga7e4ce02023-02-03 13:37:14 +000071 let i = index_from_ptr(buffer, cdi_attest).ok_or(DiceError::PlatformError)?;
72 let s = buffer.get(i..(i + mem::size_of::<Cdi>())).ok_or(DiceError::PlatformError)?;
73 s.try_into().map_err(|_| DiceError::PlatformError)?
Pierre-Clément Tosi8edf72e2022-12-06 16:02:57 +000074 };
75 let cdi_seal = {
Alice Wanga7e4ce02023-02-03 13:37:14 +000076 let i = index_from_ptr(buffer, cdi_seal).ok_or(DiceError::PlatformError)?;
77 let s = buffer.get(i..(i + mem::size_of::<Cdi>())).ok_or(DiceError::PlatformError)?;
78 s.try_into().map_err(|_| DiceError::PlatformError)?
Pierre-Clément Tosi8edf72e2022-12-06 16:02:57 +000079 };
80 let bcc = if bcc.is_null() {
81 None
82 } else {
Alice Wanga7e4ce02023-02-03 13:37:14 +000083 let i = index_from_ptr(buffer, bcc).ok_or(DiceError::PlatformError)?;
84 Some(buffer.get(i..(i + bcc_size)).ok_or(DiceError::PlatformError)?)
Pierre-Clément Tosi8edf72e2022-12-06 16:02:57 +000085 };
86
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +000087 Ok(Self { buffer, cdi_attest, cdi_seal, bcc })
Pierre-Clément Tosi8edf72e2022-12-06 16:02:57 +000088 }
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +000089
90 /// Executes the main BCC handover flow.
91 pub fn main_flow(&self, input_values: &InputValues, buffer: &mut [u8]) -> Result<usize> {
92 let context = ptr::null_mut();
93 let mut size: usize = 0;
94 // SAFETY - The function only reads `self.buffer`, writes to `buffer` within its bounds,
95 // reads `input_values` as a constant input and doesn't store any pointer.
Alice Wanga7e4ce02023-02-03 13:37:14 +000096 check_result(unsafe {
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +000097 BccHandoverMainFlow(
98 context,
99 self.buffer.as_ptr(),
100 self.buffer.len(),
Alice Wang5aeed332023-02-02 09:42:21 +0000101 input_values.as_ptr(),
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +0000102 buffer.len(),
103 buffer.as_mut_ptr(),
104 &mut size as *mut usize,
105 )
106 })?;
107
108 Ok(size)
109 }
110}
111
112/// Formats a configuration descriptor following the BCC's specification.
113///
114/// ```
115/// BccConfigDescriptor = {
116/// ? -70002 : tstr, ; Component name
117/// ? -70003 : int, ; Component version
118/// ? -70004 : null, ; Resettable
119/// }
120/// ```
121pub fn format_config_descriptor(
122 buffer: &mut [u8],
123 name: Option<&CStr>,
124 version: Option<u64>,
125 resettable: bool,
126) -> Result<usize> {
127 let mut inputs = 0;
128
129 if name.is_some() {
130 inputs |= BCC_INPUT_COMPONENT_NAME;
131 }
132
133 if version.is_some() {
134 inputs |= BCC_INPUT_COMPONENT_VERSION;
135 }
136
137 if resettable {
138 inputs |= BCC_INPUT_RESETTABLE;
139 }
140
141 let values = BccConfigValues {
142 inputs,
143 component_name: name.map_or(ptr::null(), |p| p.as_ptr()),
144 component_version: version.unwrap_or(0),
145 };
146
147 let mut buffer_size = 0;
148
149 // SAFETY - The function writes to the buffer, within the given bounds, and only reads the
150 // input values. It writes its result to buffer_size.
Alice Wanga7e4ce02023-02-03 13:37:14 +0000151 check_result(unsafe {
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +0000152 BccFormatConfigDescriptor(
153 &values as *const _,
154 buffer.len(),
155 buffer.as_mut_ptr(),
156 &mut buffer_size as *mut _,
157 )
158 })?;
159
160 Ok(buffer_size)
Pierre-Clément Tosi8edf72e2022-12-06 16:02:57 +0000161}
162
163fn index_from_ptr(slice: &[u8], pointer: *const u8) -> Option<usize> {
164 if slice.as_ptr_range().contains(&pointer) {
165 (pointer as usize).checked_sub(slice.as_ptr() as usize)
166 } else {
167 None
168 }
169}