blob: 849dfa0f677dfdbf20f80ea198c1c0202a37d9f9 [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
22use open_dice_bcc_bindgen::BccHandoverParse;
23
24use crate::check_call;
25use crate::Cdi;
26use crate::Error;
27use crate::Result;
28
29/// Boot Chain Certificate handover format combining the BCC and CDIs in a single CBOR object.
30#[derive(Clone, Debug)]
31pub struct Handover<'a> {
32 /// Attestation CDI.
33 pub cdi_attest: &'a Cdi,
34 /// Sealing CDI.
35 pub cdi_seal: &'a Cdi,
36 /// Boot Chain Certificate (optional).
37 pub bcc: Option<&'a [u8]>,
38}
39
40impl<'a> Handover<'a> {
41 /// Validates and extracts the fields of a BCC handover buffer.
42 pub fn new(buffer: &'a [u8]) -> Result<Self> {
43 let mut cdi_attest: *const u8 = ptr::null();
44 let mut cdi_seal: *const u8 = ptr::null();
45 let mut bcc: *const u8 = ptr::null();
46 let mut bcc_size: usize = 0;
47
48 // SAFETY - The buffer is only read and never stored and the returned pointers should all
49 // point within the address range of the buffer or be NULL.
50 check_call(unsafe {
51 BccHandoverParse(
52 buffer.as_ptr(),
53 buffer.len(),
54 &mut cdi_attest as *mut *const u8,
55 &mut cdi_seal as *mut *const u8,
56 &mut bcc as *mut *const u8,
57 &mut bcc_size as *mut usize,
58 )
59 })?;
60
61 let cdi_attest = {
62 let i = index_from_ptr(buffer, cdi_attest).ok_or(Error::PlatformError)?;
63 let s = buffer.get(i..(i + mem::size_of::<Cdi>())).ok_or(Error::PlatformError)?;
64 s.try_into().map_err(|_| Error::PlatformError)?
65 };
66 let cdi_seal = {
67 let i = index_from_ptr(buffer, cdi_seal).ok_or(Error::PlatformError)?;
68 let s = buffer.get(i..(i + mem::size_of::<Cdi>())).ok_or(Error::PlatformError)?;
69 s.try_into().map_err(|_| Error::PlatformError)?
70 };
71 let bcc = if bcc.is_null() {
72 None
73 } else {
74 let i = index_from_ptr(buffer, bcc).ok_or(Error::PlatformError)?;
75 Some(buffer.get(i..(i + bcc_size)).ok_or(Error::PlatformError)?)
76 };
77
78 Ok(Self { cdi_attest, cdi_seal, bcc })
79 }
80}
81
82fn index_from_ptr(slice: &[u8], pointer: *const u8) -> Option<usize> {
83 if slice.as_ptr_range().contains(&pointer) {
84 (pointer as usize).checked_sub(slice.as_ptr() as usize)
85 } else {
86 None
87 }
88}