blob: a7ef8823282d8516688a107db6e0223279923c1a [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
19use core::mem;
20use core::ptr;
21
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +000022use open_dice_bcc_bindgen::BccHandoverMainFlow;
Pierre-Clément Tosi8edf72e2022-12-06 16:02:57 +000023use open_dice_bcc_bindgen::BccHandoverParse;
24
Alice Wanga7e4ce02023-02-03 13:37:14 +000025use crate::check_result;
Pierre-Clément Tosi8edf72e2022-12-06 16:02:57 +000026use crate::Cdi;
Alice Wanga7e4ce02023-02-03 13:37:14 +000027use crate::DiceError;
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +000028use crate::InputValues;
Pierre-Clément Tosi8edf72e2022-12-06 16:02:57 +000029use crate::Result;
30
31/// Boot Chain Certificate handover format combining the BCC and CDIs in a single CBOR object.
32#[derive(Clone, Debug)]
33pub struct Handover<'a> {
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +000034 buffer: &'a [u8],
Pierre-Clément Tosi8edf72e2022-12-06 16:02:57 +000035 /// Attestation CDI.
36 pub cdi_attest: &'a Cdi,
37 /// Sealing CDI.
38 pub cdi_seal: &'a Cdi,
39 /// Boot Chain Certificate (optional).
40 pub bcc: Option<&'a [u8]>,
41}
42
43impl<'a> Handover<'a> {
44 /// Validates and extracts the fields of a BCC handover buffer.
45 pub fn new(buffer: &'a [u8]) -> Result<Self> {
46 let mut cdi_attest: *const u8 = ptr::null();
47 let mut cdi_seal: *const u8 = ptr::null();
48 let mut bcc: *const u8 = ptr::null();
49 let mut bcc_size: usize = 0;
50
51 // SAFETY - The buffer is only read and never stored and the returned pointers should all
52 // point within the address range of the buffer or be NULL.
Alice Wanga7e4ce02023-02-03 13:37:14 +000053 check_result(unsafe {
Pierre-Clément Tosi8edf72e2022-12-06 16:02:57 +000054 BccHandoverParse(
55 buffer.as_ptr(),
56 buffer.len(),
57 &mut cdi_attest as *mut *const u8,
58 &mut cdi_seal as *mut *const u8,
59 &mut bcc as *mut *const u8,
60 &mut bcc_size as *mut usize,
61 )
62 })?;
63
64 let cdi_attest = {
Alice Wanga7e4ce02023-02-03 13:37:14 +000065 let i = index_from_ptr(buffer, cdi_attest).ok_or(DiceError::PlatformError)?;
66 let s = buffer.get(i..(i + mem::size_of::<Cdi>())).ok_or(DiceError::PlatformError)?;
67 s.try_into().map_err(|_| DiceError::PlatformError)?
Pierre-Clément Tosi8edf72e2022-12-06 16:02:57 +000068 };
69 let cdi_seal = {
Alice Wanga7e4ce02023-02-03 13:37:14 +000070 let i = index_from_ptr(buffer, cdi_seal).ok_or(DiceError::PlatformError)?;
71 let s = buffer.get(i..(i + mem::size_of::<Cdi>())).ok_or(DiceError::PlatformError)?;
72 s.try_into().map_err(|_| DiceError::PlatformError)?
Pierre-Clément Tosi8edf72e2022-12-06 16:02:57 +000073 };
74 let bcc = if bcc.is_null() {
75 None
76 } else {
Alice Wanga7e4ce02023-02-03 13:37:14 +000077 let i = index_from_ptr(buffer, bcc).ok_or(DiceError::PlatformError)?;
78 Some(buffer.get(i..(i + bcc_size)).ok_or(DiceError::PlatformError)?)
Pierre-Clément Tosi8edf72e2022-12-06 16:02:57 +000079 };
80
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +000081 Ok(Self { buffer, cdi_attest, cdi_seal, bcc })
Pierre-Clément Tosi8edf72e2022-12-06 16:02:57 +000082 }
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +000083
84 /// Executes the main BCC handover flow.
85 pub fn main_flow(&self, input_values: &InputValues, buffer: &mut [u8]) -> Result<usize> {
86 let context = ptr::null_mut();
87 let mut size: usize = 0;
88 // SAFETY - The function only reads `self.buffer`, writes to `buffer` within its bounds,
89 // reads `input_values` as a constant input and doesn't store any pointer.
Alice Wanga7e4ce02023-02-03 13:37:14 +000090 check_result(unsafe {
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +000091 BccHandoverMainFlow(
92 context,
93 self.buffer.as_ptr(),
94 self.buffer.len(),
Alice Wang5aeed332023-02-02 09:42:21 +000095 input_values.as_ptr(),
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +000096 buffer.len(),
97 buffer.as_mut_ptr(),
98 &mut size as *mut usize,
99 )
100 })?;
101
102 Ok(size)
103 }
104}
105
Pierre-Clément Tosi8edf72e2022-12-06 16:02:57 +0000106fn index_from_ptr(slice: &[u8], pointer: *const u8) -> Option<usize> {
107 if slice.as_ptr_range().contains(&pointer) {
108 (pointer as usize).checked_sub(slice.as_ptr() as usize)
109 } else {
110 None
111 }
112}