Alice Wang | 0b9e110 | 2023-02-02 09:57:06 +0000 | [diff] [blame] | 1 | // 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 Wang | 7cc5956 | 2023-02-08 13:17:10 +0000 | [diff] [blame] | 18 | use crate::error::{check_result, Result}; |
Alice Wang | 9c40eca | 2023-02-03 13:10:24 +0000 | [diff] [blame] | 19 | pub use open_dice_cbor_bindgen::DiceMode; |
Alice Wang | 0b9e110 | 2023-02-02 09:57:06 +0000 | [diff] [blame] | 20 | use open_dice_cbor_bindgen::{ |
Alice Wang | 7cc5956 | 2023-02-08 13:17:10 +0000 | [diff] [blame] | 21 | DiceConfigType, DiceDeriveCdiCertificateId, DiceDeriveCdiPrivateKeySeed, DiceInputValues, |
Alice Wang | 44f48b2 | 2023-02-09 09:51:22 +0000 | [diff] [blame] | 22 | DiceMainFlow, DICE_CDI_SIZE, DICE_HASH_SIZE, DICE_HIDDEN_SIZE, DICE_ID_SIZE, |
Alice Wang | 8722d9e | 2023-02-13 14:56:56 +0000 | [diff] [blame] | 23 | DICE_INLINE_CONFIG_SIZE, DICE_PRIVATE_KEY_SEED_SIZE, DICE_PRIVATE_KEY_SIZE, |
| 24 | DICE_PUBLIC_KEY_SIZE, DICE_SIGNATURE_SIZE, |
Alice Wang | 0b9e110 | 2023-02-02 09:57:06 +0000 | [diff] [blame] | 25 | }; |
Alice Wang | 856d656 | 2023-02-03 13:51:08 +0000 | [diff] [blame] | 26 | use std::ptr; |
Alice Wang | f4bd1c6 | 2023-02-08 08:38:44 +0000 | [diff] [blame] | 27 | use zeroize::{Zeroize, ZeroizeOnDrop}; |
Alice Wang | 0b9e110 | 2023-02-02 09:57:06 +0000 | [diff] [blame] | 28 | |
| 29 | /// The size of a DICE hash. |
| 30 | pub const HASH_SIZE: usize = DICE_HASH_SIZE as usize; |
| 31 | /// The size of the DICE hidden value. |
| 32 | pub const HIDDEN_SIZE: usize = DICE_HIDDEN_SIZE as usize; |
| 33 | /// The size of a DICE inline config. |
| 34 | const INLINE_CONFIG_SIZE: usize = DICE_INLINE_CONFIG_SIZE as usize; |
Alice Wang | 3213d49 | 2023-02-03 15:52:18 +0000 | [diff] [blame] | 35 | /// The size of a CDI. |
| 36 | pub const CDI_SIZE: usize = DICE_CDI_SIZE as usize; |
Alice Wang | 7cc5956 | 2023-02-08 13:17:10 +0000 | [diff] [blame] | 37 | /// The size of a private key seed. |
| 38 | pub const PRIVATE_KEY_SEED_SIZE: usize = DICE_PRIVATE_KEY_SEED_SIZE as usize; |
Alice Wang | 8722d9e | 2023-02-13 14:56:56 +0000 | [diff] [blame] | 39 | /// The size of a private key. |
| 40 | pub const PRIVATE_KEY_SIZE: usize = DICE_PRIVATE_KEY_SIZE as usize; |
| 41 | /// The size of a public key. |
| 42 | pub const PUBLIC_KEY_SIZE: usize = DICE_PUBLIC_KEY_SIZE as usize; |
| 43 | /// The size of a signature. |
| 44 | pub const SIGNATURE_SIZE: usize = DICE_SIGNATURE_SIZE as usize; |
Alice Wang | 7cc5956 | 2023-02-08 13:17:10 +0000 | [diff] [blame] | 45 | /// The size of an ID. |
| 46 | pub const ID_SIZE: usize = DICE_ID_SIZE as usize; |
Alice Wang | 0b9e110 | 2023-02-02 09:57:06 +0000 | [diff] [blame] | 47 | |
| 48 | /// Array type of hashes used by DICE. |
| 49 | pub type Hash = [u8; HASH_SIZE]; |
| 50 | /// Array type of additional input. |
| 51 | pub type Hidden = [u8; HIDDEN_SIZE]; |
| 52 | /// Array type of inline configuration values. |
| 53 | pub type InlineConfig = [u8; INLINE_CONFIG_SIZE]; |
Alice Wang | 3213d49 | 2023-02-03 15:52:18 +0000 | [diff] [blame] | 54 | /// Array type of CDIs. |
| 55 | pub type Cdi = [u8; CDI_SIZE]; |
Alice Wang | 7cc5956 | 2023-02-08 13:17:10 +0000 | [diff] [blame] | 56 | /// Array type of private key seeds. |
| 57 | pub type PrivateKeySeed = [u8; PRIVATE_KEY_SEED_SIZE]; |
Alice Wang | 8722d9e | 2023-02-13 14:56:56 +0000 | [diff] [blame] | 58 | /// Array type of the public key. |
| 59 | pub type PublicKey = [u8; PUBLIC_KEY_SIZE]; |
| 60 | /// Array type of the signature. |
| 61 | pub type Signature = [u8; SIGNATURE_SIZE]; |
Alice Wang | 7cc5956 | 2023-02-08 13:17:10 +0000 | [diff] [blame] | 62 | /// Array type of DICE ID. |
| 63 | pub type DiceId = [u8; ID_SIZE]; |
Alice Wang | 0b9e110 | 2023-02-02 09:57:06 +0000 | [diff] [blame] | 64 | |
Alice Wang | 4d3059a | 2023-02-15 10:24:33 +0000 | [diff] [blame^] | 65 | /// A trait for types that represent Dice artifacts, which include: |
| 66 | /// |
| 67 | /// - Attestation CDI |
| 68 | /// - Sealing CDI |
| 69 | /// - Boot Certificate Chain |
| 70 | /// |
| 71 | /// Types that implement this trait provide an access these artifacts. |
| 72 | pub trait DiceArtifacts { |
| 73 | /// Returns a reference to the attestation CDI. |
| 74 | fn cdi_attest(&self) -> &[u8; CDI_SIZE]; |
| 75 | |
| 76 | /// Returns a reference to the sealing CDI. |
| 77 | fn cdi_seal(&self) -> &[u8; CDI_SIZE]; |
| 78 | |
| 79 | /// Returns a reference to the Boot Certificate Chain, if present. |
| 80 | fn bcc(&self) -> Option<&[u8]>; |
| 81 | } |
| 82 | |
Alice Wang | f4bd1c6 | 2023-02-08 08:38:44 +0000 | [diff] [blame] | 83 | /// CDI Values. |
Alice Wang | acee4fb | 2023-02-15 09:42:07 +0000 | [diff] [blame] | 84 | #[derive(Debug, Zeroize, ZeroizeOnDrop, Default)] |
Alice Wang | f4bd1c6 | 2023-02-08 08:38:44 +0000 | [diff] [blame] | 85 | pub struct CdiValues { |
| 86 | /// Attestation CDI. |
Alice Wang | 4d3059a | 2023-02-15 10:24:33 +0000 | [diff] [blame^] | 87 | pub cdi_attest: [u8; CDI_SIZE], |
Alice Wang | f4bd1c6 | 2023-02-08 08:38:44 +0000 | [diff] [blame] | 88 | /// Sealing CDI. |
Alice Wang | 4d3059a | 2023-02-15 10:24:33 +0000 | [diff] [blame^] | 89 | pub cdi_seal: [u8; CDI_SIZE], |
Alice Wang | f4bd1c6 | 2023-02-08 08:38:44 +0000 | [diff] [blame] | 90 | } |
| 91 | |
Alice Wang | 0b9e110 | 2023-02-02 09:57:06 +0000 | [diff] [blame] | 92 | /// Configuration descriptor for DICE input values. |
| 93 | #[derive(Debug, Clone, PartialEq, Eq)] |
| 94 | pub enum Config<'a> { |
| 95 | /// Reference to an inline descriptor. |
| 96 | Inline(&'a InlineConfig), |
| 97 | /// Reference to a free form descriptor that will be hashed by the implementation. |
| 98 | Descriptor(&'a [u8]), |
| 99 | } |
| 100 | |
| 101 | impl Config<'_> { |
| 102 | fn dice_config_type(&self) -> DiceConfigType { |
| 103 | match self { |
| 104 | Self::Inline(_) => DiceConfigType::kDiceConfigTypeInline, |
| 105 | Self::Descriptor(_) => DiceConfigType::kDiceConfigTypeDescriptor, |
| 106 | } |
| 107 | } |
| 108 | |
| 109 | fn inline_config(&self) -> InlineConfig { |
| 110 | match self { |
| 111 | Self::Inline(inline) => **inline, |
| 112 | Self::Descriptor(_) => [0u8; INLINE_CONFIG_SIZE], |
| 113 | } |
| 114 | } |
| 115 | |
| 116 | fn descriptor_ptr(&self) -> *const u8 { |
| 117 | match self { |
| 118 | Self::Descriptor(descriptor) => descriptor.as_ptr(), |
| 119 | _ => ptr::null(), |
| 120 | } |
| 121 | } |
| 122 | |
| 123 | fn descriptor_size(&self) -> usize { |
| 124 | match self { |
| 125 | Self::Descriptor(descriptor) => descriptor.len(), |
| 126 | _ => 0, |
| 127 | } |
| 128 | } |
| 129 | } |
| 130 | |
| 131 | /// Wrap of `DiceInputValues`. |
| 132 | #[derive(Clone, Debug)] |
| 133 | pub struct InputValues(DiceInputValues); |
| 134 | |
| 135 | impl InputValues { |
| 136 | /// Creates a new `InputValues`. |
| 137 | pub fn new( |
Alice Wang | b68814b | 2023-02-02 13:15:32 +0000 | [diff] [blame] | 138 | code_hash: Hash, |
Alice Wang | 0b9e110 | 2023-02-02 09:57:06 +0000 | [diff] [blame] | 139 | config: Config, |
Alice Wang | b68814b | 2023-02-02 13:15:32 +0000 | [diff] [blame] | 140 | authority_hash: Hash, |
Alice Wang | 0b9e110 | 2023-02-02 09:57:06 +0000 | [diff] [blame] | 141 | mode: DiceMode, |
Alice Wang | b68814b | 2023-02-02 13:15:32 +0000 | [diff] [blame] | 142 | hidden: Hidden, |
Alice Wang | 0b9e110 | 2023-02-02 09:57:06 +0000 | [diff] [blame] | 143 | ) -> Self { |
| 144 | Self(DiceInputValues { |
Alice Wang | b68814b | 2023-02-02 13:15:32 +0000 | [diff] [blame] | 145 | code_hash, |
| 146 | code_descriptor: ptr::null(), |
| 147 | code_descriptor_size: 0, |
Alice Wang | 0b9e110 | 2023-02-02 09:57:06 +0000 | [diff] [blame] | 148 | config_type: config.dice_config_type(), |
| 149 | config_value: config.inline_config(), |
| 150 | config_descriptor: config.descriptor_ptr(), |
| 151 | config_descriptor_size: config.descriptor_size(), |
Alice Wang | b68814b | 2023-02-02 13:15:32 +0000 | [diff] [blame] | 152 | authority_hash, |
| 153 | authority_descriptor: ptr::null(), |
| 154 | authority_descriptor_size: 0, |
Alice Wang | 0b9e110 | 2023-02-02 09:57:06 +0000 | [diff] [blame] | 155 | mode, |
Alice Wang | b68814b | 2023-02-02 13:15:32 +0000 | [diff] [blame] | 156 | hidden, |
Alice Wang | 0b9e110 | 2023-02-02 09:57:06 +0000 | [diff] [blame] | 157 | }) |
| 158 | } |
| 159 | |
| 160 | /// Returns a raw pointer to the wrapped `DiceInputValues`. |
| 161 | pub fn as_ptr(&self) -> *const DiceInputValues { |
| 162 | &self.0 as *const DiceInputValues |
| 163 | } |
| 164 | } |
Alice Wang | 7cc5956 | 2023-02-08 13:17:10 +0000 | [diff] [blame] | 165 | |
| 166 | /// Derives a CDI private key seed from a `cdi_attest` value. |
| 167 | pub fn derive_cdi_private_key_seed(cdi_attest: &Cdi) -> Result<PrivateKeySeed> { |
| 168 | let mut seed = [0u8; PRIVATE_KEY_SEED_SIZE]; |
| 169 | // SAFETY: The function writes to the buffer within the given bounds, and only reads the |
| 170 | // input values. The first argument context is not used in this function. |
| 171 | check_result(unsafe { |
| 172 | DiceDeriveCdiPrivateKeySeed( |
| 173 | ptr::null_mut(), // context |
| 174 | cdi_attest.as_ptr(), |
| 175 | seed.as_mut_ptr(), |
| 176 | ) |
| 177 | })?; |
| 178 | Ok(seed) |
| 179 | } |
| 180 | |
| 181 | /// Derives an ID from the given `cdi_public_key` value. |
| 182 | pub fn derive_cdi_certificate_id(cdi_public_key: &[u8]) -> Result<DiceId> { |
| 183 | let mut id = [0u8; ID_SIZE]; |
| 184 | // SAFETY: The function writes to the buffer within the given bounds, and only reads the |
| 185 | // input values. The first argument context is not used in this function. |
| 186 | check_result(unsafe { |
| 187 | DiceDeriveCdiCertificateId( |
| 188 | ptr::null_mut(), // context |
| 189 | cdi_public_key.as_ptr(), |
| 190 | cdi_public_key.len(), |
| 191 | id.as_mut_ptr(), |
| 192 | ) |
| 193 | })?; |
| 194 | Ok(id) |
| 195 | } |
Alice Wang | 44f48b2 | 2023-02-09 09:51:22 +0000 | [diff] [blame] | 196 | |
| 197 | /// Executes the main DICE flow. |
| 198 | /// |
| 199 | /// Given a full set of input values and the current CDI values, computes the |
| 200 | /// next CDI values and a matching certificate. |
| 201 | /// Returns the actual size of the next CDI certificate. |
| 202 | pub fn dice_main_flow( |
| 203 | current_cdi_attest: &Cdi, |
| 204 | current_cdi_seal: &Cdi, |
| 205 | input_values: &InputValues, |
| 206 | next_cdi_certificate: &mut [u8], |
| 207 | next_cdi_values: &mut CdiValues, |
| 208 | ) -> Result<usize> { |
| 209 | let mut next_cdi_certificate_actual_size = 0; |
| 210 | // SAFETY: The function only reads the current CDI values and inputs and writes |
| 211 | // to `next_cdi_certificate` and next CDI values within its bounds. |
| 212 | // The first argument can be null and is not used in the current implementation. |
| 213 | check_result(unsafe { |
| 214 | DiceMainFlow( |
| 215 | ptr::null_mut(), // context |
| 216 | current_cdi_attest.as_ptr(), |
| 217 | current_cdi_seal.as_ptr(), |
| 218 | input_values.as_ptr(), |
| 219 | next_cdi_certificate.len(), |
| 220 | next_cdi_certificate.as_mut_ptr(), |
| 221 | &mut next_cdi_certificate_actual_size, |
| 222 | next_cdi_values.cdi_attest.as_mut_ptr(), |
| 223 | next_cdi_values.cdi_seal.as_mut_ptr(), |
| 224 | ) |
| 225 | })?; |
| 226 | Ok(next_cdi_certificate_actual_size) |
| 227 | } |