tss_esapi/structures/
capability_data.rs

1// Copyright 2020 Contributors to the Parsec project.
2// SPDX-License-Identifier: Apache-2.0
3use crate::{
4    constants::CapabilityType,
5    structures::{
6        AlgorithmPropertyList, CommandCodeAttributesList, CommandCodeList, EccCurveList,
7        HandleList, PcrSelectionList, TaggedPcrPropertyList, TaggedTpmPropertyList,
8    },
9    tss2_esys::{TPM2_CAP, TPM2_MAX_CAP_BUFFER, TPMS_CAPABILITY_DATA, TPMU_CAPABILITIES},
10    Error, Result, WrapperErrorKind,
11};
12use log::error;
13use std::convert::{TryFrom, TryInto};
14use std::mem::size_of;
15
16/// A representation of all the capabilites that can be associated
17/// with a TPM.
18///
19/// # Details
20/// This corresponds to `TPMS_CAPABILITY_DATA`
21#[non_exhaustive]
22#[derive(Debug, Clone)]
23pub enum CapabilityData {
24    Algorithms(AlgorithmPropertyList),
25    Handles(HandleList),
26    Commands(CommandCodeAttributesList),
27    PpCommands(CommandCodeList),
28    AuditCommands(CommandCodeList),
29    AssignedPcr(PcrSelectionList),
30    TpmProperties(TaggedTpmPropertyList),
31    PcrProperties(TaggedPcrPropertyList),
32    EccCurves(EccCurveList),
33    // These are in the TPM TPMU_CAPABILITIES, but are not defined by esapi-2.4.1
34    // AuthPolicies(),
35    // ActData(),
36}
37
38pub const fn max_cap_size<T>() -> usize {
39    (TPM2_MAX_CAP_BUFFER as usize - size_of::<TPM2_CAP>() - size_of::<u32>()) / size_of::<T>()
40}
41
42impl From<CapabilityData> for TPMS_CAPABILITY_DATA {
43    fn from(capability_data: CapabilityData) -> Self {
44        match capability_data {
45            CapabilityData::Algorithms(data) => TPMS_CAPABILITY_DATA {
46                capability: CapabilityType::Algorithms.into(),
47                data: TPMU_CAPABILITIES {
48                    algorithms: data.into(),
49                },
50            },
51            CapabilityData::Handles(data) => TPMS_CAPABILITY_DATA {
52                capability: CapabilityType::Handles.into(),
53                data: TPMU_CAPABILITIES {
54                    handles: data.into(),
55                },
56            },
57            CapabilityData::Commands(data) => TPMS_CAPABILITY_DATA {
58                capability: CapabilityType::Command.into(),
59                data: TPMU_CAPABILITIES {
60                    command: data.into(),
61                },
62            },
63            CapabilityData::PpCommands(data) => TPMS_CAPABILITY_DATA {
64                capability: CapabilityType::PpCommands.into(),
65                data: TPMU_CAPABILITIES {
66                    ppCommands: data.into(),
67                },
68            },
69            CapabilityData::AuditCommands(data) => TPMS_CAPABILITY_DATA {
70                capability: CapabilityType::AuditCommands.into(),
71                data: TPMU_CAPABILITIES {
72                    auditCommands: data.into(),
73                },
74            },
75            CapabilityData::AssignedPcr(data) => TPMS_CAPABILITY_DATA {
76                capability: CapabilityType::AssignedPcr.into(),
77                data: TPMU_CAPABILITIES {
78                    assignedPCR: data.into(),
79                },
80            },
81            CapabilityData::TpmProperties(data) => TPMS_CAPABILITY_DATA {
82                capability: CapabilityType::TpmProperties.into(),
83                data: TPMU_CAPABILITIES {
84                    tpmProperties: data.into(),
85                },
86            },
87            CapabilityData::PcrProperties(data) => TPMS_CAPABILITY_DATA {
88                capability: CapabilityType::PcrProperties.into(),
89                data: TPMU_CAPABILITIES {
90                    pcrProperties: data.into(),
91                },
92            },
93            CapabilityData::EccCurves(data) => TPMS_CAPABILITY_DATA {
94                capability: CapabilityType::EccCurves.into(),
95                data: TPMU_CAPABILITIES {
96                    eccCurves: data.into(),
97                },
98            },
99        }
100    }
101}
102
103impl TryFrom<TPMS_CAPABILITY_DATA> for CapabilityData {
104    type Error = Error;
105
106    fn try_from(tpms_capability_data: TPMS_CAPABILITY_DATA) -> Result<Self> {
107        // SAFETY: This is a C union, and Rust wants us to make sure we're using the correct item.
108        // These unsafe blocks are fine because we ensure the correct type is used.
109        match CapabilityType::try_from(tpms_capability_data.capability)? {
110            CapabilityType::Algorithms => Ok(CapabilityData::Algorithms(
111                unsafe { tpms_capability_data.data.algorithms }.try_into()?,
112            )),
113            CapabilityType::Handles => Ok(CapabilityData::Handles(
114                unsafe { tpms_capability_data.data.handles }.try_into()?,
115            )),
116            CapabilityType::Command => Ok(CapabilityData::Commands(
117                unsafe { tpms_capability_data.data.command }.try_into()?,
118            )),
119            CapabilityType::PpCommands => Ok(CapabilityData::PpCommands(
120                unsafe { tpms_capability_data.data.ppCommands }.try_into()?,
121            )),
122            CapabilityType::AuditCommands => Ok(CapabilityData::AuditCommands(
123                unsafe { tpms_capability_data.data.auditCommands }.try_into()?,
124            )),
125            CapabilityType::AssignedPcr => Ok(CapabilityData::AssignedPcr(
126                unsafe { tpms_capability_data.data.assignedPCR }.try_into()?,
127            )),
128            CapabilityType::TpmProperties => Ok(CapabilityData::TpmProperties(
129                unsafe { tpms_capability_data.data.tpmProperties }.try_into()?,
130            )),
131            CapabilityType::PcrProperties => Ok(CapabilityData::PcrProperties(
132                unsafe { tpms_capability_data.data.pcrProperties }.try_into()?,
133            )),
134            CapabilityType::EccCurves => Ok(CapabilityData::EccCurves(
135                unsafe { tpms_capability_data.data.eccCurves }.try_into()?,
136            )),
137            CapabilityType::AuthPolicies => {
138                error!("AuthPolicies capability type is currently not supported");
139                Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam))
140            }
141            CapabilityType::Act => {
142                error!("Act capability type is currently not supported");
143                Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam))
144            }
145        }
146    }
147}