tss_esapi/handles/
handle.rs

1// Copyright 2020 Contributors to the Parsec project.
2// SPDX-License-Identifier: Apache-2.0
3
4//! ESYS handle types
5//!
6//! The ESAPI specification has only one handle type
7//! ESYS_TR. That type is wrapped by ObjectHandle but there
8//! are also specific handle types that indicates what created
9//! them or how they are intended to be used.
10
11pub mod conversions {
12    pub(crate) trait TryIntoNotNone {
13        fn try_into_not_none(self) -> crate::Result<crate::tss2_esys::ESYS_TR>;
14    }
15}
16
17/// Macro for generating a basic handle implementation
18macro_rules! impl_basic_handle {
19    (
20        $(#[$outer:meta])*
21        $handle_type:ident
22    ) => {
23        use crate::tss2_esys::ESYS_TR;
24        use std::convert::From;
25
26        $(#[$outer])*
27        #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
28        pub struct $handle_type {
29            value: u32,
30        }
31
32        impl $handle_type {
33            pub fn value(&self) -> u32 {
34                self.value
35            }
36        }
37
38        impl From<ESYS_TR> for $handle_type {
39            fn from(tss_esys_object_handle: ESYS_TR) -> $handle_type {
40                $handle_type {
41                    value: tss_esys_object_handle,
42                }
43            }
44        }
45
46        impl From<$handle_type> for ESYS_TR {
47            fn from(handle: $handle_type) -> ESYS_TR {
48                handle.value
49            }
50        }
51    };
52}
53
54/// Macro for making a esys constant available
55/// for a handle type.
56macro_rules! add_constant_handle {
57    ($handle_type:ident, $constant_handle_name:ident, $constant_handle_value:ident) => {
58        impl $handle_type {
59            #[allow(non_upper_case_globals)]
60            pub const $constant_handle_name: $handle_type = $handle_type {
61                value: $constant_handle_value,
62            };
63        }
64    };
65}
66
67/// Macro for making the Esys None constant available
68/// for a handle type
69macro_rules! add_constant_none_handle {
70    ($handle_type:ident) => {
71        use crate::{
72            handles::handle_conversion::TryIntoNotNone, tss2_esys::ESYS_TR_NONE, Error, Result,
73            WrapperErrorKind as ErrorKind,
74        };
75        use log::error;
76
77        add_constant_handle!($handle_type, None, ESYS_TR_NONE);
78
79        impl $handle_type {
80            /// Method that returns true if the handle corresponds
81            /// to the None handle.
82            pub fn is_none(&self) -> bool {
83                *self == $handle_type::None
84            }
85        }
86
87        impl TryIntoNotNone for $handle_type {
88            fn try_into_not_none(self) -> Result<ESYS_TR> {
89                if !self.is_none() {
90                    Ok(self.into())
91                } else {
92                    error!("Found invalid parameter {}::None", stringify!($handle_type));
93                    Err(Error::local_error(ErrorKind::InvalidParam))
94                }
95            }
96        }
97    };
98}
99
100/// Module for the ObjectHandle
101pub mod object {
102    use crate::tss2_esys::{
103        ESYS_TR_PASSWORD, ESYS_TR_RH_ENDORSEMENT, ESYS_TR_RH_LOCKOUT, ESYS_TR_RH_NULL,
104        ESYS_TR_RH_OWNER, ESYS_TR_RH_PLATFORM, ESYS_TR_RH_PLATFORM_NV,
105    };
106
107    impl_basic_handle!(
108        /// The ObjectHandle is the general handle type
109        /// and it wraps the ESYS_TR.
110        ///
111        /// All the other more specific handle types can be
112        /// converted into an ObjectHandle.
113        ObjectHandle
114    );
115
116    // Add None handle
117    add_constant_none_handle!(ObjectHandle);
118    // Add all the other constant handles
119    add_constant_handle!(ObjectHandle, Password, ESYS_TR_PASSWORD);
120    add_constant_handle!(ObjectHandle, Owner, ESYS_TR_RH_OWNER);
121    add_constant_handle!(ObjectHandle, Lockout, ESYS_TR_RH_LOCKOUT);
122    add_constant_handle!(ObjectHandle, Endorsement, ESYS_TR_RH_ENDORSEMENT);
123    add_constant_handle!(ObjectHandle, Platform, ESYS_TR_RH_PLATFORM);
124    add_constant_handle!(ObjectHandle, PlatformNv, ESYS_TR_RH_PLATFORM_NV);
125    add_constant_handle!(ObjectHandle, Null, ESYS_TR_RH_NULL);
126}
127
128/// Macro for creating ESYS_TR conversion for
129/// constant handle types
130macro_rules! impl_basic_multiple_constant_values_handle {
131    ($constant_handle_type:ident) => {
132        impl From<$constant_handle_type> for ESYS_TR {
133            fn from(constant_handle: $constant_handle_type) -> ESYS_TR {
134                // Cannot fail because each value is an ESYS_TR which is defined as u32.
135                constant_handle.to_u32().unwrap()
136            }
137        }
138
139        impl TryFrom<ESYS_TR> for $constant_handle_type {
140            type Error = Error;
141            fn try_from(tss_esys_handle: ESYS_TR) -> Result<$constant_handle_type> {
142                $constant_handle_type::from_u32(tss_esys_handle).ok_or_else(|| {
143                    error!(
144                        "failed to convert handle into {}",
145                        std::stringify!($constant_handle_type)
146                    );
147                    Error::local_error(WrapperErrorKind::InvalidParam)
148                })
149            }
150        }
151    };
152}
153
154/// Macro for creating handle conversion
155/// from constant handle to a 'non-restricted'
156/// handle type
157macro_rules! impl_multiple_constant_values_handle_conversion {
158    ($constant_handle_type:ident, $handle_type_other:ident) => {
159        impl From<$constant_handle_type> for $handle_type_other {
160            fn from(constant_handle: $constant_handle_type) -> $handle_type_other {
161                // Cannot fail because each value is an ESYS_TR which is defined as u32.
162                $handle_type_other::from(constant_handle.to_u32().unwrap())
163            }
164        }
165
166        impl TryFrom<$handle_type_other> for $constant_handle_type {
167            type Error = Error;
168            fn try_from(other_handle: $handle_type_other) -> Result<$constant_handle_type> {
169                $constant_handle_type::from_u32(other_handle.value()).ok_or_else(|| {
170                    error!(
171                        "failed to convert handle into {}",
172                        std::stringify!($constant_handle_type)
173                    );
174                    Error::local_error(WrapperErrorKind::InvalidParam)
175                })
176            }
177        }
178    };
179}
180
181/// PCR handle module
182///
183/// The specification:
184/// "TCG TSS 2.0 Enhanced System API (ESAPI) Specification, Version 1.00, Revision 08, May 28, 2020"
185/// specifies preallocated identifiers for PCRs
186/// the PcrHandle is a wrapper for those handles.
187pub mod pcr {
188    use super::object::ObjectHandle;
189    use crate::{
190        tss2_esys::{
191            ESYS_TR, ESYS_TR_PCR0, ESYS_TR_PCR1, ESYS_TR_PCR10, ESYS_TR_PCR11, ESYS_TR_PCR12,
192            ESYS_TR_PCR13, ESYS_TR_PCR14, ESYS_TR_PCR15, ESYS_TR_PCR16, ESYS_TR_PCR17,
193            ESYS_TR_PCR18, ESYS_TR_PCR19, ESYS_TR_PCR2, ESYS_TR_PCR20, ESYS_TR_PCR21,
194            ESYS_TR_PCR22, ESYS_TR_PCR23, ESYS_TR_PCR24, ESYS_TR_PCR25, ESYS_TR_PCR26,
195            ESYS_TR_PCR27, ESYS_TR_PCR28, ESYS_TR_PCR29, ESYS_TR_PCR3, ESYS_TR_PCR30,
196            ESYS_TR_PCR31, ESYS_TR_PCR4, ESYS_TR_PCR5, ESYS_TR_PCR6, ESYS_TR_PCR7, ESYS_TR_PCR8,
197            ESYS_TR_PCR9,
198        },
199        Error, Result, WrapperErrorKind,
200    };
201
202    use log::error;
203    use num_derive::{FromPrimitive, ToPrimitive};
204    use num_traits::{FromPrimitive, ToPrimitive};
205    use std::convert::{From, TryFrom};
206    /// PCR handle
207    ///
208    /// Handles to the pre-allocated
209    /// PCR meta data objects.
210    #[derive(FromPrimitive, ToPrimitive, Debug, Copy, Clone, PartialEq, Eq)]
211    #[repr(u32)]
212    pub enum PcrHandle {
213        Pcr0 = ESYS_TR_PCR0,
214        Pcr1 = ESYS_TR_PCR1,
215        Pcr2 = ESYS_TR_PCR2,
216        Pcr3 = ESYS_TR_PCR3,
217        Pcr4 = ESYS_TR_PCR4,
218        Pcr5 = ESYS_TR_PCR5,
219        Pcr6 = ESYS_TR_PCR6,
220        Pcr7 = ESYS_TR_PCR7,
221        Pcr8 = ESYS_TR_PCR8,
222        Pcr9 = ESYS_TR_PCR9,
223        Pcr10 = ESYS_TR_PCR10,
224        Pcr11 = ESYS_TR_PCR11,
225        Pcr12 = ESYS_TR_PCR12,
226        Pcr13 = ESYS_TR_PCR13,
227        Pcr14 = ESYS_TR_PCR14,
228        Pcr15 = ESYS_TR_PCR15,
229        Pcr16 = ESYS_TR_PCR16,
230        Pcr17 = ESYS_TR_PCR17,
231        Pcr18 = ESYS_TR_PCR18,
232        Pcr19 = ESYS_TR_PCR19,
233        Pcr20 = ESYS_TR_PCR20,
234        Pcr21 = ESYS_TR_PCR21,
235        Pcr22 = ESYS_TR_PCR22,
236        Pcr23 = ESYS_TR_PCR23,
237        Pcr24 = ESYS_TR_PCR24,
238        Pcr25 = ESYS_TR_PCR25,
239        Pcr26 = ESYS_TR_PCR26,
240        Pcr27 = ESYS_TR_PCR27,
241        Pcr28 = ESYS_TR_PCR28,
242        Pcr29 = ESYS_TR_PCR29,
243        Pcr30 = ESYS_TR_PCR30,
244        Pcr31 = ESYS_TR_PCR31,
245    }
246
247    impl_basic_multiple_constant_values_handle!(PcrHandle);
248    impl_multiple_constant_values_handle_conversion!(PcrHandle, ObjectHandle);
249}
250
251/// Macro for implementing conversion between handles.
252macro_rules! impl_handle_conversion {
253    ($handle_type_self:ident, $handle_type_other:ident) => {
254        impl From<$handle_type_self> for $handle_type_other {
255            fn from(handle_self: $handle_type_self) -> $handle_type_other {
256                $handle_type_other::from(ESYS_TR::from(handle_self.value))
257            }
258        }
259
260        impl From<$handle_type_other> for $handle_type_self {
261            fn from(handle_other: $handle_type_other) -> $handle_type_self {
262                $handle_type_self {
263                    value: handle_other.value(),
264                }
265            }
266        }
267    };
268}
269
270/// Auth handle module
271pub mod auth {
272    use super::object::ObjectHandle;
273    use crate::tss2_esys::{
274        ESYS_TR_RH_ENDORSEMENT, ESYS_TR_RH_LOCKOUT, ESYS_TR_RH_OWNER, ESYS_TR_RH_PLATFORM,
275    };
276    impl_basic_handle!(
277        /// Auth handle
278        ///
279        /// Represents an esys handle to resources
280        /// that can be used for authentication.
281        AuthHandle
282    );
283    impl_handle_conversion!(AuthHandle, ObjectHandle);
284    // The following constant handles can be used for authorization
285    // according to the TCG TPM2 r1p59 Structures specification.
286    add_constant_handle!(AuthHandle, Owner, ESYS_TR_RH_OWNER);
287    add_constant_handle!(AuthHandle, Lockout, ESYS_TR_RH_LOCKOUT);
288    add_constant_handle!(AuthHandle, Endorsement, ESYS_TR_RH_ENDORSEMENT);
289    add_constant_handle!(AuthHandle, Platform, ESYS_TR_RH_PLATFORM);
290    // TODO: Figure out how to add AUTH_00 to AUTH_FF range
291    // TODO: Figure out how to add ACT_0 to ACT_F range
292}
293
294/// NV Index handle module
295pub mod nv_index {
296    use super::auth::AuthHandle;
297    use super::object::ObjectHandle;
298    impl_basic_handle!(
299        /// NV Index Handle
300        ///
301        /// Represents an esys resource handle
302        /// for a nv index.
303        NvIndexHandle
304    );
305    impl_handle_conversion!(NvIndexHandle, ObjectHandle);
306    impl_handle_conversion!(NvIndexHandle, AuthHandle);
307}
308
309/// Key handle module
310pub mod key {
311    use super::object::ObjectHandle;
312    use crate::tss2_esys::ESYS_TR_RH_NULL;
313    impl_basic_handle!(
314        /// Key Handle
315        ///
316        /// Represents an esys resource handle
317        /// for a key.
318        KeyHandle
319    );
320    impl_handle_conversion!(KeyHandle, ObjectHandle);
321    add_constant_handle!(KeyHandle, Null, ESYS_TR_RH_NULL);
322}
323
324/// Session handle module
325pub mod session {
326    use super::auth::AuthHandle;
327    use super::object::ObjectHandle;
328    use crate::tss2_esys::ESYS_TR_PASSWORD;
329    impl_basic_handle!(
330        /// Session Handle
331        ///
332        /// Represents an esys handle used for
333        /// referencing session resources.
334        SessionHandle
335    );
336
337    // TSS ESAPI v1p0_r08 specifies that both
338    // PASSWORD and NONE can be used as session handles
339    // NONE are used when session handle is optional.
340
341    // Add the none handle
342    add_constant_none_handle!(SessionHandle);
343    // Add all other constant handles
344    add_constant_handle!(SessionHandle, Password, ESYS_TR_PASSWORD);
345
346    impl_handle_conversion!(SessionHandle, ObjectHandle);
347    impl_handle_conversion!(SessionHandle, AuthHandle);
348}