| // Copyright 2024 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| // use this file except in compliance with the License. You may obtain a copy of |
| // the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| // License for the specific language governing permissions and limitations under |
| // the License. |
| |
| //! Types and traits related to DICE. |
| use crate::byte_array_wrapper; |
| use crate::constants::{ |
| DICE_CDI_SIZE, DICE_UDS_SIZE, DPE_MAX_CERTIFICATE_INFOS_PER_CONTEXT, |
| DPE_MAX_CERTIFICATE_SIZE, |
| }; |
| use crate::crypto::{ |
| EncryptionKey, Hash, MacKey, SealingPrivateKey, SealingPublicKey, |
| SigningPrivateKey, SigningPublicKey, |
| }; |
| use crate::error::DpeResult; |
| use heapless::Vec; |
| use num_derive::{FromPrimitive, ToPrimitive}; |
| use zeroize::ZeroizeOnDrop; |
| |
| byte_array_wrapper!(Uds, DICE_UDS_SIZE, "UDS"); |
| byte_array_wrapper!(Cdi, DICE_CDI_SIZE, "CDI"); |
| |
| /// A Vec wrapper to represent a single encoded certificate. |
| #[derive(Clone, Debug, Default, Eq, PartialEq, Hash, ZeroizeOnDrop)] |
| pub(crate) struct Certificate(pub(crate) Vec<u8, DPE_MAX_CERTIFICATE_SIZE>); |
| |
| /// Contains all the information necessary to construct a certificate except for |
| /// the subject and issuer keys. |
| #[derive(Clone, Debug, Default, Eq, PartialEq, Hash, ZeroizeOnDrop)] |
| pub(crate) struct CertificateInfo(pub(crate) Vec<u8, DPE_MAX_CERTIFICATE_SIZE>); |
| |
| /// A Vec wrapper to represent a [`CertificateInfo`] list. |
| #[derive(Clone, Debug, Default, Eq, PartialEq, Hash)] |
| pub(crate) struct CertificateInfoList( |
| pub(crate) Vec<CertificateInfo, DPE_MAX_CERTIFICATE_INFOS_PER_CONTEXT>, |
| ); |
| |
| /// Represents a code input value as defined by the Open Profile for DICE. |
| #[derive(Clone, Debug, Eq, PartialEq, Hash)] |
| pub(crate) enum DiceInputCode<'a> { |
| /// The client provides the hash directly. |
| CodeHash(Hash), |
| /// The client provides a free-form descriptor. |
| CodeDescriptor(&'a [u8]), |
| } |
| |
| /// Represents an authority input value as defined by the Open Profile for DICE. |
| #[derive(Clone, Debug, Eq, PartialEq, Hash)] |
| pub(crate) enum DiceInputAuthority<'a> { |
| /// The client provides the hash directly. |
| AuthorityHash(Hash), |
| /// The client provides a free-form descriptor. |
| AuthorityDescriptor(&'a [u8]), |
| } |
| |
| /// Represents a config value as defined by the Open Profile for DICE. |
| #[derive(Clone, Debug, Eq, PartialEq, Hash)] |
| pub(crate) enum DiceInputConfig<'a> { |
| /// The client provides a 64-byte value. |
| ConfigInlineValue(Hash), |
| /// The client provides a free-form descriptor. |
| ConfigDescriptor(&'a [u8]), |
| } |
| |
| /// Represents the mode value in DICE input. The discriminants match the |
| /// corresponding encoded values for CBOR or X.509. See the Open Profile for |
| /// DICE specification for details. |
| #[derive( |
| Clone, Copy, Debug, Eq, PartialEq, Hash, FromPrimitive, ToPrimitive, |
| )] |
| pub(crate) enum DiceInputMode { |
| /// The `Not Configured` mode. |
| NotInitialized = 0, |
| /// The `Normal` mode. |
| Normal = 1, |
| /// The `Debug` mode. |
| Debug = 2, |
| /// The `Recovery` mode (aka maintenance mode). |
| Recovery = 3, |
| } |
| |
| /// Defines the supported internal input types. The enum discriminants match the |
| /// encoded CBOR values. When an internal input is indicated as part of a |
| /// context derivation, the corresponding information is included in the CDI |
| /// derivation and possibly an associated certificate. |
| #[derive( |
| Clone, Copy, Debug, Eq, PartialEq, Hash, FromPrimitive, ToPrimitive, |
| )] |
| pub(crate) enum InternalInputType { |
| /// Associated with information the DPE has about its own identity. This |
| /// information is included in the context's certificate info. |
| DpeInfo = 1, |
| /// Associated with information the DPE has about its own DICE attestation |
| /// data. This information is included in the context's certificate info. |
| DpeDice = 2, |
| /// Associated with a value that can be rotated in some way. This value |
| /// remains internal to the DPE and is not included in certificate info. |
| RotationValue = 3, |
| /// Associated with a monotonic counter internal do the DPE. This value |
| /// remains internal to the DPE and is not included in certificate info. |
| MonotonicCounter = 4, |
| } |
| |
| /// Represents a complete set of DICE input values as defined by the Open |
| /// Profile for DICE. |
| #[derive(Clone, Debug, Eq, PartialEq, Hash)] |
| pub(crate) struct DiceInput<'a> { |
| /// The `Code` input value. |
| pub(crate) code: DiceInputCode<'a>, |
| /// The `Configuration Data` input value. |
| pub(crate) config: DiceInputConfig<'a>, |
| /// The `Authority Data` input value. When not provided, the value will be |
| /// 64 zero bytes. |
| pub(crate) authority: Option<DiceInputAuthority<'a>>, |
| /// The `Mode Decision` input value. |
| pub(crate) mode: DiceInputMode, |
| /// The `Hidden Inputs` input value. When not provided, the value will be |
| /// 64 zero bytes. |
| pub(crate) hidden: Option<Hash>, |
| } |
| |
| /// A trait to represent DICE-related functionality required by a DPE. |
| pub(crate) trait Dice { |
| /// Performs a DICE derivation flow. |
| /// |
| /// On success returns a tuple containing the new CDI for signing followed |
| /// by the new CDI for sealing. |
| fn dice( |
| &self, |
| cdi_sign: &Cdi, |
| cdi_seal: &Cdi, |
| inputs: &DiceInput, |
| internal_inputs: &[InternalInputType], |
| is_export: bool, |
| ) -> DpeResult<(Cdi, Cdi)>; |
| |
| /// Derives a key pair from a CDI for signing certificates (embedded CA). |
| fn derive_eca_key_pair( |
| &self, |
| cdi_sign: &Cdi, |
| ) -> DpeResult<(SigningPublicKey, SigningPrivateKey)>; |
| |
| /// Derives a key pair from a CDI for general purpose signing. |
| fn derive_signing_key_pair( |
| &self, |
| cdi_sign: &Cdi, |
| label: &[u8], |
| ) -> DpeResult<(SigningPublicKey, SigningPrivateKey)>; |
| |
| /// Derives a key pair from a CDI for asymmetric sealing. |
| fn derive_sealing_key_pair( |
| &self, |
| cdi_seal: &Cdi, |
| label: &[u8], |
| unseal_policy: &[u8], |
| ) -> DpeResult<(SealingPublicKey, SealingPrivateKey)>; |
| |
| /// Derives a key from a CDI for generating MACs. |
| fn derive_mac_key(&self, cdi_sign: &Cdi, label: &[u8]) |
| -> DpeResult<MacKey>; |
| |
| /// Derives a key from a CDI for symmetric sealing. |
| fn derive_sealing_key( |
| &self, |
| cdi_seal: &Cdi, |
| label: &[u8], |
| unseal_policy: &[u8], |
| ) -> DpeResult<EncryptionKey>; |
| |
| /// Populates [`CertificateInfo`] from the given DICE inputs. |
| fn create_certificate_info( |
| &self, |
| inputs: &DiceInput, |
| internal_inputs: &[InternalInputType], |
| ) -> DpeResult<CertificateInfo>; |
| |
| /// Creates an embedded CA certificate. |
| /// |
| /// Derive the `subject_public_key` using [`Dice::derive_eca_key_pair`]. |
| fn create_eca_certificate( |
| &self, |
| issuer_key_pair: &(SigningPublicKey, SigningPrivateKey), |
| subject_public_key: &SigningPublicKey, |
| certificate_info: &CertificateInfo, |
| additional_certificate_info: &CertificateInfoList, |
| is_export: bool, |
| ) -> DpeResult<Certificate>; |
| |
| /// Creates a leaf certificate. |
| /// |
| /// Derive the `subject_public_key` using [`Dice::derive_signing_key_pair`]. |
| fn create_leaf_certificate( |
| &self, |
| issuer_key_pair: &(SigningPublicKey, SigningPrivateKey), |
| subject_public_key: &SigningPublicKey, |
| certificate_info: &CertificateInfoList, |
| additional_input: &[u8], |
| ) -> DpeResult<Certificate>; |
| } |