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 | f4bd1c6 | 2023-02-08 08:38:44 +0000 | [diff] [blame] | 65 | /// CDI Values. |
| 66 | #[derive(Zeroize, ZeroizeOnDrop, Default)] |
| 67 | pub struct CdiValues { |
| 68 | /// Attestation CDI. |
| 69 | pub cdi_attest: Cdi, |
| 70 | /// Sealing CDI. |
| 71 | pub cdi_seal: Cdi, |
| 72 | } |
| 73 | |
Alice Wang | 0b9e110 | 2023-02-02 09:57:06 +0000 | [diff] [blame] | 74 | /// Configuration descriptor for DICE input values. |
| 75 | #[derive(Debug, Clone, PartialEq, Eq)] |
| 76 | pub enum Config<'a> { |
| 77 | /// Reference to an inline descriptor. |
| 78 | Inline(&'a InlineConfig), |
| 79 | /// Reference to a free form descriptor that will be hashed by the implementation. |
| 80 | Descriptor(&'a [u8]), |
| 81 | } |
| 82 | |
| 83 | impl Config<'_> { |
| 84 | fn dice_config_type(&self) -> DiceConfigType { |
| 85 | match self { |
| 86 | Self::Inline(_) => DiceConfigType::kDiceConfigTypeInline, |
| 87 | Self::Descriptor(_) => DiceConfigType::kDiceConfigTypeDescriptor, |
| 88 | } |
| 89 | } |
| 90 | |
| 91 | fn inline_config(&self) -> InlineConfig { |
| 92 | match self { |
| 93 | Self::Inline(inline) => **inline, |
| 94 | Self::Descriptor(_) => [0u8; INLINE_CONFIG_SIZE], |
| 95 | } |
| 96 | } |
| 97 | |
| 98 | fn descriptor_ptr(&self) -> *const u8 { |
| 99 | match self { |
| 100 | Self::Descriptor(descriptor) => descriptor.as_ptr(), |
| 101 | _ => ptr::null(), |
| 102 | } |
| 103 | } |
| 104 | |
| 105 | fn descriptor_size(&self) -> usize { |
| 106 | match self { |
| 107 | Self::Descriptor(descriptor) => descriptor.len(), |
| 108 | _ => 0, |
| 109 | } |
| 110 | } |
| 111 | } |
| 112 | |
| 113 | /// Wrap of `DiceInputValues`. |
| 114 | #[derive(Clone, Debug)] |
| 115 | pub struct InputValues(DiceInputValues); |
| 116 | |
| 117 | impl InputValues { |
| 118 | /// Creates a new `InputValues`. |
| 119 | pub fn new( |
Alice Wang | b68814b | 2023-02-02 13:15:32 +0000 | [diff] [blame] | 120 | code_hash: Hash, |
Alice Wang | 0b9e110 | 2023-02-02 09:57:06 +0000 | [diff] [blame] | 121 | config: Config, |
Alice Wang | b68814b | 2023-02-02 13:15:32 +0000 | [diff] [blame] | 122 | authority_hash: Hash, |
Alice Wang | 0b9e110 | 2023-02-02 09:57:06 +0000 | [diff] [blame] | 123 | mode: DiceMode, |
Alice Wang | b68814b | 2023-02-02 13:15:32 +0000 | [diff] [blame] | 124 | hidden: Hidden, |
Alice Wang | 0b9e110 | 2023-02-02 09:57:06 +0000 | [diff] [blame] | 125 | ) -> Self { |
| 126 | Self(DiceInputValues { |
Alice Wang | b68814b | 2023-02-02 13:15:32 +0000 | [diff] [blame] | 127 | code_hash, |
| 128 | code_descriptor: ptr::null(), |
| 129 | code_descriptor_size: 0, |
Alice Wang | 0b9e110 | 2023-02-02 09:57:06 +0000 | [diff] [blame] | 130 | config_type: config.dice_config_type(), |
| 131 | config_value: config.inline_config(), |
| 132 | config_descriptor: config.descriptor_ptr(), |
| 133 | config_descriptor_size: config.descriptor_size(), |
Alice Wang | b68814b | 2023-02-02 13:15:32 +0000 | [diff] [blame] | 134 | authority_hash, |
| 135 | authority_descriptor: ptr::null(), |
| 136 | authority_descriptor_size: 0, |
Alice Wang | 0b9e110 | 2023-02-02 09:57:06 +0000 | [diff] [blame] | 137 | mode, |
Alice Wang | b68814b | 2023-02-02 13:15:32 +0000 | [diff] [blame] | 138 | hidden, |
Alice Wang | 0b9e110 | 2023-02-02 09:57:06 +0000 | [diff] [blame] | 139 | }) |
| 140 | } |
| 141 | |
| 142 | /// Returns a raw pointer to the wrapped `DiceInputValues`. |
| 143 | pub fn as_ptr(&self) -> *const DiceInputValues { |
| 144 | &self.0 as *const DiceInputValues |
| 145 | } |
| 146 | } |
Alice Wang | 7cc5956 | 2023-02-08 13:17:10 +0000 | [diff] [blame] | 147 | |
| 148 | /// Derives a CDI private key seed from a `cdi_attest` value. |
| 149 | pub fn derive_cdi_private_key_seed(cdi_attest: &Cdi) -> Result<PrivateKeySeed> { |
| 150 | let mut seed = [0u8; PRIVATE_KEY_SEED_SIZE]; |
| 151 | // SAFETY: The function writes to the buffer within the given bounds, and only reads the |
| 152 | // input values. The first argument context is not used in this function. |
| 153 | check_result(unsafe { |
| 154 | DiceDeriveCdiPrivateKeySeed( |
| 155 | ptr::null_mut(), // context |
| 156 | cdi_attest.as_ptr(), |
| 157 | seed.as_mut_ptr(), |
| 158 | ) |
| 159 | })?; |
| 160 | Ok(seed) |
| 161 | } |
| 162 | |
| 163 | /// Derives an ID from the given `cdi_public_key` value. |
| 164 | pub fn derive_cdi_certificate_id(cdi_public_key: &[u8]) -> Result<DiceId> { |
| 165 | let mut id = [0u8; ID_SIZE]; |
| 166 | // SAFETY: The function writes to the buffer within the given bounds, and only reads the |
| 167 | // input values. The first argument context is not used in this function. |
| 168 | check_result(unsafe { |
| 169 | DiceDeriveCdiCertificateId( |
| 170 | ptr::null_mut(), // context |
| 171 | cdi_public_key.as_ptr(), |
| 172 | cdi_public_key.len(), |
| 173 | id.as_mut_ptr(), |
| 174 | ) |
| 175 | })?; |
| 176 | Ok(id) |
| 177 | } |
Alice Wang | 44f48b2 | 2023-02-09 09:51:22 +0000 | [diff] [blame] | 178 | |
| 179 | /// Executes the main DICE flow. |
| 180 | /// |
| 181 | /// Given a full set of input values and the current CDI values, computes the |
| 182 | /// next CDI values and a matching certificate. |
| 183 | /// Returns the actual size of the next CDI certificate. |
| 184 | pub fn dice_main_flow( |
| 185 | current_cdi_attest: &Cdi, |
| 186 | current_cdi_seal: &Cdi, |
| 187 | input_values: &InputValues, |
| 188 | next_cdi_certificate: &mut [u8], |
| 189 | next_cdi_values: &mut CdiValues, |
| 190 | ) -> Result<usize> { |
| 191 | let mut next_cdi_certificate_actual_size = 0; |
| 192 | // SAFETY: The function only reads the current CDI values and inputs and writes |
| 193 | // to `next_cdi_certificate` and next CDI values within its bounds. |
| 194 | // The first argument can be null and is not used in the current implementation. |
| 195 | check_result(unsafe { |
| 196 | DiceMainFlow( |
| 197 | ptr::null_mut(), // context |
| 198 | current_cdi_attest.as_ptr(), |
| 199 | current_cdi_seal.as_ptr(), |
| 200 | input_values.as_ptr(), |
| 201 | next_cdi_certificate.len(), |
| 202 | next_cdi_certificate.as_mut_ptr(), |
| 203 | &mut next_cdi_certificate_actual_size, |
| 204 | next_cdi_values.cdi_attest.as_mut_ptr(), |
| 205 | next_cdi_values.cdi_seal.as_mut_ptr(), |
| 206 | ) |
| 207 | })?; |
| 208 | Ok(next_cdi_certificate_actual_size) |
| 209 | } |