tss-esapi-7.4.0/.cargo_vcs_info.json0000644000000001470000000000100127560ustar { "git": { "sha1": "7c68948b3264c051a16c3a04af505f9d662999bf" }, "path_in_vcs": "tss-esapi" }tss-esapi-7.4.0/Cargo.toml0000644000000033650000000000100107610ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "tss-esapi" version = "7.4.0" authors = ["Parsec Project Contributors"] description = "Rust-native wrapper around TSS 2.0 Enhanced System API" documentation = "https://docs.rs/crate/tss-esapi" readme = "README.md" keywords = [ "tpm", "tss", "esys", "esapi", ] categories = [ "api-bindings", "external-ffi-bindings", "cryptography", ] license = "Apache-2.0" repository = "https://github.com/parallaxsecond/rust-tss-esapi" [dependencies.bitfield] version = "0.14.0" [dependencies.enumflags2] version = "0.7.1" [dependencies.hostname-validator] version = "1.1.0" [dependencies.log] version = "0.4.11" [dependencies.mbox] version = "0.6.0" [dependencies.num-derive] version = "0.4.0" [dependencies.num-traits] version = "0.2.12" [dependencies.oid] version = "0.2.1" [dependencies.picky-asn1] version = "0.8.0" [dependencies.picky-asn1-x509] version = "0.12.0" [dependencies.regex] version = "1.3.9" [dependencies.serde] version = "1.0.115" features = ["derive"] [dependencies.tss-esapi-sys] version = "0.5.0" [dependencies.zeroize] version = "1.1.0" features = ["zeroize_derive"] [dev-dependencies.env_logger] version = "0.10.0" [dev-dependencies.sha2] version = "0.10.1" [features] generate-bindings = ["tss-esapi-sys/generate-bindings"] tss-esapi-7.4.0/Cargo.toml.orig000064400000000000000000000017431046102023000144400ustar 00000000000000[package] name = "tss-esapi" version = "7.4.0" authors = ["Parsec Project Contributors"] edition = "2018" description = "Rust-native wrapper around TSS 2.0 Enhanced System API" readme = "README.md" keywords = ["tpm", "tss", "esys", "esapi"] categories = ["api-bindings", "external-ffi-bindings", "cryptography"] license = "Apache-2.0" repository = "https://github.com/parallaxsecond/rust-tss-esapi" documentation = "https://docs.rs/crate/tss-esapi" [dependencies] bitfield = "0.14.0" serde = { version = "1.0.115", features = ["derive"] } mbox = "0.6.0" log = "0.4.11" enumflags2 = "0.7.1" num-derive = "0.4.0" num-traits = "0.2.12" hostname-validator = "1.1.0" regex = "1.3.9" zeroize = { version = "1.1.0", features = ["zeroize_derive"] } tss-esapi-sys = { path = "../tss-esapi-sys", version = "0.5.0" } oid = "0.2.1" picky-asn1 = "0.8.0" picky-asn1-x509 = "0.12.0" [dev-dependencies] env_logger = "0.10.0" sha2 = "0.10.1" [features] generate-bindings = ["tss-esapi-sys/generate-bindings"] tss-esapi-7.4.0/LICENSE000064400000000000000000000261361046102023000125610ustar 00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] 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 http://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. tss-esapi-7.4.0/README.md000064400000000000000000000025631046102023000130310ustar 00000000000000# TPM2 Software Stack Rust Wrapper

Crates.io Code documentation

This is the high-level, Rust idiomatic wrapper crate that exposes an interface to [TSS](https://github.com/tpm2-software/tpm2-tss). This crate depends on the [`tss-esapi-sys`](../tss-esapi-sys/) crate for its FFI interface. By default, pre-generated bindings are used. If you'd like the bindings to be generated at build time, please enable either the `generate-bindings` feature - the FFI bindings will then be generated at build time using the headers identified on the system. Our end-goal is to achieve a fully Rust-native interface that offers strong safety and security guarantees. Check out our [documentation](https://docs.rs/tss-esapi/*/tss_esapi/#notes-on-code-safety) for an overview of our code safety approach. ## Cross compiling For more information on cross-compiling the `tss-esapi` crate, please see the README of the `tss-esapi-sys` crate. *Copyright 2021 Contributors to the Parsec project.* tss-esapi-7.4.0/build.rs000064400000000000000000000010321046102023000132050ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 fn main() { if let Ok(tss2_esys_version) = std::env::var("DEP_TSS2_ESYS_VERSION") { match tss2_esys_version.chars().next().unwrap() { '2' => println!("cargo:rustc-cfg=tpm2_tss_version=\"2\""), '3' => println!("cargo:rustc-cfg=tpm2_tss_version=\"3\""), '4' => println!("cargo:rustc-cfg=tpm2_tss_version=\"4\""), major => panic!("Unsupported TSS version: {}", major), } } } tss-esapi-7.4.0/src/abstraction/ak.rs000064400000000000000000000165571046102023000156230ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ abstraction::{cipher::Cipher, IntoKeyCustomization, KeyCustomization}, attributes::{ObjectAttributesBuilder, SessionAttributesBuilder}, constants::{AlgorithmIdentifier, SessionType}, handles::{AuthHandle, KeyHandle, SessionHandle}, interface_types::{ algorithm::{ AsymmetricAlgorithm, EccSchemeAlgorithm, HashingAlgorithm, PublicAlgorithm, RsaSchemeAlgorithm, SignatureSchemeAlgorithm, }, ecc::EccCurve, key_bits::RsaKeyBits, session_handles::PolicySession, }, structures::{ Auth, CreateKeyResult, EccScheme, KeyDerivationFunctionScheme, Private, Public, PublicBuilder, PublicEccParametersBuilder, PublicKeyRsa, PublicRsaParametersBuilder, RsaExponent, RsaScheme, SymmetricDefinitionObject, }, Context, Error, Result, WrapperErrorKind, }; use log::error; use std::convert::{TryFrom, TryInto}; fn create_ak_public( key_alg: AsymmetricAlgorithm, hash_alg: HashingAlgorithm, sign_alg: SignatureSchemeAlgorithm, key_customization: IKC, ) -> Result { let key_customization = key_customization.into_key_customization(); let obj_attrs_builder = ObjectAttributesBuilder::new() .with_restricted(true) .with_user_with_auth(true) .with_sign_encrypt(true) .with_decrypt(false) .with_fixed_tpm(true) .with_fixed_parent(true) .with_sensitive_data_origin(true); let obj_attrs = if let Some(ref k) = key_customization { k.attributes(obj_attrs_builder) } else { obj_attrs_builder } .build()?; let key_builder = match key_alg { AsymmetricAlgorithm::Rsa => PublicBuilder::new() .with_public_algorithm(PublicAlgorithm::Rsa) .with_name_hashing_algorithm(hash_alg) .with_object_attributes(obj_attrs) .with_rsa_parameters( PublicRsaParametersBuilder::new() .with_scheme(RsaScheme::create( RsaSchemeAlgorithm::try_from(AlgorithmIdentifier::from(sign_alg))?, Some(hash_alg), )?) .with_key_bits(RsaKeyBits::Rsa2048) .with_exponent(RsaExponent::default()) .with_is_signing_key(obj_attrs.sign_encrypt()) .with_is_decryption_key(obj_attrs.decrypt()) .with_restricted(obj_attrs.restricted()) .build()?, ) .with_rsa_unique_identifier(PublicKeyRsa::default()), AsymmetricAlgorithm::Ecc => PublicBuilder::new() .with_public_algorithm(PublicAlgorithm::Ecc) .with_name_hashing_algorithm(hash_alg) .with_object_attributes(obj_attrs) .with_ecc_parameters( PublicEccParametersBuilder::new() .with_symmetric(SymmetricDefinitionObject::Null) .with_ecc_scheme(EccScheme::create( EccSchemeAlgorithm::try_from(AlgorithmIdentifier::from(sign_alg))?, Some(hash_alg), Some(0), )?) .with_curve(EccCurve::NistP192) .with_key_derivation_function_scheme(KeyDerivationFunctionScheme::Null) .build()?, ), AsymmetricAlgorithm::Null => { // TODO: Figure out what to with Null. return Err(Error::local_error(WrapperErrorKind::UnsupportedParam)); } }; let key_builder = if let Some(ref k) = key_customization { k.template(key_builder) } else { key_builder }; key_builder.build() } /// This loads an Attestation Key previously generated under the Endorsement hierarchy pub fn load_ak( context: &mut Context, parent: KeyHandle, ak_auth_value: Option, private: Private, public: Public, ) -> Result { let policy_auth_session = context .start_auth_session( None, None, None, SessionType::Policy, Cipher::aes_128_cfb().try_into()?, HashingAlgorithm::Sha256, )? .ok_or_else(|| Error::local_error(WrapperErrorKind::WrongValueFromTpm))?; let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new() .with_decrypt(true) .with_encrypt(true) .build(); context.tr_sess_set_attributes( policy_auth_session, session_attributes, session_attributes_mask, )?; let key_handle = context.execute_with_temporary_object( SessionHandle::from(policy_auth_session).into(), |ctx, _| { let _ = ctx.execute_with_nullauth_session(|ctx| { ctx.policy_secret( PolicySession::try_from(policy_auth_session)?, AuthHandle::Endorsement, Default::default(), Default::default(), Default::default(), None, ) })?; ctx.execute_with_session(Some(policy_auth_session), |ctx| { ctx.load(parent, private, public) }) }, )?; if let Some(ak_auth_value) = ak_auth_value { context.tr_set_auth(key_handle.into(), ak_auth_value)?; } Ok(key_handle) } /// This creates an Attestation Key in the Endorsement hierarchy pub fn create_ak( context: &mut Context, parent: KeyHandle, hash_alg: HashingAlgorithm, sign_alg: SignatureSchemeAlgorithm, ak_auth_value: Option, key_customization: IKC, ) -> Result { let key_alg = AsymmetricAlgorithm::try_from(sign_alg).map_err(|e| { // sign_alg is either HMAC or Null. error!("Could not retrieve asymmetric algorithm for provided signature scheme"); e })?; let ak_pub = create_ak_public(key_alg, hash_alg, sign_alg, key_customization)?; let policy_auth_session = context .start_auth_session( None, None, None, SessionType::Policy, Cipher::aes_128_cfb().try_into()?, HashingAlgorithm::Sha256, )? .ok_or_else(|| Error::local_error(WrapperErrorKind::WrongValueFromTpm))?; let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new() .with_decrypt(true) .with_encrypt(true) .build(); context.tr_sess_set_attributes( policy_auth_session, session_attributes, session_attributes_mask, )?; context.execute_with_temporary_object( SessionHandle::from(policy_auth_session).into(), |ctx, _| { let _ = ctx.execute_with_nullauth_session(|ctx| { ctx.policy_secret( PolicySession::try_from(policy_auth_session)?, AuthHandle::Endorsement, Default::default(), Default::default(), Default::default(), None, ) })?; ctx.execute_with_session(Some(policy_auth_session), |ctx| { ctx.create(parent, ak_pub, ak_auth_value, None, None, None) }) }, ) } tss-esapi-7.4.0/src/abstraction/cipher.rs000064400000000000000000000203631046102023000164700ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ constants::AlgorithmIdentifier, interface_types::{ algorithm::{HashingAlgorithm, SymmetricAlgorithm, SymmetricMode, SymmetricObject}, key_bits::{AesKeyBits, CamelliaKeyBits, Sm4KeyBits}, }, structures::{SymmetricCipherParameters, SymmetricDefinition, SymmetricDefinitionObject}, Error, Result, WrapperErrorKind, }; use std::convert::{TryFrom, TryInto}; /// Block cipher identifiers /// /// Structure useful for handling an abstract representation of ciphers. Ciphers are /// defined foremost through their symmetric algorithm and, depending on the type of that /// algorithm, on a set of other values. #[derive(Copy, Clone, Debug)] pub struct Cipher { algorithm: SymmetricAlgorithm, mode: Option, key_bits: Option, hash: Option, } impl Cipher { /// Constructor for AES cipher identifier /// /// `key_bits` must be one of 128, 192 or 256. pub fn aes(mode: SymmetricMode, key_bits: u16) -> Result { match key_bits { 128 | 192 | 256 => (), _ => return Err(Error::local_error(WrapperErrorKind::InvalidParam)), } Ok(Cipher { algorithm: SymmetricAlgorithm::Aes, mode: Some(mode), key_bits: Some(key_bits), hash: None, }) } /// Constructor for Camellia cipher identifier /// /// `key_bits` must be one of 128, 192 or 256. pub fn camellia(mode: SymmetricMode, key_bits: u16) -> Result { match key_bits { 128 | 192 | 256 => (), _ => return Err(Error::local_error(WrapperErrorKind::InvalidParam)), } Ok(Cipher { algorithm: SymmetricAlgorithm::Camellia, mode: Some(mode), key_bits: Some(key_bits), hash: None, }) } /// Constructor for Triple DES cipher identifier /// /// `key_bits` must be one of 56, 112 or 168. pub fn tdes(mode: SymmetricMode, key_bits: u16) -> Result { match key_bits { 56 | 112 | 168 => (), _ => return Err(Error::local_error(WrapperErrorKind::InvalidParam)), } Ok(Cipher { algorithm: SymmetricAlgorithm::Tdes, mode: Some(mode), key_bits: Some(key_bits), hash: None, }) } /// Constructor for SM4 cipher identifier pub fn sm4(mode: SymmetricMode) -> Self { Cipher { algorithm: SymmetricAlgorithm::Sm4, mode: Some(mode), key_bits: Some(128), hash: None, } } /// Constructor for XOR "cipher" identifier pub fn xor(hash: HashingAlgorithm) -> Self { Cipher { algorithm: SymmetricAlgorithm::Xor, mode: None, key_bits: None, hash: Some(hash), } } /// Get general object type for symmetric ciphers. pub fn object_type() -> AlgorithmIdentifier { AlgorithmIdentifier::SymCipher } /// Get the cipher key length. pub fn key_bits(self) -> Option { self.key_bits } /// Get the cipher mode. pub fn mode(self) -> Option { self.mode } /// Get the hash algorithm used with an XOR cipher pub fn hash(self) -> Option { self.hash } /// Get the symmetrical algorithm for the cipher. pub fn algorithm(&self) -> SymmetricAlgorithm { self.algorithm } /// Constructor for 128 bit AES in CFB mode. pub fn aes_128_cfb() -> Self { Cipher { algorithm: SymmetricAlgorithm::Aes, mode: Some(SymmetricMode::Cfb), key_bits: Some(128), hash: None, } } /// Constructor for 256 bit AES in CFB mode. pub fn aes_256_cfb() -> Self { Cipher { algorithm: SymmetricAlgorithm::Aes, mode: Some(SymmetricMode::Cfb), key_bits: Some(256), hash: None, } } } impl TryFrom for SymmetricDefinition { type Error = Error; fn try_from(cipher: Cipher) -> Result { match cipher.algorithm { SymmetricAlgorithm::Aes => Ok(SymmetricDefinition::Aes { key_bits: cipher .key_bits .ok_or_else(|| Error::local_error(WrapperErrorKind::ParamsMissing)) .and_then(AesKeyBits::try_from)?, mode: cipher .mode .ok_or_else(|| Error::local_error(WrapperErrorKind::ParamsMissing))?, }), SymmetricAlgorithm::Sm4 => Ok(SymmetricDefinition::Sm4 { key_bits: cipher .key_bits .ok_or_else(|| Error::local_error(WrapperErrorKind::ParamsMissing)) .and_then(Sm4KeyBits::try_from)?, mode: cipher .mode .ok_or_else(|| Error::local_error(WrapperErrorKind::ParamsMissing))?, }), SymmetricAlgorithm::Camellia => Ok(SymmetricDefinition::Camellia { key_bits: cipher .key_bits .ok_or_else(|| Error::local_error(WrapperErrorKind::ParamsMissing)) .and_then(CamelliaKeyBits::try_from)?, mode: cipher .mode .ok_or_else(|| Error::local_error(WrapperErrorKind::ParamsMissing))?, }), SymmetricAlgorithm::Xor => Ok(SymmetricDefinition::Xor { hashing_algorithm: cipher .hash .ok_or_else(|| Error::local_error(WrapperErrorKind::ParamsMissing)) .and_then(|ha| { if ha != HashingAlgorithm::Null { Ok(ha) } else { Err(Error::local_error(WrapperErrorKind::InvalidParam)) } })?, }), SymmetricAlgorithm::Null => Ok(SymmetricDefinition::Null), SymmetricAlgorithm::Tdes => { // TODO: Investigate Err(Error::local_error(WrapperErrorKind::UnsupportedParam)) } } } } impl TryFrom for SymmetricDefinitionObject { type Error = Error; fn try_from(cipher: Cipher) -> Result { match SymmetricObject::try_from(AlgorithmIdentifier::from(cipher.algorithm))? { SymmetricObject::Aes => Ok(SymmetricDefinitionObject::Aes { key_bits: cipher .key_bits .ok_or_else(|| Error::local_error(WrapperErrorKind::ParamsMissing)) .and_then(AesKeyBits::try_from)?, mode: cipher .mode .ok_or_else(|| Error::local_error(WrapperErrorKind::ParamsMissing))?, }), SymmetricObject::Sm4 => Ok(SymmetricDefinitionObject::Sm4 { key_bits: cipher .key_bits .ok_or_else(|| Error::local_error(WrapperErrorKind::ParamsMissing)) .and_then(Sm4KeyBits::try_from)?, mode: cipher .mode .ok_or_else(|| Error::local_error(WrapperErrorKind::ParamsMissing))?, }), SymmetricObject::Camellia => Ok(SymmetricDefinitionObject::Camellia { key_bits: cipher .key_bits .ok_or_else(|| Error::local_error(WrapperErrorKind::ParamsMissing)) .and_then(CamelliaKeyBits::try_from)?, mode: cipher .mode .ok_or_else(|| Error::local_error(WrapperErrorKind::ParamsMissing))?, }), SymmetricObject::Null => Ok(SymmetricDefinitionObject::Null), SymmetricObject::Tdes => { // TODO investigate Err(Error::local_error(WrapperErrorKind::UnsupportedParam)) } } } } impl TryFrom for SymmetricCipherParameters { type Error = Error; fn try_from(cipher: Cipher) -> Result { Ok(SymmetricCipherParameters::new(cipher.try_into()?)) } } tss-esapi-7.4.0/src/abstraction/ek.rs000064400000000000000000000145401046102023000156150ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ abstraction::{nv, IntoKeyCustomization, KeyCustomization}, attributes::ObjectAttributesBuilder, handles::{KeyHandle, NvIndexTpmHandle, TpmHandle}, interface_types::{ algorithm::{AsymmetricAlgorithm, HashingAlgorithm, PublicAlgorithm}, ecc::EccCurve, key_bits::RsaKeyBits, resource_handles::{Hierarchy, NvAuth}, }, structures::{ Digest, EccParameter, EccPoint, EccScheme, KeyDerivationFunctionScheme, Public, PublicBuilder, PublicEccParametersBuilder, PublicKeyRsa, PublicRsaParametersBuilder, RsaExponent, RsaScheme, SymmetricDefinitionObject, }, Context, Error, Result, WrapperErrorKind, }; use std::convert::TryFrom; // Source: TCG EK Credential Profile for TPM Family 2.0; Level 0 Version 2.3 Revision 2 // Section 2.2.1.4 (Low Range) for Windows compatibility const RSA_2048_EK_CERTIFICATE_NV_INDEX: u32 = 0x01c00002; const ECC_P256_EK_CERTIFICATE_NV_INDEX: u32 = 0x01c0000a; /// Get the [`Public`] representing a default Endorsement Key /// /// Source: TCG EK Credential Profile for TPM Family 2.0; Level 0 Version 2.3 Revision 2 /// Appendix B.3.3 and B.3.4 pub fn create_ek_public_from_default_template( alg: AsymmetricAlgorithm, key_customization: IKC, ) -> Result { let key_customization = key_customization.into_key_customization(); let obj_attrs_builder = ObjectAttributesBuilder::new() .with_fixed_tpm(true) .with_st_clear(false) .with_fixed_parent(true) .with_sensitive_data_origin(true) .with_user_with_auth(false) .with_admin_with_policy(true) .with_no_da(false) .with_encrypted_duplication(false) .with_restricted(true) .with_decrypt(true) .with_sign_encrypt(false); let obj_attrs = if let Some(ref k) = key_customization { k.attributes(obj_attrs_builder) } else { obj_attrs_builder } .build()?; // TPM2_PolicySecret(TPM_RH_ENDORSEMENT) // With 32 null-bytes attached, because of the type of with_auth_policy let authpolicy: [u8; 64] = [ 0x83, 0x71, 0x97, 0x67, 0x44, 0x84, 0xb3, 0xf8, 0x1a, 0x90, 0xcc, 0x8d, 0x46, 0xa5, 0xd7, 0x24, 0xfd, 0x52, 0xd7, 0x6e, 0x06, 0x52, 0x0b, 0x64, 0xf2, 0xa1, 0xda, 0x1b, 0x33, 0x14, 0x69, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]; let key_builder = match alg { AsymmetricAlgorithm::Rsa => PublicBuilder::new() .with_public_algorithm(PublicAlgorithm::Rsa) .with_name_hashing_algorithm(HashingAlgorithm::Sha256) .with_object_attributes(obj_attrs) .with_auth_policy(Digest::try_from(authpolicy[0..32].to_vec())?) .with_rsa_parameters( PublicRsaParametersBuilder::new() .with_symmetric(SymmetricDefinitionObject::AES_128_CFB) .with_scheme(RsaScheme::Null) .with_key_bits(RsaKeyBits::Rsa2048) .with_exponent(RsaExponent::default()) .with_is_signing_key(obj_attrs.sign_encrypt()) .with_is_decryption_key(obj_attrs.decrypt()) .with_restricted(obj_attrs.decrypt()) .build()?, ) .with_rsa_unique_identifier(PublicKeyRsa::new_empty_with_size(RsaKeyBits::Rsa2048)), AsymmetricAlgorithm::Ecc => PublicBuilder::new() .with_public_algorithm(PublicAlgorithm::Ecc) .with_name_hashing_algorithm(HashingAlgorithm::Sha256) .with_object_attributes(obj_attrs) .with_auth_policy(Digest::try_from(authpolicy[0..32].to_vec())?) .with_ecc_parameters( PublicEccParametersBuilder::new() .with_symmetric(SymmetricDefinitionObject::AES_128_CFB) .with_ecc_scheme(EccScheme::Null) .with_curve(EccCurve::NistP256) .with_key_derivation_function_scheme(KeyDerivationFunctionScheme::Null) .with_is_signing_key(obj_attrs.sign_encrypt()) .with_is_decryption_key(obj_attrs.decrypt()) .with_restricted(obj_attrs.decrypt()) .build()?, ) .with_ecc_unique_identifier(EccPoint::new( EccParameter::try_from(vec![0u8; 32])?, EccParameter::try_from(vec![0u8; 32])?, )), AsymmetricAlgorithm::Null => { // TDOD: Figure out what to with Null. return Err(Error::local_error(WrapperErrorKind::UnsupportedParam)); } }; let key_builder = if let Some(ref k) = key_customization { k.template(key_builder) } else { key_builder }; key_builder.build() } /// Create the Endorsement Key object from the specification templates pub fn create_ek_object( context: &mut Context, alg: AsymmetricAlgorithm, key_customization: IKC, ) -> Result { let ek_public = create_ek_public_from_default_template(alg, key_customization)?; Ok(context .execute_with_nullauth_session(|ctx| { ctx.create_primary(Hierarchy::Endorsement, ek_public, None, None, None, None) })? .key_handle) } /// Retrieve the Endorsement Key public certificate from the TPM pub fn retrieve_ek_pubcert(context: &mut Context, alg: AsymmetricAlgorithm) -> Result> { let nv_idx = match alg { AsymmetricAlgorithm::Rsa => RSA_2048_EK_CERTIFICATE_NV_INDEX, AsymmetricAlgorithm::Ecc => ECC_P256_EK_CERTIFICATE_NV_INDEX, AsymmetricAlgorithm::Null => { // TDOD: Figure out what to with Null. return Err(Error::local_error(WrapperErrorKind::UnsupportedParam)); } }; let nv_idx = NvIndexTpmHandle::new(nv_idx).unwrap(); let nv_auth_handle = TpmHandle::NvIndex(nv_idx); let nv_auth_handle = context.execute_without_session(|ctx| { ctx.tr_from_tpm_public(nv_auth_handle) .map(|v| NvAuth::NvIndex(v.into())) })?; context.execute_with_nullauth_session(|ctx| nv::read_full(ctx, nv_auth_handle, nv_idx)) } tss-esapi-7.4.0/src/abstraction/mod.rs000064400000000000000000000030131046102023000157660ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 pub mod ak; pub mod cipher; pub mod ek; pub mod nv; pub mod pcr; pub mod public; pub mod transient; use crate::{attributes::ObjectAttributesBuilder, structures::PublicBuilder}; /// KeyCustomizaion allows to adjust how a key is going to be created pub trait KeyCustomization { /// Alter the attributes used on key creation fn attributes(&self, attributes_builder: ObjectAttributesBuilder) -> ObjectAttributesBuilder { attributes_builder } /// Alter the key template used on key creation fn template(&self, template_builder: PublicBuilder) -> PublicBuilder { template_builder } } /// IntoKeyCustomization transforms a type into a type that support KeyCustomization pub trait IntoKeyCustomization { type T: KeyCustomization; fn into_key_customization(self) -> Option; } impl IntoKeyCustomization for T { type T = T; fn into_key_customization(self) -> Option { Some(self) } } #[derive(Debug, Copy, Clone)] pub struct DefaultKey; #[derive(Debug, Copy, Clone)] pub struct DefaultKeyImpl; impl KeyCustomization for DefaultKeyImpl {} impl IntoKeyCustomization for DefaultKey { type T = DefaultKeyImpl; fn into_key_customization(self) -> Option { None } } impl IntoKeyCustomization for Option { type T = DefaultKeyImpl; fn into_key_customization(self) -> Option { None } } tss-esapi-7.4.0/src/abstraction/nv.rs000064400000000000000000000215571046102023000156470ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::{ convert::{TryFrom, TryInto}, io::Read, }; use crate::{ constants::{tss::*, CapabilityType, PropertyTag}, handles::{AuthHandle, NvIndexHandle, NvIndexTpmHandle, TpmHandle}, interface_types::resource_handles::NvAuth, structures::{CapabilityData, MaxNvBuffer, Name, NvPublic}, Context, Error, Result, WrapperErrorKind, }; /// Allows reading an NV Index completely, regardless of the max TPM NV buffer size pub fn read_full( context: &mut Context, auth_handle: NvAuth, nv_index_handle: NvIndexTpmHandle, ) -> Result> { let mut rw = NvOpenOptions::ExistingIndex { auth_handle, nv_index_handle, } .open(context)?; let mut result = Vec::with_capacity(rw.size()); let _ = rw.read_to_end(&mut result).map_err(|e| { // Try to convert the error back into a tss-esapi::Error if it was one originally match e.into_inner() { None => Error::WrapperError(WrapperErrorKind::InvalidParam), Some(e) => match e.downcast::() { Ok(e) => *e, Err(_) => Error::WrapperError(WrapperErrorKind::InvalidParam), }, } })?; Ok(result) } /// Returns the NvPublic and Name associated with an NV index TPM handle /// /// NOTE: This call _may_ close existing ESYS handles to the NV Index. fn get_nv_index_info( context: &mut Context, nv_index_tpm_handle: NvIndexTpmHandle, ) -> Result<(NvPublic, Name)> { context .tr_from_tpm_public(nv_index_tpm_handle.into()) .and_then(|mut object_handle| { context .nv_read_public(NvIndexHandle::from(object_handle)) .map_err(|e| { let _ = context.tr_close(&mut object_handle); e }) .and_then(|(nv_public, name)| { context.tr_close(&mut object_handle)?; Ok((nv_public, name)) }) }) } /// Lists all the currently defined NV Indexes' names and public components /// /// NOTE: This call _may_ close existing ESYS handles to the existing NV Indexes. pub fn list(context: &mut Context) -> Result> { context.execute_without_session(|ctx| { ctx.get_capability( CapabilityType::Handles, TPM2_NV_INDEX_FIRST, TPM2_PT_NV_INDEX_MAX, ) .and_then(|(capability_data, _)| match capability_data { CapabilityData::Handles(tpm_handles) => Ok(tpm_handles), _ => Err(Error::local_error(WrapperErrorKind::WrongValueFromTpm)), }) .and_then(|tpm_handles| { tpm_handles .iter() .map(|&tpm_handle| get_nv_index_info(ctx, NvIndexTpmHandle::try_from(tpm_handle)?)) .collect() }) }) } /// Options and flags which can be used to determine how a non-volatile storage index is opened. #[non_exhaustive] #[derive(Debug, Clone)] pub enum NvOpenOptions { /// Define a new NV space with given auth NewIndex { nv_public: NvPublic, auth_handle: NvAuth, }, /// Open the NV space at the given handle, with the given auth ExistingIndex { nv_index_handle: NvIndexTpmHandle, auth_handle: NvAuth, }, } impl NvOpenOptions { /// Opens a non-volatile storage index using the options specified by `self` /// /// The non-volatile storage index may be used for reading or writing or both. pub fn open<'a>(&self, context: &'a mut Context) -> Result> { let buffer_size = max_nv_buffer_size(context)?; let (data_size, nv_idx, auth_handle) = match self { NvOpenOptions::ExistingIndex { nv_index_handle, auth_handle, } => { let nv_idx = TpmHandle::NvIndex(*nv_index_handle); let nv_idx = context .execute_without_session(|ctx| ctx.tr_from_tpm_public(nv_idx))? .into(); ( context .execute_without_session(|ctx| ctx.nv_read_public(nv_idx)) .map(|(nvpub, _)| nvpub.data_size())?, nv_idx, auth_handle, ) } NvOpenOptions::NewIndex { nv_public, auth_handle, } => ( nv_public.data_size(), context.nv_define_space( AuthHandle::from(*auth_handle).try_into()?, None, nv_public.clone(), )?, auth_handle, ), }; Ok(NvReaderWriter { context, auth_handle: *auth_handle, buffer_size, nv_idx, data_size, offset: 0, }) } } /// Get the maximum buffer size for an NV space. pub fn max_nv_buffer_size(ctx: &mut Context) -> Result { Ok(ctx .get_tpm_property(PropertyTag::NvBufferMax)? .map(usize::try_from) .transpose() .map_err(|_| { log::error!("Failed to obtain valid maximum NV buffer size"); Error::WrapperError(WrapperErrorKind::InternalError) })? .unwrap_or(MaxNvBuffer::MAX_SIZE)) } /// Non-volatile storage index reader/writer /// /// Provides methods and trait implementations to interact with a non-volatile storage index that has been opened. /// /// Use [`NvOpenOptions::open`] to obtain an [`NvReaderWriter`] object. /// /// NOTE: When the `NvReaderWriter` is dropped, any existing ESYS handles to NV Indexes _may_ be closed. #[derive(Debug)] pub struct NvReaderWriter<'a> { context: &'a mut Context, auth_handle: NvAuth, buffer_size: usize, nv_idx: NvIndexHandle, data_size: usize, offset: usize, } impl NvReaderWriter<'_> { /// The size of the data in the non-volatile storage index pub fn size(&self) -> usize { self.data_size } } impl Read for NvReaderWriter<'_> { fn read(&mut self, buf: &mut [u8]) -> std::io::Result { if self.data_size <= self.offset { return Ok(0); } let desired_size = std::cmp::min(buf.len(), self.data_size - self.offset); let size: u16 = std::cmp::min(self.buffer_size, desired_size) as u16; let res = self .context .nv_read(self.auth_handle, self.nv_idx, size, self.offset as u16) .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?; buf[0..size as usize].copy_from_slice(&res); self.offset += size as usize; Ok(size.into()) } } impl std::io::Write for NvReaderWriter<'_> { fn write(&mut self, buf: &[u8]) -> std::io::Result { if self.data_size < self.offset { return Ok(0); } let desired_size = std::cmp::min(buf.len(), self.data_size - self.offset); let size = std::cmp::min(self.buffer_size, desired_size) as u16; let data = buf[0..size.into()] .try_into() .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?; self.context .nv_write(self.auth_handle, self.nv_idx, data, self.offset as u16) .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?; self.offset += size as usize; Ok(size.into()) } fn flush(&mut self) -> std::io::Result<()> { // Data isn't buffered Ok(()) } } impl std::io::Seek for NvReaderWriter<'_> { fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result { let inv_input_err = |_| { std::io::Error::new( std::io::ErrorKind::InvalidInput, "invalid seek to a negative or overflowing position", ) }; let (base, offset) = match pos { std::io::SeekFrom::Start(offset) => { (usize::try_from(offset).map_err(inv_input_err)?, 0) } std::io::SeekFrom::End(offset) => (self.data_size, offset), std::io::SeekFrom::Current(offset) => (self.offset, offset), }; let new_offset = i64::try_from(base) .map_err(inv_input_err)? .checked_add(offset) .ok_or_else(|| { std::io::Error::new( std::io::ErrorKind::InvalidInput, "invalid seek to a negative or overflowing position", ) })?; self.offset = new_offset.try_into().map_err(inv_input_err)?; self.offset.try_into().map_err(inv_input_err) } } impl Drop for NvReaderWriter<'_> { fn drop(&mut self) { let mut obj_handle = self.nv_idx.into(); let _ = self .context .execute_without_session(|ctx| ctx.tr_close(&mut obj_handle)); } } tss-esapi-7.4.0/src/abstraction/pcr/bank.rs000064400000000000000000000107221046102023000167130ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ structures::{Digest, PcrSlot}, Error, Result, WrapperErrorKind, }; use log::error; use std::collections::BTreeMap; /// Struct for holding PcrSlots and their /// corresponding values. #[derive(Debug, Clone, Eq, PartialEq)] pub struct PcrBank { bank: BTreeMap, } impl PcrBank { /// Function that creates PcrBank from a vector of pcr slots and /// a vector of pcr digests. /// /// # Details /// The order of pcr slots are assumed to match the order of the Digests. /// /// # Errors /// - If number of pcr slots does not match the number of pcr digests /// InconsistentParams error is returned. /// /// - If the vector of pcr slots contains duplicates then /// InconsistentParams error is returned. pub fn create(mut pcr_slots: Vec, mut digests: Vec) -> Result { if pcr_slots.len() != digests.len() { error!( "Number of PcrSlots does not match the number of PCR digests. ({} != {})", pcr_slots.len(), digests.len() ); return Err(Error::local_error(WrapperErrorKind::InconsistentParams)); } pcr_slots .drain(..) .zip(digests.drain(..)) .try_fold(BTreeMap::::new(), |mut data, (pcr_slot, digest)| { if data.insert(pcr_slot, digest).is_none() { Ok(data) } else { error!("Error trying to insert data into PcrSlot {:?} where data have already been inserted", pcr_slot); Err(Error::local_error(WrapperErrorKind::InconsistentParams)) } }) .map(|bank| PcrBank { bank }) } /// Retrieves reference to a [Digest] associated with the provided [PcrSlot]. /// /// # Details /// Returns a reference to a [Digest] associated with the provided [PcrSlot] /// if one exists else returns None. pub fn get_digest(&self, pcr_slot: PcrSlot) -> Option<&Digest> { self.bank.get(&pcr_slot) } /// Returns true if the [PcrBank] contains a digest /// for the provided [PcrSlot]. pub fn has_digest(&self, pcr_slot: PcrSlot) -> bool { self.bank.contains_key(&pcr_slot) } /// Number of digests in the [PcrBank] pub fn len(&self) -> usize { self.bank.len() } /// Returns true if the [PcrBank] is empty pub fn is_empty(&self) -> bool { self.bank.is_empty() } /// Removees the [Digest] associated with the [PcrSlot] and /// returns it. /// /// # Details /// Removes the [Digest] associated with the provided [PcrSlot] /// out of the bank and returns it if it exists else returns None. pub fn remove_digest(&mut self, pcr_slot: PcrSlot) -> Option { self.bank.remove(&pcr_slot) } /// Inserts [Digest] value associated with a [PcrSlot] into the bank. /// /// # Errors /// Returns an error if a [Digest] is already associated with the /// provided [PcrSlot]. pub fn insert_digest(&mut self, pcr_slot: PcrSlot, digest: Digest) -> Result<()> { self.ensure_non_existing(pcr_slot, "Failed to insert")?; let _ = self.bank.insert(pcr_slot, digest); Ok(()) } /// Attempts to extend the [PcrBank] with `other`. /// /// # Errors /// Returns an error if the a value in `other` already /// exists. pub fn try_extend(&mut self, other: PcrBank) -> Result<()> { other .bank .keys() .try_for_each(|&pcr_slot| self.ensure_non_existing(pcr_slot, "Failed to extend"))?; self.bank.extend(other.bank); Ok(()) } /// Returns an error if a [Digest] for [PcrSlot] already exists in the bank fn ensure_non_existing(&self, pcr_slot: PcrSlot, error_msg: &str) -> Result<()> { if self.has_digest(pcr_slot) { error!( "{}, a digest already for PcrSlot {:?} exists in the bank", error_msg, pcr_slot ); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } Ok(()) } } impl<'a> IntoIterator for &'a PcrBank { type Item = (&'a PcrSlot, &'a Digest); type IntoIter = ::std::collections::btree_map::Iter<'a, PcrSlot, Digest>; fn into_iter(self) -> Self::IntoIter { self.bank.iter() } } tss-esapi-7.4.0/src/abstraction/pcr/data.rs000064400000000000000000000106261046102023000167140ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ abstraction::pcr::PcrBank, interface_types::algorithm::HashingAlgorithm, structures::{Digest, DigestList, PcrSelectionList}, tss2_esys::TPML_DIGEST, Error, Result, WrapperErrorKind, }; use log::error; /// Struct holding pcr banks and their associated /// hashing algorithm #[derive(Debug, Clone, PartialEq, Eq)] pub struct PcrData { data: Vec<(HashingAlgorithm, PcrBank)>, } impl PcrData { /// Creates new empty PcrData pub const fn new() -> Self { PcrData { data: Vec::new() } } /// Function for creating PcrData from a pcr selection list and pcr digests list. pub fn create( pcr_selection_list: &PcrSelectionList, digest_list: &DigestList, ) -> Result { Ok(PcrData { data: Self::create_data(pcr_selection_list, digest_list.value().to_vec())?, }) } /// Adds data to the PcrData pub fn add( &mut self, pcr_selection_list: &PcrSelectionList, digest_list: &DigestList, ) -> Result<()> { Self::create_data(pcr_selection_list, digest_list.value().to_vec())? .drain(..) .try_for_each(|(hashing_algorithm, pcr_bank)| { if let Some(existing_pcr_bank) = self.pcr_bank_mut(hashing_algorithm) { existing_pcr_bank.try_extend(pcr_bank)?; } else { self.data.push((hashing_algorithm, pcr_bank)); } Ok(()) }) } /// Function for turning a pcr selection list and pcr digests values /// into the format in which data is stored in PcrData. fn create_data( pcr_selection_list: &PcrSelectionList, mut digests: Vec, ) -> Result> { pcr_selection_list .get_selections() .iter() .map(|pcr_selection| { let pcr_slots = pcr_selection.selected(); if pcr_slots.len() > digests.len() { error!("More pcr slots in selection then available digests"); return Err(Error::local_error(WrapperErrorKind::InconsistentParams)); } let digests_in_bank = digests.drain(..pcr_slots.len()).collect(); Ok(( pcr_selection.hashing_algorithm(), PcrBank::create(pcr_slots, digests_in_bank)?, )) }) .collect() } /// Function for retrieving the first PCR values associated with hashing_algorithm. pub fn pcr_bank(&self, hashing_algorithm: HashingAlgorithm) -> Option<&PcrBank> { self.data .iter() .find(|(alg, _)| *alg == hashing_algorithm) .map(|(_, bank)| bank) } /// Function for retrieving the number of banks in the data. pub fn len(&self) -> usize { self.data.len() } /// Returns true if there are no banks in the data. pub fn is_empty(&self) -> bool { self.data.is_empty() } /// Private method for finding a PCR bank. fn pcr_bank_mut(&mut self, hashing_algorithm: HashingAlgorithm) -> Option<&mut PcrBank> { self.data .iter_mut() .find(|(alg, _)| *alg == hashing_algorithm) .map(|(_, bank)| bank) } } impl IntoIterator for PcrData { type Item = (HashingAlgorithm, PcrBank); type IntoIter = ::std::vec::IntoIter<(HashingAlgorithm, PcrBank)>; fn into_iter(self) -> Self::IntoIter { self.data.into_iter() } } impl From for Vec { fn from(pcr_data: PcrData) -> Self { pcr_data .data .iter() .flat_map(|(_, pcr_bank)| pcr_bank.into_iter()) .map(|(_, digest)| digest) .collect::>() .chunks(DigestList::MAX_SIZE) .map(|digests| { let mut tpml_digest: TPML_DIGEST = Default::default(); for (index, digest) in digests.iter().enumerate() { tpml_digest.count += 1; tpml_digest.digests[index].size = digest.len() as u16; tpml_digest.digests[index].buffer[..digest.len()] .copy_from_slice(digest.value()); } tpml_digest }) .collect() } } tss-esapi-7.4.0/src/abstraction/pcr.rs000064400000000000000000000044031046102023000157770ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod bank; mod data; use crate::{structures::PcrSelectionList, Context, Result}; pub use bank::PcrBank; pub use data::PcrData; /// Function that reads all the PCRs in a selection list and returns /// the result as PCR data. /// /// # Example /// /// ```rust /// # use tss_esapi::{Context, TctiNameConf}; /// # // Create context /// # let mut context = /// # Context::new( /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"), /// # ).expect("Failed to create Context"); /// # /// use tss_esapi::{ /// interface_types::algorithm::HashingAlgorithm, /// structures::{PcrSelectionListBuilder, PcrSlot}, /// }; /// // Create PCR selection list with slots in a bank /// // that is going to be read. /// let pcr_selection_list = PcrSelectionListBuilder::new() /// .with_selection(HashingAlgorithm::Sha256, /// &[ /// PcrSlot::Slot0, /// PcrSlot::Slot1, /// PcrSlot::Slot2, /// PcrSlot::Slot3, /// PcrSlot::Slot4, /// PcrSlot::Slot5, /// PcrSlot::Slot6, /// PcrSlot::Slot7, /// PcrSlot::Slot8, /// PcrSlot::Slot9, /// PcrSlot::Slot10, /// PcrSlot::Slot11, /// PcrSlot::Slot12, /// PcrSlot::Slot13, /// PcrSlot::Slot14, /// PcrSlot::Slot15, /// PcrSlot::Slot16, /// PcrSlot::Slot17, /// PcrSlot::Slot18, /// PcrSlot::Slot19, /// PcrSlot::Slot20, /// PcrSlot::Slot21, /// ]) /// .build() /// .expect("Failed to build PcrSelectionList"); /// let _pcr_data = tss_esapi::abstraction::pcr::read_all(&mut context, pcr_selection_list) /// .expect("pcr::read_all failed"); /// ``` pub fn read_all( context: &mut Context, mut pcr_selection_list: PcrSelectionList, ) -> Result { let mut pcr_data = PcrData::new(); while !pcr_selection_list.is_empty() { let (_, pcrs_read, pcr_digests) = context.pcr_read(pcr_selection_list.clone())?; pcr_data.add(&pcrs_read, &pcr_digests)?; pcr_selection_list.subtract(&pcrs_read)?; } Ok(pcr_data) } tss-esapi-7.4.0/src/abstraction/public.rs000064400000000000000000000122751046102023000164770ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::interface_types::ecc::EccCurve; use crate::structures::{Public, RsaExponent}; use crate::{Error, WrapperErrorKind}; use core::convert::TryFrom; use oid::ObjectIdentifier; use picky_asn1::bit_string::BitString; use picky_asn1::wrapper::{IntegerAsn1, OctetStringAsn1}; use picky_asn1_x509::{ AlgorithmIdentifier, EcParameters, EcPoint, PublicKey, RsaPublicKey, SubjectPublicKeyInfo, }; use serde::{Deserialize, Serialize}; /// Can be converted from [`crate::structures::Public`] when not a fully constructed /// [`picky_asn1_x509::SubjectPublicKeyInfo`] is required. /// /// # Details /// /// Holds either [`picky_asn1_x509::RsaPublicKey`] for [`crate::structures::Public::Rsa`] or /// [`picky_asn1_x509::EcPoint`] for [`crate::structures::Public::Ecc`]. #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] pub enum DecodedKey { RsaPublicKey(RsaPublicKey), EcPoint(EcPoint), } impl TryFrom for DecodedKey { type Error = Error; fn try_from(value: Public) -> Result { public_to_decoded_key(&value) } } impl TryFrom for SubjectPublicKeyInfo { type Error = Error; /// Converts [`crate::structures::Public::Rsa`] and [`crate::structures::Public::Ecc`] to [`picky_asn1_x509::SubjectPublicKeyInfo`]. /// /// # Details /// The result can be used to convert TPM public keys to DER using `picky_asn1_der`. /// /// # Errors /// * if other instances of [`crate::structures::Public`] are used `UnsupportedParam` will be returned. fn try_from(value: Public) -> Result { let decoded_key = public_to_decoded_key(&value)?; match (value, decoded_key) { (Public::Rsa { .. }, DecodedKey::RsaPublicKey(key)) => Ok(SubjectPublicKeyInfo { algorithm: AlgorithmIdentifier::new_rsa_encryption(), subject_public_key: PublicKey::Rsa(key.into()), }), (Public::Ecc { parameters, .. }, DecodedKey::EcPoint(point)) => { Ok(SubjectPublicKeyInfo { algorithm: AlgorithmIdentifier::new_elliptic_curve(EcParameters::NamedCurve( curve_oid(parameters.ecc_curve())?.into(), )), subject_public_key: PublicKey::Ec(BitString::with_bytes(point).into()), }) } _ => Err(Error::local_error(WrapperErrorKind::UnsupportedParam)), } } } /// Converts [`crate::structures::Public::Rsa`] and [`crate::structures::Public::Ecc`] to [DecodedKey]. /// /// # Details /// Does basic key conversion to either RSA or ECC. In RSA conversion the TPM zero exponent is replaced with `65537`. /// /// # Errors /// * if other instances of [`crate::structures::Public`] are used `UnsupportedParam` will be returned. fn public_to_decoded_key(public: &Public) -> Result { match public { Public::Rsa { unique, parameters, .. } => { let exponent = match parameters.exponent() { RsaExponent::ZERO_EXPONENT => 65537, _ => parameters.exponent().value(), } .to_be_bytes(); Ok(DecodedKey::RsaPublicKey(RsaPublicKey { modulus: IntegerAsn1::from_bytes_be_unsigned(unique.value().to_vec()), public_exponent: IntegerAsn1::from_bytes_be_signed(exponent.to_vec()), })) } Public::Ecc { unique, .. } => { let x = unique.x().value().to_vec(); let y = unique.y().value().to_vec(); Ok(DecodedKey::EcPoint(OctetStringAsn1( elliptic_curve_point_to_octet_string(x, y), ))) } _ => Err(Error::local_error(WrapperErrorKind::UnsupportedParam)), } } // Taken from https://github.com/parallaxsecond/parsec/blob/561235f3cc37bcff3d9a6cb29c84eeae5d55100b/src/providers/tpm/utils.rs#L319 // Points on elliptic curves are represented as defined in section 2.3.3 of https://www.secg.org/sec1-v2.pdf // The (uncompressed) representation is [ 0x04 || x || y ] where x and y are the coordinates of the point fn elliptic_curve_point_to_octet_string(mut x: Vec, mut y: Vec) -> Vec { let mut octet_string = vec![0x04]; octet_string.append(&mut x); octet_string.append(&mut y); octet_string } // Map TPM supported ECC curves to their respective OIDs fn curve_oid(ecc_curve: EccCurve) -> Result { match ecc_curve { EccCurve::NistP192 => Ok(picky_asn1_x509::oids::secp192r1()), EccCurve::NistP224 => Ok(picky_asn1_x509::oids::secp256r1()), EccCurve::NistP256 => Ok(picky_asn1_x509::oids::secp256r1()), EccCurve::NistP384 => Ok(picky_asn1_x509::oids::secp384r1()), EccCurve::NistP521 => Ok(picky_asn1_x509::oids::secp521r1()), // Barreto-Naehrig curves seem to not have any OIDs EccCurve::BnP256 => Err(Error::local_error(WrapperErrorKind::UnsupportedParam)), EccCurve::BnP638 => Err(Error::local_error(WrapperErrorKind::UnsupportedParam)), EccCurve::Sm2P256 => Ok(ObjectIdentifier::try_from("1.2.156.10197.1.301").unwrap()), } } tss-esapi-7.4.0/src/abstraction/transient/key_attestation.rs000064400000000000000000000164341046102023000224400ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::{ObjectWrapper, TransientKeyContext}; use crate::{ abstraction::ek, constants::SessionType, handles::{AuthHandle, KeyHandle, SessionHandle}, interface_types::{ algorithm::{AsymmetricAlgorithm, HashingAlgorithm}, session_handles::{AuthSession, PolicySession}, }, structures::{EncryptedSecret, IdObject, SymmetricDefinition}, traits::Marshall, utils::PublicKey, Result, }; use std::convert::TryFrom; #[derive(Debug)] /// Wrapper for the parameters needed by MakeCredential /// /// The 3rd party requesting proof that the key is indeed backed /// by a TPM would perform a MakeCredential and would thus require /// `name` and `attesting_key_pub` as inputs for that operation. /// /// `public` is not strictly needed, however it is returned as a /// convenience block of data. Since the MakeCredential operation /// bakes into the encrypted credential the identity of the key to /// be attested via its `name`, the correctness of the `name` must /// be verifiable by the said 3rd party. `public` bridges this gap: /// /// * it includes all the public parameters of the attested key /// * can be hashed (in its marshaled form) with the name hash /// (found by unmarshaling it) to obtain `name` pub struct MakeCredParams { /// TPM name of the object being attested pub name: Vec, /// Encoding of the public parameters of the object whose name /// will be included in the credential computations pub public: Vec, /// Public part of the key used to protect the credential pub attesting_key_pub: PublicKey, } impl TransientKeyContext { /// Get the data required to perform a MakeCredential /// /// # Parameters /// /// * `object` - the object whose TPM name will be included in /// the credential /// * `key` - the key to be used to encrypt the secret that wraps /// the credential /// /// **Note**: If no `key` is given, the default Endorsement Key /// will be used. pub fn get_make_cred_params( &mut self, object: ObjectWrapper, key: Option, ) -> Result { let object_handle = self.load_key(object.params, object.material, None)?; let (object_public, object_name, _) = self.context.read_public(object_handle).or_else(|e| { self.context.flush_context(object_handle.into())?; Err(e) })?; self.context.flush_context(object_handle.into())?; // Name of objects is derived from their publicArea, i.e. the marshaled TPMT_PUBLIC let public = object_public.marshall()?; let attesting_key_pub = match key { None => get_ek_object_public(&mut self.context)?, Some(key) => key.material.public, }; Ok(MakeCredParams { name: object_name.value().to_vec(), public, attesting_key_pub, }) } /// Perform an ActivateCredential operation for the given object /// /// # Parameters /// /// * `object` - the object whose TPM name is included in the credential /// * `key` - the key used to encrypt the secret that wraps the credential /// * `credential_blob` - encrypted credential that will be returned by the /// TPM /// * `secret` - encrypted secret that was used to encrypt the credential /// /// **Note**: if no `key` is given, the default Endorsement Key /// will be used. You can find more information about the default Endorsement /// Key in the [ek] module. pub fn activate_credential( &mut self, object: ObjectWrapper, key: Option, credential_blob: Vec, secret: Vec, ) -> Result> { let credential_blob = IdObject::try_from(credential_blob)?; let secret = EncryptedSecret::try_from(secret)?; let object_handle = self.load_key(object.params, object.material, object.auth)?; let (key_handle, session_2) = match key { Some(key) => self.prepare_key_activate_cred(key), None => self.prepare_ek_activate_cred(), } .or_else(|e| { self.context.flush_context(object_handle.into())?; Err(e) })?; let (session_1, _, _) = self.context.sessions(); let credential = self .context .execute_with_sessions((session_1, session_2, None), |ctx| { ctx.activate_credential(object_handle, key_handle, credential_blob, secret) }) .or_else(|e| { self.context.flush_context(object_handle.into())?; self.context.flush_context(key_handle.into())?; self.context .flush_context(SessionHandle::from(session_2).into())?; Err(e) })?; self.context.flush_context(object_handle.into())?; self.context.flush_context(key_handle.into())?; self.context .flush_context(SessionHandle::from(session_2).into())?; Ok(credential.value().to_vec()) } // No key was given, use the EK. This requires using a Policy session fn prepare_ek_activate_cred(&mut self) -> Result<(KeyHandle, Option)> { let session = self.context.start_auth_session( None, None, None, SessionType::Policy, SymmetricDefinition::AES_128_CFB, HashingAlgorithm::Sha256, )?; let _ = self.context.policy_secret( PolicySession::try_from(session.unwrap()) .expect("Failed to convert auth session to policy session"), AuthHandle::Endorsement, Default::default(), Default::default(), Default::default(), None, ); Ok(( ek::create_ek_object(&mut self.context, AsymmetricAlgorithm::Rsa, None).or_else( |e| { self.context .flush_context(SessionHandle::from(session).into())?; Err(e) }, )?, session, )) } // Load key and create a HMAC session for it fn prepare_key_activate_cred( &mut self, key: ObjectWrapper, ) -> Result<(KeyHandle, Option)> { let session = self.context.start_auth_session( None, None, None, SessionType::Hmac, SymmetricDefinition::AES_128_CFB, HashingAlgorithm::Sha256, )?; Ok(( self.load_key(key.params, key.material, key.auth) .or_else(|e| { self.context .flush_context(SessionHandle::from(session).into())?; Err(e) })?, session, )) } } fn get_ek_object_public(context: &mut crate::Context) -> Result { let key_handle = ek::create_ek_object(context, AsymmetricAlgorithm::Rsa, None)?; let (attesting_key_pub, _, _) = context.read_public(key_handle).or_else(|e| { context.flush_context(key_handle.into())?; Err(e) })?; context.flush_context(key_handle.into())?; PublicKey::try_from(attesting_key_pub) } tss-esapi-7.4.0/src/abstraction/transient/mod.rs000064400000000000000000000641141046102023000200060ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! Module for abstracting resource handle management //! //! This module presents an abstraction over the TPM functionality exposed through the core //! `Context` structure. The abstraction works by hiding resource handle management from the //! client. use crate::{ attributes::{ObjectAttributesBuilder, SessionAttributesBuilder}, constants::{tss::*, SessionType, Tss2ResponseCodeKind}, handles::{KeyHandle, SessionHandle}, interface_types::{ algorithm::{HashingAlgorithm, PublicAlgorithm}, ecc::EccCurve, key_bits::RsaKeyBits, resource_handles::Hierarchy, }, structures::{ Auth, CreateKeyResult, Data, Digest, EccPoint, EccScheme, Public, PublicBuilder, PublicEccParametersBuilder, PublicKeyRsa, PublicRsaParametersBuilder, RsaExponent, RsaScheme, Signature, SignatureScheme, SymmetricDefinitionObject, VerifiedTicket, }, tcti_ldr::TctiNameConf, tss2_esys::*, utils::{create_restricted_decryption_rsa_public, PublicKey, TpmsContext}, Context, Error, Result, WrapperErrorKind as ErrorKind, }; use log::error; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::convert::{AsMut, AsRef, TryFrom, TryInto}; use zeroize::Zeroize; mod key_attestation; pub use key_attestation::MakeCredParams; /// Parameters for the kinds of keys supported by the context #[derive(Debug, Clone, Copy)] pub enum KeyParams { Rsa { /// Size of key in bits /// /// Can only be one of: 1024, 2048, 3072 or 4096 size: RsaKeyBits, /// Asymmetric scheme to be used with the key scheme: RsaScheme, /// Public exponent of the key /// /// If set to 0, it will default to 2^16 - 1. /// /// (Note that the default value for [`RsaExponent`] is 0) pub_exponent: RsaExponent, }, Ecc { /// Curve that the key will be based on curve: EccCurve, /// Asymmetric scheme to be used with the key scheme: EccScheme, }, } /// Structure representing a key created or stored in the TPM /// /// The `public` field represents the public part of the key in plain text, /// while `private` is the encrypted version of the private key. /// /// For information on public key formats, see the documentation of [`PublicKey`]. /// The private part of the key should be treated as an opaque binary blob. /// /// # Warning /// /// If the Owner hierarchy is cleared, any key material generated /// prior to that event will become unusable. #[derive(Debug, Serialize, Deserialize, Clone, Zeroize)] pub struct KeyMaterial { public: PublicKey, private: Vec, } impl KeyMaterial { /// Get a reference to the public part of the key pub fn public(&self) -> &PublicKey { &self.public } /// Get a reference to the private part of the key pub fn private(&self) -> &[u8] { &self.private } } /// Structure containing all the defining elements of a TPM key /// /// - `material` identifies the numeric value of the key object /// - `params` identifies the algorithm to use on the key and other relevant /// parameters /// - `auth` identifies the optional authentication value to be used with the /// key #[derive(Debug, Clone)] pub struct ObjectWrapper { pub material: KeyMaterial, pub params: KeyParams, pub auth: Option, } /// Structure offering an abstracted programming experience. /// /// The `TransientKeyContext` makes use of a root key from which the other, client-controlled /// keys are derived. /// /// This abstraction makes public key cryptography more accessible, focusing on asymmetric /// encryption and signatures in particular, by allowing users to offload object and session management. #[allow(clippy::module_name_repetitions)] #[derive(Debug)] pub struct TransientKeyContext { context: Context, root_key_handle: KeyHandle, } impl TransientKeyContext { /// Create a new key. /// /// A key is created as a descendant of the context root key, with the given parameters. /// /// If successful, the result contains the [KeyMaterial] of the key and a vector of /// bytes forming the authentication value for said key. /// /// The following key attributes are always **set**: `fixed_tpm`, `fixed_parent`, `sensitive_data_origin`, /// `user_with_auth`. The `restricted` attribute is **not set**. See section 8.3 in the Structures /// spec for a detailed description of these attributes. /// /// # Constraints /// * `auth_size` must be at most 32 /// /// # Errors /// * if the authentication size is larger than 32 a `WrongParamSize` wrapper error is returned pub fn create_key( &mut self, key_params: KeyParams, auth_size: usize, ) -> Result<(KeyMaterial, Option)> { if auth_size > 32 { return Err(Error::local_error(ErrorKind::WrongParamSize)); } let key_auth = if auth_size > 0 { self.set_session_attrs()?; let random_bytes = self.context.get_random(auth_size)?; Some(Auth::try_from(random_bytes.value().to_vec())?) } else { None }; self.set_session_attrs()?; let CreateKeyResult { out_private, out_public, .. } = self.context.create( self.root_key_handle, TransientKeyContext::get_public_from_params(key_params, None)?, key_auth.clone(), None, None, None, )?; let key_material = KeyMaterial { public: out_public.try_into()?, private: out_private.value().to_vec(), }; Ok((key_material, key_auth)) } /// Load the public part of a key. /// /// Returns the appropriate key material after verifying that the key can be loaded. pub fn load_external_public_key( &mut self, public_key: PublicKey, params: KeyParams, ) -> Result { let public = TransientKeyContext::get_public_from_params(params, Some(public_key.clone()))?; self.set_session_attrs()?; let key_handle = self .context .load_external_public(public, Hierarchy::Owner)?; self.context.flush_context(key_handle.into())?; Ok(KeyMaterial { public: public_key, private: vec![], }) } /// Encrypt a message with an existing key. /// /// Takes the key as a set of parameters (`key_material`, `key_params`, `key_auth`), encrypts the message /// and returns the ciphertext. A label can also be provided which will be associated with the ciphertext. /// /// Note: the data passed as `label` MUST end in a `0x00` byte. pub fn rsa_encrypt( &mut self, key_material: KeyMaterial, key_params: KeyParams, key_auth: Option, message: PublicKeyRsa, label: Option, ) -> Result { let key_handle = self.load_key(key_params, key_material, key_auth)?; let decrypt_scheme = if let KeyParams::Rsa { scheme, .. } = key_params { scheme.try_into()? } else { return Err(Error::local_error(ErrorKind::InvalidParam)); }; self.set_session_attrs()?; let ciphertext = self .context .rsa_encrypt( key_handle, message, decrypt_scheme, label.unwrap_or_default(), ) .or_else(|e| { self.context.flush_context(key_handle.into())?; Err(e) })?; self.context.flush_context(key_handle.into())?; Ok(ciphertext) } /// Decrypt ciphertext with an existing key. /// /// Takes the key as a set of parameters (`key_material`, `key_params`, `key_auth`), decrypts the ciphertext /// and returns the plaintext. A label which was associated with the ciphertext can also be provided. /// /// Note: the data passed as `label` MUST end in a `0x00` byte. pub fn rsa_decrypt( &mut self, key_material: KeyMaterial, key_params: KeyParams, key_auth: Option, ciphertext: PublicKeyRsa, label: Option, ) -> Result { let key_handle = self.load_key(key_params, key_material, key_auth)?; let decrypt_scheme = if let KeyParams::Rsa { scheme, .. } = key_params { scheme.try_into()? } else { return Err(Error::local_error(ErrorKind::InvalidParam)); }; self.set_session_attrs()?; let plaintext = self .context .rsa_decrypt( key_handle, ciphertext, decrypt_scheme, label.unwrap_or_default(), ) .or_else(|e| { self.context.flush_context(key_handle.into())?; Err(e) })?; self.context.flush_context(key_handle.into())?; Ok(plaintext) } /// Sign a digest with an existing key. /// /// Takes the key as a set of parameters (`key_material`, `key_params`, `key_auth`), signs and returns the signature. pub fn sign( &mut self, key_material: KeyMaterial, key_params: KeyParams, key_auth: Option, digest: Digest, ) -> Result { let key_handle = self.load_key(key_params, key_material, key_auth)?; let validation = TPMT_TK_HASHCHECK { tag: TPM2_ST_HASHCHECK, hierarchy: TPM2_RH_NULL, digest: Default::default(), }; self.set_session_attrs()?; let signature = self .context .sign( key_handle, digest, SignatureScheme::Null, validation.try_into()?, ) .or_else(|e| { self.context.flush_context(key_handle.into())?; Err(e) })?; self.context.flush_context(key_handle.into())?; Ok(signature) } /// Verify a signature against a digest. /// /// Given a digest, a key and a signature, this method returns a `Verified` ticket if the /// verification was successful. /// /// # Errors /// * if the verification fails (i.e. the signature is invalid), a TPM error is returned pub fn verify_signature( &mut self, key_material: KeyMaterial, key_params: KeyParams, digest: Digest, signature: Signature, ) -> Result { let key_handle = self.load_key(key_params, key_material, None)?; self.set_session_attrs()?; let verified = self .context .verify_signature(key_handle, digest, signature) .or_else(|e| { self.context.flush_context(key_handle.into())?; Err(e) })?; self.context.flush_context(key_handle.into())?; Ok(verified) } /// Perform a migration from the previous version of the TransientKeyContext. /// /// The original version of the TransientKeyContext used contexts of keys for /// persistence. This method allows a key persisted in this way to be migrated /// to the new format. /// /// The method determines on its own whether the loaded key was a keypair or /// just a public key. pub fn migrate_key_from_ctx( &mut self, context: TpmsContext, auth: Option, ) -> Result { self.set_session_attrs()?; let key_handle = self.context.context_load(context).map(KeyHandle::from)?; if let Some(key_auth_value) = auth.clone() { self.context .tr_set_auth(key_handle.into(), key_auth_value) .or_else(|e| { self.context.flush_context(key_handle.into())?; Err(e) })?; } let (public, _, _) = self.context.read_public(key_handle).or_else(|e| { self.context.flush_context(key_handle.into())?; Err(e) })?; let private = self .context .object_change_auth( key_handle.into(), self.root_key_handle.into(), auth.unwrap_or_default(), ) .or_else(|e| { if let Error::Tss2Error(resp_code) = e { // If we get `AuthUnavailable` it means the private part of the key has not been // loaded, and this is thus a public key if resp_code.kind() == Some(Tss2ResponseCodeKind::AuthUnavailable) { return Ok(Default::default()); } } error!("Getting private part of key failed."); self.context.flush_context(key_handle.into())?; Err(e) })?; let key_material = KeyMaterial { public: public.try_into()?, private: private.value().to_vec(), }; self.context.flush_context(key_handle.into())?; Ok(key_material) } /// Sets the encrypt and decrypt flags on the main session used by the context. /// /// # Errors /// * if `Context::set_session_attr` returns an error, that error is propagated through fn set_session_attrs(&mut self) -> Result<()> { if let (Some(session), _, _) = self.context.sessions() { let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new() .with_decrypt(true) .with_encrypt(true) .build(); self.context.tr_sess_set_attributes( session, session_attributes, session_attributes_mask, )?; } Ok(()) } /// Given the parameters for an asymmetric key, return its [Public] structure /// /// The public part of the key can optionally be inserted in the structure. /// /// # Errors /// * if the public key and the parameters don't match, `InconsistentParams` is returned fn get_public_from_params(params: KeyParams, pub_key: Option) -> Result { let decrypt_flag = matches!( params, KeyParams::Rsa { scheme: RsaScheme::RsaEs, .. } | KeyParams::Rsa { scheme: RsaScheme::Oaep(..), .. } ); let object_attributes = ObjectAttributesBuilder::new() .with_fixed_tpm(true) .with_fixed_parent(true) .with_sensitive_data_origin(true) .with_user_with_auth(true) .with_decrypt(decrypt_flag) .with_sign_encrypt(true) .with_restricted(false) .build()?; let mut pub_builder = PublicBuilder::new() .with_public_algorithm(match params { KeyParams::Ecc { .. } => PublicAlgorithm::Ecc, KeyParams::Rsa { .. } => PublicAlgorithm::Rsa, }) .with_name_hashing_algorithm(HashingAlgorithm::Sha256) .with_object_attributes(object_attributes); match params { KeyParams::Rsa { size, scheme, pub_exponent, } => { let unique = pub_key .map(|pub_key| { if let PublicKey::Rsa(val) = pub_key { PublicKeyRsa::try_from(val) } else { Err(Error::local_error(ErrorKind::InconsistentParams)) } }) .transpose()? .unwrap_or_default(); pub_builder = pub_builder .with_rsa_parameters( PublicRsaParametersBuilder::new() .with_scheme(match scheme { RsaScheme::RsaSsa { .. } | RsaScheme::RsaPss { .. } => scheme, _ => RsaScheme::Null, }) .with_key_bits(size) .with_exponent(pub_exponent) .with_is_signing_key(true) .with_is_decryption_key(decrypt_flag) .with_restricted(false) .build()?, ) .with_rsa_unique_identifier(unique); } KeyParams::Ecc { scheme, curve } => { let unique = pub_key .map(|pub_key| { if let PublicKey::Ecc { x, y } = pub_key { Ok(EccPoint::new(x.try_into()?, y.try_into()?)) } else { Err(Error::local_error(ErrorKind::InconsistentParams)) } }) .transpose()? .unwrap_or_default(); pub_builder = pub_builder .with_ecc_parameters( PublicEccParametersBuilder::new_unrestricted_signing_key(scheme, curve) .build()?, ) .with_ecc_unique_identifier(unique); } } pub_builder.build() } /// Load a key into a TPM given its [KeyMaterial] /// /// If the key has only a public part, it is loaded accordingly in the Owner Hierarchy fn load_key( &mut self, params: KeyParams, material: KeyMaterial, auth: Option, ) -> Result { let public = TransientKeyContext::get_public_from_params(params, Some(material.public))?; self.set_session_attrs()?; let key_handle = if material.private.is_empty() { self.context .load_external_public(public, Hierarchy::Owner)? } else { self.context .load(self.root_key_handle, material.private.try_into()?, public) .map(KeyHandle::from)? }; let key_auth_value = auth.unwrap_or_default(); if !key_auth_value.is_empty() { self.context .tr_set_auth(key_handle.into(), key_auth_value) .or_else(|e| { self.context.flush_context(key_handle.into())?; Err(e) })?; } Ok(key_handle) } /// Get a builder for the structure pub fn builder() -> TransientKeyContextBuilder { TransientKeyContextBuilder::new() } } impl AsRef for TransientKeyContext { fn as_ref(&self) -> &Context { &self.context } } impl AsMut for TransientKeyContext { fn as_mut(&mut self) -> &mut Context { &mut self.context } } /// Build a new `TransientKeyContext`. /// /// # Default values /// * TCTI: Device TCTI /// * Hierarchy: Owner hierarchy /// * Root key size: 2048 bits /// * Root key authentication size: 32 bytes /// * Hierarchy authentication value: Empty array of bytes /// * Session encryption cipher: 256 bit AES in CFB mode /// * Session hash algorithm: SHA256 #[derive(Debug)] pub struct TransientKeyContextBuilder { tcti_name_conf: TctiNameConf, root_key_size: u16, // TODO: replace with root key PUBLIC definition root_key_auth_size: usize, root_hierarchy: Hierarchy, hierarchy_auth: HashMap>, default_context_cipher: SymmetricDefinitionObject, session_hash_alg: HashingAlgorithm, } impl TransientKeyContextBuilder { /// Create a new builder. pub fn new() -> Self { TransientKeyContextBuilder { tcti_name_conf: TctiNameConf::Device(Default::default()), root_hierarchy: Hierarchy::Owner, root_key_size: 2048, root_key_auth_size: 32, hierarchy_auth: HashMap::new(), default_context_cipher: SymmetricDefinitionObject::AES_256_CFB, session_hash_alg: HashingAlgorithm::Sha256, } } /// Define the TCTI name configuration to be used by the client. pub fn with_tcti(mut self, tcti_name_conf: TctiNameConf) -> Self { self.tcti_name_conf = tcti_name_conf; self } /// Set the auth values for any hierarchies that will be used pub fn with_hierarchy_auth(mut self, hierarchy: Hierarchy, auth: Vec) -> Self { let _ = self.hierarchy_auth.insert(hierarchy, auth); self } /// Define which hierarchy will be used for the keys being managed. pub fn with_root_hierarchy(mut self, hierarchy: Hierarchy) -> Self { self.root_hierarchy = hierarchy; self } /// Choose length in bits of primary key that will serve as parent to all user keys. pub fn with_root_key_size(mut self, root_key_size: u16) -> Self { self.root_key_size = root_key_size; self } /// Choose authentication value length (in bytes) for primary key. pub fn with_root_key_auth_size(mut self, root_key_auth_size: usize) -> Self { self.root_key_auth_size = root_key_auth_size; self } /// Define the cipher to be used within this context as a default. /// /// Currently this default is used for: /// * securing command parameters using session-based encryption /// * encrypting all user keys using the primary key pub fn with_default_context_cipher( mut self, default_context_cipher: SymmetricDefinitionObject, ) -> Self { self.default_context_cipher = default_context_cipher; self } /// Define the cipher to be used by sessions for hashing commands. pub fn with_session_hash_alg(mut self, session_hash_alg: HashingAlgorithm) -> Self { self.session_hash_alg = session_hash_alg; self } /// Bootstrap the TransientKeyContext. /// /// The root key is created as a primary key in the provided hierarchy and thus authentication is /// needed for said hierarchy. The authentication valuei for the key is generated by the TPM itself, /// with a configurable length, and never exposed outside the context. /// /// # Warning /// It is the responsibility of the client to ensure that the context can be initialized /// safely, threading-wise by choosing the correct TCTI. See the Warning notice of the Context /// structure for more information. /// /// # Constraints /// * `root_key_size` must be 1024, 2048, 3072 or 4096 /// * `root_key_auth_size` must be at most 32 /// /// # Errors /// * errors are returned if any method calls return an error: `Context::get_random`, /// `Context::start_auth_session`, `Context::create_primary`, `Context::flush_context`, /// `Context::set_handle_auth` /// * if the root key authentication size is given greater than 32 or if the root key size is /// not 1024, 2048, 3072 or 4096, a `InvalidParam` wrapper error is returned pub fn build(mut self) -> Result { if self.root_key_auth_size > 32 { return Err(Error::local_error(ErrorKind::WrongParamSize)); } let root_key_rsa_key_bits = RsaKeyBits::try_from(self.root_key_size)?; let mut context = Context::new(self.tcti_name_conf)?; let root_key_auth = if self.root_key_auth_size > 0 { let random = context.get_random(self.root_key_auth_size)?; Some(Auth::try_from(random.value().to_vec())?) } else { None }; for (hierarchy, auth) in self.hierarchy_auth.drain() { let auth_hierarchy = Auth::try_from(auth)?; context.tr_set_auth(hierarchy.into(), auth_hierarchy)?; } let session = context .start_auth_session( None, None, None, SessionType::Hmac, self.default_context_cipher.into(), self.session_hash_alg, ) .and_then(|session| { session.ok_or_else(|| { error!("Received unexpected NONE handle from the TPM"); Error::local_error(ErrorKind::WrongValueFromTpm) }) })?; let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new() .with_decrypt(true) .with_encrypt(true) .build(); context.tr_sess_set_attributes(session, session_attributes, session_attributes_mask)?; context.set_sessions((Some(session), None, None)); let root_key_handle = context .create_primary( self.root_hierarchy, create_restricted_decryption_rsa_public( self.default_context_cipher, root_key_rsa_key_bits, RsaExponent::ZERO_EXPONENT, )?, root_key_auth, None, None, None, )? .key_handle; let new_session_cipher = self.default_context_cipher; let new_session_hashing_algorithm = self.session_hash_alg; let new_session = context.execute_without_session(|ctx| { ctx.start_auth_session( Some(root_key_handle), None, None, SessionType::Hmac, new_session_cipher.into(), new_session_hashing_algorithm, ) .and_then(|session| { session.ok_or_else(|| { error!("Received unexpected NONE handle from the TPM"); Error::local_error(ErrorKind::WrongValueFromTpm) }) }) })?; if let (Some(old_session), _, _) = context.sessions() { context.set_sessions((Some(new_session), None, None)); context.flush_context(SessionHandle::from(old_session).into())?; } Ok(TransientKeyContext { context, root_key_handle, }) } } impl Default for TransientKeyContextBuilder { fn default() -> Self { TransientKeyContextBuilder::new() } } tss-esapi-7.4.0/src/attributes/algorithm.rs000064400000000000000000000015351046102023000170610ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::tss2_esys::TPMA_ALGORITHM; use bitfield::bitfield; bitfield! { /// Bitfield representing the algorithm attributes. #[derive(Copy, Clone, Eq, PartialEq)] pub struct AlgorithmAttributes(TPMA_ALGORITHM); impl Debug; pub asymmetric, _: 0; pub symmetric, _: 1; pub hash, _: 2; pub object, _: 3; // 7:4 Reserved pub signing, _: 8; pub encrypting, _: 9; pub method, _: 10; // 31:11 Reserved } impl From for AlgorithmAttributes { fn from(tpma_algorithm: TPMA_ALGORITHM) -> Self { AlgorithmAttributes(tpma_algorithm) } } impl From for TPMA_ALGORITHM { fn from(algorithm_attributes: AlgorithmAttributes) -> Self { algorithm_attributes.0 } } tss-esapi-7.4.0/src/attributes/command_code.rs000064400000000000000000000106621046102023000175040ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ constants::CommandCode, tss2_esys::{TPM2_CC, TPMA_CC}, Error, Result, WrapperErrorKind, }; use bitfield::bitfield; use log::error; use std::convert::{TryFrom, TryInto}; bitfield! { /// Bitfield representing the command code attributes. /// /// # Details /// This corresponds to TPMA_CC. #[derive(Copy, Clone, Eq, PartialEq)] pub struct CommandCodeAttributes(TPMA_CC); impl Debug; pub u16, command_index, _: 15, 0; u16, _, set_command_index: 15, 0; u8, reserved, set_reserved: 21, 16; // shall be zero pub nv, _: 22; _, set_nv: 22; pub extensive, _: 23; _, set_extensive: 23; pub flushed, _: 24; _, set_flushed: 24; pub u8, c_handles, _: 27, 25; u8, _, set_c_handles: 27, 25; pub r_handle, _: 28; _, set_r_handle: 28; pub is_vendor_specific, _: 29; _, set_vendor_specific: 29; res, set_res: 31, 30; // shall be zero } impl CommandCodeAttributes { /// Returns a command code attributes builder pub const fn builder() -> CommandCodeAttributesBuilder { CommandCodeAttributesBuilder::new() } } impl TryFrom for CommandCodeAttributes { type Error = Error; fn try_from(tpma_cc: TPMA_CC) -> Result { let command_code_attributes = CommandCodeAttributes(tpma_cc); if command_code_attributes.reserved() != 0 || command_code_attributes.res() != 0 { error!( "Command code attributes from the TPM contained a non zero value in a resrved area" ); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } if !command_code_attributes.is_vendor_specific() { // Non vendor specific command code attributes needs to // have a command index that corresponds to a command code. let tpm_command_code: TPM2_CC = command_code_attributes.command_index().into(); let _ = CommandCode::try_from(tpm_command_code)?; } Ok(command_code_attributes) } } impl From for TPMA_CC { fn from(command_code_attributes: CommandCodeAttributes) -> Self { command_code_attributes.0 } } /// A builder for [CommandCodeAttributes] #[derive(Copy, Clone, Eq, PartialEq, Debug)] pub struct CommandCodeAttributesBuilder { command_code_attributes: CommandCodeAttributes, } impl CommandCodeAttributesBuilder { /// Creates a new command code attributes builder. pub const fn new() -> Self { CommandCodeAttributesBuilder { command_code_attributes: CommandCodeAttributes(0), } } /// Sets the command code to the specified value /// in the builder. pub fn with_command_index(mut self, command_index: u16) -> Self { self.command_code_attributes .set_command_index(command_index); self } /// Sets the 'nv' bit in the builder. pub fn with_nv(mut self, set: bool) -> Self { self.command_code_attributes.set_nv(set); self } /// Sets the 'extensive' bit in the builder. pub fn with_extensive(mut self, set: bool) -> Self { self.command_code_attributes.set_extensive(set); self } /// Sets the 'flushed' bit in the builder. pub fn with_flushed(mut self, set: bool) -> Self { self.command_code_attributes.set_flushed(set); self } /// Sets the three 'c_handles' bits in the builder. /// /// # Details /// All bits besides the three first in the provided /// argument will be ignored. pub fn with_c_handles(mut self, value: u8) -> Self { self.command_code_attributes.set_c_handles(value); self } /// Sets the 'r_handle' bit in the builder. pub fn with_r_handle(mut self, set: bool) -> Self { self.command_code_attributes.set_r_handle(set); self } /// Sets the 'V'(i.e. vendor specific) bit in the builder. pub fn with_vendor_specific(mut self, set: bool) -> Self { self.command_code_attributes.set_vendor_specific(set); self } /// Builds the command code attributes /// /// # Errors /// Returns an error if command index is not /// a command index associated with a CommandCode /// specified in the TPM specification. pub fn build(self) -> Result { self.command_code_attributes.0.try_into() } } tss-esapi-7.4.0/src/attributes/locality.rs000064400000000000000000000107041046102023000167110ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{tss2_esys::TPMA_LOCALITY, Error, Result, WrapperErrorKind}; use bitfield::bitfield; use log::error; bitfield! { /// Bitfield representing the locality attributes. #[derive(Copy, Clone, Eq, PartialEq)] pub struct LocalityAttributes(TPMA_LOCALITY); impl Debug; _, set_locality_zero: 0; pub locality_zero, _: 0; _, set_locality_one: 1; pub locality_one, _: 1; _, set_locality_two: 2; pub locality_two, _: 2; _, set_locality_three: 3; pub locality_three, _: 3; _, set_locality_four: 4; pub locality_four, _: 4; _, set_extended: 7, 5; extended, _: 7, 5; } impl LocalityAttributes { pub const LOCALITY_ZERO: LocalityAttributes = LocalityAttributes(1); pub const LOCALITY_ONE: LocalityAttributes = LocalityAttributes(2); pub const LOCALITY_TWO: LocalityAttributes = LocalityAttributes(4); pub const LOCALITY_THREE: LocalityAttributes = LocalityAttributes(8); pub const LOCALITY_FOUR: LocalityAttributes = LocalityAttributes(16); /// Returns true if the attributes are extended pub fn is_extended(&self) -> bool { self.extended() != 0u8 } /// Returns the LocalityAttributes as a number. /// /// # Errors /// If the attributes are not extended en InvalidParams error /// is returned. pub fn as_extended(&self) -> Result { if self.is_extended() { Ok(self.0) } else { error!("Cannot retrieve LocalityAttributes as extended when the attributes are not indicated to be extended"); Err(Error::local_error(WrapperErrorKind::InvalidParam)) } } /// Returns the builder used to construct LocalAttributes. pub const fn builder() -> LocalityAttributesBuilder { LocalityAttributesBuilder::new() } } impl From for LocalityAttributes { fn from(tpma_locality: TPMA_LOCALITY) -> Self { LocalityAttributes(tpma_locality) } } impl From for TPMA_LOCALITY { fn from(locality_attributes: LocalityAttributes) -> Self { locality_attributes.0 } } #[derive(Debug, Clone)] pub struct LocalityAttributesBuilder { localities: Vec, } impl LocalityAttributesBuilder { /// Creates a new builder. pub const fn new() -> Self { LocalityAttributesBuilder { localities: Vec::new(), } } /// Adds a locality to the builder pub fn with_locality(mut self, locality: u8) -> Self { self.localities.push(locality); self } /// Adds a slice of localities to the builder pub fn with_localities(mut self, localities: &[u8]) -> Self { self.localities.extend_from_slice(localities); self } /// Builds the attributes pub fn build(self) -> Result { let mut locality_attributes = LocalityAttributes(0); for locality in self.localities { if locality_attributes.is_extended() { error!("Locality attribute {new} and locality attribute {prev} cannot be combined because locality attribute {prev} is extended", new=locality, prev=locality_attributes.0); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } match locality { 0 => locality_attributes.set_locality_zero(true), 1 => locality_attributes.set_locality_one(true), 2 => locality_attributes.set_locality_two(true), 3 => locality_attributes.set_locality_three(true), 4 => locality_attributes.set_locality_four(true), 5..=31 => { error!( "Locality attribute {new} is invalid and cannot be combined with other locality attributes", new=locality ); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } 32..=255 => { if locality_attributes.0 != 0 { error!("Locality attribute {new} is extended and cannot be combined with locality attribute(s) {old}", new=locality, old=locality_attributes.0); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } locality_attributes.0 = locality; } } } Ok(locality_attributes) } } tss-esapi-7.4.0/src/attributes/mod.rs000064400000000000000000000015711046102023000156520ustar 00000000000000//! Module for representation of attributes /// Representation of the attributes defined in the /// Attribute structures -> TPMA_OBJECT section of /// the specification pub mod object; /// Representation of the attributes defined in the /// Attribute structures -> TPMA_OBJECT section of /// the specification. pub mod session; /// Representation of the attributes defined in the /// NV Storage -> TPMA_NV section of /// the specification. pub mod nv_index; pub mod locality; pub mod algorithm; pub mod command_code; pub use algorithm::AlgorithmAttributes; pub use command_code::CommandCodeAttributes; pub use locality::{LocalityAttributes, LocalityAttributesBuilder}; pub use nv_index::{NvIndexAttributes, NvIndexAttributesBuilder}; pub use object::{ObjectAttributes, ObjectAttributesBuilder}; pub use session::{SessionAttributes, SessionAttributesBuilder, SessionAttributesMask}; tss-esapi-7.4.0/src/attributes/nv_index.rs000064400000000000000000000322001046102023000166760ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ constants::NvIndexType, tss2_esys::{TPM2_NT, TPMA_NV}, Error, Result, WrapperErrorKind, }; use bitfield::bitfield; use log::error; use std::convert::TryFrom; bitfield! { /// Bitfield representing the nv index attributes. #[derive(Copy, Clone, Eq, PartialEq)] pub struct NvIndexAttributes(TPMA_NV); impl Debug; // NV Index Attributes pub pp_write, _: 0; _, set_pp_write: 0; pub owner_write, _: 1; _, set_owner_write: 1; pub auth_write, _: 2; _, set_auth_write: 2; pub policy_write, _: 3; _, set_policy_write: 3; TPM2_NT, tss_index_type, _: 7, 4; // private getter TPM2_NT, from into NvIndexType, _, set_index_type: 7, 4; // Reserved 9,8 pub policy_delete, _: 10; _, set_policy_delete: 10; pub write_locked, _: 11; _, set_write_locked: 11; pub write_all, _: 12; _, set_write_all: 12; pub write_define, _: 13; _, set_write_define: 13; pub write_stclear, _: 14; _, set_write_stclear: 14; pub global_lock, _: 15; _, set_global_lock: 15; pub pp_read, _: 16; _, set_pp_read: 16; pub owner_read, _: 17; _, set_owner_read: 17; pub auth_read, _: 18; _, set_auth_read: 18; pub policy_read, _: 19; _, set_policy_read: 19; // Reserved 24, 20 pub no_da, _: 25; _, set_no_da: 25; pub orderly, _: 26; _, set_orderly: 26; pub clear_stclear, _: 27; _, set_clear_stclear: 27; pub read_locked, _: 28; _, set_read_locked: 28; pub written, _: 29; _, set_written: 29; pub platform_create, _: 30; _, set_platform_create: 30; pub read_stclear, _: 31; _, set_read_stclear: 31; } impl NvIndexAttributes { /// Returns the `NvIndexType` of the `NvIndexAttributes` pub fn index_type(&self) -> Result { NvIndexType::try_from(self.tss_index_type()) } /// Validates the attributes /// /// # Details /// Performs checks on `self` in order to verify /// that the attributes conforms to the requirements /// specified in the standard. /// /// # Errors /// Returns an error if some attributes are missing /// or are in conflict with each other. pub fn validate(&self) -> Result<()> { // "At least one of TPMA_NV_PPREAD, TPMA_NV_OWNERREAD, // TPMA_NV_AUTHREAD, or TPMA_NV_POLICYREAD shall be SET." if !(self.pp_read() | self.owner_read() | self.auth_read() | self.policy_read()) { error!("Non of the attributes PPREAD, OWERREAD, AUTHREAD, POLICYREAD have been set"); return Err(Error::local_error(WrapperErrorKind::ParamsMissing)); } // "At least one of TPMA_NV_PPWRITE, TPMA_NV_OWNERWRITE, // TPMA_NV_AUTHWRITE, or TPMA_NV_POLICYWRITE shall be SET." if !(self.pp_write() | self.owner_write() | self.auth_write() | self.policy_write()) { error!( "Non of the attributes PPWRITE, OWNERWRITE, AUTHWRITE, POLICYWRITE have been set" ); return Err(Error::local_error(WrapperErrorKind::ParamsMissing)); } // "If TPM_NT is TPM_NT_PIN_FAIL, TPMA_NV_NO_DA must be SET. // This removes ambiguity over which Dictionary Attack defense // protects a TPM_NV_PIN_FAIL's authValue." if (self.index_type()? == NvIndexType::PinFail) & !self.no_da() { error!("NvIndexType was PinFail but `no DA` attribute was not set"); return Err(Error::local_error(WrapperErrorKind::ParamsMissing)); } Ok(()) } /// Get a builder for the structure pub const fn builder() -> NvIndexAttributesBuilder { NvIndexAttributesBuilder::new() } } impl TryFrom for NvIndexAttributes { type Error = Error; fn try_from(tss_nv_index_atttributes: TPMA_NV) -> Result { let nv_index_attributes = NvIndexAttributes(tss_nv_index_atttributes); nv_index_attributes.validate()?; Ok(nv_index_attributes) } } impl TryFrom for TPMA_NV { type Error = Error; fn try_from(nv_index_atttributes: NvIndexAttributes) -> Result { nv_index_atttributes.validate()?; Ok(nv_index_atttributes.0) } } /// A builder NV index attributes #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub struct NvIndexAttributesBuilder { nv_index_attributes: NvIndexAttributes, } impl NvIndexAttributesBuilder { /// Creates a new nv index builder pub const fn new() -> Self { NvIndexAttributesBuilder { nv_index_attributes: NvIndexAttributes(0), } } /// Creates a new builder from existing `NvIndexAttributes` pub const fn with_attributes(nv_index_attributes: NvIndexAttributes) -> Self { NvIndexAttributesBuilder { nv_index_attributes, } } /// Controls the `pp write` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_pp_write(mut self, set: bool) -> Self { self.nv_index_attributes.set_pp_write(set); self } /// Controls the `owner write` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_owner_write(mut self, set: bool) -> Self { self.nv_index_attributes.set_owner_write(set); self } /// Controls the `auth write` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_auth_write(mut self, set: bool) -> Self { self.nv_index_attributes.set_auth_write(set); self } /// Controls the `policy write` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_policy_write(mut self, set: bool) -> Self { self.nv_index_attributes.set_policy_write(set); self } /// Controls the `nv index type` attribute /// /// # Arguments /// * `nv_index_type` - The nv index type to be used. pub fn with_nv_index_type(mut self, nv_index_type: NvIndexType) -> Self { self.nv_index_attributes.set_index_type(nv_index_type); self } /// Controls the `policy delete` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_policy_delete(mut self, set: bool) -> Self { self.nv_index_attributes.set_policy_delete(set); self } /// Controls the `write locked` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_write_locked(mut self, set: bool) -> Self { self.nv_index_attributes.set_write_locked(set); self } /// Controls the `write all` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_write_all(mut self, set: bool) -> Self { self.nv_index_attributes.set_write_all(set); self } /// Controls the `write define` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_write_define(mut self, set: bool) -> Self { self.nv_index_attributes.set_write_define(set); self } /// Controls the `write stclear` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_write_stclear(mut self, set: bool) -> Self { self.nv_index_attributes.set_write_stclear(set); self } /// Controls the `global lock` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_global_lock(mut self, set: bool) -> Self { self.nv_index_attributes.set_global_lock(set); self } /// Controls the `pp read` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_pp_read(mut self, set: bool) -> Self { self.nv_index_attributes.set_pp_read(set); self } /// Controls the `owner read` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_owner_read(mut self, set: bool) -> Self { self.nv_index_attributes.set_owner_read(set); self } /// Controls the `auth read` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_auth_read(mut self, set: bool) -> Self { self.nv_index_attributes.set_auth_read(set); self } /// Controls the `policy read` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_policy_read(mut self, set: bool) -> Self { self.nv_index_attributes.set_policy_read(set); self } /// Controls the `no DA` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_no_da(mut self, set: bool) -> Self { self.nv_index_attributes.set_no_da(set); self } /// Controls the `orderly` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_orderly(mut self, set: bool) -> Self { self.nv_index_attributes.set_orderly(set); self } /// Controls the `clear stclear` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_clear_stclear(mut self, set: bool) -> Self { self.nv_index_attributes.set_clear_stclear(set); self } /// Controls the `read locked` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_read_locked(mut self, set: bool) -> Self { self.nv_index_attributes.set_read_locked(set); self } /// Controls the `written` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_written(mut self, set: bool) -> Self { self.nv_index_attributes.set_written(set); self } /// Controls the `platform create` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_platform_create(mut self, set: bool) -> Self { self.nv_index_attributes.set_platform_create(set); self } /// Controls the `read stclear` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_read_stclear(mut self, set: bool) -> Self { self.nv_index_attributes.set_read_stclear(set); self } /// Builds the nv index attributes. /// /// # Errors /// Returns an error if some attributes are missing /// or are in conflict with each other. pub fn build(self) -> Result { self.nv_index_attributes.validate()?; Ok(self.nv_index_attributes) } } impl Default for NvIndexAttributesBuilder { fn default() -> Self { NvIndexAttributesBuilder::new() } } tss-esapi-7.4.0/src/attributes/object.rs000064400000000000000000000164251046102023000163450ustar 00000000000000use crate::{tss2_esys::TPMA_OBJECT, Result}; use bitfield::bitfield; bitfield! { /// Bitfield representing the object attributes. #[derive(Copy, Clone, Eq, PartialEq)] pub struct ObjectAttributes(TPMA_OBJECT); impl Debug; // Object attribute flags pub fixed_tpm, _: 1; _, set_fixed_tpm: 1; pub st_clear, _: 2; _, set_st_clear: 2; pub fixed_parent, _: 4; _, set_fixed_parent: 4; pub sensitive_data_origin, _: 5; _, set_sensitive_data_origin: 5; pub user_with_auth, _: 6; _, set_user_with_auth: 6; pub admin_with_policy, _: 7; _, set_admin_with_policy: 7; pub no_da, _: 10; _, set_no_da: 10; pub encrypted_duplication, _: 11; _, set_encrypted_duplication: 11; pub restricted, _: 16; _, set_restricted: 16; pub decrypt, _: 17; _, set_decrypt: 17; pub sign_encrypt, _: 18; _, set_sign_encrypt: 18; pub x509_sign, _: 19; _, set_x509_sign: 19; } impl ObjectAttributes { /// Function for creating attributes for a /// fixed parent key object. pub fn new_fixed_parent_key() -> Self { let mut attrs = ObjectAttributes(0); attrs.set_fixed_tpm(true); attrs.set_fixed_parent(true); attrs.set_sensitive_data_origin(true); attrs.set_user_with_auth(true); attrs.set_decrypt(true); attrs.set_restricted(true); attrs } /// Function for creating attributes for /// a fixed signing key object. pub fn new_fixed_signing_key() -> Self { let mut attrs = ObjectAttributes(0); attrs.set_fixed_tpm(true); attrs.set_fixed_parent(true); attrs.set_sensitive_data_origin(true); attrs.set_user_with_auth(true); attrs.set_sign_encrypt(true); attrs } /// Get a builder for the structure pub const fn builder() -> ObjectAttributesBuilder { ObjectAttributesBuilder::new() } } impl From for TPMA_OBJECT { fn from(object_attributes: ObjectAttributes) -> Self { object_attributes.0 } } impl From for ObjectAttributes { fn from(tpma_object: TPMA_OBJECT) -> Self { ObjectAttributes(tpma_object) } } /// A builder for [ObjectAttributes] #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub struct ObjectAttributesBuilder { object_attributes: ObjectAttributes, } impl ObjectAttributesBuilder { /// Creates an new [ObjectAttributes] builder. pub const fn new() -> Self { ObjectAttributesBuilder { object_attributes: ObjectAttributes(0), } } /// Controls the `fixed tpm` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_fixed_tpm(mut self, set: bool) -> Self { self.object_attributes.set_fixed_tpm(set); self } /// Controls the `st clear` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_st_clear(mut self, set: bool) -> Self { self.object_attributes.set_st_clear(set); self } /// Controls the `fixed parent` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_fixed_parent(mut self, set: bool) -> Self { self.object_attributes.set_fixed_parent(set); self } /// Controls the `sensitive data origin` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_sensitive_data_origin(mut self, set: bool) -> Self { self.object_attributes.set_sensitive_data_origin(set); self } /// Controls the `user with auth` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_user_with_auth(mut self, set: bool) -> Self { self.object_attributes.set_user_with_auth(set); self } /// Controls the `admin with policy` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_admin_with_policy(mut self, set: bool) -> Self { self.object_attributes.set_admin_with_policy(set); self } /// Controls the `no da` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_no_da(mut self, set: bool) -> Self { self.object_attributes.set_no_da(set); self } /// Controls the `encrypted duplication` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_encrypted_duplication(mut self, set: bool) -> Self { self.object_attributes.set_encrypted_duplication(set); self } /// Controls the `restricted` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_restricted(mut self, set: bool) -> Self { self.object_attributes.set_restricted(set); self } /// Controls the `decrypt` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_decrypt(mut self, set: bool) -> Self { self.object_attributes.set_decrypt(set); self } /// Controls the `sign/encrypt` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_sign_encrypt(mut self, set: bool) -> Self { self.object_attributes.set_sign_encrypt(set); self } /// Controls the `X509 sign` attribute /// /// # Arguments /// * `set` - `true` indicates that the attribute should have the value SET. /// `false`indicates that the attribute should have the value CLEAR. pub fn with_x509_sign(mut self, set: bool) -> Self { self.object_attributes.set_x509_sign(set); self } /// Builds the nv index attributes. /// /// # Errors /// Returns an error if some attributes are missing /// or are in conflict with each other. pub fn build(self) -> Result { Ok(self.object_attributes) } } impl Default for ObjectAttributesBuilder { fn default() -> Self { ObjectAttributesBuilder::new() } } tss-esapi-7.4.0/src/attributes/session.rs000064400000000000000000000072721046102023000165620ustar 00000000000000use crate::tss2_esys::TPMA_SESSION; use bitfield::bitfield; // SESSION ATTRIBUTES bitfield! { /// Bitfield representing the session attributes. #[derive(Copy, Clone, Eq, PartialEq)] pub struct SessionAttributes(TPMA_SESSION); impl Debug; _, set_continue_session: 0; pub continue_session, _: 0; _, set_audit_exclusive: 1; pub audit_exclusive, _: 1; _, set_audit_reset: 2; pub audit_reset, _: 2; // Reserved 3,4 (Shall be clear) _, set_decrypt: 5; pub decrypt, _: 5; _, set_encrypt: 6; pub encrypt, _: 6; _, set_audit: 7; pub audit, _: 7; } impl SessionAttributes { /// Get a builder for the structure pub const fn builder() -> SessionAttributesBuilder { SessionAttributesBuilder::new() } } impl From for SessionAttributes { fn from(tss_session_attributes: TPMA_SESSION) -> SessionAttributes { SessionAttributes(tss_session_attributes) } } impl From for TPMA_SESSION { fn from(session_attributes: SessionAttributes) -> TPMA_SESSION { session_attributes.0 } } // SESSION ATTRIBUTES MASK bitfield! { /// Bitfield representing the session attributes mask. #[derive(Copy, Clone, Eq, PartialEq)] pub struct SessionAttributesMask(TPMA_SESSION); impl Debug; _, use_continue_session: 0; _, use_audit_exclusive: 1; _, use_audit_reset: 2; // Reserved 3,4 (Shall be clear) _, use_decrypt: 5; _, use_encrypt: 6; _, use_audit: 7; } impl SessionAttributesMask { /// Get a builder for the structure pub const fn builder() -> SessionAttributesBuilder { SessionAttributesBuilder::new() } } impl From for SessionAttributesMask { fn from(tss_session_attributes: TPMA_SESSION) -> SessionAttributesMask { SessionAttributesMask(tss_session_attributes) } } impl From for TPMA_SESSION { fn from(session_attributes_mask: SessionAttributesMask) -> TPMA_SESSION { session_attributes_mask.0 } } // SESSION ATTRIBUTES ITEMS BUILDER /// A builder that is used to create /// SessionAttributes and a corresponding /// SessionAttributesMask. #[derive(Debug, Copy, Clone)] pub struct SessionAttributesBuilder { attributes: SessionAttributes, mask: SessionAttributesMask, } impl SessionAttributesBuilder { pub const fn new() -> SessionAttributesBuilder { SessionAttributesBuilder { attributes: SessionAttributes(0), mask: SessionAttributesMask(0), } } pub fn with_continue_session(mut self, set: bool) -> Self { self.attributes.set_continue_session(set); self.mask.use_continue_session(true); self } pub fn with_audit_exclusive(mut self, set: bool) -> Self { self.attributes.set_audit_exclusive(set); self.mask.use_audit_exclusive(true); self } pub fn with_audit_reset(mut self, set: bool) -> Self { self.attributes.set_audit_reset(set); self.mask.use_audit_reset(true); self } pub fn with_decrypt(mut self, set: bool) -> Self { self.attributes.set_decrypt(set); self.mask.use_decrypt(true); self } pub fn with_encrypt(mut self, set: bool) -> Self { self.attributes.set_encrypt(set); self.mask.use_encrypt(true); self } pub fn with_audit(mut self, set: bool) -> Self { self.attributes.set_audit(set); self.mask.use_audit(true); self } pub fn build(self) -> (SessionAttributes, SessionAttributesMask) { (self.attributes, self.mask) } } impl Default for SessionAttributesBuilder { fn default() -> Self { Self::new() } } tss-esapi-7.4.0/src/constants/algorithm.rs000064400000000000000000000056511046102023000167120ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ constants::tss::{ TPM2_ALG_AES, TPM2_ALG_CAMELLIA, TPM2_ALG_CBC, TPM2_ALG_CFB, TPM2_ALG_CMAC, TPM2_ALG_CTR, TPM2_ALG_ECB, TPM2_ALG_ECC, TPM2_ALG_ECDAA, TPM2_ALG_ECDH, TPM2_ALG_ECDSA, TPM2_ALG_ECMQV, TPM2_ALG_ECSCHNORR, TPM2_ALG_ERROR, TPM2_ALG_HMAC, TPM2_ALG_KDF1_SP800_108, TPM2_ALG_KDF1_SP800_56A, TPM2_ALG_KDF2, TPM2_ALG_KEYEDHASH, TPM2_ALG_MGF1, TPM2_ALG_NULL, TPM2_ALG_OAEP, TPM2_ALG_OFB, TPM2_ALG_RSA, TPM2_ALG_RSAES, TPM2_ALG_RSAPSS, TPM2_ALG_RSASSA, TPM2_ALG_SHA1, TPM2_ALG_SHA256, TPM2_ALG_SHA384, TPM2_ALG_SHA3_256, TPM2_ALG_SHA3_384, TPM2_ALG_SHA3_512, TPM2_ALG_SHA512, TPM2_ALG_SM2, TPM2_ALG_SM3_256, TPM2_ALG_SM4, TPM2_ALG_SYMCIPHER, TPM2_ALG_TDES, TPM2_ALG_XOR, }, tss2_esys::TPM2_ALG_ID, Error, Result, WrapperErrorKind, }; use log::error; use num_derive::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive}; use std::convert::TryFrom; #[derive(FromPrimitive, ToPrimitive, Copy, Clone, Debug, PartialEq, Eq, Hash)] #[repr(u16)] pub enum AlgorithmIdentifier { Aes = TPM2_ALG_AES, Camellia = TPM2_ALG_CAMELLIA, Cbc = TPM2_ALG_CBC, Cfb = TPM2_ALG_CFB, Ctr = TPM2_ALG_CTR, Ecb = TPM2_ALG_ECB, Ecc = TPM2_ALG_ECC, EcDaa = TPM2_ALG_ECDAA, EcDh = TPM2_ALG_ECDH, EcDsa = TPM2_ALG_ECDSA, EcMqv = TPM2_ALG_ECMQV, EcSchnorr = TPM2_ALG_ECSCHNORR, Error = TPM2_ALG_ERROR, Hmac = TPM2_ALG_HMAC, Kdf1Sp800_108 = TPM2_ALG_KDF1_SP800_108, Kdf1Sp800_56a = TPM2_ALG_KDF1_SP800_56A, Kdf2 = TPM2_ALG_KDF2, KeyedHash = TPM2_ALG_KEYEDHASH, Mgf1 = TPM2_ALG_MGF1, Null = TPM2_ALG_NULL, Oaep = TPM2_ALG_OAEP, Ofb = TPM2_ALG_OFB, Rsa = TPM2_ALG_RSA, RsaEs = TPM2_ALG_RSAES, RsaPss = TPM2_ALG_RSAPSS, RsaSsa = TPM2_ALG_RSASSA, Sha1 = TPM2_ALG_SHA1, Sha256 = TPM2_ALG_SHA256, Sha384 = TPM2_ALG_SHA384, Sha3_256 = TPM2_ALG_SHA3_256, Sha3_384 = TPM2_ALG_SHA3_384, Sha3_512 = TPM2_ALG_SHA3_512, Sha512 = TPM2_ALG_SHA512, Sm2 = TPM2_ALG_SM2, Sm3_256 = TPM2_ALG_SM3_256, Sm4 = TPM2_ALG_SM4, SymCipher = TPM2_ALG_SYMCIPHER, Tdes = TPM2_ALG_TDES, Xor = TPM2_ALG_XOR, Cmac = TPM2_ALG_CMAC, } impl TryFrom for AlgorithmIdentifier { type Error = Error; fn try_from(tpm_alg_id: TPM2_ALG_ID) -> Result { AlgorithmIdentifier::from_u16(tpm_alg_id).ok_or_else(|| { error!( "Value = {} did not match any algorithm identifier", tpm_alg_id ); Error::local_error(WrapperErrorKind::InvalidParam) }) } } impl From for TPM2_ALG_ID { fn from(algorithm: AlgorithmIdentifier) -> TPM2_ALG_ID { // The values are well defined so this cannot fail. algorithm.to_u16().unwrap() } } tss-esapi-7.4.0/src/constants/capabilities.rs000064400000000000000000000033071046102023000173510ustar 00000000000000use crate::{Error, Result, WrapperErrorKind}; use log::error; use num_derive::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive}; use std::convert::{From, TryFrom}; use crate::{ constants::tss::{ TPM2_CAP_ACT, TPM2_CAP_ALGS, TPM2_CAP_AUDIT_COMMANDS, TPM2_CAP_AUTH_POLICIES, TPM2_CAP_COMMANDS, TPM2_CAP_ECC_CURVES, TPM2_CAP_HANDLES, TPM2_CAP_PCRS, TPM2_CAP_PCR_PROPERTIES, TPM2_CAP_PP_COMMANDS, TPM2_CAP_TPM_PROPERTIES, }, tss2_esys::TPM2_CAP, }; // Enum representing the different TPM Capability Type values. #[derive(FromPrimitive, ToPrimitive, Debug, Copy, Clone, PartialEq, Eq)] #[repr(u32)] pub enum CapabilityType { Algorithms = TPM2_CAP_ALGS, Handles = TPM2_CAP_HANDLES, Command = TPM2_CAP_COMMANDS, PpCommands = TPM2_CAP_PP_COMMANDS, AuditCommands = TPM2_CAP_AUDIT_COMMANDS, AssignedPcr = TPM2_CAP_PCRS, TpmProperties = TPM2_CAP_TPM_PROPERTIES, PcrProperties = TPM2_CAP_PCR_PROPERTIES, EccCurves = TPM2_CAP_ECC_CURVES, AuthPolicies = TPM2_CAP_AUTH_POLICIES, Act = TPM2_CAP_ACT, } impl From for TPM2_CAP { fn from(capability_type: CapabilityType) -> TPM2_CAP { // The values are well defined so this cannot fail. capability_type.to_u32().unwrap() } } impl TryFrom for CapabilityType { type Error = Error; fn try_from(tpm_capability_type: TPM2_CAP) -> Result { CapabilityType::from_u32(tpm_capability_type).ok_or_else(|| { error!( "value = {} did not match any CapabilityType.", tpm_capability_type ); Error::local_error(WrapperErrorKind::InvalidParam) }) } } tss-esapi-7.4.0/src/constants/command_code/structure.rs000064400000000000000000000370311046102023000213710ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ constants::tss::{ TPM2_CC_AC_GetCapability, TPM2_CC_AC_Send, TPM2_CC_ActivateCredential, TPM2_CC_Certify, TPM2_CC_CertifyCreation, TPM2_CC_ChangeEPS, TPM2_CC_ChangePPS, TPM2_CC_Clear, TPM2_CC_ClearControl, TPM2_CC_ClockRateAdjust, TPM2_CC_ClockSet, TPM2_CC_Commit, TPM2_CC_ContextLoad, TPM2_CC_ContextSave, TPM2_CC_Create, TPM2_CC_CreateLoaded, TPM2_CC_CreatePrimary, TPM2_CC_DictionaryAttackLockReset, TPM2_CC_DictionaryAttackParameters, TPM2_CC_Duplicate, TPM2_CC_ECC_Parameters, TPM2_CC_ECDH_KeyGen, TPM2_CC_ECDH_ZGen, TPM2_CC_EC_Ephemeral, TPM2_CC_EncryptDecrypt, TPM2_CC_EncryptDecrypt2, TPM2_CC_EventSequenceComplete, TPM2_CC_EvictControl, TPM2_CC_FieldUpgradeData, TPM2_CC_FieldUpgradeStart, TPM2_CC_FirmwareRead, TPM2_CC_FlushContext, TPM2_CC_GetCapability, TPM2_CC_GetCommandAuditDigest, TPM2_CC_GetRandom, TPM2_CC_GetSessionAuditDigest, TPM2_CC_GetTestResult, TPM2_CC_GetTime, TPM2_CC_HMAC_Start, TPM2_CC_Hash, TPM2_CC_HashSequenceStart, TPM2_CC_HierarchyChangeAuth, TPM2_CC_HierarchyControl, TPM2_CC_Import, TPM2_CC_IncrementalSelfTest, TPM2_CC_Load, TPM2_CC_LoadExternal, TPM2_CC_MakeCredential, TPM2_CC_NV_Certify, TPM2_CC_NV_ChangeAuth, TPM2_CC_NV_DefineSpace, TPM2_CC_NV_Extend, TPM2_CC_NV_GlobalWriteLock, TPM2_CC_NV_Increment, TPM2_CC_NV_Read, TPM2_CC_NV_ReadLock, TPM2_CC_NV_ReadPublic, TPM2_CC_NV_SetBits, TPM2_CC_NV_UndefineSpace, TPM2_CC_NV_UndefineSpaceSpecial, TPM2_CC_NV_Write, TPM2_CC_NV_WriteLock, TPM2_CC_ObjectChangeAuth, TPM2_CC_PCR_Allocate, TPM2_CC_PCR_Event, TPM2_CC_PCR_Extend, TPM2_CC_PCR_Read, TPM2_CC_PCR_Reset, TPM2_CC_PCR_SetAuthPolicy, TPM2_CC_PCR_SetAuthValue, TPM2_CC_PP_Commands, TPM2_CC_PolicyAuthValue, TPM2_CC_PolicyAuthorize, TPM2_CC_PolicyAuthorizeNV, TPM2_CC_PolicyCommandCode, TPM2_CC_PolicyCounterTimer, TPM2_CC_PolicyCpHash, TPM2_CC_PolicyDuplicationSelect, TPM2_CC_PolicyGetDigest, TPM2_CC_PolicyLocality, TPM2_CC_PolicyNV, TPM2_CC_PolicyNameHash, TPM2_CC_PolicyNvWritten, TPM2_CC_PolicyOR, TPM2_CC_PolicyPCR, TPM2_CC_PolicyPassword, TPM2_CC_PolicyPhysicalPresence, TPM2_CC_PolicyRestart, TPM2_CC_PolicySecret, TPM2_CC_PolicySigned, TPM2_CC_PolicyTemplate, TPM2_CC_PolicyTicket, TPM2_CC_Policy_AC_SendSelect, TPM2_CC_Quote, TPM2_CC_RSA_Decrypt, TPM2_CC_RSA_Encrypt, TPM2_CC_ReadClock, TPM2_CC_ReadPublic, TPM2_CC_Rewrap, TPM2_CC_SelfTest, TPM2_CC_SequenceComplete, TPM2_CC_SequenceUpdate, TPM2_CC_SetAlgorithmSet, TPM2_CC_SetCommandCodeAuditStatus, TPM2_CC_SetPrimaryPolicy, TPM2_CC_Shutdown, TPM2_CC_Sign, TPM2_CC_StartAuthSession, TPM2_CC_Startup, TPM2_CC_StirRandom, TPM2_CC_TestParms, TPM2_CC_Unseal, TPM2_CC_VerifySignature, TPM2_CC_ZGen_2Phase, TPM2_CC_HMAC, }, tss2_esys::TPM2_CC, Error, Result, WrapperErrorKind, }; use bitfield::bitfield; use log::error; use std::convert::TryFrom; bitfield! { /// Bitfield representing the command code structure #[derive(Copy, Clone, Eq, PartialEq, Hash)] pub struct CommandCodeStructure(u32); impl Debug; _, set_command_index: 15, 0; pub command_index, _: 15, 0; pub reserved, _ : 28, 16; // Shall be zero _, set_vendor_specific: 29; pub vendor_specific, _: 29; pub res, _ : 31, 30; // Shall be zero } impl CommandCodeStructure { pub const NV_UNDEFINE_SPACE_SPECIAL: CommandCodeStructure = CommandCodeStructure(TPM2_CC_NV_UndefineSpaceSpecial); pub const EVICT_CONTROL: CommandCodeStructure = CommandCodeStructure(TPM2_CC_EvictControl); pub const HIERARCHY_CONTROL: CommandCodeStructure = CommandCodeStructure(TPM2_CC_HierarchyControl); pub const NV_UNDEFINE_SPACE: CommandCodeStructure = CommandCodeStructure(TPM2_CC_NV_UndefineSpace); pub const CHANGE_EPS: CommandCodeStructure = CommandCodeStructure(TPM2_CC_ChangeEPS); pub const CHANGE_PPS: CommandCodeStructure = CommandCodeStructure(TPM2_CC_ChangePPS); pub const CLEAR: CommandCodeStructure = CommandCodeStructure(TPM2_CC_Clear); pub const CLEAR_CONTROL: CommandCodeStructure = CommandCodeStructure(TPM2_CC_ClearControl); pub const CLOCK_SET: CommandCodeStructure = CommandCodeStructure(TPM2_CC_ClockSet); pub const HIERARCHY_CHANGE_AUTH: CommandCodeStructure = CommandCodeStructure(TPM2_CC_HierarchyChangeAuth); pub const NV_DEFINE_SPACE: CommandCodeStructure = CommandCodeStructure(TPM2_CC_NV_DefineSpace); pub const PCR_ALLOCATE: CommandCodeStructure = CommandCodeStructure(TPM2_CC_PCR_Allocate); pub const PCR_SET_AUTH_POLICY: CommandCodeStructure = CommandCodeStructure(TPM2_CC_PCR_SetAuthPolicy); pub const PP_COMMANDS: CommandCodeStructure = CommandCodeStructure(TPM2_CC_PP_Commands); pub const SET_PRIMARY_POLICY: CommandCodeStructure = CommandCodeStructure(TPM2_CC_SetPrimaryPolicy); pub const FIELD_UPGRADE_START: CommandCodeStructure = CommandCodeStructure(TPM2_CC_FieldUpgradeStart); pub const CLOCK_RATE_ADJUST: CommandCodeStructure = CommandCodeStructure(TPM2_CC_ClockRateAdjust); pub const CREATE_PRIMARY: CommandCodeStructure = CommandCodeStructure(TPM2_CC_CreatePrimary); pub const NV_GLOBAL_WRITE_LOCK: CommandCodeStructure = CommandCodeStructure(TPM2_CC_NV_GlobalWriteLock); pub const GET_COMMAND_AUDIT_DIGEST: CommandCodeStructure = CommandCodeStructure(TPM2_CC_GetCommandAuditDigest); pub const NV_INCREMENT: CommandCodeStructure = CommandCodeStructure(TPM2_CC_NV_Increment); pub const NV_SET_BITS: CommandCodeStructure = CommandCodeStructure(TPM2_CC_NV_SetBits); pub const NV_EXTEND: CommandCodeStructure = CommandCodeStructure(TPM2_CC_NV_Extend); pub const NV_WRITE: CommandCodeStructure = CommandCodeStructure(TPM2_CC_NV_Write); pub const NV_WRITE_LOCK: CommandCodeStructure = CommandCodeStructure(TPM2_CC_NV_WriteLock); pub const DICTIONARY_ATTACK_LOCK_RESET: CommandCodeStructure = CommandCodeStructure(TPM2_CC_DictionaryAttackLockReset); pub const DICTIONARY_ATTACK_PARAMETERS: CommandCodeStructure = CommandCodeStructure(TPM2_CC_DictionaryAttackParameters); pub const NV_CHANGE_AUTH: CommandCodeStructure = CommandCodeStructure(TPM2_CC_NV_ChangeAuth); pub const PCR_EVENT: CommandCodeStructure = CommandCodeStructure(TPM2_CC_PCR_Event); pub const PCR_RESET: CommandCodeStructure = CommandCodeStructure(TPM2_CC_PCR_Reset); pub const SEQUENCE_COMPLETE: CommandCodeStructure = CommandCodeStructure(TPM2_CC_SequenceComplete); pub const SET_ALGORITHM_SET: CommandCodeStructure = CommandCodeStructure(TPM2_CC_SetAlgorithmSet); pub const SET_COMMAND_CODE_AUDIT_STATUS: CommandCodeStructure = CommandCodeStructure(TPM2_CC_SetCommandCodeAuditStatus); pub const FIELD_UPGRADE_DATA: CommandCodeStructure = CommandCodeStructure(TPM2_CC_FieldUpgradeData); pub const INCREMENTAL_SELF_TEST: CommandCodeStructure = CommandCodeStructure(TPM2_CC_IncrementalSelfTest); pub const SELF_TEST: CommandCodeStructure = CommandCodeStructure(TPM2_CC_SelfTest); pub const STARTUP: CommandCodeStructure = CommandCodeStructure(TPM2_CC_Startup); pub const SHUTDOWN: CommandCodeStructure = CommandCodeStructure(TPM2_CC_Shutdown); pub const STIR_RANDOM: CommandCodeStructure = CommandCodeStructure(TPM2_CC_StirRandom); pub const ACTIVATE_CREDENTIAL: CommandCodeStructure = CommandCodeStructure(TPM2_CC_ActivateCredential); pub const CERTIFY: CommandCodeStructure = CommandCodeStructure(TPM2_CC_Certify); pub const POLICY_NV: CommandCodeStructure = CommandCodeStructure(TPM2_CC_PolicyNV); pub const CERTIFY_CREATION: CommandCodeStructure = CommandCodeStructure(TPM2_CC_CertifyCreation); pub const DUPLICATE: CommandCodeStructure = CommandCodeStructure(TPM2_CC_Duplicate); pub const GET_TIME: CommandCodeStructure = CommandCodeStructure(TPM2_CC_GetTime); pub const GET_SESSION_AUDIT_DIGEST: CommandCodeStructure = CommandCodeStructure(TPM2_CC_GetSessionAuditDigest); pub const NV_READ: CommandCodeStructure = CommandCodeStructure(TPM2_CC_NV_Read); pub const NV_READ_LOCK: CommandCodeStructure = CommandCodeStructure(TPM2_CC_NV_ReadLock); pub const OBJECT_CHANGE_AUTH: CommandCodeStructure = CommandCodeStructure(TPM2_CC_ObjectChangeAuth); pub const POLICY_SECRET: CommandCodeStructure = CommandCodeStructure(TPM2_CC_PolicySecret); pub const REWRAP: CommandCodeStructure = CommandCodeStructure(TPM2_CC_Rewrap); pub const CREATE: CommandCodeStructure = CommandCodeStructure(TPM2_CC_Create); pub const ECDH_Z_GEN: CommandCodeStructure = CommandCodeStructure(TPM2_CC_ECDH_ZGen); pub const HMAC: CommandCodeStructure = CommandCodeStructure(TPM2_CC_HMAC); pub const IMPORT: CommandCodeStructure = CommandCodeStructure(TPM2_CC_Import); pub const LOAD: CommandCodeStructure = CommandCodeStructure(TPM2_CC_Load); pub const QUOTE: CommandCodeStructure = CommandCodeStructure(TPM2_CC_Quote); pub const RSA_DECRYPT: CommandCodeStructure = CommandCodeStructure(TPM2_CC_RSA_Decrypt); pub const HMAC_START: CommandCodeStructure = CommandCodeStructure(TPM2_CC_HMAC_Start); pub const SEQUENCE_UPDATE: CommandCodeStructure = CommandCodeStructure(TPM2_CC_SequenceUpdate); pub const SIGN: CommandCodeStructure = CommandCodeStructure(TPM2_CC_Sign); pub const UNSEAL: CommandCodeStructure = CommandCodeStructure(TPM2_CC_Unseal); pub const POLICY_SIGNED: CommandCodeStructure = CommandCodeStructure(TPM2_CC_PolicySigned); pub const CONTEXT_LOAD: CommandCodeStructure = CommandCodeStructure(TPM2_CC_ContextLoad); pub const CONTEXT_SAVE: CommandCodeStructure = CommandCodeStructure(TPM2_CC_ContextSave); pub const ECDH_KEY_GEN: CommandCodeStructure = CommandCodeStructure(TPM2_CC_ECDH_KeyGen); pub const ENCRYPT_DECRYPT: CommandCodeStructure = CommandCodeStructure(TPM2_CC_EncryptDecrypt); pub const FLUSH_CONTEXT: CommandCodeStructure = CommandCodeStructure(TPM2_CC_FlushContext); pub const LOAD_EXTERNAL: CommandCodeStructure = CommandCodeStructure(TPM2_CC_LoadExternal); pub const MAKE_CREDENTIAL: CommandCodeStructure = CommandCodeStructure(TPM2_CC_MakeCredential); pub const NV_READ_PUBLIC: CommandCodeStructure = CommandCodeStructure(TPM2_CC_NV_ReadPublic); pub const POLICY_AUTHORIZE: CommandCodeStructure = CommandCodeStructure(TPM2_CC_PolicyAuthorize); pub const POLICY_AUTH_VALUE: CommandCodeStructure = CommandCodeStructure(TPM2_CC_PolicyAuthValue); pub const POLICY_COMMAND_CODE: CommandCodeStructure = CommandCodeStructure(TPM2_CC_PolicyCommandCode); pub const POLICY_COUNTER_TIMER: CommandCodeStructure = CommandCodeStructure(TPM2_CC_PolicyCounterTimer); pub const POLICY_CP_HASH: CommandCodeStructure = CommandCodeStructure(TPM2_CC_PolicyCpHash); pub const POLICY_LOCALITY: CommandCodeStructure = CommandCodeStructure(TPM2_CC_PolicyLocality); pub const POLICY_NAME_HASH: CommandCodeStructure = CommandCodeStructure(TPM2_CC_PolicyNameHash); pub const POLICY_OR: CommandCodeStructure = CommandCodeStructure(TPM2_CC_PolicyOR); pub const POLICY_TICKET: CommandCodeStructure = CommandCodeStructure(TPM2_CC_PolicyTicket); pub const READ_PUBLIC: CommandCodeStructure = CommandCodeStructure(TPM2_CC_ReadPublic); pub const RSA_ENCRYPT: CommandCodeStructure = CommandCodeStructure(TPM2_CC_RSA_Encrypt); pub const START_AUTH_SESSION: CommandCodeStructure = CommandCodeStructure(TPM2_CC_StartAuthSession); pub const VERIFY_SIGNATURE: CommandCodeStructure = CommandCodeStructure(TPM2_CC_VerifySignature); pub const ECC_PARAMETERS: CommandCodeStructure = CommandCodeStructure(TPM2_CC_ECC_Parameters); pub const FIRMWARE_READ: CommandCodeStructure = CommandCodeStructure(TPM2_CC_FirmwareRead); pub const GET_CAPABILITY: CommandCodeStructure = CommandCodeStructure(TPM2_CC_GetCapability); pub const GET_RANDOM: CommandCodeStructure = CommandCodeStructure(TPM2_CC_GetRandom); pub const GET_TEST_RESULT: CommandCodeStructure = CommandCodeStructure(TPM2_CC_GetTestResult); pub const HASH: CommandCodeStructure = CommandCodeStructure(TPM2_CC_Hash); pub const PCR_READ: CommandCodeStructure = CommandCodeStructure(TPM2_CC_PCR_Read); pub const POLICY_PCR: CommandCodeStructure = CommandCodeStructure(TPM2_CC_PolicyPCR); pub const POLICY_RESTART: CommandCodeStructure = CommandCodeStructure(TPM2_CC_PolicyRestart); pub const READ_CLOCK: CommandCodeStructure = CommandCodeStructure(TPM2_CC_ReadClock); pub const PCR_EXTEND: CommandCodeStructure = CommandCodeStructure(TPM2_CC_PCR_Extend); pub const PCR_SET_AUTH_VALUE: CommandCodeStructure = CommandCodeStructure(TPM2_CC_PCR_SetAuthValue); pub const NV_CERTIFY: CommandCodeStructure = CommandCodeStructure(TPM2_CC_NV_Certify); pub const EVENT_SEQUENCE_COMPLETE: CommandCodeStructure = CommandCodeStructure(TPM2_CC_EventSequenceComplete); pub const HASH_SEQUENCE_START: CommandCodeStructure = CommandCodeStructure(TPM2_CC_HashSequenceStart); pub const POLICY_PHYSICAL_PRESENCE: CommandCodeStructure = CommandCodeStructure(TPM2_CC_PolicyPhysicalPresence); pub const POLICY_DUPLICATION_SELECT: CommandCodeStructure = CommandCodeStructure(TPM2_CC_PolicyDuplicationSelect); pub const POLICY_GET_DIGEST: CommandCodeStructure = CommandCodeStructure(TPM2_CC_PolicyGetDigest); pub const TEST_PARMS: CommandCodeStructure = CommandCodeStructure(TPM2_CC_TestParms); pub const COMMIT: CommandCodeStructure = CommandCodeStructure(TPM2_CC_Commit); pub const POLICY_PASSWORD: CommandCodeStructure = CommandCodeStructure(TPM2_CC_PolicyPassword); pub const Z_GEN_2_PHASE: CommandCodeStructure = CommandCodeStructure(TPM2_CC_ZGen_2Phase); pub const EC_EPHEMERAL: CommandCodeStructure = CommandCodeStructure(TPM2_CC_EC_Ephemeral); pub const POLICY_NV_WRITTEN: CommandCodeStructure = CommandCodeStructure(TPM2_CC_PolicyNvWritten); pub const POLICY_TEMPLATE: CommandCodeStructure = CommandCodeStructure(TPM2_CC_PolicyTemplate); pub const CREATE_LOADED: CommandCodeStructure = CommandCodeStructure(TPM2_CC_CreateLoaded); pub const POLICY_AUTHORIZE_NV: CommandCodeStructure = CommandCodeStructure(TPM2_CC_PolicyAuthorizeNV); pub const ENCRYPT_DECRYPT_2: CommandCodeStructure = CommandCodeStructure(TPM2_CC_EncryptDecrypt2); pub const AC_GET_CAPABILITY: CommandCodeStructure = CommandCodeStructure(TPM2_CC_AC_GetCapability); pub const AC_SEND: CommandCodeStructure = CommandCodeStructure(TPM2_CC_AC_Send); pub const POLICY_AC_SEND_SELECT: CommandCodeStructure = CommandCodeStructure(TPM2_CC_Policy_AC_SendSelect); } impl TryFrom for CommandCodeStructure { type Error = Error; fn try_from(tpm2_cc: TPM2_CC) -> Result { let command_code_structure = CommandCodeStructure(tpm2_cc); if command_code_structure.vendor_specific() { error!("The command code is vendor specific and cannot be parsed"); return Err(Error::local_error(WrapperErrorKind::UnsupportedParam)); } if command_code_structure.reserved() != 0 || command_code_structure.res() != 0 { error!("Encountered non zero reserved bits"); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } Ok(command_code_structure) } } impl From for TPM2_CC { fn from(command_code_structure: CommandCodeStructure) -> Self { command_code_structure.0 } } tss-esapi-7.4.0/src/constants/command_code.rs000064400000000000000000000173561046102023000173410ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod structure; use crate::{tss2_esys::TPM2_CC, Error, Result, WrapperErrorKind}; use log::error; use num_derive::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive}; use std::convert::TryFrom; use structure::CommandCodeStructure; /// Enum representing the command code constants. /// /// # Details /// This corresponds to the TPM2_CC constants. #[derive(FromPrimitive, ToPrimitive, Copy, Clone, Debug, PartialEq, Eq, Hash)] #[repr(u32)] pub enum CommandCode { NvUndefineSpaceSpecial = CommandCodeStructure::NV_UNDEFINE_SPACE_SPECIAL.0, EvictControl = CommandCodeStructure::EVICT_CONTROL.0, HierarchyControl = CommandCodeStructure::HIERARCHY_CONTROL.0, NvUndefineSpace = CommandCodeStructure::NV_UNDEFINE_SPACE.0, ChangeEps = CommandCodeStructure::CHANGE_EPS.0, ChangePps = CommandCodeStructure::CHANGE_PPS.0, Clear = CommandCodeStructure::CLEAR.0, ClearControl = CommandCodeStructure::CLEAR_CONTROL.0, ClockSet = CommandCodeStructure::CLOCK_SET.0, HierarchyChangeAuth = CommandCodeStructure::HIERARCHY_CHANGE_AUTH.0, NvDefineSpace = CommandCodeStructure::NV_DEFINE_SPACE.0, PcrAllocate = CommandCodeStructure::PCR_ALLOCATE.0, PcrSetAuthPolicy = CommandCodeStructure::PCR_SET_AUTH_POLICY.0, PpCommands = CommandCodeStructure::PP_COMMANDS.0, SetPrimaryPolicy = CommandCodeStructure::SET_PRIMARY_POLICY.0, FieldUpgradeStart = CommandCodeStructure::FIELD_UPGRADE_START.0, ClockRateAdjust = CommandCodeStructure::CLOCK_RATE_ADJUST.0, CreatePrimary = CommandCodeStructure::CREATE_PRIMARY.0, NvGlobalWriteLock = CommandCodeStructure::NV_GLOBAL_WRITE_LOCK.0, GetCommandAuditDigest = CommandCodeStructure::GET_COMMAND_AUDIT_DIGEST.0, NvIncrement = CommandCodeStructure::NV_INCREMENT.0, NvSetBits = CommandCodeStructure::NV_SET_BITS.0, NvExtend = CommandCodeStructure::NV_EXTEND.0, NvWrite = CommandCodeStructure::NV_WRITE.0, NvWriteLock = CommandCodeStructure::NV_WRITE_LOCK.0, DictionaryAttackLockReset = CommandCodeStructure::DICTIONARY_ATTACK_LOCK_RESET.0, DictionaryAttackParameters = CommandCodeStructure::DICTIONARY_ATTACK_PARAMETERS.0, NvChangeAuth = CommandCodeStructure::NV_CHANGE_AUTH.0, PcrEvent = CommandCodeStructure::PCR_EVENT.0, PcrReset = CommandCodeStructure::PCR_RESET.0, SequenceComplete = CommandCodeStructure::SEQUENCE_COMPLETE.0, SetAlgorithmSet = CommandCodeStructure::SET_ALGORITHM_SET.0, SetCommandCodeAuditStatus = CommandCodeStructure::SET_COMMAND_CODE_AUDIT_STATUS.0, FieldUpgradeData = CommandCodeStructure::FIELD_UPGRADE_DATA.0, IncrementalSelfTest = CommandCodeStructure::INCREMENTAL_SELF_TEST.0, SelfTest = CommandCodeStructure::SELF_TEST.0, Startup = CommandCodeStructure::STARTUP.0, Shutdown = CommandCodeStructure::SHUTDOWN.0, StirRandom = CommandCodeStructure::STIR_RANDOM.0, ActivateCredential = CommandCodeStructure::ACTIVATE_CREDENTIAL.0, Certify = CommandCodeStructure::CERTIFY.0, PolicyNv = CommandCodeStructure::POLICY_NV.0, CertifyCreation = CommandCodeStructure::CERTIFY_CREATION.0, Duplicate = CommandCodeStructure::DUPLICATE.0, GetTime = CommandCodeStructure::GET_TIME.0, GetSessionAuditDigest = CommandCodeStructure::GET_SESSION_AUDIT_DIGEST.0, NvRead = CommandCodeStructure::NV_READ.0, NvReadLock = CommandCodeStructure::NV_READ_LOCK.0, ObjectChangeAuth = CommandCodeStructure::OBJECT_CHANGE_AUTH.0, PolicySecret = CommandCodeStructure::POLICY_SECRET.0, Rewrap = CommandCodeStructure::REWRAP.0, Create = CommandCodeStructure::CREATE.0, EcdhZGen = CommandCodeStructure::ECDH_Z_GEN.0, Hmac = CommandCodeStructure::HMAC.0, Import = CommandCodeStructure::IMPORT.0, Load = CommandCodeStructure::LOAD.0, Quote = CommandCodeStructure::QUOTE.0, RsaDecrypt = CommandCodeStructure::RSA_DECRYPT.0, HmacStart = CommandCodeStructure::HMAC_START.0, SequenceUpdate = CommandCodeStructure::SEQUENCE_UPDATE.0, Sign = CommandCodeStructure::SIGN.0, Unseal = CommandCodeStructure::UNSEAL.0, PolicySigned = CommandCodeStructure::POLICY_SIGNED.0, ContextLoad = CommandCodeStructure::CONTEXT_LOAD.0, ContextSave = CommandCodeStructure::CONTEXT_SAVE.0, EcdhKeyGen = CommandCodeStructure::ECDH_KEY_GEN.0, EncryptDecrypt = CommandCodeStructure::ENCRYPT_DECRYPT.0, FlushContext = CommandCodeStructure::FLUSH_CONTEXT.0, LoadExternal = CommandCodeStructure::LOAD_EXTERNAL.0, MakeCredential = CommandCodeStructure::MAKE_CREDENTIAL.0, NvReadPublic = CommandCodeStructure::NV_READ_PUBLIC.0, PolicyAuthorize = CommandCodeStructure::POLICY_AUTHORIZE.0, PolicyAuthValue = CommandCodeStructure::POLICY_AUTH_VALUE.0, PolicyCommandCode = CommandCodeStructure::POLICY_COMMAND_CODE.0, PolicyCounterTimer = CommandCodeStructure::POLICY_COUNTER_TIMER.0, PolicyCpHash = CommandCodeStructure::POLICY_CP_HASH.0, PolicyLocality = CommandCodeStructure::POLICY_LOCALITY.0, PolicyNameHash = CommandCodeStructure::POLICY_NAME_HASH.0, PolicyOr = CommandCodeStructure::POLICY_OR.0, PolicyTicket = CommandCodeStructure::POLICY_TICKET.0, ReadPublic = CommandCodeStructure::READ_PUBLIC.0, RsaEncrypt = CommandCodeStructure::RSA_ENCRYPT.0, StartAuthSession = CommandCodeStructure::START_AUTH_SESSION.0, VerifySignature = CommandCodeStructure::VERIFY_SIGNATURE.0, EccParameters = CommandCodeStructure::ECC_PARAMETERS.0, FirmwareRead = CommandCodeStructure::FIRMWARE_READ.0, GetCapability = CommandCodeStructure::GET_CAPABILITY.0, GetRandom = CommandCodeStructure::GET_RANDOM.0, GetTestResult = CommandCodeStructure::GET_TEST_RESULT.0, Hash = CommandCodeStructure::HASH.0, PcrRead = CommandCodeStructure::PCR_READ.0, PolicyPcr = CommandCodeStructure::POLICY_PCR.0, PolicyRestart = CommandCodeStructure::POLICY_RESTART.0, ReadClock = CommandCodeStructure::READ_CLOCK.0, PcrExtend = CommandCodeStructure::PCR_EXTEND.0, PcrSetAuthValue = CommandCodeStructure::PCR_SET_AUTH_VALUE.0, NvCertify = CommandCodeStructure::NV_CERTIFY.0, EventSequenceComplete = CommandCodeStructure::EVENT_SEQUENCE_COMPLETE.0, HashSequenceStart = CommandCodeStructure::HASH_SEQUENCE_START.0, PolicyPhysicalPresence = CommandCodeStructure::POLICY_PHYSICAL_PRESENCE.0, PolicyDuplicationSelect = CommandCodeStructure::POLICY_DUPLICATION_SELECT.0, PolicyGetDigest = CommandCodeStructure::POLICY_GET_DIGEST.0, TestParms = CommandCodeStructure::TEST_PARMS.0, Commit = CommandCodeStructure::COMMIT.0, PolicyPassword = CommandCodeStructure::POLICY_PASSWORD.0, ZGen2Phase = CommandCodeStructure::Z_GEN_2_PHASE.0, EcEphemeral = CommandCodeStructure::EC_EPHEMERAL.0, PolicyNvWritten = CommandCodeStructure::POLICY_NV_WRITTEN.0, PolicyTemplate = CommandCodeStructure::POLICY_TEMPLATE.0, CreateLoaded = CommandCodeStructure::CREATE_LOADED.0, PolicyAuthorizeNv = CommandCodeStructure::POLICY_AUTHORIZE_NV.0, EncryptDecrypt2 = CommandCodeStructure::ENCRYPT_DECRYPT_2.0, AcGetCapability = CommandCodeStructure::AC_GET_CAPABILITY.0, AcSend = CommandCodeStructure::AC_SEND.0, PolicyAcSendSelect = CommandCodeStructure::POLICY_AC_SEND_SELECT.0, } impl TryFrom for CommandCode { type Error = Error; fn try_from(tpm2_cc: TPM2_CC) -> Result { CommandCode::from_u32(CommandCodeStructure::try_from(tpm2_cc)?.0).ok_or_else(|| { error!("Value = {} did not match any Command Code", tpm2_cc); Error::local_error(WrapperErrorKind::InvalidParam) }) } } impl From for TPM2_CC { fn from(command_code: CommandCode) -> Self { // The values are well defined so this cannot fail. command_code.to_u32().unwrap() } } tss-esapi-7.4.0/src/constants/ecc.rs000064400000000000000000000031241046102023000154470ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ constants::tss::{ TPM2_ECC_BN_P256, TPM2_ECC_BN_P638, TPM2_ECC_NIST_P192, TPM2_ECC_NIST_P224, TPM2_ECC_NIST_P256, TPM2_ECC_NIST_P384, TPM2_ECC_NIST_P521, TPM2_ECC_SM2_P256, }, tss2_esys::TPM2_ECC_CURVE, Error, Result, WrapperErrorKind, }; use log::error; use num_derive::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive}; use std::convert::TryFrom; /// Enum that contains the constants for the /// implemented elliptic curves. /// /// # Details /// This corresponds to `TPM2_ECC_CURVE` #[derive(FromPrimitive, ToPrimitive, Debug, Copy, Clone, PartialEq, Eq, Hash)] #[repr(u16)] pub enum EccCurveIdentifier { NistP192 = TPM2_ECC_NIST_P192, NistP224 = TPM2_ECC_NIST_P224, NistP256 = TPM2_ECC_NIST_P256, NistP384 = TPM2_ECC_NIST_P384, NistP521 = TPM2_ECC_NIST_P521, BnP256 = TPM2_ECC_BN_P256, BnP638 = TPM2_ECC_BN_P638, Sm2P256 = TPM2_ECC_SM2_P256, } impl From for TPM2_ECC_CURVE { fn from(curve: EccCurveIdentifier) -> Self { // The values are well defined so this cannot fail. curve.to_u16().unwrap() } } impl TryFrom for EccCurveIdentifier { type Error = Error; fn try_from(tpm2_ecc_curve: TPM2_ECC_CURVE) -> Result { EccCurveIdentifier::from_u16(tpm2_ecc_curve).ok_or_else(|| { error!("Value = {} did not match any ecc curve.", tpm2_ecc_curve); Error::local_error(WrapperErrorKind::InvalidParam) }) } } tss-esapi-7.4.0/src/constants/mod.rs000064400000000000000000000043401046102023000154750ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 /// This module contains both the constants defined in the TSS specification (tss module) /// but also the internal representation of the TSS constants. /// Representation of the constants defined in the /// Constants -> TPM_ALG_ID section of the specification mod algorithm; pub use algorithm::AlgorithmIdentifier; /// The constants defined in the TSS specification. #[allow( non_snake_case, non_camel_case_types, non_upper_case_globals, dead_code, clippy::all )] /// Exposes the constants form the TSS header. pub mod tss; /// Representation of the constants defined in the /// Constants -> TPM_ST section of the specification pub mod structure_tags; /// Representation of the constants defined in the /// Constants -> TPM_PT section of the specification pub mod property_tag; /// Representation of the constants defined in the /// Constants -> TPM_SU section of the specification pub mod startup_type; /// Representation of the constants defined in the /// Constants -> TPM_SE section of the specification pub mod session_type; /// Representation of the constants defined in the /// Constants -> TPM_CAP section of the specification pub mod capabilities; /// Representation of the return code TSS2_RC (TPM_RC) pub mod response_code; /// Representation of the constants defined in the /// NV Storage -> TPM_NT section of the specification pub mod nv_index_type; /// Representation of the constants defined in /// Constants -> TPM_ECC_CURVE section of the specification. pub mod ecc; /// Representation of the constants defined in /// Constants -> TPM_CC section of the specification. pub mod command_code; /// Representation of the constants defined in /// Constants -> TPM_PT_PCR section of the specification. pub mod pcr_property_tag; pub use capabilities::CapabilityType; pub use command_code::CommandCode; pub use ecc::EccCurveIdentifier; pub use nv_index_type::NvIndexType; pub use pcr_property_tag::PcrPropertyTag; pub use property_tag::PropertyTag; pub use response_code::{ResponseCode, Tss2ResponseCode, Tss2ResponseCodeKind}; pub use session_type::SessionType; pub use startup_type::StartupType; pub use structure_tags::StructureTag; tss-esapi-7.4.0/src/constants/nv_index_type.rs000064400000000000000000000032721046102023000175740ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ constants::tss::{ TPM2_NT_BITS, TPM2_NT_COUNTER, TPM2_NT_EXTEND, TPM2_NT_ORDINARY, TPM2_NT_PIN_FAIL, TPM2_NT_PIN_PASS, }, tss2_esys::TPM2_NT, Error, Result, WrapperErrorKind, }; use log::error; use std::convert::TryFrom; /// Enum with values representing the NV index type. #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum NvIndexType { Ordinary, Counter, Bits, Extend, PinFail, PinPass, } impl From for TPM2_NT { fn from(nv_index_type: NvIndexType) -> TPM2_NT { match nv_index_type { NvIndexType::Ordinary => TPM2_NT_ORDINARY, NvIndexType::Counter => TPM2_NT_COUNTER, NvIndexType::Bits => TPM2_NT_BITS, NvIndexType::Extend => TPM2_NT_EXTEND, NvIndexType::PinFail => TPM2_NT_PIN_FAIL, NvIndexType::PinPass => TPM2_NT_PIN_PASS, } } } impl TryFrom for NvIndexType { type Error = Error; fn try_from(tss_nv_index_type: TPM2_NT) -> Result { match tss_nv_index_type { TPM2_NT_ORDINARY => Ok(NvIndexType::Ordinary), TPM2_NT_COUNTER => Ok(NvIndexType::Counter), TPM2_NT_BITS => Ok(NvIndexType::Bits), TPM2_NT_EXTEND => Ok(NvIndexType::Extend), TPM2_NT_PIN_FAIL => Ok(NvIndexType::PinFail), TPM2_NT_PIN_PASS => Ok(NvIndexType::PinPass), _ => { error!("Found invalid value when trying to parse Nv Index Type"); Err(Error::local_error(WrapperErrorKind::InvalidParam)) } } } } tss-esapi-7.4.0/src/constants/pcr_property_tag.rs000064400000000000000000000036711046102023000203070ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ constants::tss::{ TPM2_PT_PCR_AUTH, TPM2_PT_PCR_DRTM_RESET, TPM2_PT_PCR_EXTEND_L0, TPM2_PT_PCR_EXTEND_L1, TPM2_PT_PCR_EXTEND_L2, TPM2_PT_PCR_EXTEND_L3, TPM2_PT_PCR_EXTEND_L4, TPM2_PT_PCR_NO_INCREMENT, TPM2_PT_PCR_POLICY, TPM2_PT_PCR_RESET_L0, TPM2_PT_PCR_RESET_L1, TPM2_PT_PCR_RESET_L2, TPM2_PT_PCR_RESET_L3, TPM2_PT_PCR_RESET_L4, TPM2_PT_PCR_SAVE, }, tss2_esys::TPM2_PT_PCR, Error, Result, WrapperErrorKind, }; use log::error; use num_derive::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive}; use std::convert::TryFrom; #[derive(FromPrimitive, ToPrimitive, Debug, Clone, Copy, PartialEq, Eq, Hash)] #[repr(u32)] pub enum PcrPropertyTag { Save = TPM2_PT_PCR_SAVE, ExtendL0 = TPM2_PT_PCR_EXTEND_L0, ResetL0 = TPM2_PT_PCR_RESET_L0, ExtendL1 = TPM2_PT_PCR_EXTEND_L1, ResetL1 = TPM2_PT_PCR_RESET_L1, ExtendL2 = TPM2_PT_PCR_EXTEND_L2, ResetL2 = TPM2_PT_PCR_RESET_L2, ExtendL3 = TPM2_PT_PCR_EXTEND_L3, ResetL3 = TPM2_PT_PCR_RESET_L3, ExtendL4 = TPM2_PT_PCR_EXTEND_L4, ResetL4 = TPM2_PT_PCR_RESET_L4, // Reserved 0x0000000B – 0x00000010 NoIncrement = TPM2_PT_PCR_NO_INCREMENT, DrtmReset = TPM2_PT_PCR_DRTM_RESET, Policy = TPM2_PT_PCR_POLICY, Auth = TPM2_PT_PCR_AUTH, } impl From for TPM2_PT_PCR { fn from(pcr_property_tag: PcrPropertyTag) -> Self { // The values are well defined so this cannot fail. pcr_property_tag.to_u32().unwrap() } } impl TryFrom for PcrPropertyTag { type Error = Error; fn try_from(tpm_pt_pcr: TPM2_PT_PCR) -> Result { PcrPropertyTag::from_u32(tpm_pt_pcr).ok_or_else(|| { error!("value = {} did not match any PcrPropertyTag.", tpm_pt_pcr); Error::local_error(WrapperErrorKind::InvalidParam) }) } } tss-esapi-7.4.0/src/constants/property_tag.rs000064400000000000000000000074071046102023000174440ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{constants::tss::*, tss2_esys::TPM2_PT, Error, Result, WrapperErrorKind}; use log::error; use num_derive::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive}; use std::convert::TryFrom; #[derive(FromPrimitive, ToPrimitive, Debug, Clone, Copy, PartialEq, Eq, Hash)] #[repr(u32)] pub enum PropertyTag { None = TPM2_PT_NONE, // Fixed FamilyIndicator = TPM2_PT_FAMILY_INDICATOR, Level = TPM2_PT_LEVEL, Revision = TPM2_PT_REVISION, DayOfYear = TPM2_PT_DAY_OF_YEAR, Year = TPM2_PT_YEAR, Manufacturer = TPM2_PT_MANUFACTURER, VendorString1 = TPM2_PT_VENDOR_STRING_1, VendorString2 = TPM2_PT_VENDOR_STRING_2, VendorString3 = TPM2_PT_VENDOR_STRING_3, VendorString4 = TPM2_PT_VENDOR_STRING_4, VendorTPMType = TPM2_PT_VENDOR_TPM_TYPE, FirmwareVersion1 = TPM2_PT_FIRMWARE_VERSION_1, FirmwareVersion2 = TPM2_PT_FIRMWARE_VERSION_2, InputBuffer = TPM2_PT_INPUT_BUFFER, HrTransientMin = TPM2_PT_HR_TRANSIENT_MIN, HrPersistentMin = TPM2_PT_HR_PERSISTENT_MIN, HrLoadedMin = TPM2_PT_HR_LOADED_MIN, ActiveSessionsMax = TPM2_PT_ACTIVE_SESSIONS_MAX, PcrCount = TPM2_PT_PCR_COUNT, PcrSelectMin = TPM2_PT_PCR_SELECT_MIN, ContextGapMax = TPM2_PT_CONTEXT_GAP_MAX, NvCountersMax = TPM2_PT_NV_COUNTERS_MAX, NvIndexMax = TPM2_PT_NV_INDEX_MAX, Memory = TPM2_PT_MEMORY, ClockUpdate = TPM2_PT_CLOCK_UPDATE, ContextHash = TPM2_PT_CONTEXT_HASH, ContextSym = TPM2_PT_CONTEXT_SYM, ContextSymSize = TPM2_PT_CONTEXT_SYM_SIZE, OrderlyCount = TPM2_PT_ORDERLY_COUNT, MaxCommandSize = TPM2_PT_MAX_COMMAND_SIZE, MaxResponseSize = TPM2_PT_MAX_RESPONSE_SIZE, MaxDigest = TPM2_PT_MAX_DIGEST, MaxObjectContext = TPM2_PT_MAX_OBJECT_CONTEXT, MaxSessionContext = TPM2_PT_MAX_SESSION_CONTEXT, PsFamilyIndicator = TPM2_PT_PS_FAMILY_INDICATOR, PsLevel = TPM2_PT_PS_LEVEL, PsRevision = TPM2_PT_PS_REVISION, PsDayOfYear = TPM2_PT_PS_DAY_OF_YEAR, PsYear = TPM2_PT_PS_YEAR, SplitMax = TPM2_PT_SPLIT_MAX, TotalCommands = TPM2_PT_TOTAL_COMMANDS, LibraryCommands = TPM2_PT_LIBRARY_COMMANDS, VendorCommands = TPM2_PT_VENDOR_COMMANDS, NvBufferMax = TPM2_PT_NV_BUFFER_MAX, Modes = TPM2_PT_MODES, MaxCapBuffer = TPM2_PT_MAX_CAP_BUFFER, // Variable Permanent = TPM2_PT_PERMANENT, StartupClear = TPM2_PT_STARTUP_CLEAR, HrNvIndex = TPM2_PT_HR_NV_INDEX, HrLoaded = TPM2_PT_HR_LOADED, HrLoadedAvail = TPM2_PT_HR_LOADED_AVAIL, HrActive = TPM2_PT_HR_ACTIVE, HrActiveAvail = TPM2_PT_HR_ACTIVE_AVAIL, HrTransientAvail = TPM2_PT_HR_TRANSIENT_AVAIL, HrPersistent = TPM2_PT_HR_PERSISTENT, HrPersistentAvail = TPM2_PT_HR_PERSISTENT_AVAIL, NvCounters = TPM2_PT_NV_COUNTERS, NvCountersAvail = TPM2_PT_NV_COUNTERS_AVAIL, AlgorithmSet = TPM2_PT_ALGORITHM_SET, LoadedCurves = TPM2_PT_LOADED_CURVES, LockoutCounter = TPM2_PT_LOCKOUT_COUNTER, MaxAuthFail = TPM2_PT_MAX_AUTH_FAIL, LockoutInterval = TPM2_PT_LOCKOUT_INTERVAL, LockoutRecovery = TPM2_PT_LOCKOUT_RECOVERY, WriteRecovery = TPM2_PT_NV_WRITE_RECOVERY, AuditCounter0 = TPM2_PT_AUDIT_COUNTER_0, AuditCounter1 = TPM2_PT_AUDIT_COUNTER_1, } impl From for TPM2_PT { fn from(property_tag: PropertyTag) -> TPM2_PT { // The values are well defined so this cannot fail. property_tag.to_u32().unwrap() } } impl TryFrom for PropertyTag { type Error = Error; fn try_from(tpm_pt: TPM2_PT) -> Result { PropertyTag::from_u32(tpm_pt).ok_or_else(|| { error!("value = {} did not match any PropertyTag.", tpm_pt); Error::local_error(WrapperErrorKind::InvalidParam) }) } } tss-esapi-7.4.0/src/constants/response_code.rs000064400000000000000000000651401046102023000175530ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! Module for error types //! //! This module provides the error reporting framework for the crate. Error provenience is marked //! as a variant of an enum, distinguishing between errors coming from the TSS stack and those //! generated by this crate. use crate::tss2_esys::TSS2_RC; use bitfield::bitfield; bitfield! { pub struct ResponseCode(TSS2_RC); impl Debug; format_selector, _: 7; } bitfield! { #[derive(PartialEq, Eq, Copy, Clone)] pub struct FormatZeroResponseCode(TSS2_RC); impl Debug; error_number, _: 6, 0; format_selector, _: 7; version, _: 8; tcg_vendor_indicator, _: 10; severity, _: 11; } impl std::fmt::Display for FormatZeroResponseCode { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { // Display response code as "Response code value: 0xdeadbeef" write!(f, "Response code value: {:#x}", self.0) } } impl std::error::Error for FormatZeroResponseCode {} bitfield! { #[derive(PartialEq, Eq, Copy, Clone)] pub struct FormatOneResponseCode(TSS2_RC); impl Debug; error_number, _: 5, 0; parameter, _: 6; format_selector, _: 7; number, _: 11, 8; } impl std::fmt::Display for FormatOneResponseCode { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { // Display response code as "Response code value: 0xdeadbeef" write!(f, "Response code value: {:#x}", self.0) } } impl std::error::Error for FormatOneResponseCode {} /// Rust native representation of the TSS2 response codes as defined in the spec. #[allow(clippy::module_name_repetitions)] #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum Tss2ResponseCode { Success, FormatZero(FormatZeroResponseCode), FormatOne(FormatOneResponseCode), } impl Tss2ResponseCode { /// Generate a `Tss2ResponseCode` from a TSS error pub(crate) fn from_tss_rc(response_code: TSS2_RC) -> Self { if response_code == 0 { Tss2ResponseCode::Success } else if ResponseCode(response_code).format_selector() { // The response code is in Format-One. Tss2ResponseCode::FormatOne(FormatOneResponseCode(response_code)) } else { // The response code is in Format-Zero. Tss2ResponseCode::FormatZero(FormatZeroResponseCode(response_code)) } } /// Check whether the response code is successful pub fn is_success(self) -> bool { self == Tss2ResponseCode::Success } fn is_warning(self) -> bool { match self { Tss2ResponseCode::Success => false, Tss2ResponseCode::FormatZero(rc) => rc.severity(), Tss2ResponseCode::FormatOne(_) => false, } } fn error_number(self) -> u32 { match self { Tss2ResponseCode::Success => 0, Tss2ResponseCode::FormatZero(rc) => rc.error_number(), Tss2ResponseCode::FormatOne(rc) => rc.error_number(), } } fn get_associated_number_message(self) -> String { if let Tss2ResponseCode::FormatOne(rc) = self { if rc.parameter() { format!("associated with parameter number {}", rc.number()) } else if rc.number() <= 0b0111 { format!("associated with handle number {}", rc.number()) } else { format!("associated with session number {}", rc.number() - 8) } } else { String::from("no associated message") } } /// Get the error code as an enum variant. pub fn kind(self) -> Option { match self { Tss2ResponseCode::Success => Some(Tss2ResponseCodeKind::Success), Tss2ResponseCode::FormatZero(rc) => { if rc.tcg_vendor_indicator() { Some(Tss2ResponseCodeKind::TpmVendorSpecific) } else if self.is_warning() { // Warnings match self.error_number() { 0x001 => Some(Tss2ResponseCodeKind::ContextGap), 0x002 => Some(Tss2ResponseCodeKind::ObjectMemory), 0x003 => Some(Tss2ResponseCodeKind::SessionMemory), 0x004 => Some(Tss2ResponseCodeKind::Memory), 0x005 => Some(Tss2ResponseCodeKind::SessionHandles), 0x006 => Some(Tss2ResponseCodeKind::ObjectHandles), 0x007 => Some(Tss2ResponseCodeKind::Locality), 0x008 => Some(Tss2ResponseCodeKind::Yielded), 0x009 => Some(Tss2ResponseCodeKind::Canceled), 0x00A => Some(Tss2ResponseCodeKind::Testing), 0x010 => Some(Tss2ResponseCodeKind::ReferenceH0), 0x011 => Some(Tss2ResponseCodeKind::ReferenceH1), 0x012 => Some(Tss2ResponseCodeKind::ReferenceH2), 0x013 => Some(Tss2ResponseCodeKind::ReferenceH3), 0x014 => Some(Tss2ResponseCodeKind::ReferenceH4), 0x015 => Some(Tss2ResponseCodeKind::ReferenceH5), 0x016 => Some(Tss2ResponseCodeKind::ReferenceH6), 0x018 => Some(Tss2ResponseCodeKind::ReferenceS0), 0x019 => Some(Tss2ResponseCodeKind::ReferenceS1), 0x01A => Some(Tss2ResponseCodeKind::ReferenceS2), 0x01B => Some(Tss2ResponseCodeKind::ReferenceS3), 0x01C => Some(Tss2ResponseCodeKind::ReferenceS4), 0x01D => Some(Tss2ResponseCodeKind::ReferenceS5), 0x01E => Some(Tss2ResponseCodeKind::ReferenceS6), 0x020 => Some(Tss2ResponseCodeKind::NvRate), 0x021 => Some(Tss2ResponseCodeKind::Lockout), 0x022 => Some(Tss2ResponseCodeKind::Retry), 0x023 => Some(Tss2ResponseCodeKind::NvUnavailable), _ => None, } } else { // Errors match self.error_number() { 0x000 => Some(Tss2ResponseCodeKind::Initialize), 0x001 => Some(Tss2ResponseCodeKind::Failure), 0x003 => Some(Tss2ResponseCodeKind::Sequence), 0x00B => Some(Tss2ResponseCodeKind::Private), 0x019 => Some(Tss2ResponseCodeKind::Hmac), 0x020 => Some(Tss2ResponseCodeKind::Disabled), 0x021 => Some(Tss2ResponseCodeKind::Exclusive), 0x024 => Some(Tss2ResponseCodeKind::AuthType), 0x025 => Some(Tss2ResponseCodeKind::AuthMissing), 0x026 => Some(Tss2ResponseCodeKind::Policy), 0x027 => Some(Tss2ResponseCodeKind::Pcr), 0x028 => Some(Tss2ResponseCodeKind::PcrChanged), 0x02D => Some(Tss2ResponseCodeKind::Upgrade), 0x02E => Some(Tss2ResponseCodeKind::TooManyContexts), 0x02F => Some(Tss2ResponseCodeKind::AuthUnavailable), 0x030 => Some(Tss2ResponseCodeKind::Reboot), 0x031 => Some(Tss2ResponseCodeKind::Unbalanced), 0x042 => Some(Tss2ResponseCodeKind::CommandSize), 0x043 => Some(Tss2ResponseCodeKind::CommandCode), 0x044 => Some(Tss2ResponseCodeKind::AuthSize), 0x045 => Some(Tss2ResponseCodeKind::AuthContext), 0x046 => Some(Tss2ResponseCodeKind::NvRange), 0x047 => Some(Tss2ResponseCodeKind::NvSize), 0x048 => Some(Tss2ResponseCodeKind::NvLocked), 0x049 => Some(Tss2ResponseCodeKind::NvAuthorization), 0x04A => Some(Tss2ResponseCodeKind::NvUninitialized), 0x04B => Some(Tss2ResponseCodeKind::NvSpace), 0x04C => Some(Tss2ResponseCodeKind::NvDefined), 0x050 => Some(Tss2ResponseCodeKind::BadContext), 0x051 => Some(Tss2ResponseCodeKind::CpHash), 0x052 => Some(Tss2ResponseCodeKind::Parent), 0x053 => Some(Tss2ResponseCodeKind::NeedsTest), 0x054 => Some(Tss2ResponseCodeKind::NoResult), 0x055 => Some(Tss2ResponseCodeKind::Sensitive), _ => None, } } } Tss2ResponseCode::FormatOne(_) => match self.error_number() { 0x001 => Some(Tss2ResponseCodeKind::Asymmetric), 0x002 => Some(Tss2ResponseCodeKind::Attributes), 0x003 => Some(Tss2ResponseCodeKind::Hash), 0x004 => Some(Tss2ResponseCodeKind::Value), 0x005 => Some(Tss2ResponseCodeKind::Hierarchy), 0x007 => Some(Tss2ResponseCodeKind::KeySize), 0x008 => Some(Tss2ResponseCodeKind::Mgf), 0x009 => Some(Tss2ResponseCodeKind::Mode), 0x00A => Some(Tss2ResponseCodeKind::Type), 0x00B => Some(Tss2ResponseCodeKind::Handle), 0x00C => Some(Tss2ResponseCodeKind::Kdf), 0x00D => Some(Tss2ResponseCodeKind::Range), 0x00E => Some(Tss2ResponseCodeKind::AuthFail), 0x00F => Some(Tss2ResponseCodeKind::Nonce), 0x010 => Some(Tss2ResponseCodeKind::Pp), 0x012 => Some(Tss2ResponseCodeKind::Scheme), 0x015 => Some(Tss2ResponseCodeKind::Size), 0x016 => Some(Tss2ResponseCodeKind::Symmetric), 0x017 => Some(Tss2ResponseCodeKind::Tag), 0x018 => Some(Tss2ResponseCodeKind::Selector), 0x01A => Some(Tss2ResponseCodeKind::Insufficient), 0x01B => Some(Tss2ResponseCodeKind::Signature), 0x01C => Some(Tss2ResponseCodeKind::Key), 0x01D => Some(Tss2ResponseCodeKind::PolicyFail), 0x01F => Some(Tss2ResponseCodeKind::Integrity), 0x020 => Some(Tss2ResponseCodeKind::Ticket), 0x021 => Some(Tss2ResponseCodeKind::ReservedBits), 0x022 => Some(Tss2ResponseCodeKind::BadAuth), 0x023 => Some(Tss2ResponseCodeKind::Expired), 0x024 => Some(Tss2ResponseCodeKind::PolicyCc), 0x025 => Some(Tss2ResponseCodeKind::Binding), 0x026 => Some(Tss2ResponseCodeKind::Curve), 0x027 => Some(Tss2ResponseCodeKind::EccPoint), _ => None, }, } } } /// Rust enum representation of TSS 2 error codes. #[derive(PartialEq, Eq, Copy, Clone, Debug)] pub enum Tss2ResponseCodeKind { // FormatZero errors Success, TpmVendorSpecific, Initialize, Failure, Sequence, Private, Hmac, Disabled, Exclusive, AuthType, AuthMissing, Policy, Pcr, PcrChanged, Upgrade, TooManyContexts, AuthUnavailable, Reboot, Unbalanced, CommandSize, CommandCode, AuthSize, AuthContext, NvRange, NvSize, NvLocked, NvAuthorization, NvUninitialized, NvSpace, NvDefined, BadContext, CpHash, Parent, NeedsTest, NoResult, Sensitive, // FormatOne errors Asymmetric, Attributes, Hash, Value, Hierarchy, KeySize, Mgf, Mode, Type, Handle, Kdf, Range, AuthFail, Nonce, Pp, Scheme, Size, Symmetric, Tag, Selector, Insufficient, Signature, Key, PolicyFail, Integrity, Ticket, ReservedBits, BadAuth, Expired, PolicyCc, Binding, Curve, EccPoint, // Warnings ContextGap, ObjectMemory, SessionMemory, Memory, SessionHandles, ObjectHandles, Locality, Yielded, Canceled, Testing, ReferenceH0, ReferenceH1, ReferenceH2, ReferenceH3, ReferenceH4, ReferenceH5, ReferenceH6, ReferenceS0, ReferenceS1, ReferenceS2, ReferenceS3, ReferenceS4, ReferenceS5, ReferenceS6, NvRate, Lockout, Retry, NvUnavailable, } impl std::fmt::Display for Tss2ResponseCode { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let kind = self.kind(); if kind.is_none() { return write!(f, "response code not recognized"); } match self.kind().unwrap() { // should not panic, given the check above Tss2ResponseCodeKind::Success => write!(f, "success"), Tss2ResponseCodeKind::TpmVendorSpecific => write!(f, "vendor specific error: {}", self.error_number()), // Format Zero Tss2ResponseCodeKind::Initialize => write!(f, "TPM not initialized by TPM2_Startup or already initialized"), Tss2ResponseCodeKind::Failure => write!(f, "commands not being accepted because of a TPM failure. NOTE: This may be returned by TPM2_GetTestResult() as the testResultparameter"), Tss2ResponseCodeKind::Sequence => write!(f, "improper use of a sequence handle"), Tss2ResponseCodeKind::Private => write!(f, "not currently used"), Tss2ResponseCodeKind::Hmac => write!(f, "not currently used"), Tss2ResponseCodeKind::Disabled => write!(f, "the command is disabled"), Tss2ResponseCodeKind::Exclusive => write!(f, "command failed because audit sequence required exclusivity"), Tss2ResponseCodeKind::AuthType => write!(f, "authorization handle is not correct for command"), Tss2ResponseCodeKind::AuthMissing => write!(f, "command requires an authorization session for handle and it is not present"), Tss2ResponseCodeKind::Policy => write!(f, "policy failure in math operation or an invalid authPolicy value"), Tss2ResponseCodeKind::Pcr => write!(f, "PCR check fail"), Tss2ResponseCodeKind::PcrChanged => write!(f, "PCR have changed since checked"), Tss2ResponseCodeKind::Upgrade => write!(f, "for all commands other than TPM2_FieldUpgradeData(), this code indicates that the TPM is in field upgrade mode; for TPM2_FieldUpgradeData(), this code indicates that the TPM is not in field upgrade mode"), Tss2ResponseCodeKind::TooManyContexts => write!(f, "context ID counter is at maximum"), Tss2ResponseCodeKind::AuthUnavailable => write!(f, "authValue or authPolicy is not available for selected entity"), Tss2ResponseCodeKind::Reboot => write!(f, "a _TPM_Init and Startup(CLEAR) is required before the TPM can resume operation"), Tss2ResponseCodeKind::Unbalanced => write!(f, "the protection algorithms (hash and symmetric) are not reasonably balanced. The digest size of the hash must be larger than the key size of the symmetric algorithm"), Tss2ResponseCodeKind::CommandSize => write!(f, "command commandSizevalue is inconsistent with contents of the command buffer; either the size is not the same as the octets loaded by the hardware interface layer or the value is not large enough to hold a command header"), Tss2ResponseCodeKind::CommandCode => write!(f, "command code not supported"), Tss2ResponseCodeKind::AuthSize => write!(f, "the value of authorizationSizeis out of range or the number of octets in the Authorization Area is greater than required"), Tss2ResponseCodeKind::AuthContext => write!(f, "use of an authorization session with a context command or another command that cannot have an authorization session"), Tss2ResponseCodeKind::NvRange => write!(f, "NV offset+size is out of range"), Tss2ResponseCodeKind::NvSize => write!(f, "Requested allocation size is larger than allowed"), Tss2ResponseCodeKind::NvLocked => write!(f, "NV access locked"), Tss2ResponseCodeKind::NvAuthorization => write!(f, "NV access authorization fails in command actions (this failure does not affect lockout.action)"), Tss2ResponseCodeKind::NvUninitialized => write!(f, "an NV Index is used before being initialized or the state saved by TPM2_Shutdown(STATE) could not be restored"), Tss2ResponseCodeKind::NvSpace => write!(f, "insufficient space for NV allocation"), Tss2ResponseCodeKind::NvDefined => write!(f, "NV Index or persistent object already defined"), Tss2ResponseCodeKind::BadContext => write!(f, "context in TPM2_ContextLoad() is not valid"), Tss2ResponseCodeKind::CpHash => write!(f, "cpHash value already set or not correct for use"), Tss2ResponseCodeKind::Parent => write!(f, "handle for parent is not a valid parent"), Tss2ResponseCodeKind::NeedsTest => write!(f, "some function needs testing."), Tss2ResponseCodeKind::NoResult => write!(f, "returned when an internal function cannot process a request due to an unspecified problem. This code is usually related to invalid parameters that are not properly filtered by the input unmarshaling code."), Tss2ResponseCodeKind::Sensitive => write!(f, "the sensitive area did not unmarshal correctly after decryption – this code is used in lieu of the other unmarshaling errors so that an attacker cannot determine where the unmarshaling error occurred"), // Warnings Tss2ResponseCodeKind::ContextGap => write!(f, "gap for context ID is too large"), Tss2ResponseCodeKind::ObjectMemory => write!(f, "out of memory for object contexts"), Tss2ResponseCodeKind::SessionMemory => write!(f, "out of memory for session contexts"), Tss2ResponseCodeKind::Memory => write!(f, "out of shared object/session memory or need space for internal operations"), Tss2ResponseCodeKind::SessionHandles => write!(f, "out of session handles – a session must be flushed before a new session may be created"), Tss2ResponseCodeKind::ObjectHandles => write!(f, "out of object handles – the handle space for objects is depleted and a reboot is required. NOTE 1: This cannot occur on the reference implementation. NOTE 2: There is no reason why an implementation would implement a design that would delete handle space. Platform specifications are encouraged to forbid it."), Tss2ResponseCodeKind::Locality => write!(f, "bad locality"), Tss2ResponseCodeKind::Yielded => write!(f, "the TPM has suspended operation on the command; forward progress was made and the command may be retried. See TPM 2.0 Part 1, “Multi-tasking.” NOTE: This cannot occur on the reference implementation."), Tss2ResponseCodeKind::Canceled => write!(f, "the command was canceled"), Tss2ResponseCodeKind::Testing => write!(f, "TPM is performing self-tests"), Tss2ResponseCodeKind::ReferenceH0 => write!(f, "the 1st handle in the handle area references a transient object or session that is not loaded"), Tss2ResponseCodeKind::ReferenceH1 => write!(f, "the 2nd handle in the handle area references a transient object or session that is not loaded"), Tss2ResponseCodeKind::ReferenceH2 => write!(f, "the 3rd handle in the handle area references a transient object or session that is not loaded"), Tss2ResponseCodeKind::ReferenceH3 => write!(f, "the 4th handle in the handle area references a transient object or session that is not loaded"), Tss2ResponseCodeKind::ReferenceH4 => write!(f, "the 5th handle in the handle area references a transient object or session that is not loaded"), Tss2ResponseCodeKind::ReferenceH5 => write!(f, "the 6th handle in the handle area references a transient object or session that is not loaded"), Tss2ResponseCodeKind::ReferenceH6 => write!(f, "the 7th handle in the handle area references a transient object or session that is not loaded"), Tss2ResponseCodeKind::ReferenceS0 => write!(f, "the 1st authorization session handle references a session that is not loaded"), Tss2ResponseCodeKind::ReferenceS1 => write!(f, "the 2nd authorization session handle references a session that is not loaded"), Tss2ResponseCodeKind::ReferenceS2 => write!(f, "the 3rd authorization session handle references a session that is not loaded"), Tss2ResponseCodeKind::ReferenceS3 => write!(f, "the 4th authorization session handle references a session that is not loaded"), Tss2ResponseCodeKind::ReferenceS4 => write!(f, "the 5th session handle references a session that is not loaded"), Tss2ResponseCodeKind::ReferenceS5 => write!(f, "the 6th session handle references a session that is not loaded"), Tss2ResponseCodeKind::ReferenceS6 => write!(f, "the 7th authorization session handle references a session that is not loaded"), Tss2ResponseCodeKind::NvRate => write!(f, "the TPM is rate-limiting accesses to prevent wearout of NV"), Tss2ResponseCodeKind::Lockout => write!(f, "authorizations for objects subject to DA protection are not allowed at this time because the TPM is in DA lockout mode"), Tss2ResponseCodeKind::Retry => write!(f, "the TPM was not able to start the command"), Tss2ResponseCodeKind::NvUnavailable => write!(f, "the command may require writing of NV and NV is not current accessible"), // Format-One Tss2ResponseCodeKind::Asymmetric => write!(f, "asymmetric algorithm not supported or not correct ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::Attributes => write!(f, "inconsistent attributes ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::Hash => write!(f, "hash algorithm not supported or not appropriate ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::Value => write!(f, "value is out of range or is not correct for the context ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::Hierarchy => write!(f, "hierarchy is not enabled or is not correct for the use ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::KeySize => write!(f, "key size is not supported ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::Mgf => write!(f, "mask generation function not supported ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::Mode => write!(f, "mode of operation not supported ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::Type => write!(f, "the type of the value is not appropriate for the use ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::Handle => write!(f, "the handle is not correct for the use ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::Kdf => write!(f, "unsupported key derivation function or function not appropriate for use ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::Range => write!(f, "value was out of allowed range. ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::AuthFail => write!(f, "the authorization HMAC check failed and DA counter incremented ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::Nonce => write!(f, "invalid nonce size or nonce value mismatch ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::Pp => write!(f, "authorization requires assertion of PP ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::Scheme => write!(f, "unsupported or incompatible scheme ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::Size => write!(f, "structure is the wrong size ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::Symmetric => write!(f, "unsupported symmetric algorithm or key size, or not appropriate for instance ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::Tag => write!(f, "incorrect structure tag ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::Selector => write!(f, "union selector is incorrect ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::Insufficient => write!(f, "the TPM was unable to unmarshal a value because there were not enough octets in the input buffer ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::Signature => write!(f, "the signature is not valid ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::Key => write!(f, "key fields are not compatible with the selected use ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::PolicyFail => write!(f, "a policy check failed ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::Integrity => write!(f, "integrity check failed ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::Ticket => write!(f, "invalid ticket ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::ReservedBits => write!(f, "reserved bits not set to zero as required ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::BadAuth => write!(f, "authorization failure without DA implications ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::Expired => write!(f, "the policy has expired ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::PolicyCc => write!(f, "the command Code in the policy is not the command Code of the command or the command code in a policy command references a command that is not implemented ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::Binding => write!(f, "public and sensitive portions of an object are not cryptographically bound ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::Curve => write!(f, "curve not supported ({})", self.get_associated_number_message()), Tss2ResponseCodeKind::EccPoint => write!(f, "point is not on the required curve ({})", self.get_associated_number_message()), } } } impl From for Tss2ResponseCode { fn from(rc: TSS2_RC) -> Self { Tss2ResponseCode::from_tss_rc(rc) } } impl std::error::Error for Tss2ResponseCode { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self { Tss2ResponseCode::FormatOne(response_code) => Some(response_code), Tss2ResponseCode::FormatZero(response_code) => Some(response_code), Tss2ResponseCode::Success => None, } } } tss-esapi-7.4.0/src/constants/session_type.rs000064400000000000000000000023061046102023000174420ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ constants::tss::{TPM2_SE_HMAC, TPM2_SE_POLICY, TPM2_SE_TRIAL}, tss2_esys::TPM2_SE, Error, Result, WrapperErrorKind, }; use log::error; use num_derive::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive}; use std::convert::TryFrom; /// Enum representing the different TPM session types. #[derive(FromPrimitive, ToPrimitive, Debug, Copy, Clone, PartialEq, Eq)] #[repr(u8)] pub enum SessionType { Hmac = TPM2_SE_HMAC, Policy = TPM2_SE_POLICY, Trial = TPM2_SE_TRIAL, } impl From for TPM2_SE { fn from(session_type: SessionType) -> TPM2_SE { // The values are well defined so this cannot fail. session_type.to_u8().unwrap() } } impl TryFrom for SessionType { type Error = Error; fn try_from(tpm_session_type: TPM2_SE) -> Result { SessionType::from_u8(tpm_session_type).ok_or_else(|| { error!( "value = {} did not match any SessionType.", tpm_session_type ); Error::local_error(WrapperErrorKind::InvalidParam) }) } } tss-esapi-7.4.0/src/constants/startup_type.rs000064400000000000000000000022421046102023000174600ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ constants::tss::{TPM2_SU_CLEAR, TPM2_SU_STATE}, tss2_esys::TPM2_SU, Error, Result, WrapperErrorKind, }; use log::error; use num_derive::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive}; use std::convert::TryFrom; /// Enum repsenting the different TPM Startup Type values. #[derive(FromPrimitive, ToPrimitive, Debug, Copy, Clone, PartialEq, Eq)] #[repr(u16)] pub enum StartupType { Clear = TPM2_SU_CLEAR, State = TPM2_SU_STATE, } impl From for TPM2_SU { fn from(startup_type: StartupType) -> TPM2_SU { // The values are well defined so this cannot fail. startup_type.to_u16().unwrap() } } impl TryFrom for StartupType { type Error = Error; fn try_from(tpm_startup_type: TPM2_SU) -> Result { StartupType::from_u16(tpm_startup_type).ok_or_else(|| { error!( "value = {} did not match any StartupType.", tpm_startup_type ); Error::local_error(WrapperErrorKind::InvalidParam) }) } } tss-esapi-7.4.0/src/constants/structure_tags.rs000064400000000000000000000044361046102023000200020ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::constants::tss::{ TPM2_ST_ATTEST_CERTIFY, TPM2_ST_ATTEST_COMMAND_AUDIT, TPM2_ST_ATTEST_CREATION, TPM2_ST_ATTEST_NV, TPM2_ST_ATTEST_NV_DIGEST, TPM2_ST_ATTEST_QUOTE, TPM2_ST_ATTEST_SESSION_AUDIT, TPM2_ST_ATTEST_TIME, TPM2_ST_AUTH_SECRET, TPM2_ST_AUTH_SIGNED, TPM2_ST_CREATION, TPM2_ST_FU_MANIFEST, TPM2_ST_HASHCHECK, TPM2_ST_NO_SESSIONS, TPM2_ST_NULL, TPM2_ST_RSP_COMMAND, TPM2_ST_SESSIONS, TPM2_ST_VERIFIED, }; use crate::{tss2_esys::TPM2_ST, Error, Result, WrapperErrorKind}; use log::error; use num_derive::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive}; use std::convert::TryFrom; /// This enum represents the TPM_ST (Structure Tags) #[derive(FromPrimitive, ToPrimitive, Copy, Clone, Debug, PartialEq, Eq, Hash)] #[repr(u16)] pub enum StructureTag { RspCommand = TPM2_ST_RSP_COMMAND, Null = TPM2_ST_NULL, NoSessions = TPM2_ST_NO_SESSIONS, Sessions = TPM2_ST_SESSIONS, // Reserved1 = TPM2_ST_RESERVED1, // Reserved2 = TPM2_ST_RESERVED2, AttestNv = TPM2_ST_ATTEST_NV, AttestCommandAudit = TPM2_ST_ATTEST_COMMAND_AUDIT, AttestSessionAudit = TPM2_ST_ATTEST_SESSION_AUDIT, AttestCertify = TPM2_ST_ATTEST_CERTIFY, AttestQuote = TPM2_ST_ATTEST_QUOTE, AttestTime = TPM2_ST_ATTEST_TIME, AttestCreation = TPM2_ST_ATTEST_CREATION, // Reserved3 = TPM2_ST_RESERVED3, AttestNvDigest = TPM2_ST_ATTEST_NV_DIGEST, Creation = TPM2_ST_CREATION, Verified = TPM2_ST_VERIFIED, AuthSecret = TPM2_ST_AUTH_SECRET, Hashcheck = TPM2_ST_HASHCHECK, AuthSigned = TPM2_ST_AUTH_SIGNED, FuManifest = TPM2_ST_FU_MANIFEST, } impl TryFrom for StructureTag { type Error = Error; fn try_from(tpm_structure_tag: TPM2_ST) -> Result { StructureTag::from_u16(tpm_structure_tag).ok_or_else(|| { error!( "value = {} did not match any StructureTag.", tpm_structure_tag ); Error::local_error(WrapperErrorKind::InvalidParam) }) } } impl From for TPM2_ST { fn from(structure_tag: StructureTag) -> Self { // The values are well defined so this cannot fail. structure_tag.to_u16().unwrap() } } tss-esapi-7.4.0/src/constants/tss.rs000064400000000000000000002224371046102023000155400ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::tss2_esys::*; pub const TPM2_ALG_ERROR: TPM2_ALG_ID = 0x0000; pub const TPM2_ALG_RSA: TPM2_ALG_ID = 0x0001; pub const TPM2_ALG_TDES: TPM2_ALG_ID = 0x0003; pub const TPM2_ALG_SHA: TPM2_ALG_ID = 0x0004; pub const TPM2_ALG_SHA1: TPM2_ALG_ID = 0x0004; pub const TPM2_ALG_HMAC: TPM2_ALG_ID = 0x0005; pub const TPM2_ALG_AES: TPM2_ALG_ID = 0x0006; pub const TPM2_ALG_MGF1: TPM2_ALG_ID = 0x0007; pub const TPM2_ALG_KEYEDHASH: TPM2_ALG_ID = 0x0008; pub const TPM2_ALG_XOR: TPM2_ALG_ID = 0x000A; pub const TPM2_ALG_SHA256: TPM2_ALG_ID = 0x000B; pub const TPM2_ALG_SHA384: TPM2_ALG_ID = 0x000C; pub const TPM2_ALG_SHA512: TPM2_ALG_ID = 0x000D; pub const TPM2_ALG_NULL: TPM2_ALG_ID = 0x0010; pub const TPM2_ALG_SM3_256: TPM2_ALG_ID = 0x0012; pub const TPM2_ALG_SM4: TPM2_ALG_ID = 0x0013; pub const TPM2_ALG_RSASSA: TPM2_ALG_ID = 0x0014; pub const TPM2_ALG_RSAES: TPM2_ALG_ID = 0x0015; pub const TPM2_ALG_RSAPSS: TPM2_ALG_ID = 0x0016; pub const TPM2_ALG_OAEP: TPM2_ALG_ID = 0x0017; pub const TPM2_ALG_ECDSA: TPM2_ALG_ID = 0x0018; pub const TPM2_ALG_ECDH: TPM2_ALG_ID = 0x0019; pub const TPM2_ALG_ECDAA: TPM2_ALG_ID = 0x001A; pub const TPM2_ALG_SM2: TPM2_ALG_ID = 0x001B; pub const TPM2_ALG_ECSCHNORR: TPM2_ALG_ID = 0x001C; pub const TPM2_ALG_ECMQV: TPM2_ALG_ID = 0x001D; pub const TPM2_ALG_KDF1_SP800_56A: TPM2_ALG_ID = 0x0020; pub const TPM2_ALG_KDF2: TPM2_ALG_ID = 0x0021; pub const TPM2_ALG_KDF1_SP800_108: TPM2_ALG_ID = 0x0022; pub const TPM2_ALG_ECC: TPM2_ALG_ID = 0x0023; pub const TPM2_ALG_SYMCIPHER: TPM2_ALG_ID = 0x0025; pub const TPM2_ALG_CAMELLIA: TPM2_ALG_ID = 0x0026; pub const TPM2_ALG_CMAC: TPM2_ALG_ID = 0x003F; pub const TPM2_ALG_CTR: TPM2_ALG_ID = 0x0040; pub const TPM2_ALG_SHA3_256: TPM2_ALG_ID = 0x0027; pub const TPM2_ALG_SHA3_384: TPM2_ALG_ID = 0x0028; pub const TPM2_ALG_SHA3_512: TPM2_ALG_ID = 0x0029; pub const TPM2_ALG_OFB: TPM2_ALG_ID = 0x0041; pub const TPM2_ALG_CBC: TPM2_ALG_ID = 0x0042; pub const TPM2_ALG_CFB: TPM2_ALG_ID = 0x0043; pub const TPM2_ALG_ECB: TPM2_ALG_ID = 0x0044; pub const TPM2_ALG_FIRST: TPM2_ALG_ID = 0x0001; pub const TPM2_ALG_LAST: TPM2_ALG_ID = 0x0044; pub const TPM2_ECC_NONE: TPM2_ECC_CURVE = 0x0000; pub const TPM2_ECC_NIST_P192: TPM2_ECC_CURVE = 0x0001; pub const TPM2_ECC_NIST_P224: TPM2_ECC_CURVE = 0x0002; pub const TPM2_ECC_NIST_P256: TPM2_ECC_CURVE = 0x0003; pub const TPM2_ECC_NIST_P384: TPM2_ECC_CURVE = 0x0004; pub const TPM2_ECC_NIST_P521: TPM2_ECC_CURVE = 0x0005; pub const TPM2_ECC_BN_P256: TPM2_ECC_CURVE = 0x0010; pub const TPM2_ECC_BN_P638: TPM2_ECC_CURVE = 0x0011; pub const TPM2_ECC_SM2_P256: TPM2_ECC_CURVE = 0x0020; pub const TPM2_CC_NV_UndefineSpaceSpecial: TPM2_CC = 0x0000011f; pub const TPM2_CC_FIRST: TPM2_CC = TPM2_CC_NV_UndefineSpaceSpecial; pub const TPM2_CC_EvictControl: TPM2_CC = 0x00000120; pub const TPM2_CC_HierarchyControl: TPM2_CC = 0x00000121; pub const TPM2_CC_NV_UndefineSpace: TPM2_CC = 0x00000122; pub const TPM2_CC_ChangeEPS: TPM2_CC = 0x00000124; pub const TPM2_CC_ChangePPS: TPM2_CC = 0x00000125; pub const TPM2_CC_Clear: TPM2_CC = 0x00000126; pub const TPM2_CC_ClearControl: TPM2_CC = 0x00000127; pub const TPM2_CC_ClockSet: TPM2_CC = 0x00000128; pub const TPM2_CC_HierarchyChangeAuth: TPM2_CC = 0x00000129; pub const TPM2_CC_NV_DefineSpace: TPM2_CC = 0x0000012a; pub const TPM2_CC_PCR_Allocate: TPM2_CC = 0x0000012b; pub const TPM2_CC_PCR_SetAuthPolicy: TPM2_CC = 0x00000012c; pub const TPM2_CC_PP_Commands: TPM2_CC = 0x0000012d; pub const TPM2_CC_SetPrimaryPolicy: TPM2_CC = 0x0000012e; pub const TPM2_CC_FieldUpgradeStart: TPM2_CC = 0x0000012f; pub const TPM2_CC_ClockRateAdjust: TPM2_CC = 0x00000130; pub const TPM2_CC_CreatePrimary: TPM2_CC = 0x00000131; pub const TPM2_CC_NV_GlobalWriteLock: TPM2_CC = 0x00000132; pub const TPM2_CC_GetCommandAuditDigest: TPM2_CC = 0x00000133; pub const TPM2_CC_NV_Increment: TPM2_CC = 0x00000134; pub const TPM2_CC_NV_SetBits: TPM2_CC = 0x00000135; pub const TPM2_CC_NV_Extend: TPM2_CC = 0x00000136; pub const TPM2_CC_NV_Write: TPM2_CC = 0x00000137; pub const TPM2_CC_NV_WriteLock: TPM2_CC = 0x00000138; pub const TPM2_CC_DictionaryAttackLockReset: TPM2_CC = 0x00000139; pub const TPM2_CC_DictionaryAttackParameters: TPM2_CC = 0x0000013a; pub const TPM2_CC_NV_ChangeAuth: TPM2_CC = 0x0000013b; pub const TPM2_CC_PCR_Event: TPM2_CC = 0x0000013c; pub const TPM2_CC_PCR_Reset: TPM2_CC = 0x0000013d; pub const TPM2_CC_SequenceComplete: TPM2_CC = 0x0000013e; pub const TPM2_CC_SetAlgorithmSet: TPM2_CC = 0x0000013f; pub const TPM2_CC_SetCommandCodeAuditStatus: TPM2_CC = 0x00000140; pub const TPM2_CC_FieldUpgradeData: TPM2_CC = 0x00000141; pub const TPM2_CC_IncrementalSelfTest: TPM2_CC = 0x00000142; pub const TPM2_CC_SelfTest: TPM2_CC = 0x00000143; pub const TPM2_CC_Startup: TPM2_CC = 0x00000144; pub const TPM2_CC_Shutdown: TPM2_CC = 0x00000145; pub const TPM2_CC_StirRandom: TPM2_CC = 0x00000146; pub const TPM2_CC_ActivateCredential: TPM2_CC = 0x00000147; pub const TPM2_CC_Certify: TPM2_CC = 0x00000148; pub const TPM2_CC_PolicyNV: TPM2_CC = 0x00000149; pub const TPM2_CC_CertifyCreation: TPM2_CC = 0x0000014a; pub const TPM2_CC_Duplicate: TPM2_CC = 0x0000014b; pub const TPM2_CC_GetTime: TPM2_CC = 0x0000014c; pub const TPM2_CC_GetSessionAuditDigest: TPM2_CC = 0x0000014d; pub const TPM2_CC_NV_Read: TPM2_CC = 0x0000014e; pub const TPM2_CC_NV_ReadLock: TPM2_CC = 0x0000014f; pub const TPM2_CC_ObjectChangeAuth: TPM2_CC = 0x00000150; pub const TPM2_CC_PolicySecret: TPM2_CC = 0x00000151; pub const TPM2_CC_Rewrap: TPM2_CC = 0x00000152; pub const TPM2_CC_Create: TPM2_CC = 0x00000153; pub const TPM2_CC_ECDH_ZGen: TPM2_CC = 0x00000154; pub const TPM2_CC_HMAC: TPM2_CC = 0x00000155; pub const TPM2_CC_Import: TPM2_CC = 0x00000156; pub const TPM2_CC_Load: TPM2_CC = 0x00000157; pub const TPM2_CC_Quote: TPM2_CC = 0x00000158; pub const TPM2_CC_RSA_Decrypt: TPM2_CC = 0x00000159; pub const TPM2_CC_HMAC_Start: TPM2_CC = 0x0000015b; pub const TPM2_CC_SequenceUpdate: TPM2_CC = 0x0000015c; pub const TPM2_CC_Sign: TPM2_CC = 0x0000015d; pub const TPM2_CC_Unseal: TPM2_CC = 0x0000015e; pub const TPM2_CC_PolicySigned: TPM2_CC = 0x00000160; pub const TPM2_CC_ContextLoad: TPM2_CC = 0x00000161; pub const TPM2_CC_ContextSave: TPM2_CC = 0x00000162; pub const TPM2_CC_ECDH_KeyGen: TPM2_CC = 0x00000163; pub const TPM2_CC_EncryptDecrypt: TPM2_CC = 0x00000164; pub const TPM2_CC_FlushContext: TPM2_CC = 0x00000165; pub const TPM2_CC_LoadExternal: TPM2_CC = 0x00000167; pub const TPM2_CC_MakeCredential: TPM2_CC = 0x00000168; pub const TPM2_CC_NV_ReadPublic: TPM2_CC = 0x00000169; pub const TPM2_CC_PolicyAuthorize: TPM2_CC = 0x0000016a; pub const TPM2_CC_PolicyAuthValue: TPM2_CC = 0x0000016b; pub const TPM2_CC_PolicyCommandCode: TPM2_CC = 0x0000016c; pub const TPM2_CC_PolicyCounterTimer: TPM2_CC = 0x0000016d; pub const TPM2_CC_PolicyCpHash: TPM2_CC = 0x0000016e; pub const TPM2_CC_PolicyLocality: TPM2_CC = 0x0000016f; pub const TPM2_CC_PolicyNameHash: TPM2_CC = 0x00000170; pub const TPM2_CC_PolicyOR: TPM2_CC = 0x00000171; pub const TPM2_CC_PolicyTicket: TPM2_CC = 0x00000172; pub const TPM2_CC_ReadPublic: TPM2_CC = 0x00000173; pub const TPM2_CC_RSA_Encrypt: TPM2_CC = 0x00000174; pub const TPM2_CC_StartAuthSession: TPM2_CC = 0x00000176; pub const TPM2_CC_VerifySignature: TPM2_CC = 0x00000177; pub const TPM2_CC_ECC_Parameters: TPM2_CC = 0x00000178; pub const TPM2_CC_FirmwareRead: TPM2_CC = 0x00000179; pub const TPM2_CC_GetCapability: TPM2_CC = 0x0000017a; pub const TPM2_CC_GetRandom: TPM2_CC = 0x0000017b; pub const TPM2_CC_GetTestResult: TPM2_CC = 0x0000017c; pub const TPM2_CC_Hash: TPM2_CC = 0x0000017d; pub const TPM2_CC_PCR_Read: TPM2_CC = 0x0000017e; pub const TPM2_CC_PolicyPCR: TPM2_CC = 0x0000017f; pub const TPM2_CC_PolicyRestart: TPM2_CC = 0x00000180; pub const TPM2_CC_ReadClock: TPM2_CC = 0x00000181; pub const TPM2_CC_PCR_Extend: TPM2_CC = 0x00000182; pub const TPM2_CC_PCR_SetAuthValue: TPM2_CC = 0x00000183; pub const TPM2_CC_NV_Certify: TPM2_CC = 0x00000184; pub const TPM2_CC_EventSequenceComplete: TPM2_CC = 0x00000185; pub const TPM2_CC_HashSequenceStart: TPM2_CC = 0x00000186; pub const TPM2_CC_PolicyPhysicalPresence: TPM2_CC = 0x00000187; pub const TPM2_CC_PolicyDuplicationSelect: TPM2_CC = 0x00000188; pub const TPM2_CC_PolicyGetDigest: TPM2_CC = 0x00000189; pub const TPM2_CC_TestParms: TPM2_CC = 0x0000018a; pub const TPM2_CC_Commit: TPM2_CC = 0x0000018b; pub const TPM2_CC_PolicyPassword: TPM2_CC = 0x0000018c; pub const TPM2_CC_ZGen_2Phase: TPM2_CC = 0x0000018d; pub const TPM2_CC_EC_Ephemeral: TPM2_CC = 0x0000018e; pub const TPM2_CC_PolicyNvWritten: TPM2_CC = 0x0000018f; pub const TPM2_CC_PolicyTemplate: TPM2_CC = 0x00000190; pub const TPM2_CC_CreateLoaded: TPM2_CC = 0x00000191; pub const TPM2_CC_PolicyAuthorizeNV: TPM2_CC = 0x00000192; pub const TPM2_CC_EncryptDecrypt2: TPM2_CC = 0x00000193; pub const TPM2_CC_AC_GetCapability: TPM2_CC = 0x00000194; pub const TPM2_CC_AC_Send: TPM2_CC = 0x00000195; pub const TPM2_CC_Policy_AC_SendSelect: TPM2_CC = 0x00000196; pub const TPM2_CC_LAST: TPM2_CC = 0x00000196; pub const TPM2_CC_Vendor_TCG_Test: TPM2_CC = 0x20000000; pub const TPM2_SPEC_FAMILY: TPM2_SPEC = 0x322E3000; /* ASCII 2.0 with null terminator */ pub const TPM2_SPEC_LEVEL: TPM2_SPEC = 00; /* the level number for the specification */ pub const TPM2_SPEC_VERSION: TPM2_SPEC = 126; /* the version number of the spec 001.26 * 100 */ pub const TPM2_SPEC_YEAR: TPM2_SPEC = 2015; /* the year of the version */ pub const TPM2_SPEC_DAY_OF_YEAR: TPM2_SPEC = 233; /* the day of the year August 21 2015 */ pub const TPM2_GENERATED_VALUE: TPM2_GENERATED = 0xff544347; /* 0xFF TCG FF 54 43 4716 */ pub const TPM2_RC_SUCCESS: TPM2_RC = 0x000; pub const TPM2_RC_BAD_TAG: TPM2_RC = 0x01E; /* defined for compatibility with TPM 1.2 */ pub const TPM2_RC_VER1: TPM2_RC = 0x100; /* set for all format 0 response codes */ pub const TPM2_RC_INITIALIZE: TPM2_RC = TPM2_RC_VER1 + 0x000; /* TPM not initialized by TPM2_Startup or already initialized */ pub const TPM2_RC_FAILURE: TPM2_RC = TPM2_RC_VER1 + 0x001; /* commands not being accepted because of a TPM failure. NOTE This may be returned by TPM2_GetTestResult as the testResult parameter. */ pub const TPM2_RC_SEQUENCE: TPM2_RC = TPM2_RC_VER1 + 0x003; /* improper use of a sequence handle */ pub const TPM2_RC_PRIVATE: TPM2_RC = TPM2_RC_VER1 + 0x00B; /* not currently used */ pub const TPM2_RC_HMAC: TPM2_RC = TPM2_RC_VER1 + 0x019; /* not currently used */ pub const TPM2_RC_DISABLED: TPM2_RC = TPM2_RC_VER1 + 0x020; /* the command is disabled */ pub const TPM2_RC_EXCLUSIVE: TPM2_RC = TPM2_RC_VER1 + 0x021; /* command failed because audit sequence required exclusivity */ pub const TPM2_RC_AUTH_TYPE: TPM2_RC = TPM2_RC_VER1 + 0x024; /* authorization handle is not correct for command */ pub const TPM2_RC_AUTH_MISSING: TPM2_RC = TPM2_RC_VER1 + 0x025; /* command requires an authorization session for handle and it is not present. */ pub const TPM2_RC_POLICY: TPM2_RC = TPM2_RC_VER1 + 0x026; /* policy failure in math operation or an invalid authPolicy value */ pub const TPM2_RC_PCR: TPM2_RC = TPM2_RC_VER1 + 0x027; /* PCR check fail */ pub const TPM2_RC_PCR_CHANGED: TPM2_RC = TPM2_RC_VER1 + 0x028; /* PCR have changed since checked. */ pub const TPM2_RC_UPGRADE: TPM2_RC = TPM2_RC_VER1 + 0x02D; /* For all commands, other than TPM2_FieldUpgradeData, this code indicates that the TPM is in field upgrade mode. For TPM2_FieldUpgradeData, this code indicates that the TPM is not in field upgrade mode */ pub const TPM2_RC_TOO_MANY_CONTEXTS: TPM2_RC = TPM2_RC_VER1 + 0x02E; /* context ID counter is at maximum. */ pub const TPM2_RC_AUTH_UNAVAILABLE: TPM2_RC = TPM2_RC_VER1 + 0x02F; /* authValue or authPolicy is not available for selected entity. */ pub const TPM2_RC_REBOOT: TPM2_RC = TPM2_RC_VER1 + 0x030; /* a _TPM_Init and StartupCLEAR is required before the TPM can resume operation. */ pub const TPM2_RC_UNBALANCED: TPM2_RC = TPM2_RC_VER1 + 0x031; /* the protection algorithms hash and symmetric are not reasonably balanced. The digest size of the hash must be larger than the key size of the symmetric algorithm. */ pub const TPM2_RC_COMMAND_SIZE: TPM2_RC = TPM2_RC_VER1 + 0x042; /* command commandSize value is inconsistent with contents of the command buffer. Either the size is not the same as the octets loaded by the hardware interface layer or the value is not large enough to hold a command header */ pub const TPM2_RC_COMMAND_CODE: TPM2_RC = TPM2_RC_VER1 + 0x043; /* command code not supported */ pub const TPM2_RC_AUTHSIZE: TPM2_RC = TPM2_RC_VER1 + 0x044; /* the value of authorizationSize is out of range or the number of octets in the Authorization Area is greater than required */ pub const TPM2_RC_AUTH_CONTEXT: TPM2_RC = TPM2_RC_VER1 + 0x045; /* use of an authorization session with a context command or another command that cannot have an authorization session. */ pub const TPM2_RC_NV_RANGE: TPM2_RC = TPM2_RC_VER1 + 0x046; /* NV offset+size is out of range. */ pub const TPM2_RC_NV_SIZE: TPM2_RC = TPM2_RC_VER1 + 0x047; /* Requested allocation size is larger than allowed. */ pub const TPM2_RC_NV_LOCKED: TPM2_RC = TPM2_RC_VER1 + 0x048; /* NV access locked. */ pub const TPM2_RC_NV_AUTHORIZATION: TPM2_RC = TPM2_RC_VER1 + 0x049; /* NV access authorization fails in command actions this failure does not affect lockout.action */ pub const TPM2_RC_NV_UNINITIALIZED: TPM2_RC = TPM2_RC_VER1 + 0x04A; /* an NV Index is used before being initialized or the state saved by TPM2_ShutdownSTATE could not be restored */ pub const TPM2_RC_NV_SPACE: TPM2_RC = TPM2_RC_VER1 + 0x04B; /* insufficient space for NV allocation */ pub const TPM2_RC_NV_DEFINED: TPM2_RC = TPM2_RC_VER1 + 0x04C; /* NV Index or persistent object already defined */ pub const TPM2_RC_BAD_CONTEXT: TPM2_RC = TPM2_RC_VER1 + 0x050; /* context in TPM2_ContextLoad is not valid */ pub const TPM2_RC_CPHASH: TPM2_RC = TPM2_RC_VER1 + 0x051; /* cpHash value already set or not correct for use */ pub const TPM2_RC_PARENT: TPM2_RC = TPM2_RC_VER1 + 0x052; /* handle for parent is not a valid parent */ pub const TPM2_RC_NEEDS_TEST: TPM2_RC = TPM2_RC_VER1 + 0x053; /* some function needs testing. */ pub const TPM2_RC_NO_RESULT: TPM2_RC = TPM2_RC_VER1 + 0x054; /* returned when an internal function cannot process a request due to an unspecified problem. This code is usually related to invalid parameters that are not properly filtered by the input unmarshaling code. */ pub const TPM2_RC_SENSITIVE: TPM2_RC = TPM2_RC_VER1 + 0x055; /* the sensitive area did not unmarshal correctly after decryption. This code is used in lieu of the other unmarshaling errors so that an attacker cannot determine where the unmarshaling error occurred */ pub const TPM2_RC_MAX_FM0: TPM2_RC = TPM2_RC_VER1 + 0x07F; /* largest version 1 code that is not a warning */ pub const TPM2_RC_FMT1: TPM2_RC = 0x080; /* This bit is SET in all format 1 response codes. The codes in this group may have a value added to them to indicate the handle session or parameter to which they apply. */ pub const TPM2_RC_ASYMMETRIC: TPM2_RC = TPM2_RC_FMT1 + 0x001; /* asymmetric algorithm not supported or not correct */ pub const TPM2_RC_ATTRIBUTES: TPM2_RC = TPM2_RC_FMT1 + 0x002; /* inconsistent attributes */ pub const TPM2_RC_HASH: TPM2_RC = TPM2_RC_FMT1 + 0x003; /* hash algorithm not supported or not appropriate */ pub const TPM2_RC_VALUE: TPM2_RC = TPM2_RC_FMT1 + 0x004; /* value is out of range or is not correct for the context */ pub const TPM2_RC_HIERARCHY: TPM2_RC = TPM2_RC_FMT1 + 0x005; /* hierarchy is not enabled or is not correct for the use */ pub const TPM2_RC_KEY_SIZE: TPM2_RC = TPM2_RC_FMT1 + 0x007; /* key size is not supported */ pub const TPM2_RC_MGF: TPM2_RC = TPM2_RC_FMT1 + 0x008; /* mask generation function not supported */ pub const TPM2_RC_MODE: TPM2_RC = TPM2_RC_FMT1 + 0x009; /* mode of operation not supported */ pub const TPM2_RC_TYPE: TPM2_RC = TPM2_RC_FMT1 + 0x00A; /* the type of the value is not appropriate for the use */ pub const TPM2_RC_HANDLE: TPM2_RC = TPM2_RC_FMT1 + 0x00B; /* the handle is not correct for the use */ pub const TPM2_RC_KDF: TPM2_RC = TPM2_RC_FMT1 + 0x00C; /* unsupported key derivation function or function not appropriate for use */ pub const TPM2_RC_RANGE: TPM2_RC = TPM2_RC_FMT1 + 0x00D; /* value was out of allowed range. */ pub const TPM2_RC_AUTH_FAIL: TPM2_RC = TPM2_RC_FMT1 + 0x00E; /* the authorization HMAC check failed and DA counter incremented */ pub const TPM2_RC_NONCE: TPM2_RC = TPM2_RC_FMT1 + 0x00F; /* invalid nonce size or nonce value mismatch */ pub const TPM2_RC_PP: TPM2_RC = TPM2_RC_FMT1 + 0x010; /* authorization requires assertion of PP */ pub const TPM2_RC_SCHEME: TPM2_RC = TPM2_RC_FMT1 + 0x012; /* unsupported or incompatible scheme */ pub const TPM2_RC_SIZE: TPM2_RC = TPM2_RC_FMT1 + 0x015; /* structure is the wrong size */ pub const TPM2_RC_SYMMETRIC: TPM2_RC = TPM2_RC_FMT1 + 0x016; /* unsupported symmetric algorithm or key size or not appropriate for instance */ pub const TPM2_RC_TAG: TPM2_RC = TPM2_RC_FMT1 + 0x017; /* incorrect structure tag */ pub const TPM2_RC_SELECTOR: TPM2_RC = TPM2_RC_FMT1 + 0x018; /* union selector is incorrect */ pub const TPM2_RC_INSUFFICIENT: TPM2_RC = TPM2_RC_FMT1 + 0x01A; /* the TPM was unable to unmarshal a value because there were not enough octets in the input buffer */ pub const TPM2_RC_SIGNATURE: TPM2_RC = TPM2_RC_FMT1 + 0x01B; /* the signature is not valid */ pub const TPM2_RC_KEY: TPM2_RC = TPM2_RC_FMT1 + 0x01C; /* key fields are not compatible with the selected use */ pub const TPM2_RC_POLICY_FAIL: TPM2_RC = TPM2_RC_FMT1 + 0x01D; /* a policy check failed */ pub const TPM2_RC_INTEGRITY: TPM2_RC = TPM2_RC_FMT1 + 0x01F; /* integrity check failed */ pub const TPM2_RC_TICKET: TPM2_RC = TPM2_RC_FMT1 + 0x020; /* invalid ticket */ pub const TPM2_RC_RESERVED_BITS: TPM2_RC = TPM2_RC_FMT1 + 0x021; /* reserved bits not set to zero as required */ pub const TPM2_RC_BAD_AUTH: TPM2_RC = TPM2_RC_FMT1 + 0x022; /* authorization failure without DA implications */ pub const TPM2_RC_EXPIRED: TPM2_RC = TPM2_RC_FMT1 + 0x023; /* the policy has expired */ pub const TPM2_RC_POLICY_CC: TPM2_RC = TPM2_RC_FMT1 + 0x024; /* the commandCode in the policy is not the commandCode of the command or the command code in a policy command references a command that is not implemented */ pub const TPM2_RC_BINDING: TPM2_RC = TPM2_RC_FMT1 + 0x025; /* public and sensitive portions of an object are not cryptographically bound */ pub const TPM2_RC_CURVE: TPM2_RC = TPM2_RC_FMT1 + 0x026; /* curve not supported */ pub const TPM2_RC_ECC_POINT: TPM2_RC = TPM2_RC_FMT1 + 0x027; /* point is not on the required curve. */ pub const TPM2_RC_WARN: TPM2_RC = 0x900; /* set for warning response codes */ pub const TPM2_RC_CONTEXT_GAP: TPM2_RC = TPM2_RC_WARN + 0x001; /* gap for context ID is too large */ pub const TPM2_RC_OBJECT_MEMORY: TPM2_RC = TPM2_RC_WARN + 0x002; /* out of memory for object contexts */ pub const TPM2_RC_SESSION_MEMORY: TPM2_RC = TPM2_RC_WARN + 0x003; /* out of memory for session contexts */ pub const TPM2_RC_MEMORY: TPM2_RC = TPM2_RC_WARN + 0x004; /* out of shared objectsession memory or need space for internal operations */ pub const TPM2_RC_SESSION_HANDLES: TPM2_RC = TPM2_RC_WARN + 0x005; /* out of session handles a session must be flushed before a new session may be created */ pub const TPM2_RC_OBJECT_HANDLES: TPM2_RC = TPM2_RC_WARN + 0x006; /* out of object handles. The handle space for objects is depleted and a reboot is required. NOTE This cannot occur on the reference implementation. NOTE There is no reason why an implementation would implement a design that would deplete handle space. Platform specifications are encouraged to forbid it. */ pub const TPM2_RC_LOCALITY: TPM2_RC = TPM2_RC_WARN + 0x007; /* bad locality */ pub const TPM2_RC_YIELDED: TPM2_RC = TPM2_RC_WARN + 0x008; /* the TPM has suspended operation on the command forward progress was made and the command may be retried. See TPM 2.0 Part 1 Multitasking. NOTE This cannot occur on the reference implementation. */ pub const TPM2_RC_CANCELED: TPM2_RC = TPM2_RC_WARN + 0x009; /* the command was canceled */ pub const TPM2_RC_TESTING: TPM2_RC = TPM2_RC_WARN + 0x00A; /* TPM is performing selftests */ pub const TPM2_RC_REFERENCE_H0: TPM2_RC = TPM2_RC_WARN + 0x010; /* the 1st handle in the handle area references a transient object or session that is not loaded */ pub const TPM2_RC_REFERENCE_H1: TPM2_RC = TPM2_RC_WARN + 0x011; /* the 2nd handle in the handle area references a transient object or session that is not loaded */ pub const TPM2_RC_REFERENCE_H2: TPM2_RC = TPM2_RC_WARN + 0x012; /* the 3rd handle in the handle area references a transient object or session that is not loaded */ pub const TPM2_RC_REFERENCE_H3: TPM2_RC = TPM2_RC_WARN + 0x013; /* the 4th handle in the handle area references a transient object or session that is not loaded */ pub const TPM2_RC_REFERENCE_H4: TPM2_RC = TPM2_RC_WARN + 0x014; /* the 5th handle in the handle area references a transient object or session that is not loaded */ pub const TPM2_RC_REFERENCE_H5: TPM2_RC = TPM2_RC_WARN + 0x015; /* the 6th handle in the handle area references a transient object or session that is not loaded */ pub const TPM2_RC_REFERENCE_H6: TPM2_RC = TPM2_RC_WARN + 0x016; /* the 7th handle in the handle area references a transient object or session that is not loaded */ pub const TPM2_RC_REFERENCE_S0: TPM2_RC = TPM2_RC_WARN + 0x018; /* the 1st authorization session handle references a session that is not loaded */ pub const TPM2_RC_REFERENCE_S1: TPM2_RC = TPM2_RC_WARN + 0x019; /* the 2nd authorization session handle references a session that is not loaded */ pub const TPM2_RC_REFERENCE_S2: TPM2_RC = TPM2_RC_WARN + 0x01A; /* the 3rd authorization session handle references a session that is not loaded */ pub const TPM2_RC_REFERENCE_S3: TPM2_RC = TPM2_RC_WARN + 0x01B; /* the 4th authorization session handle references a session that is not loaded */ pub const TPM2_RC_REFERENCE_S4: TPM2_RC = TPM2_RC_WARN + 0x01C; /* the 5th session handle references a session that is not loaded */ pub const TPM2_RC_REFERENCE_S5: TPM2_RC = TPM2_RC_WARN + 0x01D; /* the 6th session handle references a session that is not loaded */ pub const TPM2_RC_REFERENCE_S6: TPM2_RC = TPM2_RC_WARN + 0x01E; /* the 7th authorization session handle references a session that is not loaded */ pub const TPM2_RC_NV_RATE: TPM2_RC = TPM2_RC_WARN + 0x020; /* the TPM is rate limiting accesses to prevent wearout of NV */ pub const TPM2_RC_LOCKOUT: TPM2_RC = TPM2_RC_WARN + 0x021; /* authorizations for objects subject to DA protection are not allowed at this time because the TPM is in DA lockout mode */ pub const TPM2_RC_RETRY: TPM2_RC = TPM2_RC_WARN + 0x022; /* the TPM was not able to start the command */ pub const TPM2_RC_NV_UNAVAILABLE: TPM2_RC = TPM2_RC_WARN + 0x023; /* the command may require writing of NV and NV is not current accessible */ pub const TPM2_RC_NOT_USED: TPM2_RC = TPM2_RC_WARN + 0x07F; /* this value is reserved and shall not be returned by the TPM */ pub const TPM2_RC_H: TPM2_RC = 0x000; /* add to a handle related error */ pub const TPM2_RC_P: TPM2_RC = 0x040; /* add to a parameter-related error */ pub const TPM2_RC_S: TPM2_RC = 0x800; /* add to a session-related error */ pub const TPM2_RC_1: TPM2_RC = 0x100; /* add to a parameter handle or session-related error */ pub const TPM2_RC_2: TPM2_RC = 0x200; /* add to a parameter handle or session-related error */ pub const TPM2_RC_3: TPM2_RC = 0x300; /* add to a parameter handle or session-related error */ pub const TPM2_RC_4: TPM2_RC = 0x400; /* add to a parameter handle or session-related error */ pub const TPM2_RC_5: TPM2_RC = 0x500; /* add to a parameter handle or session-related error */ pub const TPM2_RC_6: TPM2_RC = 0x600; /* add to a parameter handle or session-related error */ pub const TPM2_RC_7: TPM2_RC = 0x700; /* add to a parameter handle or session-related error */ pub const TPM2_RC_8: TPM2_RC = 0x800; /* add to a parameter-related error */ pub const TPM2_RC_9: TPM2_RC = 0x900; /* add to a parameter-related error */ pub const TPM2_RC_A: TPM2_RC = 0xA00; /* add to a parameter-related error */ pub const TPM2_RC_B: TPM2_RC = 0xB00; /* add to a parameter-related error */ pub const TPM2_RC_C: TPM2_RC = 0xC00; /* add to a parameter-related error */ pub const TPM2_RC_D: TPM2_RC = 0xD00; /* add to a parameter-related error */ pub const TPM2_RC_E: TPM2_RC = 0xE00; /* add to a parameter-related error */ pub const TPM2_RC_F: TPM2_RC = 0xF00; /* add to a parameter-related error */ pub const TPM2_RC_N_MASK: TPM2_RC = 0xF00; /* number mask */ pub const TPM2_CLOCK_COARSE_SLOWER: TPM2_CLOCK_ADJUST = -3; /* Slow the Clock update rate by one coarse adjustment step. */ pub const TPM2_CLOCK_MEDIUM_SLOWER: TPM2_CLOCK_ADJUST = -2; /* Slow the Clock update rate by one medium adjustment step. */ pub const TPM2_CLOCK_FINE_SLOWER: TPM2_CLOCK_ADJUST = -1; /* Slow the Clock update rate by one fine adjustment step. */ pub const TPM2_CLOCK_NO_CHANGE: TPM2_CLOCK_ADJUST = 0; /* No change to the Clock update rate. */ pub const TPM2_CLOCK_FINE_FASTER: TPM2_CLOCK_ADJUST = 1; /* Speed the Clock update rate by one fine adjustment step. */ pub const TPM2_CLOCK_MEDIUM_FASTER: TPM2_CLOCK_ADJUST = 2; /* Speed the Clock update rate by one medium adjustment step. */ pub const TPM2_CLOCK_COARSE_FASTER: TPM2_CLOCK_ADJUST = 3; /* Speed the Clock update rate by one coarse adjustment step. */ pub const TPM2_EO_EQ: TPM2_EO = 0x0000; /* A B */ pub const TPM2_EO_NEQ: TPM2_EO = 0x0001; /* A B */ pub const TPM2_EO_SIGNED_GT: TPM2_EO = 0x0002; /* A > B signed */ pub const TPM2_EO_UNSIGNED_GT: TPM2_EO = 0x0003; /* A > B unsigned */ pub const TPM2_EO_SIGNED_LT: TPM2_EO = 0x0004; /* A < B signed */ pub const TPM2_EO_UNSIGNED_LT: TPM2_EO = 0x0005; /* A < B unsigned */ pub const TPM2_EO_SIGNED_GE: TPM2_EO = 0x0006; /* A B signed */ pub const TPM2_EO_UNSIGNED_GE: TPM2_EO = 0x0007; /* A B unsigned */ pub const TPM2_EO_SIGNED_LE: TPM2_EO = 0x0008; /* A B signed */ pub const TPM2_EO_UNSIGNED_LE: TPM2_EO = 0x0009; /* A B unsigned */ pub const TPM2_EO_BITSET: TPM2_EO = 0x000A; /* All bits SET in B are SET in A. ABB */ pub const TPM2_EO_BITCLEAR: TPM2_EO = 0x000B; /* All bits SET in B are CLEAR in A. AB0 */ pub const TPM2_ST_RSP_COMMAND: TPM2_ST = 0x00C4; /* Tag value for a response used when there is an error in the tag. This is also the value returned from a TPM 1.2 when an error occurs. This value is used in this specification because an error in the command tag may prevent determination of the family. When this tag is used in the response the response code will be TPM2_RC_BAD_TAG 0 1E16 which has the same numeric value as the TPM 1.2 response code for TPM_BADTAG. NOTE In a previously published version of this specification TPM2_RC_BAD_TAG was incorrectly assigned a value of 0x030 instead of 30 0x01e. Some implementations my return the old value instead of the new value. */ pub const TPM2_ST_NULL: TPM2_ST = 0x8000; /* no structure type specified */ pub const TPM2_ST_NO_SESSIONS: TPM2_ST = 0x8001; /* tag value for a command response for a command defined in this specification indicating that the command response has no attached sessions and no authorizationSizeparameterSize value is present. If the responseCode from the TPM is not TPM2_RC_SUCCESS then the response tag shall have this value. */ pub const TPM2_ST_SESSIONS: TPM2_ST = 0x8002; /* tag value for a command response for a command defined in this specification indicating that the command response has one or more attached sessions and the authorizationSizeparameterSize field is present */ pub const TPM2_ST_RESERVED1: TPM2_ST = 0x8003; /* When used between application software and the TPM resource manager, this tag indicates that the command has no sessions and the handles are using the Name format rather than the 32-bit handle format. NOTE 1 The response to application software will have a tag of TPM2_ST_NO_SESSIONS. Between the TRM and TPM, this tag would occur in a response from a TPM that overlaps the tag parameter of a request with the tag parameter of a response when the response has no associated sessions. NOTE 2 This tag is not used by all TPM or TRM implementations. */ pub const TPM2_ST_RESERVED2: TPM2_ST = 0x8004; /* When used between application software and the TPM resource manager. This tag indicates that the command has sessions and the handles are using the Name format rather than the 32-bit handle format. NOTE 1 If the command completes successfully the response to application software will have a tag of TPM2_ST_SESSIONS. Between the TRM and TPM would occur in a response from a TPM that overlaps the tag parameter of a request with the tag parameter of a response when the response has authorization sessions. NOTE 2 This tag is not used by all TPM or TRM implementations. */ pub const TPM2_ST_ATTEST_NV: TPM2_ST = 0x8014; /* tag for an attestation structure */ pub const TPM2_ST_ATTEST_COMMAND_AUDIT: TPM2_ST = 0x8015; /* tag for an attestation structure */ pub const TPM2_ST_ATTEST_SESSION_AUDIT: TPM2_ST = 0x8016; /* tag for an attestation structure */ pub const TPM2_ST_ATTEST_CERTIFY: TPM2_ST = 0x8017; /* tag for an attestation structure */ pub const TPM2_ST_ATTEST_QUOTE: TPM2_ST = 0x8018; /* tag for an attestation structure */ pub const TPM2_ST_ATTEST_TIME: TPM2_ST = 0x8019; /* tag for an attestation structure */ pub const TPM2_ST_ATTEST_CREATION: TPM2_ST = 0x801A; /* tag for an attestation structure */ pub const TPM2_ST_RESERVED3: TPM2_ST = 0x801B; /* do not use . NOTE This was previously assigned to TPM2_ST_ATTEST_NV. The tag is changed because the structure has changed */ pub const TPM2_ST_ATTEST_NV_DIGEST: TPM2_ST = 0x801c; /* tag for an attestation structure */ pub const TPM2_ST_CREATION: TPM2_ST = 0x8021; /* tag for a ticket type */ pub const TPM2_ST_VERIFIED: TPM2_ST = 0x8022; /* tag for a ticket type */ pub const TPM2_ST_AUTH_SECRET: TPM2_ST = 0x8023; /* tag for a ticket type */ pub const TPM2_ST_HASHCHECK: TPM2_ST = 0x8024; /* tag for a ticket type */ pub const TPM2_ST_AUTH_SIGNED: TPM2_ST = 0x8025; /* tag for a ticket type */ pub const TPM2_ST_FU_MANIFEST: TPM2_ST = 0x8029; /* tag for a structure describing a Field Upgrade Policy */ pub const TPM2_SU_CLEAR: TPM2_SU = 0x0000; /* On TPM2_Shutdown indicates that the TPM should prepare for loss of power and save state required for an orderly startup TPM Reset. On TPM2_Startup indicates that the TPM should perform TPM Reset or TPM Restart */ pub const TPM2_SU_STATE: TPM2_SU = 0x0001; /* On TPM2_Shutdown indicates that the TPM should prepare for loss of power and save state required for an orderly startup. TPM Restart or TPM Resume on TPM2_Startup indicates that the TPM should restore the state saved by TPM2_Shutdown TPM2_SU_STATE */ pub const TPM2_SE_HMAC: TPM2_SE = 0x00; pub const TPM2_SE_POLICY: TPM2_SE = 0x01; pub const TPM2_SE_TRIAL: TPM2_SE = 0x03; /* The policy session is being used to compute the policyHash and not for command authorization.This setting modifies some policy commands and prevents session from being used to authorize a command. */ pub const TPM2_CAP_FIRST: TPM2_CAP = 0x00000000; pub const TPM2_CAP_ALGS: TPM2_CAP = 0x00000000; /* TPM2_ALG_ID1 */ pub const TPM2_CAP_HANDLES: TPM2_CAP = 0x00000001; /* TPM2_HANDLE */ pub const TPM2_CAP_COMMANDS: TPM2_CAP = 0x00000002; /* TPM2_CC */ pub const TPM2_CAP_PP_COMMANDS: TPM2_CAP = 0x00000003; /* TPM2_CC */ pub const TPM2_CAP_AUDIT_COMMANDS: TPM2_CAP = 0x00000004; /* TPM2_CC */ pub const TPM2_CAP_PCRS: TPM2_CAP = 0x00000005; /* reserved */ pub const TPM2_CAP_TPM_PROPERTIES: TPM2_CAP = 0x00000006; /* TPM2_PT */ pub const TPM2_CAP_PCR_PROPERTIES: TPM2_CAP = 0x00000007; /* TPM2_PT_PCR */ pub const TPM2_CAP_ECC_CURVES: TPM2_CAP = 0x00000008; /* TPM2_ECC_CURVE */ pub const TPM2_CAP_AUTH_POLICIES: TPM2_CAP = 0x00000009; /* TPM2_HANDLE */ pub const TPM2_CAP_ACT: TPM2_CAP = 0x0000000A; /* TPM2_HANDLE */ pub const TPM2_CAP_LAST: TPM2_CAP = 0x0000000A; pub const TPM2_CAP_VENDOR_PROPERTY: TPM2_CAP = 0x00000100; /* manufacturer specific */ pub const TPM2_NT_ORDINARY: TPM2_NT = 0x0; /* Ordinary – contains data that is opaque to the TPM that can only be modified using TPM2_NV_Write(). */ pub const TPM2_NT_COUNTER: TPM2_NT = 0x1; /* Counter – contains an 8-octet value that is to be used as a counter and can only be modified with TPM2_NV_Increment() */ pub const TPM2_NT_BITS: TPM2_NT = 0x2; /* Bit Field – contains an 8-octet value to be used as a bit field and can only be modified with TPM2_NV_SetBits(). */ pub const TPM2_NT_EXTEND: TPM2_NT = 0x4; /* Extend – contains a digest-sized value used like a PCR. The Index can only be modified using TPM2_NV_Extend(). The extend will use the nameAlg of the Index. */ pub const TPM2_NT_PIN_FAIL: TPM2_NT = 0x8; /* PIN Fail - contains pinCount that increments on a PIN authorization failure and a pinLimit. */ pub const TPM2_NT_PIN_PASS: TPM2_NT = 0x9; /* PIN Pass - contains pinCount that increments on a PIN authorization success and a pinLimit. */ pub const TPM2_PT_NONE: TPM2_PT = 0x00000000; /* indicates no property type */ pub const TPM2_PT_GROUP: TPM2_PT = 0x00000100; /* The number of properties in each group. NOTE The first group with any properties is group 1 TPM2_PT_GROUP * 1. Group 0 is reserved. */ pub const TPM2_PT_FIXED: TPM2_PT = TPM2_PT_GROUP * 1; /* the group of fixed properties returned as TPMS_TAGGED_PROPERTY. The values in this group are only changed due to a firmware change in the TPM. */ pub const TPM2_PT_FAMILY_INDICATOR: TPM2_PT = TPM2_PT_FIXED + 0; /* a 4-octet character string containing the TPM Family value TPM2_SPEC_FAMILY */ pub const TPM2_PT_LEVEL: TPM2_PT = TPM2_PT_FIXED + 1; /* the level of the specification. NOTE 1 For this specification the level is zero. NOTE 2 The level is on the title page of the specification. */ pub const TPM2_PT_REVISION: TPM2_PT = TPM2_PT_FIXED + 2; /* the specification Revision times 100. EXAMPLE Revision 01.01 would have a value of 101. NOTE The Revision value is on the title page of the specification. */ pub const TPM2_PT_DAY_OF_YEAR: TPM2_PT = TPM2_PT_FIXED + 3; /* the specification day of year using TCG calendar. EXAMPLE November 15 2010 has a day of year value of 319 00 00 01 3F16. NOTE The specification date is on the title page of the specification. */ pub const TPM2_PT_YEAR: TPM2_PT = TPM2_PT_FIXED + 4; /* the specification year using the CE. EXAMPLE The year 2010 has a value of 00 00 07 DA16. NOTE The specification date is on the title page of the specification. */ pub const TPM2_PT_MANUFACTURER: TPM2_PT = TPM2_PT_FIXED + 5; /* the vendor ID unique to each TPM manufacturer */ pub const TPM2_PT_VENDOR_STRING_1: TPM2_PT = TPM2_PT_FIXED + 6; /* the first four characters of the vendor ID string. NOTE When the vendor string is fewer than 16 octets the additional property values do not have to be present. A vendor string of 4 octets can be represented in one 32-bit value and no null terminating character is required. */ pub const TPM2_PT_VENDOR_STRING_2: TPM2_PT = TPM2_PT_FIXED + 7; /* the second four characters of the vendor ID string */ pub const TPM2_PT_VENDOR_STRING_3: TPM2_PT = TPM2_PT_FIXED + 8; /* the third four characters of the vendor ID string */ pub const TPM2_PT_VENDOR_STRING_4: TPM2_PT = TPM2_PT_FIXED + 9; /* the fourth four characters of the vendor ID string */ pub const TPM2_PT_VENDOR_TPM_TYPE: TPM2_PT = TPM2_PT_FIXED + 10; /* vendor defined value indicating the TPM model */ pub const TPM2_PT_FIRMWARE_VERSION_1: TPM2_PT = TPM2_PT_FIXED + 11; /* the most significant 32 bits of a TPM vendor-specific value indicating the version number of the firmware. See 10.12.2 and 10.12.8. */ pub const TPM2_PT_FIRMWARE_VERSION_2: TPM2_PT = TPM2_PT_FIXED + 12; /* the least significant 32 bits of a TPM vendor-specific value indicating the version number of the firmware. See 10.12.2 and 10.12.8. */ pub const TPM2_PT_INPUT_BUFFER: TPM2_PT = TPM2_PT_FIXED + 13; /* the maximum size of a parameter typically a TPM2B_MAX_BUFFER */ pub const TPM2_PT_HR_TRANSIENT_MIN: TPM2_PT = TPM2_PT_FIXED + 14; /* the minimum number of transient objects that can be held in TPM RAM. NOTE This minimum shall be no less than the minimum value required by the platforms-pecific specification to which the TPM is built. */ pub const TPM2_PT_HR_PERSISTENT_MIN: TPM2_PT = TPM2_PT_FIXED + 15; /* the minimum number of persistent objects that can be held in TPM NV memory. NOTE This minimum shall be no less than the minimum value required by the platform-specific specification to which the TPM is built. */ pub const TPM2_PT_HR_LOADED_MIN: TPM2_PT = TPM2_PT_FIXED + 16; /* the minimum number of authorization sessions that can be held in TPM RAM . NOTE This minimum shall be no less than the minimum value required by the platform-specific specification to which the TPM is built. */ pub const TPM2_PT_ACTIVE_SESSIONS_MAX: TPM2_PT = TPM2_PT_FIXED + 17; /* the number of authorization sessions that may be active at a time. A session is active when it has a context associated with its handle. The context may either be in TPM RAM or be context saved. NOTE This value shall be no less than the minimum value required by the platform-specific specification to which the TPM is built. */ pub const TPM2_PT_PCR_COUNT: TPM2_PT = TPM2_PT_FIXED + 18; /* the number of PCR implemented. NOTE This number is determined by the defined attributes not the number of PCR that are populated. */ pub const TPM2_PT_PCR_SELECT_MIN: TPM2_PT = TPM2_PT_FIXED + 19; /* the minimum number of octets in a TPMS_PCR_SELECT.sizeofSelect. NOTE This value is not determined by the number of PCR implemented but by the number of PCR required by the platform-specific specification with which the TPM is compliant or by the implementer if not adhering to a platform-specific specification. */ pub const TPM2_PT_CONTEXT_GAP_MAX: TPM2_PT = TPM2_PT_FIXED + 20; /* the maximum allowed difference unsigned between the contextID values of two saved session contexts. This value shall be 2n1 where n is at least 16. */ pub const TPM2_PT_NV_COUNTERS_MAX: TPM2_PT = TPM2_PT_FIXED + 22; /* the maximum number of NV Indexes that are allowed to have the TPM2_NT_COUNTER attribute. NOTE It is allowed for this value to be larger than the number of NV Indexes that can be defined. This would be indicative of a TPM implementation that did not use different implementation technology for different NV Index types. */ pub const TPM2_PT_NV_INDEX_MAX: TPM2_PT = TPM2_PT_FIXED + 23; /* the maximum size of an NV Index data area */ pub const TPM2_PT_MEMORY: TPM2_PT = TPM2_PT_FIXED + 24; /* a TPMA_MEMORY indicating the memory management method for the TPM */ pub const TPM2_PT_CLOCK_UPDATE: TPM2_PT = TPM2_PT_FIXED + 25; /* interval in milliseconds between updates to the copy of TPMS_CLOCK_INFO.clock in NV */ pub const TPM2_PT_CONTEXT_HASH: TPM2_PT = TPM2_PT_FIXED + 26; /* the algorithm used for the integrity HMAC on saved contexts and for hashing the fuData of TPM2_FirmwareRead */ pub const TPM2_PT_CONTEXT_SYM: TPM2_PT = TPM2_PT_FIXED + 27; /* TPM2_ALG_ID the algorithm used for encryption of saved contexts */ pub const TPM2_PT_CONTEXT_SYM_SIZE: TPM2_PT = TPM2_PT_FIXED + 28; /* TPM2_KEY_BITS the size of the key used for encryption of saved contexts */ pub const TPM2_PT_ORDERLY_COUNT: TPM2_PT = TPM2_PT_FIXED + 29; /* the modulus 1 of the count for NV update of an orderly counter. The returned value is MAX_ORDERLY_COUNT. This will have a value of 2N 1 where 1 N 32. NOTE An orderly counter is an NV Index with an TPM2_NT of TPM_NV_COUNTER and TPMA_NV_ORDERLY SET. NOTE When the low-order bits of a counter equal this value an NV write occurs on the next increment. */ pub const TPM2_PT_MAX_COMMAND_SIZE: TPM2_PT = TPM2_PT_FIXED + 30; /* the maximum value for commandSize in a command */ pub const TPM2_PT_MAX_RESPONSE_SIZE: TPM2_PT = TPM2_PT_FIXED + 31; /* the maximum value for responseSize in a response */ pub const TPM2_PT_MAX_DIGEST: TPM2_PT = TPM2_PT_FIXED + 32; /* the maximum size of a digest that can be produced by the TPM */ pub const TPM2_PT_MAX_OBJECT_CONTEXT: TPM2_PT = TPM2_PT_FIXED + 33; /* the maximum size of an object context that will be returned by TPM2_ContextSave */ pub const TPM2_PT_MAX_SESSION_CONTEXT: TPM2_PT = TPM2_PT_FIXED + 34; /* the maximum size of a session context that will be returned by TPM2_ContextSave */ pub const TPM2_PT_PS_FAMILY_INDICATOR: TPM2_PT = TPM2_PT_FIXED + 35; /* platform-specific family. A TPM2_PS value. See Table 25. NOTE The platform-specific values for the TPM2_PT_PS parameters are in the relevant platform-specific specification. In the reference implementation all of these values are 0. */ pub const TPM2_PT_PS_LEVEL: TPM2_PT = TPM2_PT_FIXED + 36; /* the level of the platform-specific specification */ pub const TPM2_PT_PS_REVISION: TPM2_PT = TPM2_PT_FIXED + 37; /* the specification Revision times 100 for the platform-specific specification */ pub const TPM2_PT_PS_DAY_OF_YEAR: TPM2_PT = TPM2_PT_FIXED + 38; /* the platform-specific specification day of year using TCG calendar */ pub const TPM2_PT_PS_YEAR: TPM2_PT = TPM2_PT_FIXED + 39; /* the platform-specific specification year using the CE */ pub const TPM2_PT_SPLIT_MAX: TPM2_PT = TPM2_PT_FIXED + 40; /* the number of split signing operations supported by the TPM */ pub const TPM2_PT_TOTAL_COMMANDS: TPM2_PT = TPM2_PT_FIXED + 41; /* total number of commands implemented in the TPM */ pub const TPM2_PT_LIBRARY_COMMANDS: TPM2_PT = TPM2_PT_FIXED + 42; /* number of commands from the TPM library that are implemented */ pub const TPM2_PT_VENDOR_COMMANDS: TPM2_PT = TPM2_PT_FIXED + 43; /* number of vendor commands that are implemented */ pub const TPM2_PT_NV_BUFFER_MAX: TPM2_PT = TPM2_PT_FIXED + 44; /* the maximum data size in one NV write command */ pub const TPM2_PT_MODES: TPM2_PT = TPM2_PT_FIXED + 45; /* a TPMA_MODES value indicating that the TPM is designed for these modes. */ pub const TPM2_PT_MAX_CAP_BUFFER: TPM2_PT = TPM2_PT_FIXED + 46; /* the maximum size of a TPMS_CAPABILITY_DATA structure returned in TPM2_GetCapability(). */ pub const TPM2_PT_VAR: TPM2_PT = TPM2_PT_GROUP * 2; /* the group of variable properties returned as TPMS_TAGGED_PROPERTY. The properties in this group change because of a Protected Capability other than a firmware update. The values are not necessarily persistent across all power transitions. */ pub const TPM2_PT_PERMANENT: TPM2_PT = TPM2_PT_VAR + 0; /* TPMA_PERMANENT */ pub const TPM2_PT_STARTUP_CLEAR: TPM2_PT = TPM2_PT_VAR + 1; /* TPMA_STARTUP_CLEAR */ pub const TPM2_PT_HR_NV_INDEX: TPM2_PT = TPM2_PT_VAR + 2; /* the number of NV Indexes currently defined */ pub const TPM2_PT_HR_LOADED: TPM2_PT = TPM2_PT_VAR + 3; /* the number of authorization sessions currently loaded into TPM RAM */ pub const TPM2_PT_HR_LOADED_AVAIL: TPM2_PT = TPM2_PT_VAR + 4; /* the number of additional authorization sessions of any type that could be loaded into TPM RAM. This value is an estimate. If this value is at least 1 then at least one authorization session of any type may be loaded. Any command that changes the RAM memory allocation can make this estimate invalid. NOTE A valid implementation may return 1 even if more than one authorization session would fit into RAM. */ pub const TPM2_PT_HR_ACTIVE: TPM2_PT = TPM2_PT_VAR + 5; /* the number of active authorization sessions currently being tracked by the TPMThis is the sum of the loaded and saved sessions. */ pub const TPM2_PT_HR_ACTIVE_AVAIL: TPM2_PT = TPM2_PT_VAR + 6; /* the number of additional authorization sessions of any type that could be created. This value is an estimate. If this value is at least 1 then at least one authorization session of any type may be created. Any command that changes the RAM memory allocation can make this estimate invalid. NOTE A valid implementation may return 1 even if more than one authorization session could be created. */ pub const TPM2_PT_HR_TRANSIENT_AVAIL: TPM2_PT = TPM2_PT_VAR + 7; /* estimate of the number of additional transient objects that could be loaded into TPM RAM. This value is an estimate. If this value is at least 1 then at least one object of any type may be loaded. Any command that changes the memory allocation can make this estimate invalid. NOTE A valid implementation may return 1 even if more than one transient object would fit into RAM. */ pub const TPM2_PT_HR_PERSISTENT: TPM2_PT = TPM2_PT_VAR + 8; /* the number of persistent objects currently loaded into TPM NV memory */ pub const TPM2_PT_HR_PERSISTENT_AVAIL: TPM2_PT = TPM2_PT_VAR + 9; /* the number of additional persistent objects that could be loaded into NV memory. This value is an estimate. If this value is at least 1 then at least one object of any type may be made persistent. Any command that changes the NV memory allocation can make this estimate invalid. NOTE A valid implementation may return 1 even if more than one persistent object would fit into NV memory. */ pub const TPM2_PT_NV_COUNTERS: TPM2_PT = TPM2_PT_VAR + 10; /* the number of defined NV Indexes that have NV the TPM2_NT_COUNTER attribute */ pub const TPM2_PT_NV_COUNTERS_AVAIL: TPM2_PT = TPM2_PT_VAR + 11; /* the number of additional NV Indexes that can be defined with their TPM2_NT of TPM_NV_COUNTER and the TPMA_NV_ORDERLY attribute SET. This value is an estimate. If this value is at least 1 then at least one NV Index may be created with a TPM2_NT of TPM_NV_COUNTER and the TPMA_NV_ORDERLY attributes. Any command that changes the NV memory allocation can make this estimate invalid. NOTE A valid implementation may return 1 even if more than one NV counter could be defined. */ pub const TPM2_PT_ALGORITHM_SET: TPM2_PT = TPM2_PT_VAR + 12; /* code that limits the algorithms that may be used with the TPM */ pub const TPM2_PT_LOADED_CURVES: TPM2_PT = TPM2_PT_VAR + 13; /* the number of loaded ECC curves */ pub const TPM2_PT_LOCKOUT_COUNTER: TPM2_PT = TPM2_PT_VAR + 14; /* the current value of the lockout counter failedTries */ pub const TPM2_PT_MAX_AUTH_FAIL: TPM2_PT = TPM2_PT_VAR + 15; /* the number of authorization failures before DA lockout is invoked */ pub const TPM2_PT_LOCKOUT_INTERVAL: TPM2_PT = TPM2_PT_VAR + 16; /* the number of seconds before the value reported by TPM2_PT_LOCKOUT_COUNTER is decremented */ pub const TPM2_PT_LOCKOUT_RECOVERY: TPM2_PT = TPM2_PT_VAR + 17; /* the number of seconds after a lockoutAuth failure before use of lockoutAuth may be attempted again */ pub const TPM2_PT_NV_WRITE_RECOVERY: TPM2_PT = TPM2_PT_VAR + 18; /* number of milliseconds before the TPM will accept another command that will modify NVThis value is an approximation and may go up or down over time. */ pub const TPM2_PT_AUDIT_COUNTER_0: TPM2_PT = TPM2_PT_VAR + 19; /* the high-order 32 bits of the command audit counter */ pub const TPM2_PT_AUDIT_COUNTER_1: TPM2_PT = TPM2_PT_VAR + 20; /* the low-order 32 bits of the command audit counter */ pub const TPM2_PT_TPM2_PCR_FIRST: TPM2_PT_PCR = 0x00000000; /* bottom of the range of TPM2_PT_PCR properties */ pub const TPM2_PT_PCR_SAVE: TPM2_PT_PCR = 0x00000000; /* a SET bit in the TPMS_PCR_SELECT indicates that the PCR is saved and restored by TPM2_SU_STATE */ pub const TPM2_PT_PCR_EXTEND_L0: TPM2_PT_PCR = 0x00000001; /* a SET bit in the TPMS_PCR_SELECT indicates that the PCR may be extended from locality 0This property is only present if a locality other than 0 is implemented. */ pub const TPM2_PT_PCR_RESET_L0: TPM2_PT_PCR = 0x00000002; /* a SET bit in the TPMS_PCR_SELECT indicates that the PCR may be reset by TPM2_PCR_Reset from locality 0 */ pub const TPM2_PT_PCR_EXTEND_L1: TPM2_PT_PCR = 0x00000003; /* a SET bit in the TPMS_PCR_SELECT indicates that the PCR may be extended from locality 1 This property is only present if locality 1 is implemented. */ pub const TPM2_PT_PCR_RESET_L1: TPM2_PT_PCR = 0x00000004; /* a SET bit in the TPMS_PCR_SELECT indicates that the PCR may be reset by TPM2_PCR_Reset from locality 1This property is only present if locality 1 is implemented. */ pub const TPM2_PT_PCR_EXTEND_L2: TPM2_PT_PCR = 0x00000005; /* a SET bit in the TPMS_PCR_SELECT indicates that the PCR may be extended from locality 2 This property is only present if localities 1 and 2 are implemented. */ pub const TPM2_PT_PCR_RESET_L2: TPM2_PT_PCR = 0x00000006; /* a SET bit in the TPMS_PCR_SELECT indicates that the PCR may be reset by TPM2_PCR_Reset from locality 2This property is only present if localities 1 and 2 are implemented. */ pub const TPM2_PT_PCR_EXTEND_L3: TPM2_PT_PCR = 0x00000007; /* a SET bit in the TPMS_PCR_SELECT indicates that the PCR may be extended from locality 3This property is only present if localities 1 2 and 3 are implemented. */ pub const TPM2_PT_PCR_RESET_L3: TPM2_PT_PCR = 0x00000008; /* a SET bit in the TPMS_PCR_SELECT indicates that the PCR may be reset by TPM2_PCR_Reset from locality 3This property is only present if localities 1 2 and 3 are implemented. */ pub const TPM2_PT_PCR_EXTEND_L4: TPM2_PT_PCR = 0x00000009; /* a SET bit in the TPMS_PCR_SELECT indicates that the PCR may be extended from locality 4This property is only present if localities 1 2 3 and 4 are implemented. */ pub const TPM2_PT_PCR_RESET_L4: TPM2_PT_PCR = 0x0000000A; /* a SET bit in the TPMS_PCR_SELECT indicates that the PCR may be reset by TPM2_PCR_Reset from locality 4This property is only present if localities 1 2 3 and 4 are implemented. */ pub const TPM2_PT_PCR_NO_INCREMENT: TPM2_PT_PCR = 0x00000011; /* a SET bit in the TPMS_PCR_SELECT indicates that modifications to this PCR reset or Extend will not increment the pcrUpdateCounter */ pub const TPM2_PT_PCR_DRTM_RESET: TPM2_PT_PCR = 0x00000012; /* a SET bit in the TPMS_PCR_SELECT indicates that the PCR is reset by a DRTM event. These PCR are reset to 1 on TPM2_Startup and reset to 0 on a _TPM_Hash_End event following a _TPM_Hash_Start event. */ pub const TPM2_PT_PCR_POLICY: TPM2_PT_PCR = 0x00000013; /* a SET bit in the TPMS_PCR_SELECT indicates that the PCR is controlled by policy. This property is only present if the TPM supports policy control of a PCR. */ pub const TPM2_PT_PCR_AUTH: TPM2_PT_PCR = 0x00000014; /* a SET bit in the TPMS_PCR_SELECT indicates that the PCR is controlled by an authorization value. This property is only present if the TPM supports authorization control of a PCR. */ pub const TPM2_PT_TPM2_PCR_LAST: TPM2_PT_PCR = 0x00000014; /* top of the range of TPM2_PT_PCR properties of the implementation. If the TPM receives a request for a PCR property with a value larger than this the TPM will return a zero length list and set the moreData parameter to NO. NOTE This is an implementation-specific value. The value shown reflects the reference code implementation. */ pub const TPM2_PS_MAIN: TPM2_PS = 0x00000000; /* not platform-specific */ pub const TPM2_PS_PC: TPM2_PS = 0x00000001; /* PC Client */ pub const TPM2_PS_PDA: TPM2_PS = 0x00000002; /* PDA includes all mobile devices that are not specifically cell phones */ pub const TPM2_PS_CELL_PHONE: TPM2_PS = 0x00000003; /* Cell Phone */ pub const TPM2_PS_SERVER: TPM2_PS = 0x00000004; /* Server WG */ pub const TPM2_PS_PERIPHERAL: TPM2_PS = 0x00000005; /* Peripheral WG */ pub const TPM2_PS_TSS: TPM2_PS = 0x00000006; /* TSS WG */ pub const TPM2_PS_STORAGE: TPM2_PS = 0x00000007; /* Storage WG */ pub const TPM2_PS_AUTHENTICATION: TPM2_PS = 0x00000008; /* Authentication WG */ pub const TPM2_PS_EMBEDDED: TPM2_PS = 0x00000009; /* Embedded WG */ pub const TPM2_PS_HARDCOPY: TPM2_PS = 0x0000000A; /* Hardcopy WG */ pub const TPM2_PS_INFRASTRUCTURE: TPM2_PS = 0x0000000B; /* Infrastructure WG */ pub const TPM2_PS_VIRTUALIZATION: TPM2_PS = 0x0000000C; /* Virtualization WG */ pub const TPM2_PS_TNC: TPM2_PS = 0x0000000D; /* Trusted Network Connect WG */ pub const TPM2_PS_MULTI_TENANT: TPM2_PS = 0x0000000E; /* Multi-tenant WG */ pub const TPM2_PS_TC: TPM2_PS = 0x0000000F; /* Technical Committee */ pub const TPM2_HT_PCR: TPM2_HT = 0x00; /* PCR consecutive numbers starting at 0 that reference the PCR registers. A platform-specific specification will set the minimum number of PCR and an implementation may have more. */ pub const TPM2_HT_NV_INDEX: TPM2_HT = 0x01; /* NV Index assigned by the caller */ pub const TPM2_HT_HMAC_SESSION: TPM2_HT = 0x02; /* HMAC Authorization Session assigned by the TPM when the session is created */ pub const TPM2_HT_LOADED_SESSION: TPM2_HT = 0x02; /* Loaded Authorization Session used only in the context of TPM2_GetCapability. This type references both loaded HMAC and loaded policy authorization sessions. */ pub const TPM2_HT_POLICY_SESSION: TPM2_HT = 0x03; /* Policy Authorization Session assigned by the TPM when the session is created */ pub const TPM2_HT_SAVED_SESSION: TPM2_HT = 0x03; /* Saved Authorization Session used only in the context of TPM2_GetCapability. This type references saved authorization session contexts for which the TPM is maintaining tracking information. */ pub const TPM2_HT_PERMANENT: TPM2_HT = 0x40; /* Permanent Values assigned by this specification in */ pub const TPM2_HT_TRANSIENT: TPM2_HT = 0x80; /* Transient Objects assigned by the TPM when an object is loaded into transient object memory or when a persistent object is converted to a transient object */ pub const TPM2_HT_PERSISTENT: TPM2_HT = 0x81; /* Persistent Objects assigned by the TPM when a loaded transient object is made persistent */ pub const TPM2_HT_AC: TPM2_HT = 0x90; /* Attached Component – handle for an Attached Component. */ pub const TPM2_RH_FIRST: TPM2_RH = 0x40000000; /* R */ pub const TPM2_RH_SRK: TPM2_RH = 0x40000000; /* R */ pub const TPM2_RH_OWNER: TPM2_RH = 0x40000001; /* K A P */ pub const TPM2_RH_REVOKE: TPM2_RH = 0x40000002; /* R */ pub const TPM2_RH_TRANSPORT: TPM2_RH = 0x40000003; /* R */ pub const TPM2_RH_OPERATOR: TPM2_RH = 0x40000004; /* R */ pub const TPM2_RH_ADMIN: TPM2_RH = 0x40000005; /* R */ pub const TPM2_RH_EK: TPM2_RH = 0x40000006; /* R */ pub const TPM2_RH_NULL: TPM2_RH = 0x40000007; /* K A P */ pub const TPM2_RH_UNASSIGNED: TPM2_RH = 0x40000008; /* R */ pub const TPM2_RS_PW: TPM2_RH = 0x40000009; /* S */ pub const TPM2_RH_LOCKOUT: TPM2_RH = 0x4000000A; /* A */ pub const TPM2_RH_ENDORSEMENT: TPM2_RH = 0x4000000B; /* K A P */ pub const TPM2_RH_PLATFORM: TPM2_RH = 0x4000000C; /* K A P */ pub const TPM2_RH_PLATFORM_NV: TPM2_RH = 0x4000000D; /* C */ pub const TPM2_RH_AUTH_00: TPM2_RH = 0x40000010; /* A */ pub const TPM2_RH_AUTH_FF: TPM2_RH = 0x4000010F; /* A */ pub const TPM2_RH_ACT_0: TPM2_RH = 0x40000110; /* A P */ pub const TPM2_RH_ACT_F: TPM2_RH = 0x4000011F; /* A P */ pub const TPM2_RH_LAST: TPM2_RH = 0x4000010F; /* R */ pub const TPM2_HR_HANDLE_MASK: TPM2_HC = 0x00FFFFFF; /* to mask off the HR */ pub const TPM2_HR_RANGE_MASK: TPM2_HC = 0xFF000000; /* to mask off the variable part */ pub const TPM2_HR_SHIFT: TPM2_HC = 24; pub const TPM2_HR_PCR: TPM2_HC = (TPM2_HT_PCR as TPM2_HC) << TPM2_HR_SHIFT; pub const TPM2_HR_HMAC_SESSION: TPM2_HC = (TPM2_HT_HMAC_SESSION as TPM2_HC) << TPM2_HR_SHIFT; pub const TPM2_HR_POLICY_SESSION: TPM2_HC = (TPM2_HT_POLICY_SESSION as TPM2_HC) << TPM2_HR_SHIFT; pub const TPM2_HR_TRANSIENT: TPM2_HC = (TPM2_HT_TRANSIENT as TPM2_HC) << TPM2_HR_SHIFT; pub const TPM2_HR_PERSISTENT: TPM2_HC = (TPM2_HT_PERSISTENT as TPM2_HC) << TPM2_HR_SHIFT; pub const TPM2_HR_NV_INDEX: TPM2_HC = (TPM2_HT_NV_INDEX as TPM2_HC) << TPM2_HR_SHIFT; pub const TPM2_HR_PERMANENT: TPM2_HC = (TPM2_HT_PERMANENT as TPM2_HC) << TPM2_HR_SHIFT; pub const TPM2_PCR_FIRST: TPM2_HC = TPM2_HR_PCR + 0; /* first PCR */ pub const TPM2_PCR_LAST: TPM2_HC = TPM2_PCR_FIRST + TPM2_MAX_PCRS - 1; /* last PCR */ pub const TPM2_HMAC_SESSION_FIRST: TPM2_HC = TPM2_HR_HMAC_SESSION + 0; /* first HMAC session */ pub const TPM2_HMAC_SESSION_LAST: TPM2_HC = TPM2_HMAC_SESSION_FIRST + 0x00fffffe; /* last HMAC session */ pub const TPM2_LOADED_SESSION_FIRST: TPM2_HC = TPM2_HMAC_SESSION_FIRST; /* used in GetCapability */ pub const TPM2_LOADED_SESSION_LAST: TPM2_HC = TPM2_HMAC_SESSION_LAST; /* used in GetCapability */ pub const TPM2_POLICY_SESSION_FIRST: TPM2_HC = TPM2_HR_POLICY_SESSION + 0; /* first policy session */ pub const TPM2_POLICY_SESSION_LAST: TPM2_HC = TPM2_POLICY_SESSION_FIRST + 0x00fffffe; /* last policy session */ pub const TPM2_TRANSIENT_FIRST: TPM2_HC = TPM2_HR_TRANSIENT + 0; /* first transient object */ pub const TPM2_ACTIVE_SESSION_FIRST: TPM2_HC = TPM2_POLICY_SESSION_FIRST; /* used in GetCapability */ pub const TPM2_ACTIVE_SESSION_LAST: TPM2_HC = TPM2_POLICY_SESSION_LAST; /* used in GetCapability */ pub const TPM2_TRANSIENT_LAST: TPM2_HC = TPM2_TRANSIENT_FIRST + 0x00fffffe; /* last transient object */ pub const TPM2_PERSISTENT_FIRST: TPM2_HC = TPM2_HR_PERSISTENT + 0; /* first persistent object */ pub const TPM2_PERSISTENT_LAST: TPM2_HC = TPM2_PERSISTENT_FIRST + 0x00FFFFFF; /* last persistent object */ pub const TPM2_PLATFORM_PERSISTENT: TPM2_HC = TPM2_PERSISTENT_FIRST + 0x00800000; /* first platform persistent object */ pub const TPM2_NV_INDEX_FIRST: TPM2_HC = TPM2_HR_NV_INDEX + 0; /* first allowed NV Index */ pub const TPM2_NV_INDEX_LAST: TPM2_HC = TPM2_NV_INDEX_FIRST + 0x00FFFFFF; /* last allowed NV Index */ pub const TPM2_PERMANENT_FIRST: TPM2_HC = TPM2_RH_FIRST; pub const TPM2_PERMANENT_LAST: TPM2_HC = TPM2_RH_LAST; pub const TPM2_HR_NV_AC: TPM2_HC = ((TPM2_HT_NV_INDEX as TPM2_HC) << TPM2_HR_SHIFT) + 0x00D00000; /* AC aliased NV Index */ pub const TPM2_NV_AC_FIRST: TPM2_HC = TPM2_HR_NV_AC + 0; /* first NV Index aliased to Attached Component */ pub const TPM2_NV_AC_LAST: TPM2_HC = TPM2_HR_NV_AC + 0x0000FFFF; /* last NV Index aliased to Attached Component */ pub const TPM2_HR_AC: TPM2_HC = (TPM2_HT_AC as TPM2_HC) << TPM2_HR_SHIFT; /* AC Handle */ pub const TPM2_AC_FIRST: TPM2_HC = TPM2_HR_AC + 0; /* first Attached Component */ pub const TPM2_AC_LAST: TPM2_HC = TPM2_HR_AC + 0x0000FFFF; /* last Attached Component */ pub const TPMA_ALGORITHM_ASYMMETRIC: TPMA_ALGORITHM = 0x00000001; /* SET 1 an asymmetric algorithm with public and private portions. CLEAR 0 not an asymmetric algorithm */ pub const TPMA_ALGORITHM_SYMMETRIC: TPMA_ALGORITHM = 0x00000002; /* SET 1 a symmetric block cipher. CLEAR 0 not a symmetric block cipher */ pub const TPMA_ALGORITHM_HASH: TPMA_ALGORITHM = 0x00000004; /* SET 1 a hash algorithm. CLEAR 0 not a hash algorithm */ pub const TPMA_ALGORITHM_OBJECT: TPMA_ALGORITHM = 0x00000008; /* SET 1 an algorithm that may be used as an object type. CLEAR 0 an algorithm that is not used as an object type */ pub const TPMA_ALGORITHM_RESERVED1_MASK: TPMA_ALGORITHM = 0x000000F0; pub const TPMA_ALGORITHM_SIGNING: TPMA_ALGORITHM = 0x00000100; /* SET 1 a signing algorithm. The setting of asymmetric symmetric and hash will indicate the type of signing algorithm. CLEAR 0 not a signing algorithm */ pub const TPMA_ALGORITHM_ENCRYPTING: TPMA_ALGORITHM = 0x00000200; /* SET 1 an encryptiondecryption algorithm. The setting of asymmetric symmetric and hash will indicate the type of encryptiondecryption algorithm. CLEAR 0 not an encryption-decryption algorithm */ pub const TPMA_ALGORITHM_METHOD: TPMA_ALGORITHM = 0x00000400; /* SET 1 a method such as a key derivative function KDF. CLEAR 0 not a method */ pub const TPMA_ALGORITHM_RESERVED2_MASK: TPMA_ALGORITHM = 0xFFFFF800; pub const TPMA_OBJECT_RESERVED1_MASK: TPMA_OBJECT = 0x00000001; /* shall be zero */ pub const TPMA_OBJECT_FIXEDTPM: TPMA_OBJECT = 0x00000002; /* SET 1 The hierarchy of the object as indicated by its Qualified Name may not change. CLEAR 0 The hierarchy of the object may change as a result of this object or an ancestor key being duplicated for use in another hierarchy. */ pub const TPMA_OBJECT_STCLEAR: TPMA_OBJECT = 0x00000004; /* SET 1 Previously saved contexts of this object may not be loaded after StartupCLEAR. CLEAR 0 Saved contexts of this object may be used after a ShutdownSTATE and subsequent Startup. */ pub const TPMA_OBJECT_RESERVED2_MASK: TPMA_OBJECT = 0x00000008; /* shall be zero */ pub const TPMA_OBJECT_FIXEDPARENT: TPMA_OBJECT = 0x00000010; /* SET 1 The parent of the object may not change. CLEAR 0 The parent of the object may change as the result of a TPM2_Duplicate of the object. */ pub const TPMA_OBJECT_SENSITIVEDATAORIGIN: TPMA_OBJECT = 0x00000020; /* SET 1 Indicates that when the object was created with TPM2_Create or TPM2_CreatePrimary the TPM generated all of the sensitive data other than the authValue. CLEAR 0 A portion of the sensitive data other than the authValue was provided by the caller. */ pub const TPMA_OBJECT_USERWITHAUTH: TPMA_OBJECT = 0x00000040; /* SET 1 Approval of USER role actions with this object may be with an HMAC session or with a password using the authValue of the object or a policy session. CLEAR 0 Approval of USER role actions with this object may only be done with a policy session. */ pub const TPMA_OBJECT_ADMINWITHPOLICY: TPMA_OBJECT = 0x00000080; /* SET 1 Approval of ADMIN role actions with this object may only be done with a policy session. CLEAR 0 Approval of ADMIN role actions with this object may be with an HMAC session or with a password using the authValue of the object or a policy session. */ pub const TPMA_OBJECT_RESERVED3_MASK: TPMA_OBJECT = 0x00000300; /* shall be zero */ pub const TPMA_OBJECT_NODA: TPMA_OBJECT = 0x00000400; /* SET 1 The object is not subject to dictionary attack protections. CLEAR 0 The object is subject to dictionary attack protections. */ pub const TPMA_OBJECT_ENCRYPTEDDUPLICATION: TPMA_OBJECT = 0x00000800; /* SET 1 If the object is duplicated then symmetricAlg shall not be TPM2_ALG_NULL and newParentHandle shall not be TPM2_RH_NULL. CLEAR 0 The object may be duplicated without an inner wrapper on the private portion of the object and the new parent may be TPM2_RH_NULL. */ pub const TPMA_OBJECT_RESERVED4_MASK: TPMA_OBJECT = 0x0000F000; /* shall be zero */ pub const TPMA_OBJECT_RESTRICTED: TPMA_OBJECT = 0x00010000; /* SET 1 Key usage is restricted to manipulate structures of known format the parent of this key shall have restricted SET. CLEAR 0 Key usage is not restricted to use on special formats. */ pub const TPMA_OBJECT_DECRYPT: TPMA_OBJECT = 0x00020000; /* SET 1 The private portion of the key may be used to decrypt. CLEAR 0 The private portion of the key may not be used to decrypt. */ pub const TPMA_OBJECT_SIGN_ENCRYPT: TPMA_OBJECT = 0x00040000; /* SET 1 For a symmetric cipher object the private portion of the key may be used to encrypt. For other objects the private portion of the key may be used to sign. CLEAR 0 The private portion of the key may not be used to sign or encrypt. */ pub const TPMA_OBJECT_RESERVED5_MASK: TPMA_OBJECT = 0xFFF80000; /* shall be zero */ pub const TPMA_SESSION_CONTINUESESSION: TPMA_SESSION = 0x00000001; /* SET 1 In a command this setting indicates that the session is to remain active after successful completion of the command. In a response it indicates that the session is still active. If SET in the command this attribute shall be SET in the response. CLEAR 0 In a command this setting indicates that the TPM should close the session and flush any related context when the command completes successfully. In a response it indicates that the session is closed and the context is no longer active. This attribute has no meaning for a password authorization and the TPM will allow any setting of the attribute in the command and SET the attribute in the response. This attribute will only be CLEAR in one response for a logical session. If the attribute is CLEAR the context associated with the session is no longer in use and the space is available. A session created after another session is ended may have the same handle but logically is not the same session. This attribute has no effect if the command does not complete successfully. */ pub const TPMA_SESSION_AUDITEXCLUSIVE: TPMA_SESSION = 0x00000002; /* SET 1 In a command this setting indicates that the command should only be executed if the session is exclusive at the start of the command. In a response it indicates that the session is exclusive. This setting is only allowed if the audit attribute is SET TPM2_RC_ATTRIBUTES. CLEAR 0 In a command indicates that the session need not be exclusive at the start of the command. In a response indicates that the session is not exclusive. In this revision if audit is CLEAR auditExclusive must be CLEAR in the command and will be CLEAR in the response. In a future revision this bit may have a different meaning if audit is CLEAR. See Exclusive Audit Session clause in TPM 2.0 Part 1. */ pub const TPMA_SESSION_AUDITRESET: TPMA_SESSION = 0x00000004; /* SET 1 In a command this setting indicates that the audit digest of the session should be initialized and the exclusive status of the session SET. This setting is only allowed if the audit attribute is SET TPM2_RC_ATTRIBUTES. CLEAR 0 In a command indicates that the audit digest should not be initialized. This bit is always CLEAR in a response. In this revision if audit is CLEAR auditReset must be clear in the command and will be CLEAR in the response. In a future revision this bit may have a different meaning if audit is CLEAR. */ pub const TPMA_SESSION_RESERVED1_MASK: TPMA_SESSION = 0x00000018; /* shall be CLEAR */ pub const TPMA_SESSION_DECRYPT: TPMA_SESSION = 0x00000020; /* SET 1 In a command this setting indicates that the first parameter in the command is symmetrically encrypted using the parameter encryption scheme described in TPM 2.0 Part 1. The TPM will decrypt the parameter after performing any HMAC computations and before unmarshaling the parameter. In a response the attribute is copied from the request but has no effect on the response. CLEAR 0 Session not used for encryption. For a password authorization this attribute will be CLEAR in both the command and response. This attribute may only be SET in one session per command. This attribute may be SET in a session that is not associated with a command handle. Such a session is provided for purposes of encrypting a parameter and not for authorization. This attribute may be SET in combination with any other session attributes. This attribute may only be SET if the first parameter of the command is a sized buffer TPM2B_. */ pub const TPMA_SESSION_ENCRYPT: TPMA_SESSION = 0x00000040; /* SET 1 In a command this setting indicates that the TPM should use this session to encrypt the first parameter in the response. In a response it indicates that the attribute was set in the command and that the TPM used the session to encrypt the first parameter in the response using the parameter encryption scheme described in TPM 2.0 Part 1. CLEAR 0 Session not used for encryption. For a password authorization this attribute will be CLEAR in both the command and response. This attribute may only be SET in one session per command. This attribute may be SET in a session that is not associated with a command handle. Such a session is provided for purposes of encrypting a parameter and not for authorization. This attribute may only be SET if the first parameter of a response is a sized buffer TPM2B_. */ pub const TPMA_SESSION_AUDIT: TPMA_SESSION = 0x00000080; /* SET 1 In a command or response this setting indicates that the session is for audit and that auditExclusive and auditReset have meaning. This session may also be used for authorization encryption or decryption. The encrypted and encrypt fields may be SET or CLEAR. CLEAR 0 Session is not used for audit. This attribute may only be SET in one session per command or response. If SET in the command then this attribute will be SET in the response. */ pub const TPMA_LOCALITY_TPM2_LOC_ZERO: TPMA_LOCALITY = 0x00000001; pub const TPMA_LOCALITY_TPM2_LOC_ONE: TPMA_LOCALITY = 0x00000002; pub const TPMA_LOCALITY_TPM2_LOC_TWO: TPMA_LOCALITY = 0x00000004; pub const TPMA_LOCALITY_TPM2_LOC_THREE: TPMA_LOCALITY = 0x00000008; pub const TPMA_LOCALITY_TPM2_LOC_FOUR: TPMA_LOCALITY = 0x00000010; pub const TPMA_LOCALITY_EXTENDED_MASK: TPMA_LOCALITY = 0x000000E0; /* If any of these bits is set an extended locality is indicated */ pub const TPMA_LOCALITY_EXTENDED_SHIFT: u32 = 5; pub const TPMA_PERMANENT_OWNERAUTHSET: TPMA_PERMANENT = 0x00000001; /* SET 1 TPM2_HierarchyChangeAuth with ownerAuth has been executed since the last TPM2_Clear. CLEAR 0 ownerAuth has not been changed since TPM2_Clear. */ pub const TPMA_PERMANENT_ENDORSEMENTAUTHSET: TPMA_PERMANENT = 0x00000002; /* SET 1 TPM2_HierarchyChangeAuth with endorsementAuth has been executed since the last TPM2_Clear. CLEAR 0 endorsementAuth has not been changed since TPM2_Clear. */ pub const TPMA_PERMANENT_LOCKOUTAUTHSET: TPMA_PERMANENT = 0x00000004; /* SET 1 TPM2_HierarchyChangeAuth with lockoutAuth has been executed since the last TPM2_Clear. CLEAR 0 lockoutAuth has not been changed since TPM2_Clear. */ pub const TPMA_PERMANENT_RESERVED1_MASK: TPMA_PERMANENT = 0x000000F8; pub const TPMA_PERMANENT_DISABLECLEAR: TPMA_PERMANENT = 0x00000100; /* SET 1 TPM2_Clear is disabled. CLEAR 0 TPM2_Clear is enabled. NOTE See TPM2_ClearControl in TPM 2.0 Part 3 for details on changing this attribute. */ pub const TPMA_PERMANENT_INLOCKOUT: TPMA_PERMANENT = 0x00000200; /* SET 1 The TPM is in lockout and commands that require authorization with other than Platform Authorization or Lockout Authorization will not succeed. */ pub const TPMA_PERMANENT_TPMGENERATEDEPS: TPMA_PERMANENT = 0x00000400; /* SET 1 The EPS was created by the TPM. CLEAR 0 The EPS was created outside of the TPM using a manufacturer specific process. */ pub const TPMA_PERMANENT_RESERVED2_MASK: TPMA_PERMANENT = 0xFFFFF800; pub const TPMA_STARTUP_CLEAR_PHENABLE: TPMA_STARTUP_CLEAR = 0x00000001; /* SET 1 The platform hierarchy is enabled and platformAuth or platformPolicy may be used for authorization. CLEAR 0 platformAuth and platformPolicy may not be used for authorizations and objects in the platform hierarchy including persistent objects cannot be used. NOTE See TPM2_HierarchyControl in TPM 2.0 Part 3 for details on changing this attribute. */ pub const TPMA_STARTUP_CLEAR_SHENABLE: TPMA_STARTUP_CLEAR = 0x00000002; /* SET 1 The Storage hierarchy is enabled and ownerAuth or ownerPolicy may be used for authorization. NV indices defined using owner authorization are accessible. CLEAR 0 ownerAuth and ownerPolicy may not be used for authorizations and objects in the Storage hierarchy persistent objects and NV indices defined using owner authorization cannot be used. NOTE See TPM2_HierarchyControl in TPM 2.0 Part 3 for details on changing this attribute. */ pub const TPMA_STARTUP_CLEAR_EHENABLE: TPMA_STARTUP_CLEAR = 0x00000004; /* SET 1 The EPS hierarchy is enabled and Endorsement Authorization may be used to authorize commands. CLEAR 0 Endorsement Authorization may not be used for authorizations and objects in the endorsement hierarchy including persistent objects cannot be used. NOTE See TPM2_HierarchyControl in TPM 2.0 Part 3 for details on changing this attribute. */ pub const TPMA_STARTUP_CLEAR_PHENABLENV: TPMA_STARTUP_CLEAR = 0x00000008; /* SET 1 NV indices that have TPMA_PLATFORM_CREATE SET may be read or written. The platform can create define and undefine indices. CLEAR 0 NV indices that have TPMA_PLATFORM_CREATE SET may not be read or written TPM2_RC_HANDLE. The platform cannot define TPM2_RC_HIERARCHY or undefined TPM2_RC_HANDLE indices. NOTE See TPM2_HierarchyControl in TPM 2.0 Part 3 for details on changing this attribute. NOTE read refers to these commands TPM2_NV_Read TPM2_NV_ReadPublic TPM_NV_Certify TPM2_PolicyNVwrite refers to these commands TPM2_NV_Write TPM2_NV_Increment TPM2_NV_Extend TPM2_NV_SetBitsNOTE The TPM must query the index TPMA_PLATFORM_CREATE attribute to determine whether phEnableNV is applicable. Since the TPM will return TPM2_RC_HANDLE if the index does not exist it also returns this error code if the index is disabled. Otherwise the TPM would leak the existence of an index even when disabled. */ pub const TPMA_STARTUP_CLEAR_RESERVED1_MASK: TPMA_STARTUP_CLEAR = 0x7FFFFFF0; /* shall be zero */ pub const TPMA_STARTUP_CLEAR_ORDERLY: TPMA_STARTUP_CLEAR = 0x80000000; /* SET 1 The TPM received a TPM2_Shutdown and a matching TPM2_Startup. CLEAR 0 TPM2_StartupTPM2_SU_CLEAR was not preceded by a TPM2_Shutdown of any type. NOTE A shutdown is orderly if the TPM receives a TPM2_Shutdown of any type followed by a TPM2_Startup of any type. However the TPM will return an error if TPM2_StartupTPM2_SU_STATE was not preceded by TPM2_State_SaveTPM2_SU_STATE. */ pub const TPMA_MEMORY_SHAREDRAM: TPMA_MEMORY = 0x00000001; /* SET 1 indicates that the RAM memory used for authorization session contexts is shared with the memory used for transient objects. CLEAR 0 indicates that the memory used for authorization sessions is not shared with memory used for transient objects */ pub const TPMA_MEMORY_SHAREDNV: TPMA_MEMORY = 0x00000002; /* SET 1 indicates that the NV memory used for persistent objects is shared with the NV memory used for NV Index values. CLEAR 0 indicates that the persistent objects and NV Index values are allocated from separate sections of NV */ pub const TPMA_MEMORY_OBJECTCOPIEDTORAM: TPMA_MEMORY = 0x00000004; /* SET 1 indicates that the TPM copies persistent objects to a transientobject slot in RAM when the persistent object is referenced in a command. The TRM is required to make sure that an object slot is available. CLEAR 0 indicates that the TPM does not use transientobject slots when persistent objects are referenced */ pub const TPMA_MEMORY_RESERVED1_MASK: TPMA_MEMORY = 0xFFFFFFF8; /* shall be zero */ pub const TPMA_CC_COMMANDINDEX_MASK: TPMA_CC = 0x0000FFFF; /* indicates the command being selected */ pub const TPMA_CC_COMMANDINDEX_SHIFT: u32 = 0; pub const TPMA_CC_RESERVED1_MASK: TPMA_CC = 0x003F0000; /* shall be zero */ pub const TPMA_CC_NV: TPMA_CC = 0x00400000; /* SET 1 indicates that the command may write to NV. CLEAR 0 indicates that the command does not write to NV */ pub const TPMA_CC_EXTENSIVE: TPMA_CC = 0x00800000; /* SET 1 This command could flush any number of loaded contexts. CLEAR 0 no additional changes other than indicated by the flushed attribute */ pub const TPMA_CC_FLUSHED: TPMA_CC = 0x01000000; /* SET 1 The context associated with any transient handle in the command will be flushed when this command completes. CLEAR 0 No context is flushed as a side effect of this command. */ pub const TPMA_CC_CHANDLES_MASK: TPMA_CC = 0x0E000000; /* indicates the number of the handles in the handle area for this command */ pub const TPMA_CC_CHANDLES_SHIFT: u32 = 25; pub const TPMA_CC_RHANDLE: TPMA_CC = 0x10000000; /* SET 1 indicates the presence of the handle area in the response */ pub const TPMA_CC_V: TPMA_CC = 0x20000000; /* SET 1 indicates that the command is vendor-specific. CLEAR 0 indicates that the command is defined in a version of this specification */ pub const TPMA_CC_RES_MASK: TPMA_CC = 0xC0000000; /* allocated for software shall be zero */ pub const TPMA_CC_RES_SHIFT: u32 = 30; tss-esapi-7.4.0/src/constants/types.rs000064400000000000000000000100731046102023000160620ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{Error, Result, WrapperErrorKind}; use log::error; use num_derive::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive}; use std::convert::{From, TryFrom}; pub mod capability { use super::*; use crate::{ constants::tss::{ TPM2_CAP_ALGS, TPM2_CAP_AUDIT_COMMANDS, TPM2_CAP_COMMANDS, TPM2_CAP_ECC_CURVES, TPM2_CAP_HANDLES, TPM2_CAP_PCRS, TPM2_CAP_PCR_PROPERTIES, TPM2_CAP_PP_COMMANDS, TPM2_CAP_TPM_PROPERTIES, }, tss2_esys::TPM2_CAP, }; // Enum representing the different TPM Capability Type values. #[derive(FromPrimitive, ToPrimitive, Debug, Copy, Clone, PartialEq, Eq)] #[repr(u32)] pub enum CapabilityType { Algorithms = TPM2_CAP_ALGS, Handles = TPM2_CAP_HANDLES, Command = TPM2_CAP_COMMANDS, PPCommands = TPM2_CAP_PP_COMMANDS, AuditCommands = TPM2_CAP_AUDIT_COMMANDS, AssignedPCR = TPM2_CAP_PCRS, TPMProperties = TPM2_CAP_TPM_PROPERTIES, PCRProperties = TPM2_CAP_PCR_PROPERTIES, ECCCurves = TPM2_CAP_ECC_CURVES, } impl From for TPM2_CAP { fn from(capability_type: CapabilityType) -> TPM2_CAP { // The values are well defined so this cannot fail. capability_type.to_u32().unwrap() } } impl TryFrom for CapabilityType { type Error = Error; fn try_from(tpm_capability_type: TPM2_CAP) -> Result { CapabilityType::from_u32(tpm_capability_type).ok_or_else(|| { error!( "value = {} did not match any CapabilityType.", tpm_capability_type ); Error::local_error(WrapperErrorKind::InvalidParam) }) } } } /// Startup module pub mod startup { use super::*; use crate::{ constants::tss::{TPM2_SU_CLEAR, TPM2_SU_STATE}, tss2_esys::TPM2_SU, }; /// Enum repsenting the different TPM Startup Type values. #[derive(FromPrimitive, ToPrimitive, Debug, Copy, Clone, PartialEq, Eq)] #[repr(u16)] pub enum StartupType { Clear = TPM2_SU_CLEAR, State = TPM2_SU_STATE, } impl From for TPM2_SU { fn from(startup_type: StartupType) -> TPM2_SU { // The values are well defined so this cannot fail. startup_type.to_u16().unwrap() } } impl TryFrom for StartupType { type Error = Error; fn try_from(tpm_startup_type: TPM2_SU) -> Result { StartupType::from_u16(tpm_startup_type).ok_or_else(|| { error!( "value = {} did not match any StartupType.", tpm_startup_type ); Error::local_error(WrapperErrorKind::InvalidParam) }) } } } /// Session module pub mod session { use super::*; use crate::{ constants::tss::{TPM2_SE_HMAC, TPM2_SE_POLICY, TPM2_SE_TRIAL}, tss2_esys::TPM2_SE, }; /// Enum representing the different TPM session types. #[derive(FromPrimitive, ToPrimitive, Debug, Copy, Clone, PartialEq, Eq)] #[repr(u8)] pub enum SessionType { Hmac = TPM2_SE_HMAC, Policy = TPM2_SE_POLICY, Trial = TPM2_SE_TRIAL, } impl From for TPM2_SE { fn from(session_type: SessionType) -> TPM2_SE { // The values are well defined so this cannot fail. session_type.to_u8().unwrap() } } impl TryFrom for SessionType { type Error = Error; fn try_from(tpm_session_type: TPM2_SE) -> Result { SessionType::from_u8(tpm_session_type).ok_or_else(|| { error!( "value = {} did not match any SessionType.", tpm_session_type ); Error::local_error(WrapperErrorKind::InvalidParam) }) } } } tss-esapi-7.4.0/src/context/general_esys_tr.rs000064400000000000000000000067121046102023000175600ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ context::handle_manager::HandleDropAction, handles::ObjectHandle, handles::{handle_conversion::TryIntoNotNone, TpmHandle}, structures::Auth, structures::Name, tss2_esys::{Esys_TR_Close, Esys_TR_FromTPMPublic, Esys_TR_GetName, Esys_TR_SetAuth}, Context, Error, Result, }; use log::error; use std::convert::TryFrom; use std::ptr::null_mut; use zeroize::Zeroize; impl Context { /// Set the authentication value for a given object handle in the ESYS context. pub fn tr_set_auth(&mut self, object_handle: ObjectHandle, auth: Auth) -> Result<()> { let mut auth_value = auth.into(); let ret = unsafe { Esys_TR_SetAuth(self.mut_context(), object_handle.into(), &auth_value) }; auth_value.buffer.zeroize(); let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(()) } else { error!("Error when setting authentication value: {}", ret); Err(ret) } } /// Retrieve the name of an object from the object handle pub fn tr_get_name(&mut self, object_handle: ObjectHandle) -> Result { let mut name_ptr = null_mut(); let ret = unsafe { Esys_TR_GetName(self.mut_context(), object_handle.into(), &mut name_ptr) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Name::try_from(Context::ffi_data_to_owned(name_ptr)) } else { error!("Error in getting name: {}", ret); Err(ret) } } /// Used to construct an esys object from the resources inside the TPM. pub fn tr_from_tpm_public(&mut self, tpm_handle: TpmHandle) -> Result { let mut object = ObjectHandle::None.into(); let ret = unsafe { Esys_TR_FromTPMPublic( self.mut_context(), tpm_handle.into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), &mut object, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { self.handle_manager.add_handle( object.into(), if tpm_handle.may_be_flushed() { HandleDropAction::Flush } else { HandleDropAction::Close }, )?; Ok(object.into()) } else { error!("Error when getting ESYS handle from TPM handle: {}", ret); Err(ret) } } /// Instructs the ESAPI to release the metadata and resources allocated for a specific ObjectHandle. /// /// This is useful for cleaning up handles for which the context cannot be flushed. pub fn tr_close(&mut self, object_handle: &mut ObjectHandle) -> Result<()> { let mut rsrc_handle = object_handle.try_into_not_none()?; let ret = unsafe { Esys_TR_Close(self.mut_context(), &mut rsrc_handle) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { self.handle_manager.set_as_closed(*object_handle)?; *object_handle = ObjectHandle::from(rsrc_handle); Ok(()) } else { error!("Error when closing an ESYS handle: {}", ret); Err(ret) } } // Missing function: Esys_TR_Serialize // Missing function: Esys_TR_Deserialize } tss-esapi-7.4.0/src/context/handle_manager.rs000064400000000000000000000114751046102023000173220ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{handles::ObjectHandle, tss2_esys::ESYS_TR, Error, Result, WrapperErrorKind}; use log::error; use std::collections::HashMap; /// Enum representing the action to be taken /// when the handle is dropped. #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum HandleDropAction { Close, Flush, } /// The HandleManager is responsible for storing /// the handles used by Context iand their states. /// In order to make sure the correct handles get /// flushed and closed when the Context is dropped. #[derive(Debug)] pub struct HandleManager { open_handles: HashMap, } impl HandleManager { /// Creates a new HandleManager pub fn new() -> HandleManager { HandleManager { open_handles: HashMap::new(), } } /// Adds a handle to the HandleManager pub fn add_handle( &mut self, handle: ObjectHandle, handle_drop_action: HandleDropAction, ) -> Result<()> { if handle == ObjectHandle::None || handle == ObjectHandle::Null { error!("Handle manager does not handle None or Null handles"); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } // The TSS might return the same handle, see #383 if let Some(stored_handle_drop_action) = self.open_handles.get(&handle) { if handle_drop_action != *stored_handle_drop_action { error!("Handle drop action inconsistency"); return Err(Error::local_error(WrapperErrorKind::InconsistentParams)); } } let _ = self.open_handles.insert(handle, handle_drop_action); Ok(()) } /// Sets the handle as flushed which removes it from the manager. /// /// # Errors /// If the handle was not set to be flushed then this will cause an /// error but the handle will still be removed from the handler. pub fn set_as_flushed(&mut self, handle: ObjectHandle) -> Result<()> { self.open_handles .remove(&handle) .ok_or_else(|| { error!("Handle({}) does not exist", ESYS_TR::from(handle)); Error::local_error(WrapperErrorKind::InvalidHandleState) }) .and_then(|handle_drop_action| { if handle_drop_action == HandleDropAction::Flush { Ok(()) } else { error!( "Flushing handle({}) that should not have been flushed.", ESYS_TR::from(handle) ); Err(Error::local_error(WrapperErrorKind::InvalidHandleState)) } }) } /// Sets the handles as closed which removes it from the handler. /// /// # Errors /// If the handle was set to be flushed then this will cause an /// error but the handle will still be removed from the handler. pub fn set_as_closed(&mut self, handle: ObjectHandle) -> Result<()> { self.open_handles .remove(&handle) .ok_or_else(|| { error!("Handle({}) does not exist", ESYS_TR::from(handle)); Error::local_error(WrapperErrorKind::InvalidHandleState) }) .and_then(|handle_drop_action| { if handle_drop_action == HandleDropAction::Close { Ok(()) } else { error!( "Closing handle({}) that should have been flushed", ESYS_TR::from(handle) ); Err(Error::local_error(WrapperErrorKind::InvalidHandleState)) } }) } /// Retrieves all handles that needs to be flushed. pub fn handles_to_flush(&self) -> Vec { self.open_handles .iter() .filter_map(|(open_handle, &handle_drop_action)| { if handle_drop_action == HandleDropAction::Flush { Some(open_handle) } else { None } }) .cloned() .collect::>() } /// Retrieves all handles that needs to be closed. pub fn handles_to_close(&self) -> Vec { self.open_handles .iter() .filter_map(|(open_handle, &handle_drop_action)| { if handle_drop_action == HandleDropAction::Close { Some(open_handle) } else { None } }) .cloned() .collect::>() } /// Indicates if the manager has any open handles pub fn has_open_handles(&self) -> bool { !self.open_handles.is_empty() } } tss-esapi-7.4.0/src/context/session_administration.rs000064400000000000000000000033071046102023000211600ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ attributes::{SessionAttributes, SessionAttributesMask}, handles::SessionHandle, interface_types::session_handles::AuthSession, tss2_esys::{Esys_TRSess_GetAttributes, Esys_TRSess_SetAttributes}, Context, Error, Result, }; use log::error; impl Context { /// Set the given attributes on a given session. pub fn tr_sess_set_attributes( &mut self, session: AuthSession, attributes: SessionAttributes, mask: SessionAttributesMask, ) -> Result<()> { let ret = unsafe { Esys_TRSess_SetAttributes( self.mut_context(), SessionHandle::from(session).into(), attributes.into(), mask.into(), ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(()) } else { error!("Error when setting session attributes: {}", ret); Err(ret) } } /// Get session attribute flags. pub fn tr_sess_get_attributes(&mut self, session: AuthSession) -> Result { let mut flags = 0; let ret = unsafe { Esys_TRSess_GetAttributes( self.mut_context(), SessionHandle::from(session).into(), &mut flags, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(SessionAttributes(flags)) } else { error!("Error when getting session attributes: {}", ret); Err(ret) } } // Missing function: Esys_TRSess_GetNonceTPM } tss-esapi-7.4.0/src/context/tpm_commands/asymmetric_primitives.rs000064400000000000000000000311501046102023000234760ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ handles::KeyHandle, structures::Data, structures::{EccPoint, PublicKeyRsa, RsaDecryptionScheme}, tss2_esys::{Esys_ECDH_KeyGen, Esys_ECDH_ZGen, Esys_RSA_Decrypt, Esys_RSA_Encrypt}, Context, Error, Result, }; use log::error; use std::convert::TryFrom; use std::ptr::null_mut; impl Context { /// Perform an asymmetric RSA encryption. pub fn rsa_encrypt( &mut self, key_handle: KeyHandle, message: PublicKeyRsa, in_scheme: RsaDecryptionScheme, label: Data, ) -> Result { let mut out_data_ptr = null_mut(); let ret = unsafe { Esys_RSA_Encrypt( self.mut_context(), key_handle.into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), &message.into(), &in_scheme.into(), &label.into(), &mut out_data_ptr, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { PublicKeyRsa::try_from(Context::ffi_data_to_owned(out_data_ptr)) } else { error!("Error when performing RSA encryption: {}", ret); Err(ret) } } /// Perform an asymmetric RSA decryption. pub fn rsa_decrypt( &mut self, key_handle: KeyHandle, cipher_text: PublicKeyRsa, in_scheme: RsaDecryptionScheme, label: Data, ) -> Result { let mut message_ptr = null_mut(); let ret = unsafe { Esys_RSA_Decrypt( self.mut_context(), key_handle.into(), self.required_session_1()?, self.optional_session_2(), self.optional_session_3(), &cipher_text.into(), &in_scheme.into(), &label.into(), &mut message_ptr, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { PublicKeyRsa::try_from(Context::ffi_data_to_owned(message_ptr)) } else { error!("Error when performing RSA decryption: {}", ret); Err(ret) } } /// Generate an ephemeral key pair. /// /// # Arguments /// * `key_handle`- A [KeyHandle] of ECC key which curve parameters will be used /// to generate the ephemeral key. /// /// # Details /// This command uses the TPM to generate an ephemeral /// key pair. It uses the private ephemeral key and a loaded /// public key to compute the shared secret value. /// /// # Example /// /// ```rust /// # use tss_esapi::{ /// # Context, TctiNameConf, /// # attributes::{SessionAttributesBuilder, ObjectAttributesBuilder}, /// # constants::SessionType, /// # interface_types::{ /// # algorithm::{ /// # HashingAlgorithm, PublicAlgorithm, RsaDecryptAlgorithm, /// # }, /// # ecc::EccCurve, /// # resource_handles::Hierarchy, /// # }, /// # structures::{ /// # Auth, Data, EccScheme, PublicBuilder, PublicEccParametersBuilder, PublicKeyRsa, KeyDerivationFunctionScheme, EccPoint, /// # RsaDecryptionScheme, HashScheme, SymmetricDefinition, /// # }, /// # }; /// # use std::{env, str::FromStr, convert::TryFrom}; /// # // Create context /// # let mut context = /// # Context::new( /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"), /// # ).expect("Failed to create Context"); /// # /// # let session = context /// # .start_auth_session( /// # None, /// # None, /// # None, /// # SessionType::Hmac, /// # SymmetricDefinition::AES_256_CFB, /// # tss_esapi::interface_types::algorithm::HashingAlgorithm::Sha256, /// # ) /// # .expect("Failed to create session") /// # .expect("Received invalid handle"); /// # let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new() /// # .with_decrypt(true) /// # .with_encrypt(true) /// # .build(); /// # context.tr_sess_set_attributes(session, session_attributes, session_attributes_mask) /// # .expect("Failed to set attributes on session"); /// # context.set_sessions((Some(session), None, None)); /// # let random_digest = context.get_random(16).unwrap(); /// # let key_auth = Auth::try_from(random_digest.value().to_vec()).unwrap(); /// # /// // Create a key suitable for ECDH key generation /// let ecc_parms = PublicEccParametersBuilder::new() /// .with_ecc_scheme( /// EccScheme::EcDh(HashScheme::new(HashingAlgorithm::Sha256)), /// ) /// .with_curve(EccCurve::NistP256) /// .with_is_signing_key(false) /// .with_is_decryption_key(true) /// .with_restricted(false) /// .with_key_derivation_function_scheme(KeyDerivationFunctionScheme::Null) /// .build() /// .unwrap(); /// /// let object_attributes = ObjectAttributesBuilder::new() /// .with_fixed_tpm(true) /// .with_fixed_parent(true) /// .with_sensitive_data_origin(true) /// .with_user_with_auth(true) /// .with_decrypt(true) /// .with_sign_encrypt(false) /// .with_restricted(false) /// .build() /// .unwrap(); /// /// let public = PublicBuilder::new() /// .with_public_algorithm(PublicAlgorithm::Ecc) /// .with_name_hashing_algorithm(HashingAlgorithm::Sha256) /// .with_object_attributes(object_attributes) /// .with_ecc_parameters(ecc_parms) /// .with_ecc_unique_identifier(EccPoint::default()) /// .build() /// .unwrap(); /// /// let key_handle = context /// .create_primary( /// Hierarchy::Owner, /// public, /// Some(key_auth), /// None, /// None, /// None, /// ) /// .unwrap() /// .key_handle; /// /// // Generate ephemeral key pair and a shared secret /// let (z_point, pub_point) = context.ecdh_key_gen(key_handle).unwrap(); /// ``` pub fn ecdh_key_gen(&mut self, key_handle: KeyHandle) -> Result<(EccPoint, EccPoint)> { let mut z_point_ptr = null_mut(); let mut pub_point_ptr = null_mut(); let ret = unsafe { Esys_ECDH_KeyGen( self.mut_context(), key_handle.into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), &mut z_point_ptr, &mut pub_point_ptr, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { let z_point = Context::ffi_data_to_owned(z_point_ptr); let pub_point = Context::ffi_data_to_owned(pub_point_ptr); Ok(( EccPoint::try_from(z_point.point)?, EccPoint::try_from(pub_point.point)?, )) } else { error!("Error when generating ECDH keypair: {}", ret); Err(ret) } } /// Recover Z value from a public point and a private key. /// /// # Arguments /// * `key_handle` - A [KeyHandle] of ECC key which curve parameters will be used /// to generate the ephemeral key. /// * `in_point` - An [EccPoint] on the curve of the key referenced by `key_handle` /// /// # Details /// This command uses the TPM to recover the Z value from a public point and a private key. /// It will perform the multiplication of the provided `in_point` with the private key and /// return the coordinates of the resultant point. /// /// # Example /// /// ```rust /// # use tss_esapi::{ /// # Context, TctiNameConf, /// # attributes::{SessionAttributesBuilder, ObjectAttributesBuilder}, /// # constants::SessionType, /// # interface_types::{ /// # algorithm::{ /// # HashingAlgorithm, PublicAlgorithm, RsaDecryptAlgorithm, /// # }, /// # ecc::EccCurve, /// # resource_handles::Hierarchy, /// # }, /// # structures::{ /// # Auth, Data, EccScheme, PublicBuilder, PublicEccParametersBuilder, PublicKeyRsa, KeyDerivationFunctionScheme, EccPoint, /// # RsaDecryptionScheme, HashScheme, SymmetricDefinition, /// # }, /// # }; /// # use std::{env, str::FromStr, convert::TryFrom}; /// # // Create context /// # let mut context = /// # Context::new( /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"), /// # ).expect("Failed to create Context"); /// # /// # let session = context /// # .start_auth_session( /// # None, /// # None, /// # None, /// # SessionType::Hmac, /// # SymmetricDefinition::AES_256_CFB, /// # tss_esapi::interface_types::algorithm::HashingAlgorithm::Sha256, /// # ) /// # .expect("Failed to create session") /// # .expect("Received invalid handle"); /// # let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new() /// # .with_decrypt(true) /// # .with_encrypt(true) /// # .build(); /// # context.tr_sess_set_attributes(session, session_attributes, session_attributes_mask) /// # .expect("Failed to set attributes on session"); /// # context.set_sessions((Some(session), None, None)); /// # let random_digest = context.get_random(16).unwrap(); /// # let key_auth = Auth::try_from(random_digest.value().to_vec()).unwrap(); /// # /// // Create a key suitable for ECDH key generation /// let ecc_parms = PublicEccParametersBuilder::new() /// .with_ecc_scheme( /// EccScheme::EcDh(HashScheme::new(HashingAlgorithm::Sha256)), /// ) /// .with_curve(EccCurve::NistP256) /// .with_is_signing_key(false) /// .with_is_decryption_key(true) /// .with_restricted(false) /// .with_key_derivation_function_scheme(KeyDerivationFunctionScheme::Null) /// .build() /// .unwrap(); /// /// let object_attributes = ObjectAttributesBuilder::new() /// .with_fixed_tpm(true) /// .with_fixed_parent(true) /// .with_sensitive_data_origin(true) /// .with_user_with_auth(true) /// .with_decrypt(true) /// .with_sign_encrypt(false) /// .with_restricted(false) /// .build() /// .unwrap(); /// /// let public = PublicBuilder::new() /// .with_public_algorithm(PublicAlgorithm::Ecc) /// .with_name_hashing_algorithm(HashingAlgorithm::Sha256) /// .with_object_attributes(object_attributes) /// .with_ecc_parameters(ecc_parms) /// .with_ecc_unique_identifier(EccPoint::default()) /// .build() /// .unwrap(); /// /// let key_handle = context /// .create_primary( /// Hierarchy::Owner, /// public, /// Some(key_auth), /// None, /// None, /// None, /// ) /// .unwrap() /// .key_handle; /// /// // Generate ephemeral key pair and a shared secret /// let (z_point, pub_point) = context.ecdh_key_gen(key_handle).unwrap(); /// let z_point_gen = context.ecdh_z_gen(key_handle, pub_point).unwrap(); /// assert_eq!(z_point.x().value(), z_point_gen.x().value()); /// ``` pub fn ecdh_z_gen(&mut self, key_handle: KeyHandle, in_point: EccPoint) -> Result { let mut out_point_ptr = null_mut(); let ret = unsafe { Esys_ECDH_ZGen( self.mut_context(), key_handle.into(), self.required_session_1()?, self.optional_session_2(), self.optional_session_3(), &in_point.into(), &mut out_point_ptr, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { let out_point = Context::ffi_data_to_owned(out_point_ptr); EccPoint::try_from(out_point.point) } else { error!("Error when performing ECDH ZGen: {}", ret); Err(ret) } } // Missing function: ECC_Parameters // Missing function: ZGen_2Phase } tss-esapi-7.4.0/src/context/tpm_commands/attached_components.rs000064400000000000000000000003741046102023000230740ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::Context; impl Context { // Missing function: AC_GetCapability // Missing function: AC_Send // Missing function: Policy_AC_SendSelect } tss-esapi-7.4.0/src/context/tpm_commands/attestation_commands.rs000064400000000000000000000166761046102023000233060ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ handles::{KeyHandle, ObjectHandle}, structures::{Attest, AttestBuffer, Data, PcrSelectionList, Signature, SignatureScheme}, tss2_esys::{Esys_Certify, Esys_Quote}, Context, Error, Result, }; use log::error; use std::convert::TryFrom; use std::ptr::null_mut; impl Context { /// Prove that an object is loaded in the TPM /// /// # Arguments /// * `object_handle` - Handle of the object to be certified /// * `signing_key_handle` - Handle of the key used to sign the attestation buffer /// * `qualifying_data` - Qualifying data /// * `signing_scheme` - Signing scheme to use if the scheme for `signing_key_handle` is `Null`. /// /// The object may be any object that is loaded with [Self::load()] or [Self::create_primary()]. An object that /// only has its public area loaded may not be certified. /// /// The `signing_key_handle` must be usable for signing. /// /// If `signing_key_handle` has the Restricted attribute set to `true` then `signing_scheme` must be /// [SignatureScheme::Null]. /// /// # Returns /// The command returns a tuple consisting of: /// * `attest_data` - TPM-generated attestation data. /// * `signature` - Signature for the attestation data. /// /// # Errors /// * if the qualifying data provided is too long, a `WrongParamSize` wrapper error will be returned /// /// # Examples /// /// ```rust /// # use tss_esapi::{Context, TctiNameConf}; /// # use std::convert::TryFrom; /// # use tss_esapi::{ /// # abstraction::cipher::Cipher, /// # handles::KeyHandle, /// # interface_types::{ /// # algorithm::{HashingAlgorithm, RsaSchemeAlgorithm, SignatureSchemeAlgorithm}, /// # key_bits::RsaKeyBits, /// # resource_handles::Hierarchy, /// # }, /// # structures::{ /// # RsaExponent, RsaScheme, SymmetricDefinition, /// # }, /// # utils::{create_unrestricted_signing_rsa_public, create_restricted_decryption_rsa_public}, /// # }; /// use std::convert::TryInto; /// use tss_esapi::{ /// structures::{Data, SignatureScheme}, /// interface_types::session_handles::AuthSession, /// }; /// # let mut context = /// # Context::new( /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"), /// # ).expect("Failed to create Context"); /// let qualifying_data = vec![0xff; 16]; /// # let signing_key_pub = create_unrestricted_signing_rsa_public( /// # RsaScheme::create(RsaSchemeAlgorithm::RsaSsa, Some(HashingAlgorithm::Sha256)) /// # .expect("Failed to create RSA scheme"), /// # RsaKeyBits::Rsa2048, /// # RsaExponent::default(), /// # ) /// # .expect("Failed to create an unrestricted signing rsa public structure"); /// # let sign_key_handle = context /// # .execute_with_nullauth_session(|ctx| { /// # ctx.create_primary(Hierarchy::Owner, signing_key_pub, None, None, None, None) /// # }) /// # .unwrap() /// # .key_handle; /// # let decryption_key_pub = create_restricted_decryption_rsa_public( /// # Cipher::aes_256_cfb() /// # .try_into() /// # .expect("Failed to create symmetric object"), /// # RsaKeyBits::Rsa2048, /// # RsaExponent::default(), /// # ) /// # .expect("Failed to create a restricted decryption rsa public structure"); /// # let obj_key_handle = context /// # .execute_with_nullauth_session(|ctx| { /// # ctx.create_primary( /// # Hierarchy::Owner, /// # decryption_key_pub, /// # None, /// # None, /// # None, /// # None, /// # ) /// # }) /// # .unwrap() /// # .key_handle; /// let (attest, signature) = context /// .execute_with_sessions( /// ( /// Some(AuthSession::Password), /// Some(AuthSession::Password), /// None, /// ), /// |ctx| { /// ctx.certify( /// obj_key_handle.into(), /// sign_key_handle, /// Data::try_from(qualifying_data).unwrap(), /// SignatureScheme::Null, /// ) /// }, /// ) /// .expect("Failed to certify object handle"); /// ``` pub fn certify( &mut self, object_handle: ObjectHandle, signing_key_handle: KeyHandle, qualifying_data: Data, signing_scheme: SignatureScheme, ) -> Result<(Attest, Signature)> { let mut certify_info_ptr = null_mut(); let mut signature_ptr = null_mut(); let ret = unsafe { Esys_Certify( self.mut_context(), object_handle.into(), signing_key_handle.into(), self.required_session_1()?, self.required_session_2()?, self.optional_session_3(), &qualifying_data.into(), &signing_scheme.into(), &mut certify_info_ptr, &mut signature_ptr, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { let certify_info = Context::ffi_data_to_owned(certify_info_ptr); let signature = Context::ffi_data_to_owned(signature_ptr); Ok(( Attest::try_from(AttestBuffer::try_from(certify_info)?)?, Signature::try_from(signature)?, )) } else { error!("Error in certifying: {}", ret); Err(ret) } } // Missing function: CertifyCreation /// Generate a quote on the selected PCRs /// /// # Errors /// * if the qualifying data provided is too long, a `WrongParamSize` wrapper error will be returned pub fn quote( &mut self, signing_key_handle: KeyHandle, qualifying_data: Data, signing_scheme: SignatureScheme, pcr_selection_list: PcrSelectionList, ) -> Result<(Attest, Signature)> { let mut quoted_ptr = null_mut(); let mut signature_ptr = null_mut(); let ret = unsafe { Esys_Quote( self.mut_context(), signing_key_handle.into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), &qualifying_data.into(), &signing_scheme.into(), &pcr_selection_list.into(), &mut quoted_ptr, &mut signature_ptr, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { let quoted = Context::ffi_data_to_owned(quoted_ptr); let signature = Context::ffi_data_to_owned(signature_ptr); Ok(( Attest::try_from(AttestBuffer::try_from(quoted)?)?, Signature::try_from(signature)?, )) } else { error!("Error in quoting PCR: {}", ret); Err(ret) } } // Missing function: GetSessionAuditDigest // Missing function: GestCommandAuditDigest // Missing function: GetTime // Missing function: CertifyX509 } tss-esapi-7.4.0/src/context/tpm_commands/authenticated_countdown_timer.rs000064400000000000000000000002531046102023000251700ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::Context; impl Context { // Missing function: ACT_SetTimeout } tss-esapi-7.4.0/src/context/tpm_commands/capability_commands.rs000064400000000000000000000065271046102023000230620ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ constants::CapabilityType, interface_types::YesNo, structures::{CapabilityData, PublicParameters}, tss2_esys::{Esys_GetCapability, Esys_TestParms}, Context, Error, Result, }; use log::{error, warn}; use std::convert::TryFrom; use std::ptr::null_mut; impl Context { /// Get current capability information about the TPM. /// /// # Warning /// - If [CapabilityType::AuthPolicies] is used but the version of the /// tpm2-tss library used does not have the 'authPolicies' field /// in the TPMU_CAPABILITIES defined then the call using this method /// will fail. /// /// - If [CapabilityType::Act] is used but the the version of the /// tpm2-tss library used does not have the 'actData' field in the /// TPMU_CAPABILITIES defined then the call using this method will fail. /// /// # Example /// /// ```rust /// # use tss_esapi::{Context, TctiNameConf}; /// # // Create context /// # let mut context = /// # Context::new( /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"), /// # ).expect("Failed to create Context"); /// # /// use tss_esapi::constants::CapabilityType; /// /// let (_capabilities, _more) = context /// .get_capability(CapabilityType::Algorithms, 0, 80) /// .expect("Failed to call get_capability"); /// ``` pub fn get_capability( &mut self, capability: CapabilityType, property: u32, property_count: u32, ) -> Result<(CapabilityData, bool)> { let mut capability_data_ptr = null_mut(); let mut more_data = YesNo::No.into(); let ret = unsafe { Esys_GetCapability( self.mut_context(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), capability.into(), property, property_count, &mut more_data, &mut capability_data_ptr, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(( CapabilityData::try_from(Context::ffi_data_to_owned(capability_data_ptr))?, YesNo::try_from(more_data)?.into(), )) } else { error!("Error when getting capabilities: {}", ret); Err(ret) } } /// Test if the given parameters are supported by the TPM. /// /// # Errors /// * if any of the public parameters is not compatible with the TPM, /// an `Err` containing the specific unmarshalling error will be returned. pub fn test_parms(&mut self, public_parmeters: PublicParameters) -> Result<()> { let ret = unsafe { Esys_TestParms( self.mut_context(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), &public_parmeters.into(), ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(()) } else { warn!("Parameters under test could not be unmarshalled: {}", ret); Err(ret) } } } tss-esapi-7.4.0/src/context/tpm_commands/clocks_and_timers.rs000064400000000000000000000003611046102023000225310ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::Context; impl Context { // Missing function: ReadClock // Missing function: ClockSet // Missing function: ClockRateAdjust } tss-esapi-7.4.0/src/context/tpm_commands/command_audit.rs000064400000000000000000000002661046102023000216560ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::Context; impl Context { // Missing function: SetCommandCodeAuditStatus } tss-esapi-7.4.0/src/context/tpm_commands/context_management.rs000064400000000000000000000477071046102023000227450ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ context::handle_manager::HandleDropAction, handles::{handle_conversion::TryIntoNotNone, AuthHandle, ObjectHandle, PersistentTpmHandle}, interface_types::{dynamic_handles::Persistent, resource_handles::Provision}, tss2_esys::{Esys_ContextLoad, Esys_ContextSave, Esys_EvictControl, Esys_FlushContext}, utils::TpmsContext, Context, Error, Result, }; use log::error; use std::convert::{TryFrom, TryInto}; use std::ptr::null_mut; impl Context { /// Save the context of an object from the TPM and return it. /// /// # Errors /// * if conversion from `TPMS_CONTEXT` to `TpmsContext` fails, a `WrongParamSize` error will /// be returned pub fn context_save(&mut self, handle: ObjectHandle) -> Result { let mut context_ptr = null_mut(); let ret = unsafe { Esys_ContextSave(self.mut_context(), handle.into(), &mut context_ptr) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { TpmsContext::try_from(Context::ffi_data_to_owned(context_ptr)) } else { error!("Error in saving context: {}", ret); Err(ret) } } /// Load a previously saved context into the TPM and return the object handle. /// /// # Errors /// * if conversion from `TpmsContext` to the native `TPMS_CONTEXT` fails, a `WrongParamSize` /// error will be returned pub fn context_load(&mut self, context: TpmsContext) -> Result { let mut loaded_handle = ObjectHandle::None.into(); let ret = unsafe { Esys_ContextLoad(self.mut_context(), &context.try_into()?, &mut loaded_handle) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { self.handle_manager .add_handle(loaded_handle.into(), HandleDropAction::Flush)?; Ok(loaded_handle.into()) } else { error!("Error in loading context: {}", ret); Err(ret) } } /// Flush the context of an object from the TPM. /// /// # Example /// /// ```rust /// # use tss_esapi::{ /// # Context, tcti_ldr::TctiNameConf, structures::Auth, /// # constants::{ /// # tss::{TPMA_SESSION_DECRYPT, TPMA_SESSION_ENCRYPT}, /// # SessionType, /// # }, /// # interface_types::{ /// # resource_handles::Hierarchy, /// # algorithm::{HashingAlgorithm, RsaSchemeAlgorithm}, /// # key_bits::RsaKeyBits, /// # }, /// # utils::create_unrestricted_signing_rsa_public, /// # attributes::SessionAttributesBuilder, /// # structures::{SymmetricDefinition, RsaExponent, RsaScheme}, /// # }; /// # use std::convert::TryFrom; /// # use std::str::FromStr; /// # // Create context /// # let mut context = /// # Context::new( /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"), /// # ).expect("Failed to create Context"); /// /// // Create session for a key /// let session = context /// .start_auth_session( /// None, /// None, /// None, /// SessionType::Hmac, /// SymmetricDefinition::AES_256_CFB, /// HashingAlgorithm::Sha256, /// ) /// .expect("Failed to create session") /// .expect("Received invalid handle"); /// let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new() /// .with_decrypt(true) /// .with_encrypt(true) /// .build(); /// context.tr_sess_set_attributes(session, session_attributes, session_attributes_mask) /// .expect("Failed to set attributes on session"); /// /// // Create public area for a rsa key /// let public_area = create_unrestricted_signing_rsa_public( /// RsaScheme::create(RsaSchemeAlgorithm::RsaSsa, Some(HashingAlgorithm::Sha256)) /// .expect("Failed to create RSA scheme"), /// RsaKeyBits::Rsa2048, /// RsaExponent::default(), /// ) /// .expect("Failed to create rsa public area"); /// /// // Execute context methods using the session /// context.execute_with_session(Some(session), |ctx| { /// let random_digest = ctx.get_random(16) /// .expect("Call to get_random failed"); /// let key_auth = Auth::try_from(random_digest.value().to_vec()) /// .expect("Failed to create Auth"); /// let key_handle = ctx /// .create_primary( /// Hierarchy::Owner, /// public_area, /// Some(key_auth), /// None, /// None, /// None, /// ) /// .expect("Failed to create primary key") /// .key_handle; /// /// // Flush the context of the key. /// ctx.flush_context(key_handle.into()).expect("Call to flush_context failed"); /// assert!(ctx.read_public(key_handle).is_err()); /// }) /// ``` pub fn flush_context(&mut self, handle: ObjectHandle) -> Result<()> { let ret = unsafe { Esys_FlushContext(self.mut_context(), handle.try_into_not_none()?) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { self.handle_manager.set_as_flushed(handle)?; Ok(()) } else { error!("Error in flushing context: {}", ret); Err(ret) } } /// Evicts persistent objects or allows certain transient objects /// to be made persistent. /// /// # Details /// In order to be able to perform this action an authorization /// session is required. /// /// # Arguments /// * `auth` - An a handle used for authorization that is limited to the ones /// specified in [Provision]. /// * `object_handle` - The handle of a loaded object. /// * `persistent` - If the `object_handle` is transient object then this /// then this will become the persistent handle of that /// object. If the `object_handle` refers to a persistent /// object then this shall be the persistent handle of that /// object. /// /// # Returns /// If the input `object_handle` was transient object then it will be made /// persistent and the returned [ObjectHandle] will refer to the persistent /// object. /// /// If the input `object_handle` refers to a persistent object the returned /// value will be ObjectHandle::None and the input `object_handle` will not /// be valid after this call is made. /// /// # Example /// /// Make transient object persistent: /// ```rust /// # use tss_esapi::{ /// # Context, tcti_ldr::TctiNameConf, Result, /// # constants::{ /// # SessionType, CapabilityType, /// # tss::TPM2_PERSISTENT_FIRST, /// # }, /// # handles::PcrHandle, /// # structures::{Digest, CapabilityData, Auth, RsaExponent, SymmetricDefinitionObject}, /// # interface_types::{ /// # resource_handles::Hierarchy, /// # key_bits::RsaKeyBits, /// # }, /// # handles::{ObjectHandle, TpmHandle, PersistentTpmHandle}, /// # utils::create_restricted_decryption_rsa_public, /// # tss2_esys::TPM2_HANDLE, /// # }; /// # use std::{env, str::FromStr, convert::TryFrom}; /// # // Create context /// # let mut context = /// # Context::new( /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"), /// # ).expect("Failed to create Context"); /// # // Create persistent TPM handle with /// # let persistent_tpm_handle = /// # PersistentTpmHandle::new(u32::from_be_bytes([0x81, 0x00, 0x00, 0x01])) /// # .expect("Failed to create Persistent TPM handle"); /// # // -----> REMOVE ANY PREVIOUS HANDLES <--------------- /// # let mut property = TPM2_PERSISTENT_FIRST; /// # while let Ok((capability_data, more_data_available)) = /// # context.get_capability(CapabilityType::Handles, property, 1) /// # { /// # if let CapabilityData::Handles(persistent_handles) = capability_data { /// # if let Some(&retrieved_persistent_handle) = persistent_handles.first() { /// # if retrieved_persistent_handle == persistent_tpm_handle.into() { /// # let handle = context /// # .tr_from_tpm_public(TpmHandle::Persistent(persistent_tpm_handle)) /// # .expect("Failed to retrieve handle from TPM"); /// # context.execute_with_session(Some(tss_esapi::interface_types::session_handles::AuthSession::Password), |ctx| { /// # ctx /// # .evict_control( /// # tss_esapi::interface_types::resource_handles::Provision::Owner, /// # handle, /// # tss_esapi::interface_types::dynamic_handles::Persistent::Persistent(persistent_tpm_handle), /// # ) /// # .expect("Failed to evict persitent handle") /// # }); /// # break; /// # } /// # if more_data_available { /// # property = TPM2_HANDLE::from(retrieved_persistent_handle) + 1; /// # } /// # } /// # } /// # if !more_data_available { /// # break; /// # } /// # } /// # let transient_object_handle = context.execute_with_session(Some(tss_esapi::interface_types::session_handles::AuthSession::Password), |ctx| { /// # // Create primary key handle /// # let auth_value_primary = Auth::try_from(vec![1, 2, 3, 4, 5]) /// # .expect("Failed to crate auth value for primary key"); /// # ctx /// # .create_primary( /// # Hierarchy::Owner, /// # create_restricted_decryption_rsa_public( /// # SymmetricDefinitionObject::AES_256_CFB, /// # RsaKeyBits::Rsa2048, /// # RsaExponent::default(), /// # ).expect("Failed to Public structure for key"), /// # Some(auth_value_primary), /// # None, /// # None, /// # None, /// # ) /// # .map(|v| ObjectHandle::from(v.key_handle)) /// # .expect("Failed to create primary key") /// # }); /// use tss_esapi::{ /// interface_types::{ /// resource_handles::Provision, /// dynamic_handles::Persistent, /// session_handles::AuthSession, /// }, /// }; /// // Create interface type Persistent by using the persistent tpm handle. /// let persistent = Persistent::Persistent(persistent_tpm_handle); /// // Make transient_object_handle persistent. /// // An authorization session is required! /// let mut persistent_object_handle = context.execute_with_session(Some(AuthSession::Password), |ctx| { /// ctx /// .evict_control(Provision::Owner, transient_object_handle.into(), persistent) /// .expect("Failed to make the transient_object_handle handle persistent") /// }); /// # assert_ne!(persistent_object_handle, ObjectHandle::Null); /// # assert_ne!(persistent_object_handle, ObjectHandle::None); /// # // Flush out the transient_object_handle /// # context /// # .flush_context(ObjectHandle::from(transient_object_handle)) /// # .expect("Failed to flush context"); /// # // Close the persistent_handle returned by evict_control /// # context /// # .tr_close(&mut persistent_object_handle) /// # .expect("Failed to close persistent handle"); /// # // Retrieve the handle from the tpm again. /// # let retireved_persistent_handle = context.execute_without_session(|ctx| { /// # ctx.tr_from_tpm_public(TpmHandle::Persistent(persistent_tpm_handle)) /// # .expect("Failed to load the persistent handle") /// # }); /// # // Evict the persitent handle from the tpm /// # let _ = context.execute_with_session(Some(AuthSession::Password), |ctx| { /// # ctx /// # .evict_control(Provision::Owner, retireved_persistent_handle, persistent) /// # .expect("Failed to evict persistent handle") /// # }); /// # assert_ne!(retireved_persistent_handle, ObjectHandle::None); /// ``` /// /// Make persistent object transient /// ```rust /// # use tss_esapi::{ /// # Context, tcti_ldr::TctiNameConf, Result, /// # constants::{ /// # SessionType, CapabilityType, /// # tss::TPM2_PERSISTENT_FIRST, /// # }, /// # handles::PcrHandle, /// # structures::{Digest, CapabilityData, Auth, RsaExponent, SymmetricDefinitionObject}, /// # interface_types::{ /// # resource_handles::Hierarchy, /// # key_bits::RsaKeyBits, /// # }, /// # handles::{ObjectHandle, TpmHandle, PersistentTpmHandle}, /// # utils::create_restricted_decryption_rsa_public, /// # tss2_esys::TPM2_HANDLE, /// # }; /// # use std::{env, str::FromStr, convert::TryFrom}; /// # // Create context /// # let mut context = /// # Context::new( /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"), /// # ).expect("Failed to create Context"); /// # // Create persistent TPM handle with /// # let persistent_tpm_handle = /// # PersistentTpmHandle::new(u32::from_be_bytes([0x81, 0x00, 0x00, 0x01])) /// # .expect("Failed to create Persistent TPM handle"); /// # // -----> REMOVE ANY PREVIOUS HANDLES <--------------- /// # let mut property = TPM2_PERSISTENT_FIRST; /// # while let Ok((capability_data, more_data_available)) = /// # context.get_capability(CapabilityType::Handles, property, 1) /// # { /// # if let CapabilityData::Handles(persistent_handles) = capability_data { /// # if let Some(&retrieved_persistent_handle) = persistent_handles.first() { /// # if retrieved_persistent_handle == persistent_tpm_handle.into() { /// # let handle = context /// # .tr_from_tpm_public(TpmHandle::Persistent(persistent_tpm_handle)) /// # .expect("Failed to retrieve handle from TPM"); /// # context.execute_with_session(Some(tss_esapi::interface_types::session_handles::AuthSession::Password), |ctx| { /// # ctx /// # .evict_control( /// # tss_esapi::interface_types::resource_handles::Provision::Owner, /// # handle, /// # tss_esapi::interface_types::dynamic_handles::Persistent::Persistent(persistent_tpm_handle), /// # ) /// # .expect("Failed to evict persitent handle") /// # }); /// # break; /// # } /// # if more_data_available { /// # property = TPM2_HANDLE::from(retrieved_persistent_handle) + 1; /// # } /// # } /// # } /// # if !more_data_available { /// # break; /// # } /// # } /// # let transient_object_handle = context.execute_with_session(Some(tss_esapi::interface_types::session_handles::AuthSession::Password), |ctx| { /// # // Create primary key handle /// # let auth_value_primary = Auth::try_from(vec![1, 2, 3, 4, 5]) /// # .expect("Failed to crate auth value for primary key"); /// # ctx /// # .create_primary( /// # Hierarchy::Owner, /// # create_restricted_decryption_rsa_public( /// # SymmetricDefinitionObject::AES_256_CFB, /// # RsaKeyBits::Rsa2048, /// # RsaExponent::default(), /// # ).expect("Failed to Public structure for key"), /// # Some(auth_value_primary), /// # None, /// # None, /// # None, /// # ) /// # .map(|v| ObjectHandle::from(v.key_handle)) /// # .expect("Failed to create primary key") /// # }); /// use tss_esapi::{ /// interface_types::{ /// resource_handles::Provision, /// dynamic_handles::Persistent, /// session_handles::AuthSession, /// }, /// }; /// // Create interface type Persistent by using the persistent tpm handle. /// let persistent = Persistent::Persistent(persistent_tpm_handle); /// # // Evict control to make transient_object_handle persistent. /// # // An authorization session is required! /// # let mut persistent_object_handle = context.execute_with_session(Some(AuthSession::Password), |ctx| { /// # ctx /// # .evict_control(Provision::Owner, transient_object_handle.into(), persistent) /// # .expect("Failed to make the transient_object_handle handle persistent") /// # }); /// # assert_ne!(persistent_object_handle, ObjectHandle::Null); /// # assert_ne!(persistent_object_handle, ObjectHandle::None); /// # // Flush out the transient_object_handle /// # context /// # .flush_context(ObjectHandle::from(transient_object_handle)) /// # .expect("Failed to flush context"); /// # // Close the persistent_handle returned by evict_control /// # context /// # .tr_close(&mut persistent_object_handle) /// # .expect("Failed to close persistent handle"); /// # // Retrieve the handle from the tpm again. /// # let retrieved_persistent_handle = context.execute_without_session(|ctx| { /// # ctx.tr_from_tpm_public(TpmHandle::Persistent(persistent_tpm_handle)) /// # .expect("Failed to load the persistent handle") /// # }); /// // Evict the persitent handle from the tpm /// // An authorization session is required! /// let _ = context.execute_with_session(Some(AuthSession::Password), |ctx| { /// ctx /// .evict_control(Provision::Owner, retrieved_persistent_handle, persistent) /// .expect("Failed to evict persistent handle") /// }); /// # assert_ne!(retrieved_persistent_handle, ObjectHandle::None); /// ``` pub fn evict_control( &mut self, auth: Provision, object_handle: ObjectHandle, persistent: Persistent, ) -> Result { let mut new_object_handle = ObjectHandle::None.into(); let ret = unsafe { Esys_EvictControl( self.mut_context(), AuthHandle::from(auth).into(), object_handle.into(), self.required_session_1()?, self.optional_session_2(), self.optional_session_3(), PersistentTpmHandle::from(persistent).into(), &mut new_object_handle, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { let new_object_handle = ObjectHandle::from(new_object_handle); // If you look at the specification and see that it says ESYS_TR_NULL // then that is an error in the spec. ESYS_TR_NULL was renamed to // ESYS_TR NONE. if new_object_handle.is_none() { self.handle_manager.set_as_closed(object_handle)?; } else { self.handle_manager .add_handle(new_object_handle, HandleDropAction::Close)?; } Ok(new_object_handle) } else { error!("Error in evict control: {}", ret); Err(ret) } } } tss-esapi-7.4.0/src/context/tpm_commands/dictionary_attack_functions.rs000064400000000000000000000003521046102023000246320ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::Context; impl Context { // Missing function: DictionaryAttackLockReset // Missing function: DictionaryAttackParameters } tss-esapi-7.4.0/src/context/tpm_commands/duplication_commands.rs000064400000000000000000000634741046102023000232600ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::Context; use crate::{ handles::ObjectHandle, structures::{Data, EncryptedSecret, Private, Public, SymmetricDefinitionObject}, tss2_esys::{Esys_Duplicate, Esys_Import}, Error, Result, }; use log::error; use std::convert::{TryFrom, TryInto}; use std::ptr::null_mut; impl Context { /// Duplicate a loaded object so that it may be used in a different hierarchy. /// /// # Details /// This command duplicates a loaded object so that it may be used in a different hierarchy. /// The new parent key for the duplicate may be on the same or different TPM or the Null hierarchy. /// Only the public area of `new_parent_handle` is required to be loaded. /// /// # Arguments /// * `object_to_duplicate` - An [ObjectHandle] of the object that will be duplicated. /// * `new_parent_handle` - An [ObjectHandle] of the new parent. /// * `encryption_key_in` - An optional encryption key. If this parameter is `None` /// then a [default value][Default::default] is used. /// * `symmetric_alg` - Symmetric algorithm to be used for the inner wrapper. /// /// The `object_to_duplicate` need to be have Fixed TPM and Fixed Parent attributes set to `false`. /// /// # Returns /// The command returns a tuple consisting of: /// * `encryption_key_out` - TPM generated, symmetric encryption key for the inner wrapper if /// `symmetric_alg` is not `Null`. /// * `duplicate` - Private area that may be encrypted. /// * `out_sym_seed` - Seed protected by the asymmetric algorithms of new parent. /// /// # Example /// /// ```rust /// # use std::convert::{TryFrom, TryInto}; /// # use tss_esapi::attributes::{ObjectAttributesBuilder, SessionAttributesBuilder}; /// # use tss_esapi::constants::{CommandCode, SessionType}; /// # use tss_esapi::handles::ObjectHandle; /// # use tss_esapi::interface_types::{ /// # algorithm::{HashingAlgorithm, PublicAlgorithm}, /// # key_bits::RsaKeyBits, /// # resource_handles::Hierarchy, /// # session_handles::PolicySession, /// # }; /// # use tss_esapi::structures::SymmetricDefinition; /// # use tss_esapi::structures::{ /// # PublicBuilder, PublicKeyRsa, PublicRsaParametersBuilder, RsaScheme, /// # RsaExponent, /// # }; /// use tss_esapi::structures::SymmetricDefinitionObject; /// # use tss_esapi::abstraction::cipher::Cipher; /// # use tss_esapi::{Context, TctiNameConf}; /// # /// # let mut context = // ... /// # Context::new( /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"), /// # ).expect("Failed to create Context"); /// # /// # let trial_session = context /// # .start_auth_session( /// # None, /// # None, /// # None, /// # SessionType::Trial, /// # SymmetricDefinition::AES_256_CFB, /// # HashingAlgorithm::Sha256, /// # ) /// # .expect("Start auth session failed") /// # .expect("Start auth session returned a NONE handle"); /// # /// # let (policy_auth_session_attributes, policy_auth_session_attributes_mask) = /// # SessionAttributesBuilder::new() /// # .with_decrypt(true) /// # .with_encrypt(true) /// # .build(); /// # context /// # .tr_sess_set_attributes( /// # trial_session, /// # policy_auth_session_attributes, /// # policy_auth_session_attributes_mask, /// # ) /// # .expect("tr_sess_set_attributes call failed"); /// # /// # let policy_session = PolicySession::try_from(trial_session) /// # .expect("Failed to convert auth session into policy session"); /// # /// # context /// # .policy_auth_value(policy_session) /// # .expect("Policy auth value"); /// # /// # context /// # .policy_command_code(policy_session, CommandCode::Duplicate) /// # .expect("Policy command code"); /// # /// # /// Digest of the policy that allows duplication /// # let digest = context /// # .policy_get_digest(policy_session) /// # .expect("Could retrieve digest"); /// # /// # drop(context); /// # let mut context = // ... /// # Context::new( /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"), /// # ).expect("Failed to create Context"); /// # /// # let session = context /// # .start_auth_session( /// # None, /// # None, /// # None, /// # SessionType::Hmac, /// # SymmetricDefinition::AES_256_CFB, /// # HashingAlgorithm::Sha256, /// # ) /// # .expect("Start auth session failed") /// # .expect("Start auth session returned a NONE handle"); /// # /// # let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new() /// # .with_decrypt(true) /// # .with_encrypt(true) /// # .build(); /// # /// # context.tr_sess_set_attributes( /// # session, /// # session_attributes, /// # session_attributes_mask, /// # ).unwrap(); /// # /// # context.set_sessions((Some(session), None, None)); /// # /// # // Attributes of parent objects. The `restricted` attribute need /// # // to be `true` so that parents can act as storage keys. /// # let parent_object_attributes = ObjectAttributesBuilder::new() /// # .with_fixed_tpm(true) /// # .with_fixed_parent(true) /// # .with_sensitive_data_origin(true) /// # .with_user_with_auth(true) /// # .with_decrypt(true) /// # .with_sign_encrypt(false) /// # .with_restricted(true) /// # .build() /// # .unwrap(); /// # /// # let parent_public = PublicBuilder::new() /// # .with_public_algorithm(PublicAlgorithm::Rsa) /// # .with_name_hashing_algorithm(HashingAlgorithm::Sha256) /// # .with_object_attributes(parent_object_attributes) /// # .with_rsa_parameters( /// # PublicRsaParametersBuilder::new_restricted_decryption_key( /// # Cipher::aes_256_cfb().try_into().unwrap(), /// # RsaKeyBits::Rsa2048, /// # RsaExponent::default(), /// # ) /// # .build() /// # .unwrap(), /// # ) /// # .with_rsa_unique_identifier(PublicKeyRsa::default()) /// # .build() /// # .unwrap(); /// # /// # let parent_of_object_to_duplicate_handle = context /// # .create_primary( /// # Hierarchy::Owner, /// # parent_public.clone(), /// # None, /// # None, /// # None, /// # None, /// # ) /// # .unwrap() /// # .key_handle; /// # /// # // Fixed TPM and Fixed Parent should be "false" for an object /// # // to be eligible for duplication /// # let object_attributes = ObjectAttributesBuilder::new() /// # .with_fixed_tpm(false) /// # .with_fixed_parent(false) /// # .with_sensitive_data_origin(true) /// # .with_user_with_auth(true) /// # .with_decrypt(true) /// # .with_sign_encrypt(true) /// # .with_restricted(false) /// # .build() /// # .expect("Attributes to be valid"); /// # /// # let public_child = PublicBuilder::new() /// # .with_public_algorithm(PublicAlgorithm::Rsa) /// # .with_name_hashing_algorithm(HashingAlgorithm::Sha256) /// # .with_object_attributes(object_attributes) /// # .with_auth_policy(digest) /// # .with_rsa_parameters( /// # PublicRsaParametersBuilder::new() /// # .with_scheme(RsaScheme::Null) /// # .with_key_bits(RsaKeyBits::Rsa2048) /// # .with_is_signing_key(true) /// # .with_is_decryption_key(true) /// # .with_restricted(false) /// # .build() /// # .expect("Params to be valid"), /// # ) /// # .with_rsa_unique_identifier(PublicKeyRsa::default()) /// # .build() /// # .expect("public to be valid"); /// # /// # let result = context /// # .create( /// # parent_of_object_to_duplicate_handle, /// # public_child, /// # None, /// # None, /// # None, /// # None, /// # ) /// # .unwrap(); /// # /// # let object_to_duplicate_handle: ObjectHandle = context /// # .load( /// # parent_of_object_to_duplicate_handle, /// # result.out_private.clone(), /// # result.out_public, /// # ) /// # .unwrap() /// # .into(); /// # /// # let new_parent_handle: ObjectHandle = context /// # .create_primary( /// # Hierarchy::Owner, /// # parent_public, /// # None, /// # None, /// # None, /// # None, /// # ) /// # .unwrap() /// # .key_handle /// # .into(); /// # /// # context.set_sessions((None, None, None)); /// # /// # // Create a Policy session with the same exact attributes /// # // as the trial session so that the session digest stays /// # // the same. /// # let policy_auth_session = context /// # .start_auth_session( /// # None, /// # None, /// # None, /// # SessionType::Policy, /// # SymmetricDefinition::AES_256_CFB, /// # HashingAlgorithm::Sha256, /// # ) /// # .expect("Start auth session failed") /// # .expect("Start auth session returned a NONE handle"); /// # /// # let (policy_auth_session_attributes, policy_auth_session_attributes_mask) = /// # SessionAttributesBuilder::new() /// # .with_decrypt(true) /// # .with_encrypt(true) /// # .build(); /// # context /// # .tr_sess_set_attributes( /// # policy_auth_session, /// # policy_auth_session_attributes, /// # policy_auth_session_attributes_mask, /// # ) /// # .expect("tr_sess_set_attributes call failed"); /// # /// # let policy_session = PolicySession::try_from(policy_auth_session) /// # .expect("Failed to convert auth session into policy session"); /// # /// # context /// # .policy_auth_value(policy_session) /// # .expect("Policy auth value"); /// # /// # context /// # .policy_command_code(policy_session, CommandCode::Duplicate) /// # .unwrap(); /// # /// # context.set_sessions((Some(policy_auth_session), None, None)); /// /// let (encryption_key_out, duplicate, out_sym_seed) = context /// .duplicate( /// object_to_duplicate_handle, /// new_parent_handle, /// None, /// SymmetricDefinitionObject::Null, /// ) /// .unwrap(); /// # eprintln!("D: {:?}, P: {:?}, S: {:?}", encryption_key_out, duplicate, out_sym_seed); /// ``` pub fn duplicate( &mut self, object_to_duplicate: ObjectHandle, new_parent_handle: ObjectHandle, encryption_key_in: Option, symmetric_alg: SymmetricDefinitionObject, ) -> Result<(Data, Private, EncryptedSecret)> { let mut encryption_key_out_ptr = null_mut(); let mut duplicate_ptr = null_mut(); let mut out_sym_seed_ptr = null_mut(); let ret = unsafe { Esys_Duplicate( self.mut_context(), object_to_duplicate.into(), new_parent_handle.into(), self.required_session_1()?, self.optional_session_2(), self.optional_session_3(), &encryption_key_in.unwrap_or_default().into(), &symmetric_alg.into(), &mut encryption_key_out_ptr, &mut duplicate_ptr, &mut out_sym_seed_ptr, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(( Data::try_from(Context::ffi_data_to_owned(encryption_key_out_ptr))?, Private::try_from(Context::ffi_data_to_owned(duplicate_ptr))?, EncryptedSecret::try_from(Context::ffi_data_to_owned(out_sym_seed_ptr))?, )) } else { error!("Error when performing duplication: {}", ret); Err(ret) } } // Missing function: Rewrap /// Import attaches imported object to a new parent. /// /// # Details /// This command allows an object to be encrypted using the symmetric /// encryption values of a Storage Key. After encryption, the /// object may be loaded and used in the new hierarchy. The /// imported object (duplicate) may be singly encrypted, multiply /// encrypted, or unencrypted. /// /// # Arguments /// * `parent_handle` - An [ObjectHandle] of the new parent for the object. /// * `encryption_key` - An optional symmetric encryption key used as the inner wrapper. /// If `encryption_key` is `None` then a [default value][Default::default] is used. /// * `public` - A [Public] of the imported object. /// * `duplicate` - A symmetrically encrypted duplicated object. /// * `encrypted_secret` - The seed for the symmetric key and HMAC key. /// * `symmetric_alg` - Symmetric algorithm to be used for the inner wrapper. /// /// The `public` is needed to check the integrity value for `duplicate`. /// /// # Returns /// The command returns the sensitive area encrypted with the symmetric key of `parent_handle`. /// /// # Example /// /// ```rust /// # use std::convert::{TryFrom, TryInto}; /// # use tss_esapi::attributes::{ObjectAttributesBuilder, SessionAttributesBuilder}; /// # use tss_esapi::constants::{CommandCode, SessionType}; /// # use tss_esapi::handles::ObjectHandle; /// # use tss_esapi::interface_types::{ /// # algorithm::{HashingAlgorithm, PublicAlgorithm}, /// # key_bits::RsaKeyBits, /// # resource_handles::Hierarchy, /// # session_handles::PolicySession, /// # }; /// # use tss_esapi::structures::SymmetricDefinition; /// # use tss_esapi::structures::{ /// # PublicBuilder, PublicKeyRsa, PublicRsaParametersBuilder, RsaScheme, /// # RsaExponent, /// # }; /// use tss_esapi::structures::SymmetricDefinitionObject; /// # use tss_esapi::abstraction::cipher::Cipher; /// # use tss_esapi::{Context, TctiNameConf}; /// # /// # let mut context = // ... /// # Context::new( /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"), /// # ).expect("Failed to create Context"); /// # /// # let trial_session = context /// # .start_auth_session( /// # None, /// # None, /// # None, /// # SessionType::Trial, /// # SymmetricDefinition::AES_256_CFB, /// # HashingAlgorithm::Sha256, /// # ) /// # .expect("Start auth session failed") /// # .expect("Start auth session returned a NONE handle"); /// # /// # let (policy_auth_session_attributes, policy_auth_session_attributes_mask) = /// # SessionAttributesBuilder::new() /// # .with_decrypt(true) /// # .with_encrypt(true) /// # .build(); /// # context /// # .tr_sess_set_attributes( /// # trial_session, /// # policy_auth_session_attributes, /// # policy_auth_session_attributes_mask, /// # ) /// # .expect("tr_sess_set_attributes call failed"); /// # /// # let policy_session = PolicySession::try_from(trial_session) /// # .expect("Failed to convert auth session into policy session"); /// # /// # context /// # .policy_auth_value(policy_session) /// # .expect("Policy auth value"); /// # /// # context /// # .policy_command_code(policy_session, CommandCode::Duplicate) /// # .expect("Policy command code"); /// # /// # /// Digest of the policy that allows duplication /// # let digest = context /// # .policy_get_digest(policy_session) /// # .expect("Could retrieve digest"); /// # /// # drop(context); /// # let mut context = // ... /// # Context::new( /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"), /// # ).expect("Failed to create Context"); /// # /// # let session = context /// # .start_auth_session( /// # None, /// # None, /// # None, /// # SessionType::Hmac, /// # SymmetricDefinition::AES_256_CFB, /// # HashingAlgorithm::Sha256, /// # ) /// # .expect("Start auth session failed") /// # .expect("Start auth session returned a NONE handle"); /// # /// # let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new() /// # .with_decrypt(true) /// # .with_encrypt(true) /// # .build(); /// # /// # context.tr_sess_set_attributes( /// # session, /// # session_attributes, /// # session_attributes_mask, /// # ).unwrap(); /// # /// # context.set_sessions((Some(session), None, None)); /// # /// # // Attributes of parent objects. The `restricted` attribute need /// # // to be `true` so that parents can act as storage keys. /// # let parent_object_attributes = ObjectAttributesBuilder::new() /// # .with_fixed_tpm(true) /// # .with_fixed_parent(true) /// # .with_sensitive_data_origin(true) /// # .with_user_with_auth(true) /// # .with_decrypt(true) /// # .with_sign_encrypt(false) /// # .with_restricted(true) /// # .build() /// # .unwrap(); /// # /// # let parent_public = PublicBuilder::new() /// # .with_public_algorithm(PublicAlgorithm::Rsa) /// # .with_name_hashing_algorithm(HashingAlgorithm::Sha256) /// # .with_object_attributes(parent_object_attributes) /// # .with_rsa_parameters( /// # PublicRsaParametersBuilder::new_restricted_decryption_key( /// # Cipher::aes_256_cfb().try_into().unwrap(), /// # RsaKeyBits::Rsa2048, /// # RsaExponent::default(), /// # ) /// # .build() /// # .unwrap(), /// # ) /// # .with_rsa_unique_identifier(PublicKeyRsa::default()) /// # .build() /// # .unwrap(); /// # /// # let parent_of_object_to_duplicate_handle = context /// # .create_primary( /// # Hierarchy::Owner, /// # parent_public.clone(), /// # None, /// # None, /// # None, /// # None, /// # ) /// # .unwrap() /// # .key_handle; /// # /// # // Fixed TPM and Fixed Parent should be "false" for an object /// # // to be eligible for duplication /// # let object_attributes = ObjectAttributesBuilder::new() /// # .with_fixed_tpm(false) /// # .with_fixed_parent(false) /// # .with_sensitive_data_origin(true) /// # .with_user_with_auth(true) /// # .with_decrypt(true) /// # .with_sign_encrypt(true) /// # .with_restricted(false) /// # .build() /// # .expect("Attributes to be valid"); /// # /// # let public_child = PublicBuilder::new() /// # .with_public_algorithm(PublicAlgorithm::Rsa) /// # .with_name_hashing_algorithm(HashingAlgorithm::Sha256) /// # .with_object_attributes(object_attributes) /// # .with_auth_policy(digest) /// # .with_rsa_parameters( /// # PublicRsaParametersBuilder::new() /// # .with_scheme(RsaScheme::Null) /// # .with_key_bits(RsaKeyBits::Rsa2048) /// # .with_is_signing_key(true) /// # .with_is_decryption_key(true) /// # .with_restricted(false) /// # .build() /// # .expect("Params to be valid"), /// # ) /// # .with_rsa_unique_identifier(PublicKeyRsa::default()) /// # .build() /// # .expect("public to be valid"); /// # /// # let result = context /// # .create( /// # parent_of_object_to_duplicate_handle, /// # public_child, /// # None, /// # None, /// # None, /// # None, /// # ) /// # .unwrap(); /// # /// # let object_to_duplicate_handle: ObjectHandle = context /// # .load( /// # parent_of_object_to_duplicate_handle, /// # result.out_private.clone(), /// # result.out_public, /// # ) /// # .unwrap() /// # .into(); /// # /// # let new_parent_handle: ObjectHandle = context /// # .create_primary( /// # Hierarchy::Owner, /// # parent_public, /// # None, /// # None, /// # None, /// # None, /// # ) /// # .unwrap() /// # .key_handle /// # .into(); /// # /// # context.set_sessions((None, None, None)); /// # /// # // Create a Policy session with the same exact attributes /// # // as the trial session so that the session digest stays /// # // the same. /// # let policy_auth_session = context /// # .start_auth_session( /// # None, /// # None, /// # None, /// # SessionType::Policy, /// # SymmetricDefinition::AES_256_CFB, /// # HashingAlgorithm::Sha256, /// # ) /// # .expect("Start auth session failed") /// # .expect("Start auth session returned a NONE handle"); /// # /// # let (policy_auth_session_attributes, policy_auth_session_attributes_mask) = /// # SessionAttributesBuilder::new() /// # .with_decrypt(true) /// # .with_encrypt(true) /// # .build(); /// # context /// # .tr_sess_set_attributes( /// # policy_auth_session, /// # policy_auth_session_attributes, /// # policy_auth_session_attributes_mask, /// # ) /// # .expect("tr_sess_set_attributes call failed"); /// # /// # let policy_session = PolicySession::try_from(policy_auth_session) /// # .expect("Failed to convert auth session into policy session"); /// # /// # context /// # .policy_auth_value(policy_session) /// # .expect("Policy auth value"); /// # /// # context /// # .policy_command_code(policy_session, CommandCode::Duplicate) /// # .unwrap(); /// # /// # context.set_sessions((Some(policy_auth_session), None, None)); /// # /// # let (encryption_key_out, duplicate, out_sym_seed) = context /// # .duplicate( /// # object_to_duplicate_handle, /// # new_parent_handle, /// # None, /// # SymmetricDefinitionObject::Null, /// # ) /// # .unwrap(); /// # eprintln!("D: {:?}, P: {:?}, S: {:?}", encryption_key_out, duplicate, out_sym_seed); /// # let public = context.read_public(object_to_duplicate_handle.into()).unwrap().0; /// # /// # let session = context /// # .start_auth_session( /// # None, /// # None, /// # None, /// # SessionType::Hmac, /// # SymmetricDefinition::AES_256_CFB, /// # HashingAlgorithm::Sha256, /// # ) /// # .unwrap(); /// # let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new() /// # .with_decrypt(true) /// # .with_encrypt(true) /// # .build(); /// # context.tr_sess_set_attributes( /// # session.unwrap(), /// # session_attributes, /// # session_attributes_mask, /// # ) /// # .unwrap(); /// # context.set_sessions((session, None, None)); /// /// // `encryption_key_out`, `duplicate` and `out_sym_seed` are generated /// // by `duplicate` function /// let private = context.import( /// new_parent_handle, /// Some(encryption_key_out), /// public, /// duplicate, /// out_sym_seed, /// SymmetricDefinitionObject::Null, /// ).unwrap(); /// # /// # eprintln!("P: {:?}", private); /// ``` pub fn import( &mut self, parent_handle: ObjectHandle, encryption_key: Option, public: Public, duplicate: Private, encrypted_secret: EncryptedSecret, symmetric_alg: SymmetricDefinitionObject, ) -> Result { let mut out_private_ptr = null_mut(); let ret = unsafe { Esys_Import( self.mut_context(), parent_handle.into(), self.required_session_1()?, self.optional_session_2(), self.optional_session_3(), &encryption_key.unwrap_or_default().into(), &public.try_into()?, &duplicate.into(), &encrypted_secret.into(), &symmetric_alg.into(), &mut out_private_ptr, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Private::try_from(Context::ffi_data_to_owned(out_private_ptr)) } else { error!("Error when performing import: {}", ret); Err(ret) } } } tss-esapi-7.4.0/src/context/tpm_commands/enhanced_authorization_ea_commands.rs000064400000000000000000000526361046102023000261350ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ attributes::LocalityAttributes, constants::CommandCode, handles::{AuthHandle, ObjectHandle, SessionHandle}, interface_types::{session_handles::PolicySession, YesNo}, structures::{ AuthTicket, Digest, DigestList, Name, Nonce, PcrSelectionList, Signature, Timeout, VerifiedTicket, }, tss2_esys::{ Esys_PolicyAuthValue, Esys_PolicyAuthorize, Esys_PolicyCommandCode, Esys_PolicyCpHash, Esys_PolicyDuplicationSelect, Esys_PolicyGetDigest, Esys_PolicyLocality, Esys_PolicyNameHash, Esys_PolicyNvWritten, Esys_PolicyOR, Esys_PolicyPCR, Esys_PolicyPassword, Esys_PolicyPhysicalPresence, Esys_PolicySecret, Esys_PolicySigned, Esys_PolicyTemplate, }, Context, Error, Result, WrapperErrorKind as ErrorKind, }; use log::error; use std::convert::{TryFrom, TryInto}; use std::ptr::null_mut; use std::time::Duration; impl Context { /// Cause the policy to include a signed authorization #[allow(clippy::too_many_arguments)] pub fn policy_signed( &mut self, policy_session: PolicySession, auth_object: ObjectHandle, nonce_tpm: Nonce, cp_hash_a: Digest, policy_ref: Nonce, expiration: Option, signature: Signature, ) -> Result<(Timeout, AuthTicket)> { let mut out_timeout_ptr = null_mut(); let mut out_policy_ticket_ptr = null_mut(); let ret = unsafe { Esys_PolicySigned( self.mut_context(), auth_object.into(), SessionHandle::from(policy_session).into(), self.required_session_1()?, self.optional_session_2(), self.optional_session_3(), &nonce_tpm.into(), &cp_hash_a.into(), &policy_ref.into(), i32::try_from(expiration.map_or(0, |v| v.as_secs())).map_err(|e| { error!("Unable to convert duration to i32: {}", e); Error::local_error(ErrorKind::InvalidParam) })?, &signature.try_into()?, &mut out_timeout_ptr, &mut out_policy_ticket_ptr, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(( Timeout::try_from(Context::ffi_data_to_owned(out_timeout_ptr))?, AuthTicket::try_from(Context::ffi_data_to_owned(out_policy_ticket_ptr))?, )) } else { error!("Error when sending policy signed: {}", ret); Err(ret) } } /// Cause the policy to require a secret in authValue pub fn policy_secret( &mut self, policy_session: PolicySession, auth_handle: AuthHandle, nonce_tpm: Nonce, cp_hash_a: Digest, policy_ref: Nonce, expiration: Option, ) -> Result<(Timeout, AuthTicket)> { let mut out_timeout_ptr = null_mut(); let mut out_policy_ticket_ptr = null_mut(); let ret = unsafe { Esys_PolicySecret( self.mut_context(), auth_handle.into(), SessionHandle::from(policy_session).into(), self.required_session_1()?, self.optional_session_2(), self.optional_session_3(), &nonce_tpm.into(), &cp_hash_a.into(), &policy_ref.into(), i32::try_from(expiration.map_or(0, |v| v.as_secs())).map_err(|e| { error!("Unable to convert duration to i32: {}", e); Error::local_error(ErrorKind::InvalidParam) })?, &mut out_timeout_ptr, &mut out_policy_ticket_ptr, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(( Timeout::try_from(Context::ffi_data_to_owned(out_timeout_ptr))?, AuthTicket::try_from(Context::ffi_data_to_owned(out_policy_ticket_ptr))?, )) } else { error!("Error when sending policy secret: {}", ret); Err(ret) } } // Missing function: PolicyTicket /// Cause conditional gating of a policy based on an OR'd condition. /// /// The TPM will ensure that the current policy digest equals at least /// one of the digests. /// If this is the case, the policyDigest of the policy session is replaced /// by the value of the different hashes. /// /// # Constraints /// * `digest_list` must be at least 2 and at most 8 elements long /// /// # Errors /// * if the hash list provided is too short or too long, a `WrongParamSize` wrapper error will be returned pub fn policy_or( &mut self, policy_session: PolicySession, digest_list: DigestList, ) -> Result<()> { if digest_list.len() < 2 { error!( "The digest list only contains {} digests, it must contain at least 2", digest_list.len() ); return Err(Error::local_error(ErrorKind::WrongParamSize)); } let ret = unsafe { Esys_PolicyOR( self.mut_context(), SessionHandle::from(policy_session).into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), &digest_list.try_into()?, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(()) } else { error!("Error when computing policy OR: {}", ret); Err(ret) } } /// Cause conditional gating of a policy based on PCR. /// /// # Details /// The TPM will use the hash algorithm of the policy_session /// to calculate a digest from the values of the pcr slots /// specified in the pcr_selections. /// This is then compared to pcr_policy_digest if they match then /// the policyDigest of the policy session is extended. /// /// # Errors /// * if the pcr policy digest provided is too long, a `WrongParamSize` wrapper error will be returned pub fn policy_pcr( &mut self, policy_session: PolicySession, pcr_policy_digest: Digest, pcr_selection_list: PcrSelectionList, ) -> Result<()> { let ret = unsafe { Esys_PolicyPCR( self.mut_context(), SessionHandle::from(policy_session).into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), &pcr_policy_digest.into(), &pcr_selection_list.into(), ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(()) } else { error!("Error when computing policy PCR: {}", ret); Err(ret) } } /// Cause conditional gating of a policy based on locality. /// /// The TPM will ensure that the current policy can only complete in the specified /// locality (extended) or any of the specified localities (non-extended). pub fn policy_locality( &mut self, policy_session: PolicySession, locality: LocalityAttributes, ) -> Result<()> { let ret = unsafe { Esys_PolicyLocality( self.mut_context(), SessionHandle::from(policy_session).into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), locality.into(), ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(()) } else { error!("Error when computing policy locality: {}", ret); Err(ret) } } // Missing function: PolicyNV // Missing function: PolicyCounterTimer /// Cause conditional gating of a policy based on command code of authorized command. /// /// The TPM will ensure that the current policy can only be used to complete the command /// indicated by code. pub fn policy_command_code( &mut self, policy_session: PolicySession, code: CommandCode, ) -> Result<()> { let ret = unsafe { Esys_PolicyCommandCode( self.mut_context(), SessionHandle::from(policy_session).into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), code.into(), ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(()) } else { error!("Error when computing policy command code: {}", ret); Err(ret) } } /// Cause conditional gating of a policy based on physical presence. /// /// The TPM will ensure that the current policy can only complete when physical /// presence is asserted. The way this is done is implementation-specific. pub fn policy_physical_presence(&mut self, policy_session: PolicySession) -> Result<()> { let ret = unsafe { Esys_PolicyPhysicalPresence( self.mut_context(), SessionHandle::from(policy_session).into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(()) } else { error!("Error when computing policy physical presence: {}", ret); Err(ret) } } /// Cause conditional gating of a policy based on command parameters. /// /// The TPM will ensure that the current policy can only be used to authorize /// a command where the parameters are hashed into cp_hash_a. pub fn policy_cp_hash( &mut self, policy_session: PolicySession, cp_hash_a: Digest, ) -> Result<()> { let ret = unsafe { Esys_PolicyCpHash( self.mut_context(), SessionHandle::from(policy_session).into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), &cp_hash_a.into(), ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(()) } else { error!("Error when computing policy command parameters: {}", ret); Err(ret) } } /// Cause conditional gating of a policy based on name hash. /// /// The TPM will ensure that the current policy can only be used to authorize /// a command acting on an object whose name hashes to name_hash. pub fn policy_name_hash( &mut self, policy_session: PolicySession, name_hash: Digest, ) -> Result<()> { let ret = unsafe { Esys_PolicyNameHash( self.mut_context(), SessionHandle::from(policy_session).into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), &name_hash.into(), ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(()) } else { error!("Error when computing policy name hash: {}", ret); Err(ret) } } /// Cause conditional gating of a policy based on duplication parent's name. /// /// # Arguments /// * `policy_session` - The [policy session][PolicySession] being extended. /// * `object_name` - The [name][Name] of the object being duplicated. /// * `new_parent_name` - The [name][Name] of the new parent. /// * `include_object` - Flag indicating if `object_name` will be included in policy /// calculation. /// /// # Details /// Set `include_object` only when this command is used in conjunction with /// [`policy_authorize`][Context::policy_authorize]. /// /// # Example /// /// ```rust /// # use std::convert::{TryFrom, TryInto}; /// # use tss_esapi::attributes::{ObjectAttributesBuilder, SessionAttributesBuilder}; /// # use tss_esapi::constants::{CommandCode, SessionType}; /// # use tss_esapi::handles::ObjectHandle; /// # use tss_esapi::interface_types::{ /// # algorithm::{HashingAlgorithm, PublicAlgorithm}, /// # key_bits::RsaKeyBits, /// # resource_handles::Hierarchy, /// # session_handles::PolicySession, /// # }; /// # use tss_esapi::structures::SymmetricDefinition; /// # use tss_esapi::structures::{ /// # PublicBuilder, PublicKeyRsa, PublicRsaParametersBuilder, RsaScheme, /// # RsaExponent, Name, /// # }; /// # use tss_esapi::structures::SymmetricDefinitionObject; /// # use tss_esapi::abstraction::cipher::Cipher; /// # use tss_esapi::{Context, TctiNameConf}; /// # /// # let mut context = // ... /// # Context::new( /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"), /// # ).expect("Failed to create Context"); /// # /// # let trial_session = context /// # .start_auth_session( /// # None, /// # None, /// # None, /// # SessionType::Trial, /// # SymmetricDefinition::AES_256_CFB, /// # HashingAlgorithm::Sha256, /// # ) /// # .expect("Start auth session failed") /// # .expect("Start auth session returned a NONE handle"); /// # /// # let (policy_auth_session_attributes, policy_auth_session_attributes_mask) = /// # SessionAttributesBuilder::new() /// # .with_decrypt(true) /// # .with_encrypt(true) /// # .build(); /// # context /// # .tr_sess_set_attributes( /// # trial_session, /// # policy_auth_session_attributes, /// # policy_auth_session_attributes_mask, /// # ) /// # .expect("tr_sess_set_attributes call failed"); /// # /// # let policy_session = PolicySession::try_from(trial_session) /// # .expect("Failed to convert auth session into policy session"); /// # /// # let object_name: Name = Vec::::new().try_into().unwrap(); /// # let parent_name = object_name.clone(); /// # /// context /// .policy_duplication_select(policy_session, object_name, parent_name, false) /// .expect("Policy command code"); /// # /// # /// Digest of the policy that allows duplication /// # let digest = context /// # .policy_get_digest(policy_session) /// # .expect("Could retrieve digest"); /// ``` pub fn policy_duplication_select( &mut self, policy_session: PolicySession, object_name: Name, new_parent_name: Name, include_object: bool, ) -> Result<()> { let ret = unsafe { Esys_PolicyDuplicationSelect( self.mut_context(), SessionHandle::from(policy_session).into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), &object_name.into(), &new_parent_name.into(), u8::from(include_object), ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(()) } else { error!("Error when computing policy duplication select: {}", ret); Err(ret) } } /// Cause conditional gating of a policy based on an authorized policy /// /// The TPM will ensure that the current policy digest is correctly signed /// by the ticket in check_ticket and that check_ticket is signed by the key /// named in key_sign. /// If this is the case, the policyDigest of the policy session is replaced /// by the value of the key_sign and policy_ref values. pub fn policy_authorize( &mut self, policy_session: PolicySession, approved_policy: Digest, policy_ref: Nonce, key_sign: &Name, check_ticket: VerifiedTicket, ) -> Result<()> { let ret = unsafe { Esys_PolicyAuthorize( self.mut_context(), SessionHandle::from(policy_session).into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), &approved_policy.into(), &policy_ref.into(), key_sign.as_ref(), &check_ticket.try_into()?, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(()) } else { error!("Error when computing policy authorize: {}", ret); Err(ret) } } /// Cause conditional gating of a policy based on authValue. /// /// The TPM will ensure that the current policy requires the user to know the authValue /// used when creating the object. pub fn policy_auth_value(&mut self, policy_session: PolicySession) -> Result<()> { let ret = unsafe { Esys_PolicyAuthValue( self.mut_context(), SessionHandle::from(policy_session).into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(()) } else { error!("Error when computing policy auth value: {}", ret); Err(ret) } } /// Cause conditional gating of a policy based on password. /// /// The TPM will ensure that the current policy requires the user to know the password /// used when creating the object. pub fn policy_password(&mut self, policy_session: PolicySession) -> Result<()> { let ret = unsafe { Esys_PolicyPassword( self.mut_context(), SessionHandle::from(policy_session).into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(()) } else { error!("Error when computing policy password: {}", ret); Err(ret) } } /// Function for retrieving the current policy digest for /// the session. pub fn policy_get_digest(&mut self, policy_session: PolicySession) -> Result { let mut policy_digest_ptr = null_mut(); let ret = unsafe { Esys_PolicyGetDigest( self.mut_context(), SessionHandle::from(policy_session).into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), &mut policy_digest_ptr, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Digest::try_from(Context::ffi_data_to_owned(policy_digest_ptr)) } else { error!( "Error failed to perform policy get digest operation: {}.", ret ); Err(ret) } } /// Cause conditional gating of a policy based on NV written state. /// /// The TPM will ensure that the NV index that is used has a specific written state. pub fn policy_nv_written( &mut self, policy_session: PolicySession, written_set: bool, ) -> Result<()> { let ret = unsafe { Esys_PolicyNvWritten( self.mut_context(), SessionHandle::from(policy_session).into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), YesNo::from(written_set).into(), ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(()) } else { error!("Error when computing policy NV written state: {}", ret); Err(ret) } } /// Bind policy to a specific creation template. /// /// # Arguments /// * `policy_session` - The [policy session][PolicySession] being extended. /// * `template_hash` - The [digest][Digest] to be added to the policy. pub fn policy_template( &mut self, policy_session: PolicySession, template_hash: Digest, ) -> Result<()> { let ret = unsafe { Esys_PolicyTemplate( self.mut_context(), SessionHandle::from(policy_session).into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), &template_hash.into(), ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(()) } else { error!( "Failed to bind template to a specific creation template: {}", ret ); Err(ret) } } // Missing function: PolicyAuthorizeNV } tss-esapi-7.4.0/src/context/tpm_commands/ephemeral_ec_keys.rs000064400000000000000000000003111046102023000225050ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::Context; impl Context { // Missing function: Commit // Missing function: EC_Ephemeral } tss-esapi-7.4.0/src/context/tpm_commands/field_upgrade.rs000064400000000000000000000003761046102023000216460ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::Context; impl Context { // Missing function: FieldUpgradeStart // Missing function: FieldUpgradeData // Missing function: FirmwareRead } tss-esapi-7.4.0/src/context/tpm_commands/hash_hmac_event_sequences.rs000064400000000000000000000005661046102023000242440ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::Context; impl Context { // Missing function: HMAC_Start // Missing function: MAC_Start // Missing function: HashSequenceStart // Missing function: SequenceUpdate // Missing function: SequenceComplete // Missing function: EventSequenceComplete } tss-esapi-7.4.0/src/context/tpm_commands/hierarchy_commands.rs000064400000000000000000000140241046102023000227060ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ context::handle_manager::HandleDropAction, handles::{AuthHandle, KeyHandle, ObjectHandle}, interface_types::{resource_handles::Hierarchy, YesNo}, structures::{ Auth, CreatePrimaryKeyResult, CreationData, CreationTicket, Data, Digest, PcrSelectionList, Public, SensitiveData, }, tss2_esys::{ Esys_Clear, Esys_ClearControl, Esys_CreatePrimary, Esys_HierarchyChangeAuth, TPM2B_SENSITIVE_CREATE, TPMS_SENSITIVE_CREATE, }, Context, Error, Result, }; use log::error; use std::convert::{TryFrom, TryInto}; use std::ptr::null_mut; impl Context { /// Create a primary key and return the handle. /// /// The authentication value, initial data, outside info and creation PCRs are passed as slices /// which are then converted by the method into TSS native structures. /// /// # Errors /// * if either of the slices is larger than the maximum size of the native objects, a /// `WrongParamSize` wrapper error is returned // TODO: Fix when compacting the arguments into a struct #[allow(clippy::too_many_arguments)] pub fn create_primary( &mut self, primary_handle: Hierarchy, public: Public, auth_value: Option, initial_data: Option, outside_info: Option, creation_pcrs: Option, ) -> Result { let sensitive_create = TPM2B_SENSITIVE_CREATE { size: std::mem::size_of::() .try_into() .unwrap(), sensitive: TPMS_SENSITIVE_CREATE { userAuth: auth_value.unwrap_or_default().into(), data: initial_data.unwrap_or_default().into(), }, }; let creation_pcrs = PcrSelectionList::list_from_option(creation_pcrs); let mut out_public_ptr = null_mut(); let mut creation_data_ptr = null_mut(); let mut creation_hash_ptr = null_mut(); let mut creation_ticket_ptr = null_mut(); let mut object_handle = ObjectHandle::None.into(); let ret = unsafe { Esys_CreatePrimary( self.mut_context(), ObjectHandle::from(primary_handle).into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), &sensitive_create, &public.try_into()?, &outside_info.unwrap_or_default().into(), &creation_pcrs.into(), &mut object_handle, &mut out_public_ptr, &mut creation_data_ptr, &mut creation_hash_ptr, &mut creation_ticket_ptr, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { let out_public_owned = Context::ffi_data_to_owned(out_public_ptr); let creation_data_owned = Context::ffi_data_to_owned(creation_data_ptr); let creation_hash_owned = Context::ffi_data_to_owned(creation_hash_ptr); let creation_ticket_owned = Context::ffi_data_to_owned(creation_ticket_ptr); let primary_key_handle = KeyHandle::from(object_handle); self.handle_manager .add_handle(primary_key_handle.into(), HandleDropAction::Flush)?; Ok(CreatePrimaryKeyResult { key_handle: primary_key_handle, out_public: Public::try_from(out_public_owned)?, creation_data: CreationData::try_from(creation_data_owned)?, creation_hash: Digest::try_from(creation_hash_owned)?, creation_ticket: CreationTicket::try_from(creation_ticket_owned)?, }) } else { error!("Error in creating primary key: {}", ret); Err(ret) } } // Missing function: HierarchyControl // Missing function: SetPrimaryPolicy // Missing function: ChangePPS // Missing function: ChangeEPS /// Clear all TPM context associated with a specific Owner pub fn clear(&mut self, auth_handle: AuthHandle) -> Result<()> { let ret = unsafe { Esys_Clear( self.mut_context(), auth_handle.into(), self.required_session_1()?, self.optional_session_2(), self.optional_session_3(), ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(()) } else { error!("Error in clearing TPM hierarchy: {}", ret); Err(ret) } } /// Disable or enable the TPM2_CLEAR command pub fn clear_control(&mut self, auth_handle: AuthHandle, disable: bool) -> Result<()> { let ret = unsafe { Esys_ClearControl( self.mut_context(), auth_handle.into(), self.required_session_1()?, self.optional_session_2(), self.optional_session_3(), YesNo::from(disable).into(), ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(()) } else { error!("Error in controlling clear command: {}", ret); Err(ret) } } /// Change authorization for a hierarchy root pub fn hierarchy_change_auth(&mut self, auth_handle: AuthHandle, new_auth: Auth) -> Result<()> { let ret = unsafe { Esys_HierarchyChangeAuth( self.mut_context(), auth_handle.into(), self.required_session_1()?, self.optional_session_2(), self.optional_session_3(), &new_auth.into(), ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(()) } else { error!("Error changing hierarchy auth: {}", ret); Err(ret) } } } tss-esapi-7.4.0/src/context/tpm_commands/integrity_collection_pcr.rs000064400000000000000000000230221046102023000241420ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ handles::PcrHandle, structures::{DigestList, DigestValues, PcrSelectionList}, tss2_esys::{Esys_PCR_Extend, Esys_PCR_Read, Esys_PCR_Reset}, Context, Error, Result, }; use log::error; use std::convert::{TryFrom, TryInto}; use std::ptr::null_mut; impl Context { /// Extends a PCR with the specified digests. /// /// # Arguments /// * `pcr_handle`- A [PcrHandle] to the PCR slot that is to be extended. /// * `digests` - The [DigestValues] with which the slot shall be extended. /// /// # Details /// This method is used to cause an update to the indicated PCR. The digests param /// contains the digests for specific algorithms that are to be used. /// /// # Example /// /// ```rust /// # use tss_esapi::{ /// # Context, TctiNameConf, /// # constants::SessionType, /// # attributes::SessionAttributesBuilder, /// # handles::PcrHandle, /// # structures::{Digest, SymmetricDefinition}, /// # }; /// # use std::{env, str::FromStr}; /// # // Create context /// # let mut context = /// # Context::new( /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"), /// # ).expect("Failed to create Context"); /// # // Create session for a pcr /// # let pcr_session = context /// # .start_auth_session( /// # None, /// # None, /// # None, /// # SessionType::Hmac, /// # SymmetricDefinition::AES_256_CFB, /// # tss_esapi::interface_types::algorithm::HashingAlgorithm::Sha256, /// # ) /// # .expect("Failed to create session") /// # .expect("Received invalid handle"); /// # let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new() /// # .with_decrypt(true) /// # .with_encrypt(true) /// # .build(); /// # context.tr_sess_set_attributes(pcr_session, session_attributes, session_attributes_mask) /// # .expect("Failed to set attributes on session"); /// # /// # let digest_sha1 = Digest::try_from(vec![ /// # 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, /// # ]) /// # .expect("Failed to create sha1 Digest from data"); /// # /// # let digest_sha256 = Digest::try_from(vec![ /// # 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, /// # 24, 25, 26, 27, 28, 29, 30, 31, 32, /// # ]).expect("Failed to create Sha256 Digest from data"); /// use std::convert::TryFrom; /// use tss_esapi::{ /// structures::{DigestValues}, /// interface_types::algorithm::HashingAlgorithm, /// }; /// // Extend both sha256 and sha1 /// let mut vals = DigestValues::new(); /// vals.set( /// HashingAlgorithm::Sha1, /// digest_sha1, /// ); /// vals.set( /// HashingAlgorithm::Sha256, /// digest_sha256, /// ); /// // Use pcr_session for authorization when extending /// // PCR 16 with the values for the banks specified in /// // vals. /// context.execute_with_session(Some(pcr_session), |ctx| { /// ctx.pcr_extend(PcrHandle::Pcr16, vals).expect("Call to pcr_extend failed"); /// }); /// ``` pub fn pcr_extend(&mut self, pcr_handle: PcrHandle, digests: DigestValues) -> Result<()> { let ret = unsafe { Esys_PCR_Extend( self.mut_context(), pcr_handle.into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), &digests.try_into()?, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(()) } else { error!("Error when extending PCR: {}", ret); Err(ret) } } // Missing function: PCR_Event /// Reads the values of a PCR. /// /// # Arguments /// * `pcr_selection_list` - A [PcrSelectionList] that contains pcr slots in /// different banks that is going to be read. /// /// # Details /// The provided [PcrSelectionList] contains the pcr slots in the different /// banks that is going to be read. It is possible to select more pcr slots /// then what will fit in the returned result so the method returns a [PcrSelectionList] /// that indicates what values were read. The values that were read are returned /// in a [DigestList]. /// /// # Errors /// * Several different errors can occur if conversion of return /// data fails. /// /// # Example /// /// ```rust /// # use tss_esapi::{Context, TctiNameConf}; /// # use std::{env, str::FromStr}; /// # // Create context /// # let mut context = /// # Context::new( /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"), /// # ).expect("Failed to create Context"); /// use tss_esapi::{ /// interface_types::algorithm::HashingAlgorithm, /// structures::{PcrSelectionListBuilder, PcrSlot}, /// }; /// // Create PCR selection list with slots in a bank /// // that is going to be read. /// let pcr_selection_list = PcrSelectionListBuilder::new() /// .with_selection(HashingAlgorithm::Sha256, &[PcrSlot::Slot0, PcrSlot::Slot1]) /// .build() /// .expect("Failed to build PcrSelectionList"); /// /// let (update_counter, read_pcr_list, digest_list) = context.pcr_read(pcr_selection_list) /// .expect("Call to pcr_read failed"); /// ``` pub fn pcr_read( &mut self, pcr_selection_list: PcrSelectionList, ) -> Result<(u32, PcrSelectionList, DigestList)> { let mut pcr_update_counter: u32 = 0; let mut pcr_selection_out_ptr = null_mut(); let mut pcr_values_ptr = null_mut(); let ret = unsafe { Esys_PCR_Read( self.mut_context(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), &pcr_selection_list.into(), &mut pcr_update_counter, &mut pcr_selection_out_ptr, &mut pcr_values_ptr, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(( pcr_update_counter, PcrSelectionList::try_from(Context::ffi_data_to_owned(pcr_selection_out_ptr))?, DigestList::try_from(Context::ffi_data_to_owned(pcr_values_ptr))?, )) } else { error!("Error when reading PCR: {}", ret); Err(ret) } } // Missing function: PCR_Allocate // Missing function: PCR_SetAuthPolicy // Missing function: PCR_SetAuthValue /// Resets the value in a PCR. /// /// # Arguments /// * `pcr_handle` - A [PcrHandle] to the PCR slot that is to be reset. /// /// # Details /// If the attributes of the PCR indicates that it is allowed /// to reset them and the proper authorization is provided then /// this method can be used to set the the specified PCR in all /// banks to 0. /// /// # Example /// /// ```rust /// # use tss_esapi::{ /// # Context, TctiNameConf, /// # constants::SessionType, /// # attributes::SessionAttributesBuilder, /// # structures::SymmetricDefinition, /// # interface_types::algorithm::HashingAlgorithm, /// # }; /// # use std::{env, str::FromStr}; /// # // Create context /// # let mut context = /// # Context::new( /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"), /// # ).expect("Failed to create Context"); /// # // Create session for a pcr /// # let pcr_session = context /// # .start_auth_session( /// # None, /// # None, /// # None, /// # SessionType::Hmac, /// # SymmetricDefinition::AES_256_CFB, /// # HashingAlgorithm::Sha256, /// # ) /// # .expect("Failed to create session") /// # .expect("Received invalid handle"); /// # let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new() /// # .with_decrypt(true) /// # .with_encrypt(true) /// # .build(); /// # context.tr_sess_set_attributes(pcr_session, session_attributes, session_attributes_mask) /// # .expect("Failed to set attributes on session"); /// /// use tss_esapi::{ /// handles::PcrHandle /// }; /// context.execute_with_session(Some(pcr_session), |ctx| { /// ctx.pcr_reset(PcrHandle::Pcr16).expect("Call to pcr_reset failed"); /// }); /// ``` pub fn pcr_reset(&mut self, pcr_handle: PcrHandle) -> Result<()> { let ret = unsafe { Esys_PCR_Reset( self.mut_context(), pcr_handle.into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(()) } else { error!("Error when resetting PCR: {}", ret); Err(ret) } } // Missing function: _TPM_Hash_Start // Missing function: _TPM_Hash_Data // Missing function: _TPM_Hash_End } tss-esapi-7.4.0/src/context/tpm_commands/miscellaneous_management_functions.rs000064400000000000000000000003211046102023000261710ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::Context; impl Context { // Missing function: PP_Commands // Missing function: SetAlgorithmSet } tss-esapi-7.4.0/src/context/tpm_commands/mod.rs000064400000000000000000000014061046102023000176260ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod asymmetric_primitives; mod attached_components; mod attestation_commands; mod authenticated_countdown_timer; mod capability_commands; mod clocks_and_timers; mod command_audit; mod context_management; mod dictionary_attack_functions; mod duplication_commands; mod enhanced_authorization_ea_commands; mod ephemeral_ec_keys; mod field_upgrade; mod hash_hmac_event_sequences; mod hierarchy_commands; mod integrity_collection_pcr; mod miscellaneous_management_functions; mod non_volatile_storage; mod object_commands; mod random_number_generator; mod session_commands; mod signing_and_signature_verification; mod startup; mod symmetric_primitives; mod testing; mod vendor_specific; tss-esapi-7.4.0/src/context/tpm_commands/non_volatile_storage.rs000064400000000000000000000162231046102023000232670ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ context::handle_manager::HandleDropAction, handles::{AuthHandle, NvIndexHandle, ObjectHandle}, interface_types::resource_handles::{NvAuth, Provision}, structures::{Auth, MaxNvBuffer, Name, NvPublic}, tss2_esys::{ Esys_NV_DefineSpace, Esys_NV_Increment, Esys_NV_Read, Esys_NV_ReadPublic, Esys_NV_UndefineSpace, Esys_NV_Write, }, Context, Error, Result, }; use log::error; use std::convert::{TryFrom, TryInto}; use std::ptr::null_mut; impl Context { /// Allocates an index in the non volatile storage. /// /// # Details /// This method will instruct the TPM to reserve space for an NV index /// with the attributes defined in the provided parameters. /// /// # Arguments /// * `nv_auth` - The [Provision] used for authorization. /// * `auth` - The authorization value. /// * `public_info` - The public parameters of the NV area. pub fn nv_define_space( &mut self, nv_auth: Provision, auth: Option, public_info: NvPublic, ) -> Result { let mut nv_handle = ObjectHandle::None.into(); let ret = unsafe { Esys_NV_DefineSpace( self.mut_context(), AuthHandle::from(nv_auth).into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), &auth.unwrap_or_default().into(), &public_info.try_into()?, &mut nv_handle, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { self.handle_manager .add_handle(nv_handle.into(), HandleDropAction::Close)?; Ok(NvIndexHandle::from(nv_handle)) } else { error!("Error when defining NV space: {}", ret); Err(ret) } } /// Deletes an index in the non volatile storage. /// /// # Details /// The method will instruct the TPM to remove a /// nv index. /// /// # Arguments /// * `nv_auth` - The [Provision] used for authorization. /// * `nv_index_handle`- The [NvIndexHandle] associated with /// the nv area that is to be removed. pub fn nv_undefine_space( &mut self, nv_auth: Provision, nv_index_handle: NvIndexHandle, ) -> Result<()> { let ret = unsafe { Esys_NV_UndefineSpace( self.mut_context(), AuthHandle::from(nv_auth).into(), nv_index_handle.into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { self.handle_manager.set_as_closed(nv_index_handle.into())?; Ok(()) } else { error!("Error when undefining NV space: {}", ret); Err(ret) } } // Missing function: UndefineSpaceSpecial /// Reads the public part of an nv index. /// /// # Details /// This method is used to read the public /// area and name of a nv index. pub fn nv_read_public(&mut self, nv_index_handle: NvIndexHandle) -> Result<(NvPublic, Name)> { let mut nv_public_ptr = null_mut(); let mut nv_name_ptr = null_mut(); let ret = unsafe { Esys_NV_ReadPublic( self.mut_context(), nv_index_handle.into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), &mut nv_public_ptr, &mut nv_name_ptr, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(( NvPublic::try_from(Context::ffi_data_to_owned(nv_public_ptr))?, Name::try_from(Context::ffi_data_to_owned(nv_name_ptr))?, )) } else { error!("Error when reading NV public: {}", ret); Err(ret) } } /// Writes data to an nv index. /// /// # Details /// This method is used to write a value to /// the nv memory in the TPM. pub fn nv_write( &mut self, auth_handle: NvAuth, nv_index_handle: NvIndexHandle, data: MaxNvBuffer, offset: u16, ) -> Result<()> { let ret = unsafe { Esys_NV_Write( self.mut_context(), AuthHandle::from(auth_handle).into(), nv_index_handle.into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), &data.into(), offset, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(()) } else { error!("Error when writing NV: {}", ret); Err(ret) } } /// Increment monotonic counter index /// /// # Details /// This method is used to increment monotonic counter /// in the TPM. pub fn nv_increment( &mut self, auth_handle: NvAuth, nv_index_handle: NvIndexHandle, ) -> Result<()> { let ret = unsafe { Esys_NV_Increment( self.mut_context(), AuthHandle::from(auth_handle).into(), nv_index_handle.into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(()) } else { error!("Error when incrementing NV: {}", ret); Err(ret) } } // Missing function: NV_Extend // Missing function: NV_SetBits // Missing function: NV_WriteLock // Missing function: NV_GlobalWriteLock /// Reads data from the nv index. /// /// # Details /// This method is used to read a value from an area in /// NV memory of the TPM. pub fn nv_read( &mut self, auth_handle: NvAuth, nv_index_handle: NvIndexHandle, size: u16, offset: u16, ) -> Result { let mut data_ptr = null_mut(); let ret = unsafe { Esys_NV_Read( self.mut_context(), AuthHandle::from(auth_handle).into(), nv_index_handle.into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), size, offset, &mut data_ptr, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { MaxNvBuffer::try_from(Context::ffi_data_to_owned(data_ptr)) } else { error!("Error when reading NV: {}", ret); Err(ret) } } // Missing function: NV_ReadLock // Missing function: NV_ChangeAuth // Missing function: NV_Certify } tss-esapi-7.4.0/src/context/tpm_commands/object_commands.rs000064400000000000000000000321671046102023000222060ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ context::handle_manager::HandleDropAction, handles::{KeyHandle, ObjectHandle, TpmHandle}, interface_types::resource_handles::Hierarchy, structures::{ Auth, CreateKeyResult, CreationData, CreationTicket, Data, Digest, EncryptedSecret, IdObject, Name, PcrSelectionList, Private, Public, Sensitive, SensitiveData, }, tss2_esys::{ Esys_ActivateCredential, Esys_Create, Esys_Load, Esys_LoadExternal, Esys_MakeCredential, Esys_ObjectChangeAuth, Esys_ReadPublic, Esys_Unseal, TPM2B_SENSITIVE_CREATE, TPMS_SENSITIVE_CREATE, }, Context, Error, Result, }; use log::error; use std::convert::{TryFrom, TryInto}; use std::ptr::{null, null_mut}; impl Context { /// Create a key and return the handle. /// /// The authentication value, initial data, outside info and creation PCRs are passed as slices /// which are then converted by the method into TSS native structures. /// /// # Parameters /// * `parent_handle` - The [KeyHandle] of the parent for the new object that is being created. /// * `public` - The public part of the object that is being created. /// * `auth_value` - The value used to be used for authorize usage of the object. /// * `sensitive_data` - The data that is to be sealed, a key or derivation values. /// * `outside_info` - Data that will be included in the creation data for this /// object to provide permanent, verifiable linkage between /// the object that is being created and some object owner data. /// * `creation_pcrs`- PCRs that will be used in creation data. /// /// # Errors /// * if either of the slices is larger than the maximum size of the native objects, a /// `WrongParamSize` wrapper error is returned // TODO: Fix when compacting the arguments into a struct #[allow(clippy::too_many_arguments)] pub fn create( &mut self, parent_handle: KeyHandle, public: Public, auth_value: Option, sensitive_data: Option, outside_info: Option, creation_pcrs: Option, ) -> Result { let sensitive_create = TPM2B_SENSITIVE_CREATE { size: std::mem::size_of::() .try_into() .unwrap(), // will not fail on targets of at least 16 bits sensitive: TPMS_SENSITIVE_CREATE { userAuth: auth_value.unwrap_or_default().into(), data: sensitive_data.unwrap_or_default().into(), }, }; let creation_pcrs = PcrSelectionList::list_from_option(creation_pcrs); let mut out_public_ptr = null_mut(); let mut out_private_ptr = null_mut(); let mut creation_data_ptr = null_mut(); let mut creation_hash_ptr = null_mut(); let mut creation_ticket_ptr = null_mut(); let ret = unsafe { Esys_Create( self.mut_context(), parent_handle.into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), &sensitive_create, &public.try_into()?, &outside_info.unwrap_or_default().into(), &creation_pcrs.into(), &mut out_private_ptr, &mut out_public_ptr, &mut creation_data_ptr, &mut creation_hash_ptr, &mut creation_ticket_ptr, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { let out_private_owned = Context::ffi_data_to_owned(out_private_ptr); let out_public_owned = Context::ffi_data_to_owned(out_public_ptr); let creation_data_owned = Context::ffi_data_to_owned(creation_data_ptr); let creation_hash_owned = Context::ffi_data_to_owned(creation_hash_ptr); let creation_ticket_owned = Context::ffi_data_to_owned(creation_ticket_ptr); Ok(CreateKeyResult { out_private: Private::try_from(out_private_owned)?, out_public: Public::try_from(out_public_owned)?, creation_data: CreationData::try_from(creation_data_owned)?, creation_hash: Digest::try_from(creation_hash_owned)?, creation_ticket: CreationTicket::try_from(creation_ticket_owned)?, }) } else { error!("Error in creating derived key: {}", ret); Err(ret) } } /// Load a previously generated key back into the TPM and return its new handle. pub fn load( &mut self, parent_handle: KeyHandle, private: Private, public: Public, ) -> Result { let mut object_handle = ObjectHandle::None.into(); let ret = unsafe { Esys_Load( self.mut_context(), parent_handle.into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), &private.into(), &public.try_into()?, &mut object_handle, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { let key_handle = KeyHandle::from(object_handle); self.handle_manager .add_handle(key_handle.into(), HandleDropAction::Flush)?; Ok(key_handle) } else { error!("Error in loading: {}", ret); Err(ret) } } /// Load an external key into the TPM and return its new handle. pub fn load_external( &mut self, private: Sensitive, public: Public, hierarchy: Hierarchy, ) -> Result { let mut object_handle = ObjectHandle::None.into(); let ret = unsafe { Esys_LoadExternal( self.mut_context(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), &private.try_into()?, &public.try_into()?, if cfg!(tpm2_tss_version = "2") { TpmHandle::from(hierarchy).into() } else { ObjectHandle::from(hierarchy).into() }, &mut object_handle, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { let key_handle = KeyHandle::from(object_handle); self.handle_manager .add_handle(key_handle.into(), HandleDropAction::Flush)?; Ok(key_handle) } else { error!("Error in loading external object: {}", ret); Err(ret) } } /// Load the public part of an external key and return its new handle. pub fn load_external_public( &mut self, public: Public, hierarchy: Hierarchy, ) -> Result { let mut object_handle = ObjectHandle::None.into(); let ret = unsafe { Esys_LoadExternal( self.mut_context(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), null(), &public.try_into()?, if cfg!(tpm2_tss_version = "2") { TpmHandle::from(hierarchy).into() } else { ObjectHandle::from(hierarchy).into() }, &mut object_handle, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { let key_handle = KeyHandle::from(object_handle); self.handle_manager .add_handle(key_handle.into(), HandleDropAction::Flush)?; Ok(key_handle) } else { error!("Error in loading external public object: {}", ret); Err(ret) } } /// Read the public part of a key currently in the TPM and return it. pub fn read_public(&mut self, key_handle: KeyHandle) -> Result<(Public, Name, Name)> { let mut out_public_ptr = null_mut(); let mut name_ptr = null_mut(); let mut qualified_name_ptr = null_mut(); let ret = unsafe { Esys_ReadPublic( self.mut_context(), key_handle.into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), &mut out_public_ptr, &mut name_ptr, &mut qualified_name_ptr, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(( Public::try_from(Context::ffi_data_to_owned(out_public_ptr))?, Name::try_from(Context::ffi_data_to_owned(name_ptr))?, Name::try_from(Context::ffi_data_to_owned(qualified_name_ptr))?, )) } else { error!("Error in reading public part of object: {}", ret); Err(ret) } } /// Activates a credential in a way that ensures parameters are validated. pub fn activate_credential( &mut self, activate_handle: KeyHandle, key_handle: KeyHandle, credential_blob: IdObject, secret: EncryptedSecret, ) -> Result { let mut cert_info_ptr = null_mut(); let ret = unsafe { Esys_ActivateCredential( self.mut_context(), activate_handle.into(), key_handle.into(), self.required_session_1()?, self.required_session_2()?, self.optional_session_3(), &credential_blob.into(), &secret.into(), &mut cert_info_ptr, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Digest::try_from(Context::ffi_data_to_owned(cert_info_ptr)) } else { error!("Error when activating credential: {}", ret); Err(ret) } } /// Perform actions to create a [IdObject] containing an activation credential. /// /// This does not use any TPM secrets, and is really just a convenience function. pub fn make_credential( &mut self, key_handle: KeyHandle, credential: Digest, object_name: Name, ) -> Result<(IdObject, EncryptedSecret)> { let mut credential_blob_ptr = null_mut(); let mut secret_ptr = null_mut(); let ret = unsafe { Esys_MakeCredential( self.mut_context(), key_handle.into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), &credential.into(), object_name.as_ref(), &mut credential_blob_ptr, &mut secret_ptr, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(( IdObject::try_from(Context::ffi_data_to_owned(credential_blob_ptr))?, EncryptedSecret::try_from(Context::ffi_data_to_owned(secret_ptr))?, )) } else { error!("Error when making credential: {}", ret); Err(ret) } } /// Unseal and return data from a Sealed Data Object pub fn unseal(&mut self, item_handle: ObjectHandle) -> Result { let mut out_data_ptr = null_mut(); let ret = unsafe { Esys_Unseal( self.mut_context(), item_handle.into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), &mut out_data_ptr, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { SensitiveData::try_from(Context::ffi_data_to_owned(out_data_ptr)) } else { error!("Error in unsealing: {}", ret); Err(ret) } } /// Change authorization for a TPM-resident object. pub fn object_change_auth( &mut self, object_handle: ObjectHandle, parent_handle: ObjectHandle, new_auth: Auth, ) -> Result { let mut out_private_ptr = null_mut(); let ret = unsafe { Esys_ObjectChangeAuth( self.mut_context(), object_handle.into(), parent_handle.into(), self.required_session_1()?, self.optional_session_2(), self.optional_session_3(), &new_auth.into(), &mut out_private_ptr, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Private::try_from(Context::ffi_data_to_owned(out_private_ptr)) } else { error!("Error changing object auth: {}", ret); Err(ret) } } // Missing function: CreateLoaded } tss-esapi-7.4.0/src/context/tpm_commands/random_number_generator.rs000064400000000000000000000036431046102023000237520ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ structures::{Digest, SensitiveData}, tss2_esys::{Esys_GetRandom, Esys_StirRandom}, Context, Error, Result, WrapperErrorKind as ErrorKind, }; use log::error; use std::convert::{TryFrom, TryInto}; use std::ptr::null_mut; impl Context { /// Get a number of random bytes from the TPM and return them. /// /// # Errors /// * if converting `num_bytes` to `u16` fails, a `WrongParamSize` will be returned pub fn get_random(&mut self, num_bytes: usize) -> Result { let mut random_bytes_ptr = null_mut(); let ret = unsafe { Esys_GetRandom( self.mut_context(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), num_bytes .try_into() .map_err(|_| Error::local_error(ErrorKind::WrongParamSize))?, &mut random_bytes_ptr, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Digest::try_from(Context::ffi_data_to_owned(random_bytes_ptr)) } else { error!("Error in getting random bytes: {}", ret); Err(ret) } } /// Add additional information into the TPM RNG state pub fn stir_random(&mut self, in_data: SensitiveData) -> Result<()> { let ret = unsafe { Esys_StirRandom( self.mut_context(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), &in_data.into(), ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(()) } else { error!("Error stirring random: {}", ret); Err(ret) } } } tss-esapi-7.4.0/src/context/tpm_commands/session_commands.rs000064400000000000000000000076001046102023000224150ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ constants::SessionType, context::handle_manager::HandleDropAction, handles::{KeyHandle, ObjectHandle, SessionHandle}, interface_types::{ algorithm::HashingAlgorithm, session_handles::{AuthSession, PolicySession}, }, structures::{Nonce, SymmetricDefinition}, tss2_esys::{Esys_PolicyRestart, Esys_StartAuthSession}, Context, Error, Result, }; use log::error; use std::{convert::TryInto, ptr::null}; impl Context { /// Start new authentication session and return the Session object /// associated with the session. /// /// If the returned session handle from ESYS api is ESYS_TR_NONE then /// the value of the option in the result will be None. /// /// # Example /// /// ```rust /// # use tss_esapi::{Context, Tcti, /// # constants::SessionType, /// # interface_types::algorithm::HashingAlgorithm, /// # structures::SymmetricDefinition, /// # }; /// # // Create context /// # let mut context = /// # Context::new( /// # Tcti::from_environment_variable().expect("Failed to get TCTI"), /// # ).expect("Failed to create Context"); /// // Create auth session without key_handle, bind_handle /// // and Nonce /// let session = context /// .start_auth_session( /// None, /// None, /// None, /// SessionType::Hmac, /// SymmetricDefinition::AES_256_CFB, /// HashingAlgorithm::Sha256, /// ) /// .expect("Failed to create session") /// .expect("Received invalid handle"); /// ``` #[allow(clippy::too_many_arguments)] pub fn start_auth_session( &mut self, tpm_key: Option, bind: Option, nonce: Option, session_type: SessionType, symmetric: SymmetricDefinition, auth_hash: HashingAlgorithm, ) -> Result> { let mut session_handle = ObjectHandle::None.into(); let potential_tpm2b_nonce = nonce.map(|v| v.into()); let ret = unsafe { Esys_StartAuthSession( self.mut_context(), tpm_key .map(ObjectHandle::from) .unwrap_or(ObjectHandle::None) .into(), bind.unwrap_or(ObjectHandle::None).into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), potential_tpm2b_nonce.as_ref().map_or_else(null, |v| v), session_type.into(), &symmetric.try_into()?, auth_hash.into(), &mut session_handle, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { self.handle_manager .add_handle(session_handle.into(), HandleDropAction::Flush)?; Ok(AuthSession::create( session_type, session_handle.into(), auth_hash, )) } else { error!("Error when creating a session: {}", ret); Err(ret) } } /// Restart the TPM Policy pub fn policy_restart(&mut self, policy_session: PolicySession) -> Result<()> { let ret = unsafe { Esys_PolicyRestart( self.mut_context(), SessionHandle::from(policy_session).into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(()) } else { error!("Error restarting policy: {}", ret); Err(ret) } } } tss-esapi-7.4.0/src/context/tpm_commands/signing_and_signature_verification.rs000064400000000000000000000044561046102023000261620ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ handles::KeyHandle, structures::{Digest, HashcheckTicket, Signature, SignatureScheme, VerifiedTicket}, tss2_esys::{Esys_Sign, Esys_VerifySignature}, Context, Error, Result, }; use log::error; use std::convert::{TryFrom, TryInto}; use std::ptr::null_mut; impl Context { /// Verify if a signature was generated by signing a given digest with a key in the TPM. pub fn verify_signature( &mut self, key_handle: KeyHandle, digest: Digest, signature: Signature, ) -> Result { let mut validation_ptr = null_mut(); let ret = unsafe { Esys_VerifySignature( self.mut_context(), key_handle.into(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), &digest.into(), &signature.try_into()?, &mut validation_ptr, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { VerifiedTicket::try_from(Context::ffi_data_to_owned(validation_ptr)) } else { error!("Error when verifying signature: {}", ret); Err(ret) } } /// Sign a digest with a key present in the TPM and return the signature. pub fn sign( &mut self, key_handle: KeyHandle, digest: Digest, scheme: SignatureScheme, validation: HashcheckTicket, ) -> Result { let mut signature_ptr = null_mut(); let ret = unsafe { Esys_Sign( self.mut_context(), key_handle.into(), self.required_session_1()?, self.optional_session_2(), self.optional_session_3(), &digest.into(), &scheme.into(), &validation.try_into()?, &mut signature_ptr, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Signature::try_from(Context::ffi_data_to_owned(signature_ptr)) } else { error!("Error when signing: {}", ret); Err(ret) } } } tss-esapi-7.4.0/src/context/tpm_commands/startup.rs000064400000000000000000000023651046102023000205560ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ constants::StartupType, tss2_esys::{Esys_Shutdown, Esys_Startup}, Context, Error, Result, }; use log::error; impl Context { /// Send a TPM2_STARTUP command to the TPM pub fn startup(&mut self, startup_type: StartupType) -> Result<()> { let ret = unsafe { Esys_Startup(self.mut_context(), startup_type.into()) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(()) } else { error!("Error while starting up TPM: {}", ret); Err(ret) } } /// Send a TPM2_SHUTDOWN command to the TPM pub fn shutdown(&mut self, shutdown_type: StartupType) -> Result<()> { let ret = unsafe { Esys_Shutdown( self.mut_context(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), shutdown_type.into(), ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(()) } else { error!("Error while shutting down TPM: {}", ret); Err(ret) } } } tss-esapi-7.4.0/src/context/tpm_commands/symmetric_primitives.rs000064400000000000000000000370311046102023000233410ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ handles::{KeyHandle, ObjectHandle, TpmHandle}, interface_types::{ algorithm::{HashingAlgorithm, SymmetricMode}, resource_handles::Hierarchy, }, structures::{Digest, HashcheckTicket, InitialValue, MaxBuffer}, tss2_esys::{Esys_EncryptDecrypt2, Esys_HMAC, Esys_Hash}, Context, Error, Result, }; use log::error; use std::convert::TryFrom; use std::ptr::null_mut; impl Context { // Missing function: EncryptDecrypt, deprecated use EncryptDecrypt2 instead. /// Performs symmetric encryption or decryption of the data using /// the key associated with the `key_handle` /// /// # Arguments /// * `key_handle` - A [KeyHandle] to the key to be used. /// * `decrypt` - A boolean indicating if the data should be decrypted or encrypted. /// If set to true the data will be decrypted else encrypted. /// * `mode` - The [SymmetricMode] to be used. /// * `in_data` - The data that is going to be decrypted or encrypted. /// * `initial_value_in` - An initial value as required by the algorithm. /// /// # Example /// ```rust /// # use tss_esapi::{ /// # constants::AlgorithmIdentifier, /// # attributes::ObjectAttributesBuilder, /// # Context, tcti_ldr::TctiNameConf, Result, /// # structures::{ /// # Auth, InitialValue, MaxBuffer, SensitiveData, RsaExponent, SymmetricDefinitionObject, /// # SymmetricCipherParameters, PublicBuilder, /// # }, /// # interface_types::{ /// # algorithm::{PublicAlgorithm, HashingAlgorithm}, /// # key_bits::RsaKeyBits, /// # }, /// # }; /// use tss_esapi::interface_types::session_handles::AuthSession; /// use tss_esapi::interface_types::algorithm::SymmetricMode; /// # use std::convert::TryFrom; /// # // Create context /// # let mut context = /// # Context::new( /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"), /// # ).expect("Failed to create Context"); /// # // Set auth for owner /// # context /// # .tr_set_auth(tss_esapi::interface_types::resource_handles::Hierarchy::Owner.into(), Auth::default()) /// # .expect("Failed to set auth to empty for owner"); /// # // Create primary key auth /// # let primary_key_auth = Auth::try_from( /// # context /// # .get_random(16) /// # .expect("get_rand call failed") /// # .value() /// # .to_vec(), /// # ) /// # .expect("Failed to create primary key auth"); /// # // Create primary key /// # let primary_key_handle = context.execute_with_session(Some(AuthSession::Password), |ctx| { /// # ctx.create_primary( /// # tss_esapi::interface_types::resource_handles::Hierarchy::Owner, /// # tss_esapi::utils::create_restricted_decryption_rsa_public( /// # SymmetricDefinitionObject::AES_256_CFB, /// # RsaKeyBits::Rsa2048, /// # RsaExponent::default(), /// # ) /// # .expect("Failed to create public for primary key"), /// # Some(primary_key_auth.clone()), /// # None, /// # None, /// # None, /// # ) /// # .expect("Failed to create primary handle") /// # .key_handle /// # }); /// # // Set auth for the primary key handle /// # context /// # .tr_set_auth(primary_key_handle.into(), primary_key_auth) /// # .expect("Failed to set auth from primary key handle."); /// # // Create symmetric key objhect attributes /// # let symmetric_key_object_attributes = ObjectAttributesBuilder::new() /// # .with_user_with_auth(true) /// # .with_sign_encrypt(true) /// # .with_decrypt(true) /// # .build() /// # .expect("Failed to create object attributes for symmetric key"); /// # // Create public part for the symmetric key /// # let symmetric_key_public = PublicBuilder::new() /// # .with_public_algorithm(PublicAlgorithm::SymCipher) /// # .with_name_hashing_algorithm(HashingAlgorithm::Sha256) /// # .with_object_attributes(symmetric_key_object_attributes) /// # .with_symmetric_cipher_parameters(SymmetricCipherParameters::new(SymmetricDefinitionObject::AES_256_CFB)) /// # .with_symmetric_cipher_unique_identifier(Default::default()) /// # .build() /// # .expect("Failed to create public for symmetric key public"); /// # // Create auth for the symmetric key /// # let symmetric_key_auth = Auth::try_from( /// # context /// # .get_random(16) /// # .expect("get_rand call failed") /// # .value() /// # .to_vec(), /// # ) /// # .expect("Failed to create symmetric key auth"); /// # // Create symmetric key data /// # let symmetric_key_value = /// # SensitiveData::try_from(vec![ /// # 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, /// # 17, 18, 19, 20, 21, 22 ,23, 24, 25, 26, 27, 28, 29, 30, 31, 32]) /// # .expect("Failed to create sensitive data from data"); /// # // Create the symmetric key /// # // if this fails with "tpm:parameter(2):inconsistent attributes" then the symmetric /// # // cipher is probably not supported. /// # let symmetric_key_creation_data = /// # context.execute_with_session(Some(AuthSession::Password), |ctx| { /// # ctx.create( /// # primary_key_handle, /// # symmetric_key_public, /// # Some(symmetric_key_auth.clone()), /// # Some(symmetric_key_value), /// # None, /// # None, /// # ) /// # .expect("Failed to create symmetric key") /// # }); /// # // Load the symmetric key in order to get handle to it. /// # let symmetric_key_handle = /// # context.execute_with_session(Some(AuthSession::Password), |ctx| { /// # ctx.load( /// # primary_key_handle, /// # symmetric_key_creation_data.out_private, /// # symmetric_key_creation_data.out_public, /// # ) /// # .expect("Failed to load symmetric key") /// # }); /// # // Set auth for the handle to be able to use it. /// # context /// # .tr_set_auth(symmetric_key_handle.into(), symmetric_key_auth) /// # .expect("Failed to set auth on symmetric key handle"); /// # /// # // Create initial value to be used by the algorithm. /// # let initial_value = /// # InitialValue::try_from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]) /// # .expect("Failed to create InitialValue from data"); /// # // Create data to be encrypted. /// # let data = MaxBuffer::try_from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 16]) /// # .expect("Failed to create MaxBuffer from data"); /// // Encrypt the data /// let (encrypted_data, _initial_value_out) = /// context.execute_with_session(Some(AuthSession::Password), |ctx| { /// ctx.encrypt_decrypt_2( /// symmetric_key_handle, // Handle to a symmetric key /// false, // false, indicates that the data should be encrypted. /// SymmetricMode::Cfb, // The symmetric mode of the encryption. /// data.clone(), // The data that is to be encrypted. /// initial_value.clone(), // Initial value needed by the algorithmen. /// ) /// .expect("Call to encrypt_decrypt_2 failed when encrypting data") /// }); /// /// assert_ne!(data.clone(), encrypted_data); /// # /// # let (decrypted_data, _) = /// # context.execute_with_session(Some(AuthSession::Password), |ctx| { /// # ctx.encrypt_decrypt_2( /// # symmetric_key_handle, /// # true, /// # SymmetricMode::Cfb, /// # encrypted_data, /// # initial_value, /// # ) /// # .expect("Call to encrypt_decrypt_2 failed when decrypting data") /// # }); /// # /// # debug_assert_eq!(data, decrypted_data); /// ``` pub fn encrypt_decrypt_2( &mut self, key_handle: KeyHandle, decrypt: bool, mode: SymmetricMode, in_data: MaxBuffer, initial_value_in: InitialValue, ) -> Result<(MaxBuffer, InitialValue)> { let mut out_data_ptr = null_mut(); let mut iv_out_ptr = null_mut(); let ret = unsafe { Esys_EncryptDecrypt2( self.mut_context(), key_handle.into(), self.required_session_1()?, self.optional_session_2(), self.optional_session_3(), &in_data.into(), decrypt.into(), mode.into(), &initial_value_in.into(), &mut out_data_ptr, &mut iv_out_ptr, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(( MaxBuffer::try_from(Context::ffi_data_to_owned(out_data_ptr))?, InitialValue::try_from(Context::ffi_data_to_owned(iv_out_ptr))?, )) } else { error!( "Error failed to perform encrypt or decrypt operations {}", ret ); Err(ret) } } /// Hashes the provided data using the specified algorithm. /// /// # Details /// Performs the specified hash operation on a data buffer and return /// the result. The HashCheckTicket indicates if the hash can be used in /// a signing operation that uses restricted signing key. /// /// # Example /// /// ```rust /// # use tss_esapi::{Context, tcti_ldr::TctiNameConf, /// # structures::{MaxBuffer, Ticket}, /// # interface_types::{algorithm::HashingAlgorithm, resource_handles::Hierarchy}, /// # }; /// # use std::convert::TryFrom; /// # // Create context /// # let mut context = /// # Context::new( /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"), /// # ).expect("Failed to create Context"); /// let input_data = MaxBuffer::try_from("There is no spoon".as_bytes().to_vec()) /// .expect("Failed to create buffer for input data."); /// let expected_hashed_data: [u8; 32] = [ /// 0x6b, 0x38, 0x4d, 0x2b, 0xfb, 0x0e, 0x0d, 0xfb, 0x64, 0x89, 0xdb, 0xf4, 0xf8, 0xe9, /// 0xe5, 0x2f, 0x71, 0xee, 0xb1, 0x0d, 0x06, 0x4c, 0x56, 0x59, 0x70, 0xcd, 0xd9, 0x44, /// 0x43, 0x18, 0x5d, 0xc1, /// ]; /// let expected_hierarchy = Hierarchy::Owner; /// let (actual_hashed_data, ticket) = context /// .hash( /// input_data, /// HashingAlgorithm::Sha256, /// expected_hierarchy, /// ) /// .expect("Call to hash failed."); /// assert_eq!(expected_hashed_data.len(), actual_hashed_data.len()); /// assert_eq!(&expected_hashed_data[..], &actual_hashed_data[..]); /// assert_eq!(ticket.hierarchy(), expected_hierarchy); /// ``` pub fn hash( &mut self, data: MaxBuffer, hashing_algorithm: HashingAlgorithm, hierarchy: Hierarchy, ) -> Result<(Digest, HashcheckTicket)> { let mut out_hash_ptr = null_mut(); let mut validation_ptr = null_mut(); let ret = unsafe { Esys_Hash( self.mut_context(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), &data.into(), hashing_algorithm.into(), if cfg!(tpm2_tss_version = "2") { TpmHandle::from(hierarchy).into() } else { ObjectHandle::from(hierarchy).into() }, &mut out_hash_ptr, &mut validation_ptr, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(( Digest::try_from(Context::ffi_data_to_owned(out_hash_ptr))?, HashcheckTicket::try_from(Context::ffi_data_to_owned(validation_ptr))?, )) } else { error!("Error failed to perform hash operation: {}", ret); Err(ret) } } /// Asks the TPM to compute an HMAC over buffer with the specified key /// /// # Example /// /// ```rust /// # use tss_esapi::{ /// # attributes::ObjectAttributesBuilder, /// # structures::{MaxBuffer, Ticket, PublicKeyedHashParameters, KeyedHashScheme, HmacScheme, PublicBuilder, Digest}, /// # interface_types::{ /// # resource_handles::Hierarchy, /// # algorithm::{HashingAlgorithm, PublicAlgorithm}, /// # }, /// # Context, tcti_ldr::TctiNameConf, /// # }; /// # use std::convert::TryFrom; /// # // Create context /// # let mut context = /// # Context::new( /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"), /// # ).expect("Failed to create Context"); /// // Create a key /// let object_attributes = ObjectAttributesBuilder::new() /// .with_sign_encrypt(true) /// .with_sensitive_data_origin(true) /// .with_user_with_auth(true) /// .build() /// .expect("Failed to build object attributes"); /// let key_pub = PublicBuilder::new() /// .with_public_algorithm(PublicAlgorithm::KeyedHash) /// .with_name_hashing_algorithm(HashingAlgorithm::Sha256) /// .with_object_attributes(object_attributes) /// .with_keyed_hash_parameters(PublicKeyedHashParameters::new(KeyedHashScheme::HMAC_SHA_256)) /// .with_keyed_hash_unique_identifier(Digest::default()) /// .build() /// .unwrap(); /// /// let input_data = MaxBuffer::try_from("There is no spoon".as_bytes().to_vec()) /// .expect("Failed to create buffer for input data."); /// /// let hmac = context.execute_with_nullauth_session(|ctx| { /// let key = ctx.create_primary(Hierarchy::Owner, key_pub, None, None, None, None).unwrap(); /// /// ctx.hmac(key.key_handle.into(), input_data, HashingAlgorithm::Sha256) /// }).unwrap(); /// /// ``` /// /// # Errors /// * if any of the public parameters is not compatible with the TPM, /// an `Err` containing the specific unmarshalling error will be returned. pub fn hmac( &mut self, handle: ObjectHandle, buffer: MaxBuffer, alg_hash: HashingAlgorithm, ) -> Result { let mut out_hmac_ptr = null_mut(); let ret = unsafe { Esys_HMAC( self.mut_context(), handle.into(), self.required_session_1()?, self.optional_session_2(), self.optional_session_3(), &buffer.into(), alg_hash.into(), &mut out_hmac_ptr, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Digest::try_from(Context::ffi_data_to_owned(out_hmac_ptr)) } else { error!("Error in hmac: {}", ret); Err(ret) } } // Missing function: MAC } tss-esapi-7.4.0/src/context/tpm_commands/testing.rs000064400000000000000000000041171046102023000205260ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ interface_types::YesNo, structures::MaxBuffer, tss2_esys::{Esys_GetTestResult, Esys_SelfTest}, Context, Error, Result, }; use log::error; use std::convert::TryFrom; use std::ptr::null_mut; impl Context { /// Execute the TPM self test and returns the result pub fn self_test(&mut self, full_test: bool) -> Result<()> { let ret = unsafe { Esys_SelfTest( self.mut_context(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), YesNo::from(full_test).into(), ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(()) } else { error!("Error in self-test: {}", ret); Err(ret) } } // Missing function: incremental_self_test /// Get the TPM self test result /// /// The returned buffer data is manufacturer-specific information. pub fn get_test_result(&mut self) -> Result<(MaxBuffer, Result<()>)> { let mut out_data_ptr = null_mut(); let mut test_result: u32 = 0; let ret = unsafe { Esys_GetTestResult( self.mut_context(), self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), &mut out_data_ptr, &mut test_result, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { let out_data = MaxBuffer::try_from(Context::ffi_data_to_owned(out_data_ptr))?; let test_result_rc = Error::from_tss_rc(test_result); let test_result_rc = if test_result_rc.is_success() { Ok(()) } else { Err(test_result_rc) }; Ok((out_data, test_result_rc)) } else { error!("Error getting test result: {}", ret); Err(ret) } } } tss-esapi-7.4.0/src/context/tpm_commands/vendor_specific.rs000064400000000000000000000002541046102023000222110ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::Context; impl Context { // Missing function: Vendor_TCG_Test } tss-esapi-7.4.0/src/context.rs000064400000000000000000000422661046102023000143770ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod handle_manager; use crate::{ attributes::SessionAttributesBuilder, constants::{CapabilityType, PropertyTag, SessionType}, handles::{ObjectHandle, SessionHandle}, interface_types::{algorithm::HashingAlgorithm, session_handles::AuthSession}, structures::{CapabilityData, SymmetricDefinition}, tcti_ldr::{TabrmdConfig, TctiContext, TctiNameConf}, tss2_esys::*, Error, Result, WrapperErrorKind as ErrorKind, }; use handle_manager::HandleManager; use log::{error, info}; use mbox::MBox; use std::collections::HashMap; use std::ptr::null_mut; /// Safe abstraction over an ESYS_CONTEXT. /// /// Serves as a low-level abstraction interface to the TPM, providing a thin wrapper around the /// `unsafe` FFI calls. It is meant for more advanced uses of the TSS where control over all /// parameters is necessary or important. /// /// The methods it exposes take the parameters advertised by the specification, with some of the /// parameters being passed as generated by `bindgen` and others in a more convenient/Rust-efficient /// way. /// /// The context also keeps track of all object allocated and deallocated through it and, before /// being dropped, will attempt to close all outstanding handles. However, care must be taken by /// the client to not exceed the maximum number of slots available from the RM. /// /// Code safety-wise, the methods should cover the two kinds of problems that might arise: /// * in terms of memory safety, all parameters passed down to the TSS are verified and the library /// stack is then trusted to provide back valid outputs /// * in terms of thread safety, all methods require a mutable reference to the context object, /// ensuring that no two threads can use the context at the same time for an operation (barring use /// of `unsafe` constructs on the client side) /// More testing and verification will be added to ensure this. /// /// For most methods, if the wrapped TSS call fails and returns a non-zero `TPM2_RC`, a /// corresponding `Tss2ResponseCode` will be created and returned as an `Error`. Wherever this is /// not the case or additional error types can be returned, the method definition should mention /// it. #[derive(Debug)] pub struct Context { /// Handle for the ESYS context object owned through an Mbox. /// Wrapping the handle in an optional Mbox is done to allow the `Context` to be closed properly when the `Context` structure is dropped. esys_context: Option>, sessions: ( Option, Option, Option, ), /// TCTI context handle associated with the ESYS context. /// As with the ESYS context, an optional Mbox wrapper allows the context to be deallocated. _tcti_context: TctiContext, /// Handle manager that keep tracks of the state of the handles and how they are to be /// disposed. handle_manager: HandleManager, /// A cache of determined TPM limits cached_tpm_properties: HashMap, } // Implementation of the TPM commands mod tpm_commands; // Implementation of the ESAPI session administration // functions. mod session_administration; // Implementation of the general ESAPI ESYS_TR functions mod general_esys_tr; impl Context { /// Create a new ESYS context based on the desired TCTI /// /// # Warning /// The client is responsible for ensuring that the context can be initialized safely, /// threading-wise. Some TCTI are not safe to execute with multiple commands in parallel. /// If the sequence of commands to the TPM is interrupted by another application, commands /// might fail unexpectedly. /// If multiple applications are using the TPM in parallel, make sure to use the TABRMD TCTI /// which will offer multi-user support to a single TPM device. /// See the /// [specification](https://trustedcomputinggroup.org/wp-content/uploads/TSS-TAB-and-Resource-Manager-ver1.0-rev16_Public_Review.pdf) for more information. /// /// # Errors /// * if either `Tss2_TctiLdr_Initiialize` or `Esys_Initialize` fail, a corresponding /// Tss2ResponseCode will be returned pub fn new(tcti_name_conf: TctiNameConf) -> Result { let mut esys_context = null_mut(); let mut _tcti_context = TctiContext::initialize(tcti_name_conf)?; let ret = unsafe { Esys_Initialize( &mut esys_context, _tcti_context.tcti_context_ptr(), null_mut(), ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { let esys_context = unsafe { Some(MBox::from_raw(esys_context)) }; let context = Context { esys_context, sessions: (None, None, None), _tcti_context, handle_manager: HandleManager::new(), cached_tpm_properties: HashMap::new(), }; Ok(context) } else { error!("Error when creating a new context: {}", ret); Err(ret) } } /// Create a new ESYS context based on the TAB Resource Manager Daemon. /// The TABRMD will make sure that multiple users can use the TPM safely. /// /// # Errors /// * if either `Tss2_TctiLdr_Initiialize` or `Esys_Initialize` fail, a corresponding /// Tss2ResponseCode will be returned pub fn new_with_tabrmd(tabrmd_conf: TabrmdConfig) -> Result { Context::new(TctiNameConf::Tabrmd(tabrmd_conf)) } /// Set the sessions to be used in calls to ESAPI. /// /// # Details /// In some calls these sessions are optional and in others /// they are required. /// /// # Example /// /// ```rust /// # use tss_esapi::{Context, tcti_ldr::TctiNameConf, /// # constants::SessionType, /// # interface_types::algorithm::HashingAlgorithm, /// # structures::SymmetricDefinition, /// # }; /// # // Create context /// # let mut context = /// # Context::new( /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"), /// # ).expect("Failed to create Context"); /// // Create auth session without key_handle, bind_handle /// // and Nonce /// let auth_session = context /// .start_auth_session( /// None, /// None, /// None, /// SessionType::Hmac, /// SymmetricDefinition::AES_256_CFB, /// HashingAlgorithm::Sha256, /// ) /// .expect("Failed to create session"); /// /// // Set auth_session as the first handle to be /// // used in calls to ESAPI no matter if it None /// // or not. /// context.set_sessions((auth_session, None, None)); /// ``` pub fn set_sessions( &mut self, session_handles: ( Option, Option, Option, ), ) { self.sessions = session_handles; } /// Clears any sessions that have been set /// /// This will result in the None handle being /// used in all calls to ESAPI. /// /// # Example /// /// ```rust /// # use tss_esapi::{Context, tcti_ldr::TctiNameConf, interface_types::session_handles::AuthSession}; /// # // Create context /// # let mut context = /// # Context::new( /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"), /// # ).expect("Failed to create Context"); /// // Use password session for auth /// context.set_sessions((Some(AuthSession::Password), None, None)); /// /// // Clear auth sessions /// context.clear_sessions(); /// ``` pub fn clear_sessions(&mut self) { self.sessions = (None, None, None) } /// Returns the sessions that are currently set. /// /// # Example /// /// ```rust /// # use tss_esapi::{Context, tcti_ldr::TctiNameConf, interface_types::session_handles::AuthSession}; /// # // Create context /// # let mut context = /// # Context::new( /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"), /// # ).expect("Failed to create Context"); /// // Use password session for auth /// context.set_sessions((Some(AuthSession::Password), None, None)); /// /// // Retrieve sessions in use /// let (session_1, session_2, session_3) = context.sessions(); /// assert_eq!(Some(AuthSession::Password), session_1); /// assert_eq!(None, session_2); /// assert_eq!(None, session_3); /// ``` pub fn sessions( &self, ) -> ( Option, Option, Option, ) { self.sessions } /// Execute the closure in f with the specified set of sessions, and sets the original sessions back afterwards pub fn execute_with_sessions( &mut self, session_handles: ( Option, Option, Option, ), f: F, ) -> T where // We only need to call f once, so it can be FnOnce F: FnOnce(&mut Context) -> T, { let oldses = self.sessions(); self.set_sessions(session_handles); let res = f(self); self.set_sessions(oldses); res } /// Executes the closure with a single session set, and the others set to None pub fn execute_with_session(&mut self, session_handle: Option, f: F) -> T where // We only need to call f once, so it can be FnOnce F: FnOnce(&mut Context) -> T, { self.execute_with_sessions((session_handle, None, None), f) } /// Executes the closure without any sessions, pub fn execute_without_session(&mut self, f: F) -> T where // We only need to call f once, so it can be FnOnce F: FnOnce(&mut Context) -> T, { self.execute_with_sessions((None, None, None), f) } /// Executes the closure with a newly generated empty session /// /// # Details /// The session attributes for the generated empty session that /// is used to execute closure will have the attributes decrypt /// and encrypt set. pub fn execute_with_nullauth_session(&mut self, f: F) -> std::result::Result where // We only need to call f once, so it can be FnOnce F: FnOnce(&mut Context) -> std::result::Result, E: From, { let auth_session = match self.start_auth_session( None, None, None, SessionType::Hmac, SymmetricDefinition::AES_128_CFB, HashingAlgorithm::Sha256, )? { Some(ses) => ses, None => return Err(E::from(Error::local_error(ErrorKind::WrongValueFromTpm))), }; let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new() .with_decrypt(true) .with_encrypt(true) .build(); self.tr_sess_set_attributes(auth_session, session_attributes, session_attributes_mask)?; let res = self.execute_with_session(Some(auth_session), f); self.flush_context(SessionHandle::from(auth_session).into())?; res } /// Execute the closure in f, and clear up the object after it's done before returning the result /// This is a convenience function that ensures object is always closed, even if an error occurs pub fn execute_with_temporary_object(&mut self, object: ObjectHandle, f: F) -> Result where F: FnOnce(&mut Context, ObjectHandle) -> Result, { let res = f(self, object); self.flush_context(object)?; res } /// Determine a TPM property /// /// # Details /// Returns the value of the provided `TpmProperty` if /// the TPM has a value for it else None will be returned. /// If None is returned then use default from specification. /// /// # Errors /// If the TPM returns a value that is wrong when /// its capabilities is being retrieved then a /// `WrongValueFromTpm` is returned. /// /// # Example /// /// ```rust /// # use tss_esapi::{Context, tcti_ldr::TctiNameConf, constants::PropertyTag}; /// # use std::str::FromStr; /// # // Create context /// # let mut context = /// # Context::new( /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"), /// # ).expect("Failed to create Context"); /// let rev = context /// .get_tpm_property(PropertyTag::Revision) /// .expect("Wrong value from TPM") /// .expect("Value is not supported"); /// ``` pub fn get_tpm_property(&mut self, property: PropertyTag) -> Result> { // Return cached value if it exists if let Some(&val) = self.cached_tpm_properties.get(&property) { return Ok(Some(val)); } let (capabs, _) = self.execute_without_session(|ctx| { ctx.get_capability(CapabilityType::TpmProperties, property.into(), 4) })?; let props = match capabs { CapabilityData::TpmProperties(props) => props, _ => return Err(Error::WrapperError(ErrorKind::WrongValueFromTpm)), }; for tagged_property in props { // If we are returned a property we don't know, just ignore it let _ = self .cached_tpm_properties .insert(tagged_property.property(), tagged_property.value()); } if let Some(val) = self.cached_tpm_properties.get(&property) { return Ok(Some(*val)); } Ok(None) } // //////////////////////////////////////////////////////////////////////// // Private Methods Section // //////////////////////////////////////////////////////////////////////// /// Returns a mutable reference to the native ESYS context handle. fn mut_context(&mut self) -> *mut ESYS_CONTEXT { self.esys_context .as_mut() .map(MBox::::as_mut_ptr) .unwrap() // will only fail if called from Drop after .take() } /// Private method for retrieving the ESYS session handle for /// the optional session 1. fn optional_session_1(&self) -> ESYS_TR { SessionHandle::from(self.sessions.0).into() } /// Private method for retrieving the ESYS session handle for /// the optional session 2. fn optional_session_2(&self) -> ESYS_TR { SessionHandle::from(self.sessions.1).into() } /// Private method for retrieving the ESYS session handle for /// the optional session 3. fn optional_session_3(&self) -> ESYS_TR { SessionHandle::from(self.sessions.2).into() } /// Private method that returns the required /// session handle 1 if it is available else /// returns an error. fn required_session_1(&self) -> Result { self.sessions .0 .map(|v| SessionHandle::from(v).into()) .ok_or_else(|| { error!("Missing session handle for authorization (authSession1 = None)"); Error::local_error(ErrorKind::MissingAuthSession) }) } /// Private method that returns the required /// session handle 2 if it is available else /// returns an error. fn required_session_2(&self) -> Result { self.sessions .1 .map(|v| SessionHandle::from(v).into()) .ok_or_else(|| { error!("Missing session handle for authorization (authSession2 = None)"); Error::local_error(ErrorKind::MissingAuthSession) }) } /// Private function for handling that has been allocated with /// C memory allocation functions in TSS. fn ffi_data_to_owned(data_ptr: *mut T) -> T { MBox::into_inner(unsafe { MBox::from_raw(data_ptr) }) } } impl Drop for Context { fn drop(&mut self) { info!("Closing context."); // Flush handles for handle in self.handle_manager.handles_to_flush() { info!("Flushing handle {}", ESYS_TR::from(handle)); if let Err(e) = self.flush_context(handle) { error!("Error when dropping the context: {}", e); } } // Close handles for handle in self.handle_manager.handles_to_close().iter_mut() { info!("Closing handle {}", ESYS_TR::from(*handle)); if let Err(e) = self.tr_close(handle) { error!("Error when dropping context: {}.", e); } } // Check if all handles have been cleaned up proeprly. if self.handle_manager.has_open_handles() { error!("Not all handles have had their resources successfully released"); } // Close the context. unsafe { Esys_Finalize( &mut self .esys_context .take() .map(MBox::::into_raw) .unwrap(), // should not fail based on how the context is initialised/used ) }; info!("Context closed."); } } tss-esapi-7.4.0/src/error.rs000064400000000000000000000077251046102023000140450ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::constants::response_code::Tss2ResponseCode; use crate::tss2_esys::TSS2_RC; /// Main error type used by the crate to return issues with a method call. The value can either be /// a TSS-generated response code or a wrapper error - marking an issue caught within the wrapping /// layer. pub type Result = std::result::Result; #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum Error { WrapperError(WrapperErrorKind), Tss2Error(Tss2ResponseCode), } impl Error { pub(crate) fn from_tss_rc(rc: TSS2_RC) -> Self { Error::Tss2Error(Tss2ResponseCode::from_tss_rc(rc)) } pub(crate) fn local_error(kind: WrapperErrorKind) -> Self { Error::WrapperError(kind) } /// Verify whether the value contained is a success response code. pub fn is_success(self) -> bool { if let Error::Tss2Error(tss2_rc) = self { tss2_rc.is_success() } else { false } } } impl std::fmt::Display for Error { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Error::WrapperError(e) => e.fmt(f), Error::Tss2Error(e) => e.fmt(f), } } } impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self { Error::WrapperError(wrapper_error) => Some(wrapper_error), Error::Tss2Error(response_code) => Some(response_code), } } } /// List of error types that might occur in the wrapper. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum WrapperErrorKind { /// Returned when a size or length-defined parameter does not conform with the size /// restrictions for it. WrongParamSize, /// Returned when a required parameter was not passed, usually to a builder. ParamsMissing, /// Returned when two or more parameters have inconsistent values or variants. InconsistentParams, /// Returned when the value of a parameter is not yet supported. UnsupportedParam, /// Returned when the value of a parameter is invalid for that type. InvalidParam, /// Returned when the TPM returns an invalid value from a call. WrongValueFromTpm, /// Returned when a session for authentication has not been set /// before the call is made. MissingAuthSession, /// Returned when a handle is required to be in a specific state /// (i.g. Open, Flushed, Closed) but it is not. InvalidHandleState, /// An unexpected internal error occurred. InternalError, } impl std::fmt::Display for WrapperErrorKind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { WrapperErrorKind::WrongParamSize => { write!(f, "parameter provided is of the wrong size") } WrapperErrorKind::ParamsMissing => { write!(f, "some of the required parameters were not provided") } WrapperErrorKind::InconsistentParams => write!( f, "the provided parameters have inconsistent values or variants" ), WrapperErrorKind::UnsupportedParam => write!( f, "the provided parameter is not yet supported by the library" ), WrapperErrorKind::InvalidParam => { write!(f, "the provided parameter is invalid for that type.") } WrapperErrorKind::WrongValueFromTpm => write!(f, "the TPM returned an invalid value."), WrapperErrorKind::MissingAuthSession => write!(f, "Missing authorization session"), WrapperErrorKind::InvalidHandleState => write!(f, "Invalid handle state"), WrapperErrorKind::InternalError => { write!(f, "an unexpected error occurred within the crate") } } } } impl std::error::Error for WrapperErrorKind {} tss-esapi-7.4.0/src/handles/handle.rs000064400000000000000000000270751046102023000155650ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! ESYS handle types //! //! The ESAPI specification has only one handle type //! ESYS_TR. That type is wrapped by ObjectHandle but there //! are also specific handle types that indicates what created //! them or how they are intended to be used. pub mod conversions { pub(crate) trait TryIntoNotNone { fn try_into_not_none(self) -> crate::Result; } } /// Macro for generating a basic handle implementation macro_rules! impl_basic_handle { ( $(#[$outer:meta])* $handle_type:ident ) => { use crate::tss2_esys::ESYS_TR; use std::convert::From; $(#[$outer])* #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct $handle_type { value: u32, } impl $handle_type { pub fn value(&self) -> u32 { self.value } } impl From for $handle_type { fn from(tss_esys_object_handle: ESYS_TR) -> $handle_type { $handle_type { value: tss_esys_object_handle, } } } impl From<$handle_type> for ESYS_TR { fn from(handle: $handle_type) -> ESYS_TR { handle.value } } }; } /// Macro for making a esys constant available /// for a handle type. macro_rules! add_constant_handle { ($handle_type:ident, $constant_handle_name:ident, $constant_handle_value:ident) => { impl $handle_type { #[allow(non_upper_case_globals)] pub const $constant_handle_name: $handle_type = $handle_type { value: $constant_handle_value, }; } }; } /// Macro for making the Esys None constant available /// for a handle type macro_rules! add_constant_none_handle { ($handle_type:ident) => { use crate::{ handles::handle_conversion::TryIntoNotNone, tss2_esys::ESYS_TR_NONE, Error, Result, WrapperErrorKind as ErrorKind, }; use log::error; add_constant_handle!($handle_type, None, ESYS_TR_NONE); impl $handle_type { /// Method that returns true if the handle corresponds /// to the None handle. pub fn is_none(&self) -> bool { *self == $handle_type::None } } impl TryIntoNotNone for $handle_type { fn try_into_not_none(self) -> Result { if !self.is_none() { Ok(self.into()) } else { error!("Found invalid parameter {}::None", stringify!($handle_type)); Err(Error::local_error(ErrorKind::InvalidParam)) } } } }; } /// Module for the ObjectHandle pub mod object { use crate::tss2_esys::{ ESYS_TR_PASSWORD, ESYS_TR_RH_ENDORSEMENT, ESYS_TR_RH_LOCKOUT, ESYS_TR_RH_NULL, ESYS_TR_RH_OWNER, ESYS_TR_RH_PLATFORM, ESYS_TR_RH_PLATFORM_NV, }; impl_basic_handle!( /// The ObjectHandle is the general handle type /// and it wraps the ESYS_TR. /// /// All the other more specific handle types can be /// converted into an ObjectHandle. ObjectHandle ); // Add None handle add_constant_none_handle!(ObjectHandle); // Add all the other constant handles add_constant_handle!(ObjectHandle, Password, ESYS_TR_PASSWORD); add_constant_handle!(ObjectHandle, Owner, ESYS_TR_RH_OWNER); add_constant_handle!(ObjectHandle, Lockout, ESYS_TR_RH_LOCKOUT); add_constant_handle!(ObjectHandle, Endorsement, ESYS_TR_RH_ENDORSEMENT); add_constant_handle!(ObjectHandle, Platform, ESYS_TR_RH_PLATFORM); add_constant_handle!(ObjectHandle, PlatformNv, ESYS_TR_RH_PLATFORM_NV); add_constant_handle!(ObjectHandle, Null, ESYS_TR_RH_NULL); } /// Macro for creating ESYS_TR conversion for /// constant handle types macro_rules! impl_basic_multiple_constant_values_handle { ($constant_handle_type:ident) => { impl From<$constant_handle_type> for ESYS_TR { fn from(constant_handle: $constant_handle_type) -> ESYS_TR { // Cannot fail because each value is an ESYS_TR which is defined as u32. constant_handle.to_u32().unwrap() } } impl TryFrom for $constant_handle_type { type Error = Error; fn try_from(tss_esys_handle: ESYS_TR) -> Result<$constant_handle_type> { $constant_handle_type::from_u32(tss_esys_handle).ok_or_else(|| { error!( "failed to convert handle into {}", std::stringify!($constant_handle_type) ); Error::local_error(WrapperErrorKind::InvalidParam) }) } } }; } /// Macro for creating handle conversion /// from constant handle to a 'non-restricted' /// handle type macro_rules! impl_multiple_constant_values_handle_conversion { ($constant_handle_type:ident, $handle_type_other:ident) => { impl From<$constant_handle_type> for $handle_type_other { fn from(constant_handle: $constant_handle_type) -> $handle_type_other { // Cannot fail because each value is an ESYS_TR which is defined as u32. $handle_type_other::from(constant_handle.to_u32().unwrap()) } } impl TryFrom<$handle_type_other> for $constant_handle_type { type Error = Error; fn try_from(other_handle: $handle_type_other) -> Result<$constant_handle_type> { $constant_handle_type::from_u32(other_handle.value()).ok_or_else(|| { error!( "failed to convert handle into {}", std::stringify!($constant_handle_type) ); Error::local_error(WrapperErrorKind::InvalidParam) }) } } }; } /// PCR handle module /// /// The specification: /// "TCG TSS 2.0 Enhanced System API (ESAPI) Specification, Version 1.00, Revision 08, May 28, 2020" /// specifies preallocated identifiers for PCRs /// the PcrHandle is a wrapper for those handles. pub mod pcr { use super::object::ObjectHandle; use crate::{ tss2_esys::{ ESYS_TR, ESYS_TR_PCR0, ESYS_TR_PCR1, ESYS_TR_PCR10, ESYS_TR_PCR11, ESYS_TR_PCR12, ESYS_TR_PCR13, ESYS_TR_PCR14, ESYS_TR_PCR15, ESYS_TR_PCR16, ESYS_TR_PCR17, ESYS_TR_PCR18, ESYS_TR_PCR19, ESYS_TR_PCR2, ESYS_TR_PCR20, ESYS_TR_PCR21, ESYS_TR_PCR22, ESYS_TR_PCR23, ESYS_TR_PCR24, ESYS_TR_PCR25, ESYS_TR_PCR26, ESYS_TR_PCR27, ESYS_TR_PCR28, ESYS_TR_PCR29, ESYS_TR_PCR3, ESYS_TR_PCR30, ESYS_TR_PCR31, ESYS_TR_PCR4, ESYS_TR_PCR5, ESYS_TR_PCR6, ESYS_TR_PCR7, ESYS_TR_PCR8, ESYS_TR_PCR9, }, Error, Result, WrapperErrorKind, }; use log::error; use num_derive::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive}; use std::convert::{From, TryFrom}; /// PCR handle /// /// Handles to the pre-allocated /// PCR meta data objects. #[derive(FromPrimitive, ToPrimitive, Debug, Copy, Clone, PartialEq, Eq)] #[repr(u32)] pub enum PcrHandle { Pcr0 = ESYS_TR_PCR0, Pcr1 = ESYS_TR_PCR1, Pcr2 = ESYS_TR_PCR2, Pcr3 = ESYS_TR_PCR3, Pcr4 = ESYS_TR_PCR4, Pcr5 = ESYS_TR_PCR5, Pcr6 = ESYS_TR_PCR6, Pcr7 = ESYS_TR_PCR7, Pcr8 = ESYS_TR_PCR8, Pcr9 = ESYS_TR_PCR9, Pcr10 = ESYS_TR_PCR10, Pcr11 = ESYS_TR_PCR11, Pcr12 = ESYS_TR_PCR12, Pcr13 = ESYS_TR_PCR13, Pcr14 = ESYS_TR_PCR14, Pcr15 = ESYS_TR_PCR15, Pcr16 = ESYS_TR_PCR16, Pcr17 = ESYS_TR_PCR17, Pcr18 = ESYS_TR_PCR18, Pcr19 = ESYS_TR_PCR19, Pcr20 = ESYS_TR_PCR20, Pcr21 = ESYS_TR_PCR21, Pcr22 = ESYS_TR_PCR22, Pcr23 = ESYS_TR_PCR23, Pcr24 = ESYS_TR_PCR24, Pcr25 = ESYS_TR_PCR25, Pcr26 = ESYS_TR_PCR26, Pcr27 = ESYS_TR_PCR27, Pcr28 = ESYS_TR_PCR28, Pcr29 = ESYS_TR_PCR29, Pcr30 = ESYS_TR_PCR30, Pcr31 = ESYS_TR_PCR31, } impl_basic_multiple_constant_values_handle!(PcrHandle); impl_multiple_constant_values_handle_conversion!(PcrHandle, ObjectHandle); } /// Macro for implementing conversion between handles. macro_rules! impl_handle_conversion { ($handle_type_self:ident, $handle_type_other:ident) => { impl From<$handle_type_self> for $handle_type_other { fn from(handle_self: $handle_type_self) -> $handle_type_other { $handle_type_other::from(ESYS_TR::from(handle_self.value)) } } impl From<$handle_type_other> for $handle_type_self { fn from(handle_other: $handle_type_other) -> $handle_type_self { $handle_type_self { value: handle_other.value(), } } } }; } /// Auth handle module pub mod auth { use super::object::ObjectHandle; use crate::tss2_esys::{ ESYS_TR_RH_ENDORSEMENT, ESYS_TR_RH_LOCKOUT, ESYS_TR_RH_OWNER, ESYS_TR_RH_PLATFORM, }; impl_basic_handle!( /// Auth handle /// /// Represents an esys handle to resources /// that can be used for authentication. AuthHandle ); impl_handle_conversion!(AuthHandle, ObjectHandle); // The following constant handles can be used for authorization // according to the TCG TPM2 r1p59 Structures specification. add_constant_handle!(AuthHandle, Owner, ESYS_TR_RH_OWNER); add_constant_handle!(AuthHandle, Lockout, ESYS_TR_RH_LOCKOUT); add_constant_handle!(AuthHandle, Endorsement, ESYS_TR_RH_ENDORSEMENT); add_constant_handle!(AuthHandle, Platform, ESYS_TR_RH_PLATFORM); // TODO: Figure out how to add AUTH_00 to AUTH_FF range // TODO: Figure out how to add ACT_0 to ACT_F range } /// NV Index handle module pub mod nv_index { use super::auth::AuthHandle; use super::object::ObjectHandle; impl_basic_handle!( /// NV Index Handle /// /// Represents an esys resource handle /// for a nv index. NvIndexHandle ); impl_handle_conversion!(NvIndexHandle, ObjectHandle); impl_handle_conversion!(NvIndexHandle, AuthHandle); } /// Key handle module pub mod key { use super::object::ObjectHandle; use crate::tss2_esys::ESYS_TR_RH_NULL; impl_basic_handle!( /// Key Handle /// /// Represents an esys resource handle /// for a key. KeyHandle ); impl_handle_conversion!(KeyHandle, ObjectHandle); add_constant_handle!(KeyHandle, Null, ESYS_TR_RH_NULL); } /// Session handle module pub mod session { use super::auth::AuthHandle; use super::object::ObjectHandle; use crate::tss2_esys::ESYS_TR_PASSWORD; impl_basic_handle!( /// Session Handle /// /// Represents an esys handle used for /// referencing session resources. SessionHandle ); // TSS ESAPI v1p0_r08 specifies that both // PASSWORD and NONE can be used as session handles // NONE are used when session handle is optional. // Add the none handle add_constant_none_handle!(SessionHandle); // Add all other constant handles add_constant_handle!(SessionHandle, Password, ESYS_TR_PASSWORD); impl_handle_conversion!(SessionHandle, ObjectHandle); impl_handle_conversion!(SessionHandle, AuthHandle); } tss-esapi-7.4.0/src/handles/mod.rs000064400000000000000000000025031046102023000150760ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 /// Module that contains the different types of handles /// that the ESAPI and the TPM uses in order to provide /// access to objects that was or has been created. ///////////////////////////////////////////////////////// /// ESYS Handles ///////////////////////////////////////////////////////// pub use handle::auth::AuthHandle; pub use handle::key::KeyHandle; pub use handle::nv_index::NvIndexHandle; pub use handle::object::ObjectHandle; pub use handle::pcr::PcrHandle; pub use handle::session::SessionHandle; pub(crate) mod handle_conversion { pub(crate) use super::handle::conversions::*; } mod handle; ///////////////////////////////////////////////////////// /// TPM Handles ///////////////////////////////////////////////////////// pub use tpm::attached_component::AttachedComponentTpmHandle; pub use tpm::hmac_session::HmacSessionTpmHandle; pub use tpm::loaded_session::LoadedSessionTpmHandle; pub use tpm::nv_index::NvIndexTpmHandle; pub use tpm::pcr::PcrTpmHandle; pub use tpm::permanent::PermanentTpmHandle; pub use tpm::persistent::PersistentTpmHandle; pub use tpm::policy_session::PolicySessionTpmHandle; pub use tpm::saved_session::SavedSessionTpmHandle; pub use tpm::transient::TransientTpmHandle; pub use tpm::TpmHandle; mod tpm; tss-esapi-7.4.0/src/handles/tpm.rs000064400000000000000000000314241046102023000151230ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ constants::tss::{ TPM2_HT_AC, TPM2_HT_HMAC_SESSION, TPM2_HT_NV_INDEX, TPM2_HT_PCR, TPM2_HT_PERMANENT, TPM2_HT_PERSISTENT, TPM2_HT_POLICY_SESSION, TPM2_HT_TRANSIENT, }, tss2_esys::TPM2_HANDLE, Error, Result, WrapperErrorKind, }; use log::error; use std::convert::{From, TryFrom}; use std::stringify; /// Enum representing the different types of tpm handles /// of a TPM handle. /// /// * Details /// The TPM handles are used /// to reference shielded locations of various /// types within the TPM. /// /// * OBS /// Do not confuse the TpmHandles with the /// ESYS [ObjectHandle](crate::handles::ObjectHandle). #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum TpmHandle { Pcr(pcr::PcrTpmHandle), NvIndex(nv_index::NvIndexTpmHandle), HmacSession(hmac_session::HmacSessionTpmHandle), LoadedSession(loaded_session::LoadedSessionTpmHandle), PolicySession(policy_session::PolicySessionTpmHandle), SavedSession(saved_session::SavedSessionTpmHandle), Permanent(permanent::PermanentTpmHandle), Transient(transient::TransientTpmHandle), Persistent(persistent::PersistentTpmHandle), AttachedComponent(attached_component::AttachedComponentTpmHandle), } impl TpmHandle { /// Method that indicates if the flushing the /// context of the handle is a valid action. pub(crate) fn may_be_flushed(&self) -> bool { matches!( self, TpmHandle::HmacSession(_) | TpmHandle::LoadedSession(_) | TpmHandle::Transient(_) ) } } impl From for TPM2_HANDLE { fn from(tpm_handle: TpmHandle) -> TPM2_HANDLE { match tpm_handle { TpmHandle::Pcr(handle) => handle.into(), TpmHandle::NvIndex(handle) => handle.into(), TpmHandle::HmacSession(handle) => handle.into(), TpmHandle::LoadedSession(handle) => handle.into(), TpmHandle::PolicySession(handle) => handle.into(), TpmHandle::SavedSession(handle) => handle.into(), TpmHandle::Permanent(handle) => handle.into(), TpmHandle::Transient(handle) => handle.into(), TpmHandle::Persistent(handle) => handle.into(), TpmHandle::AttachedComponent(handle) => handle.into(), } } } impl TryFrom for TpmHandle { type Error = Error; fn try_from(tss_tpm_handle: TPM2_HANDLE) -> Result { let most_significant_byte = tss_tpm_handle.to_be_bytes()[0]; match most_significant_byte { TPM2_HT_PCR => Ok(TpmHandle::Pcr(pcr::PcrTpmHandle::new(tss_tpm_handle)?)), TPM2_HT_NV_INDEX => Ok(TpmHandle::NvIndex(nv_index::NvIndexTpmHandle::new( tss_tpm_handle, )?)), TPM2_HT_HMAC_SESSION => Ok(TpmHandle::HmacSession( hmac_session::HmacSessionTpmHandle::new(tss_tpm_handle)?, )), // HMAC and LOADED has the same type id TPM2_HT_POLICY_SESSION => Ok(TpmHandle::PolicySession( policy_session::PolicySessionTpmHandle::new(tss_tpm_handle)?, )), // POLICY and SAVED has the same type id. TPM2_HT_PERMANENT => Ok(TpmHandle::Permanent(permanent::PermanentTpmHandle::new( tss_tpm_handle, )?)), TPM2_HT_TRANSIENT => Ok(TpmHandle::Transient(transient::TransientTpmHandle::new( tss_tpm_handle, )?)), TPM2_HT_PERSISTENT => Ok(TpmHandle::Persistent(persistent::PersistentTpmHandle::new( tss_tpm_handle, )?)), TPM2_HT_AC => Ok(TpmHandle::AttachedComponent( attached_component::AttachedComponentTpmHandle::new(tss_tpm_handle)?, )), _ => { error!("Invalid TPM handle type {}", most_significant_byte); Err(Error::local_error(WrapperErrorKind::InvalidParam)) } } } } /// Macro for creating the specific TPM handle types macro_rules! create_tpm_handle_type { ($handle_type_name:ident, $tpm_handle_kind:path, $tpm_handle_type_id:tt, $tpm_handle_type_first:tt, $tpm_handle_type_last:tt) => { #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub struct $handle_type_name { value: u32, } impl $handle_type_name { pub fn new(value: u32) -> Result<$handle_type_name> { if value.to_be_bytes()[0] != $tpm_handle_type_id { error!( "TPM Handle ID of the input value did not match the {} (!={})", stringify!($handle_type_name), $tpm_handle_type_id ); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } // Add +1 to include tpm_handle_type_last in the range if !($tpm_handle_type_first..($tpm_handle_type_last + 1)).contains(&value) { error!( "TPM Handle ID is not in range ({}..{})", $tpm_handle_type_first, $tpm_handle_type_last ); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } Ok($handle_type_name { value }) } } impl From<$handle_type_name> for TpmHandle { fn from(specific_tpm_handle: $handle_type_name) -> TpmHandle { $tpm_handle_kind(specific_tpm_handle) } } impl TryFrom for $handle_type_name { type Error = Error; fn try_from(general_tpm_handle: TpmHandle) -> Result<$handle_type_name> { match general_tpm_handle { $tpm_handle_kind(val) => Ok(val), _ => { error!( "Error: Incorrect tpm handle kind(=={}) when converting to {}", stringify!($tpm_handle_kind), stringify!($handle_type_name) ); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } } } } impl From<$handle_type_name> for TPM2_HANDLE { fn from(specific_tpm_handle: $handle_type_name) -> TPM2_HANDLE { specific_tpm_handle.value } } impl TryFrom for $handle_type_name { type Error = Error; fn try_from(tss_tpm_handle: TPM2_HANDLE) -> Result<$handle_type_name> { $handle_type_name::new(tss_tpm_handle) } } }; } /// Macro for making a constant available /// for a TPM handle type. macro_rules! add_constant_handle { ($handle_type:ident, $constant_handle_name:ident, $constant_handle_value:ident) => { impl $handle_type { #[allow(non_upper_case_globals)] pub const $constant_handle_name: $handle_type = $handle_type { value: $constant_handle_value, }; } }; } pub mod pcr { //! Module for the PCR TPM handle. use super::*; use crate::constants::tss::{TPM2_HT_PCR, TPM2_PCR_FIRST, TPM2_PCR_LAST}; // Creates the specific handle types create_tpm_handle_type!( PcrTpmHandle, TpmHandle::Pcr, TPM2_HT_PCR, TPM2_PCR_FIRST, TPM2_PCR_LAST ); } pub mod nv_index { //! Module for the NV index TPM handle. use super::*; use crate::constants::tss::{TPM2_HT_NV_INDEX, TPM2_NV_INDEX_FIRST, TPM2_NV_INDEX_LAST}; create_tpm_handle_type!( NvIndexTpmHandle, TpmHandle::NvIndex, TPM2_HT_NV_INDEX, TPM2_NV_INDEX_FIRST, TPM2_NV_INDEX_LAST ); } pub mod hmac_session { //! Module for the HMAC session TPM handle. use super::*; use crate::constants::tss::{ TPM2_HMAC_SESSION_FIRST, TPM2_HMAC_SESSION_LAST, TPM2_HT_HMAC_SESSION, }; create_tpm_handle_type!( HmacSessionTpmHandle, TpmHandle::HmacSession, TPM2_HT_HMAC_SESSION, TPM2_HMAC_SESSION_FIRST, TPM2_HMAC_SESSION_LAST ); } pub mod loaded_session { //! Module for the loaded session TPM handle. use super::*; use crate::constants::tss::{ TPM2_HT_LOADED_SESSION, TPM2_LOADED_SESSION_FIRST, TPM2_LOADED_SESSION_LAST, }; create_tpm_handle_type!( LoadedSessionTpmHandle, TpmHandle::LoadedSession, TPM2_HT_LOADED_SESSION, TPM2_LOADED_SESSION_FIRST, TPM2_LOADED_SESSION_LAST ); } pub mod policy_session { //! Module for policy session TPM handles. use super::*; use crate::constants::tss::{ TPM2_HT_POLICY_SESSION, TPM2_POLICY_SESSION_FIRST, TPM2_POLICY_SESSION_LAST, }; create_tpm_handle_type!( PolicySessionTpmHandle, TpmHandle::PolicySession, TPM2_HT_POLICY_SESSION, TPM2_POLICY_SESSION_FIRST, TPM2_POLICY_SESSION_LAST ); } pub mod permanent { use super::*; use crate::constants::tss::{ TPM2_HT_PERMANENT, TPM2_PERMANENT_FIRST, TPM2_PERMANENT_LAST, TPM2_RH_ACT_0, TPM2_RH_ACT_F, TPM2_RH_ADMIN, TPM2_RH_AUTH_00, TPM2_RH_AUTH_FF, TPM2_RH_EK, TPM2_RH_ENDORSEMENT, TPM2_RH_FIRST, TPM2_RH_LAST, TPM2_RH_LOCKOUT, TPM2_RH_NULL, TPM2_RH_OPERATOR, TPM2_RH_OWNER, TPM2_RH_PLATFORM, TPM2_RH_PLATFORM_NV, TPM2_RH_REVOKE, TPM2_RH_SRK, TPM2_RH_TRANSPORT, TPM2_RH_UNASSIGNED, TPM2_RS_PW, }; create_tpm_handle_type!( PermanentTpmHandle, TpmHandle::Permanent, TPM2_HT_PERMANENT, TPM2_PERMANENT_FIRST, TPM2_PERMANENT_LAST ); add_constant_handle!(PermanentTpmHandle, First, TPM2_RH_FIRST); add_constant_handle!(PermanentTpmHandle, StorageRootKey, TPM2_RH_SRK); add_constant_handle!(PermanentTpmHandle, Owner, TPM2_RH_OWNER); add_constant_handle!(PermanentTpmHandle, Revoke, TPM2_RH_REVOKE); add_constant_handle!(PermanentTpmHandle, Transport, TPM2_RH_TRANSPORT); add_constant_handle!(PermanentTpmHandle, Operator, TPM2_RH_OPERATOR); add_constant_handle!(PermanentTpmHandle, Admin, TPM2_RH_ADMIN); add_constant_handle!(PermanentTpmHandle, EndorsementKey, TPM2_RH_EK); add_constant_handle!(PermanentTpmHandle, Null, TPM2_RH_NULL); add_constant_handle!(PermanentTpmHandle, Unassigned, TPM2_RH_UNASSIGNED); add_constant_handle!(PermanentTpmHandle, PasswordSession, TPM2_RS_PW); add_constant_handle!(PermanentTpmHandle, Lockout, TPM2_RH_LOCKOUT); add_constant_handle!(PermanentTpmHandle, Endorsement, TPM2_RH_ENDORSEMENT); add_constant_handle!(PermanentTpmHandle, Platform, TPM2_RH_PLATFORM); add_constant_handle!(PermanentTpmHandle, PlatformNv, TPM2_RH_PLATFORM_NV); add_constant_handle!( PermanentTpmHandle, VendorSpecificAuthorizationFirst, TPM2_RH_AUTH_00 ); add_constant_handle!( PermanentTpmHandle, VendorSpecificAuthorizationLast, TPM2_RH_AUTH_FF ); add_constant_handle!(PermanentTpmHandle, AuthenticatedTimersFirst, TPM2_RH_ACT_0); add_constant_handle!(PermanentTpmHandle, AuthenticatedTimersLast, TPM2_RH_ACT_F); add_constant_handle!(PermanentTpmHandle, Last, TPM2_RH_LAST); } pub mod saved_session { //! Module for saved session TPM handles use super::*; use crate::constants::tss::{ TPM2_HT_SAVED_SESSION, TPM2_POLICY_SESSION_FIRST, TPM2_POLICY_SESSION_LAST, }; create_tpm_handle_type!( SavedSessionTpmHandle, TpmHandle::SavedSession, TPM2_HT_SAVED_SESSION, TPM2_POLICY_SESSION_FIRST, // Policy session have the same type as saved session. TPM2_POLICY_SESSION_LAST // so assuming they have the same valid range makes sense. ); } pub mod transient { //! Module for transient TPM handles use super::*; use crate::constants::tss::{TPM2_HT_TRANSIENT, TPM2_TRANSIENT_FIRST, TPM2_TRANSIENT_LAST}; create_tpm_handle_type!( TransientTpmHandle, TpmHandle::Transient, TPM2_HT_TRANSIENT, TPM2_TRANSIENT_FIRST, TPM2_TRANSIENT_LAST ); } pub mod persistent { //! Module for persistent TPM handles use super::*; use crate::constants::tss::{TPM2_HT_PERSISTENT, TPM2_PERSISTENT_FIRST, TPM2_PERSISTENT_LAST}; create_tpm_handle_type!( PersistentTpmHandle, TpmHandle::Persistent, TPM2_HT_PERSISTENT, TPM2_PERSISTENT_FIRST, TPM2_PERSISTENT_LAST ); } pub mod attached_component { //! Module for attached component TPM handles. use super::*; use crate::constants::tss::{TPM2_AC_FIRST, TPM2_AC_LAST, TPM2_HT_AC}; create_tpm_handle_type!( AttachedComponentTpmHandle, TpmHandle::AttachedComponent, TPM2_HT_AC, TPM2_AC_FIRST, TPM2_AC_LAST ); } tss-esapi-7.4.0/src/interface_types/algorithm.rs000064400000000000000000000602051046102023000200560ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ constants::AlgorithmIdentifier, tss2_esys::{ TPMI_ALG_ASYM, TPMI_ALG_ECC_SCHEME, TPMI_ALG_HASH, TPMI_ALG_KDF, TPMI_ALG_KEYEDHASH_SCHEME, TPMI_ALG_PUBLIC, TPMI_ALG_RSA_DECRYPT, TPMI_ALG_RSA_SCHEME, TPMI_ALG_SIG_SCHEME, TPMI_ALG_SYM, TPMI_ALG_SYM_MODE, TPMI_ALG_SYM_OBJECT, }, Error, Result, WrapperErrorKind, }; use std::convert::TryFrom; /// Enum containing the supported hash algorithms /// /// # Details /// This corresponds to TPMI_ALG_HASH interface type. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum HashingAlgorithm { Sha1, Sha256, Sha384, Sha512, Sm3_256, Sha3_256, Sha3_384, Sha3_512, Null, } impl From for AlgorithmIdentifier { fn from(hashing_algorithm: HashingAlgorithm) -> Self { match hashing_algorithm { HashingAlgorithm::Sha1 => AlgorithmIdentifier::Sha1, HashingAlgorithm::Sha256 => AlgorithmIdentifier::Sha256, HashingAlgorithm::Sha384 => AlgorithmIdentifier::Sha384, HashingAlgorithm::Sha512 => AlgorithmIdentifier::Sha512, HashingAlgorithm::Sm3_256 => AlgorithmIdentifier::Sm3_256, HashingAlgorithm::Sha3_256 => AlgorithmIdentifier::Sha3_256, HashingAlgorithm::Sha3_384 => AlgorithmIdentifier::Sha3_384, HashingAlgorithm::Sha3_512 => AlgorithmIdentifier::Sha3_512, HashingAlgorithm::Null => AlgorithmIdentifier::Null, } } } impl TryFrom for HashingAlgorithm { type Error = Error; fn try_from(algorithm_identifier: AlgorithmIdentifier) -> Result { match algorithm_identifier { AlgorithmIdentifier::Sha1 => Ok(HashingAlgorithm::Sha1), AlgorithmIdentifier::Sha256 => Ok(HashingAlgorithm::Sha256), AlgorithmIdentifier::Sha384 => Ok(HashingAlgorithm::Sha384), AlgorithmIdentifier::Sha512 => Ok(HashingAlgorithm::Sha512), AlgorithmIdentifier::Sm3_256 => Ok(HashingAlgorithm::Sm3_256), AlgorithmIdentifier::Sha3_256 => Ok(HashingAlgorithm::Sha3_256), AlgorithmIdentifier::Sha3_384 => Ok(HashingAlgorithm::Sha3_384), AlgorithmIdentifier::Sha3_512 => Ok(HashingAlgorithm::Sha3_512), AlgorithmIdentifier::Null => Ok(HashingAlgorithm::Null), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } impl From for TPMI_ALG_HASH { fn from(hashing_algorithm: HashingAlgorithm) -> Self { AlgorithmIdentifier::from(hashing_algorithm).into() } } impl TryFrom for HashingAlgorithm { type Error = Error; fn try_from(tpmi_alg_hash: TPMI_ALG_HASH) -> Result { HashingAlgorithm::try_from(AlgorithmIdentifier::try_from(tpmi_alg_hash)?) } } /// Enum containing the supported keyed hash scheme /// /// # Details /// This corresponds to TPMI_ALG_KEYEDHASH_SCHEME interface type. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum KeyedHashSchemeAlgorithm { Hmac, Xor, Null, } impl From for AlgorithmIdentifier { fn from(keyed_hash_scheme: KeyedHashSchemeAlgorithm) -> Self { match keyed_hash_scheme { KeyedHashSchemeAlgorithm::Hmac => AlgorithmIdentifier::Hmac, KeyedHashSchemeAlgorithm::Xor => AlgorithmIdentifier::Xor, KeyedHashSchemeAlgorithm::Null => AlgorithmIdentifier::Null, } } } impl TryFrom for KeyedHashSchemeAlgorithm { type Error = Error; fn try_from(algorithm_identifier: AlgorithmIdentifier) -> Result { match algorithm_identifier { AlgorithmIdentifier::Hmac => Ok(KeyedHashSchemeAlgorithm::Hmac), AlgorithmIdentifier::Xor => Ok(KeyedHashSchemeAlgorithm::Xor), AlgorithmIdentifier::Null => Ok(KeyedHashSchemeAlgorithm::Null), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } impl From for TPMI_ALG_KEYEDHASH_SCHEME { fn from(keyed_hash_scheme: KeyedHashSchemeAlgorithm) -> Self { AlgorithmIdentifier::from(keyed_hash_scheme).into() } } impl TryFrom for KeyedHashSchemeAlgorithm { type Error = Error; fn try_from(tpmi_alg_keyed_hash_scheme: TPMI_ALG_KEYEDHASH_SCHEME) -> Result { KeyedHashSchemeAlgorithm::try_from(AlgorithmIdentifier::try_from( tpmi_alg_keyed_hash_scheme, )?) } } /// Enum containing key derivation functions interface type. /// /// # Details this corresponds to the TPMI_ALG_KDF #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum KeyDerivationFunction { Kdf1Sp800_56a, Kdf2, Kdf1Sp800_108, Mgf1, Null, } impl From for AlgorithmIdentifier { fn from(key_derivation_function: KeyDerivationFunction) -> Self { match key_derivation_function { KeyDerivationFunction::Kdf1Sp800_56a => AlgorithmIdentifier::Kdf1Sp800_56a, KeyDerivationFunction::Kdf2 => AlgorithmIdentifier::Kdf2, KeyDerivationFunction::Kdf1Sp800_108 => AlgorithmIdentifier::Kdf1Sp800_108, KeyDerivationFunction::Mgf1 => AlgorithmIdentifier::Mgf1, KeyDerivationFunction::Null => AlgorithmIdentifier::Null, } } } impl TryFrom for KeyDerivationFunction { type Error = Error; fn try_from(algorithm_identifier: AlgorithmIdentifier) -> Result { match algorithm_identifier { AlgorithmIdentifier::Kdf1Sp800_56a => Ok(KeyDerivationFunction::Kdf1Sp800_56a), AlgorithmIdentifier::Kdf2 => Ok(KeyDerivationFunction::Kdf2), AlgorithmIdentifier::Kdf1Sp800_108 => Ok(KeyDerivationFunction::Kdf1Sp800_108), AlgorithmIdentifier::Mgf1 => Ok(KeyDerivationFunction::Mgf1), AlgorithmIdentifier::Null => Ok(KeyDerivationFunction::Null), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } impl From for TPMI_ALG_KDF { fn from(key_derivation_function: KeyDerivationFunction) -> Self { AlgorithmIdentifier::from(key_derivation_function).into() } } impl TryFrom for KeyDerivationFunction { type Error = Error; fn try_from(tpmi_alg_kdf: TPMI_ALG_KDF) -> Result { KeyDerivationFunction::try_from(AlgorithmIdentifier::try_from(tpmi_alg_kdf)?) } } /// Enum representing the symmetric algorithm interface type. /// /// # Details /// This corresponds to TPMI_ALG_SYM. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum SymmetricAlgorithm { Tdes, Aes, Sm4, Camellia, Xor, Null, } impl From for AlgorithmIdentifier { fn from(symmetric_algorithm: SymmetricAlgorithm) -> Self { match symmetric_algorithm { SymmetricAlgorithm::Tdes => AlgorithmIdentifier::Tdes, SymmetricAlgorithm::Aes => AlgorithmIdentifier::Aes, SymmetricAlgorithm::Sm4 => AlgorithmIdentifier::Sm4, SymmetricAlgorithm::Camellia => AlgorithmIdentifier::Camellia, SymmetricAlgorithm::Xor => AlgorithmIdentifier::Xor, SymmetricAlgorithm::Null => AlgorithmIdentifier::Null, } } } impl TryFrom for SymmetricAlgorithm { type Error = Error; fn try_from(algorithm_identifier: AlgorithmIdentifier) -> Result { match algorithm_identifier { AlgorithmIdentifier::Tdes => Ok(SymmetricAlgorithm::Tdes), AlgorithmIdentifier::Aes => Ok(SymmetricAlgorithm::Aes), AlgorithmIdentifier::Sm4 => Ok(SymmetricAlgorithm::Sm4), AlgorithmIdentifier::Camellia => Ok(SymmetricAlgorithm::Camellia), AlgorithmIdentifier::Xor => Ok(SymmetricAlgorithm::Xor), AlgorithmIdentifier::Null => Ok(SymmetricAlgorithm::Null), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } impl From for TPMI_ALG_SYM { fn from(symmetric_algorithm: SymmetricAlgorithm) -> Self { AlgorithmIdentifier::from(symmetric_algorithm).into() } } impl TryFrom for SymmetricAlgorithm { type Error = Error; fn try_from(tpmi_alg_sym: TPMI_ALG_SYM) -> Result { SymmetricAlgorithm::try_from(AlgorithmIdentifier::try_from(tpmi_alg_sym)?) } } /// Enum representing the symmetric mode interface type. /// /// # Details /// Corresponds to TPMI_ALG_SYM_MODE. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum SymmetricMode { Ctr, Ofb, Cbc, Cfb, Ecb, Null, } impl From for AlgorithmIdentifier { fn from(symmetric_mode: SymmetricMode) -> Self { match symmetric_mode { SymmetricMode::Ctr => AlgorithmIdentifier::Ctr, SymmetricMode::Ofb => AlgorithmIdentifier::Ofb, SymmetricMode::Cbc => AlgorithmIdentifier::Cbc, SymmetricMode::Cfb => AlgorithmIdentifier::Cfb, SymmetricMode::Ecb => AlgorithmIdentifier::Ecb, SymmetricMode::Null => AlgorithmIdentifier::Null, } } } impl TryFrom for SymmetricMode { type Error = Error; fn try_from(algorithm_identifier: AlgorithmIdentifier) -> Result { match algorithm_identifier { AlgorithmIdentifier::Ctr => Ok(SymmetricMode::Ctr), AlgorithmIdentifier::Ofb => Ok(SymmetricMode::Ofb), AlgorithmIdentifier::Cbc => Ok(SymmetricMode::Cbc), AlgorithmIdentifier::Cfb => Ok(SymmetricMode::Cfb), AlgorithmIdentifier::Ecb => Ok(SymmetricMode::Ecb), AlgorithmIdentifier::Null => Ok(SymmetricMode::Null), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } impl From for TPMI_ALG_SYM_MODE { fn from(symmetric_mode: SymmetricMode) -> Self { AlgorithmIdentifier::from(symmetric_mode).into() } } impl TryFrom for SymmetricMode { type Error = Error; fn try_from(tpmi_alg_sym_mode: TPMI_ALG_SYM_MODE) -> Result { SymmetricMode::try_from(AlgorithmIdentifier::try_from(tpmi_alg_sym_mode)?) } } /// Enum representing the asymmetric algorithm interface type. /// /// # Details /// This corresponds to TPMI_ALG_ASYM #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum AsymmetricAlgorithm { Rsa, Ecc, Null, } impl From for AlgorithmIdentifier { fn from(asymmetric_algorithm: AsymmetricAlgorithm) -> Self { match asymmetric_algorithm { AsymmetricAlgorithm::Rsa => AlgorithmIdentifier::Rsa, AsymmetricAlgorithm::Ecc => AlgorithmIdentifier::Ecc, AsymmetricAlgorithm::Null => AlgorithmIdentifier::Null, } } } impl TryFrom for AsymmetricAlgorithm { type Error = Error; fn try_from(algorithm_identifier: AlgorithmIdentifier) -> Result { match algorithm_identifier { AlgorithmIdentifier::Rsa => Ok(AsymmetricAlgorithm::Rsa), AlgorithmIdentifier::Ecc => Ok(AsymmetricAlgorithm::Ecc), AlgorithmIdentifier::Null => Ok(AsymmetricAlgorithm::Null), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } impl From for TPMI_ALG_ASYM { fn from(asymmetric_algorithm: AsymmetricAlgorithm) -> Self { AlgorithmIdentifier::from(asymmetric_algorithm).into() } } impl TryFrom for AsymmetricAlgorithm { type Error = Error; fn try_from(tpmi_alg_sym: TPMI_ALG_ASYM) -> Result { AsymmetricAlgorithm::try_from(AlgorithmIdentifier::try_from(tpmi_alg_sym)?) } } /// Enum representing the signature scheme interface type. /// /// # Details /// This corresponds to TPMI_ALG_SIG_SCHEME #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum SignatureSchemeAlgorithm { RsaSsa, RsaPss, EcDsa, EcDaa, Sm2, EcSchnorr, Hmac, Null, } impl From for AlgorithmIdentifier { fn from(signature_scheme_algorithm: SignatureSchemeAlgorithm) -> Self { match signature_scheme_algorithm { SignatureSchemeAlgorithm::RsaSsa => AlgorithmIdentifier::RsaSsa, SignatureSchemeAlgorithm::RsaPss => AlgorithmIdentifier::RsaPss, SignatureSchemeAlgorithm::EcDsa => AlgorithmIdentifier::EcDsa, SignatureSchemeAlgorithm::EcDaa => AlgorithmIdentifier::EcDaa, SignatureSchemeAlgorithm::Sm2 => AlgorithmIdentifier::Sm2, SignatureSchemeAlgorithm::EcSchnorr => AlgorithmIdentifier::EcSchnorr, SignatureSchemeAlgorithm::Hmac => AlgorithmIdentifier::Hmac, SignatureSchemeAlgorithm::Null => AlgorithmIdentifier::Null, } } } impl TryFrom for SignatureSchemeAlgorithm { type Error = Error; fn try_from(algorithm_identifier: AlgorithmIdentifier) -> Result { match algorithm_identifier { AlgorithmIdentifier::RsaSsa => Ok(SignatureSchemeAlgorithm::RsaSsa), AlgorithmIdentifier::RsaPss => Ok(SignatureSchemeAlgorithm::RsaPss), AlgorithmIdentifier::EcDsa => Ok(SignatureSchemeAlgorithm::EcDsa), AlgorithmIdentifier::EcDaa => Ok(SignatureSchemeAlgorithm::EcDaa), AlgorithmIdentifier::Sm2 => Ok(SignatureSchemeAlgorithm::Sm2), AlgorithmIdentifier::EcSchnorr => Ok(SignatureSchemeAlgorithm::EcSchnorr), AlgorithmIdentifier::Hmac => Ok(SignatureSchemeAlgorithm::Hmac), AlgorithmIdentifier::Null => Ok(SignatureSchemeAlgorithm::Null), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } impl From for TPMI_ALG_SIG_SCHEME { fn from(signature_scheme_algorithm: SignatureSchemeAlgorithm) -> Self { AlgorithmIdentifier::from(signature_scheme_algorithm).into() } } impl TryFrom for SignatureSchemeAlgorithm { type Error = Error; fn try_from(tpmi_alg_sym_scheme: TPMI_ALG_SIG_SCHEME) -> Result { SignatureSchemeAlgorithm::try_from(AlgorithmIdentifier::try_from(tpmi_alg_sym_scheme)?) } } // A convenience conversion into AsymmetricAlgorithm // that is associated with the signature scheme. impl TryFrom for AsymmetricAlgorithm { type Error = Error; fn try_from(signature_scheme: SignatureSchemeAlgorithm) -> Result { match signature_scheme { SignatureSchemeAlgorithm::RsaSsa => Ok(AsymmetricAlgorithm::Rsa), SignatureSchemeAlgorithm::RsaPss => Ok(AsymmetricAlgorithm::Rsa), SignatureSchemeAlgorithm::EcDsa => Ok(AsymmetricAlgorithm::Ecc), SignatureSchemeAlgorithm::EcDaa => Ok(AsymmetricAlgorithm::Ecc), SignatureSchemeAlgorithm::Sm2 => Ok(AsymmetricAlgorithm::Ecc), SignatureSchemeAlgorithm::EcSchnorr => Ok(AsymmetricAlgorithm::Ecc), _ => { // HMAC is for symmetric algorithms // // Null could be converted into AsymmetricAlgorithm::Null // but I do not know if that is useful. Err(Error::local_error(WrapperErrorKind::InvalidParam)) } } } } /// Enum repsenting the symmetric object inetrface type. /// /// # Details /// This corresponds to TPMI_ALG_SYM_OBJECT #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum SymmetricObject { Tdes, Aes, Sm4, Camellia, Null, } impl From for AlgorithmIdentifier { fn from(symmetric_object: SymmetricObject) -> Self { match symmetric_object { SymmetricObject::Tdes => AlgorithmIdentifier::Tdes, SymmetricObject::Aes => AlgorithmIdentifier::Aes, SymmetricObject::Sm4 => AlgorithmIdentifier::Sm4, SymmetricObject::Camellia => AlgorithmIdentifier::Camellia, SymmetricObject::Null => AlgorithmIdentifier::Null, } } } impl TryFrom for SymmetricObject { type Error = Error; fn try_from(algorithm_identifier: AlgorithmIdentifier) -> Result { match algorithm_identifier { AlgorithmIdentifier::Tdes => Ok(SymmetricObject::Tdes), AlgorithmIdentifier::Aes => Ok(SymmetricObject::Aes), AlgorithmIdentifier::Sm4 => Ok(SymmetricObject::Sm4), AlgorithmIdentifier::Camellia => Ok(SymmetricObject::Camellia), AlgorithmIdentifier::Null => Ok(SymmetricObject::Null), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } impl From for TPMI_ALG_SYM_OBJECT { fn from(symmetric_object: SymmetricObject) -> Self { AlgorithmIdentifier::from(symmetric_object).into() } } impl TryFrom for SymmetricObject { type Error = Error; fn try_from(tpmi_alg_sym_object: TPMI_ALG_SYM_OBJECT) -> Result { SymmetricObject::try_from(AlgorithmIdentifier::try_from(tpmi_alg_sym_object)?) } } /// Enum repsenting the public interface type /// /// # Details /// This corresponds to TPMI_ALG_PUBLIC #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum PublicAlgorithm { Rsa, KeyedHash, Ecc, SymCipher, } impl From for AlgorithmIdentifier { fn from(public_algorithm: PublicAlgorithm) -> Self { match public_algorithm { PublicAlgorithm::Rsa => AlgorithmIdentifier::Rsa, PublicAlgorithm::KeyedHash => AlgorithmIdentifier::KeyedHash, PublicAlgorithm::Ecc => AlgorithmIdentifier::Ecc, PublicAlgorithm::SymCipher => AlgorithmIdentifier::SymCipher, } } } impl TryFrom for PublicAlgorithm { type Error = Error; fn try_from(algorithm_identifier: AlgorithmIdentifier) -> Result { match algorithm_identifier { AlgorithmIdentifier::Rsa => Ok(PublicAlgorithm::Rsa), AlgorithmIdentifier::KeyedHash => Ok(PublicAlgorithm::KeyedHash), AlgorithmIdentifier::Ecc => Ok(PublicAlgorithm::Ecc), AlgorithmIdentifier::SymCipher => Ok(PublicAlgorithm::SymCipher), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } impl From for TPMI_ALG_PUBLIC { fn from(public_algorithm: PublicAlgorithm) -> Self { AlgorithmIdentifier::from(public_algorithm).into() } } impl TryFrom for PublicAlgorithm { type Error = Error; fn try_from(tpmi_alg_public: TPMI_ALG_PUBLIC) -> Result { PublicAlgorithm::try_from(AlgorithmIdentifier::try_from(tpmi_alg_public)?) } } /// Enum repsenting the rsa scheme interface type /// /// # Details /// This corresponds to TPMI_ALG_RSA_SCHEME #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum RsaSchemeAlgorithm { RsaSsa, RsaEs, RsaPss, Oaep, Null, } impl From for AlgorithmIdentifier { fn from(rsa_scheme_algorithm: RsaSchemeAlgorithm) -> Self { match rsa_scheme_algorithm { RsaSchemeAlgorithm::RsaSsa => AlgorithmIdentifier::RsaSsa, RsaSchemeAlgorithm::RsaEs => AlgorithmIdentifier::RsaEs, RsaSchemeAlgorithm::RsaPss => AlgorithmIdentifier::RsaPss, RsaSchemeAlgorithm::Oaep => AlgorithmIdentifier::Oaep, RsaSchemeAlgorithm::Null => AlgorithmIdentifier::Null, } } } impl TryFrom for RsaSchemeAlgorithm { type Error = Error; fn try_from(algorithm_identifier: AlgorithmIdentifier) -> Result { match algorithm_identifier { AlgorithmIdentifier::RsaSsa => Ok(RsaSchemeAlgorithm::RsaSsa), AlgorithmIdentifier::RsaEs => Ok(RsaSchemeAlgorithm::RsaEs), AlgorithmIdentifier::RsaPss => Ok(RsaSchemeAlgorithm::RsaPss), AlgorithmIdentifier::Oaep => Ok(RsaSchemeAlgorithm::Oaep), AlgorithmIdentifier::Null => Ok(RsaSchemeAlgorithm::Null), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } impl From for TPMI_ALG_RSA_SCHEME { fn from(rsa_scheme_algorithm: RsaSchemeAlgorithm) -> Self { AlgorithmIdentifier::from(rsa_scheme_algorithm).into() } } impl TryFrom for RsaSchemeAlgorithm { type Error = Error; fn try_from(tpmi_alg_rsa_scheme: TPMI_ALG_RSA_SCHEME) -> Result { RsaSchemeAlgorithm::try_from(AlgorithmIdentifier::try_from(tpmi_alg_rsa_scheme)?) } } /// Enum repsenting the rsa scheme interface type /// /// # Details /// This corresponds to TPMI_ALG_ECC_SCHEME #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum EccSchemeAlgorithm { EcDsa, EcDh, EcDaa, Sm2, EcSchnorr, EcMqv, Null, } impl From for AlgorithmIdentifier { fn from(ecc_scheme_algorithm: EccSchemeAlgorithm) -> Self { match ecc_scheme_algorithm { EccSchemeAlgorithm::EcDsa => AlgorithmIdentifier::EcDsa, EccSchemeAlgorithm::EcDh => AlgorithmIdentifier::EcDh, EccSchemeAlgorithm::EcDaa => AlgorithmIdentifier::EcDaa, EccSchemeAlgorithm::Sm2 => AlgorithmIdentifier::Sm2, EccSchemeAlgorithm::EcSchnorr => AlgorithmIdentifier::EcSchnorr, EccSchemeAlgorithm::EcMqv => AlgorithmIdentifier::EcMqv, EccSchemeAlgorithm::Null => AlgorithmIdentifier::Null, } } } impl TryFrom for EccSchemeAlgorithm { type Error = Error; fn try_from(algorithm_identifier: AlgorithmIdentifier) -> Result { match algorithm_identifier { AlgorithmIdentifier::EcDsa => Ok(EccSchemeAlgorithm::EcDsa), AlgorithmIdentifier::EcDh => Ok(EccSchemeAlgorithm::EcDh), AlgorithmIdentifier::EcDaa => Ok(EccSchemeAlgorithm::EcDaa), AlgorithmIdentifier::Sm2 => Ok(EccSchemeAlgorithm::Sm2), AlgorithmIdentifier::EcSchnorr => Ok(EccSchemeAlgorithm::EcSchnorr), AlgorithmIdentifier::EcMqv => Ok(EccSchemeAlgorithm::EcMqv), AlgorithmIdentifier::Null => Ok(EccSchemeAlgorithm::Null), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } impl From for TPMI_ALG_ECC_SCHEME { fn from(ecc_scheme_algorithm: EccSchemeAlgorithm) -> Self { AlgorithmIdentifier::from(ecc_scheme_algorithm).into() } } impl TryFrom for EccSchemeAlgorithm { type Error = Error; fn try_from(tpmi_alg_ecc_scheme: TPMI_ALG_ECC_SCHEME) -> Result { EccSchemeAlgorithm::try_from(AlgorithmIdentifier::try_from(tpmi_alg_ecc_scheme)?) } } /// Enum repsenting the rsa decryption interface type /// /// # Details /// This corresponds to TPMI_ALG_RSA_DECRYPT #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum RsaDecryptAlgorithm { RsaEs, Oaep, Null, } impl From for AlgorithmIdentifier { fn from(rsa_decrypt_algorithm: RsaDecryptAlgorithm) -> Self { match rsa_decrypt_algorithm { RsaDecryptAlgorithm::RsaEs => AlgorithmIdentifier::RsaEs, RsaDecryptAlgorithm::Oaep => AlgorithmIdentifier::Oaep, RsaDecryptAlgorithm::Null => AlgorithmIdentifier::Null, } } } impl TryFrom for RsaDecryptAlgorithm { type Error = Error; fn try_from(algorithm_identifier: AlgorithmIdentifier) -> Result { match algorithm_identifier { AlgorithmIdentifier::RsaEs => Ok(RsaDecryptAlgorithm::RsaEs), AlgorithmIdentifier::Oaep => Ok(RsaDecryptAlgorithm::Oaep), AlgorithmIdentifier::Null => Ok(RsaDecryptAlgorithm::Null), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } impl From for TPMI_ALG_RSA_DECRYPT { fn from(rsa_decrypt_algorithm: RsaDecryptAlgorithm) -> Self { AlgorithmIdentifier::from(rsa_decrypt_algorithm).into() } } impl TryFrom for RsaDecryptAlgorithm { type Error = Error; fn try_from(tpmi_alg_rsa_decrypt: TPMI_ALG_RSA_DECRYPT) -> Result { RsaDecryptAlgorithm::try_from(AlgorithmIdentifier::try_from(tpmi_alg_rsa_decrypt)?) } } tss-esapi-7.4.0/src/interface_types/dynamic_handles.rs000064400000000000000000000026441046102023000212150ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::handles::{NvIndexTpmHandle, PcrTpmHandle, PersistentTpmHandle, TransientTpmHandle}; /// Can be created with either a persistent /// or transient TPM handle. #[derive(Debug, Copy, Clone)] pub enum Object { Transient(TransientTpmHandle), Persistent(PersistentTpmHandle), } #[derive(Debug, Copy, Clone)] pub enum Parent { Transient(TransientTpmHandle), Persistent(PersistentTpmHandle), Owner, Platform, Endorsement, } /// /// Enum representing the Persistent DH interface type /// (TPMI_DH_PERSISTENT) /// #[derive(Debug, Copy, Clone)] pub enum Persistent { Persistent(PersistentTpmHandle), } impl From for PersistentTpmHandle { fn from(persistent: Persistent) -> PersistentTpmHandle { match persistent { Persistent::Persistent(val) => val, } } } impl From for Persistent { fn from(persistent_tpm_handle: PersistentTpmHandle) -> Persistent { Persistent::Persistent(persistent_tpm_handle) } } #[derive(Debug, Copy, Clone)] pub enum Entity { Transient(TransientTpmHandle), Persistent(PersistentTpmHandle), Pcr(PcrTpmHandle), NvIndex(NvIndexTpmHandle), Owner, Platform, Endorsement, Lockout, // TODO: Handle Auth } #[derive(Debug, Copy, Clone)] pub enum Pcr { Pcr(PcrTpmHandle), } tss-esapi-7.4.0/src/interface_types/ecc.rs000064400000000000000000000041631046102023000166230ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{constants::EccCurveIdentifier, tss2_esys::TPMI_ECC_CURVE, Error, Result}; use std::convert::TryFrom; /// Enum containing the implemented ECC curves /// /// # Details /// This corresponds to TPMI_ECC_CURVE #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum EccCurve { NistP192, NistP224, NistP256, NistP384, NistP521, BnP256, BnP638, Sm2P256, } impl From for EccCurveIdentifier { fn from(ecc_curve: EccCurve) -> Self { match ecc_curve { EccCurve::NistP192 => EccCurveIdentifier::NistP192, EccCurve::NistP224 => EccCurveIdentifier::NistP224, EccCurve::NistP256 => EccCurveIdentifier::NistP256, EccCurve::NistP384 => EccCurveIdentifier::NistP384, EccCurve::NistP521 => EccCurveIdentifier::NistP521, EccCurve::BnP256 => EccCurveIdentifier::BnP256, EccCurve::BnP638 => EccCurveIdentifier::BnP638, EccCurve::Sm2P256 => EccCurveIdentifier::Sm2P256, } } } impl From for EccCurve { fn from(ecc_curve_identifier: EccCurveIdentifier) -> Self { match ecc_curve_identifier { EccCurveIdentifier::NistP192 => EccCurve::NistP192, EccCurveIdentifier::NistP224 => EccCurve::NistP224, EccCurveIdentifier::NistP256 => EccCurve::NistP256, EccCurveIdentifier::NistP384 => EccCurve::NistP384, EccCurveIdentifier::NistP521 => EccCurve::NistP521, EccCurveIdentifier::BnP256 => EccCurve::BnP256, EccCurveIdentifier::BnP638 => EccCurve::BnP638, EccCurveIdentifier::Sm2P256 => EccCurve::Sm2P256, } } } impl From for TPMI_ECC_CURVE { fn from(curve: EccCurve) -> Self { EccCurveIdentifier::from(curve).into() } } impl TryFrom for EccCurve { type Error = Error; fn try_from(tpmi_ecc_curve: TPMI_ECC_CURVE) -> Result { Ok(EccCurve::from(EccCurveIdentifier::try_from( tpmi_ecc_curve, )?)) } } tss-esapi-7.4.0/src/interface_types/key_bits.rs000064400000000000000000000100741046102023000177000ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ tss2_esys::{TPM2_KEY_BITS, TPMI_AES_KEY_BITS, TPMI_RSA_KEY_BITS, TPMI_SM4_KEY_BITS}, Error, Result, WrapperErrorKind, }; use std::convert::TryFrom; /// AES key bits interface type /// /// # Details /// This corresponds to TPMI_AES_KEY_BITS #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum AesKeyBits { Aes128, Aes192, Aes256, } impl From for TPMI_AES_KEY_BITS { fn from(aes_key_bits: AesKeyBits) -> TPMI_AES_KEY_BITS { match aes_key_bits { AesKeyBits::Aes128 => 128, AesKeyBits::Aes192 => 192, AesKeyBits::Aes256 => 256, } } } impl TryFrom for AesKeyBits { type Error = Error; fn try_from(tpmi_aes_key_bits: TPMI_AES_KEY_BITS) -> Result { match tpmi_aes_key_bits { 128 => Ok(AesKeyBits::Aes128), 192 => Ok(AesKeyBits::Aes192), 256 => Ok(AesKeyBits::Aes256), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } /// SM4 key bits interface type /// /// # Details /// This corresponds to TPMI_SM4_KEY_BITS #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum Sm4KeyBits { Sm4_128, } impl From for TPMI_SM4_KEY_BITS { fn from(sm4_key_bits: Sm4KeyBits) -> TPMI_SM4_KEY_BITS { match sm4_key_bits { Sm4KeyBits::Sm4_128 => 128, } } } impl TryFrom for Sm4KeyBits { type Error = Error; fn try_from(tpmi_sm4_key_bits: TPMI_SM4_KEY_BITS) -> Result { match tpmi_sm4_key_bits { 128 => Ok(Sm4KeyBits::Sm4_128), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } /// Camellia key bits interface type /// /// # Details /// This corresponds to TPMI_CAMELLIA_KEY_BITS // This should convert to and from TPMI_CAMELLIA_KEY_BITS // but in version 2.3.X version of tpm2-tss // lib this type had the wrong name so instead // it converts to and from TPM2_KEY_BITS. // This is an acceptable compromise because // the interface type defined as // pub type TPMI_CAMELLIA_KEY_BITS = TPM2_KEY_BITS #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum CamelliaKeyBits { Camellia128, Camellia192, Camellia256, } impl From for TPM2_KEY_BITS { fn from(camellia_key_bits: CamelliaKeyBits) -> TPM2_KEY_BITS { match camellia_key_bits { CamelliaKeyBits::Camellia128 => 128, CamelliaKeyBits::Camellia192 => 192, CamelliaKeyBits::Camellia256 => 256, } } } impl TryFrom for CamelliaKeyBits { type Error = Error; fn try_from(tpmi_camellia_key_bits: TPM2_KEY_BITS) -> Result { match tpmi_camellia_key_bits { 128 => Ok(CamelliaKeyBits::Camellia128), 192 => Ok(CamelliaKeyBits::Camellia192), 256 => Ok(CamelliaKeyBits::Camellia256), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } /// RSA key bits interface type /// /// # Details /// This corresponds to TPMI_RSA_KEY_BITS #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum RsaKeyBits { Rsa1024, Rsa2048, Rsa3072, Rsa4096, } impl From for TPMI_RSA_KEY_BITS { fn from(rsa_key_bits: RsaKeyBits) -> TPMI_RSA_KEY_BITS { match rsa_key_bits { RsaKeyBits::Rsa1024 => 1024, RsaKeyBits::Rsa2048 => 2048, RsaKeyBits::Rsa3072 => 3072, RsaKeyBits::Rsa4096 => 4096, } } } impl TryFrom for RsaKeyBits { type Error = Error; fn try_from(tpmi_rsa_key_bits: TPMI_RSA_KEY_BITS) -> Result { match tpmi_rsa_key_bits { 1024 => Ok(RsaKeyBits::Rsa1024), 2048 => Ok(RsaKeyBits::Rsa2048), 3072 => Ok(RsaKeyBits::Rsa3072), 4096 => Ok(RsaKeyBits::Rsa4096), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } tss-esapi-7.4.0/src/interface_types/mod.rs000064400000000000000000000005721046102023000166500ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! This module contains the different interface types defined in //! the TPM 2.0 specification. mod yes_no; pub mod algorithm; pub mod dynamic_handles; pub mod ecc; pub mod key_bits; pub mod resource_handles; pub mod session_handles; pub mod structure_tags; pub use yes_no::YesNo; tss-esapi-7.4.0/src/interface_types/resource_handles.rs000064400000000000000000000362601046102023000214210ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ handles::{ AttachedComponentTpmHandle, AuthHandle, NvIndexHandle, NvIndexTpmHandle, ObjectHandle, PermanentTpmHandle, TpmHandle, }, Error, Result, WrapperErrorKind, }; use std::convert::TryFrom; ////////////////////////////////////////////////////////////////////////////////// /// Hierarchy /// /// Enum describing the object hierarchies in a TPM 2.0. ////////////////////////////////////////////////////////////////////////////////// #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Hierarchy { Owner, Platform, Endorsement, Null, } impl From for ObjectHandle { fn from(hierarchy: Hierarchy) -> ObjectHandle { match hierarchy { Hierarchy::Owner => ObjectHandle::Owner, Hierarchy::Platform => ObjectHandle::Platform, Hierarchy::Endorsement => ObjectHandle::Endorsement, Hierarchy::Null => ObjectHandle::Null, } } } impl From for TpmHandle { fn from(hierarchy: Hierarchy) -> TpmHandle { match hierarchy { Hierarchy::Owner => TpmHandle::Permanent(PermanentTpmHandle::Owner), Hierarchy::Platform => TpmHandle::Permanent(PermanentTpmHandle::Platform), Hierarchy::Endorsement => TpmHandle::Permanent(PermanentTpmHandle::Endorsement), Hierarchy::Null => TpmHandle::Permanent(PermanentTpmHandle::Null), } } } impl TryFrom for Hierarchy { type Error = Error; fn try_from(object_handle: ObjectHandle) -> Result { match object_handle { ObjectHandle::Owner => Ok(Hierarchy::Owner), ObjectHandle::Platform => Ok(Hierarchy::Platform), ObjectHandle::Endorsement => Ok(Hierarchy::Endorsement), ObjectHandle::Null => Ok(Hierarchy::Null), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } impl TryFrom for Hierarchy { type Error = Error; fn try_from(tpm_handle: TpmHandle) -> Result { match tpm_handle { TpmHandle::Permanent(permanent_handle) => match permanent_handle { PermanentTpmHandle::Owner => Ok(Hierarchy::Owner), PermanentTpmHandle::Platform => Ok(Hierarchy::Platform), PermanentTpmHandle::Endorsement => Ok(Hierarchy::Endorsement), PermanentTpmHandle::Null => Ok(Hierarchy::Null), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), }, _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } ////////////////////////////////////////////////////////////////////////////////// /// Enables ////////////////////////////////////////////////////////////////////////////////// #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Enables { Owner, Platform, Endorsement, PlatformNv, Null, } impl From for ObjectHandle { fn from(enables: Enables) -> ObjectHandle { match enables { Enables::Owner => ObjectHandle::Owner, Enables::Platform => ObjectHandle::Platform, Enables::Endorsement => ObjectHandle::Endorsement, Enables::PlatformNv => ObjectHandle::PlatformNv, Enables::Null => ObjectHandle::Null, } } } impl From for TpmHandle { fn from(enables: Enables) -> TpmHandle { match enables { Enables::Owner => TpmHandle::Permanent(PermanentTpmHandle::Owner), Enables::Platform => TpmHandle::Permanent(PermanentTpmHandle::Platform), Enables::Endorsement => TpmHandle::Permanent(PermanentTpmHandle::Endorsement), Enables::PlatformNv => TpmHandle::Permanent(PermanentTpmHandle::PlatformNv), Enables::Null => TpmHandle::Permanent(PermanentTpmHandle::Null), } } } impl TryFrom for Enables { type Error = Error; fn try_from(object_handle: ObjectHandle) -> Result { match object_handle { ObjectHandle::Owner => Ok(Enables::Owner), ObjectHandle::Platform => Ok(Enables::Platform), ObjectHandle::Endorsement => Ok(Enables::Endorsement), ObjectHandle::PlatformNv => Ok(Enables::PlatformNv), ObjectHandle::Null => Ok(Enables::Null), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } impl TryFrom for Enables { type Error = Error; fn try_from(tpm_handle: TpmHandle) -> Result { match tpm_handle { TpmHandle::Permanent(permanent_handle) => match permanent_handle { PermanentTpmHandle::Owner => Ok(Enables::Owner), PermanentTpmHandle::Platform => Ok(Enables::Platform), PermanentTpmHandle::Endorsement => Ok(Enables::Endorsement), PermanentTpmHandle::PlatformNv => Ok(Enables::PlatformNv), PermanentTpmHandle::Null => Ok(Enables::Null), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), }, _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } ////////////////////////////////////////////////////////////////////////////////// /// HierarchyAuth ////////////////////////////////////////////////////////////////////////////////// #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum HierarchyAuth { Owner, Platform, Endorsement, Lockout, } impl From for ObjectHandle { fn from(hierarchy_auth: HierarchyAuth) -> ObjectHandle { match hierarchy_auth { HierarchyAuth::Owner => ObjectHandle::Owner, HierarchyAuth::Platform => ObjectHandle::Platform, HierarchyAuth::Endorsement => ObjectHandle::Endorsement, HierarchyAuth::Lockout => ObjectHandle::Lockout, } } } impl From for TpmHandle { fn from(hierarchy_auth: HierarchyAuth) -> TpmHandle { match hierarchy_auth { HierarchyAuth::Owner => TpmHandle::Permanent(PermanentTpmHandle::Owner), HierarchyAuth::Platform => TpmHandle::Permanent(PermanentTpmHandle::Platform), HierarchyAuth::Endorsement => TpmHandle::Permanent(PermanentTpmHandle::Endorsement), HierarchyAuth::Lockout => TpmHandle::Permanent(PermanentTpmHandle::Lockout), } } } impl TryFrom for HierarchyAuth { type Error = Error; fn try_from(object_handle: ObjectHandle) -> Result { match object_handle { ObjectHandle::Owner => Ok(HierarchyAuth::Owner), ObjectHandle::Platform => Ok(HierarchyAuth::Platform), ObjectHandle::Endorsement => Ok(HierarchyAuth::Endorsement), ObjectHandle::Lockout => Ok(HierarchyAuth::Lockout), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } impl TryFrom for HierarchyAuth { type Error = Error; fn try_from(tpm_handle: TpmHandle) -> Result { match tpm_handle { TpmHandle::Permanent(permanent_handle) => match permanent_handle { PermanentTpmHandle::Owner => Ok(HierarchyAuth::Owner), PermanentTpmHandle::Platform => Ok(HierarchyAuth::Platform), PermanentTpmHandle::Endorsement => Ok(HierarchyAuth::Endorsement), PermanentTpmHandle::Lockout => Ok(HierarchyAuth::Lockout), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), }, _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } ////////////////////////////////////////////////////////////////////////////////// /// TODO: HierarchyPolicy ////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////// /// Platform ////////////////////////////////////////////////////////////////////////////////// #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Platform { Platform, } impl From for AuthHandle { fn from(_: Platform) -> AuthHandle { AuthHandle::Platform } } impl TryFrom for Platform { type Error = Error; fn try_from(auth_handle: AuthHandle) -> Result { match auth_handle { AuthHandle::Platform => Ok(Platform::Platform), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } ////////////////////////////////////////////////////////////////////////////////// /// Owner ////////////////////////////////////////////////////////////////////////////////// #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Owner { Owner, Null, } impl From for ObjectHandle { fn from(owner: Owner) -> ObjectHandle { match owner { Owner::Owner => ObjectHandle::Owner, Owner::Null => ObjectHandle::Null, } } } impl TryFrom for Owner { type Error = Error; fn try_from(object_handle: ObjectHandle) -> Result { match object_handle { ObjectHandle::Owner => Ok(Owner::Owner), ObjectHandle::Null => Ok(Owner::Null), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } ////////////////////////////////////////////////////////////////////////////////// /// Endorsement ////////////////////////////////////////////////////////////////////////////////// #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Endorsement { Endorsement, Null, } impl From for ObjectHandle { fn from(endorsement: Endorsement) -> ObjectHandle { match endorsement { Endorsement::Endorsement => ObjectHandle::Endorsement, Endorsement::Null => ObjectHandle::Null, } } } impl TryFrom for Endorsement { type Error = Error; fn try_from(object_handle: ObjectHandle) -> Result { match object_handle { ObjectHandle::Endorsement => Ok(Endorsement::Endorsement), ObjectHandle::Null => Ok(Endorsement::Null), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } ////////////////////////////////////////////////////////////////////////////////// /// Provision ////////////////////////////////////////////////////////////////////////////////// #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Provision { Owner, Platform, } impl From for AuthHandle { fn from(provision: Provision) -> AuthHandle { match provision { Provision::Owner => AuthHandle::Owner, Provision::Platform => AuthHandle::Platform, } } } impl TryFrom for Provision { type Error = Error; fn try_from(auth_handle: AuthHandle) -> Result { match auth_handle { AuthHandle::Owner => Ok(Provision::Owner), AuthHandle::Platform => Ok(Provision::Platform), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } ////////////////////////////////////////////////////////////////////////////////// /// Clear ////////////////////////////////////////////////////////////////////////////////// #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Clear { Owner, Platform, } impl From for AuthHandle { fn from(clear: Clear) -> AuthHandle { match clear { Clear::Owner => AuthHandle::Owner, Clear::Platform => AuthHandle::Platform, } } } impl TryFrom for Clear { type Error = Error; fn try_from(auth_handle: AuthHandle) -> Result { match auth_handle { AuthHandle::Owner => Ok(Clear::Owner), AuthHandle::Platform => Ok(Clear::Platform), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } ////////////////////////////////////////////////////////////////////////////////// /// NvAuth ////////////////////////////////////////////////////////////////////////////////// #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum NvAuth { Platform, Owner, NvIndex(NvIndexHandle), } impl From for AuthHandle { fn from(nv_auth: NvAuth) -> AuthHandle { match nv_auth { NvAuth::Platform => AuthHandle::Platform, NvAuth::Owner => AuthHandle::Owner, NvAuth::NvIndex(nv_index_handle) => nv_index_handle.into(), } } } impl TryFrom for NvAuth { type Error = Error; fn try_from(auth_handle: AuthHandle) -> Result { match auth_handle { AuthHandle::Platform => Ok(NvAuth::Platform), AuthHandle::Owner => Ok(NvAuth::Owner), _ => Ok(NvAuth::NvIndex(NvIndexHandle::from(auth_handle))), } } } ////////////////////////////////////////////////////////////////////////////////// /// Lockout ////////////////////////////////////////////////////////////////////////////////// #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Lockout { Lockout, } impl From for ObjectHandle { fn from(_: Lockout) -> ObjectHandle { ObjectHandle::Lockout } } impl TryFrom for Lockout { type Error = Error; fn try_from(object_handle: ObjectHandle) -> Result { match object_handle { ObjectHandle::Lockout => Ok(Lockout::Lockout), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } ////////////////////////////////////////////////////////////////////////////////// /// NvIndex ////////////////////////////////////////////////////////////////////////////////// #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum NvIndex { NvIndex(NvIndexTpmHandle), } impl From for NvIndex { fn from(nv_index_tpm_handle: NvIndexTpmHandle) -> NvIndex { NvIndex::NvIndex(nv_index_tpm_handle) } } impl From for NvIndexTpmHandle { fn from(nv_index: NvIndex) -> NvIndexTpmHandle { match nv_index { NvIndex::NvIndex(handle) => handle, } } } ////////////////////////////////////////////////////////////////////////////////// /// AttachedComponent ////////////////////////////////////////////////////////////////////////////////// #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum AttachedComponent { AttachedComponent(AttachedComponentTpmHandle), } impl From for AttachedComponent { fn from(attached_component_tpm_handle: AttachedComponentTpmHandle) -> AttachedComponent { AttachedComponent::AttachedComponent(attached_component_tpm_handle) } } impl From for AttachedComponentTpmHandle { fn from(attached_component: AttachedComponent) -> AttachedComponentTpmHandle { match attached_component { AttachedComponent::AttachedComponent(handle) => handle, } } } ////////////////////////////////////////////////////////////////////////////////// // Act (authenticated timers) // // TODO: Figure out how to implement this. This is some kind of counter. ////////////////////////////////////////////////////////////////////////////////// tss-esapi-7.4.0/src/interface_types/session_handles.rs000064400000000000000000000116001046102023000212440ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ constants::SessionType, handles::SessionHandle, interface_types::algorithm::HashingAlgorithm, Error, Result, WrapperErrorKind, }; use std::convert::TryFrom; /// Enum representing an policy session interface type /// /// # Details /// This corresponds to TPMI_SH_POLICY but provides more /// information regarding the parameters used when the policy session /// was created. #[derive(Debug, Clone, Copy, Eq, PartialEq)] pub enum PolicySession { PolicySession { hashing_algorithm: HashingAlgorithm, session_handle: SessionHandle, session_type: SessionType, }, } impl From for SessionHandle { fn from(policy_session: PolicySession) -> SessionHandle { match policy_session { PolicySession::PolicySession { hashing_algorithm: _, session_handle, session_type: _, } => session_handle, } } } impl From for AuthSession { fn from(policy_session: PolicySession) -> AuthSession { AuthSession::PolicySession(policy_session) } } impl TryFrom for PolicySession { type Error = Error; fn try_from(auth_session: AuthSession) -> Result { match auth_session { AuthSession::PolicySession(policy_session) => Ok(policy_session), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } /// Enum representing an hmac session interface type /// /// # Details /// This corresponds to TPMI_SH_HMAC but provides more /// information regarding the parameters used when the hmac session /// was created. #[derive(Debug, Clone, Copy, Eq, PartialEq)] pub enum HmacSession { HmacSession { hashing_algorithm: HashingAlgorithm, session_handle: SessionHandle, }, } impl From for AuthSession { fn from(hmac_session: HmacSession) -> AuthSession { AuthSession::HmacSession(hmac_session) } } impl TryFrom for HmacSession { type Error = Error; fn try_from(auth_session: AuthSession) -> Result { match auth_session { AuthSession::HmacSession(hmac_session) => Ok(hmac_session), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } /// Enum representing an authorization session interface type /// /// # Details /// This corresponds to TPMI_SH_AUTH_SESSION but provides more /// information regarding the parameters used when the AuthSession /// was created. #[derive(Debug, Clone, Copy, Eq, PartialEq)] pub enum AuthSession { HmacSession(HmacSession), PolicySession(PolicySession), Password, } impl AuthSession { /// Function that creates a Option. /// /// If a Session is created from the NoneHandle /// then the returned value from the function will be None. pub fn create( session_type: SessionType, session_handle: SessionHandle, auth_hash: HashingAlgorithm, ) -> Option { if session_handle != SessionHandle::None { Some(match session_type { SessionType::Hmac => { //AuthSession::HmacSession(HmacSessionData::new(auth_hash, session_handle)) AuthSession::HmacSession(HmacSession::HmacSession { hashing_algorithm: auth_hash, session_handle, }) } SessionType::Policy => AuthSession::PolicySession(PolicySession::PolicySession { hashing_algorithm: auth_hash, session_handle, session_type, }), SessionType::Trial => AuthSession::PolicySession(PolicySession::PolicySession { hashing_algorithm: auth_hash, session_handle, session_type, }), }) } else { None } } } impl From for SessionHandle { fn from(auth_session: AuthSession) -> SessionHandle { match auth_session { AuthSession::HmacSession(HmacSession::HmacSession { hashing_algorithm: _, session_handle, }) => session_handle, AuthSession::PolicySession(PolicySession::PolicySession { hashing_algorithm: _, session_handle, session_type: _, }) => session_handle, AuthSession::Password => SessionHandle::Password, } } } impl From> for SessionHandle { fn from(optional_auth_session: Option) -> SessionHandle { if let Some(auth_session) = optional_auth_session { auth_session.into() } else { SessionHandle::None } } } tss-esapi-7.4.0/src/interface_types/structure_tags.rs000064400000000000000000000045661046102023000211560ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{constants::StructureTag, tss2_esys::TPMI_ST_ATTEST, Error, Result, WrapperErrorKind}; use std::convert::TryFrom; /// Type of attestation. /// /// # Details /// Corresponds to `TPMI_ST_ATTEST`. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum AttestationType { Certify, Quote, SessionAudit, CommandAudit, Time, Creation, Nv, NvDigest, } impl From for StructureTag { fn from(native: AttestationType) -> Self { match native { AttestationType::Certify => StructureTag::AttestCertify, AttestationType::Quote => StructureTag::AttestQuote, AttestationType::SessionAudit => StructureTag::AttestSessionAudit, AttestationType::CommandAudit => StructureTag::AttestCommandAudit, AttestationType::Time => StructureTag::AttestTime, AttestationType::Creation => StructureTag::AttestCreation, AttestationType::Nv => StructureTag::AttestNv, AttestationType::NvDigest => StructureTag::AttestNvDigest, } } } impl TryFrom for AttestationType { type Error = Error; fn try_from(structure_tag: StructureTag) -> Result { match structure_tag { StructureTag::AttestCertify => Ok(AttestationType::Certify), StructureTag::AttestQuote => Ok(AttestationType::Quote), StructureTag::AttestSessionAudit => Ok(AttestationType::SessionAudit), StructureTag::AttestCommandAudit => Ok(AttestationType::CommandAudit), StructureTag::AttestTime => Ok(AttestationType::Time), StructureTag::AttestCreation => Ok(AttestationType::Creation), StructureTag::AttestNv => Ok(AttestationType::Nv), StructureTag::AttestNvDigest => Ok(AttestationType::NvDigest), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } impl From for TPMI_ST_ATTEST { fn from(attestation_type: AttestationType) -> Self { StructureTag::from(attestation_type).into() } } impl TryFrom for AttestationType { type Error = Error; fn try_from(tpmi_st_attest: TPMI_ST_ATTEST) -> Result { AttestationType::try_from(StructureTag::try_from(tpmi_st_attest)?) } } tss-esapi-7.4.0/src/interface_types/yes_no.rs000064400000000000000000000022531046102023000173630ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{tss2_esys::TPMI_YES_NO, Error, Result, WrapperErrorKind}; use std::convert::TryFrom; /// Enum representing a yes or no. /// /// # Details /// This corresponds to the TPMI_YES_NO interface type. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum YesNo { Yes, No, } impl From for YesNo { fn from(value: bool) -> Self { if value { YesNo::Yes } else { YesNo::No } } } impl From for bool { fn from(yes_no: YesNo) -> Self { match yes_no { YesNo::Yes => true, YesNo::No => false, } } } impl From for TPMI_YES_NO { fn from(yes_no: YesNo) -> Self { match yes_no { YesNo::Yes => 1, YesNo::No => 0, } } } impl TryFrom for YesNo { type Error = Error; fn try_from(tpmi_yes_no: TPMI_YES_NO) -> Result { match tpmi_yes_no { 0 => Ok(YesNo::No), 1 => Ok(YesNo::Yes), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } tss-esapi-7.4.0/src/lib.rs000064400000000000000000000125371046102023000134570ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 #![deny( nonstandard_style, dead_code, improper_ctypes, non_shorthand_field_patterns, no_mangle_generic_items, overflowing_literals, path_statements, patterns_in_fns_without_body, private_in_public, unconditional_recursion, unused, unused_allocation, unused_comparisons, unused_parens, while_true, missing_debug_implementations, //TODO: activate this! //missing_docs, trivial_casts, trivial_numeric_casts, unused_extern_crates, unused_import_braces, unused_qualifications, unused_results, missing_copy_implementations, rustdoc::broken_intra_doc_links, )] //! # TSS 2.0 Rust Wrapper over Enhanced System API //! This crate exposes the functionality of the TCG Software Stack Enhanced System API to //! Rust developers, both directly through FFI bindings and through more Rust-tailored interfaces //! at varying levels of abstraction. //! Only platforms based on processors with a word size of at least 16 bits are supported. //! //! # Relevant specifications //! This library is built with insight from Trusted Computing Group specifications. The specs most relevant //! here are: //! * the [Trusted Platform Module Library Specification, Family “2.0”, Level 00, Revision 01.59](https://trustedcomputinggroup.org/work-groups/trusted-platform-module/) //! * the [TCG TSS 2.0 Enhanced System API (ESAPI) Specification, version 1.00, revision 14](https://trustedcomputinggroup.org/resource/tcg-tss-2-0-enhanced-system-api-esapi-specification/) //! //! The different parts of the first spec mentioned above (henceforth called the TPM2 spec) can be //! referenced individually throughout the documentation of this crate, using their part number or name. //! For example, //! [Part 1, Architecture](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part1_Architecture_pub.pdf) //! could be referenced as "the Architecture spec" or "part 1 of the TPM2 spec". //! //! The second spec mentioned above will henceforth be called the ESAPI or ESys spec. //! //! Some parts of the code relate to features or functionality defined in other specifications (such as the //! [Marshaling/Unmarshaling API v1, rev7 spec](https://trustedcomputinggroup.org/resource/tcg-tss-2-0-marshalingunmarshaling-api-specification/)), //! and in such cases the specification should be linked and referenced in full. //! //! # Code structure //! Our code structure is mostly derived from part 2 of the TPM2 spec. //! For simplicity, however, we have reduced the depth of the import tree, so most (if not all) types //! are at most one level away from root. //! //! Minimum supported Rust version (MSRV): //! We currently check with version 1.66.0 of the Rust compiler during CI builds. //! //! # Notes on code safety: //! * thread safety is ensured by the required mutability of the `Context` structure within the //! methods implemented on it; thus, in an otherwise safe app commands cannot be dispatched in //! parallel for the same context; whether multithreading with multiple context objects is possible //! depends on the TCTI used and this is the responsibility of the crate client to establish. //! * the `unsafe` keyword is used to denote methods that could panic, crash or cause undefined //! behaviour. Whenever this is the case, the properties that need to be checked against //! parameters before passing them in will be stated in the documentation of the method. //! * `unsafe` blocks within this crate need to be documented through code comments if they //! are not covered by the points of trust described here. //! * the TSS2.0 library that this crate links to is trusted to return consistent values and to //! not crash or lead to undefined behaviour when presented with valid arguments. //! * the `Mbox` crate is trusted to perform operations safely on the pointers provided to it, if //! the pointers are trusted to be valid. //! * methods not marked `unsafe` are trusted to behave safely, potentially returning appropriate //! error messages when encountering any problems. //! * whenever `unwrap`, `expect`, `panic` or derivatives of these are used, they need to be //! thoroughly documented and justified - preferably `unwrap` and `expect` should *never* fail //! during normal operation. //! * these rules can be broken in test-only code and in tests. //! //! # Logging //! This crate uses the typical `log` crate for printing errors generated in method calls. If //! you would like to filter out these log messages, please check with your logger documentation //! on how to do that. //! //! Additionally, the TSS library will also generate its own log messages and these can be //! controlled through environment variables as explained //! [here](https://github.com/tpm2-software/tpm2-tss/blob/main/doc/logging.md#runtime-log-level). //! pub use abstraction::transient::TransientKeyContext; pub use context::Context; pub use error::{Error, Result, WrapperErrorKind}; pub use tcti_ldr::TctiNameConf; // To replace painlessly the old Tcti structure, should maybe be deprecated at some point. pub use tcti_ldr::TctiNameConf as Tcti; pub use tss_esapi_sys as tss2_esys; pub mod abstraction; pub mod attributes; pub mod constants; mod context; mod error; pub mod handles; pub mod interface_types; pub mod structures; pub mod tcti_ldr; pub mod traits; pub mod utils; tss-esapi-7.4.0/src/macros/mod.rs000064400000000000000000000001351046102023000147430ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 tss-esapi-7.4.0/src/structures/attestation/attest.rs000064400000000000000000000136201046102023000207710ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ constants::tss::TPM2_GENERATED_VALUE, interface_types::structure_tags::AttestationType, structures::{AttestInfo, ClockInfo, Data, Name}, traits::{Marshall, UnMarshall}, tss2_esys::TPMS_ATTEST, Error, Result, WrapperErrorKind, }; use log::error; use std::convert::{TryFrom, TryInto}; /// Type for holding attestation data /// /// # Details /// Corresponds to `TPMS_ATTEST`. #[derive(Debug, Clone)] pub struct Attest { attestation_type: AttestationType, qualified_signer: Name, extra_data: Data, clock_info: ClockInfo, firmware_version: u64, attested: AttestInfo, } impl Attest { /// Returns attestation type pub const fn attestation_type(&self) -> AttestationType { self.attestation_type } /// Returns the qualified name of the signing object. pub const fn qualified_signer(&self) -> &Name { &self.qualified_signer } /// Returns the extra data specified by the caller. pub const fn extra_data(&self) -> &Data { &self.extra_data } /// Returns the internal TPM clock data. pub const fn clock_info(&self) -> &ClockInfo { &self.clock_info } /// Returns TPM firmware version number. pub const fn firmware_version(&self) -> u64 { self.firmware_version } /// Returns types specific attestation information pub const fn attested(&self) -> &AttestInfo { &self.attested } } impl From for TPMS_ATTEST { fn from(attest: Attest) -> Self { TPMS_ATTEST { magic: TPM2_GENERATED_VALUE, type_: attest.attestation_type.into(), qualifiedSigner: attest.qualified_signer.into(), extraData: attest.extra_data.into(), clockInfo: attest.clock_info.into(), firmwareVersion: attest.firmware_version, attested: attest.attested.into(), } } } impl TryFrom for Attest { type Error = Error; fn try_from(tpms_attest: TPMS_ATTEST) -> Result { if tpms_attest.magic != TPM2_GENERATED_VALUE { return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } let attestation_type = AttestationType::try_from(tpms_attest.type_)?; Ok(Attest { attestation_type, qualified_signer: Name::try_from(tpms_attest.qualifiedSigner)?, extra_data: Data::try_from(tpms_attest.extraData)?, clock_info: ClockInfo::try_from(tpms_attest.clockInfo)?, firmware_version: tpms_attest.firmwareVersion, attested: match attestation_type { AttestationType::Certify => AttestInfo::Certify { info: unsafe { tpms_attest.attested.certify }.try_into()?, }, AttestationType::Quote => AttestInfo::Quote { info: unsafe { tpms_attest.attested.quote }.try_into()?, }, AttestationType::SessionAudit => AttestInfo::SessionAudit { info: unsafe { tpms_attest.attested.sessionAudit }.try_into()?, }, AttestationType::CommandAudit => AttestInfo::CommandAudit { info: unsafe { tpms_attest.attested.commandAudit }.try_into()?, }, AttestationType::Time => AttestInfo::Time { info: unsafe { tpms_attest.attested.time }.try_into()?, }, AttestationType::Creation => AttestInfo::Creation { info: unsafe { tpms_attest.attested.creation }.try_into()?, }, AttestationType::Nv => AttestInfo::Nv { info: unsafe { tpms_attest.attested.nv }.try_into()?, }, AttestationType::NvDigest => { error!("NvDigest attestation type is currently not supported"); return Err(Error::local_error(WrapperErrorKind::UnsupportedParam)); } }, }) } } impl Marshall for Attest { const BUFFER_SIZE: usize = std::mem::size_of::(); /// Produce a marshalled [`TPMS_ATTEST`] fn marshall(&self) -> Result> { let mut buffer = vec![0; Self::BUFFER_SIZE]; let mut offset = 0; let ret = Error::from_tss_rc(unsafe { crate::tss2_esys::Tss2_MU_TPMS_ATTEST_Marshal( &self.clone().into(), buffer.as_mut_ptr(), Self::BUFFER_SIZE.try_into().map_err(|e| { error!("Failed to convert size of buffer to TSS size_t type: {}", e); Error::local_error(WrapperErrorKind::InvalidParam) })?, &mut offset, ) }); if !ret.is_success() { return Err(ret); } let checked_offset = usize::try_from(offset).map_err(|e| { error!("Failed to parse offset as usize: {}", e); Error::local_error(WrapperErrorKind::InvalidParam) })?; buffer.truncate(checked_offset); Ok(buffer) } } impl UnMarshall for Attest { /// Unmarshall the structure from [`TPMS_ATTEST`] fn unmarshall(marshalled_data: &[u8]) -> Result { let mut dest = TPMS_ATTEST::default(); let mut offset = 0; let ret = Error::from_tss_rc(unsafe { crate::tss2_esys::Tss2_MU_TPMS_ATTEST_Unmarshal( marshalled_data.as_ptr(), marshalled_data.len().try_into().map_err(|e| { error!("Failed to convert length of marshalled data: {}", e); Error::local_error(WrapperErrorKind::InvalidParam) })?, &mut offset, &mut dest, ) }); if !ret.is_success() { return Err(ret); } Attest::try_from(dest) } } tss-esapi-7.4.0/src/structures/attestation/attest_info.rs000064400000000000000000000032771046102023000220130ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ structures::{ CertifyInfo, CommandAuditInfo, CreationInfo, NvCertifyInfo, QuoteInfo, SessionAuditInfo, TimeAttestInfo, }, tss2_esys::TPMU_ATTEST, }; /// Enum that holds the different types of /// attest info. /// /// # Details /// This type does to some degree corresponds to the /// TPMU_ATTEST but with the TPM_ST_ATTEST selectore /// included. #[derive(Debug, Clone)] pub enum AttestInfo { Certify { info: CertifyInfo }, Quote { info: QuoteInfo }, SessionAudit { info: SessionAuditInfo }, CommandAudit { info: CommandAuditInfo }, Time { info: TimeAttestInfo }, Creation { info: CreationInfo }, Nv { info: NvCertifyInfo }, // NvDigest, the TPMS_NV_DIGEST_CERTIFY_INFO, // was first added in the 3.1.0 version of the tpm2-tss } impl From for TPMU_ATTEST { fn from(attest_info: AttestInfo) -> Self { match attest_info { AttestInfo::Certify { info } => TPMU_ATTEST { certify: info.into(), }, AttestInfo::Quote { info } => TPMU_ATTEST { quote: info.into() }, AttestInfo::SessionAudit { info } => TPMU_ATTEST { sessionAudit: info.into(), }, AttestInfo::CommandAudit { info } => TPMU_ATTEST { commandAudit: info.into(), }, AttestInfo::Time { info } => TPMU_ATTEST { time: info.into() }, AttestInfo::Creation { info } => TPMU_ATTEST { creation: info.into(), }, AttestInfo::Nv { info } => TPMU_ATTEST { nv: info.into() }, } } } tss-esapi-7.4.0/src/structures/attestation/certify_info.rs000064400000000000000000000023671046102023000221530ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{structures::Name, tss2_esys::TPMS_CERTIFY_INFO, Error, Result}; use std::convert::{TryFrom, TryInto}; /// This a struct holding the attested data for the command TPM2_Certify /// /// # Details /// This corresponds to the TPMS_CERTIFY_INFO. #[derive(Debug, Clone)] pub struct CertifyInfo { name: Name, qualified_name: Name, } impl CertifyInfo { /// Returns a reference to the name pub const fn name(&self) -> &Name { &self.name } /// Returns a reference to the qualified name pub const fn qualified_name(&self) -> &Name { &self.qualified_name } } impl From for TPMS_CERTIFY_INFO { fn from(certify_info: CertifyInfo) -> Self { TPMS_CERTIFY_INFO { name: certify_info.name.into(), qualifiedName: certify_info.qualified_name.into(), } } } impl TryFrom for CertifyInfo { type Error = Error; fn try_from(tpms_certify_info: TPMS_CERTIFY_INFO) -> Result { Ok(CertifyInfo { name: tpms_certify_info.name.try_into()?, qualified_name: tpms_certify_info.qualifiedName.try_into()?, }) } } tss-esapi-7.4.0/src/structures/attestation/command_audit_info.rs000064400000000000000000000042311046102023000233020ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ constants::AlgorithmIdentifier, interface_types::algorithm::HashingAlgorithm, structures::Digest, tss2_esys::TPMS_COMMAND_AUDIT_INFO, Error, Result, }; use std::convert::{TryFrom, TryInto}; /// Structure holding the attested data for /// TPM2_GetCommandAuditDigest(). /// /// # Details /// This corresponds to the TPMS_COMMAND_AUDIT_INFO #[derive(Debug, Clone)] pub struct CommandAuditInfo { audit_counter: u64, hashing_algorithm: HashingAlgorithm, audit_digest: Digest, command_digest: Digest, } impl CommandAuditInfo { /// Returns the audit counter pub const fn audit_counter(&self) -> u64 { self.audit_counter } /// Returns the hash algorithm used for the command audit pub const fn hashing_algorithm(&self) -> HashingAlgorithm { self.hashing_algorithm } /// Returns the audit digest pub const fn audit_digest(&self) -> &Digest { &self.audit_digest } /// Returns the command digest pub const fn command_digest(&self) -> &Digest { &self.command_digest } } impl From for TPMS_COMMAND_AUDIT_INFO { fn from(command_audit_info: CommandAuditInfo) -> Self { TPMS_COMMAND_AUDIT_INFO { auditCounter: command_audit_info.audit_counter, digestAlg: AlgorithmIdentifier::from(command_audit_info.hashing_algorithm).into(), auditDigest: command_audit_info.audit_digest.into(), commandDigest: command_audit_info.command_digest.into(), } } } impl TryFrom for CommandAuditInfo { type Error = Error; fn try_from(tpms_command_audit_info: TPMS_COMMAND_AUDIT_INFO) -> Result { Ok(CommandAuditInfo { audit_counter: tpms_command_audit_info.auditCounter, hashing_algorithm: AlgorithmIdentifier::try_from(tpms_command_audit_info.digestAlg)? .try_into()?, audit_digest: tpms_command_audit_info.auditDigest.try_into()?, command_digest: tpms_command_audit_info.commandDigest.try_into()?, }) } } tss-esapi-7.4.0/src/structures/attestation/creation_info.rs000064400000000000000000000024661046102023000223120ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ structures::{Digest, Name}, tss2_esys::TPMS_CREATION_INFO, Error, Result, }; use std::convert::{TryFrom, TryInto}; /// Structure holding the attested data for TPM2_CertifyCreation() /// /// # Details /// This corresponds to the TPMS_CREATION_INFO #[derive(Debug, Clone)] pub struct CreationInfo { object_name: Name, creation_hash: Digest, } impl CreationInfo { /// Returns the name of the object pub const fn object_name(&self) -> &Name { &self.object_name } /// Returns the creation hash pub const fn creation_hash(&self) -> &Digest { &self.creation_hash } } impl From for TPMS_CREATION_INFO { fn from(creation_info: CreationInfo) -> Self { TPMS_CREATION_INFO { objectName: creation_info.object_name.into(), creationHash: creation_info.creation_hash.into(), } } } impl TryFrom for CreationInfo { type Error = Error; fn try_from(tpms_creation_info: TPMS_CREATION_INFO) -> Result { Ok(CreationInfo { object_name: tpms_creation_info.objectName.try_into()?, creation_hash: tpms_creation_info.creationHash.try_into()?, }) } } tss-esapi-7.4.0/src/structures/attestation/mod.rs000064400000000000000000000005161046102023000202440ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 pub mod attest; pub mod attest_info; pub mod certify_info; pub mod command_audit_info; pub mod creation_info; pub mod nv_certify_info; pub mod nv_digest_certify_info; pub mod quote_info; pub mod session_audit_info; pub mod time_attest_info; tss-esapi-7.4.0/src/structures/attestation/nv_certify_info.rs000064400000000000000000000031061046102023000226460ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ structures::{MaxNvBuffer, Name}, tss2_esys::TPMS_NV_CERTIFY_INFO, Error, Result, }; use std::convert::{TryFrom, TryInto}; /// This structure contains the Name and contents of the /// selected NV Index that is certified by TPM2_NV_Certify() /// /// # Details /// This corresponds to the TPMS_NV_CERTIFY_INFO. #[derive(Debug, Clone)] pub struct NvCertifyInfo { index_name: Name, offset: u16, nv_contents: MaxNvBuffer, } impl NvCertifyInfo { /// Returns index name pub const fn index_name(&self) -> &Name { &self.index_name } /// Returns offset pub const fn offset(&self) -> u16 { self.offset } /// Returns nv contents pub const fn nv_contents(&self) -> &MaxNvBuffer { &self.nv_contents } } impl From for TPMS_NV_CERTIFY_INFO { fn from(nv_certify_info: NvCertifyInfo) -> Self { TPMS_NV_CERTIFY_INFO { indexName: nv_certify_info.index_name.into(), offset: nv_certify_info.offset, nvContents: nv_certify_info.nv_contents.into(), } } } impl TryFrom for NvCertifyInfo { type Error = Error; fn try_from(tpms_nv_certify_info: TPMS_NV_CERTIFY_INFO) -> Result { Ok(NvCertifyInfo { index_name: tpms_nv_certify_info.indexName.try_into()?, offset: tpms_nv_certify_info.offset, nv_contents: tpms_nv_certify_info.nvContents.try_into()?, }) } } tss-esapi-7.4.0/src/structures/attestation/nv_digest_certify_info.rs000064400000000000000000000012631046102023000242070ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::structures::{Digest, Name}; /// This structure contains the Name and hash of the /// contents of the selected NV Index that is certified by /// TPM2_NV_Certify() /// /// # Details /// This corresponds to TPMS_NV_DIGEST_CERTIFY_INFO. #[derive(Debug, Clone)] pub struct NvDigestCertifyInfo { index_name: Name, nv_digest: Digest, } impl NvDigestCertifyInfo { /// Returns the index name pub const fn index_name(&self) -> &Name { &self.index_name } /// Returns the NV digest. pub const fn nv_digest(&self) -> &Digest { &self.nv_digest } } tss-esapi-7.4.0/src/structures/attestation/quote_info.rs000064400000000000000000000025161046102023000216370ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ structures::{Digest, PcrSelectionList}, tss2_esys::TPMS_QUOTE_INFO, Error, Result, }; use std::convert::{TryFrom, TryInto}; /// Structure holding the attested data for TPM2_Quote() /// /// # Details /// This corresponds to the TPMS_QUOTE_INFO #[derive(Debug, Clone)] pub struct QuoteInfo { pcr_selection: PcrSelectionList, pcr_digest: Digest, } impl QuoteInfo { /// Returns the pcr selections list representing the selected PCRs. pub const fn pcr_selection(&self) -> &PcrSelectionList { &self.pcr_selection } /// Returns the digest selected PCRs hash of the signing key. pub const fn pcr_digest(&self) -> &Digest { &self.pcr_digest } } impl From for TPMS_QUOTE_INFO { fn from(quote_info: QuoteInfo) -> Self { TPMS_QUOTE_INFO { pcrSelect: quote_info.pcr_selection.into(), pcrDigest: quote_info.pcr_digest.into(), } } } impl TryFrom for QuoteInfo { type Error = Error; fn try_from(tpms_quote_info: TPMS_QUOTE_INFO) -> Result { Ok(QuoteInfo { pcr_selection: tpms_quote_info.pcrSelect.try_into()?, pcr_digest: tpms_quote_info.pcrDigest.try_into()?, }) } } tss-esapi-7.4.0/src/structures/attestation/session_audit_info.rs000064400000000000000000000031631046102023000233520ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ interface_types::YesNo, structures::Digest, tss2_esys::TPMS_SESSION_AUDIT_INFO, Error, Result, }; use std::convert::{TryFrom, TryInto}; /// This type holds the attested data for /// TPM2_GetSessionAuditDigest() /// /// # Details /// This corresponds to the TPMS_SESSION_AUDIT_INFO. #[derive(Debug, Clone)] pub struct SessionAuditInfo { exclusive_session: YesNo, session_digest: Digest, } impl SessionAuditInfo { /// Returns true if if all of the commands recorded in the sessionDigest were /// executed without any intervening TPM command that did not use /// this audit session pub fn exlusive_session(&self) -> bool { self.exclusive_session.into() } /// Returns the current value of the session audit diges pub const fn session_digest(&self) -> &Digest { &self.session_digest } } impl From for TPMS_SESSION_AUDIT_INFO { fn from(session_audit_info: SessionAuditInfo) -> Self { TPMS_SESSION_AUDIT_INFO { exclusiveSession: session_audit_info.exclusive_session.into(), sessionDigest: session_audit_info.session_digest.into(), } } } impl TryFrom for SessionAuditInfo { type Error = Error; fn try_from(tpms_session_audit_info: TPMS_SESSION_AUDIT_INFO) -> Result { Ok(SessionAuditInfo { exclusive_session: tpms_session_audit_info.exclusiveSession.try_into()?, session_digest: tpms_session_audit_info.sessionDigest.try_into()?, }) } } tss-esapi-7.4.0/src/structures/attestation/time_attest_info.rs000064400000000000000000000025171046102023000230250ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{structures::TimeInfo, tss2_esys::TPMS_TIME_ATTEST_INFO, Error, Result}; use std::convert::{TryFrom, TryInto}; /// This type is holding attested data for the command TPM2_GetTime /// /// # Details /// This corresponds to the TPMS_TIME_ATTEST_INFO. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct TimeAttestInfo { time_info: TimeInfo, firmware_version: u64, } impl TimeAttestInfo { /// Returns the time info pub const fn time_info(&self) -> &TimeInfo { &self.time_info } /// Returns the firmware version pub const fn firmware_version(&self) -> u64 { self.firmware_version } } impl From for TPMS_TIME_ATTEST_INFO { fn from(time_attest_info: TimeAttestInfo) -> Self { TPMS_TIME_ATTEST_INFO { time: time_attest_info.time_info.into(), firmwareVersion: time_attest_info.firmware_version, } } } impl TryFrom for TimeAttestInfo { type Error = Error; fn try_from(tpms_time_attest_info: TPMS_TIME_ATTEST_INFO) -> Result { Ok(TimeAttestInfo { time_info: tpms_time_attest_info.time.try_into()?, firmware_version: tpms_time_attest_info.firmwareVersion, }) } } tss-esapi-7.4.0/src/structures/buffers/attest.rs000064400000000000000000000047331046102023000200730ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ structures::Attest, traits::UnMarshall, tss2_esys::TPM2B_ATTEST, Error, Result, WrapperErrorKind, }; use log::error; use std::{convert::TryFrom, ops::Deref}; use zeroize::Zeroizing; /// Attestation data buffer. /// /// # Details /// Corresponds to `TPM2B_ATTEST`. The contents of /// the buffer can be unmarshalled into an [Attest] /// structure. #[derive(Debug, Clone, PartialEq, Eq)] pub struct AttestBuffer(Zeroizing>); impl Default for AttestBuffer { fn default() -> Self { AttestBuffer(Vec::new().into()) } } impl AttestBuffer { pub const MAX_SIZE: usize = 2304; pub fn value(&self) -> &[u8] { &self.0 } } impl Deref for AttestBuffer { type Target = Vec; fn deref(&self) -> &Self::Target { &self.0 } } impl TryFrom> for AttestBuffer { type Error = Error; fn try_from(bytes: Vec) -> Result { if bytes.len() > Self::MAX_SIZE { error!("Invalid Vec size(> {})", Self::MAX_SIZE); return Err(Error::local_error(WrapperErrorKind::WrongParamSize)); } Ok(AttestBuffer(bytes.into())) } } impl TryFrom<&[u8]> for AttestBuffer { type Error = Error; fn try_from(bytes: &[u8]) -> Result { if bytes.len() > Self::MAX_SIZE { error!("Invalid &[u8] size(> {})", Self::MAX_SIZE); return Err(Error::local_error(WrapperErrorKind::WrongParamSize)); } Ok(AttestBuffer(bytes.to_vec().into())) } } impl TryFrom for AttestBuffer { type Error = Error; fn try_from(tss: TPM2B_ATTEST) -> Result { let size = tss.size as usize; if size > Self::MAX_SIZE { error!("Invalid buffer size(> {})", Self::MAX_SIZE); return Err(Error::local_error(WrapperErrorKind::WrongParamSize)); } Ok(AttestBuffer(tss.attestationData[..size].to_vec().into())) } } impl From for TPM2B_ATTEST { fn from(native: AttestBuffer) -> Self { let mut buffer = TPM2B_ATTEST { size: native.0.len() as u16, ..Default::default() }; buffer.attestationData[..native.0.len()].copy_from_slice(&native.0); buffer } } impl TryFrom for Attest { type Error = Error; fn try_from(buf: AttestBuffer) -> Result { Attest::unmarshall(&buf.0) } } tss-esapi-7.4.0/src/structures/buffers/public.rs000064400000000000000000000114111046102023000200340ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ structures::Public, traits::{Marshall, UnMarshall}, tss2_esys::{TPM2B_PUBLIC, TPMT_PUBLIC}, Error, Result, WrapperErrorKind, }; use log::error; use std::{ convert::{TryFrom, TryInto}, ops::Deref, }; use zeroize::Zeroize; /// Public data buffer. /// /// # Details /// Corresponds to `TPM2B_PUBLIC`. The contents of /// the buffer can be unmarshalled into a [Public] /// structure. #[derive(Debug, Clone, PartialEq, Eq, Zeroize)] #[zeroize(drop)] pub struct PublicBuffer(Vec); impl PublicBuffer { pub const MAX_SIZE: usize = std::mem::size_of::(); pub fn value(&self) -> &[u8] { &self.0 } } impl Deref for PublicBuffer { type Target = Vec; fn deref(&self) -> &Self::Target { &self.0 } } impl TryFrom> for PublicBuffer { type Error = Error; fn try_from(bytes: Vec) -> Result { if bytes.len() > Self::MAX_SIZE { error!( "Error: Invalid Vec size ({} > {})", bytes.len(), Self::MAX_SIZE ); return Err(Error::local_error(WrapperErrorKind::WrongParamSize)); } Ok(PublicBuffer(bytes)) } } impl TryFrom<&[u8]> for PublicBuffer { type Error = Error; fn try_from(bytes: &[u8]) -> Result { if bytes.len() > Self::MAX_SIZE { error!( "Error: Invalid &[u8] size ({} > {})", bytes.len(), Self::MAX_SIZE ); return Err(Error::local_error(WrapperErrorKind::WrongParamSize)); } Ok(PublicBuffer(bytes.to_vec())) } } impl TryFrom for PublicBuffer { type Error = Error; fn try_from(tss: TPM2B_PUBLIC) -> Result { let size = tss.size as usize; if size > Self::MAX_SIZE { error!("Error: Invalid buffer size ({} > {})", size, Self::MAX_SIZE); return Err(Error::local_error(WrapperErrorKind::WrongParamSize)); } let public = Public::try_from(tss.publicArea)?; Ok(PublicBuffer(public.marshall()?)) } } impl TryFrom for TPM2B_PUBLIC { type Error = Error; fn try_from(native: PublicBuffer) -> Result { let mut buffer = TPM2B_PUBLIC { size: native.0.len() as u16, ..Default::default() }; let public = Public::unmarshall(&native.0)?; buffer.publicArea = public.into(); Ok(buffer) } } impl TryFrom for Public { type Error = Error; fn try_from(buf: PublicBuffer) -> Result { Public::unmarshall(&buf.0) } } impl TryFrom for PublicBuffer { type Error = Error; fn try_from(public: Public) -> Result { Ok(PublicBuffer(public.marshall()?)) } } impl Marshall for PublicBuffer { const BUFFER_SIZE: usize = std::mem::size_of::(); /// Produce a marshalled [`TPM2B_PUBLIC`] fn marshall(&self) -> Result> { let mut buffer = vec![0; Self::BUFFER_SIZE]; let mut offset = 0; let ret = Error::from_tss_rc(unsafe { crate::tss2_esys::Tss2_MU_TPM2B_PUBLIC_Marshal( &self.clone().try_into()?, buffer.as_mut_ptr(), Self::BUFFER_SIZE.try_into().map_err(|e| { error!("Failed to convert size of buffer to TSS size_t type: {}", e); Error::local_error(WrapperErrorKind::InvalidParam) })?, &mut offset, ) }); if !ret.is_success() { return Err(ret); } let checked_offset = usize::try_from(offset).map_err(|e| { error!("Failed to parse offset as usize: {}", e); Error::local_error(WrapperErrorKind::InvalidParam) })?; buffer.truncate(checked_offset); Ok(buffer) } } impl UnMarshall for PublicBuffer { /// Unmarshall the structure from [`TPM2B_PUBLIC`] fn unmarshall(marshalled_data: &[u8]) -> Result { let mut dest = TPM2B_PUBLIC::default(); let mut offset = 0; let ret = Error::from_tss_rc(unsafe { crate::tss2_esys::Tss2_MU_TPM2B_PUBLIC_Unmarshal( marshalled_data.as_ptr(), marshalled_data.len().try_into().map_err(|e| { error!("Failed to convert length of marshalled data: {}", e); Error::local_error(WrapperErrorKind::InvalidParam) })?, &mut offset, &mut dest, ) }); if !ret.is_success() { return Err(ret); } PublicBuffer::try_from(dest) } } tss-esapi-7.4.0/src/structures/buffers/sensitive.rs000064400000000000000000000116361046102023000206000ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ structures::Sensitive, traits::{Marshall, UnMarshall}, tss2_esys::{TPM2B_SENSITIVE, TPMT_SENSITIVE}, Error, Result, WrapperErrorKind, }; use log::error; use std::{ convert::{TryFrom, TryInto}, ops::Deref, }; use zeroize::Zeroize; /// Sensitive data buffer. /// /// # Details /// Corresponds to `TPM2B_SENSITIVE`. The contents of /// the buffer can be unmarshalled into a [Sensitive] /// structure. #[derive(Debug, Clone, PartialEq, Eq, Zeroize)] #[zeroize(drop)] pub struct SensitiveBuffer(Vec); impl SensitiveBuffer { pub const MAX_SIZE: usize = std::mem::size_of::(); pub fn value(&self) -> &[u8] { &self.0 } } impl Deref for SensitiveBuffer { type Target = Vec; fn deref(&self) -> &Self::Target { &self.0 } } impl TryFrom> for SensitiveBuffer { type Error = Error; fn try_from(bytes: Vec) -> Result { if bytes.len() > Self::MAX_SIZE { error!( "Error: Invalid Vec size ({} > {})", bytes.len(), Self::MAX_SIZE ); return Err(Error::local_error(WrapperErrorKind::WrongParamSize)); } Ok(SensitiveBuffer(bytes)) } } impl TryFrom<&[u8]> for SensitiveBuffer { type Error = Error; fn try_from(bytes: &[u8]) -> Result { if bytes.len() > Self::MAX_SIZE { error!( "Error: Invalid &[u8] size ({} > {})", bytes.len(), Self::MAX_SIZE ); return Err(Error::local_error(WrapperErrorKind::WrongParamSize)); } Ok(SensitiveBuffer(bytes.to_vec())) } } impl TryFrom for SensitiveBuffer { type Error = Error; fn try_from(tss: TPM2B_SENSITIVE) -> Result { let size = tss.size as usize; if size > Self::MAX_SIZE { error!("Error: Invalid buffer size ({} > {})", size, Self::MAX_SIZE); return Err(Error::local_error(WrapperErrorKind::WrongParamSize)); } let sensitive = Sensitive::try_from(tss.sensitiveArea)?; Ok(SensitiveBuffer(sensitive.marshall()?)) } } impl TryFrom for TPM2B_SENSITIVE { type Error = Error; fn try_from(native: SensitiveBuffer) -> Result { let mut buffer = TPM2B_SENSITIVE { size: native.0.len() as u16, ..Default::default() }; let sensitive = Sensitive::unmarshall(&native.0)?; buffer.sensitiveArea = sensitive.into(); Ok(buffer) } } impl TryFrom for Sensitive { type Error = Error; fn try_from(buf: SensitiveBuffer) -> Result { Sensitive::unmarshall(&buf.0) } } impl TryFrom for SensitiveBuffer { type Error = Error; fn try_from(sensitive: Sensitive) -> Result { Ok(SensitiveBuffer(sensitive.marshall()?)) } } impl Marshall for SensitiveBuffer { const BUFFER_SIZE: usize = std::mem::size_of::(); /// Produce a marshalled [`TPM2B_SENSITIVE`] fn marshall(&self) -> Result> { let mut buffer = vec![0; Self::BUFFER_SIZE]; let mut offset = 0; let ret = Error::from_tss_rc(unsafe { crate::tss2_esys::Tss2_MU_TPM2B_SENSITIVE_Marshal( &self.clone().try_into()?, buffer.as_mut_ptr(), Self::BUFFER_SIZE.try_into().map_err(|e| { error!("Failed to convert size of buffer to TSS size_t type: {}", e); Error::local_error(WrapperErrorKind::InvalidParam) })?, &mut offset, ) }); if !ret.is_success() { return Err(ret); } let checked_offset = usize::try_from(offset).map_err(|e| { error!("Failed to parse offset as usize: {}", e); Error::local_error(WrapperErrorKind::InvalidParam) })?; buffer.truncate(checked_offset); Ok(buffer) } } impl UnMarshall for SensitiveBuffer { /// Unmarshall the structure from [`TPM2B_SENSITIVE`] fn unmarshall(marshalled_data: &[u8]) -> Result { let mut dest = TPM2B_SENSITIVE::default(); let mut offset = 0; let ret = Error::from_tss_rc(unsafe { crate::tss2_esys::Tss2_MU_TPM2B_SENSITIVE_Unmarshal( marshalled_data.as_ptr(), marshalled_data.len().try_into().map_err(|e| { error!("Failed to convert length of marshalled data: {}", e); Error::local_error(WrapperErrorKind::InvalidParam) })?, &mut offset, &mut dest, ) }); if !ret.is_success() { return Err(ret); } SensitiveBuffer::try_from(dest) } } tss-esapi-7.4.0/src/structures/buffers.rs000064400000000000000000000237621046102023000165720ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 #[allow(unused_macros)] macro_rules! named_field_buffer_type { ($native_type:ident,$MAX:expr,$tss_type:ident,$buffer_field_name:ident) => { use crate::tss2_esys::$tss_type; use crate::{Error, Result, WrapperErrorKind}; use log::error; use std::convert::TryFrom; use std::ops::Deref; use zeroize::Zeroizing; #[derive(Debug, Clone, PartialEq, Eq)] pub struct $native_type(Zeroizing>); impl Default for $native_type { fn default() -> Self { $native_type(Vec::new().into()) } } impl $native_type { pub const MAX_SIZE: usize = $MAX; pub fn value(&self) -> &[u8] { &self.0 } } impl Deref for $native_type { type Target = Vec; fn deref(&self) -> &Self::Target { &self.0 } } impl TryFrom> for $native_type { type Error = Error; fn try_from(bytes: Vec) -> Result { if bytes.len() > Self::MAX_SIZE { error!("Invalid Vec size(> {})", Self::MAX_SIZE); return Err(Error::local_error(WrapperErrorKind::WrongParamSize)); } Ok($native_type(bytes.into())) } } impl TryFrom<&[u8]> for $native_type { type Error = Error; fn try_from(bytes: &[u8]) -> Result { if bytes.len() > Self::MAX_SIZE { error!("Invalid &[u8] size(> {})", Self::MAX_SIZE); return Err(Error::local_error(WrapperErrorKind::WrongParamSize)); } Ok($native_type(bytes.to_vec().into())) } } impl TryFrom<$tss_type> for $native_type { type Error = Error; fn try_from(tss: $tss_type) -> Result { let size = tss.size as usize; if size > Self::MAX_SIZE { error!("Invalid buffer size(> {})", Self::MAX_SIZE); return Err(Error::local_error(WrapperErrorKind::WrongParamSize)); } Ok($native_type(tss.$buffer_field_name[..size].to_vec().into())) } } impl From<$native_type> for $tss_type { fn from(native: $native_type) -> Self { let mut buffer = $tss_type { size: native.0.len() as u16, ..Default::default() }; buffer.$buffer_field_name[..native.0.len()].copy_from_slice(&native.0); buffer } } }; } #[allow(unused_macros)] macro_rules! buffer_type { ($native_type:ident,$MAX:expr,$tss_type:ident) => { named_field_buffer_type!($native_type, $MAX, $tss_type, buffer); }; } pub mod attest; pub mod public; pub mod sensitive; pub mod auth { buffer_type!(Auth, 64, TPM2B_AUTH); } pub mod data { buffer_type!(Data, 64, TPM2B_DATA); } pub mod digest { buffer_type!(Digest, 64, TPM2B_DIGEST); // Some implementations to get from Digest to [u8; N] for common values of N (sha* primarily) // This is used to work around the fact that Rust does not allow custom functions for general values of N in [T; N], // and the standard try_from for Slice to Array is only for LengthAtMost32. use std::convert::TryInto; // For the arrays that are LengthAtMost32, we use the built-in try_from impl TryFrom for [u8; 20] { type Error = Error; fn try_from(value: Digest) -> Result { value .value() .try_into() .map_err(|_| Error::local_error(WrapperErrorKind::WrongParamSize)) } } impl TryFrom for [u8; 32] { type Error = Error; fn try_from(value: Digest) -> Result { value .value() .try_into() .map_err(|_| Error::local_error(WrapperErrorKind::WrongParamSize)) } } // For the others, we build our own impl TryFrom for [u8; 48] { type Error = Error; fn try_from(value: Digest) -> Result { if value.value().len() != 48 { return Err(Error::local_error(WrapperErrorKind::WrongParamSize)); } let mut result = [0; 48]; result.copy_from_slice(value.value()); Ok(result) } } impl TryFrom for [u8; 64] { type Error = Error; fn try_from(value: Digest) -> Result { if value.value().len() != 64 { return Err(Error::local_error(WrapperErrorKind::WrongParamSize)); } let mut result = [0; 64]; result.copy_from_slice(value.value()); Ok(result) } } } pub mod ecc_parameter { buffer_type!( EccParameter, crate::tss2_esys::TPM2_MAX_ECC_KEY_BYTES as usize, TPM2B_ECC_PARAMETER ); } pub mod encrypted_secret { named_field_buffer_type!(EncryptedSecret, 256, TPM2B_ENCRYPTED_SECRET, secret); } pub mod id_object { named_field_buffer_type!(IdObject, 256, TPM2B_ID_OBJECT, credential); } pub mod initial_value { buffer_type!( InitialValue, crate::tss2_esys::TPM2_MAX_SYM_BLOCK_SIZE as usize, TPM2B_IV ); } pub mod max_buffer { use crate::tss2_esys::TPM2_MAX_DIGEST_BUFFER; buffer_type!(MaxBuffer, TPM2_MAX_DIGEST_BUFFER as usize, TPM2B_MAX_BUFFER); } pub mod max_nv_buffer { use crate::tss2_esys::TPM2_MAX_NV_BUFFER_SIZE; buffer_type!( MaxNvBuffer, TPM2_MAX_NV_BUFFER_SIZE as usize, TPM2B_MAX_NV_BUFFER ); } pub mod nonce { buffer_type!(Nonce, 64, TPM2B_NONCE); } pub mod private { use tss_esapi_sys::_PRIVATE; buffer_type!(Private, ::std::mem::size_of::<_PRIVATE>(), TPM2B_PRIVATE); } pub mod private_key_rsa { use crate::tss2_esys::TPM2_MAX_RSA_KEY_BYTES; // The maximum size is given in the spec as: // "RSA_PRIVATE_SIZE is a vendor specific value that can be (MAX_RSA_KEY_BYTES / 2) or // ((MAX_RSA_KEY_BYTES * 5) ./ 2. The larger size would only apply to keys that have fixedTPM parents. // The larger size was added in revision 01.53." // The TSS stack we use only accepts the smaller of the two sizes described above (for now). buffer_type!( PrivateKeyRsa, (TPM2_MAX_RSA_KEY_BYTES / 2) as usize, TPM2B_PRIVATE_KEY_RSA ); } pub mod private_vendor_specific { use crate::tss2_esys::TPM2_PRIVATE_VENDOR_SPECIFIC_BYTES; // The spec states the maximum size as: // "The value for PRIVATE_VENDOR_SPECIFIC_BYTES is determined by the vendor." // Not very helpful, but the TSS exposes a generic value that we can use. buffer_type!( PrivateVendorSpecific, TPM2_PRIVATE_VENDOR_SPECIFIC_BYTES as usize, TPM2B_PRIVATE_VENDOR_SPECIFIC ); } pub mod public_key_rsa { use crate::{interface_types::key_bits::RsaKeyBits, tss2_esys::TPM2_MAX_RSA_KEY_BYTES}; buffer_type!( PublicKeyRsa, TPM2_MAX_RSA_KEY_BYTES as usize, TPM2B_PUBLIC_KEY_RSA ); impl PublicKeyRsa { pub fn new_empty_with_size(rsa_key_bits: RsaKeyBits) -> Self { match rsa_key_bits { RsaKeyBits::Rsa1024 => PublicKeyRsa(vec![0u8; 128].into()), RsaKeyBits::Rsa2048 => PublicKeyRsa(vec![0u8; 256].into()), RsaKeyBits::Rsa3072 => PublicKeyRsa(vec![0u8; 384].into()), RsaKeyBits::Rsa4096 => PublicKeyRsa(vec![0u8; 512].into()), } } } impl TryFrom for [u8; 128] { type Error = Error; fn try_from(public_key_rsa: PublicKeyRsa) -> Result { if public_key_rsa.value().len() > 128 { return Err(Error::local_error(WrapperErrorKind::WrongParamSize)); } let mut value = [0u8; 128]; value.copy_from_slice(public_key_rsa.value()); Ok(value) } } impl TryFrom for [u8; 256] { type Error = Error; fn try_from(public_key_rsa: PublicKeyRsa) -> Result { if public_key_rsa.value().len() > 256 { return Err(Error::local_error(WrapperErrorKind::WrongParamSize)); } let mut value = [0u8; 256]; value.copy_from_slice(public_key_rsa.value()); Ok(value) } } impl TryFrom for [u8; 384] { type Error = Error; fn try_from(public_key_rsa: PublicKeyRsa) -> Result { if public_key_rsa.value().len() > 384 { return Err(Error::local_error(WrapperErrorKind::WrongParamSize)); } let mut value = [0u8; 384]; value.copy_from_slice(public_key_rsa.value()); Ok(value) } } impl TryFrom for [u8; 512] { type Error = Error; fn try_from(public_key_rsa: PublicKeyRsa) -> Result { if public_key_rsa.value().len() > 512 { return Err(Error::local_error(WrapperErrorKind::WrongParamSize)); } let mut value = [0u8; 512]; value.copy_from_slice(public_key_rsa.value()); Ok(value) } } } pub mod sensitive_data { buffer_type!( SensitiveData, ::std::mem::size_of::(), TPM2B_SENSITIVE_DATA ); } pub mod symmetric_key { use crate::tss2_esys::TPM2_MAX_SYM_KEY_BYTES; // The spec states the maximum size as: // "MAX_SYM_KEY_BYTES will be the larger of the largest symmetric key supported by the TPM and the // largest digest produced by any hashing algorithm implemented on the TPM" buffer_type!(SymmetricKey, TPM2_MAX_SYM_KEY_BYTES as usize, TPM2B_SYM_KEY); } pub mod timeout { buffer_type!(Timeout, 8, TPM2B_TIMEOUT); } tss-esapi-7.4.0/src/structures/capability_data.rs000064400000000000000000000140331046102023000202370ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ constants::CapabilityType, structures::{ AlgorithmPropertyList, CommandCodeAttributesList, CommandCodeList, EccCurveList, HandleList, PcrSelectionList, TaggedPcrPropertyList, TaggedTpmPropertyList, }, tss2_esys::{TPM2_CAP, TPM2_MAX_CAP_BUFFER, TPMS_CAPABILITY_DATA, TPMU_CAPABILITIES}, Error, Result, WrapperErrorKind, }; use log::error; use std::convert::{TryFrom, TryInto}; use std::mem::size_of; /// A representation of all the capabilites that can be associated /// with a TPM. /// /// # Details /// This corresponds to `TPMS_CAPABILITY_DATA` #[non_exhaustive] #[derive(Debug, Clone)] pub enum CapabilityData { Algorithms(AlgorithmPropertyList), Handles(HandleList), Commands(CommandCodeAttributesList), PpCommands(CommandCodeList), AuditCommands(CommandCodeList), AssignedPcr(PcrSelectionList), TpmProperties(TaggedTpmPropertyList), PcrProperties(TaggedPcrPropertyList), EccCurves(EccCurveList), // These are in the TPM TPMU_CAPABILITIES, but are not defined by esapi-2.4.1 // AuthPolicies(), // ActData(), } pub const fn max_cap_size() -> usize { (TPM2_MAX_CAP_BUFFER as usize - size_of::() - size_of::()) / size_of::() } impl From for TPMS_CAPABILITY_DATA { fn from(capability_data: CapabilityData) -> Self { match capability_data { CapabilityData::Algorithms(data) => TPMS_CAPABILITY_DATA { capability: CapabilityType::Algorithms.into(), data: TPMU_CAPABILITIES { algorithms: data.into(), }, }, CapabilityData::Handles(data) => TPMS_CAPABILITY_DATA { capability: CapabilityType::Handles.into(), data: TPMU_CAPABILITIES { handles: data.into(), }, }, CapabilityData::Commands(data) => TPMS_CAPABILITY_DATA { capability: CapabilityType::Command.into(), data: TPMU_CAPABILITIES { command: data.into(), }, }, CapabilityData::PpCommands(data) => TPMS_CAPABILITY_DATA { capability: CapabilityType::PpCommands.into(), data: TPMU_CAPABILITIES { ppCommands: data.into(), }, }, CapabilityData::AuditCommands(data) => TPMS_CAPABILITY_DATA { capability: CapabilityType::AuditCommands.into(), data: TPMU_CAPABILITIES { auditCommands: data.into(), }, }, CapabilityData::AssignedPcr(data) => TPMS_CAPABILITY_DATA { capability: CapabilityType::AssignedPcr.into(), data: TPMU_CAPABILITIES { assignedPCR: data.into(), }, }, CapabilityData::TpmProperties(data) => TPMS_CAPABILITY_DATA { capability: CapabilityType::TpmProperties.into(), data: TPMU_CAPABILITIES { tpmProperties: data.into(), }, }, CapabilityData::PcrProperties(data) => TPMS_CAPABILITY_DATA { capability: CapabilityType::PcrProperties.into(), data: TPMU_CAPABILITIES { pcrProperties: data.into(), }, }, CapabilityData::EccCurves(data) => TPMS_CAPABILITY_DATA { capability: CapabilityType::EccCurves.into(), data: TPMU_CAPABILITIES { eccCurves: data.into(), }, }, } } } impl TryFrom for CapabilityData { type Error = Error; fn try_from(tpms_capability_data: TPMS_CAPABILITY_DATA) -> Result { // SAFETY: This is a C union, and Rust wants us to make sure we're using the correct item. // These unsafe blocks are fine because we ensure the correct type is used. match CapabilityType::try_from(tpms_capability_data.capability)? { CapabilityType::Algorithms => Ok(CapabilityData::Algorithms( unsafe { tpms_capability_data.data.algorithms }.try_into()?, )), CapabilityType::Handles => Ok(CapabilityData::Handles( unsafe { tpms_capability_data.data.handles }.try_into()?, )), CapabilityType::Command => Ok(CapabilityData::Commands( unsafe { tpms_capability_data.data.command }.try_into()?, )), CapabilityType::PpCommands => Ok(CapabilityData::PpCommands( unsafe { tpms_capability_data.data.ppCommands }.try_into()?, )), CapabilityType::AuditCommands => Ok(CapabilityData::AuditCommands( unsafe { tpms_capability_data.data.auditCommands }.try_into()?, )), CapabilityType::AssignedPcr => Ok(CapabilityData::AssignedPcr( unsafe { tpms_capability_data.data.assignedPCR }.try_into()?, )), CapabilityType::TpmProperties => Ok(CapabilityData::TpmProperties( unsafe { tpms_capability_data.data.tpmProperties }.try_into()?, )), CapabilityType::PcrProperties => Ok(CapabilityData::PcrProperties( unsafe { tpms_capability_data.data.pcrProperties }.try_into()?, )), CapabilityType::EccCurves => Ok(CapabilityData::EccCurves( unsafe { tpms_capability_data.data.eccCurves }.try_into()?, )), CapabilityType::AuthPolicies => { error!("AuthPolicies capability type is currently not supported"); Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam)) } CapabilityType::Act => { error!("Act capability type is currently not supported"); Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam)) } } } } tss-esapi-7.4.0/src/structures/clock/clock_info.rs000064400000000000000000000030031046102023000203210ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{interface_types::YesNo, tss2_esys::TPMS_CLOCK_INFO, Error, Result}; use std::convert::TryFrom; /// Information related to the internal temporal /// state of the TPM. /// /// # Details /// Corresponds to `TPMS_CLOCK_INFO` #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct ClockInfo { clock: u64, reset_count: u32, restart_count: u32, safe: YesNo, } impl ClockInfo { /// Returns the clock value pub const fn clock(&self) -> u64 { self.clock } /// Returns the reset count value pub const fn reset_count(&self) -> u32 { self.reset_count } /// Returns the restart count value pub const fn restart_count(&self) -> u32 { self.restart_count } /// Returns safe pub fn safe(&self) -> bool { self.safe.into() } } impl TryFrom for ClockInfo { type Error = Error; fn try_from(tss: TPMS_CLOCK_INFO) -> Result { Ok(ClockInfo { clock: tss.clock, reset_count: tss.resetCount, restart_count: tss.restartCount, safe: YesNo::try_from(tss.safe)?, }) } } impl From for TPMS_CLOCK_INFO { fn from(native: ClockInfo) -> Self { TPMS_CLOCK_INFO { clock: native.clock, resetCount: native.reset_count, restartCount: native.restart_count, safe: native.safe.into(), } } } tss-esapi-7.4.0/src/structures/clock/mod.rs000064400000000000000000000002041046102023000167720ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 pub mod clock_info; pub mod time_info; tss-esapi-7.4.0/src/structures/clock/time_info.rs000064400000000000000000000022341046102023000201710ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{structures::ClockInfo, tss2_esys::TPMS_TIME_INFO, Error, Result}; use std::convert::{TryFrom, TryInto}; /// Structure holding the attestation for /// TPM2_GetTime() and TPM2_ReadClock(). /// /// # Details /// This corresponds to the TPMS_TIME_INFO #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct TimeInfo { time: u64, clock_info: ClockInfo, } impl TimeInfo { /// Returns the time pub const fn time(&self) -> u64 { self.time } /// Restursn the clock info. pub const fn clock_info(&self) -> &ClockInfo { &self.clock_info } } impl From for TPMS_TIME_INFO { fn from(time_info: TimeInfo) -> Self { TPMS_TIME_INFO { time: time_info.time, clockInfo: time_info.clock_info.into(), } } } impl TryFrom for TimeInfo { type Error = Error; fn try_from(tpms_time_info: TPMS_TIME_INFO) -> Result { Ok(TimeInfo { time: tpms_time_info.time, clock_info: tpms_time_info.clockInfo.try_into()?, }) } } tss-esapi-7.4.0/src/structures/creation.rs000064400000000000000000000046011046102023000167310ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ attributes::LocalityAttributes, constants::AlgorithmIdentifier, interface_types::algorithm::HashingAlgorithm, structures::{Data, Digest, Name, PcrSelectionList}, tss2_esys::{TPM2B_CREATION_DATA, TPMS_CREATION_DATA}, Error, Result, }; use std::convert::{TryFrom, TryInto}; #[derive(Debug, Clone)] pub struct CreationData { pcr_select: PcrSelectionList, pcr_digest: Digest, locality: LocalityAttributes, parent_name_alg: Option, parent_name: Name, parent_qualified_name: Name, outside_info: Data, } impl TryFrom for CreationData { type Error = Error; fn try_from(tss_creation_data: TPMS_CREATION_DATA) -> Result { Ok(CreationData { pcr_select: tss_creation_data.pcrSelect.try_into()?, pcr_digest: tss_creation_data.pcrDigest.try_into()?, locality: tss_creation_data.locality.into(), parent_name_alg: match AlgorithmIdentifier::try_from(tss_creation_data.parentNameAlg)? { AlgorithmIdentifier::Null => None, alg => Some(HashingAlgorithm::try_from(alg)?), }, parent_name: tss_creation_data.parentName.try_into()?, parent_qualified_name: tss_creation_data.parentQualifiedName.try_into()?, outside_info: tss_creation_data.outsideInfo.try_into()?, }) } } impl TryFrom for CreationData { type Error = Error; fn try_from(tss_creation_data_buffer: TPM2B_CREATION_DATA) -> Result { CreationData::try_from(tss_creation_data_buffer.creationData) } } impl From for TPMS_CREATION_DATA { fn from(creation_data: CreationData) -> Self { TPMS_CREATION_DATA { pcrSelect: creation_data.pcr_select.into(), pcrDigest: creation_data.pcr_digest.into(), locality: creation_data.locality.into(), parentNameAlg: match creation_data.parent_name_alg { None => AlgorithmIdentifier::Null.into(), Some(alg) => alg.into(), }, parentName: creation_data.parent_name.into(), parentQualifiedName: creation_data.parent_qualified_name.into(), outsideInfo: creation_data.outside_info.into(), } } } tss-esapi-7.4.0/src/structures/ecc/mod.rs000064400000000000000000000001541046102023000164350ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 pub mod point; tss-esapi-7.4.0/src/structures/ecc/point.rs000064400000000000000000000034171046102023000170140ustar 00000000000000use tss_esapi_sys::TPM2B_ECC_POINT; // Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{structures::EccParameter, tss2_esys::TPMS_ECC_POINT, Error, Result}; use std::convert::{TryFrom, TryInto}; /// Structure holding ecc point information /// /// # Details /// This corresponds to TPMS_ECC_POINT #[derive(Debug, Clone, PartialEq, Eq)] pub struct EccPoint { x: EccParameter, y: EccParameter, } impl EccPoint { /// Creates a new ecc point pub const fn new(x: EccParameter, y: EccParameter) -> Self { EccPoint { x, y } } /// Returns x value as an [EccParameter] reference. pub const fn x(&self) -> &EccParameter { &self.x } /// Returns y value as an [EccParameter] reference. pub const fn y(&self) -> &EccParameter { &self.y } } impl Default for EccPoint { fn default() -> Self { EccPoint::new(EccParameter::default(), EccParameter::default()) } } impl From for TPMS_ECC_POINT { fn from(ecc_point: EccPoint) -> Self { TPMS_ECC_POINT { x: ecc_point.x.into(), y: ecc_point.y.into(), } } } impl From for TPM2B_ECC_POINT { fn from(ecc_point: EccPoint) -> Self { let size = std::mem::size_of::() + ecc_point.x().len() + std::mem::size_of::() + ecc_point.y().len(); TPM2B_ECC_POINT { size: size as u16, point: ecc_point.into(), } } } impl TryFrom for EccPoint { type Error = Error; fn try_from(tpms_ecc_point: TPMS_ECC_POINT) -> Result { Ok(EccPoint { x: tpms_ecc_point.x.try_into()?, y: tpms_ecc_point.y.try_into()?, }) } } tss-esapi-7.4.0/src/structures/hash/agile.rs000064400000000000000000000047571046102023000171450ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::interface_types::algorithm::HashingAlgorithm; use crate::structures::Digest; use crate::tss2_esys::{TPMT_HA, TPMU_HA}; use crate::{Error, Result, WrapperErrorKind}; use std::convert::{TryFrom, TryInto}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct HashAgile { algorithm: HashingAlgorithm, digest: Digest, } impl HashAgile { pub fn new(algorithm: HashingAlgorithm, digest: Digest) -> Self { HashAgile { algorithm, digest } } } impl TryFrom for TPMT_HA { type Error = Error; fn try_from(ha: HashAgile) -> Result { let algid: crate::tss2_esys::TPM2_ALG_ID = ha.algorithm.into(); let digest_val = ha.digest; Ok(TPMT_HA { hashAlg: algid, digest: match ha.algorithm { HashingAlgorithm::Sha1 => TPMU_HA { sha1: digest_val.try_into()?, }, HashingAlgorithm::Sha256 => TPMU_HA { sha256: digest_val.try_into()?, }, HashingAlgorithm::Sha384 => TPMU_HA { sha384: digest_val.try_into()?, }, HashingAlgorithm::Sha512 => TPMU_HA { sha512: digest_val.try_into()?, }, HashingAlgorithm::Sm3_256 => TPMU_HA { sm3_256: digest_val.try_into()?, }, _ => return Err(Error::local_error(WrapperErrorKind::UnsupportedParam)), }, }) } } impl TryFrom for HashAgile { type Error = Error; fn try_from(tpmt_ha: TPMT_HA) -> Result { let algorithm = HashingAlgorithm::try_from(tpmt_ha.hashAlg)?; Ok(HashAgile { algorithm, digest: match algorithm { HashingAlgorithm::Sha1 => unsafe { tpmt_ha.digest.sha1 }.as_ref().try_into()?, HashingAlgorithm::Sha256 => unsafe { tpmt_ha.digest.sha256 }.as_ref().try_into()?, HashingAlgorithm::Sha384 => unsafe { tpmt_ha.digest.sha384 }.as_ref().try_into()?, HashingAlgorithm::Sha512 => unsafe { tpmt_ha.digest.sha512 }.as_ref().try_into()?, HashingAlgorithm::Sm3_256 => { unsafe { tpmt_ha.digest.sm3_256 }.as_ref().try_into()? } _ => return Err(Error::local_error(WrapperErrorKind::WrongValueFromTpm)), }, }) } } tss-esapi-7.4.0/src/structures/hash/mod.rs000064400000000000000000000001541046102023000166260ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 pub mod agile; tss-esapi-7.4.0/src/structures/lists/algorithm_property.rs000064400000000000000000000074231046102023000222220ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ constants::AlgorithmIdentifier, structures::AlgorithmProperty, tss2_esys::{TPML_ALG_PROPERTY, TPMS_ALG_PROPERTY}, Error, Result, WrapperErrorKind, }; use log::error; use std::{convert::TryFrom, iter::IntoIterator, ops::Deref}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct AlgorithmPropertyList { algorithm_properties: Vec, } impl AlgorithmPropertyList { pub const MAX_SIZE: usize = Self::calculate_max_size(); /// Finds an [AlgorithmProperty] in the list that matches /// the provided ´algorithm_identifier´. pub fn find(&self, algorithm_identifier: AlgorithmIdentifier) -> Option<&AlgorithmProperty> { self.algorithm_properties .iter() .find(|ap| ap.algorithm_identifier() == algorithm_identifier) } /// Private function that calculates the maximum number /// elements allowed in internal storage. const fn calculate_max_size() -> usize { crate::structures::capability_data::max_cap_size::() } } impl Deref for AlgorithmPropertyList { type Target = Vec; fn deref(&self) -> &Self::Target { &self.algorithm_properties } } impl AsRef<[AlgorithmProperty]> for AlgorithmPropertyList { fn as_ref(&self) -> &[AlgorithmProperty] { self.algorithm_properties.as_slice() } } impl IntoIterator for AlgorithmPropertyList { type Item = AlgorithmProperty; type IntoIter = std::vec::IntoIter; fn into_iter(self) -> Self::IntoIter { self.algorithm_properties.into_iter() } } impl TryFrom> for AlgorithmPropertyList { type Error = Error; fn try_from(algorithm_properties: Vec) -> Result { if algorithm_properties.len() > Self::MAX_SIZE { error!("Failed to convert Vec into AlgorithmPropertyList, to many items (> {})", Self::MAX_SIZE); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } Ok(AlgorithmPropertyList { algorithm_properties, }) } } impl From for Vec { fn from(algorithm_property_list: AlgorithmPropertyList) -> Self { algorithm_property_list.algorithm_properties } } impl TryFrom for AlgorithmPropertyList { type Error = Error; fn try_from(tpml_alg_property: TPML_ALG_PROPERTY) -> Result { let count = usize::try_from(tpml_alg_property.count).map_err(|e| { error!("Failed to parse count in TPML_ALG_PROPERTY as usize: {}", e); Error::local_error(WrapperErrorKind::InvalidParam) })?; if count > Self::MAX_SIZE { error!( "Invalid size value in TPML_ALG_PROPERTY (> {})", Self::MAX_SIZE, ); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } tpml_alg_property.algProperties[..count] .iter() .map(|&tp| AlgorithmProperty::try_from(tp)) .collect::>>() .map(|algorithm_properties| AlgorithmPropertyList { algorithm_properties, }) } } impl From for TPML_ALG_PROPERTY { fn from(algorithm_property_list: AlgorithmPropertyList) -> Self { let mut tpml_alg_property: TPML_ALG_PROPERTY = Default::default(); for algorithm_property in algorithm_property_list { tpml_alg_property.algProperties[tpml_alg_property.count as usize] = algorithm_property.into(); tpml_alg_property.count += 1; } tpml_alg_property } } tss-esapi-7.4.0/src/structures/lists/command_code.rs000064400000000000000000000063401046102023000206750ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ constants::CommandCode, tss2_esys::{TPM2_MAX_CAP_CC, TPML_CC}, Error, Result, WrapperErrorKind, }; use log::error; use std::{convert::TryFrom, ops::Deref}; /// A list of command codes. #[derive(Debug, Clone, Default)] pub struct CommandCodeList { command_codes: Vec, } impl CommandCodeList { pub const MAX_SIZE: usize = Self::calculate_max_size(); /// Creates a new CommandCodeList pub const fn new() -> Self { CommandCodeList { command_codes: Vec::new(), } } /// Adds a command code to the command code list. pub fn add(&mut self, command_code: CommandCode) -> Result<()> { if self.command_codes.len() + 1 > CommandCodeList::MAX_SIZE { error!( "Adding command code to list will make the list exceeded its maximum count(> {})", CommandCodeList::MAX_SIZE ); return Err(Error::local_error(WrapperErrorKind::WrongParamSize)); } self.command_codes.push(command_code); Ok(()) } /// Returns the inner type. pub fn into_inner(self) -> Vec { self.command_codes } /// Private function that calculates the maximum number /// elements allowed in internal storage. const fn calculate_max_size() -> usize { TPM2_MAX_CAP_CC as usize } } impl TryFrom for CommandCodeList { type Error = Error; fn try_from(tpml_cc: TPML_CC) -> Result { let command_code_count = tpml_cc.count as usize; if command_code_count > Self::MAX_SIZE { error!("Error: Invalid TPML_CC count(> {})", Self::MAX_SIZE); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } tpml_cc.commandCodes[..command_code_count] .iter() .map(|&cc| CommandCode::try_from(cc)) .collect::>>() .map(|command_codes| CommandCodeList { command_codes }) } } impl From for TPML_CC { fn from(command_code_list: CommandCodeList) -> Self { let mut tpml_cc = TPML_CC::default(); for cc in command_code_list.command_codes { tpml_cc.commandCodes[tpml_cc.count as usize] = cc.into(); tpml_cc.count += 1; } tpml_cc } } impl TryFrom> for CommandCodeList { type Error = Error; fn try_from(command_codes: Vec) -> Result { if command_codes.len() > Self::MAX_SIZE { error!("Error: Invalid TPML_CC count(> {})", Self::MAX_SIZE); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } Ok(CommandCodeList { command_codes }) } } impl From for Vec { fn from(command_code_list: CommandCodeList) -> Self { command_code_list.command_codes } } impl AsRef<[CommandCode]> for CommandCodeList { fn as_ref(&self) -> &[CommandCode] { self.command_codes.as_slice() } } impl Deref for CommandCodeList { type Target = Vec; fn deref(&self) -> &Self::Target { &self.command_codes } } tss-esapi-7.4.0/src/structures/lists/command_code_attributes.rs000064400000000000000000000070501046102023000231420ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ attributes::CommandCodeAttributes, tss2_esys::{TPMA_CC, TPML_CCA}, Error, Result, WrapperErrorKind, }; use log::error; use std::{convert::TryFrom, iter::IntoIterator, ops::Deref}; /// A structure holding a list of command code attributes. /// /// # Details /// This corresponds to the TPML_CCA strucutre. #[derive(Debug, Clone, PartialEq, Eq)] pub struct CommandCodeAttributesList { command_code_attributes: Vec, } impl CommandCodeAttributesList { pub const MAX_SIZE: usize = Self::calculate_max_size(); /// Finds a command code attributes with a specific /// command index pub fn find(&self, command_index: u16) -> Option<&CommandCodeAttributes> { self.command_code_attributes .iter() .find(|cca| cca.command_index() == command_index) } /// Private function that calculates the maximum number /// elements allowed in internal storage. const fn calculate_max_size() -> usize { crate::structures::capability_data::max_cap_size::() } } impl Deref for CommandCodeAttributesList { type Target = Vec; fn deref(&self) -> &Self::Target { &self.command_code_attributes } } impl AsRef<[CommandCodeAttributes]> for CommandCodeAttributesList { fn as_ref(&self) -> &[CommandCodeAttributes] { self.command_code_attributes.as_slice() } } impl TryFrom> for CommandCodeAttributesList { type Error = Error; fn try_from(command_code_attributes: Vec) -> Result { if command_code_attributes.len() > Self::MAX_SIZE { error!("Failed to convert Vec into CommandCodeAttributesList, to many items (> {})", Self::MAX_SIZE); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } Ok(CommandCodeAttributesList { command_code_attributes, }) } } impl IntoIterator for CommandCodeAttributesList { type Item = CommandCodeAttributes; type IntoIter = std::vec::IntoIter; fn into_iter(self) -> Self::IntoIter { self.command_code_attributes.into_iter() } } impl TryFrom for CommandCodeAttributesList { type Error = Error; fn try_from(tpml_cca: TPML_CCA) -> Result { let count = usize::try_from(tpml_cca.count).map_err(|e| { error!("Failed to parse count in TPML_CCA as usize: {}", e); Error::local_error(WrapperErrorKind::InvalidParam) })?; if count > Self::MAX_SIZE { error!("Invalid size value in TPML_CCA (> {})", Self::MAX_SIZE,); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } tpml_cca.commandAttributes[..count] .iter() .map(|&tp| CommandCodeAttributes::try_from(tp)) .collect::>>() .map(|command_code_attributes| CommandCodeAttributesList { command_code_attributes, }) } } impl From for TPML_CCA { fn from(command_code_attributes_list: CommandCodeAttributesList) -> Self { let mut tpml_cca: TPML_CCA = Default::default(); for command_code_attributes in command_code_attributes_list { tpml_cca.commandAttributes[tpml_cca.count as usize] = command_code_attributes.into(); tpml_cca.count += 1; } tpml_cca } } tss-esapi-7.4.0/src/structures/lists/digest.rs000064400000000000000000000047621046102023000175520ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::structures::Digest; use crate::tss2_esys::TPML_DIGEST; use crate::{Error, Result, WrapperErrorKind}; use log::error; use std::convert::TryFrom; #[derive(Debug, Clone, Default)] pub struct DigestList { digests: Vec, } impl DigestList { pub const MAX_SIZE: usize = 8; /// Creates a nnew empty DigestList pub const fn new() -> Self { DigestList { digests: Vec::new(), } } /// Returns the values in the digest list. pub fn value(&self) -> &[Digest] { &self.digests } /// Returns the number of digests in the digestlist pub fn len(&self) -> usize { self.digests.len() } /// Indicates if the digest list contains any digests. pub fn is_empty(&self) -> bool { self.digests.is_empty() } /// Adds a new digest to the digest list. pub fn add(&mut self, dig: Digest) -> Result<()> { if self.digests.len() >= DigestList::MAX_SIZE { error!("Exceeded maximum count(> {})", DigestList::MAX_SIZE); return Err(Error::local_error(WrapperErrorKind::WrongParamSize)); } self.digests.push(dig); Ok(()) } } impl TryFrom for DigestList { type Error = Error; fn try_from(tpml_digest: TPML_DIGEST) -> Result { let digests_count = tpml_digest.count as usize; if digests_count > DigestList::MAX_SIZE { error!("Invalid TPML_DIGEST count(> {})", DigestList::MAX_SIZE); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } tpml_digest.digests[..digests_count] .iter() .map(|&tss_digest| Digest::try_from(tss_digest)) .collect::>>() .map(|digests| DigestList { digests }) } } impl TryFrom for TPML_DIGEST { type Error = Error; fn try_from(digest_list: DigestList) -> Result { if digest_list.digests.len() > DigestList::MAX_SIZE { error!("Invalid digest list size(> {})", DigestList::MAX_SIZE); return Err(Error::local_error(WrapperErrorKind::WrongParamSize)); } let mut tss_digest_list: TPML_DIGEST = Default::default(); for digest in digest_list.digests { tss_digest_list.digests[tss_digest_list.count as usize] = digest.into(); tss_digest_list.count += 1; } Ok(tss_digest_list) } } tss-esapi-7.4.0/src/structures/lists/digest_values.rs000064400000000000000000000024061046102023000211220ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::interface_types::algorithm::HashingAlgorithm; use crate::structures::Digest; use crate::structures::HashAgile; use crate::tss2_esys::TPML_DIGEST_VALUES; use crate::{Error, Result}; use std::collections::HashMap; use std::convert::{TryFrom, TryInto}; #[derive(Debug, Clone, Default)] pub struct DigestValues { digests: HashMap, } impl DigestValues { pub fn new() -> Self { DigestValues { digests: HashMap::new(), } } pub fn set(&mut self, alg: HashingAlgorithm, dig: Digest) { let _ = self.digests.insert(alg, dig); } } impl TryFrom for TPML_DIGEST_VALUES { type Error = Error; fn try_from(digest_values: DigestValues) -> Result { let mut digest_values = digest_values; let mut tss_digest_values: TPML_DIGEST_VALUES = Default::default(); for (digest_hash, digest_val) in digest_values.digests.drain() { let ha = HashAgile::new(digest_hash, digest_val); tss_digest_values.digests[tss_digest_values.count as usize] = ha.try_into()?; tss_digest_values.count += 1; } Ok(tss_digest_values) } } tss-esapi-7.4.0/src/structures/lists/ecc_curves.rs000064400000000000000000000065711046102023000204140ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::constants::ecc::EccCurveIdentifier; use crate::tss2_esys::{TPM2_ECC_CURVE, TPML_ECC_CURVE}; use crate::{Error, Result, WrapperErrorKind}; use log::error; use std::convert::TryFrom; use std::ops::Deref; /// A list of ECC curves /// /// # Details /// This corresponds to `TPML_ECC_CURVE`. #[derive(Debug, Clone, Default, PartialEq, Eq)] pub struct EccCurveList { ecc_curves: Vec, } impl EccCurveList { pub const MAX_SIZE: usize = Self::calculate_max_size(); pub fn new() -> Self { EccCurveList { ecc_curves: Vec::new(), } } /// Adds an ECC curve to the list of curves. pub fn add(&mut self, ecc_curve: EccCurveIdentifier) -> Result<()> { if self.ecc_curves.len() + 1 > EccCurveList::MAX_SIZE { error!( "Adding ECC curve to list will make the list exceeded its maximum count(> {})", EccCurveList::MAX_SIZE ); return Err(Error::local_error(WrapperErrorKind::WrongParamSize)); } self.ecc_curves.push(ecc_curve); Ok(()) } /// Returns the inner type. pub fn into_inner(self) -> Vec { self.ecc_curves } /// Private function that calculates the maximum number /// elements allowed in internal storage. const fn calculate_max_size() -> usize { crate::structures::capability_data::max_cap_size::() } } impl TryFrom for EccCurveList { type Error = Error; fn try_from(ecc_curves: TPML_ECC_CURVE) -> Result { let ecc_curve_count = ecc_curves.count as usize; if ecc_curve_count > Self::MAX_SIZE { error!("Error: Invalid TPML_ECC_CURVE count(> {})", Self::MAX_SIZE); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } ecc_curves.eccCurves[..ecc_curve_count] .iter() .map(|&cc| EccCurveIdentifier::try_from(cc)) .collect::>>() .map(|ecc_curves| EccCurveList { ecc_curves }) } } impl From for TPML_ECC_CURVE { fn from(ecc_curves: EccCurveList) -> Self { let mut tss_ecc_curves: TPML_ECC_CURVE = Default::default(); for ecc_curve in ecc_curves.ecc_curves { tss_ecc_curves.eccCurves[tss_ecc_curves.count as usize] = ecc_curve.into(); tss_ecc_curves.count += 1; } tss_ecc_curves } } impl TryFrom> for EccCurveList { type Error = Error; fn try_from(ecc_curves: Vec) -> Result { if ecc_curves.len() > Self::MAX_SIZE { error!("Error: Invalid TPML_ECC_CURVE count(> {})", Self::MAX_SIZE); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } Ok(EccCurveList { ecc_curves }) } } impl From for Vec { fn from(ecc_curve_list: EccCurveList) -> Self { ecc_curve_list.ecc_curves } } impl AsRef<[EccCurveIdentifier]> for EccCurveList { fn as_ref(&self) -> &[EccCurveIdentifier] { self.ecc_curves.as_slice() } } impl Deref for EccCurveList { type Target = Vec; fn deref(&self) -> &Self::Target { &self.ecc_curves } } tss-esapi-7.4.0/src/structures/lists/handles.rs000064400000000000000000000061501046102023000177020ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::handles::TpmHandle; use crate::tss2_esys::{TPM2_HANDLE, TPML_HANDLE}; use crate::{Error, Result, WrapperErrorKind}; use log::error; use std::convert::TryFrom; use std::ops::Deref; /// A list of TPM handles /// /// # Details /// This corresponds to `TPML_HANDLE`. #[derive(Debug, Clone, Default, PartialEq, Eq)] pub struct HandleList { handles: Vec, } impl HandleList { pub const MAX_SIZE: usize = Self::calculate_max_size(); pub fn new() -> Self { HandleList { handles: Vec::new(), } } /// Adds a handle to the current list of handles. pub fn add(&mut self, handle: TpmHandle) -> Result<()> { if self.handles.len() + 1 > HandleList::MAX_SIZE { error!( "Adding TPM handle to list will make the list exceeded its maximum count(> {})", HandleList::MAX_SIZE ); return Err(Error::local_error(WrapperErrorKind::WrongParamSize)); } self.handles.push(handle); Ok(()) } /// Returns the inner type. pub fn into_inner(self) -> Vec { self.handles } /// Private function that calculates the maximum number /// elements allowed in internal storage. const fn calculate_max_size() -> usize { crate::structures::capability_data::max_cap_size::() } } impl TryFrom for HandleList { type Error = Error; fn try_from(handles: TPML_HANDLE) -> Result { let handle_count = handles.count as usize; if handle_count > Self::MAX_SIZE { error!("Error: Invalid TPML_HANDLE count(> {})", Self::MAX_SIZE); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } handles.handle[..handle_count] .iter() .map(|&cc| TpmHandle::try_from(cc)) .collect::>>() .map(|handles| HandleList { handles }) } } impl From for TPML_HANDLE { fn from(handles: HandleList) -> Self { let mut tss_handles: TPML_HANDLE = Default::default(); for handle in handles.handles { tss_handles.handle[tss_handles.count as usize] = handle.into(); tss_handles.count += 1; } tss_handles } } impl TryFrom> for HandleList { type Error = Error; fn try_from(handles: Vec) -> Result { if handles.len() > Self::MAX_SIZE { error!("Error: Invalid TPML_HANDLE count(> {})", Self::MAX_SIZE); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } Ok(HandleList { handles }) } } impl From for Vec { fn from(handle_list: HandleList) -> Self { handle_list.handles } } impl AsRef<[TpmHandle]> for HandleList { fn as_ref(&self) -> &[TpmHandle] { self.handles.as_slice() } } impl Deref for HandleList { type Target = Vec; fn deref(&self) -> &Self::Target { &self.handles } } tss-esapi-7.4.0/src/structures/lists/mod.rs000064400000000000000000000005151046102023000170420ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 pub mod algorithm_property; pub mod command_code; pub mod command_code_attributes; pub mod digest; pub mod digest_values; pub mod ecc_curves; pub mod handles; pub mod pcr_selection; pub mod tagged_pcr_property; pub mod tagged_tpm_property; tss-esapi-7.4.0/src/structures/lists/pcr_selection.rs000064400000000000000000000155611046102023000211230ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::interface_types::algorithm::HashingAlgorithm; use crate::structures::{PcrSelectSize, PcrSelection, PcrSlot}; use crate::tss2_esys::TPML_PCR_SELECTION; use crate::{Error, Result, WrapperErrorKind}; use log::error; use std::collections::HashMap; use std::convert::TryFrom; /// A struct representing a pcr selection list. This /// corresponds to the TSS TPML_PCR_SELECTION. #[derive(Debug, Clone, PartialEq, Eq, Default)] pub struct PcrSelectionList { items: Vec, } impl PcrSelectionList { pub const MAX_SIZE: usize = 16; /// Function for retrieiving the number of banks in the selection pub fn len(&self) -> usize { self.items.len() } /// Returns true if the selection is empty. pub fn is_empty(&self) -> bool { self.items.is_empty() } /// Gets the selections pub fn get_selections(&self) -> &[PcrSelection] { &self.items } /// Subtracts other from self pub fn subtract(&mut self, other: &Self) -> Result<()> { if self == other { self.items.clear(); return Ok(()); } if self.is_empty() { error!("Cannot remove items that does not exist"); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } for other_pcr_selection in other.get_selections() { self.remove_selection(other_pcr_selection)?; } self.remove_empty_selections(); Ok(()) } /// Function for retrieving the PcrSelectionList from Option /// /// This returns an empty list if None is passed pub fn list_from_option(pcr_list: Option) -> PcrSelectionList { pcr_list.unwrap_or_default() } /// Private methods for removing pcr selections that are empty. fn remove_empty_selections(&mut self) { self.items.retain(|v| !v.is_empty()); } /// Private method for removing the items defined in a [PcrSelection] /// from the data in the [PcrSelectionList]. fn remove_selection(&mut self, pcr_selection: &PcrSelection) -> Result<()> { pcr_selection.selected().iter().try_for_each(|&pcr_slot| { self.items .iter_mut() .find(|existing_pcr_selection| { existing_pcr_selection.hashing_algorithm() == pcr_selection.hashing_algorithm() && existing_pcr_selection.is_selected(pcr_slot) }) .ok_or_else(|| { error!("Cannot remove items from a selection that does not exists"); Error::local_error(WrapperErrorKind::InvalidParam) }) .and_then(|existing_pcr_selection| existing_pcr_selection.deselect_exact(pcr_slot)) }) } /// Get a builder for this structure pub fn builder() -> PcrSelectionListBuilder { PcrSelectionListBuilder::new() } } impl From for TPML_PCR_SELECTION { fn from(pcr_selections: PcrSelectionList) -> Self { let mut tss_pcr_selection_list: TPML_PCR_SELECTION = Default::default(); for pcr_selection in pcr_selections.items { tss_pcr_selection_list.pcrSelections[tss_pcr_selection_list.count as usize] = pcr_selection.into(); tss_pcr_selection_list.count += 1; } tss_pcr_selection_list } } impl TryFrom for PcrSelectionList { type Error = Error; fn try_from(tpml_pcr_selection: TPML_PCR_SELECTION) -> Result { let size = tpml_pcr_selection.count as usize; if size > PcrSelectionList::MAX_SIZE { error!( "Invalid size value in TPML_PCR_SELECTION (> {})", PcrSelectionList::MAX_SIZE ); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } let mut items = Vec::::with_capacity(size); // Loop over available selections for tpms_pcr_selection in tpml_pcr_selection.pcrSelections[..size].iter() { // Parse pcr selection. let parsed_pcr_selection = PcrSelection::try_from(*tpms_pcr_selection)?; items.push(parsed_pcr_selection); } Ok(PcrSelectionList { items }) } } /// A builder for the PcrSelectionList struct. #[derive(Debug, Default)] pub struct PcrSelectionListBuilder { size_of_select: Option, items: HashMap>, } impl PcrSelectionListBuilder { pub fn new() -> Self { PcrSelectionListBuilder { size_of_select: None, items: Default::default(), } } /// Set the size of the pcr selection(sizeofSelect) /// /// # Arguments /// size_of_select -- The size that will be used for all selections(sizeofSelect). pub fn with_size_of_select(mut self, size_of_select: PcrSelectSize) -> Self { self.size_of_select = Some(size_of_select); self } /// Adds a selection associated with a specific HashingAlgorithm. /// /// This function will not overwrite the values already associated /// with a specific HashingAlgorithm only update. /// /// # Arguments /// hash_algorithm -- The HashingAlgorithm associated with the pcr selection /// pcr_slots -- The PCR slots in the selection. pub fn with_selection( mut self, hash_algorithm: HashingAlgorithm, pcr_slots: &[PcrSlot], ) -> Self { // let selected_pcr_slots: BitFlags = pcr_slots.iter().cloned().collect(); match self.items.get_mut(&hash_algorithm) { Some(previously_selected_pcr_slots) => { // *previously_selected_pcr_slots |= selected_pcr_slots; previously_selected_pcr_slots.extend_from_slice(pcr_slots); } None => { let _ = self.items.insert(hash_algorithm, pcr_slots.to_vec()); } } self } /// Builds a PcrSelections with the values that have been /// provided. /// /// If no size of select have been provided then it will /// be defaulted to to the most suitable with regard to TPM2_PCR_SELECT_MAX. /// This may not be the correct size for /// the current platform. The correct values can be obtained /// by querying the tpm for its capabilities. pub fn build(self) -> Result { let size_of_select = self.size_of_select.unwrap_or_default(); self.items .iter() .try_fold(Vec::::new(), |mut acc, (&k, v)| { PcrSelection::create(k, size_of_select, v.as_slice()).map(|pcr_select| { acc.push(pcr_select); acc }) }) .map(|items| PcrSelectionList { items }) } } tss-esapi-7.4.0/src/structures/lists/tagged_pcr_property.rs000064400000000000000000000105071046102023000223300ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ constants::PcrPropertyTag, structures::{PcrSlot, TaggedPcrSelect}, tss2_esys::{TPML_TAGGED_PCR_PROPERTY, TPMS_TAGGED_PCR_SELECT}, Error, Result, WrapperErrorKind, }; use log::error; use std::{convert::TryFrom, iter::IntoIterator, ops::Deref}; /// A structure holding a list of tagged pcr properties. /// /// # Details /// This corresponds to the TPML_TAGGED_PCR_PROPERTY structure. #[derive(Debug, Clone, PartialEq, Eq)] pub struct TaggedPcrPropertyList { tagged_pcr_properties: Vec, } impl TaggedPcrPropertyList { pub const MAX_SIZE: usize = Self::calculate_max_size(); /// Finds the first [TaggedPcrSelect] in the list that matches the provided `pcr_property_tag`. pub fn find(&self, pcr_property_tag: PcrPropertyTag) -> Option<&TaggedPcrSelect> { self.tagged_pcr_properties .iter() .find(|tps| tps.pcr_property_tag() == pcr_property_tag) } /// Returns a collection [TaggedPcrSelect] references in which each referenced items /// has the specified [PcrSlot] selected. pub fn find_pcr_slot(&self, pcr_slot: PcrSlot) -> Vec<&TaggedPcrSelect> { self.tagged_pcr_properties .iter() .fold(Vec::<&TaggedPcrSelect>::new(), |mut acc, tps| { if tps.selected_pcrs().iter().any(|&ps| ps == pcr_slot) { acc.push(tps); } acc }) } /// Private function that calculates the maximum number /// elements allowed in internal storage. const fn calculate_max_size() -> usize { crate::structures::capability_data::max_cap_size::() } } impl Deref for TaggedPcrPropertyList { type Target = Vec; fn deref(&self) -> &Self::Target { &self.tagged_pcr_properties } } impl AsRef<[TaggedPcrSelect]> for TaggedPcrPropertyList { fn as_ref(&self) -> &[TaggedPcrSelect] { self.tagged_pcr_properties.as_slice() } } impl TryFrom> for TaggedPcrPropertyList { type Error = Error; fn try_from(tagged_pcr_properties: Vec) -> Result { if tagged_pcr_properties.len() > Self::MAX_SIZE { error!("Failed to convert Vec into TaggedPcrPropertyList, to many items (> {})", Self::MAX_SIZE); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } Ok(TaggedPcrPropertyList { tagged_pcr_properties, }) } } impl IntoIterator for TaggedPcrPropertyList { type Item = TaggedPcrSelect; type IntoIter = std::vec::IntoIter; fn into_iter(self) -> Self::IntoIter { self.tagged_pcr_properties.into_iter() } } impl TryFrom for TaggedPcrPropertyList { type Error = Error; fn try_from(tpml_tagged_pcr_property: TPML_TAGGED_PCR_PROPERTY) -> Result { let count = usize::try_from(tpml_tagged_pcr_property.count).map_err(|e| { error!( "Failed to parse count in TPML_TAGGED_PCR_PROPERTY as usize: {}", e ); Error::local_error(WrapperErrorKind::InvalidParam) })?; if count > Self::MAX_SIZE { error!( "Invalid size value in TPML_TAGGED_PCR_PROPERTY (> {})", Self::MAX_SIZE, ); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } tpml_tagged_pcr_property.pcrProperty[..count] .iter() .map(|&tp| TaggedPcrSelect::try_from(tp)) .collect::>>() .map(|tagged_pcr_properties| TaggedPcrPropertyList { tagged_pcr_properties, }) } } impl From for TPML_TAGGED_PCR_PROPERTY { fn from(tagged_pcr_property_list: TaggedPcrPropertyList) -> Self { let mut tpml_tagged_pcr_property = TPML_TAGGED_PCR_PROPERTY::default(); for tagged_pcr_select in tagged_pcr_property_list { tpml_tagged_pcr_property.pcrProperty[tpml_tagged_pcr_property.count as usize] = tagged_pcr_select.into(); tpml_tagged_pcr_property.count += 1; } tpml_tagged_pcr_property } } tss-esapi-7.4.0/src/structures/lists/tagged_tpm_property.rs000064400000000000000000000074311046102023000223460ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ constants::PropertyTag, structures::TaggedProperty, tss2_esys::{TPML_TAGGED_TPM_PROPERTY, TPMS_TAGGED_PROPERTY}, Error, Result, WrapperErrorKind, }; use log::error; use std::{convert::TryFrom, iter::IntoIterator, ops::Deref}; /// A structure holding a list of tagged tpm properties. /// /// # Details /// This corresponds to the TPML_TAGGED_TPM_PROPERTY strucutre. #[derive(Debug, Clone, PartialEq, Eq)] pub struct TaggedTpmPropertyList { tagged_tpm_properties: Vec, } impl TaggedTpmPropertyList { pub const MAX_SIZE: usize = Self::calculate_max_size(); /// Finds the first [TaggedProperty] in the list matching the provided `property_tag`. pub fn find(&self, property_tag: PropertyTag) -> Option<&TaggedProperty> { self.tagged_tpm_properties .iter() .find(|tp| tp.property() == property_tag) } /// Private function that calculates the maximum number /// elements allowed in internal storage. const fn calculate_max_size() -> usize { crate::structures::capability_data::max_cap_size::() } } impl Deref for TaggedTpmPropertyList { type Target = Vec; fn deref(&self) -> &Self::Target { &self.tagged_tpm_properties } } impl AsRef<[TaggedProperty]> for TaggedTpmPropertyList { fn as_ref(&self) -> &[TaggedProperty] { self.tagged_tpm_properties.as_slice() } } impl TryFrom> for TaggedTpmPropertyList { type Error = Error; fn try_from(tagged_tpm_properties: Vec) -> Result { if tagged_tpm_properties.len() > Self::MAX_SIZE { error!("Failed to convert Vec into TaggedTpmPropertyList, to many items (> {})", Self::MAX_SIZE); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } Ok(TaggedTpmPropertyList { tagged_tpm_properties, }) } } impl IntoIterator for TaggedTpmPropertyList { type Item = TaggedProperty; type IntoIter = std::vec::IntoIter; fn into_iter(self) -> Self::IntoIter { self.tagged_tpm_properties.into_iter() } } impl TryFrom for TaggedTpmPropertyList { type Error = Error; fn try_from(tpml_tagged_tpm_property: TPML_TAGGED_TPM_PROPERTY) -> Result { let count = usize::try_from(tpml_tagged_tpm_property.count).map_err(|e| { error!( "Failed to parse count in TPML_TAGGED_TPM_PROPERTY as usize: {}", e ); Error::local_error(WrapperErrorKind::InvalidParam) })?; if count > Self::MAX_SIZE { error!( "Invalid size value in TPML_TAGGED_TPM_PROPERTY (> {})", Self::MAX_SIZE, ); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } tpml_tagged_tpm_property.tpmProperty[..count] .iter() .map(|&tp| TaggedProperty::try_from(tp)) .collect::>>() .map(|tagged_tpm_properties| TaggedTpmPropertyList { tagged_tpm_properties, }) } } impl From for TPML_TAGGED_TPM_PROPERTY { fn from(tagged_tpm_property_list: TaggedTpmPropertyList) -> Self { let mut tpml_tagged_tpm_property: TPML_TAGGED_TPM_PROPERTY = Default::default(); for tagged_property in tagged_tpm_property_list { tpml_tagged_tpm_property.tpmProperty[tpml_tagged_tpm_property.count as usize] = tagged_property.into(); tpml_tagged_tpm_property.count += 1; } tpml_tagged_tpm_property } } tss-esapi-7.4.0/src/structures/mod.rs000064400000000000000000000154641046102023000157150ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 /// The structures module attempts as far as possible to /// reflect the specifications way of defining structures /// see: /// /// Trusted Platform Module Library /// Part 2: Structures /// Family “2.0” /// Level 00 Revision 01.59 /// November 8, 2019 /// Published /// /// Chapter 10: Structure Definitions ///////////////////////////////////////////////////////// /// The capabilitydata section ///////////////////////////////////////////////////////// mod capability_data; pub use self::capability_data::CapabilityData; ///////////////////////////////////////////////////////// /// The names section ///////////////////////////////////////////////////////// mod names; pub use names::name::Name; ///////////////////////////////////////////////////////// /// The result section ///////////////////////////////////////////////////////// mod result; pub use result::CreateKeyResult; pub use result::CreatePrimaryKeyResult; ///////////////////////////////////////////////////////// /// The sized buffers section ///////////////////////////////////////////////////////// mod buffers; pub use self::buffers::{ attest::AttestBuffer, auth::Auth, data::Data, digest::Digest, ecc_parameter::EccParameter, encrypted_secret::EncryptedSecret, id_object::IdObject, initial_value::InitialValue, max_buffer::MaxBuffer, max_nv_buffer::MaxNvBuffer, nonce::Nonce, private::Private, private_key_rsa::PrivateKeyRsa, private_vendor_specific::PrivateVendorSpecific, public::PublicBuffer, public_key_rsa::PublicKeyRsa, sensitive::SensitiveBuffer, sensitive_data::SensitiveData, symmetric_key::SymmetricKey, timeout::Timeout, }; ///////////////////////////////////////////////////////// /// The creation section ///////////////////////////////////////////////////////// mod creation; pub use self::creation::CreationData; ///////////////////////////////////////////////////////// /// The hash section ///////////////////////////////////////////////////////// mod hash; pub use self::hash::agile::HashAgile; ///////////////////////////////////////////////////////// /// The pcr section ///////////////////////////////////////////////////////// mod pcr; pub use self::pcr_slot::PcrSlot; pub mod pcr_slot { pub use super::pcr::slot::*; } pub use self::pcr_select::PcrSelect; pub mod pcr_select { pub use super::pcr::select::*; } pub use self::pcr_selection::PcrSelection; pub mod pcr_selection { pub use super::pcr::selection::*; } pub use self::pcr_select_size::PcrSelectSize; pub mod pcr_select_size { pub use super::pcr::select_size::*; } ///////////////////////////////////////////////////////// /// The lists section ///////////////////////////////////////////////////////// mod lists; pub use self::digest_list::DigestList; pub mod digest_list { pub use super::lists::digest::*; } pub use self::digest_values::DigestValues; pub mod digest_values { pub use super::lists::digest_values::*; } pub use self::ecc_curves::EccCurveList; pub mod ecc_curves { pub use super::lists::ecc_curves::*; } pub use self::handle_list::HandleList; pub mod handle_list { pub use super::lists::handles::*; } pub use self::pcr_selection_list::PcrSelectionList; pub use self::pcr_selection_list::PcrSelectionListBuilder; pub mod pcr_selection_list { pub use super::lists::pcr_selection::*; } pub use self::command_code_list::CommandCodeList; pub mod command_code_list { pub use super::lists::command_code::*; } pub use self::tagged_tpm_property_list::TaggedTpmPropertyList; pub mod tagged_tpm_property_list { pub use super::lists::tagged_tpm_property::*; } pub use algorithm_property_list::AlgorithmPropertyList; pub mod algorithm_property_list { pub use super::lists::algorithm_property::*; } pub use tagged_pcr_property_list::TaggedPcrPropertyList; pub mod tagged_pcr_property_list { pub use super::lists::tagged_pcr_property::*; } pub use self::command_code_attributes_list::CommandCodeAttributesList; pub mod command_code_attributes_list { pub use super::lists::command_code_attributes::*; } pub(crate) use pcr::slot_collection::PcrSlotCollection; ///////////////////////////////////////////////////////// /// The parameters section ///////////////////////////////////////////////////////// mod parameters; pub use self::parameters::SymmetricCipherParameters; ///////////////////////////////////////////////////////// /// The tickets section ///////////////////////////////////////////////////////// mod tickets; pub use tickets::AuthTicket; pub use tickets::CreationTicket; pub use tickets::HashcheckTicket; pub use tickets::Ticket; pub use tickets::VerifiedTicket; mod schemes; pub use schemes::{EcDaaScheme, HashScheme, HmacScheme, XorScheme}; mod tagged; pub use tagged::{ parameters::PublicParameters, public::{ ecc::{PublicEccParameters, PublicEccParametersBuilder}, keyed_hash::PublicKeyedHashParameters, rsa::{PublicRsaParameters, PublicRsaParametersBuilder, RsaExponent}, Public, PublicBuilder, }, schemes::{ EccScheme, KeyDerivationFunctionScheme, KeyedHashScheme, RsaDecryptionScheme, RsaScheme, SignatureScheme, }, sensitive::Sensitive, signature::Signature, symmetric::{SymmetricDefinition, SymmetricDefinitionObject}, }; ///////////////////////////////////////////////////////// /// ECC structures ///////////////////////////////////////////////////////// mod ecc; pub use ecc::point::EccPoint; ///////////////////////////////////////////////////////// /// Signatures structures ///////////////////////////////////////////////////////// mod signatures; pub use signatures::{EccSignature, RsaSignature}; ///////////////////////////////////////////////////////// /// Attestation Structures ///////////////////////////////////////////////////////// mod attestation; pub use attestation::{ attest::Attest, attest_info::AttestInfo, certify_info::CertifyInfo, command_audit_info::CommandAuditInfo, creation_info::CreationInfo, nv_certify_info::NvCertifyInfo, nv_digest_certify_info::NvDigestCertifyInfo, quote_info::QuoteInfo, session_audit_info::SessionAuditInfo, time_attest_info::TimeAttestInfo, }; ///////////////////////////////////////////////////////// /// Clock/Time Structures ///////////////////////////////////////////////////////// mod clock; pub use clock::{clock_info::ClockInfo, time_info::TimeInfo}; ///////////////////////////////////////////////////////// /// Property Structures ///////////////////////////////////////////////////////// mod property; pub use property::{ algorithm_property::AlgorithmProperty, tagged_pcr_select::TaggedPcrSelect, tagged_property::TaggedProperty, }; ///////////////////////////////////////////////////////// /// NV structures ///////////////////////////////////////////////////////// mod nv; pub use nv::storage::{NvPublic, NvPublicBuilder}; tss-esapi-7.4.0/src/structures/names/mod.rs000064400000000000000000000001531046102023000170050ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 pub mod name; tss-esapi-7.4.0/src/structures/names/name.rs000064400000000000000000000033421046102023000171510ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::tss2_esys::TPM2B_NAME; use crate::{Error, Result, WrapperErrorKind}; use log::error; use std::convert::TryFrom; /// Structure holding the data representing names #[allow(missing_copy_implementations)] #[derive(Debug, Clone)] pub struct Name { value: TPM2B_NAME, } impl Name { const MAX_SIZE: usize = 68; pub fn value(&self) -> &[u8] { &self.value.name[..self.value.size as usize] } } impl PartialEq for Name { fn eq(&self, other: &Self) -> bool { self.value() == other.value() } } impl Eq for Name {} impl TryFrom> for Name { type Error = Error; fn try_from(bytes: Vec) -> Result { if bytes.len() > Name::MAX_SIZE { error!("Invalid Vec size(> {})", Name::MAX_SIZE); return Err(Error::local_error(WrapperErrorKind::WrongParamSize)); } let size = bytes.len() as u16; let mut name = [0; Name::MAX_SIZE]; name[..bytes.len()].copy_from_slice(&bytes); Ok(Name { value: TPM2B_NAME { size, name }, }) } } impl TryFrom for Name { type Error = Error; fn try_from(tss_name: TPM2B_NAME) -> Result { let size = tss_name.size as usize; if size > Name::MAX_SIZE { error!("Invalid TPM2B_NAME size(> {})", Name::MAX_SIZE); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } Ok(Name { value: tss_name }) } } impl From for TPM2B_NAME { fn from(name: Name) -> Self { name.value } } impl AsRef for Name { fn as_ref(&self) -> &TPM2B_NAME { &self.value } } tss-esapi-7.4.0/src/structures/nv/mod.rs000064400000000000000000000003461046102023000163310ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 /// This module contains code that deals with the non volatile /// parts of the tpm. /// Non volatile storage module. pub mod storage; tss-esapi-7.4.0/src/structures/nv/storage/mod.rs000064400000000000000000000003601046102023000177710ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 /// This module contains code that deaals with non volatile storage /// in the TPM. /// mod public; pub use public::{NvPublic, NvPublicBuilder}; tss-esapi-7.4.0/src/structures/nv/storage/public.rs000064400000000000000000000134551046102023000205010ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ attributes::NvIndexAttributes, handles::NvIndexTpmHandle, interface_types::algorithm::HashingAlgorithm, structures::Digest, tss2_esys::{TPM2B_NV_PUBLIC, TPMS_NV_PUBLIC}, Error, Result, WrapperErrorKind, }; use log::error; use std::convert::{TryFrom, TryInto}; /// Representation of the public parameters of a non-volatile /// space allocation. /// /// # Details /// Corresponds to `TPMS_NV_PUBLIC` #[derive(Debug, Clone, Eq, PartialEq)] pub struct NvPublic { nv_index: NvIndexTpmHandle, name_algorithm: HashingAlgorithm, attributes: NvIndexAttributes, authorization_policy: Digest, data_size: usize, } impl NvPublic { const MAX_SIZE: usize = std::mem::size_of::(); pub fn nv_index(&self) -> NvIndexTpmHandle { self.nv_index } pub fn name_algorithm(&self) -> HashingAlgorithm { self.name_algorithm } pub fn attributes(&self) -> NvIndexAttributes { self.attributes } pub fn authorization_policy(&self) -> &Digest { &self.authorization_policy } pub fn data_size(&self) -> usize { self.data_size } /// Get a builder for the structure pub const fn builder() -> NvPublicBuilder { NvPublicBuilder::new() } } impl TryFrom for NvPublic { type Error = Error; fn try_from(tss_nv_public: TPM2B_NV_PUBLIC) -> Result { if tss_nv_public.size as usize > NvPublic::MAX_SIZE { error!("Encountered an invalid size of the TPMS_NV_PUBLIC"); return Err(Error::local_error(WrapperErrorKind::WrongParamSize)); } // Parse actual data Ok(NvPublic { nv_index: tss_nv_public.nvPublic.nvIndex.try_into()?, name_algorithm: tss_nv_public.nvPublic.nameAlg.try_into()?, attributes: tss_nv_public.nvPublic.attributes.try_into()?, authorization_policy: tss_nv_public.nvPublic.authPolicy.try_into()?, data_size: tss_nv_public.nvPublic.dataSize as usize, }) } } impl TryFrom for TPM2B_NV_PUBLIC { type Error = Error; fn try_from(nv_public: NvPublic) -> Result { Ok(TPM2B_NV_PUBLIC { // Will be ignored due to being a complex TPM2B type // The marshalling functionality in TSS will calculate // the correct value. size: 0, nvPublic: TPMS_NV_PUBLIC { nvIndex: nv_public.nv_index.into(), nameAlg: nv_public.name_algorithm.into(), attributes: nv_public.attributes.try_into()?, authPolicy: nv_public.authorization_policy.into(), dataSize: nv_public.data_size as u16, }, }) } } /// Builder for NvPublic. /// /// #[derive(Debug, Default)] pub struct NvPublicBuilder { nv_index: Option, name_algorithm: Option, attributes: Option, authorization_policy: Option, data_size: Option, } impl NvPublicBuilder { pub const fn new() -> Self { NvPublicBuilder { nv_index: None, name_algorithm: None, attributes: None, authorization_policy: None, data_size: None, } } pub fn with_nv_index(mut self, nv_index: NvIndexTpmHandle) -> Self { self.nv_index = Some(nv_index); self } pub fn with_index_name_algorithm(mut self, nv_index_name_algorithm: HashingAlgorithm) -> Self { self.name_algorithm = Some(nv_index_name_algorithm); self } pub fn with_index_attributes(mut self, nv_index_attributes: NvIndexAttributes) -> Self { self.attributes = Some(nv_index_attributes); self } pub fn with_index_auth_policy(mut self, nv_index_auth_policy: Digest) -> Self { self.authorization_policy = Some(nv_index_auth_policy); self } pub fn with_data_area_size(mut self, nv_index_data_area_size: usize) -> Self { self.data_size = Some(nv_index_data_area_size); self } pub fn build(self) -> Result { // TODO: Do some clever checking of the values in // order to determine some defaults values when // some params have not been specified. // Ok(NvPublic { // Nv Index nv_index: self.nv_index.ok_or_else(|| { error!("No NV index was specified"); Error::local_error(WrapperErrorKind::ParamsMissing) })?, // Hashing algorithm for the name of index name_algorithm: self.name_algorithm.ok_or_else(|| { error!("No name algorithm was specified"); Error::local_error(WrapperErrorKind::ParamsMissing) })?, // Index attributes attributes: self.attributes.ok_or_else(|| { error!("No attributes were specified"); Error::local_error(WrapperErrorKind::ParamsMissing) })?, // Index Auth policy authorization_policy: self.authorization_policy.unwrap_or_default(), // Size of the data area of the index data_size: self .data_size .ok_or_else(|| { error!("No data size specified"); Error::local_error(WrapperErrorKind::ParamsMissing) }) .and_then(|v| { if v > std::u16::MAX.into() { error!("data area size is too large (>{})", std::u16::MAX); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } Ok(v) })?, }) } } tss-esapi-7.4.0/src/structures/parameters.rs000064400000000000000000000026301046102023000172700ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ structures::SymmetricDefinitionObject, tss2_esys::TPMS_SYMCIPHER_PARMS, Error, Result, }; use std::convert::{TryFrom, TryInto}; /// Symmetric cipher parameters /// /// # Details /// Corresponds to TPMS_SYMCIPHER_PARMS #[derive(Clone, Debug, Copy, PartialEq, Eq)] pub struct SymmetricCipherParameters { symmetric_definition_object: SymmetricDefinitionObject, } impl SymmetricCipherParameters { /// Creates a new [SymmetricDefinitionObject] pub const fn new( symmetric_definition_object: SymmetricDefinitionObject, ) -> SymmetricCipherParameters { SymmetricCipherParameters { symmetric_definition_object, } } } impl TryFrom for SymmetricCipherParameters { type Error = Error; fn try_from(tpms_symcipher_params: TPMS_SYMCIPHER_PARMS) -> Result { Ok(SymmetricCipherParameters { symmetric_definition_object: tpms_symcipher_params.sym.try_into()?, }) } } impl From for TPMS_SYMCIPHER_PARMS { fn from(symmetric_cipher_parameters: SymmetricCipherParameters) -> TPMS_SYMCIPHER_PARMS { TPMS_SYMCIPHER_PARMS { sym: symmetric_cipher_parameters .symmetric_definition_object .into(), } } } tss-esapi-7.4.0/src/structures/pcr/mod.rs000064400000000000000000000002741046102023000164720ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 pub mod select; pub mod select_size; pub mod selection; pub mod slot; pub mod slot_collection; tss-esapi-7.4.0/src/structures/pcr/select.rs000064400000000000000000000043301046102023000171670ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ structures::{PcrSelectSize, PcrSlot, PcrSlotCollection}, tss2_esys::TPMS_PCR_SELECT, Error, Result, }; use std::convert::TryFrom; /// This module contains necessary representations /// of the items belonging to the TPMS_PCR_SELECT /// structure. /// /// The minimum number of octets allowed in a TPMS_PCR_SELECT.sizeOfSelect /// is not determined by the number of PCR implemented but by the /// number of PCR required by the platform-specific /// specification with which the TPM is compliant or by the implementer if /// not adhering to a platform-specific specification. #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct PcrSelect { pcr_slot_collection: PcrSlotCollection, } impl PcrSelect { /// Creates a new PcrSelect pub fn create(pcr_select_size: PcrSelectSize, pcr_slots: &[PcrSlot]) -> Result { PcrSlotCollection::create(pcr_select_size, pcr_slots).map(|pcr_slot_collection| PcrSelect { pcr_slot_collection, }) } /// Returns the size of the select. /// /// NB! This is not the same as how many [PcrSlot] /// there are in the select but rather how many /// octets that are needed to hold the bit field /// that indicate what slots that are selected. pub fn size_of_select(&self) -> PcrSelectSize { self.pcr_slot_collection.size_of_select() } /// Returns the selected PCRs in the select. pub fn selected_pcrs(&self) -> Vec { self.pcr_slot_collection.collection() } } impl TryFrom for PcrSelect { type Error = Error; fn try_from(tss_pcr_select: TPMS_PCR_SELECT) -> Result { PcrSlotCollection::try_from((tss_pcr_select.sizeofSelect, tss_pcr_select.pcrSelect)).map( |pcr_slot_collection| PcrSelect { pcr_slot_collection, }, ) } } impl From for TPMS_PCR_SELECT { fn from(pcr_select: PcrSelect) -> Self { let (size_of_select, pcr_select) = pcr_select.pcr_slot_collection.into(); TPMS_PCR_SELECT { sizeofSelect: size_of_select, pcrSelect: pcr_select, } } } tss-esapi-7.4.0/src/structures/pcr/select_size.rs000064400000000000000000000070101046102023000202170ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{tss2_esys::TPM2_PCR_SELECT_MAX, Error, Result, WrapperErrorKind}; use num_derive::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive}; use log::error; use std::convert::TryFrom; /// Enum with the possible values for sizeofSelect. #[derive(FromPrimitive, ToPrimitive, Debug, Copy, Clone, PartialEq, Eq)] #[repr(u8)] pub enum PcrSelectSize { OneOctet = 1, TwoOctets = 2, ThreeOctets = 3, FourOctets = 4, } impl PcrSelectSize { /// Returns the PcrSelectSize value as u8 pub fn as_u8(&self) -> u8 { // The value is well defined so unwrap will // never cause panic. self.to_u8().unwrap() } /// Returns the PcrSelectSize value as u32 pub fn as_u32(&self) -> u32 { // The value is well defined so unwrap will // never cause panic. self.to_u32().unwrap() } /// Returns the PcrSelectSize value as usize pub fn as_usize(&self) -> usize { // The value is well defined so unwrap will // never cause panic. self.to_usize().unwrap() } /// Parses the u8 value as PcrSelectSize pub fn try_parse_u8(value: u8) -> Result { PcrSelectSize::from_u8(value).ok_or_else(|| { error!( "Error converting sizeofSelect to a SelectSize: Invalid value {}", value ); Error::local_error(WrapperErrorKind::InvalidParam) }) } /// Parses the u32 value as PcrSelectSize pub fn try_parse_u32(value: u32) -> Result { PcrSelectSize::from_u32(value).ok_or_else(|| { error!( "Error converting sizeofSelect to a SelectSize: Invalid value {}", value ); Error::local_error(WrapperErrorKind::InvalidParam) }) } /// Parses the usize value as PcrSelectSize pub fn try_parse_usize(value: usize) -> Result { PcrSelectSize::from_usize(value).ok_or_else(|| { error!( "Error converting sizeofSelect to a SelectSize: Invalid value {}", value ); Error::local_error(WrapperErrorKind::InvalidParam) }) } } /// The default for PcrSelectSize is three octets. /// A value for the sizeofSelect that works /// on most platforms. impl Default for PcrSelectSize { fn default() -> PcrSelectSize { match TPM2_PCR_SELECT_MAX { 1 => PcrSelectSize::OneOctet, 2 => PcrSelectSize::TwoOctets, _ => PcrSelectSize::ThreeOctets, } } } impl TryFrom for PcrSelectSize { type Error = Error; fn try_from(value: u8) -> Result { if u32::from(value) > TPM2_PCR_SELECT_MAX { error!( "Found size of select value(= {}) that is larger then TPM2_PCR_SELECT_MAX(={}", value, TPM2_PCR_SELECT_MAX ); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } PcrSelectSize::try_parse_u8(value) } } impl TryFrom for u8 { type Error = Error; fn try_from(pcr_select_size: PcrSelectSize) -> Result { if pcr_select_size.as_u32() > TPM2_PCR_SELECT_MAX { error!("The number of octets specified by PcrSelectSize value us greater then TPM2_PCR_SELECT_MAX"); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } Ok(pcr_select_size.as_u8()) } } tss-esapi-7.4.0/src/structures/pcr/selection.rs000064400000000000000000000134451046102023000177040ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ interface_types::algorithm::HashingAlgorithm, structures::{PcrSelectSize, PcrSlot, PcrSlotCollection}, tss2_esys::TPMS_PCR_SELECTION, Error, Result, WrapperErrorKind, }; use log::error; use std::convert::TryFrom; /// This module contains the PcrSelection struct. /// The TSS counterpart of this struct is the /// TPMS_PCR_SELECTION. #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct PcrSelection { hashing_algorithm: HashingAlgorithm, pcr_slot_collection: PcrSlotCollection, } impl PcrSelection { /// Creates new PcrSelection /// /// # Errors /// Returns InconsistentParams error if a pcr slot /// has been provided that ends up in an octet outside the /// range specified by the `size_of_select` parameter. pub fn create( hashing_algorithm: HashingAlgorithm, size_of_select: PcrSelectSize, selected_pcr_slots: &[PcrSlot], ) -> Result { PcrSlotCollection::create(size_of_select, selected_pcr_slots).map(|pcr_slot_collection| { PcrSelection { hashing_algorithm, pcr_slot_collection, } }) } /// Returns the hashing algorithm for the selection pub const fn hashing_algorithm(&self) -> HashingAlgorithm { self.hashing_algorithm } /// Returns 'Size of Select' /// /// NB! This is not the same as how many [PcrSlot] /// there are in the selection but rather how many /// octets that are needed to hold the bit field /// that indicate what slots that are selected. pub const fn size_of_select(&self) -> PcrSelectSize { self.pcr_slot_collection.size_of_select() } /// Returns the selected pcrs. pub fn selected(&self) -> Vec { self.pcr_slot_collection.collection() } /// Returns true if the specified [PcrSlot] is selected in /// the [PcrSelection]. pub fn is_selected(&self, pcr_slot: PcrSlot) -> bool { self.pcr_slot_collection.contains(pcr_slot) } /// Removes the specified [PcrSlot]s from the selected pcrs. /// /// # Errors /// If one of the specified pcr slots does not exist in the selected pcrs. pub fn deselect_exact(&mut self, pcr_slot: PcrSlot) -> Result<()> { self.pcr_slot_collection.remove_exact(pcr_slot) } /// Removes the specified [PcrSlot]s from the selected pcrs. pub fn deselect(&mut self, pcr_slot: PcrSlot) { self.pcr_slot_collection.remove(pcr_slot) } /// Merges another [PcrSelection] into `self` if the /// elements in the collection does not already exist /// in `self`. /// /// # Constraints /// * Cannot be called with `other` that has a hashing_algorithm /// that is different from the one in `self`. /// * Cannot be called with `other` that has a size_of_select /// that is different from the one in `self`. /// * Cannot be called with `other`that contains pcr slots present /// in `self`. /// /// # Errors /// Returns InvalidParam if there is a hashing algorithm mismatch /// Returns InvalidParam if there is size of select mismatch. /// Returns InvalidParam if `other` contains items that are present in `self` pub fn merge_exact(&mut self, other: &Self) -> Result<()> { // Check that the hashing algorithm match if self.hashing_algorithm != other.hashing_algorithm { error!("Found inconsistencies in the hashing algorithm"); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } self.pcr_slot_collection .merge_exact(&other.pcr_slot_collection) } /// Removes the selected pcr slots in `other` from `self`if none /// of the pcr slots are present in `self`. /// /// # Constraints /// * Cannot be called with `other` that has a hashing_algorithm /// that is different from the one in `self`. /// * Cannot be called with `other` that has a size_of_select /// that is different from the one in `self`. /// * Cannot be called with `other`that contains pcr slots not present /// in `self`. pub fn subtract_exact(&mut self, other: &Self) -> Result<()> { // Check that the hashing algorithm match if self.hashing_algorithm != other.hashing_algorithm { error!("Mismatched hashing algorithm "); return Err(Error::local_error(WrapperErrorKind::InconsistentParams)); } self.pcr_slot_collection .subtract_exact(&other.pcr_slot_collection) } /// Indicates whether the pcr selection is empty. pub fn is_empty(&self) -> bool { self.pcr_slot_collection.is_empty() } } impl TryFrom for PcrSelection { type Error = Error; fn try_from(tss_pcr_selection: TPMS_PCR_SELECTION) -> Result { // Parse hashing algorithm. let hashing_algorithm = HashingAlgorithm::try_from(tss_pcr_selection.hash).map_err(|e| { error!("Error converting hash to a HashingAlgorithm: {}", e); Error::local_error(WrapperErrorKind::InvalidParam) })?; let pcr_slot_collection = PcrSlotCollection::try_from(( tss_pcr_selection.sizeofSelect, tss_pcr_selection.pcrSelect, ))?; Ok(PcrSelection { hashing_algorithm, pcr_slot_collection, }) } } impl From for TPMS_PCR_SELECTION { fn from(pcr_selection: PcrSelection) -> Self { let (size_of_select, pcr_select) = pcr_selection.pcr_slot_collection.into(); TPMS_PCR_SELECTION { hash: pcr_selection.hashing_algorithm.into(), sizeofSelect: size_of_select, pcrSelect: pcr_select, } } } tss-esapi-7.4.0/src/structures/pcr/slot.rs000064400000000000000000000042041046102023000166710ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{tss2_esys::TPM2_PCR_SELECT_MAX, Error, Result, WrapperErrorKind}; use enumflags2::bitflags; use log::error; use num_derive::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive}; use std::convert::TryFrom; /// Enum with the bit flag for each PCR slot. #[bitflags] #[repr(u32)] #[derive(FromPrimitive, ToPrimitive, Hash, Debug, Eq, PartialEq, Ord, PartialOrd, Clone, Copy)] pub enum PcrSlot { Slot0 = 0x0000_0001, Slot1 = 0x0000_0002, Slot2 = 0x0000_0004, Slot3 = 0x0000_0008, Slot4 = 0x0000_0010, Slot5 = 0x0000_0020, Slot6 = 0x0000_0040, Slot7 = 0x0000_0080, Slot8 = 0x0000_0100, Slot9 = 0x0000_0200, Slot10 = 0x0000_0400, Slot11 = 0x0000_0800, Slot12 = 0x0000_1000, Slot13 = 0x0000_2000, Slot14 = 0x0000_4000, Slot15 = 0x0000_8000, Slot16 = 0x0001_0000, Slot17 = 0x0002_0000, Slot18 = 0x0004_0000, Slot19 = 0x0008_0000, Slot20 = 0x0010_0000, Slot21 = 0x0020_0000, Slot22 = 0x0040_0000, Slot23 = 0x0080_0000, Slot24 = 0x0100_0000, Slot25 = 0x0200_0000, Slot26 = 0x0400_0000, Slot27 = 0x0800_0000, Slot28 = 0x1000_0000, Slot29 = 0x2000_0000, Slot30 = 0x4000_0000, Slot31 = 0x8000_0000, } impl From for u32 { fn from(pcr_slot: PcrSlot) -> u32 { pcr_slot.to_u32().unwrap() } } impl TryFrom for PcrSlot { type Error = Error; fn try_from(value: u32) -> Result { PcrSlot::from_u32(value).ok_or_else(|| { error!("{} is not valid PcrSlot value", value); Error::local_error(WrapperErrorKind::InvalidParam) }) } } impl From for [u8; TPM2_PCR_SELECT_MAX as usize] { fn from(pcr_slot: PcrSlot) -> [u8; TPM2_PCR_SELECT_MAX as usize] { u32::from(pcr_slot).to_le_bytes() } } impl TryFrom<[u8; TPM2_PCR_SELECT_MAX as usize]> for PcrSlot { type Error = Error; fn try_from(tss_pcr_slot: [u8; TPM2_PCR_SELECT_MAX as usize]) -> Result { PcrSlot::try_from(u32::from_le_bytes(tss_pcr_slot)) } } tss-esapi-7.4.0/src/structures/pcr/slot_collection.rs000064400000000000000000000177611046102023000211200ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ structures::{PcrSelectSize, PcrSlot}, tss2_esys::TPM2_PCR_SELECT_MAX, Error, Result, WrapperErrorKind, }; use enumflags2::BitFlags; use log::error; use std::convert::TryFrom; #[derive(Debug, Default, Copy, Clone, Eq, PartialEq)] pub struct PcrSlotCollection { pcr_select_size: PcrSelectSize, pcr_slots: BitFlags, } impl PcrSlotCollection { const MAX_SIZE: usize = TPM2_PCR_SELECT_MAX as usize; /// Creates a new PcrSlotCollection pub fn new() -> Self { PcrSlotCollection::default() } /// Creates a PcrCollection from the given arguments. pub fn create(pcr_select_size: PcrSelectSize, pcr_slots: &[PcrSlot]) -> Result { Self::validate_parameters(pcr_select_size, pcr_slots)?; Ok(PcrSlotCollection { pcr_select_size, pcr_slots: pcr_slots.iter().copied().collect(), }) } /// Validates that the combination of parameters /// provided can be used together. pub fn validate_parameters( pcr_select_size: PcrSelectSize, pcr_slots: &[PcrSlot], ) -> Result<()> { let _number_of_octets: u32 = u8::try_from(pcr_select_size).map(u32::from)?; let max_pcr_slot_value = Self::calculate_max_pcr_slots_value(pcr_select_size); if pcr_slots .iter() .any(|&item| u32::from(item) > max_pcr_slot_value) { error!("pcr_slots contained a pcr slot that does not reside in octets specified by size_of_select"); return Err(Error::local_error(WrapperErrorKind::InconsistentParams)); } Ok(()) } /// Returns the size of the select. pub const fn size_of_select(&self) -> PcrSelectSize { self.pcr_select_size } /// Returns true if the collection contains the /// specified pcr slot. pub fn contains(&self, pcr_slot: PcrSlot) -> bool { self.pcr_slots.contains(pcr_slot) } /// Returns true if the collection is empty. pub fn is_empty(&self) -> bool { self.pcr_slots.is_empty() } /// Returns the pcr slots in the collection. pub fn collection(&self) -> Vec { self.pcr_slots.iter().collect() } /// Removes pcr slot from the collection pub fn remove(&mut self, pcr_slot: PcrSlot) { self.pcr_slots.remove(pcr_slot) } /// Removes pcr slot from the collection if it /// exists. /// /// # Constraints /// Cannot remove a pcr slot from the collection /// if it does not reside inside the collection. /// /// # Errors /// Returns InvalidParam error if the collection /// did not contain the specified pcr slot. pub fn remove_exact(&mut self, pcr_slot: PcrSlot) -> Result<()> { self.ensure_contains_all(pcr_slot, "remove_exact")?; self.pcr_slots.remove(pcr_slot); Ok(()) } /// Merges another PcrSlotCollection into `self` if it contains no /// pcr slots that are already present in `self`. /// /// # Errors /// Returns InconsistentParams if a size of select mismatch is detected. /// Returns InvalidParam if `other` contains items that are present in `self` pub fn merge_exact(&mut self, other: &Self) -> Result<()> { // Check that size of select match. self.ensure_pcr_select_size_equality(other, "merge_exact")?; self.ensure_contains_none(other.pcr_slots, "merge_exact")?; self.pcr_slots |= other.pcr_slots; Ok(()) } /// Subtracts another PcrSlotCollection from `self` if none the /// items in the other collection is present in `self`. /// /// # Errors /// Returns InconsistentParams if a size of select mismatch is detected. /// Returns InvalidParam if `other` contains items that are not present in `self` pub fn subtract_exact(&mut self, other: &Self) -> Result<()> { // Check that size of select match. self.ensure_pcr_select_size_equality(other, "subtract_unique")?; self.ensure_contains_all(other.pcr_slots, "subtract_unique")?; self.pcr_slots.remove(other.pcr_slots); Ok(()) } /// Private method for ensuring that a size of select /// is equal to the one present in `self`. fn ensure_pcr_select_size_equality( &self, other: &PcrSlotCollection, action: &str, ) -> Result<()> { if self.pcr_select_size != other.pcr_select_size { error!( "Failed to perform '{}' due to size of select mismatch", action ); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } Ok(()) } /// Private method for ensuring that provided pcr slots does not /// already exists in `self`. fn ensure_contains_none(&self, pcr_slots: BitFlags, action: &str) -> Result<()> { if self.pcr_slots.intersects(pcr_slots) { error!( "Failed to perform '{}' because `self` contained the specified pcr slots", action ); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } Ok(()) } /// Private method that ensures that all the specified pcr slots /// exists in `self`. fn ensure_contains_all(&self, pcr_slots: T, action: &str) -> Result<()> where T: Into>, { if self.pcr_slots.contains(pcr_slots) { Ok(()) } else { error!( "Failed to perform '{}' because `self` did not contain the specified pcr slots", action ); Err(Error::local_error(WrapperErrorKind::InvalidParam)) } } /// Private function for parsing the octets into the internal representation. fn parse_octets( mut octets: [u8; PcrSlotCollection::MAX_SIZE], pcr_select_size: PcrSelectSize, ) -> Result> { // Mask all octets not indicated by pcr_select_size // to be included. octets[..] .iter_mut() .enumerate() .for_each(|(index, value)| { if index + 1 > pcr_select_size.as_usize() { *value = 0u8; } }); BitFlags::::try_from(u32::from_le_bytes(octets)).map_err(|e| { error!("Error parsing octets to a BitFlags: {}", e); Error::local_error(WrapperErrorKind::UnsupportedParam) }) } /// Private function that calculates the maximum value for /// pcr slots with regard to the PcrSelectSize const fn calculate_max_pcr_slots_value(pcr_select_size: PcrSelectSize) -> u32 { match pcr_select_size { PcrSelectSize::OneOctet => 0x000000FF, PcrSelectSize::TwoOctets => 0x0000FFFF, PcrSelectSize::ThreeOctets => 0x00FFFFFF, PcrSelectSize::FourOctets => 0xFFFFFFFF, } } } impl From for (u8, [u8; PcrSlotCollection::MAX_SIZE]) { fn from(pcr_slot_collection: PcrSlotCollection) -> Self { // PcrSlotCollection should not be able to contain // an invalid pcr_select_size. let size_of_select = pcr_slot_collection.pcr_select_size.as_u8(); let number_of_octets = pcr_slot_collection.pcr_select_size.as_usize(); let u32_bytes = pcr_slot_collection.pcr_slots.bits().to_le_bytes(); let mut octets: [u8; TPM2_PCR_SELECT_MAX as usize] = Default::default(); octets[..number_of_octets].copy_from_slice(&u32_bytes[..number_of_octets]); (size_of_select, octets) } } impl TryFrom<(u8, [u8; Self::MAX_SIZE])> for PcrSlotCollection { type Error = Error; fn try_from((size_of_select, octets): (u8, [u8; Self::MAX_SIZE])) -> Result { let pcr_select_size = PcrSelectSize::try_from(size_of_select)?; Ok(PcrSlotCollection { pcr_select_size, pcr_slots: PcrSlotCollection::parse_octets(octets, pcr_select_size)?, }) } } tss-esapi-7.4.0/src/structures/property/algorithm_property.rs000064400000000000000000000036101046102023000227420ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ attributes::AlgorithmAttributes, constants::AlgorithmIdentifier, tss2_esys::TPMS_ALG_PROPERTY, Error, Result, }; use std::convert::{TryFrom, TryInto}; /// Strucutre for holding information describing an /// algorithm. /// /// # Details /// This corresponds to the TPMS_ALG_PROPERTY /// structure. #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct AlgorithmProperty { algorithm_identifier: AlgorithmIdentifier, algorithm_properties: AlgorithmAttributes, } impl AlgorithmProperty { /// Creates a new AlgorithmProperty with the /// given parameters. pub const fn new( algorithm_identifier: AlgorithmIdentifier, algorithm_properties: AlgorithmAttributes, ) -> Self { AlgorithmProperty { algorithm_identifier, algorithm_properties, } } /// Returns the algorithm identifier pub const fn algorithm_identifier(&self) -> AlgorithmIdentifier { self.algorithm_identifier } /// Returns the algorithm properties pub const fn algorithm_properties(&self) -> AlgorithmAttributes { self.algorithm_properties } } impl TryFrom for AlgorithmProperty { type Error = Error; fn try_from(tpms_algorithm_description: TPMS_ALG_PROPERTY) -> Result { Ok(AlgorithmProperty { algorithm_identifier: tpms_algorithm_description.alg.try_into()?, algorithm_properties: tpms_algorithm_description.algProperties.into(), }) } } impl From for TPMS_ALG_PROPERTY { fn from(algorithm_description: AlgorithmProperty) -> Self { TPMS_ALG_PROPERTY { alg: algorithm_description.algorithm_identifier.into(), algProperties: algorithm_description.algorithm_properties.into(), } } } tss-esapi-7.4.0/src/structures/property/mod.rs000064400000000000000000000002551046102023000175710ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 pub mod algorithm_property; pub mod tagged_pcr_select; pub mod tagged_property; tss-esapi-7.4.0/src/structures/property/tagged_pcr_select.rs000064400000000000000000000053211046102023000224470ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ constants::PcrPropertyTag, structures::{PcrSelectSize, PcrSlot, PcrSlotCollection}, tss2_esys::TPMS_TAGGED_PCR_SELECT, Error, Result, }; use std::convert::TryFrom; /// Type that holds information regarding /// what PCR slots that are associated with /// a specific pcr property tag. /// /// This corresponds to the TPMS_TAGGED_PCR_SELECT. #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct TaggedPcrSelect { pcr_property_tag: PcrPropertyTag, pcr_slot_collection: PcrSlotCollection, } impl TaggedPcrSelect { /// Creates a new TaggedPcrSelect pub fn create( pcr_property_tag: PcrPropertyTag, pcr_select_size: PcrSelectSize, selected_pcr_slots: &[PcrSlot], ) -> Result { PcrSlotCollection::create(pcr_select_size, selected_pcr_slots).map(|pcr_slot_collection| { TaggedPcrSelect { pcr_property_tag, pcr_slot_collection, } }) } /// Returns the property identifier pub const fn pcr_property_tag(&self) -> PcrPropertyTag { self.pcr_property_tag } /// Returns the size of the select /// /// NB! This is not the same as how many [PcrSlot] /// there are in the select, but rather how many /// octets are needed to hold the bit field which /// indicates what slots have the [PcrPropertyTag] /// property. pub const fn size_of_select(&self) -> PcrSelectSize { self.pcr_slot_collection.size_of_select() } /// Returns the pcr slots that has the property /// indicated by the pcr property tag. pub fn selected_pcrs(&self) -> Vec { self.pcr_slot_collection.collection() } } impl TryFrom for TaggedPcrSelect { type Error = Error; fn try_from(tpms_tagged_pcr_select: TPMS_TAGGED_PCR_SELECT) -> Result { // Parse the tag. let pcr_property_tag = PcrPropertyTag::try_from(tpms_tagged_pcr_select.tag)?; let pcr_slot_collection = PcrSlotCollection::try_from(( tpms_tagged_pcr_select.sizeofSelect, tpms_tagged_pcr_select.pcrSelect, ))?; Ok(TaggedPcrSelect { pcr_property_tag, pcr_slot_collection, }) } } impl From for TPMS_TAGGED_PCR_SELECT { fn from(tagged_pcr_select: TaggedPcrSelect) -> Self { let (size_of_select, pcr_select) = tagged_pcr_select.pcr_slot_collection.into(); TPMS_TAGGED_PCR_SELECT { tag: tagged_pcr_select.pcr_property_tag.into(), sizeofSelect: size_of_select, pcrSelect: pcr_select, } } } tss-esapi-7.4.0/src/structures/property/tagged_property.rs000064400000000000000000000025761046102023000222210ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{constants::PropertyTag, tss2_esys::TPMS_TAGGED_PROPERTY, Error, Result}; use std::convert::TryFrom; /// Struct representing a tagged property /// /// # Details /// This corresponds to TPMS_TAGGED_PROPERTY #[derive(Debug, Clone, Copy, Eq, PartialEq)] pub struct TaggedProperty { property: PropertyTag, value: u32, } impl TaggedProperty { /// Creates a new TaggedProperty pub const fn new(property: PropertyTag, value: u32) -> Self { TaggedProperty { property, value } } /// Returns the property tag pub const fn property(&self) -> PropertyTag { self.property } /// Returns the value pub const fn value(&self) -> u32 { self.value } } impl TryFrom for TaggedProperty { type Error = Error; fn try_from(tpms_tagged_property: TPMS_TAGGED_PROPERTY) -> Result { let value = tpms_tagged_property.value; PropertyTag::try_from(tpms_tagged_property.property) .map(|property| TaggedProperty { property, value }) } } impl From for TPMS_TAGGED_PROPERTY { fn from(tagged_property: TaggedProperty) -> Self { TPMS_TAGGED_PROPERTY { property: tagged_property.property.into(), value: tagged_property.value, } } } tss-esapi-7.4.0/src/structures/result.rs000064400000000000000000000012651046102023000164460ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ handles::KeyHandle, structures::{CreationData, CreationTicket, Digest, Private, Public}, }; #[allow(missing_debug_implementations)] pub struct CreateKeyResult { pub out_private: Private, pub out_public: Public, pub creation_data: CreationData, pub creation_hash: Digest, pub creation_ticket: CreationTicket, } #[allow(missing_debug_implementations)] pub struct CreatePrimaryKeyResult { pub key_handle: KeyHandle, pub out_public: Public, pub creation_data: CreationData, pub creation_hash: Digest, pub creation_ticket: CreationTicket, } tss-esapi-7.4.0/src/structures/schemes.rs000064400000000000000000000112461046102023000165570ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ interface_types::algorithm::{HashingAlgorithm, KeyDerivationFunction}, tss2_esys::{TPMS_SCHEME_ECDAA, TPMS_SCHEME_HASH, TPMS_SCHEME_HMAC, TPMS_SCHEME_XOR}, Error, Result, }; use std::convert::{TryFrom, TryInto}; /// Struct for holding the hash scheme #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct HashScheme { hashing_algorithm: HashingAlgorithm, } impl HashScheme { /// Creates a new HashScheme pub const fn new(hashing_algorithm: HashingAlgorithm) -> HashScheme { HashScheme { hashing_algorithm } } /// Returns the hashing algorithm pub const fn hashing_algorithm(&self) -> HashingAlgorithm { self.hashing_algorithm } } impl TryFrom for HashScheme { type Error = Error; fn try_from(tpms_scheme_hash: TPMS_SCHEME_HASH) -> Result { Ok(HashScheme { hashing_algorithm: tpms_scheme_hash.hashAlg.try_into()?, }) } } impl From for TPMS_SCHEME_HASH { fn from(hash_scheme: HashScheme) -> Self { TPMS_SCHEME_HASH { hashAlg: hash_scheme.hashing_algorithm.into(), } } } /// Struct for holding HMAC scheme. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct HmacScheme { hashing_algorithm: HashingAlgorithm, } impl HmacScheme { /// Creates a new HmacScheme pub const fn new(hashing_algorithm: HashingAlgorithm) -> HmacScheme { HmacScheme { hashing_algorithm } } } impl From for HmacScheme { fn from(hash_scheme: HashScheme) -> Self { HmacScheme { hashing_algorithm: hash_scheme.hashing_algorithm, } } } impl From for HashScheme { fn from(hmac_scheme: HmacScheme) -> Self { HashScheme { hashing_algorithm: hmac_scheme.hashing_algorithm, } } } impl TryFrom for HmacScheme { type Error = Error; fn try_from(tpms_scheme_hmac: TPMS_SCHEME_HMAC) -> Result { Ok(HmacScheme { hashing_algorithm: tpms_scheme_hmac.hashAlg.try_into()?, }) } } impl From for TPMS_SCHEME_HMAC { fn from(hash_scheme: HmacScheme) -> Self { TPMS_SCHEME_HMAC { hashAlg: hash_scheme.hashing_algorithm.into(), } } } /// Struct for holding the xor scheme #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct XorScheme { hashing_algorithm: HashingAlgorithm, key_derivation_function: KeyDerivationFunction, } impl XorScheme { /// Creates a new XorScheme pub const fn new( hashing_algorithm: HashingAlgorithm, key_derivation_function: KeyDerivationFunction, ) -> XorScheme { XorScheme { hashing_algorithm, key_derivation_function, } } } impl TryFrom for XorScheme { type Error = Error; fn try_from(tpms_scheme_xor: TPMS_SCHEME_XOR) -> Result { Ok(XorScheme { hashing_algorithm: tpms_scheme_xor.hashAlg.try_into()?, key_derivation_function: tpms_scheme_xor.kdf.try_into()?, }) } } impl From for TPMS_SCHEME_XOR { fn from(xor_scheme: XorScheme) -> Self { TPMS_SCHEME_XOR { hashAlg: xor_scheme.hashing_algorithm.into(), kdf: xor_scheme.key_derivation_function.into(), } } } /// Struct for holding the ECDAA scheme /// /// # Details /// This corresponds to the TPMS_SCHEME_ECDAA #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct EcDaaScheme { hashing_algorithm: HashingAlgorithm, count: u16, } impl EcDaaScheme { /// Function for creating a new ECDAA scheme pub const fn new(hashing_algorithm: HashingAlgorithm, count: u16) -> Self { EcDaaScheme { hashing_algorithm, count, } } /// Returns the hashing algorithm of the ECDAA scheme. pub const fn hashing_algorithm(&self) -> HashingAlgorithm { self.hashing_algorithm } /// Returns the count of the ECDAA. pub const fn count(&self) -> u16 { self.count } } impl From for TPMS_SCHEME_ECDAA { fn from(ec_daa_scheme: EcDaaScheme) -> Self { TPMS_SCHEME_ECDAA { hashAlg: ec_daa_scheme.hashing_algorithm.into(), count: ec_daa_scheme.count, } } } impl TryFrom for EcDaaScheme { type Error = Error; fn try_from(tpms_scheme_ecdaa: TPMS_SCHEME_ECDAA) -> Result { Ok(EcDaaScheme { hashing_algorithm: tpms_scheme_ecdaa.hashAlg.try_into()?, count: tpms_scheme_ecdaa.count, }) } } tss-esapi-7.4.0/src/structures/signatures.rs000064400000000000000000000110151046102023000173060ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ interface_types::algorithm::HashingAlgorithm, structures::{EccParameter, PublicKeyRsa}, tss2_esys::{TPMS_SIGNATURE_ECC, TPMS_SIGNATURE_RSA}, Error, Result, WrapperErrorKind, }; use log::error; use std::convert::{TryFrom, TryInto}; /// Type holding RSA signature information. /// /// For more information about the contents of `signature` see Annex B /// in the Architecture spec. #[derive(Debug, Clone, PartialEq, Eq)] pub struct RsaSignature { hashing_algorithm: HashingAlgorithm, signature: PublicKeyRsa, } impl RsaSignature { /// Creates new RSA signature /// /// # Errors /// Using [Null][`HashingAlgorithm::Null`] will cause an error. pub fn create(hashing_algorithm: HashingAlgorithm, signature: PublicKeyRsa) -> Result { if hashing_algorithm == HashingAlgorithm::Null { error!("Hashing algorithm Null is not allowed in RsaSignature"); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } Ok(RsaSignature { hashing_algorithm, signature, }) } /// Returns the hashing algorithm pub const fn hashing_algorithm(&self) -> HashingAlgorithm { self.hashing_algorithm } /// Returns the signature pub const fn signature(&self) -> &PublicKeyRsa { &self.signature } } impl From for TPMS_SIGNATURE_RSA { fn from(rsa_signature: RsaSignature) -> Self { TPMS_SIGNATURE_RSA { hash: rsa_signature.hashing_algorithm.into(), sig: rsa_signature.signature.into(), } } } impl TryFrom for RsaSignature { type Error = Error; fn try_from(tpms_signature_rsa: TPMS_SIGNATURE_RSA) -> Result { let hashing_algorithm = tpms_signature_rsa.hash.try_into()?; if hashing_algorithm == HashingAlgorithm::Null { error!("Received invalid hashing algorithm Null from the tpm in the RSA signature."); return Err(Error::local_error(WrapperErrorKind::WrongValueFromTpm)); } Ok(RsaSignature { hashing_algorithm, signature: tpms_signature_rsa.sig.try_into()?, }) } } /// Type holding ECC signature information. /// /// For more information about the contents of `signature_r` and `signature_s` /// see Annex B in the Architecture spec (or Annex D for SM2 signatures). #[derive(Debug, Clone, PartialEq, Eq)] pub struct EccSignature { hashing_algorithm: HashingAlgorithm, signature_r: EccParameter, signature_s: EccParameter, } impl EccSignature { /// Creates new ECC signature pub fn create( hashing_algorithm: HashingAlgorithm, signature_r: EccParameter, signature_s: EccParameter, ) -> Result { if hashing_algorithm == HashingAlgorithm::Null { error!("Hashing algorithm Null is not allowed in RsaSignature"); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } Ok(EccSignature { hashing_algorithm, signature_r, signature_s, }) } /// Returns the hashing algorithm pub const fn hashing_algorithm(&self) -> HashingAlgorithm { self.hashing_algorithm } /// Returns signature r pub const fn signature_r(&self) -> &EccParameter { &self.signature_r } /// Returns signature s pub const fn signature_s(&self) -> &EccParameter { &self.signature_s } } impl From for TPMS_SIGNATURE_ECC { fn from(ecc_signature: EccSignature) -> Self { TPMS_SIGNATURE_ECC { hash: ecc_signature.hashing_algorithm.into(), signatureR: ecc_signature.signature_r.into(), signatureS: ecc_signature.signature_s.into(), } } } impl TryFrom for EccSignature { type Error = Error; fn try_from(tpms_signature_ecc: TPMS_SIGNATURE_ECC) -> Result { let hashing_algorithm = tpms_signature_ecc.hash.try_into()?; if hashing_algorithm == HashingAlgorithm::Null { error!("Received invalid hashing algorithm Null from the tpm in the ECC signature."); return Err(Error::local_error(WrapperErrorKind::WrongValueFromTpm)); } Ok(EccSignature { hashing_algorithm, signature_r: tpms_signature_ecc.signatureR.try_into()?, signature_s: tpms_signature_ecc.signatureS.try_into()?, }) } } tss-esapi-7.4.0/src/structures/tagged/mod.rs000064400000000000000000000003131046102023000171330ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 pub mod parameters; pub mod public; pub mod schemes; pub mod sensitive; pub mod signature; pub mod symmetric; tss-esapi-7.4.0/src/structures/tagged/parameters.rs000064400000000000000000000063071046102023000205300ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ interface_types::algorithm::PublicAlgorithm, structures::{ PublicEccParameters, PublicKeyedHashParameters, PublicRsaParameters, SymmetricCipherParameters, }, tss2_esys::{TPMT_PUBLIC_PARMS, TPMU_PUBLIC_PARMS}, Error, Result, }; use std::convert::{TryFrom, TryInto}; /// Enum representing the public parameters structure. /// /// # Details /// This corresponds to TPMT_PUBLIC_PARMS #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum PublicParameters { Rsa(PublicRsaParameters), KeyedHash(PublicKeyedHashParameters), Ecc(PublicEccParameters), SymCipher(SymmetricCipherParameters), } impl PublicParameters { /// Returns the algorithm pub fn algorithm(&self) -> PublicAlgorithm { match self { PublicParameters::Rsa(_) => PublicAlgorithm::Rsa, PublicParameters::KeyedHash(_) => PublicAlgorithm::KeyedHash, PublicParameters::Ecc(_) => PublicAlgorithm::Ecc, PublicParameters::SymCipher(_) => PublicAlgorithm::SymCipher, } } } impl From for TPMT_PUBLIC_PARMS { fn from(public_parameters: PublicParameters) -> TPMT_PUBLIC_PARMS { let algorithm = public_parameters.algorithm(); match public_parameters { PublicParameters::Rsa(parameters) => TPMT_PUBLIC_PARMS { type_: algorithm.into(), parameters: TPMU_PUBLIC_PARMS { rsaDetail: parameters.into(), }, }, PublicParameters::KeyedHash(parameters) => TPMT_PUBLIC_PARMS { type_: algorithm.into(), parameters: TPMU_PUBLIC_PARMS { keyedHashDetail: parameters.into(), }, }, PublicParameters::Ecc(parameters) => TPMT_PUBLIC_PARMS { type_: algorithm.into(), parameters: TPMU_PUBLIC_PARMS { eccDetail: parameters.into(), }, }, PublicParameters::SymCipher(parameters) => TPMT_PUBLIC_PARMS { type_: algorithm.into(), parameters: TPMU_PUBLIC_PARMS { symDetail: parameters.into(), }, }, } } } impl TryFrom for PublicParameters { type Error = Error; fn try_from(tpmt_public_parms: TPMT_PUBLIC_PARMS) -> Result { match PublicAlgorithm::try_from(tpmt_public_parms.type_)? { PublicAlgorithm::Rsa => Ok(PublicParameters::Rsa( unsafe { tpmt_public_parms.parameters.rsaDetail }.try_into()?, )), PublicAlgorithm::KeyedHash => Ok(PublicParameters::KeyedHash( unsafe { tpmt_public_parms.parameters.keyedHashDetail }.try_into()?, )), PublicAlgorithm::Ecc => Ok(PublicParameters::Ecc( unsafe { tpmt_public_parms.parameters.eccDetail }.try_into()?, )), PublicAlgorithm::SymCipher => Ok(PublicParameters::SymCipher( unsafe { tpmt_public_parms.parameters.symDetail }.try_into()?, )), } } } tss-esapi-7.4.0/src/structures/tagged/public/ecc.rs000064400000000000000000000260071046102023000203740ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ interface_types::{algorithm::EccSchemeAlgorithm, ecc::EccCurve}, structures::{EccScheme, KeyDerivationFunctionScheme, SymmetricDefinitionObject}, tss2_esys::TPMS_ECC_PARMS, Error, Result, WrapperErrorKind, }; use log::error; use std::convert::{TryFrom, TryInto}; /// Builder for PublicEccParameters. #[derive(Copy, Clone, Debug, Default)] pub struct PublicEccParametersBuilder { symmetric: Option, ecc_scheme: Option, ecc_curve: Option, key_derivation_function_scheme: Option, is_signing_key: bool, is_decryption_key: bool, restricted: bool, } impl PublicEccParametersBuilder { pub const fn new() -> Self { PublicEccParametersBuilder { symmetric: None, ecc_scheme: None, ecc_curve: None, key_derivation_function_scheme: None, is_signing_key: false, is_decryption_key: false, restricted: false, } } /// Create parameters for a restricted decryption key (i.e. a storage key) pub const fn new_restricted_decryption_key( symmetric: SymmetricDefinitionObject, curve: EccCurve, ) -> Self { PublicEccParametersBuilder { symmetric: Some(symmetric), ecc_scheme: Some(EccScheme::Null), ecc_curve: Some(curve), key_derivation_function_scheme: Some(KeyDerivationFunctionScheme::Null), is_signing_key: false, is_decryption_key: true, restricted: true, } } /// Create parameters for an unrestricted signing key pub const fn new_unrestricted_signing_key(scheme: EccScheme, curve: EccCurve) -> Self { PublicEccParametersBuilder { symmetric: None, ecc_scheme: Some(scheme), ecc_curve: Some(curve), key_derivation_function_scheme: Some(KeyDerivationFunctionScheme::Null), is_signing_key: true, is_decryption_key: false, restricted: false, } } /// Adds a [SymmetricDefinitionObject] to the [PublicEccParametersBuilder]. pub const fn with_symmetric(mut self, symmetric: SymmetricDefinitionObject) -> Self { self.symmetric = Some(symmetric); self } /// Adds a [EccScheme] to the [PublicEccParametersBuilder]. pub const fn with_ecc_scheme(mut self, ecc_scheme: EccScheme) -> Self { self.ecc_scheme = Some(ecc_scheme); self } /// Adds [EccCurve] to the [PublicEccParametersBuilder]. pub const fn with_curve(mut self, ecc_curve: EccCurve) -> Self { self.ecc_curve = Some(ecc_curve); self } /// Adds [KeyDerivationFunctionScheme] to the [PublicEccParametersBuilder]. pub const fn with_key_derivation_function_scheme( mut self, key_derivation_function_scheme: KeyDerivationFunctionScheme, ) -> Self { self.key_derivation_function_scheme = Some(key_derivation_function_scheme); self } /// Adds a flag that indicates if the key is going to be used /// for signing to the [PublicEccParametersBuilder]. /// /// # Arguments /// * `set` - `true` inidcates that the key is going to be used for signing operations. /// `false` indicates that the key is not going to be used for signing operations. pub const fn with_is_signing_key(mut self, set: bool) -> Self { self.is_signing_key = set; self } /// Adds a flag that indicates if the key is going to be used for /// decryption to the [PublicEccParametersBuilder]. /// /// # Arguments /// * `set` - `true` indicates that the key is going to be used for decryption operations. /// `false` indicates that the key is not going to be used for decryption operations. pub const fn with_is_decryption_key(mut self, set: bool) -> Self { self.is_decryption_key = set; self } /// Adds a flag that inidcates if the key is going to be restrictied to /// the [PublicEccParametersBuilder]. /// /// # Arguments /// * `set` - `true` indicates that it is going to be a restricted key. /// `false` indicates that it is going to be a non restricted key. pub const fn with_restricted(mut self, set: bool) -> Self { self.restricted = set; self } /// Build an object given the previously provided parameters. /// /// The only mandatory parameters are the asymmetric scheme and the elliptic curve. /// /// # Errors /// * if no asymmetric scheme is set, `ParamsMissing` wrapper error is returned. /// * if the `for_signing`, `for_decryption` and `restricted` parameters are /// inconsistent with the rest of the parameters, `InconsistentParams` wrapper /// error is returned pub fn build(self) -> Result { let ecc_scheme = self.ecc_scheme.ok_or_else(|| { error!("Scheme is required nad has not been set in the PublicEccParametersBuilder"); Error::local_error(WrapperErrorKind::ParamsMissing) })?; let ecc_curve = self.ecc_curve.ok_or_else(|| { error!("Curve is required nad has not been set in the PublicEccParametersBuilder"); Error::local_error(WrapperErrorKind::ParamsMissing) })?; let key_derivation_function_scheme = self.key_derivation_function_scheme.ok_or_else(|| { error!("Key derivation function scheme is required nad has not been set in the PublicEccParametersBuilder"); Error::local_error(WrapperErrorKind::ParamsMissing) })?; if self.restricted && self.is_decryption_key { if let Some(symmetric) = self.symmetric { if symmetric.is_null() { error!("Found symmetric parameter but it was Null but 'restricted' and 'is_decrypt_key' are set to true"); return Err(Error::local_error(WrapperErrorKind::InconsistentParams)); } } else { error!("Found symmetric parameter, expected it to be Null nor not set at all because 'restricted' and 'is_decrypt_key' are set to false"); return Err(Error::local_error(WrapperErrorKind::ParamsMissing)); } } else if let Some(symmetric) = self.symmetric { if !symmetric.is_null() { error!("Found symmetric parameter, expected it to be Null nor not set at all because 'restricted' and 'is_decrypt_key' are set to false"); return Err(Error::local_error(WrapperErrorKind::InconsistentParams)); } } if self.is_decryption_key && self.is_signing_key { error!("Key cannot be decryption and signing key at the same time"); return Err(Error::local_error(WrapperErrorKind::InconsistentParams)); } // TODO: Figure out if it actually should be allowed to not provide // these parameters. let symmetric_definition_object = self.symmetric.unwrap_or(SymmetricDefinitionObject::Null); if self.is_signing_key && ecc_scheme.algorithm() != EccSchemeAlgorithm::EcDsa && ecc_scheme.algorithm() != EccSchemeAlgorithm::EcDaa && ecc_scheme.algorithm() != EccSchemeAlgorithm::Sm2 && ecc_scheme.algorithm() != EccSchemeAlgorithm::EcSchnorr { error!("Signing key can use only EcDsa, EcDaa, Sm2 or EcSchorr schemes"); return Err(Error::local_error(WrapperErrorKind::InconsistentParams)); } if self.is_decryption_key && ecc_scheme.algorithm() != EccSchemeAlgorithm::Sm2 && ecc_scheme.algorithm() != EccSchemeAlgorithm::EcDh && ecc_scheme.algorithm() != EccSchemeAlgorithm::EcMqv && ecc_scheme.algorithm() != EccSchemeAlgorithm::Null { error!("Decryption key can use only Sm2, EcDh, EcMqv and Null schemes"); return Err(Error::local_error(WrapperErrorKind::InconsistentParams)); } if (ecc_curve == EccCurve::BnP256 || ecc_curve == EccCurve::BnP638) && ecc_scheme.algorithm() != EccSchemeAlgorithm::EcDaa { error!("Bn curve should use only EcDaa scheme"); return Err(Error::local_error(WrapperErrorKind::InconsistentParams)); } Ok(PublicEccParameters { symmetric_definition_object, ecc_scheme, ecc_curve, key_derivation_function_scheme, }) } } /// Structure holding the ECC specific parameters. /// /// # Details /// This corresponds to TPMS_ECC_PARMS. #[derive(Clone, Debug, Copy, PartialEq, Eq)] pub struct PublicEccParameters { symmetric_definition_object: SymmetricDefinitionObject, ecc_scheme: EccScheme, ecc_curve: EccCurve, key_derivation_function_scheme: KeyDerivationFunctionScheme, } impl PublicEccParameters { /// Creates new EccParameters structure pub const fn new( symmetric_definition_object: SymmetricDefinitionObject, ecc_scheme: EccScheme, ecc_curve: EccCurve, key_derivation_function_scheme: KeyDerivationFunctionScheme, ) -> PublicEccParameters { PublicEccParameters { symmetric_definition_object, ecc_scheme, ecc_curve, key_derivation_function_scheme, } } /// Returns the [SymmetricDefinitionObject]. pub const fn symmetric_definition_object(&self) -> SymmetricDefinitionObject { self.symmetric_definition_object } /// Returns the [EccScheme] pub const fn ecc_scheme(&self) -> EccScheme { self.ecc_scheme } /// Returns the [EccCurve] pub const fn ecc_curve(&self) -> EccCurve { self.ecc_curve } /// Returns the [KeyDerivationFunctionScheme] pub const fn key_derivation_function_scheme(&self) -> KeyDerivationFunctionScheme { self.key_derivation_function_scheme } /// Get a builder for this structure pub const fn builder() -> PublicEccParametersBuilder { PublicEccParametersBuilder::new() } } impl From for TPMS_ECC_PARMS { fn from(public_ecc_parameters: PublicEccParameters) -> Self { TPMS_ECC_PARMS { symmetric: public_ecc_parameters.symmetric_definition_object.into(), scheme: public_ecc_parameters.ecc_scheme.into(), curveID: public_ecc_parameters.ecc_curve.into(), kdf: public_ecc_parameters.key_derivation_function_scheme.into(), } } } impl TryFrom for PublicEccParameters { type Error = Error; fn try_from(tpms_ecc_parms: TPMS_ECC_PARMS) -> Result { Ok(PublicEccParameters { symmetric_definition_object: tpms_ecc_parms.symmetric.try_into()?, ecc_scheme: tpms_ecc_parms.scheme.try_into()?, ecc_curve: tpms_ecc_parms.curveID.try_into()?, key_derivation_function_scheme: tpms_ecc_parms.kdf.try_into()?, }) } } tss-esapi-7.4.0/src/structures/tagged/public/keyed_hash.rs000064400000000000000000000023671046102023000217510ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{structures::KeyedHashScheme, tss2_esys::TPMS_KEYEDHASH_PARMS, Error, Result}; use std::convert::{TryFrom, TryInto}; /// Keyed hash parameters /// /// # Details /// Corresponds to TPMS_KEYEDHASH_PARMS /// /// These keyed hash parameters are specific to the [`crate::structures::Public`] type. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct PublicKeyedHashParameters { keyed_hash_scheme: KeyedHashScheme, } impl PublicKeyedHashParameters { pub const fn new(keyed_hash_scheme: KeyedHashScheme) -> PublicKeyedHashParameters { PublicKeyedHashParameters { keyed_hash_scheme } } } impl TryFrom for PublicKeyedHashParameters { type Error = Error; fn try_from(tpms_keyed_hash_parms: TPMS_KEYEDHASH_PARMS) -> Result { Ok(PublicKeyedHashParameters { keyed_hash_scheme: tpms_keyed_hash_parms.scheme.try_into()?, }) } } impl From for TPMS_KEYEDHASH_PARMS { fn from(public_keyed_hash_prams: PublicKeyedHashParameters) -> Self { TPMS_KEYEDHASH_PARMS { scheme: public_keyed_hash_prams.keyed_hash_scheme.into(), } } } tss-esapi-7.4.0/src/structures/tagged/public/rsa.rs000064400000000000000000000314531046102023000204300ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ interface_types::{algorithm::RsaSchemeAlgorithm, key_bits::RsaKeyBits}, structures::{RsaScheme, SymmetricDefinitionObject}, tss2_esys::{TPMS_RSA_PARMS, UINT32}, Error, Result, WrapperErrorKind, }; use log::error; use std::convert::{TryFrom, TryInto}; /// Builder for `TPMS_RSA_PARMS` values. #[derive(Copy, Clone, Default, Debug)] pub struct PublicRsaParametersBuilder { symmetric: Option, rsa_scheme: Option, key_bits: Option, exponent: Option, is_signing_key: bool, is_decryption_key: bool, restricted: bool, } impl PublicRsaParametersBuilder { /// Creates a new [PublicRsaParametersBuilder] pub const fn new() -> Self { PublicRsaParametersBuilder { symmetric: None, rsa_scheme: None, key_bits: None, exponent: None, is_signing_key: false, is_decryption_key: false, restricted: false, } } /// Creates a [PublicRsaParametersBuilder] that is setup /// to build a restructed decryption key. pub const fn new_restricted_decryption_key( symmetric: SymmetricDefinitionObject, key_bits: RsaKeyBits, exponent: RsaExponent, ) -> Self { PublicRsaParametersBuilder { symmetric: Some(symmetric), rsa_scheme: Some(RsaScheme::Null), key_bits: Some(key_bits), exponent: Some(exponent), is_signing_key: false, is_decryption_key: true, restricted: true, } } /// Creates a [PublicRsaParametersBuilder] that is setup /// to build an unrestricted signing key. pub const fn new_unrestricted_signing_key( rsa_scheme: RsaScheme, key_bits: RsaKeyBits, exponent: RsaExponent, ) -> Self { PublicRsaParametersBuilder { symmetric: None, rsa_scheme: Some(rsa_scheme), key_bits: Some(key_bits), exponent: Some(exponent), is_signing_key: true, is_decryption_key: false, restricted: false, } } /// Adds a [SymmetricDefinitionObject] to the [PublicRsaParametersBuilder]. pub const fn with_symmetric(mut self, symmetric: SymmetricDefinitionObject) -> Self { self.symmetric = Some(symmetric); self } /// Adds a [RsaScheme] to the [PublicRsaParametersBuilder]. pub const fn with_scheme(mut self, rsa_scheme: RsaScheme) -> Self { self.rsa_scheme = Some(rsa_scheme); self } /// Adds [RsaKeyBits] to the [PublicRsaParametersBuilder]. pub const fn with_key_bits(mut self, key_bits: RsaKeyBits) -> Self { self.key_bits = Some(key_bits); self } /// Adds [RsaExponent] to the [PublicRsaParametersBuilder]. pub const fn with_exponent(mut self, exponent: RsaExponent) -> Self { self.exponent = Some(exponent); self } /// Adds a flag that indicates if the key is going to be used /// for signing to the [PublicRsaParametersBuilder]. /// /// # Arguments /// * `set` - `true` inidcates that the key is going to be used for signing operations. /// `false` indicates that the key is not going to be used for signing operations. pub const fn with_is_signing_key(mut self, set: bool) -> Self { self.is_signing_key = set; self } /// Adds a flag that indicates if the key is going to be used for /// decryption to the [PublicRsaParametersBuilder]. /// /// # Arguments /// * `set` - `true` indicates that the key is going to be used for decryption operations. /// `false` indicates that the key is not going to be used for decryption operations. pub const fn with_is_decryption_key(mut self, set: bool) -> Self { self.is_decryption_key = set; self } /// Adds a flag that inidcates if the key is going to be restrictied to /// the [PublicRsaParametersBuilder]. /// /// # Arguments /// * `set` - `true` indicates that it is going to be a restricted key. /// `false` indicates that it is going to be a non restricted key. pub const fn with_restricted(mut self, set: bool) -> Self { self.restricted = set; self } /// Build an object given the previously provided parameters. /// /// The only mandatory parameter is the asymmetric scheme. /// /// # Errors /// * if no asymmetric scheme is set, `ParamsMissing` wrapper error is returned. /// * if the `for_signing`, `for_decryption` and `restricted` parameters are /// inconsistent with the rest of the parameters, `InconsistentParams` wrapper /// error is returned pub fn build(self) -> Result { let rsa_scheme = self.rsa_scheme.ok_or_else(|| { error!("Scheme parameter is required and has not been set in the PublicRsaParametersBuilder"); Error::local_error(WrapperErrorKind::ParamsMissing) })?; let key_bits = self.key_bits.ok_or_else(|| { error!("Key bits parameter is required and has not been set in the PublicRsaParametersBuilder"); Error::local_error(WrapperErrorKind::ParamsMissing) })?; if self.restricted && self.is_decryption_key { if let Some(symmetric) = self.symmetric { if symmetric.is_null() { error!("Found symmetric parameter but it was Null but 'restricted' and 'is_decrypt_key' are set to true"); return Err(Error::local_error(WrapperErrorKind::InconsistentParams)); } } else { error!("Found symmetric parameter, expected it to be Null nor not set at all because 'restricted' and 'is_decrypt_key' are set to false"); return Err(Error::local_error(WrapperErrorKind::ParamsMissing)); } } else if let Some(symmetric) = self.symmetric { if !symmetric.is_null() { error!("Found symmetric parameter, expected it to be Null nor not set at all because 'restricted' and 'is_decrypt_key' are set to false"); return Err(Error::local_error(WrapperErrorKind::InconsistentParams)); } } // TODO: Figure out if it actually should be allowed to not provide // these parameters. let symmetric_definition_object = self.symmetric.unwrap_or(SymmetricDefinitionObject::Null); let exponent = self.exponent.unwrap_or_default(); if self.restricted { if self.is_signing_key && rsa_scheme.algorithm() != RsaSchemeAlgorithm::RsaPss && rsa_scheme.algorithm() != RsaSchemeAlgorithm::RsaSsa { error!("Invalid rsa scheme algorithm provided with 'restricted' and 'is_signing_key' set to true"); return Err(Error::local_error(WrapperErrorKind::InconsistentParams)); } if self.is_decryption_key && rsa_scheme.algorithm() != RsaSchemeAlgorithm::Null { error!("Invalid rsa scheme algorithm provided with 'restricted' and 'is_decryption_key' set to true"); return Err(Error::local_error(WrapperErrorKind::InconsistentParams)); } } else { if self.is_decryption_key && self.is_signing_key && rsa_scheme.algorithm() != RsaSchemeAlgorithm::Null { error!("Invalid rsa scheme algorithm provided with 'restricted' set to false and 'is_decryption_key' and 'is_signing_key' set to true"); return Err(Error::local_error(WrapperErrorKind::InconsistentParams)); } if self.is_signing_key && rsa_scheme.algorithm() != RsaSchemeAlgorithm::RsaPss && rsa_scheme.algorithm() != RsaSchemeAlgorithm::RsaSsa && rsa_scheme.algorithm() != RsaSchemeAlgorithm::Null { error!("Invalid rsa scheme algorithm provided with 'restricted' set to false and 'is_signing_key' set to true"); return Err(Error::local_error(WrapperErrorKind::InconsistentParams)); } if self.is_decryption_key && rsa_scheme.algorithm() != RsaSchemeAlgorithm::RsaEs && rsa_scheme.algorithm() != RsaSchemeAlgorithm::Oaep && rsa_scheme.algorithm() != RsaSchemeAlgorithm::Null { error!("Invalid rsa scheme algorithm provided with 'restricted' set to false and 'is_decryption_key' set to true"); return Err(Error::local_error(WrapperErrorKind::InconsistentParams)); } } Ok(PublicRsaParameters { symmetric_definition_object, rsa_scheme, key_bits, exponent, }) } } /// Structure used to hold the value of a RSA exponent #[derive(Default, Clone, Debug, Copy, PartialEq, Eq)] pub struct RsaExponent { value: u32, } impl RsaExponent { /// Empty exponent (internal value is 0), which is treated by TPMs /// as a shorthand for the default value (2^16 + 1). pub const ZERO_EXPONENT: Self = RsaExponent { value: 0 }; /// Function for creating a new RsaExponent /// /// # Warning /// Will not check whether the value is a valid exponent for RSA. /// /// # Errors /// Will return an error if the value passed into the function /// is not a valid RSA exponent. pub fn create(value: u32) -> Result { Ok(RsaExponent { value }) } /// Method that returns the value of the rsa exponent. pub const fn value(&self) -> u32 { self.value } /// No-op. Does not check whether the value is a valid exponent for RSA. #[deprecated( since = "7.0.1", note = "TPMs are only mandated to support 0 as an exponent, with support for and checking of other values being done differently by each manufacturer. See discussion here: https://github.com/parallaxsecond/rust-tss-esapi/pull/332" )] pub fn is_valid(_: u32) -> bool { true } } impl From for UINT32 { fn from(rsa_exponent: RsaExponent) -> Self { rsa_exponent.value } } impl TryFrom for RsaExponent { type Error = Error; fn try_from(tpm_uint32_value: UINT32) -> Result { Ok(RsaExponent { value: tpm_uint32_value, }) } } /// Structure holding the RSA specific parameters. /// /// # Details /// This corresponds to TPMS_RSA_PARMS /// /// These rsa parameters are specific to the [`crate::structures::Public`] type. #[derive(Clone, Debug, Copy, PartialEq, Eq)] pub struct PublicRsaParameters { symmetric_definition_object: SymmetricDefinitionObject, rsa_scheme: RsaScheme, key_bits: RsaKeyBits, exponent: RsaExponent, } impl PublicRsaParameters { /// Function for creating new [PublicRsaParameters] structure pub const fn new( symmetric_definition_object: SymmetricDefinitionObject, rsa_scheme: RsaScheme, key_bits: RsaKeyBits, exponent: RsaExponent, ) -> Self { PublicRsaParameters { symmetric_definition_object, rsa_scheme, key_bits, exponent, } } /// Returns the [SymmetricDefinitionObject]. pub const fn symmetric_definition_object(&self) -> SymmetricDefinitionObject { self.symmetric_definition_object } /// Returns the [RsaScheme] pub const fn rsa_scheme(&self) -> RsaScheme { self.rsa_scheme } /// Returns the [RsaKeyBits] pub const fn key_bits(&self) -> RsaKeyBits { self.key_bits } /// Returns the exponent in the form of a [RsaExponent] pub const fn exponent(&self) -> RsaExponent { self.exponent } /// Get a builder for this structure pub const fn builder() -> PublicRsaParametersBuilder { PublicRsaParametersBuilder::new() } } impl From for TPMS_RSA_PARMS { fn from(public_rsa_parameters: PublicRsaParameters) -> Self { TPMS_RSA_PARMS { symmetric: public_rsa_parameters.symmetric_definition_object.into(), scheme: public_rsa_parameters.rsa_scheme.into(), keyBits: public_rsa_parameters.key_bits.into(), exponent: public_rsa_parameters.exponent.into(), } } } impl TryFrom for PublicRsaParameters { type Error = Error; fn try_from(tpms_rsa_parms: TPMS_RSA_PARMS) -> Result { Ok(PublicRsaParameters { symmetric_definition_object: tpms_rsa_parms.symmetric.try_into()?, rsa_scheme: tpms_rsa_parms.scheme.try_into()?, key_bits: tpms_rsa_parms.keyBits.try_into()?, exponent: tpms_rsa_parms.exponent.try_into()?, }) } } tss-esapi-7.4.0/src/structures/tagged/public.rs000064400000000000000000000542161046102023000176450ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 pub mod ecc; pub mod keyed_hash; pub mod rsa; use crate::{ attributes::ObjectAttributes, interface_types::algorithm::{HashingAlgorithm, PublicAlgorithm}, structures::{Digest, EccPoint, PublicKeyRsa, SymmetricCipherParameters}, traits::{Marshall, UnMarshall}, tss2_esys::{TPM2B_PUBLIC, TPMT_PUBLIC}, Error, Result, WrapperErrorKind, }; use ecc::PublicEccParameters; use keyed_hash::PublicKeyedHashParameters; use rsa::PublicRsaParameters; use log::error; use std::convert::{TryFrom, TryInto}; use tss_esapi_sys::{TPMU_PUBLIC_ID, TPMU_PUBLIC_PARMS}; /// A builder for the [Public] type. #[derive(Debug, Clone)] pub struct PublicBuilder { public_algorithm: Option, object_attributes: Option, name_hashing_algorithm: Option, auth_policy: Option, rsa_parameters: Option, rsa_unique_identifier: Option, keyed_hash_parameters: Option, keyed_hash_unique_identifier: Option, ecc_parameters: Option, ecc_unique_identifier: Option, symmetric_cipher_parameters: Option, symmetric_cipher_unique_identifier: Option, } impl PublicBuilder { /// Creates a new [PublicBuilder] /// /// # Details /// Builds the [Public] type using the provided parameters. Parameters /// associated with other algorithms then the provided public algorithm /// will be ignored. pub const fn new() -> Self { PublicBuilder { public_algorithm: None, object_attributes: None, name_hashing_algorithm: None, auth_policy: None, rsa_parameters: None, rsa_unique_identifier: None, keyed_hash_parameters: None, keyed_hash_unique_identifier: None, ecc_parameters: None, ecc_unique_identifier: None, symmetric_cipher_parameters: None, symmetric_cipher_unique_identifier: None, } } /// Adds the public algorithm for the [Public] structure /// to the builder. pub const fn with_public_algorithm(mut self, public_algorithm: PublicAlgorithm) -> Self { self.public_algorithm = Some(public_algorithm); self } /// Adds the attributes of the [Public] structure /// to the builder pub const fn with_object_attributes(mut self, object_attributes: ObjectAttributes) -> Self { self.object_attributes = Some(object_attributes); self } /// Adds the name hash algorithm for the [Public] structure /// to the builder. pub const fn with_name_hashing_algorithm( mut self, name_hashing_algorithm: HashingAlgorithm, ) -> Self { self.name_hashing_algorithm = Some(name_hashing_algorithm); self } /// Adds the auth policy for the [Public] structure /// to the builder pub fn with_auth_policy(mut self, auth_policy: Digest) -> Self { self.auth_policy = Some(auth_policy); self } /// Adds the RSA parameters for the [Public] structure /// to the builder. /// /// # Details /// This is required if the public algorithm is set to /// [Rsa][`crate::interface_types::algorithm::PublicAlgorithm::Rsa]. pub fn with_rsa_parameters(mut self, rsa_parameters: PublicRsaParameters) -> Self { self.rsa_parameters = Some(rsa_parameters); self } /// Adds the RSA unique identifier for the [Public] structure /// to the builder. /// /// # Details /// This is required if the public algorithm is set to /// [Rsa][`crate::interface_types::algorithm::PublicAlgorithm::Rsa]. /// /// The unique identifier is the public key. pub fn with_rsa_unique_identifier(mut self, rsa_unique_identifier: PublicKeyRsa) -> Self { self.rsa_unique_identifier = Some(rsa_unique_identifier); self } /// Adds the keyed hash parameters for the [Public] structure /// to the builder. /// /// # Details /// This is required if the public algorithm is set to /// [KeyedHash][`crate::interface_types::algorithm::PublicAlgorithm::KeyedHash]. pub fn with_keyed_hash_parameters( mut self, keyed_hash_parameters: PublicKeyedHashParameters, ) -> Self { self.keyed_hash_parameters = Some(keyed_hash_parameters); self } /// Adds the keyed hash unique identifier for the [Public] structure /// to the builder. /// /// # Details /// This is required if the public algorithm is set to /// [KeyedHash][`crate::interface_types::algorithm::PublicAlgorithm::KeyedHash]. pub fn with_keyed_hash_unique_identifier( mut self, keyed_hash_unique_identifier: Digest, ) -> Self { self.keyed_hash_unique_identifier = Some(keyed_hash_unique_identifier); self } /// Adds the ECC parameters for the [Public] structure /// to the builder. /// /// # Details /// This is required if the public algorithm is set to /// [Ecc][`crate::interface_types::algorithm::PublicAlgorithm::Ecc]. pub const fn with_ecc_parameters(mut self, ecc_parameters: PublicEccParameters) -> Self { self.ecc_parameters = Some(ecc_parameters); self } /// Adds the ECC unique identifier for the [Public] structure /// to the builder. /// /// # Details /// This is required if the public algorithm is set to /// [Ecc][`crate::interface_types::algorithm::PublicAlgorithm::Ecc]. /// /// The unique identifier is a ecc point. pub fn with_ecc_unique_identifier(mut self, ecc_unique_identifier: EccPoint) -> Self { self.ecc_unique_identifier = Some(ecc_unique_identifier); self } /// Adds the symmetric cipher parameters for the [Public] structure /// to the builder. /// /// # Details /// This is required if the public algorithm is set to /// [SymCipher][`crate::interface_types::algorithm::PublicAlgorithm::SymCipher]. pub const fn with_symmetric_cipher_parameters( mut self, symmetric_cipher_parameters: SymmetricCipherParameters, ) -> Self { self.symmetric_cipher_parameters = Some(symmetric_cipher_parameters); self } /// Adds the symmetric cipher unique identifier for the [Public] structure /// to the builder. /// /// # Details /// This is required if the public algorithm is set to /// [SymCipher][`crate::interface_types::algorithm::PublicAlgorithm::SymCipher]. pub fn with_symmetric_cipher_unique_identifier( mut self, symmetric_cipher_unique_identifier: Digest, ) -> Self { self.symmetric_cipher_unique_identifier = Some(symmetric_cipher_unique_identifier); self } /// Builds the [Public] structure. /// /// # Errors /// Will return error if the public algorithm, object attributes or name /// hashing algorithm have not been set or if the parameters and unique identifier /// does not match the selected public algorithm. pub fn build(self) -> Result { let algorithm = self.public_algorithm.ok_or_else(|| { error!("Algorithm is required and has not been set in the PublicBuilder"); Error::local_error(WrapperErrorKind::ParamsMissing) })?; let object_attributes = self.object_attributes.ok_or_else(|| { error!("ObjectAttributes is required and has not been set in the PublicBuilder"); Error::local_error(WrapperErrorKind::ParamsMissing) })?; let name_hashing_algorithm = self.name_hashing_algorithm.ok_or_else(|| { error!( "The name hashing algorithm is required and has not been set in the PublicBuilder" ); Error::local_error(WrapperErrorKind::ParamsMissing) })?; let auth_policy = self.auth_policy.unwrap_or_default(); match algorithm { PublicAlgorithm::Rsa => { Ok(Public::Rsa { object_attributes, name_hashing_algorithm, auth_policy, parameters: self.rsa_parameters.ok_or_else(|| { error!("RSA parameters have not been set in the PublicBuilder even though the RSA algorithm had been selected."); Error::local_error(WrapperErrorKind::ParamsMissing) })?, unique: self.rsa_unique_identifier.ok_or_else(|| { error!("RSA unique identifier has not been set in the PublicBuilder even though the RSA algorithm had been selected. Consider using: .with_rsa_unique_identifier(&PublicKeyRsa::default())"); Error::local_error(WrapperErrorKind::ParamsMissing) })?, }) }, PublicAlgorithm::KeyedHash => { Ok(Public::KeyedHash { object_attributes, name_hashing_algorithm, auth_policy, parameters: self.keyed_hash_parameters.ok_or_else(|| { error!("Keyed hash parameters have not been set in the Public Builder even though the keyed hash algorithm have been selected"); Error::local_error(WrapperErrorKind::ParamsMissing) })?, unique: self.keyed_hash_unique_identifier.ok_or_else(|| { error!("Keyed hash unique identifier have not been set in the Public Builder even though the keyed hash algorithm have been selected. Consider using: .with_keyed_hash_unique_identifier(&Digest::default())"); Error::local_error(WrapperErrorKind::ParamsMissing) })?, }) }, PublicAlgorithm::Ecc => { Ok(Public::Ecc { object_attributes, name_hashing_algorithm, auth_policy, parameters: self.ecc_parameters.ok_or_else(|| { error!("ECC parameters have not been set in the Public Builder even though the ECC algorithm have been selected"); Error::local_error(WrapperErrorKind::ParamsMissing) })?, unique: self.ecc_unique_identifier.ok_or_else(|| { error!("ECC unique identifier have not been set in the Public Builder even though the ECC algorithm have been selected. Consider using: .with_ecc_unique_identifier(&EccPoint::default())"); Error::local_error(WrapperErrorKind::ParamsMissing) })?, }) } PublicAlgorithm::SymCipher => { Ok(Public::SymCipher { object_attributes, name_hashing_algorithm, auth_policy, parameters: self.symmetric_cipher_parameters.ok_or_else(|| { error!("Symmetric cipher parameters have not been set in the Public Builder even though the symmetric cipher algorithm have been selected"); Error::local_error(WrapperErrorKind::ParamsMissing) })?, unique: self.symmetric_cipher_unique_identifier.ok_or_else(|| { error!("Symmetric cipher unique identifier have not been set in the Public Builder even though the symmetric cipher algorithm have been selected. Consider using: .with_symmetric_cipher_unique_identifier(&Digest::default())"); Error::local_error(WrapperErrorKind::ParamsMissing) })?, }) } } } } /// Enum representing the Public structure. /// /// # Details /// This corresponds to TPMT_PUBLIC #[derive(Debug, Clone, Eq, PartialEq)] pub enum Public { Rsa { object_attributes: ObjectAttributes, name_hashing_algorithm: HashingAlgorithm, auth_policy: Digest, parameters: PublicRsaParameters, unique: PublicKeyRsa, }, KeyedHash { object_attributes: ObjectAttributes, name_hashing_algorithm: HashingAlgorithm, auth_policy: Digest, parameters: PublicKeyedHashParameters, unique: Digest, }, Ecc { object_attributes: ObjectAttributes, name_hashing_algorithm: HashingAlgorithm, auth_policy: Digest, parameters: PublicEccParameters, unique: EccPoint, }, SymCipher { object_attributes: ObjectAttributes, name_hashing_algorithm: HashingAlgorithm, auth_policy: Digest, parameters: SymmetricCipherParameters, unique: Digest, }, } impl Public { /// Returns the object attributes pub fn object_attributes(&self) -> ObjectAttributes { match self { Public::Rsa { object_attributes, .. } | Public::KeyedHash { object_attributes, .. } | Public::Ecc { object_attributes, .. } | Public::SymCipher { object_attributes, .. } => *object_attributes, } } /// Returns the name hashing algorithm pub fn name_hashing_algorithm(&self) -> HashingAlgorithm { match self { Public::Rsa { name_hashing_algorithm, .. } | Public::KeyedHash { name_hashing_algorithm, .. } | Public::Ecc { name_hashing_algorithm, .. } | Public::SymCipher { name_hashing_algorithm, .. } => *name_hashing_algorithm, } } /// Returns the auth policy digest. pub fn auth_policy(&self) -> &Digest { match self { Public::Rsa { auth_policy, .. } | Public::KeyedHash { auth_policy, .. } | Public::Ecc { auth_policy, .. } | Public::SymCipher { auth_policy, .. } => auth_policy, } } /// Get a builder for this structure pub const fn builder() -> PublicBuilder { PublicBuilder::new() } } impl From for TPMT_PUBLIC { fn from(public: Public) -> Self { match public { Public::Rsa { object_attributes, name_hashing_algorithm, auth_policy, parameters, unique, } => TPMT_PUBLIC { type_: PublicAlgorithm::Rsa.into(), nameAlg: name_hashing_algorithm.into(), objectAttributes: object_attributes.into(), authPolicy: auth_policy.into(), parameters: TPMU_PUBLIC_PARMS { rsaDetail: parameters.into(), }, unique: TPMU_PUBLIC_ID { rsa: unique.into() }, }, Public::KeyedHash { object_attributes, name_hashing_algorithm, auth_policy, parameters, unique, } => TPMT_PUBLIC { type_: PublicAlgorithm::KeyedHash.into(), nameAlg: name_hashing_algorithm.into(), objectAttributes: object_attributes.into(), authPolicy: auth_policy.into(), parameters: TPMU_PUBLIC_PARMS { keyedHashDetail: parameters.into(), }, unique: TPMU_PUBLIC_ID { keyedHash: unique.into(), }, }, Public::Ecc { object_attributes, name_hashing_algorithm, auth_policy, parameters, unique, } => TPMT_PUBLIC { type_: PublicAlgorithm::Ecc.into(), nameAlg: name_hashing_algorithm.into(), objectAttributes: object_attributes.into(), authPolicy: auth_policy.into(), parameters: TPMU_PUBLIC_PARMS { eccDetail: parameters.into(), }, unique: TPMU_PUBLIC_ID { ecc: unique.into() }, }, Public::SymCipher { object_attributes, name_hashing_algorithm, auth_policy, parameters, unique, } => TPMT_PUBLIC { type_: PublicAlgorithm::SymCipher.into(), nameAlg: name_hashing_algorithm.into(), objectAttributes: object_attributes.into(), authPolicy: auth_policy.into(), parameters: TPMU_PUBLIC_PARMS { symDetail: parameters.into(), }, unique: TPMU_PUBLIC_ID { sym: unique.into() }, }, } } } impl TryFrom for Public { type Error = Error; fn try_from(tpmt_public: TPMT_PUBLIC) -> Result { match PublicAlgorithm::try_from(tpmt_public.type_)? { PublicAlgorithm::Rsa => Ok(Public::Rsa { object_attributes: tpmt_public.objectAttributes.into(), name_hashing_algorithm: tpmt_public.nameAlg.try_into()?, auth_policy: tpmt_public.authPolicy.try_into()?, parameters: unsafe { tpmt_public.parameters.rsaDetail }.try_into()?, unique: unsafe { tpmt_public.unique.rsa }.try_into()?, }), PublicAlgorithm::KeyedHash => Ok(Public::KeyedHash { object_attributes: tpmt_public.objectAttributes.into(), name_hashing_algorithm: tpmt_public.nameAlg.try_into()?, auth_policy: tpmt_public.authPolicy.try_into()?, parameters: unsafe { tpmt_public.parameters.keyedHashDetail }.try_into()?, unique: unsafe { tpmt_public.unique.keyedHash }.try_into()?, }), PublicAlgorithm::Ecc => Ok(Public::Ecc { object_attributes: tpmt_public.objectAttributes.into(), name_hashing_algorithm: tpmt_public.nameAlg.try_into()?, auth_policy: tpmt_public.authPolicy.try_into()?, parameters: unsafe { tpmt_public.parameters.eccDetail }.try_into()?, unique: unsafe { tpmt_public.unique.ecc }.try_into()?, }), PublicAlgorithm::SymCipher => Ok(Public::SymCipher { object_attributes: tpmt_public.objectAttributes.into(), name_hashing_algorithm: tpmt_public.nameAlg.try_into()?, auth_policy: tpmt_public.authPolicy.try_into()?, parameters: unsafe { tpmt_public.parameters.symDetail }.try_into()?, unique: unsafe { tpmt_public.unique.sym }.try_into()?, }), } } } impl Marshall for Public { const BUFFER_SIZE: usize = std::mem::size_of::(); /// Produce a marshalled [TPMT_PUBLIC] /// /// Note: for [TPM2B_PUBLIC] marshalling use [PublicBuffer][`crate::structures::PublicBuffer] fn marshall(&self) -> Result> { let mut buffer = vec![0; Self::BUFFER_SIZE]; let mut offset = 0; let ret = Error::from_tss_rc(unsafe { crate::tss2_esys::Tss2_MU_TPMT_PUBLIC_Marshal( &self.clone().into(), buffer.as_mut_ptr(), Self::BUFFER_SIZE.try_into().map_err(|e| { error!("Failed to convert size of buffer to TSS size_t type: {}", e); Error::local_error(WrapperErrorKind::InvalidParam) })?, &mut offset, ) }); if !ret.is_success() { return Err(ret); } let checked_offset = usize::try_from(offset).map_err(|e| { error!("Failed to parse offset as usize: {}", e); Error::local_error(WrapperErrorKind::InvalidParam) })?; buffer.truncate(checked_offset); Ok(buffer) } } impl UnMarshall for Public { /// Unmarshall the structure from [`TPMT_PUBLIC`] /// /// Note: for [TPM2B_PUBLIC] unmarshalling use [PublicBuffer][`crate::structures::PublicBuffer] fn unmarshall(marshalled_data: &[u8]) -> Result { let mut dest = TPMT_PUBLIC::default(); let mut offset = 0; let ret = Error::from_tss_rc(unsafe { crate::tss2_esys::Tss2_MU_TPMT_PUBLIC_Unmarshal( marshalled_data.as_ptr(), marshalled_data.len().try_into().map_err(|e| { error!("Failed to convert length of marshalled data: {}", e); Error::local_error(WrapperErrorKind::InvalidParam) })?, &mut offset, &mut dest, ) }); if !ret.is_success() { return Err(ret); } Public::try_from(dest) } } impl TryFrom for Public { type Error = Error; fn try_from(tpm2b_public: TPM2B_PUBLIC) -> Result { Public::try_from(tpm2b_public.publicArea) } } impl TryFrom for TPM2B_PUBLIC { type Error = Error; fn try_from(public: Public) -> Result { let mut buffer = vec![0; Public::BUFFER_SIZE]; let mut size = 0; let public_area = TPMT_PUBLIC::from(public); let ret = Error::from_tss_rc(unsafe { crate::tss2_esys::Tss2_MU_TPMT_PUBLIC_Marshal( &public_area, buffer.as_mut_ptr(), Public::BUFFER_SIZE.try_into().map_err(|e| { error!("Failed to convert size of buffer to TSS size_t type: {}", e); Error::local_error(WrapperErrorKind::InvalidParam) })?, &mut size, ) }); if !ret.is_success() { return Err(ret); } Ok(TPM2B_PUBLIC { size: size.try_into().map_err(|e| { error!( "Failed to convert size of buffer from TSS size_t type: {}", e ); Error::local_error(WrapperErrorKind::InvalidParam) })?, publicArea: public_area, }) } } tss-esapi-7.4.0/src/structures/tagged/schemes.rs000064400000000000000000000664351046102023000200240ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ interface_types::algorithm::{ EccSchemeAlgorithm, HashingAlgorithm, KeyDerivationFunction, KeyedHashSchemeAlgorithm, RsaDecryptAlgorithm, RsaSchemeAlgorithm, SignatureSchemeAlgorithm, }, structures::schemes::{EcDaaScheme, HashScheme, HmacScheme, XorScheme}, tss2_esys::{ TPMT_ECC_SCHEME, TPMT_KDF_SCHEME, TPMT_KEYEDHASH_SCHEME, TPMT_RSA_DECRYPT, TPMT_RSA_SCHEME, TPMT_SIG_SCHEME, TPMU_ASYM_SCHEME, TPMU_KDF_SCHEME, TPMU_SCHEME_KEYEDHASH, TPMU_SIG_SCHEME, }, Error, Result, WrapperErrorKind, }; use log::error; use std::convert::{TryFrom, TryInto}; /// Enum representing the keyed hash scheme. /// /// # Details /// This corresponds to TPMT_SCHEME_KEYEDHASH. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum KeyedHashScheme { Xor { xor_scheme: XorScheme }, Hmac { hmac_scheme: HmacScheme }, Null, } impl KeyedHashScheme { pub const HMAC_SHA_256: KeyedHashScheme = KeyedHashScheme::Hmac { hmac_scheme: HmacScheme::new(HashingAlgorithm::Sha256), }; } impl From for TPMT_KEYEDHASH_SCHEME { fn from(keyed_hash_scheme: KeyedHashScheme) -> Self { match keyed_hash_scheme { KeyedHashScheme::Xor { xor_scheme } => TPMT_KEYEDHASH_SCHEME { scheme: KeyedHashSchemeAlgorithm::Xor.into(), details: TPMU_SCHEME_KEYEDHASH { exclusiveOr: xor_scheme.into(), }, }, KeyedHashScheme::Hmac { hmac_scheme } => TPMT_KEYEDHASH_SCHEME { scheme: KeyedHashSchemeAlgorithm::Hmac.into(), details: TPMU_SCHEME_KEYEDHASH { hmac: hmac_scheme.into(), }, }, KeyedHashScheme::Null => TPMT_KEYEDHASH_SCHEME { scheme: KeyedHashSchemeAlgorithm::Null.into(), details: Default::default(), }, } } } impl TryFrom for KeyedHashScheme { type Error = Error; fn try_from(tpmt_keyedhash_scheme: TPMT_KEYEDHASH_SCHEME) -> Result { match KeyedHashSchemeAlgorithm::try_from(tpmt_keyedhash_scheme.scheme)? { KeyedHashSchemeAlgorithm::Xor => Ok(KeyedHashScheme::Xor { xor_scheme: unsafe { tpmt_keyedhash_scheme.details.exclusiveOr }.try_into()?, }), KeyedHashSchemeAlgorithm::Hmac => Ok(KeyedHashScheme::Hmac { hmac_scheme: unsafe { tpmt_keyedhash_scheme.details.hmac }.try_into()?, }), KeyedHashSchemeAlgorithm::Null => Ok(KeyedHashScheme::Null), } } } /// Enum representing the rsa scheme /// /// # Details /// This corresponds to TPMT_RSA_SCHEME. /// This uses a subset of the TPMU_ASYM_SCHEME /// that has the TPMI_ALG_RSA_SCHEME as selector. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum RsaScheme { RsaSsa(HashScheme), RsaEs, RsaPss(HashScheme), Oaep(HashScheme), Null, } impl RsaScheme { /// Creates a new RsaScheme /// /// # Errors /// - `InconsistentParams` error will be returned if no hashing algorithm /// is provided when creating RSA scheme of type RSA SSA, RSA PSS and OAEP /// or if a hashing algorithm is provided when creating a RSA scheme pub fn create( rsa_scheme_algorithm: RsaSchemeAlgorithm, hashing_algorithm: Option, ) -> Result { match rsa_scheme_algorithm { RsaSchemeAlgorithm::RsaSsa => Ok(RsaScheme::RsaSsa(HashScheme::new( hashing_algorithm.ok_or_else(|| { error!( "Hashing algorithm is required when creating RSA scheme of type RSA SSA" ); Error::local_error(WrapperErrorKind::InconsistentParams) })?, ))), RsaSchemeAlgorithm::RsaEs => { if hashing_algorithm.is_none() { Ok(RsaScheme::RsaEs) } else { error!("A hashing algorithm shall not be provided when creating RSA scheme of type RSA ES"); Err(Error::local_error(WrapperErrorKind::InconsistentParams)) } } RsaSchemeAlgorithm::RsaPss => Ok(RsaScheme::RsaPss(HashScheme::new( hashing_algorithm.ok_or_else(|| { error!( "Hashing algorithm is required when creating RSA scheme of type RSA PSS" ); Error::local_error(WrapperErrorKind::InconsistentParams) })?, ))), RsaSchemeAlgorithm::Oaep => Ok(RsaScheme::Oaep(HashScheme::new( hashing_algorithm.ok_or_else(|| { error!("Hashing algorithm is required when creating RSA scheme of type OAEP"); Error::local_error(WrapperErrorKind::InconsistentParams) })?, ))), RsaSchemeAlgorithm::Null => { if hashing_algorithm.is_none() { Ok(RsaScheme::Null) } else { error!("A hashing algorithm shall not be provided when creating RSA scheme of type Null"); Err(Error::local_error(WrapperErrorKind::InconsistentParams)) } } } } /// Returns the rsa scheme algorithm pub fn algorithm(&self) -> RsaSchemeAlgorithm { match self { RsaScheme::RsaSsa(_) => RsaSchemeAlgorithm::RsaSsa, RsaScheme::RsaEs => RsaSchemeAlgorithm::RsaEs, RsaScheme::RsaPss(_) => RsaSchemeAlgorithm::RsaPss, RsaScheme::Oaep(_) => RsaSchemeAlgorithm::Oaep, RsaScheme::Null => RsaSchemeAlgorithm::Null, } } } impl From for TPMT_RSA_SCHEME { fn from(rsa_scheme: RsaScheme) -> Self { match rsa_scheme { RsaScheme::RsaSsa(hash_scheme) => TPMT_RSA_SCHEME { scheme: rsa_scheme.algorithm().into(), details: TPMU_ASYM_SCHEME { rsassa: hash_scheme.into(), }, }, RsaScheme::RsaEs => TPMT_RSA_SCHEME { scheme: rsa_scheme.algorithm().into(), details: TPMU_ASYM_SCHEME { rsaes: Default::default(), }, }, RsaScheme::RsaPss(hash_scheme) => TPMT_RSA_SCHEME { scheme: rsa_scheme.algorithm().into(), details: TPMU_ASYM_SCHEME { rsapss: hash_scheme.into(), }, }, RsaScheme::Oaep(hash_scheme) => TPMT_RSA_SCHEME { scheme: rsa_scheme.algorithm().into(), details: TPMU_ASYM_SCHEME { oaep: hash_scheme.into(), }, }, RsaScheme::Null => TPMT_RSA_SCHEME { scheme: rsa_scheme.algorithm().into(), details: Default::default(), }, } } } impl TryFrom for RsaScheme { type Error = Error; fn try_from(tpmt_rsa_scheme: TPMT_RSA_SCHEME) -> Result { match RsaSchemeAlgorithm::try_from(tpmt_rsa_scheme.scheme)? { RsaSchemeAlgorithm::RsaSsa => Ok(RsaScheme::RsaSsa( unsafe { tpmt_rsa_scheme.details.rsassa }.try_into()?, )), RsaSchemeAlgorithm::RsaEs => Ok(RsaScheme::RsaEs), RsaSchemeAlgorithm::RsaPss => Ok(RsaScheme::RsaPss( unsafe { tpmt_rsa_scheme.details.rsapss }.try_into()?, )), RsaSchemeAlgorithm::Oaep => Ok(RsaScheme::Oaep( unsafe { tpmt_rsa_scheme.details.oaep }.try_into()?, )), RsaSchemeAlgorithm::Null => Ok(RsaScheme::Null), } } } /// Enum representing the ecc scheme /// /// # Details /// This corresponds to TPMT_ECC_SCHEME. /// This uses a subset of the TPMU_ASYM_SCHEME /// that has the TPMI_ALG_ECC_SCHEME as selector. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum EccScheme { EcDsa(HashScheme), EcDh(HashScheme), EcDaa(EcDaaScheme), Sm2(HashScheme), EcSchnorr(HashScheme), EcMqv(HashScheme), Null, } impl EccScheme { pub fn create( ecc_scheme_algorithm: EccSchemeAlgorithm, hashing_algorithm: Option, count: Option, ) -> Result { match ecc_scheme_algorithm { EccSchemeAlgorithm::EcDsa => Ok(EccScheme::EcDsa(HashScheme::new( hashing_algorithm.ok_or_else(|| { error!("Hashing algorithm is required when creating ECC scheme of type EC DSA"); Error::local_error(WrapperErrorKind::ParamsMissing) })?, ))), EccSchemeAlgorithm::EcDh => Ok(EccScheme::EcDh(HashScheme::new( hashing_algorithm.ok_or_else(|| { error!("Hashing algorithm is required when creating ECC scheme of type EC DH"); Error::local_error(WrapperErrorKind::ParamsMissing) })?, ))), EccSchemeAlgorithm::EcDaa => Ok(EccScheme::EcDaa(EcDaaScheme::new( hashing_algorithm.ok_or_else(|| { error!("Hashing algorithm is required when creating ECC scheme of type EC DAA"); Error::local_error(WrapperErrorKind::ParamsMissing) })?, count.ok_or_else(|| { error!("Count is required when creating ECC scheme of type EC DAA"); Error::local_error(WrapperErrorKind::ParamsMissing) })?, ))), EccSchemeAlgorithm::Sm2 => Ok(EccScheme::Sm2(HashScheme::new( hashing_algorithm.ok_or_else(|| { error!("Hashing algorithm is required when creating ECC scheme of type EC SM2"); Error::local_error(WrapperErrorKind::ParamsMissing) })?, ))), EccSchemeAlgorithm::EcSchnorr => Ok(EccScheme::EcSchnorr(HashScheme::new( hashing_algorithm.ok_or_else(|| { error!( "Hashing algorithm is required when creating ECC scheme of type EC SCHNORR" ); Error::local_error(WrapperErrorKind::ParamsMissing) })?, ))), EccSchemeAlgorithm::EcMqv => Ok(EccScheme::EcMqv(HashScheme::new( hashing_algorithm.ok_or_else(|| { error!("Hashing algorithm is required when creating ECC scheme of type EC MQV"); Error::local_error(WrapperErrorKind::ParamsMissing) })?, ))), EccSchemeAlgorithm::Null => { if hashing_algorithm.is_none() { Ok(EccScheme::Null) } else { error!("A hashing algorithm shall not be provided when creating ECC scheme of type Null"); Err(Error::local_error(WrapperErrorKind::InconsistentParams)) } } } } pub fn algorithm(&self) -> EccSchemeAlgorithm { match self { EccScheme::EcDsa(_) => EccSchemeAlgorithm::EcDsa, EccScheme::EcDh(_) => EccSchemeAlgorithm::EcDh, EccScheme::EcDaa(_) => EccSchemeAlgorithm::EcDaa, EccScheme::Sm2(_) => EccSchemeAlgorithm::Sm2, EccScheme::EcSchnorr(_) => EccSchemeAlgorithm::EcSchnorr, EccScheme::EcMqv(_) => EccSchemeAlgorithm::EcMqv, EccScheme::Null => EccSchemeAlgorithm::Null, } } } impl From for TPMT_ECC_SCHEME { fn from(ecc_scheme: EccScheme) -> Self { match ecc_scheme { EccScheme::EcDsa(hash_scheme) => TPMT_ECC_SCHEME { scheme: ecc_scheme.algorithm().into(), details: TPMU_ASYM_SCHEME { ecdsa: hash_scheme.into(), }, }, EccScheme::EcDh(hash_scheme) => TPMT_ECC_SCHEME { scheme: ecc_scheme.algorithm().into(), details: TPMU_ASYM_SCHEME { ecdh: hash_scheme.into(), }, }, EccScheme::EcDaa(ec_daa_scheme) => TPMT_ECC_SCHEME { scheme: ecc_scheme.algorithm().into(), details: TPMU_ASYM_SCHEME { ecdaa: ec_daa_scheme.into(), }, }, EccScheme::Sm2(hash_scheme) => TPMT_ECC_SCHEME { scheme: ecc_scheme.algorithm().into(), details: TPMU_ASYM_SCHEME { sm2: hash_scheme.into(), }, }, EccScheme::EcSchnorr(hash_scheme) => TPMT_ECC_SCHEME { scheme: ecc_scheme.algorithm().into(), details: TPMU_ASYM_SCHEME { ecschnorr: hash_scheme.into(), }, }, EccScheme::EcMqv(hash_scheme) => TPMT_ECC_SCHEME { scheme: ecc_scheme.algorithm().into(), details: TPMU_ASYM_SCHEME { ecmqv: hash_scheme.into(), }, }, EccScheme::Null => TPMT_ECC_SCHEME { scheme: ecc_scheme.algorithm().into(), details: Default::default(), }, } } } impl TryFrom for EccScheme { type Error = Error; fn try_from(tpmt_ecc_scheme: TPMT_ECC_SCHEME) -> Result { match EccSchemeAlgorithm::try_from(tpmt_ecc_scheme.scheme)? { EccSchemeAlgorithm::EcDsa => Ok(EccScheme::EcDsa( unsafe { tpmt_ecc_scheme.details.ecdsa }.try_into()?, )), EccSchemeAlgorithm::EcDh => Ok(EccScheme::EcDh( unsafe { tpmt_ecc_scheme.details.ecdh }.try_into()?, )), EccSchemeAlgorithm::EcDaa => Ok(EccScheme::EcDaa( unsafe { tpmt_ecc_scheme.details.ecdaa }.try_into()?, )), EccSchemeAlgorithm::Sm2 => Ok(EccScheme::Sm2( unsafe { tpmt_ecc_scheme.details.sm2 }.try_into()?, )), EccSchemeAlgorithm::EcSchnorr => Ok(EccScheme::EcSchnorr( unsafe { tpmt_ecc_scheme.details.ecschnorr }.try_into()?, )), EccSchemeAlgorithm::EcMqv => Ok(EccScheme::EcMqv( unsafe { tpmt_ecc_scheme.details.ecmqv }.try_into()?, )), EccSchemeAlgorithm::Null => Ok(EccScheme::Null), } } } /// Enum representing the kdf scheme /// /// # Details /// This corresponds to TPMT_KDF_SCHEME. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum KeyDerivationFunctionScheme { Kdf1Sp800_56a(HashScheme), Kdf2(HashScheme), Kdf1Sp800_108(HashScheme), Mgf1(HashScheme), Null, } impl From for TPMT_KDF_SCHEME { fn from(key_derivation_function_scheme: KeyDerivationFunctionScheme) -> Self { match key_derivation_function_scheme { KeyDerivationFunctionScheme::Kdf1Sp800_56a(hash_scheme) => TPMT_KDF_SCHEME { scheme: KeyDerivationFunction::Kdf1Sp800_56a.into(), details: TPMU_KDF_SCHEME { kdf1_sp800_56a: hash_scheme.into(), }, }, KeyDerivationFunctionScheme::Kdf2(hash_scheme) => TPMT_KDF_SCHEME { scheme: KeyDerivationFunction::Kdf2.into(), details: TPMU_KDF_SCHEME { kdf2: hash_scheme.into(), }, }, KeyDerivationFunctionScheme::Kdf1Sp800_108(hash_scheme) => TPMT_KDF_SCHEME { scheme: KeyDerivationFunction::Kdf1Sp800_108.into(), details: TPMU_KDF_SCHEME { kdf1_sp800_108: hash_scheme.into(), }, }, KeyDerivationFunctionScheme::Mgf1(hash_scheme) => TPMT_KDF_SCHEME { scheme: KeyDerivationFunction::Mgf1.into(), details: TPMU_KDF_SCHEME { mgf1: hash_scheme.into(), }, }, KeyDerivationFunctionScheme::Null => TPMT_KDF_SCHEME { scheme: KeyDerivationFunction::Null.into(), details: Default::default(), }, } } } impl TryFrom for KeyDerivationFunctionScheme { type Error = Error; fn try_from(tpmt_kdf_scheme: TPMT_KDF_SCHEME) -> Result { match KeyDerivationFunction::try_from(tpmt_kdf_scheme.scheme)? { KeyDerivationFunction::Kdf1Sp800_56a => Ok(KeyDerivationFunctionScheme::Kdf1Sp800_56a( unsafe { tpmt_kdf_scheme.details.kdf1_sp800_56a }.try_into()?, )), KeyDerivationFunction::Kdf2 => Ok(KeyDerivationFunctionScheme::Kdf2( unsafe { tpmt_kdf_scheme.details.kdf2 }.try_into()?, )), KeyDerivationFunction::Kdf1Sp800_108 => Ok(KeyDerivationFunctionScheme::Kdf1Sp800_108( unsafe { tpmt_kdf_scheme.details.kdf1_sp800_108 }.try_into()?, )), KeyDerivationFunction::Mgf1 => Ok(KeyDerivationFunctionScheme::Mgf1( unsafe { tpmt_kdf_scheme.details.mgf1 }.try_into()?, )), KeyDerivationFunction::Null => Ok(KeyDerivationFunctionScheme::Null), } } } /// Enum representing the rsa decryption scheme /// /// # Details /// This corresponds to TPMT_RSA_DECRYPT. #[derive(Clone, Copy, Debug)] pub enum RsaDecryptionScheme { RsaEs, Oaep(HashScheme), Null, } impl RsaDecryptionScheme { /// Creates a new rsa decrypt scheme pub fn create( rsa_decrypt_algorithm: RsaDecryptAlgorithm, hashing_algorithm: Option, ) -> Result { match rsa_decrypt_algorithm { RsaDecryptAlgorithm::RsaEs => { if hashing_algorithm.is_none() { Ok(RsaDecryptionScheme::RsaEs) } else { error!("A hashing algorithm shall not be provided when creating RSA decryption scheme of type RSA ES"); Err(Error::local_error(WrapperErrorKind::InconsistentParams)) } }, RsaDecryptAlgorithm::Oaep => Ok(RsaDecryptionScheme::Oaep(HashScheme::new( hashing_algorithm.ok_or_else(|| { error!("Hashing algorithm is required when creating RSA decrypt scheme of type OEAP"); Error::local_error(WrapperErrorKind::ParamsMissing) })?, ))), RsaDecryptAlgorithm::Null => { if hashing_algorithm.is_none() { Ok(RsaDecryptionScheme::Null) } else { error!("A hashing algorithm shall not be provided when creating RSA decryption scheme of type Null"); Err(Error::local_error(WrapperErrorKind::InconsistentParams)) } } } } /// Returns the rsa decrypt scheme algorithm pub fn algorithm(&self) -> RsaDecryptAlgorithm { match self { RsaDecryptionScheme::RsaEs => RsaDecryptAlgorithm::RsaEs, RsaDecryptionScheme::Oaep(_) => RsaDecryptAlgorithm::Oaep, RsaDecryptionScheme::Null => RsaDecryptAlgorithm::Null, } } } impl From for TPMT_RSA_DECRYPT { fn from(rsa_decryption_scheme: RsaDecryptionScheme) -> Self { match rsa_decryption_scheme { RsaDecryptionScheme::RsaEs => TPMT_RSA_DECRYPT { scheme: rsa_decryption_scheme.algorithm().into(), details: TPMU_ASYM_SCHEME { rsaes: Default::default(), }, }, RsaDecryptionScheme::Oaep(hash_scheme) => TPMT_RSA_DECRYPT { scheme: rsa_decryption_scheme.algorithm().into(), details: TPMU_ASYM_SCHEME { oaep: hash_scheme.into(), }, }, RsaDecryptionScheme::Null => TPMT_RSA_DECRYPT { scheme: rsa_decryption_scheme.algorithm().into(), details: Default::default(), }, } } } impl TryFrom for RsaDecryptionScheme { type Error = Error; fn try_from(tpmt_rsa_decrypt: TPMT_RSA_DECRYPT) -> Result { match RsaDecryptAlgorithm::try_from(tpmt_rsa_decrypt.scheme)? { RsaDecryptAlgorithm::RsaEs => Ok(RsaDecryptionScheme::RsaEs), RsaDecryptAlgorithm::Oaep => Ok(RsaDecryptionScheme::Oaep( unsafe { tpmt_rsa_decrypt.details.oaep }.try_into()?, )), RsaDecryptAlgorithm::Null => Ok(RsaDecryptionScheme::Null), } } } impl TryFrom for RsaDecryptionScheme { type Error = Error; fn try_from(rsa_scheme: RsaScheme) -> Result { match rsa_scheme { RsaScheme::RsaEs => Ok(RsaDecryptionScheme::RsaEs), RsaScheme::Oaep(hash_scheme) => Ok(RsaDecryptionScheme::Oaep(hash_scheme)), RsaScheme::Null => Ok(RsaDecryptionScheme::Null), _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)), } } } /// Full description of signature schemes. /// /// # Details /// Corresponds to `TPMT_SIG_SCHEME`. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum SignatureScheme { RsaSsa { hash_scheme: HashScheme }, RsaPss { hash_scheme: HashScheme }, EcDsa { hash_scheme: HashScheme }, Sm2 { hash_scheme: HashScheme }, EcSchnorr { hash_scheme: HashScheme }, EcDaa { ecdaa_scheme: EcDaaScheme }, Hmac { hmac_scheme: HmacScheme }, Null, } impl SignatureScheme { /// Returns the digest( i.e. hashing algorithm) of a signing scheme. /// /// # Details /// This is intended to provide the functionality of reading /// from the ```anySig``` field in the TPMU_SIG_SCHEME union. /// /// # Errors /// Returns an InvalidParam error if the trying to read from /// SignatureScheme that is not a signing scheme. pub fn signing_scheme(&self) -> Result { match self { SignatureScheme::RsaSsa { hash_scheme } | SignatureScheme::RsaPss { hash_scheme } | SignatureScheme::EcDsa { hash_scheme } | SignatureScheme::Sm2 { hash_scheme } | SignatureScheme::EcSchnorr { hash_scheme } => Ok(hash_scheme.hashing_algorithm()), SignatureScheme::EcDaa { ecdaa_scheme } => Ok(ecdaa_scheme.hashing_algorithm()), _ => { error!("Cannot access digest for a non signing scheme"); Err(Error::local_error(WrapperErrorKind::InvalidParam)) } } } /// Sets digest( i.e. hashing algorithm) of a signing scheme. /// /// # Details /// This is intended to provide the functionality of writing /// to the ```anySig``` field in the TPMU_SIG_SCHEME union. /// /// # Errors /// Returns an InvalidParam error if the trying to read from /// SignatureScheme that is not a signing scheme. pub fn set_signing_scheme(&mut self, hashing_algorithm: HashingAlgorithm) -> Result<()> { match self { SignatureScheme::RsaSsa { hash_scheme } | SignatureScheme::RsaPss { hash_scheme } | SignatureScheme::EcDsa { hash_scheme } | SignatureScheme::Sm2 { hash_scheme } | SignatureScheme::EcSchnorr { hash_scheme } => { *hash_scheme = HashScheme::new(hashing_algorithm); Ok(()) } SignatureScheme::EcDaa { ecdaa_scheme } => { *ecdaa_scheme = EcDaaScheme::new(hashing_algorithm, ecdaa_scheme.count()); Ok(()) } _ => { error!("Cannot access digest for a non signing scheme"); Err(Error::local_error(WrapperErrorKind::InvalidParam)) } } } } impl From for TPMT_SIG_SCHEME { fn from(native: SignatureScheme) -> TPMT_SIG_SCHEME { match native { SignatureScheme::EcDaa { ecdaa_scheme } => TPMT_SIG_SCHEME { scheme: SignatureSchemeAlgorithm::EcDaa.into(), details: TPMU_SIG_SCHEME { ecdaa: ecdaa_scheme.into(), }, }, SignatureScheme::EcDsa { hash_scheme } => TPMT_SIG_SCHEME { scheme: SignatureSchemeAlgorithm::EcDsa.into(), details: TPMU_SIG_SCHEME { ecdsa: hash_scheme.into(), }, }, SignatureScheme::EcSchnorr { hash_scheme } => TPMT_SIG_SCHEME { scheme: SignatureSchemeAlgorithm::EcSchnorr.into(), details: TPMU_SIG_SCHEME { ecschnorr: hash_scheme.into(), }, }, SignatureScheme::Hmac { hmac_scheme } => TPMT_SIG_SCHEME { scheme: SignatureSchemeAlgorithm::Hmac.into(), details: TPMU_SIG_SCHEME { hmac: hmac_scheme.into(), }, }, SignatureScheme::Null => TPMT_SIG_SCHEME { scheme: SignatureSchemeAlgorithm::Null.into(), details: Default::default(), }, SignatureScheme::RsaPss { hash_scheme } => TPMT_SIG_SCHEME { scheme: SignatureSchemeAlgorithm::RsaPss.into(), details: TPMU_SIG_SCHEME { rsapss: hash_scheme.into(), }, }, SignatureScheme::RsaSsa { hash_scheme } => TPMT_SIG_SCHEME { scheme: SignatureSchemeAlgorithm::RsaSsa.into(), details: TPMU_SIG_SCHEME { rsassa: hash_scheme.into(), }, }, SignatureScheme::Sm2 { hash_scheme } => TPMT_SIG_SCHEME { scheme: SignatureSchemeAlgorithm::Sm2.into(), details: TPMU_SIG_SCHEME { sm2: hash_scheme.into(), }, }, } } } impl TryFrom for SignatureScheme { type Error = Error; fn try_from(tss: TPMT_SIG_SCHEME) -> Result { match SignatureSchemeAlgorithm::try_from(tss.scheme)? { SignatureSchemeAlgorithm::EcDaa => Ok(SignatureScheme::EcDaa { ecdaa_scheme: unsafe { tss.details.ecdaa }.try_into()?, }), SignatureSchemeAlgorithm::EcDsa => Ok(SignatureScheme::EcDsa { hash_scheme: unsafe { tss.details.ecdsa }.try_into()?, }), SignatureSchemeAlgorithm::EcSchnorr => Ok(SignatureScheme::EcSchnorr { hash_scheme: unsafe { tss.details.ecschnorr }.try_into()?, }), SignatureSchemeAlgorithm::Hmac => Ok(SignatureScheme::Hmac { hmac_scheme: unsafe { tss.details.hmac }.try_into()?, }), SignatureSchemeAlgorithm::Null => Ok(SignatureScheme::Null), SignatureSchemeAlgorithm::RsaPss => Ok(SignatureScheme::RsaPss { hash_scheme: unsafe { tss.details.rsapss }.try_into()?, }), SignatureSchemeAlgorithm::RsaSsa => Ok(SignatureScheme::RsaSsa { hash_scheme: unsafe { tss.details.rsassa }.try_into()?, }), SignatureSchemeAlgorithm::Sm2 => Ok(SignatureScheme::Sm2 { hash_scheme: unsafe { tss.details.sm2 }.try_into()?, }), } } } tss-esapi-7.4.0/src/structures/tagged/sensitive.rs000064400000000000000000000217401046102023000203740ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ interface_types::algorithm::PublicAlgorithm, structures::{Auth, Digest, EccParameter, PrivateKeyRsa, SensitiveData, SymmetricKey}, traits::{Marshall, UnMarshall}, tss2_esys::{TPM2B_SENSITIVE, TPMT_SENSITIVE, TPMU_SENSITIVE_COMPOSITE}, Error, Result, WrapperErrorKind, }; use log::error; use std::convert::{TryFrom, TryInto}; /// Enum describing the Sensitive part of an object. /// /// # Details /// This corresponds to TPMT_SENSITIVE #[derive(Debug, Clone, Eq, PartialEq)] pub enum Sensitive { Rsa { auth_value: Auth, seed_value: Digest, sensitive: PrivateKeyRsa, }, Ecc { auth_value: Auth, seed_value: Digest, sensitive: EccParameter, }, Bits { auth_value: Auth, seed_value: Digest, sensitive: SensitiveData, }, Symmetric { auth_value: Auth, seed_value: Digest, sensitive: SymmetricKey, }, // Even though this is included in TPMU_SENSITIVE_COMPOSITE, there is no // selector for it, so it can't be converted back and forth // VendorSpecific { // auth_value: Auth, // seed_value: Digest, // sensitive: PrivateVendorSpecific, // }, } impl Sensitive { /// Get the authentication value of the object pub fn auth_value(&self) -> &Auth { match self { Sensitive::Rsa { auth_value, .. } | Sensitive::Ecc { auth_value, .. } | Sensitive::Bits { auth_value, .. } | Sensitive::Symmetric { auth_value, .. } => auth_value, } } /// Get the seed value of the object pub fn seed_value(&self) -> &Digest { match self { Sensitive::Rsa { seed_value, .. } | Sensitive::Ecc { seed_value, .. } | Sensitive::Bits { seed_value, .. } | Sensitive::Symmetric { seed_value, .. } => seed_value, } } pub fn sensitive_type(&self) -> PublicAlgorithm { match self { Sensitive::Rsa { .. } => PublicAlgorithm::Rsa, Sensitive::Ecc { .. } => PublicAlgorithm::Ecc, Sensitive::Bits { .. } => PublicAlgorithm::KeyedHash, Sensitive::Symmetric { .. } => PublicAlgorithm::SymCipher, } } } impl From for TPMT_SENSITIVE { fn from(sensitive: Sensitive) -> Self { #[allow(non_snake_case)] let sensitiveType = sensitive.sensitive_type().into(); match sensitive { Sensitive::Rsa { auth_value, seed_value, sensitive, } => TPMT_SENSITIVE { sensitiveType, authValue: auth_value.into(), seedValue: seed_value.into(), sensitive: TPMU_SENSITIVE_COMPOSITE { rsa: sensitive.into(), }, }, Sensitive::Ecc { auth_value, seed_value, sensitive, } => TPMT_SENSITIVE { sensitiveType, authValue: auth_value.into(), seedValue: seed_value.into(), sensitive: TPMU_SENSITIVE_COMPOSITE { ecc: sensitive.into(), }, }, Sensitive::Bits { auth_value, seed_value, sensitive, } => TPMT_SENSITIVE { sensitiveType, authValue: auth_value.into(), seedValue: seed_value.into(), sensitive: TPMU_SENSITIVE_COMPOSITE { bits: sensitive.into(), }, }, Sensitive::Symmetric { auth_value, seed_value, sensitive, } => TPMT_SENSITIVE { sensitiveType, authValue: auth_value.into(), seedValue: seed_value.into(), sensitive: TPMU_SENSITIVE_COMPOSITE { sym: sensitive.into(), }, }, } } } impl TryFrom for Sensitive { type Error = Error; fn try_from(tpmt_sensitive: TPMT_SENSITIVE) -> Result { let sensitive_type = PublicAlgorithm::try_from(tpmt_sensitive.sensitiveType)?; match sensitive_type { PublicAlgorithm::Rsa => Ok(Sensitive::Rsa { auth_value: tpmt_sensitive.authValue.try_into()?, seed_value: tpmt_sensitive.seedValue.try_into()?, sensitive: unsafe { tpmt_sensitive.sensitive.rsa }.try_into()?, }), PublicAlgorithm::Ecc => Ok(Sensitive::Ecc { auth_value: tpmt_sensitive.authValue.try_into()?, seed_value: tpmt_sensitive.seedValue.try_into()?, sensitive: unsafe { tpmt_sensitive.sensitive.ecc }.try_into()?, }), PublicAlgorithm::KeyedHash => Ok(Sensitive::Bits { auth_value: tpmt_sensitive.authValue.try_into()?, seed_value: tpmt_sensitive.seedValue.try_into()?, sensitive: unsafe { tpmt_sensitive.sensitive.bits }.try_into()?, }), PublicAlgorithm::SymCipher => Ok(Sensitive::Symmetric { auth_value: tpmt_sensitive.authValue.try_into()?, seed_value: tpmt_sensitive.seedValue.try_into()?, sensitive: unsafe { tpmt_sensitive.sensitive.sym }.try_into()?, }), } } } impl Marshall for Sensitive { const BUFFER_SIZE: usize = std::mem::size_of::(); /// Produce a marshalled [`TPMT_SENSITIVE`] /// /// Note: for [TPM2B_SENSITIVE] marshalling use [SensitiveBuffer][`crate::structures::SensitiveBuffer] fn marshall(&self) -> Result> { let mut buffer = vec![0; Self::BUFFER_SIZE]; let mut offset = 0; let ret = Error::from_tss_rc(unsafe { crate::tss2_esys::Tss2_MU_TPMT_SENSITIVE_Marshal( &self.clone().into(), buffer.as_mut_ptr(), Self::BUFFER_SIZE.try_into().map_err(|e| { error!("Failed to convert size of buffer to TSS size_t type: {}", e); Error::local_error(WrapperErrorKind::InvalidParam) })?, &mut offset, ) }); if !ret.is_success() { return Err(ret); } let checked_offset = usize::try_from(offset).map_err(|e| { error!("Failed to parse offset as usize: {}", e); Error::local_error(WrapperErrorKind::InvalidParam) })?; buffer.truncate(checked_offset); Ok(buffer) } } impl UnMarshall for Sensitive { /// Unmarshall the structure from [`TPMT_SENSITIVE`] /// /// Note: for [TPM2B_SENSITIVE] marshalling use [SensitiveBuffer][`crate::structures::SensitiveBuffer] fn unmarshall(marshalled_data: &[u8]) -> Result { let mut dest = TPMT_SENSITIVE::default(); let mut offset = 0; let ret = Error::from_tss_rc(unsafe { crate::tss2_esys::Tss2_MU_TPMT_SENSITIVE_Unmarshal( marshalled_data.as_ptr(), marshalled_data.len().try_into().map_err(|e| { error!("Failed to convert length of marshalled data: {}", e); Error::local_error(WrapperErrorKind::InvalidParam) })?, &mut offset, &mut dest, ) }); if !ret.is_success() { return Err(ret); } Sensitive::try_from(dest) } } impl TryFrom for Sensitive { type Error = Error; fn try_from(tpm2b_sensitive: TPM2B_SENSITIVE) -> Result { Sensitive::try_from(tpm2b_sensitive.sensitiveArea) } } impl TryFrom for TPM2B_SENSITIVE { type Error = Error; fn try_from(sensitive: Sensitive) -> Result { let mut buffer = vec![0; Sensitive::BUFFER_SIZE]; let mut size = 0; let sensitive_area = TPMT_SENSITIVE::from(sensitive); let ret = Error::from_tss_rc(unsafe { crate::tss2_esys::Tss2_MU_TPMT_SENSITIVE_Marshal( &sensitive_area, buffer.as_mut_ptr(), Sensitive::BUFFER_SIZE.try_into().map_err(|e| { error!("Failed to convert size of buffer to TSS size_t type: {}", e); Error::local_error(WrapperErrorKind::InvalidParam) })?, &mut size, ) }); if !ret.is_success() { return Err(ret); } Ok(TPM2B_SENSITIVE { size: size.try_into().map_err(|e| { error!( "Failed to convert size of buffer from TSS size_t type: {}", e ); Error::local_error(WrapperErrorKind::InvalidParam) })?, sensitiveArea: sensitive_area, }) } } tss-esapi-7.4.0/src/structures/tagged/signature.rs000064400000000000000000000154741046102023000203730ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ interface_types::algorithm::SignatureSchemeAlgorithm, structures::{EccSignature, HashAgile, RsaSignature}, traits::{Marshall, UnMarshall}, tss2_esys::{TPMT_SIGNATURE, TPMU_SIGNATURE}, Error, Result, WrapperErrorKind, }; use log::error; use std::convert::{TryFrom, TryInto}; use tss_esapi_sys::{Tss2_MU_TPMT_SIGNATURE_Marshal, Tss2_MU_TPMT_SIGNATURE_Unmarshal}; /// Enum representing a Signature /// /// # Details /// This corresponds TPMT_SIGNATURE #[derive(Debug, Clone, PartialEq, Eq)] pub enum Signature { RsaSsa(RsaSignature), RsaPss(RsaSignature), EcDsa(EccSignature), EcDaa(EccSignature), Sm2(EccSignature), EcSchnorr(EccSignature), Hmac(HashAgile), Null, } impl Signature { pub fn algorithm(&self) -> SignatureSchemeAlgorithm { match self { Signature::RsaSsa(_) => SignatureSchemeAlgorithm::RsaSsa, Signature::RsaPss(_) => SignatureSchemeAlgorithm::RsaPss, Signature::EcDsa(_) => SignatureSchemeAlgorithm::EcDsa, Signature::EcDaa(_) => SignatureSchemeAlgorithm::EcDaa, Signature::Sm2(_) => SignatureSchemeAlgorithm::Sm2, Signature::EcSchnorr(_) => SignatureSchemeAlgorithm::EcSchnorr, Signature::Hmac(_) => SignatureSchemeAlgorithm::Hmac, Signature::Null => SignatureSchemeAlgorithm::Null, } } } impl TryFrom for TPMT_SIGNATURE { type Error = Error; fn try_from(signature: Signature) -> Result { let signature_algorithm = signature.algorithm().into(); match signature { Signature::RsaSsa(rsa_signature) => Ok(TPMT_SIGNATURE { sigAlg: signature_algorithm, signature: TPMU_SIGNATURE { rsassa: rsa_signature.into(), }, }), Signature::RsaPss(rsa_signature) => Ok(TPMT_SIGNATURE { sigAlg: signature_algorithm, signature: TPMU_SIGNATURE { rsapss: rsa_signature.into(), }, }), Signature::EcDsa(ecc_signature) => Ok(TPMT_SIGNATURE { sigAlg: signature_algorithm, signature: TPMU_SIGNATURE { ecdsa: ecc_signature.into(), }, }), Signature::EcDaa(ecc_signature) => Ok(TPMT_SIGNATURE { sigAlg: signature_algorithm, signature: TPMU_SIGNATURE { ecdaa: ecc_signature.into(), }, }), Signature::Sm2(ecc_signature) => Ok(TPMT_SIGNATURE { sigAlg: signature_algorithm, signature: TPMU_SIGNATURE { sm2: ecc_signature.into(), }, }), Signature::EcSchnorr(ecc_signature) => Ok(TPMT_SIGNATURE { sigAlg: signature_algorithm, signature: TPMU_SIGNATURE { ecschnorr: ecc_signature.into(), }, }), Signature::Hmac(hash_agile) => Ok(TPMT_SIGNATURE { sigAlg: signature_algorithm, signature: TPMU_SIGNATURE { hmac: hash_agile.try_into()?, }, }), Signature::Null => Ok(TPMT_SIGNATURE { sigAlg: signature_algorithm, signature: Default::default(), }), } } } impl TryFrom for Signature { type Error = Error; fn try_from(tpmt_signature: TPMT_SIGNATURE) -> Result { match SignatureSchemeAlgorithm::try_from(tpmt_signature.sigAlg)? { SignatureSchemeAlgorithm::RsaSsa => Ok(Signature::RsaSsa( unsafe { tpmt_signature.signature.rsassa }.try_into()?, )), SignatureSchemeAlgorithm::RsaPss => Ok(Signature::RsaPss( unsafe { tpmt_signature.signature.rsapss }.try_into()?, )), SignatureSchemeAlgorithm::EcDsa => Ok(Signature::EcDsa( unsafe { tpmt_signature.signature.ecdsa }.try_into()?, )), SignatureSchemeAlgorithm::EcDaa => Ok(Signature::EcDaa( unsafe { tpmt_signature.signature.ecdaa }.try_into()?, )), SignatureSchemeAlgorithm::Sm2 => Ok(Signature::Sm2( unsafe { tpmt_signature.signature.sm2 }.try_into()?, )), SignatureSchemeAlgorithm::EcSchnorr => Ok(Signature::EcSchnorr( unsafe { tpmt_signature.signature.ecschnorr }.try_into()?, )), SignatureSchemeAlgorithm::Hmac => Ok(Signature::Hmac( unsafe { tpmt_signature.signature.hmac }.try_into()?, )), SignatureSchemeAlgorithm::Null => Ok(Signature::Null), } } } impl Marshall for Signature { const BUFFER_SIZE: usize = std::mem::size_of::(); /// Produce a marshalled [`TPMT_SIGNATURE`] fn marshall(&self) -> Result> { let tpmt_sig = TPMT_SIGNATURE::try_from(self.clone())?; let mut offset = 0; let mut buffer = vec![0; Self::BUFFER_SIZE]; let ret = unsafe { Tss2_MU_TPMT_SIGNATURE_Marshal( &tpmt_sig, buffer.as_mut_ptr(), buffer.capacity().try_into().map_err(|e| { error!("Failed to convert size of buffer to TSS size_t type: {}", e); Error::local_error(WrapperErrorKind::InvalidParam) })?, &mut offset, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { let checked_offset = usize::try_from(offset).map_err(|e| { error!("Failed to parse offset as usize: {}", e); Error::local_error(WrapperErrorKind::InvalidParam) })?; buffer.truncate(checked_offset); Ok(buffer) } else { Err(ret) } } } impl UnMarshall for Signature { /// Unmarshall the structure from [`TPMT_SIGNATURE`] fn unmarshall(public_buffer: &[u8]) -> Result { let mut tpmt_sig = TPMT_SIGNATURE::default(); let mut offset = 0; let ret = unsafe { Tss2_MU_TPMT_SIGNATURE_Unmarshal( public_buffer.as_ptr(), public_buffer.len().try_into().map_err(|e| { error!("Failed to convert length of marshalled data: {}", e); Error::local_error(WrapperErrorKind::InvalidParam) })?, &mut offset, &mut tpmt_sig, ) }; let ret = Error::from_tss_rc(ret); if ret.is_success() { Ok(tpmt_sig.try_into()?) } else { Err(ret) } } } tss-esapi-7.4.0/src/structures/tagged/symmetric.rs000064400000000000000000000230641046102023000204000ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ interface_types::{ algorithm::{HashingAlgorithm, SymmetricAlgorithm, SymmetricMode, SymmetricObject}, key_bits::{AesKeyBits, CamelliaKeyBits, Sm4KeyBits}, }, tss2_esys::{TPMT_SYM_DEF, TPMT_SYM_DEF_OBJECT, TPMU_SYM_KEY_BITS, TPMU_SYM_MODE}, Error, Result, WrapperErrorKind, }; use std::convert::{TryFrom, TryInto}; /// Enum representing the symmetric algorithm definition. /// /// # Details /// This corresponds to TPMT_SYM_DEF. #[derive(Debug, Clone, Copy, Eq, PartialEq)] pub enum SymmetricDefinition { // TODO: Investigate why TDES is not included... Aes { key_bits: AesKeyBits, mode: SymmetricMode, }, Sm4 { key_bits: Sm4KeyBits, mode: SymmetricMode, }, Camellia { key_bits: CamelliaKeyBits, mode: SymmetricMode, }, Xor { hashing_algorithm: HashingAlgorithm, }, Null, } impl SymmetricDefinition { /// Constant for the AES 128 bits CFB symmetric definition pub const AES_128_CFB: SymmetricDefinition = SymmetricDefinition::Aes { key_bits: AesKeyBits::Aes128, mode: SymmetricMode::Cfb, }; /// Constant for the AES 128 bits CFB symmetric definition pub const AES_256_CFB: SymmetricDefinition = SymmetricDefinition::Aes { key_bits: AesKeyBits::Aes256, mode: SymmetricMode::Cfb, }; } impl TryFrom for TPMT_SYM_DEF { type Error = Error; fn try_from(symmetric_definition: SymmetricDefinition) -> Result { match symmetric_definition { SymmetricDefinition::Aes { key_bits, mode } => Ok(TPMT_SYM_DEF { algorithm: SymmetricAlgorithm::Aes.into(), keyBits: TPMU_SYM_KEY_BITS { aes: key_bits.into(), }, mode: TPMU_SYM_MODE { aes: mode.into() }, }), SymmetricDefinition::Sm4 { key_bits, mode } => Ok(TPMT_SYM_DEF { algorithm: SymmetricAlgorithm::Sm4.into(), keyBits: TPMU_SYM_KEY_BITS { sm4: key_bits.into(), }, mode: TPMU_SYM_MODE { sm4: mode.into() }, }), SymmetricDefinition::Camellia { key_bits, mode } => Ok(TPMT_SYM_DEF { algorithm: SymmetricAlgorithm::Camellia.into(), keyBits: TPMU_SYM_KEY_BITS { camellia: key_bits.into(), }, mode: TPMU_SYM_MODE { camellia: mode.into(), }, }), SymmetricDefinition::Xor { hashing_algorithm } => Ok(TPMT_SYM_DEF { algorithm: SymmetricAlgorithm::Xor.into(), keyBits: TPMU_SYM_KEY_BITS { exclusiveOr: if hashing_algorithm != HashingAlgorithm::Null { hashing_algorithm.into() } else { return Err(Error::local_error(WrapperErrorKind::InvalidParam)); }, }, mode: Default::default(), }), SymmetricDefinition::Null => Ok(TPMT_SYM_DEF { algorithm: SymmetricAlgorithm::Null.into(), keyBits: Default::default(), mode: Default::default(), }), } } } impl TryFrom for SymmetricDefinition { type Error = Error; fn try_from(tpmt_sym_def: TPMT_SYM_DEF) -> Result { match SymmetricAlgorithm::try_from(tpmt_sym_def.algorithm)? { SymmetricAlgorithm::Aes => Ok(SymmetricDefinition::Aes { key_bits: unsafe { tpmt_sym_def.keyBits.aes }.try_into()?, mode: unsafe { tpmt_sym_def.mode.aes }.try_into()?, }), SymmetricAlgorithm::Sm4 => Ok(SymmetricDefinition::Sm4 { key_bits: unsafe { tpmt_sym_def.keyBits.sm4 }.try_into()?, mode: unsafe { tpmt_sym_def.mode.sm4 }.try_into()?, }), SymmetricAlgorithm::Camellia => Ok(SymmetricDefinition::Camellia { key_bits: unsafe { tpmt_sym_def.keyBits.camellia }.try_into()?, mode: unsafe { tpmt_sym_def.mode.camellia }.try_into()?, }), SymmetricAlgorithm::Xor => Ok(SymmetricDefinition::Xor { hashing_algorithm: HashingAlgorithm::try_from(unsafe { tpmt_sym_def.keyBits.exclusiveOr }) .and_then(|ha| { if ha != HashingAlgorithm::Null { Ok(ha) } else { Err(Error::local_error(WrapperErrorKind::InvalidParam)) } })?, }), SymmetricAlgorithm::Null => Ok(SymmetricDefinition::Null), SymmetricAlgorithm::Tdes => { // TODO: Investigate this... Err(Error::local_error(WrapperErrorKind::WrongValueFromTpm)) } } } } /// Enum representing the symmetric definition object. /// /// # Details /// This corresponds to TPMT_SYM_DEF_OBJECT #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum SymmetricDefinitionObject { // TDOD: Investigate why TDES is missing. Aes { key_bits: AesKeyBits, mode: SymmetricMode, }, Sm4 { key_bits: Sm4KeyBits, mode: SymmetricMode, }, Camellia { key_bits: CamelliaKeyBits, mode: SymmetricMode, }, Null, } impl SymmetricDefinitionObject { /// Constant for the AES 128 bits CFB symmetric definition object pub const AES_128_CFB: SymmetricDefinitionObject = SymmetricDefinitionObject::Aes { key_bits: AesKeyBits::Aes128, mode: SymmetricMode::Cfb, }; /// Constant for the AES 256 bits CFB symmetric definition object pub const AES_256_CFB: SymmetricDefinitionObject = SymmetricDefinitionObject::Aes { key_bits: AesKeyBits::Aes256, mode: SymmetricMode::Cfb, }; pub(crate) fn is_null(&self) -> bool { matches!(self, Self::Null) } } impl Default for SymmetricDefinitionObject { fn default() -> Self { Self::Null } } impl From for TPMT_SYM_DEF_OBJECT { fn from(symmetric_definition_object: SymmetricDefinitionObject) -> TPMT_SYM_DEF_OBJECT { match symmetric_definition_object { SymmetricDefinitionObject::Aes { key_bits, mode } => TPMT_SYM_DEF_OBJECT { algorithm: SymmetricAlgorithm::Aes.into(), keyBits: TPMU_SYM_KEY_BITS { aes: key_bits.into(), }, mode: TPMU_SYM_MODE { aes: mode.into() }, }, SymmetricDefinitionObject::Sm4 { key_bits, mode } => TPMT_SYM_DEF_OBJECT { algorithm: SymmetricAlgorithm::Sm4.into(), keyBits: TPMU_SYM_KEY_BITS { sm4: key_bits.into(), }, mode: TPMU_SYM_MODE { sm4: mode.into() }, }, SymmetricDefinitionObject::Camellia { key_bits, mode } => TPMT_SYM_DEF_OBJECT { algorithm: SymmetricAlgorithm::Camellia.into(), keyBits: TPMU_SYM_KEY_BITS { camellia: key_bits.into(), }, mode: TPMU_SYM_MODE { camellia: mode.into(), }, }, SymmetricDefinitionObject::Null => TPMT_SYM_DEF_OBJECT { algorithm: SymmetricAlgorithm::Null.into(), keyBits: Default::default(), mode: Default::default(), }, } } } impl From for SymmetricDefinition { fn from(sym_def_obj: SymmetricDefinitionObject) -> Self { match sym_def_obj { SymmetricDefinitionObject::Null => SymmetricDefinition::Null, SymmetricDefinitionObject::Camellia { key_bits, mode } => { SymmetricDefinition::Camellia { key_bits, mode } } SymmetricDefinitionObject::Aes { key_bits, mode } => { SymmetricDefinition::Aes { key_bits, mode } } SymmetricDefinitionObject::Sm4 { key_bits, mode } => { SymmetricDefinition::Sm4 { key_bits, mode } } } } } impl TryFrom for SymmetricDefinitionObject { type Error = Error; fn try_from(tpmt_sym_def_object: TPMT_SYM_DEF_OBJECT) -> Result { match SymmetricObject::try_from(tpmt_sym_def_object.algorithm)? { SymmetricObject::Aes => Ok(SymmetricDefinitionObject::Aes { key_bits: unsafe { tpmt_sym_def_object.keyBits.aes }.try_into()?, mode: unsafe { tpmt_sym_def_object.mode.aes }.try_into()?, }), SymmetricObject::Sm4 => Ok(SymmetricDefinitionObject::Sm4 { key_bits: unsafe { tpmt_sym_def_object.keyBits.sm4 }.try_into()?, mode: unsafe { tpmt_sym_def_object.mode.sm4 }.try_into()?, }), SymmetricObject::Camellia => Ok(SymmetricDefinitionObject::Camellia { key_bits: unsafe { tpmt_sym_def_object.keyBits.camellia }.try_into()?, mode: unsafe { tpmt_sym_def_object.mode.camellia }.try_into()?, }), SymmetricObject::Null => Ok(SymmetricDefinitionObject::Null), SymmetricObject::Tdes => { // TODO: Investigate this... Err(Error::local_error(WrapperErrorKind::WrongValueFromTpm)) } } } } tss-esapi-7.4.0/src/structures/tickets.rs000064400000000000000000000143531046102023000166000ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ constants::StructureTag, handles::TpmHandle, interface_types::resource_handles::Hierarchy, tss2_esys::{ TPM2B_DIGEST, TPMT_TK_AUTH, TPMT_TK_CREATION, TPMT_TK_HASHCHECK, TPMT_TK_VERIFIED, }, Error, Result, WrapperErrorKind, }; use log::error; use std::convert::{TryFrom, TryInto}; /// Macro used for implementing try_from /// TssTicketType -> TicketType /// TicketType -> TssTicketType const TPM2B_DIGEST_BUFFER_SIZE: usize = 64; macro_rules! impl_ticket_try_froms { ($ticket_type:ident, $tss_ticket_type:ident) => { impl TryFrom<$ticket_type> for $tss_ticket_type { type Error = Error; fn try_from(ticket: $ticket_type) -> Result { let tag = ticket.tag(); let digest = ticket.digest; if digest.len() > TPM2B_DIGEST_BUFFER_SIZE { return Err(Error::local_error(WrapperErrorKind::WrongParamSize)); } let mut buffer = [0; TPM2B_DIGEST_BUFFER_SIZE]; buffer[..digest.len()].clone_from_slice(&digest[..digest.len()]); Ok($tss_ticket_type { tag: tag.into(), hierarchy: TpmHandle::from(ticket.hierarchy).into(), digest: TPM2B_DIGEST { size: digest.len().try_into().unwrap(), // should not fail based on the checks done above buffer, }, }) } } impl TryFrom<$tss_ticket_type> for $ticket_type { type Error = Error; fn try_from(tss_ticket: $tss_ticket_type) -> Result { let tag = match StructureTag::try_from(tss_ticket.tag) { Ok(val) => { if !<$ticket_type>::POSSIBLE_TAGS.contains(&val) { return Err(Error::local_error(WrapperErrorKind::InconsistentParams)); } val } Err(why) => { error!("Failed to parsed tag: {}", why); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } }; let len = tss_ticket.digest.size.into(); if len > TPM2B_DIGEST_BUFFER_SIZE { error!( "Invalid digest size. (Digest size: {0} > Digest buffer size: {1})", len, TPM2B_DIGEST_BUFFER_SIZE, ); return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } let mut digest = tss_ticket.digest.buffer.to_vec(); digest.truncate(len); let hierarchy = Hierarchy::try_from(TpmHandle::try_from(tss_ticket.hierarchy)?)?; Ok($ticket_type { tag, hierarchy, digest, }) } } }; } pub trait Ticket { const POSSIBLE_TAGS: &'static [StructureTag]; fn tag(&self) -> StructureTag; fn hierarchy(&self) -> Hierarchy; fn digest(&self) -> &[u8]; } #[derive(Debug, Clone)] pub struct AuthTicket { tag: StructureTag, hierarchy: Hierarchy, digest: Vec, } impl Ticket for AuthTicket { /// The possible tags of AuthTickets const POSSIBLE_TAGS: &'static [StructureTag] = &[StructureTag::AuthSecret, StructureTag::AuthSigned]; /// Get the tag associated with the auth ticket. fn tag(&self) -> StructureTag { self.tag } /// Get the hierarchy associated with the auth ticket. fn hierarchy(&self) -> Hierarchy { self.hierarchy } /// Get the digest associated with the auth ticket. fn digest(&self) -> &[u8] { &self.digest } } impl_ticket_try_froms!(AuthTicket, TPMT_TK_AUTH); #[derive(Debug, Clone)] pub struct HashcheckTicket { tag: StructureTag, hierarchy: Hierarchy, digest: Vec, } impl Ticket for HashcheckTicket { /// The tag of the verified ticket. const POSSIBLE_TAGS: &'static [StructureTag] = &[StructureTag::Hashcheck]; /// Get the tag associated with the hashcheck ticket. fn tag(&self) -> StructureTag { self.tag } /// Get the hierarchy associated with the verification ticket. fn hierarchy(&self) -> Hierarchy { self.hierarchy } /// Get the digest associated with the verification ticket. fn digest(&self) -> &[u8] { &self.digest } } impl_ticket_try_froms!(HashcheckTicket, TPMT_TK_HASHCHECK); /// Rust native wrapper for `TPMT_TK_VERIFIED` objects. #[derive(Debug)] pub struct VerifiedTicket { tag: StructureTag, hierarchy: Hierarchy, digest: Vec, } impl Ticket for VerifiedTicket { // type TssTicketType = TPMT_TK_VERIFIED; /// The tag of the verified ticket. const POSSIBLE_TAGS: &'static [StructureTag] = &[StructureTag::Verified]; /// Get the tag associated with the verification ticket. fn tag(&self) -> StructureTag { self.tag } /// Get the hierarchy associated with the verification ticket. fn hierarchy(&self) -> Hierarchy { self.hierarchy } /// Get the digest associated with the verification ticket. fn digest(&self) -> &[u8] { &self.digest } } impl_ticket_try_froms!(VerifiedTicket, TPMT_TK_VERIFIED); /// Rust native wrapper for `TPMT_TK_CREATION` objects. #[derive(Debug)] pub struct CreationTicket { tag: StructureTag, hierarchy: Hierarchy, digest: Vec, } impl Ticket for CreationTicket { // type TssTicketType = TPMT_TK_VERIFIED; /// The tag of the verified ticket. const POSSIBLE_TAGS: &'static [StructureTag] = &[StructureTag::Creation]; /// Get the tag associated with the creation ticket. fn tag(&self) -> StructureTag { self.tag } /// Get the hierarchy associated with the verification ticket. fn hierarchy(&self) -> Hierarchy { self.hierarchy } /// Get the digest associated with the verification ticket. fn digest(&self) -> &[u8] { &self.digest } } impl_ticket_try_froms!(CreationTicket, TPMT_TK_CREATION); tss-esapi-7.4.0/src/tcti_ldr.rs000064400000000000000000000503031046102023000145060ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! Wrapper around the TCTI Loader Library interface. //! See section 3.5 of the TCG TSS 2.0 TPM Command Transmission Interface(TCTI) API //! Specification. use crate::{Error, Result, WrapperErrorKind}; use log::error; use regex::Regex; use std::convert::TryFrom; use std::env; use std::ffi::CStr; use std::ffi::CString; use std::net::IpAddr; use std::path::PathBuf; use std::ptr::null_mut; use std::str::FromStr; const DEVICE: &str = "device"; const MSSIM: &str = "mssim"; const SWTPM: &str = "swtpm"; const TABRMD: &str = "tabrmd"; /// TCTI Context created via a TCTI Loader Library. /// Wrapper around the TSS2_TCTI_CONTEXT structure. #[derive(Debug)] #[allow(missing_copy_implementations)] pub struct TctiContext { tcti_context: *mut tss_esapi_sys::TSS2_TCTI_CONTEXT, } impl TctiContext { /// Allocate and initialize a new TctiContext structure. pub fn initialize(name_conf: TctiNameConf) -> Result { let mut tcti_context = null_mut(); let tcti_name_conf = CString::try_from(name_conf)?; unsafe { let ret = tss_esapi_sys::Tss2_TctiLdr_Initialize(tcti_name_conf.as_ptr(), &mut tcti_context); let ret = Error::from_tss_rc(ret); if !ret.is_success() { error!("Error when creating a TCTI context: {}", ret); return Err(ret); } } Ok(TctiContext { tcti_context }) } /// Get access to the inner C pointer pub(crate) fn tcti_context_ptr(&mut self) -> *mut tss_esapi_sys::TSS2_TCTI_CONTEXT { self.tcti_context } } impl Drop for TctiContext { fn drop(&mut self) { unsafe { tss_esapi_sys::Tss2_TctiLdr_Finalize(&mut self.tcti_context); } } } // `Send` and `Sync` are implemented to allow `TctiContext` to be thread-safe. // This is necessary because `*mut TSS2_TCTI_CONTEXT` is not thread-safe by // default. We can confirm the safety as the pointer can only be accessed // in a thread-safe way (i.e. in methods that require a `&mut self`). unsafe impl Send for TctiContext {} unsafe impl Sync for TctiContext {} /// Wrapper around the TSS2_TCTI_INFO structure. #[derive(Debug)] #[allow(missing_copy_implementations)] pub struct TctiInfo { tcti_info: *mut tss_esapi_sys::TSS2_TCTI_INFO, } impl TctiInfo { /// Query the TCTI loading mechanism pub fn get_info(name_conf: TctiNameConf) -> Result { let mut tcti_info = null_mut(); let tcti_name_conf = CString::try_from(name_conf)?; unsafe { let ret = tss_esapi_sys::Tss2_TctiLdr_GetInfo(tcti_name_conf.as_ptr(), &mut tcti_info); let ret = Error::from_tss_rc(ret); if !ret.is_success() { error!("Error when getting the TCTI_INFO structure: {}", ret); return Err(ret); } } Ok(TctiInfo { tcti_info }) } /// Get the version field pub fn version(&self) -> u32 { unsafe { (*(self.tcti_info)).version } } /// Get the name field pub fn name(&self) -> &CStr { unsafe { CStr::from_ptr((*(self.tcti_info)).name) } } /// Get the description field pub fn description(&self) -> &CStr { unsafe { CStr::from_ptr((*(self.tcti_info)).description) } } /// Get the config_help field pub fn config_help(&self) -> &CStr { unsafe { CStr::from_ptr((*(self.tcti_info)).config_help) } } } impl Drop for TctiInfo { fn drop(&mut self) { unsafe { tss_esapi_sys::Tss2_TctiLdr_FreeInfo(&mut self.tcti_info); } } } /// Placeholder TCTI types that can be used when initialising a `Context` to determine which /// interface will be used to communicate with the TPM. #[derive(Clone, Debug, PartialEq, Eq)] pub enum TctiNameConf { /// Connect to a TPM available as a device node on the system /// /// For more information about configuration, see [this page](https://www.mankier.com/3/Tss2_Tcti_Device_Init) Device(DeviceConfig), /// Connect to a TPM (simulator) available as a network device via the MSSIM protocol /// /// For more information about configuration, see [this page](https://www.mankier.com/3/Tss2_Tcti_Mssim_Init) Mssim(NetworkTPMConfig), /// Connect to a TPM (simulator) available as a network device via the SWTPM protocol /// /// For more information about configuration, see [this page](https://www.mankier.com/3/Tss2_Tcti_Mssim_Init) Swtpm(NetworkTPMConfig), /// Connect to a TPM through an Access Broker/Resource Manager daemon /// /// For more information about configuration, see [this page](https://www.mankier.com/3/Tss2_Tcti_Tabrmd_Init) Tabrmd(TabrmdConfig), } impl TctiNameConf { /// Gets a TCTI from the following environment variables, in order: /// - TPM2TOOLS_TCTI /// - TCTI /// - TEST_TCTI /// /// # Examples /// ``` /// # use tss_esapi::tcti_ldr::TctiNameConf; /// // Create context /// let tcti_name_conf = TctiNameConf::from_environment_variable().expect("Failed to get TCTI"); pub fn from_environment_variable() -> Result { env::var("TPM2TOOLS_TCTI") .or_else(|_| env::var("TCTI")) .or_else(|_| env::var("TEST_TCTI")) .map_err(|_| Error::WrapperError(WrapperErrorKind::ParamsMissing)) .and_then(|val| TctiNameConf::from_str(&val)) } } impl TryFrom for CString { type Error = Error; fn try_from(tcti: TctiNameConf) -> Result { let tcti_name = match tcti { TctiNameConf::Device(..) => DEVICE, TctiNameConf::Mssim(..) => MSSIM, TctiNameConf::Swtpm(..) => SWTPM, TctiNameConf::Tabrmd(..) => TABRMD, }; let tcti_conf = match tcti { TctiNameConf::Mssim(config) => { if let ServerAddress::Hostname(name) = &config.host { if !hostname_validator::is_valid(name) { return Err(Error::WrapperError(WrapperErrorKind::InvalidParam)); } } format!("host={},port={}", config.host, config.port) } TctiNameConf::Swtpm(config) => { if let ServerAddress::Hostname(name) = &config.host { if !hostname_validator::is_valid(name) { return Err(Error::WrapperError(WrapperErrorKind::InvalidParam)); } } format!("host={},port={}", config.host, config.port) } TctiNameConf::Device(DeviceConfig { path }) => path .to_str() .ok_or(Error::WrapperError(WrapperErrorKind::InvalidParam))? .to_owned(), TctiNameConf::Tabrmd(config) => { format!("bus_name={},bus_type={}", config.bus_name, config.bus_type) } }; if tcti_conf.is_empty() { CString::new(tcti_name).or(Err(Error::WrapperError(WrapperErrorKind::InvalidParam))) } else { CString::new(format!("{}:{}", tcti_name, tcti_conf)) .or(Err(Error::WrapperError(WrapperErrorKind::InvalidParam))) } } } impl FromStr for TctiNameConf { type Err = Error; fn from_str(config_str: &str) -> Result { let device_pattern = Regex::new(r"^device(:(.*))?$").unwrap(); //should not fail if let Some(captures) = device_pattern.captures(config_str) { return Ok(TctiNameConf::Device(DeviceConfig::from_str( captures.get(2).map_or("", |m| m.as_str()), )?)); } let mssim_pattern = Regex::new(r"^mssim(:(.*))?$").unwrap(); //should not fail if let Some(captures) = mssim_pattern.captures(config_str) { return Ok(TctiNameConf::Mssim(NetworkTPMConfig::from_str( captures.get(2).map_or("", |m| m.as_str()), )?)); } let swtpm_pattern = Regex::new(r"^swtpm(:(.*))?$").unwrap(); //should not fail if let Some(captures) = swtpm_pattern.captures(config_str) { return Ok(TctiNameConf::Swtpm(NetworkTPMConfig::from_str( captures.get(2).map_or("", |m| m.as_str()), )?)); } let tabrmd_pattern = Regex::new(r"^tabrmd(:(.*))?$").unwrap(); //should not fail if let Some(captures) = tabrmd_pattern.captures(config_str) { return Ok(TctiNameConf::Tabrmd(TabrmdConfig::from_str( captures.get(2).map_or("", |m| m.as_str()), )?)); } Err(Error::WrapperError(WrapperErrorKind::InvalidParam)) } } #[test] fn validate_from_str_tcti() { let tcti = TctiNameConf::from_str("mssim:port=1234,host=168.0.0.1").unwrap(); assert_eq!( tcti, TctiNameConf::Mssim(NetworkTPMConfig { port: 1234, host: ServerAddress::Ip(IpAddr::V4(std::net::Ipv4Addr::new(168, 0, 0, 1))) }) ); let tcti = TctiNameConf::from_str("mssim").unwrap(); assert_eq!( tcti, TctiNameConf::Mssim(NetworkTPMConfig { port: DEFAULT_SERVER_PORT, host: Default::default() }) ); let tcti = TctiNameConf::from_str("swtpm:port=1234,host=168.0.0.1").unwrap(); assert_eq!( tcti, TctiNameConf::Swtpm(NetworkTPMConfig { port: 1234, host: ServerAddress::Ip(IpAddr::V4(std::net::Ipv4Addr::new(168, 0, 0, 1))) }) ); let tcti = TctiNameConf::from_str("swtpm").unwrap(); assert_eq!( tcti, TctiNameConf::Swtpm(NetworkTPMConfig { port: DEFAULT_SERVER_PORT, host: Default::default() }) ); let tcti = TctiNameConf::from_str("device:/try/this/path").unwrap(); assert_eq!( tcti, TctiNameConf::Device(DeviceConfig { path: PathBuf::from("/try/this/path"), }) ); let tcti = TctiNameConf::from_str("device").unwrap(); assert_eq!(tcti, TctiNameConf::Device(Default::default())); let tcti = TctiNameConf::from_str("tabrmd:bus_name=some.bus.Name2,bus_type=session").unwrap(); assert_eq!( tcti, TctiNameConf::Tabrmd(TabrmdConfig { bus_name: String::from("some.bus.Name2"), bus_type: BusType::Session }) ); let tcti = TctiNameConf::from_str("tabrmd").unwrap(); assert_eq!(tcti, TctiNameConf::Tabrmd(Default::default())); } /// Configuration for a Device TCTI context /// /// The default configuration uses the library default of /// `/dev/tpm0`. #[derive(Clone, Debug, PartialEq, Eq)] pub struct DeviceConfig { /// Path to the device node to connect to /// /// If set to `None`, the default location is used path: PathBuf, } impl Default for DeviceConfig { fn default() -> Self { DeviceConfig { path: PathBuf::from("/dev/tpm0"), } } } impl FromStr for DeviceConfig { type Err = Error; fn from_str(config_str: &str) -> Result { if config_str.is_empty() { return Ok(Default::default()); } Ok(DeviceConfig { path: PathBuf::from(config_str), }) } } #[test] fn validate_from_str_device_config() { let config = DeviceConfig::from_str("").unwrap(); assert_eq!(config, Default::default()); let config = DeviceConfig::from_str("/dev/tpm0").unwrap(); assert_eq!(config.path, PathBuf::from("/dev/tpm0")); } /// Configuration for an Mssim TCTI context /// /// The default configuration will point to `localhost:2321` #[derive(Clone, Debug, PartialEq, Eq)] pub struct NetworkTPMConfig { /// Address of the server to connect to /// /// Defaults to `localhost` host: ServerAddress, /// Port used by the server at the address given in `host` /// /// Defaults to `2321` port: u16, } const DEFAULT_SERVER_PORT: u16 = 2321; impl Default for NetworkTPMConfig { fn default() -> Self { NetworkTPMConfig { host: Default::default(), port: DEFAULT_SERVER_PORT, } } } impl FromStr for NetworkTPMConfig { type Err = Error; fn from_str(config_str: &str) -> Result { if config_str.is_empty() { return Ok(Default::default()); } let host_pattern = Regex::new(r"(,|^)host=(.*?)(,|$)").unwrap(); // should not fail let host = host_pattern .captures(config_str) .map_or(Ok(Default::default()), |captures| { ServerAddress::from_str(captures.get(2).map_or("", |m| m.as_str())) })?; let port_pattern = Regex::new(r"(,|^)port=(.*?)(,|$)").unwrap(); // should not fail let port = port_pattern .captures(config_str) .map_or(Ok(DEFAULT_SERVER_PORT), |captures| { u16::from_str(captures.get(2).map_or("", |m| m.as_str())) .or(Err(Error::WrapperError(WrapperErrorKind::InvalidParam))) })?; Ok(NetworkTPMConfig { host, port }) } } #[test] fn validate_from_str_networktpm_config() { let config = NetworkTPMConfig::from_str("").unwrap(); assert_eq!(config, Default::default()); let config = NetworkTPMConfig::from_str("fjshd89943r=joishdf894u9r,sio0983=9u98jj").unwrap(); assert_eq!(config, Default::default()); let config = NetworkTPMConfig::from_str("host=127.0.0.1,random=value").unwrap(); assert_eq!( config.host, ServerAddress::Ip(IpAddr::V4(std::net::Ipv4Addr::new(127, 0, 0, 1))) ); assert_eq!(config.port, DEFAULT_SERVER_PORT); let config = NetworkTPMConfig::from_str("port=1234,random=value").unwrap(); assert_eq!(config.host, Default::default()); assert_eq!(config.port, 1234); let config = NetworkTPMConfig::from_str("host=localhost,port=1234").unwrap(); assert_eq!( config.host, ServerAddress::Hostname(String::from("localhost")) ); assert_eq!(config.port, 1234); let config = NetworkTPMConfig::from_str("port=1234,host=localhost").unwrap(); assert_eq!(config.host, "localhost".parse::().unwrap()); assert_eq!(config.port, 1234); let config = NetworkTPMConfig::from_str("port=1234,host=localhost,random=value").unwrap(); assert_eq!(config.host, "localhost".parse::().unwrap()); assert_eq!(config.port, 1234); let config = NetworkTPMConfig::from_str("host=1234.1234.1234.1234.12445.111").unwrap(); assert_eq!( config.host, ServerAddress::Hostname(String::from("1234.1234.1234.1234.12445.111")) ); let _ = NetworkTPMConfig::from_str("port=abdef").unwrap_err(); let _ = NetworkTPMConfig::from_str("host=-timey-wimey").unwrap_err(); let _ = NetworkTPMConfig::from_str("host=abc@def").unwrap_err(); let _ = NetworkTPMConfig::from_str("host=").unwrap_err(); let _ = NetworkTPMConfig::from_str("port=").unwrap_err(); let _ = NetworkTPMConfig::from_str("port=,host=,yas").unwrap_err(); } /// Address of a TPM server /// /// The default value is `localhost` #[derive(Clone, Debug, PartialEq, Eq)] pub enum ServerAddress { /// IPv4 or IPv6 address Ip(IpAddr), /// Hostname /// /// The string is checked for compatibility with DNS hostnames /// before the context is created Hostname(String), } impl FromStr for ServerAddress { type Err = Error; fn from_str(config_str: &str) -> Result { if let Ok(addr) = IpAddr::from_str(config_str) { return Ok(ServerAddress::Ip(addr)); } if !hostname_validator::is_valid(config_str) { return Err(Error::WrapperError(WrapperErrorKind::InvalidParam)); } Ok(ServerAddress::Hostname(config_str.to_owned())) } } impl std::fmt::Display for ServerAddress { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { ServerAddress::Ip(addr) => addr.fmt(f), ServerAddress::Hostname(name) => name.fmt(f), } } } impl Default for ServerAddress { fn default() -> Self { ServerAddress::Hostname(String::from("localhost")) } } /// Configuration for a TABRMD TCTI context #[derive(Clone, Debug, PartialEq, Eq)] pub struct TabrmdConfig { /// Bus name to be used by TABRMD /// /// Defaults tp `com.intel.tss2.Tabrmd` // TODO: this could be changed to use the `dbus` crate, which has some // more dependencies, though bus_name: String, /// Bus type to be used by TABRMD /// /// Defaults to `System` bus_type: BusType, } const DEFAULT_BUS_NAME: &str = "com.intel.tss2.Tabrmd"; impl Default for TabrmdConfig { fn default() -> Self { TabrmdConfig { bus_name: String::from(DEFAULT_BUS_NAME), bus_type: Default::default(), } } } impl FromStr for TabrmdConfig { type Err = Error; fn from_str(config_str: &str) -> Result { if config_str.is_empty() { return Ok(Default::default()); } let bus_name_pattern = Regex::new(r"(,|^)bus_name=(.*?)(,|$)").unwrap(); // should not fail let bus_name = bus_name_pattern.captures(config_str).map_or( Ok(DEFAULT_BUS_NAME.to_owned()), |captures| { let valid_bus_name_pattern = Regex::new(r"^[a-zA-Z0-9\-_]+(\.[a-zA-Z0-9\-_]+)+$").unwrap(); //should not fail if !valid_bus_name_pattern.is_match(captures.get(2).map_or("", |m| m.as_str())) { return Err(Error::WrapperError(WrapperErrorKind::InvalidParam)); } Ok(captures.get(2).map_or("", |m| m.as_str()).to_owned()) }, )?; let bus_type_pattern = Regex::new(r"(,|^)bus_type=(.*?)(,|$)").unwrap(); // should not fail let bus_type = bus_type_pattern .captures(config_str) .map_or(Ok(Default::default()), |captures| { BusType::from_str(captures.get(2).map_or("", |m| m.as_str())) })?; Ok(TabrmdConfig { bus_name, bus_type }) } } /// DBus type for usage with TABRMD #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] pub enum BusType { #[default] System, Session, } impl FromStr for BusType { type Err = Error; fn from_str(config_str: &str) -> Result { match config_str { "session" => Ok(BusType::Session), "system" => Ok(BusType::System), _ => Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), } } } impl std::fmt::Display for BusType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { BusType::Session => write!(f, "session"), BusType::System => write!(f, "system"), } } } #[test] fn validate_from_str_tabrmd_config() { let config = TabrmdConfig::from_str("").unwrap(); assert_eq!(config, Default::default()); let config = TabrmdConfig::from_str("fjshd89943r=joishdf894u9r,sio0983=9u98jj").unwrap(); assert_eq!(config, Default::default()); let config = TabrmdConfig::from_str("bus_name=one.true.bus.Name,random=value").unwrap(); assert_eq!(&config.bus_name, "one.true.bus.Name"); assert_eq!(config.bus_type, Default::default()); let config = TabrmdConfig::from_str("bus_type=session,random=value").unwrap(); assert_eq!(&config.bus_name, DEFAULT_BUS_NAME); assert_eq!(config.bus_type, BusType::Session); let config = TabrmdConfig::from_str("bus_name=one.true.bus.Name,bus_type=system").unwrap(); assert_eq!(&config.bus_name, "one.true.bus.Name"); assert_eq!(config.bus_type, BusType::System); let config = TabrmdConfig::from_str("bus_type=system,bus_name=one.true.bus.Name").unwrap(); assert_eq!(&config.bus_name, "one.true.bus.Name"); assert_eq!(config.bus_type, BusType::System); let config = TabrmdConfig::from_str("bus_type=system,bus_name=one.true.bus.Name,random=value").unwrap(); assert_eq!(&config.bus_name, "one.true.bus.Name"); assert_eq!(config.bus_type, BusType::System); let _ = TabrmdConfig::from_str("bus_name=abc&.bcd").unwrap_err(); let _ = TabrmdConfig::from_str("bus_name=adfsdgdfg4gf4").unwrap_err(); let _ = TabrmdConfig::from_str("bus_name=,bus_type=,bla?").unwrap_err(); let _ = TabrmdConfig::from_str("bus_type=randooom").unwrap_err(); } tss-esapi-7.4.0/src/traits.rs000064400000000000000000000010511046102023000142040ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::Result; /// Trait for types that can be converted into /// TPM marshalled data. pub trait Marshall: Sized { const BUFFER_SIZE: usize; /// Returns the type in the form of marshalled data fn marshall(&self) -> Result>; } /// Trait for types that can be created from /// TPM marshalled data. pub trait UnMarshall: Sized { /// Creates the type from marshalled data. fn unmarshall(marshalled_data: &[u8]) -> Result; } tss-esapi-7.4.0/src/utils/mod.rs000064400000000000000000000270171046102023000146270ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! Utility module //! //! This module mostly contains helper elements meant to act as either wrappers around FFI-level //! structs or builders for them, along with other convenience elements. //! The naming structure usually takes the names inherited from the TSS spec and applies Rust //! guidelines to them. Structures that are meant to act as builders have `Builder` appended to //! type name. Unions are converted to Rust `enum`s by dropping the `TPMU` qualifier and appending //! `Union`. use crate::attributes::ObjectAttributesBuilder; use crate::constants::PropertyTag; use crate::interface_types::{ algorithm::{HashingAlgorithm, PublicAlgorithm}, ecc::EccCurve, key_bits::RsaKeyBits, }; use crate::structures::{ EccPoint, EccScheme, Public, PublicBuilder, PublicEccParametersBuilder, PublicKeyRsa, PublicRsaParametersBuilder, RsaExponent, RsaScheme, SymmetricDefinitionObject, }; use crate::tss2_esys::*; use crate::{Context, Error, Result, WrapperErrorKind}; use zeroize::Zeroize; use serde::{Deserialize, Serialize}; use std::convert::{TryFrom, TryInto}; /// Rust native wrapper for `TPMS_CONTEXT` objects. /// /// This structure is intended to help with persisting object contexts. As the main reason for /// saving the context of an object is to be able to reuse it later, on demand, a serializable /// structure is most commonly needed. `TpmsContext` implements the `Serialize` and `Deserialize` /// defined by `serde`. #[derive(Debug, Serialize, Deserialize, Clone, Zeroize)] #[zeroize(drop)] pub struct TpmsContext { sequence: u64, saved_handle: TPMI_DH_CONTEXT, hierarchy: TPMI_RH_HIERARCHY, context_blob: Vec, } impl TpmsContext { /// Get a reference to the `context_blob` field pub fn context_blob(&self) -> &Vec { &self.context_blob } } // TODO: Replace with `From` impl TryFrom for TpmsContext { type Error = Error; fn try_from(tss2_context: TPMS_CONTEXT) -> Result { let mut context = TpmsContext { sequence: tss2_context.sequence, saved_handle: tss2_context.savedHandle, hierarchy: tss2_context.hierarchy, context_blob: tss2_context.contextBlob.buffer.to_vec(), }; context.context_blob.truncate( tss2_context .contextBlob .size .try_into() .map_err(|_| Error::local_error(WrapperErrorKind::WrongParamSize))?, ); Ok(context) } } #[allow(clippy::needless_update)] impl TryFrom for TPMS_CONTEXT { type Error = Error; fn try_from(context: TpmsContext) -> Result { let buffer_size = context.context_blob.len(); if buffer_size > 5188 { return Err(Error::local_error(WrapperErrorKind::WrongParamSize)); } let mut buffer = [0_u8; 5188]; for (i, val) in context.context_blob.iter().enumerate() { buffer[i] = *val; } Ok(TPMS_CONTEXT { sequence: context.sequence, savedHandle: context.saved_handle, hierarchy: context.hierarchy, contextBlob: TPM2B_CONTEXT_DATA { size: buffer_size.try_into().unwrap(), // should not panic given the check above buffer, }, ..Default::default() }) } } /// Create the [Public] structure for a restricted decryption key. /// /// * `symmetric` - Cipher to be used for decrypting children of the key /// * `key_bits` - Size in bits of the decryption key /// * `pub_exponent` - Public exponent of the RSA key pub fn create_restricted_decryption_rsa_public( symmetric: SymmetricDefinitionObject, rsa_key_bits: RsaKeyBits, rsa_pub_exponent: RsaExponent, ) -> Result { let object_attributes = ObjectAttributesBuilder::new() .with_fixed_tpm(true) .with_fixed_parent(true) .with_sensitive_data_origin(true) .with_user_with_auth(true) .with_decrypt(true) .with_sign_encrypt(false) .with_restricted(true) .build()?; PublicBuilder::new() .with_public_algorithm(PublicAlgorithm::Rsa) .with_name_hashing_algorithm(HashingAlgorithm::Sha256) .with_object_attributes(object_attributes) .with_rsa_parameters( PublicRsaParametersBuilder::new_restricted_decryption_key( symmetric, rsa_key_bits, rsa_pub_exponent, ) .build()?, ) .with_rsa_unique_identifier(PublicKeyRsa::default()) .build() } /// Create the [Public] structure for an unrestricted encryption/decryption key. /// /// * `symmetric` - Cipher to be used for decrypting children of the key /// * `key_bits` - Size in bits of the decryption key /// * `pub_exponent` - Public exponent of the RSA key pub fn create_unrestricted_encryption_decryption_rsa_public( rsa_key_bits: RsaKeyBits, rsa_pub_exponent: RsaExponent, ) -> Result { let object_attributes = ObjectAttributesBuilder::new() .with_fixed_tpm(true) .with_fixed_parent(true) .with_sensitive_data_origin(true) .with_user_with_auth(true) .with_decrypt(true) .with_sign_encrypt(true) .with_restricted(false) .build()?; PublicBuilder::new() .with_public_algorithm(PublicAlgorithm::Rsa) .with_name_hashing_algorithm(HashingAlgorithm::Sha256) .with_object_attributes(object_attributes) .with_rsa_parameters( PublicRsaParametersBuilder::new() .with_scheme(RsaScheme::Null) .with_key_bits(rsa_key_bits) .with_exponent(rsa_pub_exponent) .with_is_signing_key(true) .with_is_decryption_key(true) .with_restricted(false) .build()?, ) .with_rsa_unique_identifier(PublicKeyRsa::default()) .build() } /// Create the [Public] structure for an RSA unrestricted signing key. /// /// * `scheme` - RSA scheme to be used for signing /// * `key_bits` - Size in bits of the decryption key /// * `pub_exponent` - Public exponent of the RSA key pub fn create_unrestricted_signing_rsa_public( scheme: RsaScheme, rsa_key_bits: RsaKeyBits, rsa_pub_exponent: RsaExponent, ) -> Result { let object_attributes = ObjectAttributesBuilder::new() .with_fixed_tpm(true) .with_fixed_parent(true) .with_sensitive_data_origin(true) .with_user_with_auth(true) .with_decrypt(false) .with_sign_encrypt(true) .with_restricted(false) .build()?; PublicBuilder::new() .with_public_algorithm(PublicAlgorithm::Rsa) .with_name_hashing_algorithm(HashingAlgorithm::Sha256) .with_object_attributes(object_attributes) .with_rsa_parameters( PublicRsaParametersBuilder::new_unrestricted_signing_key( scheme, rsa_key_bits, rsa_pub_exponent, ) .build()?, ) .with_rsa_unique_identifier(PublicKeyRsa::default()) .build() } /// Create the [Public] structure for an RSA unrestricted signing key. /// /// * `scheme` - RSA scheme to be used for signing /// * `key_bits` - Size in bits of the decryption key /// * `pub_exponent` - Public exponent of the RSA key /// * `rsa_public_key` - The public part of the RSA key that is going to be used as unique identifier. pub fn create_unrestricted_signing_rsa_public_with_unique( scheme: RsaScheme, rsa_key_bits: RsaKeyBits, rsa_pub_exponent: RsaExponent, rsa_public_key: PublicKeyRsa, ) -> Result { let object_attributes = ObjectAttributesBuilder::new() .with_fixed_tpm(true) .with_fixed_parent(true) .with_sensitive_data_origin(true) .with_user_with_auth(true) .with_decrypt(false) .with_sign_encrypt(true) .with_restricted(false) .build()?; PublicBuilder::new() .with_public_algorithm(PublicAlgorithm::Rsa) .with_name_hashing_algorithm(HashingAlgorithm::Sha256) .with_object_attributes(object_attributes) .with_rsa_parameters( PublicRsaParametersBuilder::new_unrestricted_signing_key( scheme, rsa_key_bits, rsa_pub_exponent, ) .build()?, ) .with_rsa_unique_identifier(rsa_public_key) .build() } /// Create the [Public] structure for an ECC unrestricted signing key. /// /// * `scheme` - Asymmetric scheme to be used for signing; *must* be an RSA signing scheme /// * `curve` - identifier of the precise curve to be used with the key pub fn create_unrestricted_signing_ecc_public( scheme: EccScheme, curve: EccCurve, ) -> Result { let object_attributes = ObjectAttributesBuilder::new() .with_fixed_tpm(true) .with_fixed_parent(true) .with_sensitive_data_origin(true) .with_user_with_auth(true) .with_decrypt(false) .with_sign_encrypt(true) .with_restricted(false) .build()?; PublicBuilder::new() .with_public_algorithm(PublicAlgorithm::Ecc) .with_name_hashing_algorithm(HashingAlgorithm::Sha256) .with_object_attributes(object_attributes) .with_ecc_parameters( PublicEccParametersBuilder::new_unrestricted_signing_key(scheme, curve).build()?, ) .with_ecc_unique_identifier(EccPoint::default()) .build() } /// Container for public key values #[derive(Debug, Clone, Serialize, Deserialize, Zeroize, PartialEq, Eq)] pub enum PublicKey { /// RSA public modulus (see 27.5.3.4 in the Architecture spec) /// /// This is the value extracted from the `unique` part of `TPMT_PUBLIC`. /// The exponent is not included here as the expectation is that the /// exponent is always pinned to 65537 (2^16 + 1). /// /// The modulus is in Big-Endian format. Rsa(Vec), /// Public elliptic curve point (see 27.5.3.5 in the Architecture spec) /// /// The x and y coordinates are given uncompressed. Ecc { x: Vec, y: Vec }, } impl TryFrom for PublicKey { type Error = Error; fn try_from(public: Public) -> Result { match public { Public::Rsa { unique, .. } => Ok(PublicKey::Rsa(unique.value().to_vec())), Public::Ecc { unique, .. } => Ok(PublicKey::Ecc { x: unique.x().value().to_vec(), y: unique.y().value().to_vec(), }), _ => Err(Error::local_error(WrapperErrorKind::WrongValueFromTpm)), } } } fn tpm_int_to_string(num: u32) -> String { num.to_be_bytes() .iter() .filter(|x| **x != 0) .map(|x| char::from(*x)) .collect() } /// Get the TPM vendor name pub fn get_tpm_vendor(context: &mut Context) -> Result { // Retrieve the TPM property values Ok([ PropertyTag::VendorString1, PropertyTag::VendorString2, PropertyTag::VendorString3, PropertyTag::VendorString4, ] .iter() // Retrieve property values .map(|propid| context.get_tpm_property(*propid)) // Collect and return an error if we got one .collect::>>>()? .iter() // Filter out the Option::None values .filter_map(|x| *x) // Filter out zero values .filter(|x| *x != 0) // Map through int_to_string .map(tpm_int_to_string) // Collect to a single string .collect()) } tss-esapi-7.4.0/tests/Cargo.lock.frozen000064400000000000000000000472741046102023000161330ustar 00000000000000# This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "aho-corasick" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" dependencies = [ "memchr", ] [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64" version = "0.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" [[package]] name = "bindgen" version = "0.66.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2b84e06fc203107bfbad243f4aba2af864eb7db3b1cf46ea0a023b0b433d2a7" dependencies = [ "bitflags", "cexpr", "clang-sys", "lazy_static", "lazycell", "log", "peeking_take_while", "prettyplease", "proc-macro2", "quote", "regex", "rustc-hash", "shlex", "syn", "which", ] [[package]] name = "bitfield" version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d7e60934ceec538daadb9d8432424ed043a904d8e0243f3c6446bce549a46ac" [[package]] name = "bitflags" version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" [[package]] name = "block-buffer" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ "generic-array", ] [[package]] name = "cexpr" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ "nom", ] [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clang-sys" version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" dependencies = [ "glob", "libc", "libloading", ] [[package]] name = "cpufeatures" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" dependencies = [ "libc", ] [[package]] name = "crypto-common" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", "typenum", ] [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", ] [[package]] name = "either" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "enumflags2" version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5998b4f30320c9d93aed72f63af821bfdac50465b75428fce77b48ec482c3939" dependencies = [ "enumflags2_derive", ] [[package]] name = "enumflags2_derive" version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f95e2801cd355d4a1a3e3953ce6ee5ae9603a5c833455343a8bfe3f44d418246" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "env_logger" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" dependencies = [ "humantime", "is-terminal", "log", "regex", "termcolor", ] [[package]] name = "errno" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" dependencies = [ "libc", "windows-sys", ] [[package]] name = "generic-array" version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", ] [[package]] name = "glob" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "hermit-abi" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "home" version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" dependencies = [ "windows-sys", ] [[package]] name = "hostname-validator" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f558a64ac9af88b5ba400d99b579451af0d39c6d360980045b91aac966d705e2" [[package]] name = "humantime" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "is-terminal" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ "hermit-abi", "rustix", "windows-sys", ] [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "lazycell" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" [[package]] name = "libloading" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" dependencies = [ "cfg-if", "winapi", ] [[package]] name = "linux-raw-sys" version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" [[package]] name = "log" version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "mbox" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f88d5c34d63aad11aa4321ef55ccb064af58b3ad8091079ae22bf83e5eb75d6" dependencies = [ "libc", "rustc_version", "stable_deref_trait", ] [[package]] name = "memchr" version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "minimal-lexical" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "nom" version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ "memchr", "minimal-lexical", ] [[package]] name = "num-derive" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfb77679af88f8b125209d354a202862602672222e7f2313fdd6dc349bad4712" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "num-traits" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", ] [[package]] name = "oid" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c19903c598813dba001b53beeae59bb77ad4892c5c1b9b3500ce4293a0d06c2" dependencies = [ "serde", ] [[package]] name = "once_cell" version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "peeking_take_while" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" [[package]] name = "pest" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c022f1e7b65d6a24c0dbbd5fb344c66881bc01f3e5ae74a1c8100f2f985d98a4" dependencies = [ "memchr", "thiserror", "ucd-trie", ] [[package]] name = "picky-asn1" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "295eea0f33c16be21e2a98b908fdd4d73c04dd48c8480991b76dbcf0cb58b212" dependencies = [ "oid", "serde", "serde_bytes", ] [[package]] name = "picky-asn1-der" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5df7873a9e36d42dadb393bea5e211fe83d793c172afad5fb4ec846ec582793f" dependencies = [ "picky-asn1", "serde", "serde_bytes", ] [[package]] name = "picky-asn1-x509" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c5f20f71a68499ff32310f418a6fad8816eac1a2859ed3f0c5c741389dd6208" dependencies = [ "base64", "oid", "picky-asn1", "picky-asn1-der", "serde", ] [[package]] name = "pkg-config" version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] name = "prettyplease" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" dependencies = [ "proc-macro2", "syn", ] [[package]] name = "proc-macro2" version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" dependencies = [ "unicode-ident", ] [[package]] name = "quote" version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] [[package]] name = "regex" version = "1.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff" dependencies = [ "aho-corasick", "memchr", "regex-automata", "regex-syntax", ] [[package]] name = "regex-automata" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" [[package]] name = "rustc-hash" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc_version" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" dependencies = [ "semver", ] [[package]] name = "rustix" version = "0.38.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f25469e9ae0f3d0047ca8b93fc56843f38e6774f0914a107ff8b41be8be8e0b7" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys", "windows-sys", ] [[package]] name = "semver" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" dependencies = [ "semver-parser", ] [[package]] name = "semver-parser" version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" dependencies = [ "pest", ] [[package]] name = "serde" version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" dependencies = [ "serde_derive", ] [[package]] name = "serde_bytes" version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab33ec92f677585af6d88c65593ae2375adde54efdbf16d597f2cbc7a6d368ff" dependencies = [ "serde", ] [[package]] name = "serde_derive" version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "sha2" version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", "digest", ] [[package]] name = "shlex" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" [[package]] name = "stable_deref_trait" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "syn" version = "2.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "target-lexicon" version = "0.12.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a" [[package]] name = "termcolor" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" dependencies = [ "winapi-util", ] [[package]] name = "thiserror" version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "tss-esapi" version = "7.4.0" dependencies = [ "bitfield", "enumflags2", "env_logger", "hostname-validator", "log", "mbox", "num-derive", "num-traits", "oid", "picky-asn1", "picky-asn1-x509", "regex", "serde", "sha2", "tss-esapi-sys", "zeroize", ] [[package]] name = "tss-esapi-sys" version = "0.5.0" dependencies = [ "bindgen", "pkg-config", "target-lexicon", ] [[package]] name = "typenum" version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "ucd-trie" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "which" version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" dependencies = [ "either", "home", "once_cell", "rustix", ] [[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", ] [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "zeroize" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" dependencies = [ "zeroize_derive", ] [[package]] name = "zeroize_derive" version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", "syn", ] tss-esapi-7.4.0/tests/Dockerfile-fedora000064400000000000000000000002501046102023000161330ustar 00000000000000FROM fedora:35 RUN dnf install -y \ tpm2-tss-devel tpm2-abrmd tpm2-tools \ swtpm swtpm-tools \ rust clippy cargo \ llvm llvm-devel clang pkg-config \ dbus-daemon tss-esapi-7.4.0/tests/Dockerfile-fedora-rawhide000064400000000000000000000002551046102023000175610ustar 00000000000000FROM fedora:rawhide RUN dnf install -y \ tpm2-tss-devel tpm2-abrmd tpm2-tools \ swtpm swtpm-tools \ rust clippy cargo \ llvm llvm-devel clang pkg-config \ dbus-daemon tss-esapi-7.4.0/tests/Dockerfile-ubuntu000064400000000000000000000013001046102023000162120ustar 00000000000000FROM ghcr.io/tpm2-software/ubuntu-18.04:latest ARG TPM2_TSS_VERSION=2.4.6 ENV TPM2_TSS_VERSION=$TPM2_TSS_VERSION ENV PKG_CONFIG_PATH /usr/local/lib/pkgconfig # Download and install the TSS library RUN git clone https://github.com/tpm2-software/tpm2-tss.git --branch $TPM2_TSS_VERSION RUN cd tpm2-tss \ && ./bootstrap \ && ./configure \ && make -j$(nproc) \ && make install \ && ldconfig # Download and install TPM2 tools RUN git clone https://github.com/tpm2-software/tpm2-tools.git --branch 4.1 RUN cd tpm2-tools \ && ./bootstrap \ && ./configure --enable-unit \ && make install # Install Rust toolchain RUN curl https://sh.rustup.rs -sSf | bash -s -- -y ENV PATH="/root/.cargo/bin:${PATH}" tss-esapi-7.4.0/tests/all-fedora.sh000075500000000000000000000024271046102023000152600ustar 00000000000000#!/usr/bin/env bash # Copyright 2019 Contributors to the Parsec project. # SPDX-License-Identifier: Apache-2.0 # This script executes static checks and tests for the tss-esapi crate. # It can be run inside the container which Dockerfile is in the same folder. # # Usage: ./tests/all.sh set -euf -o pipefail ############################ # Run the TPM SWTPM server # ############################ mkdir /tmp/tpmdir swtpm_setup --tpm2 \ --tpmstate /tmp/tpmdir \ --createek --decryption --create-ek-cert \ --create-platform-cert \ --pcr-banks sha1,sha256 \ --display swtpm socket --tpm2 \ --tpmstate dir=/tmp/tpmdir \ --flags startup-clear \ --ctrl type=tcp,port=2322 \ --server type=tcp,port=2321 \ --daemon tpm2-abrmd \ --logger=stdout \ --tcti=swtpm: \ --allow-root \ --session \ --flush-all & ################## # Execute clippy # ################## cargo clippy --all-targets --all-features -- -D clippy::all -D clippy::cargo ################### # Build the crate # ################### RUST_BACKTRACE=1 cargo build --features generate-bindings ################# # Run the tests # ################# TEST_TCTI=tabrmd:bus_type=session RUST_BACKTRACE=1 RUST_LOG=info cargo test --features generate-bindings -- --test-threads=1 --nocapture tss-esapi-7.4.0/tests/all-ubuntu.sh000075500000000000000000000027121046102023000153370ustar 00000000000000#!/usr/bin/env bash # Copyright 2019 Contributors to the Parsec project. # SPDX-License-Identifier: Apache-2.0 # This script executes static checks and tests for the tss-esapi crate. # It can be run inside the container which Dockerfile is in the same folder. # # Usage: ./tests/all.sh set -euf -o pipefail ################################################# # Change rust toolchain version ################################################# if [[ ! -z ${RUST_TOOLCHAIN_VERSION:+x} ]]; then rustup override set ${RUST_TOOLCHAIN_VERSION} # Use the frozen Cargo lock to prevent any drift from MSRV being upgraded # underneath our feet. cp tests/Cargo.lock.frozen ../Cargo.lock fi ################################################# # Generate bindings for non-"standard" versions # ################################################# if [[ "$TPM2_TSS_VERSION" != "2.4.6" ]]; then FEATURES="--features=generate-bindings" else FEATURES="" fi ################################# # Run the TPM simulation server # ################################# tpm_server & sleep 5 tpm2_startup -c -T mssim ################## # Execute clippy # ################## cargo clippy --all-targets --all-features -- -D clippy::all -D clippy::cargo ################### # Build the crate # ################### RUST_BACKTRACE=1 cargo build $FEATURES ################# # Run the tests # ################# TEST_TCTI=mssim: RUST_BACKTRACE=1 RUST_LOG=info cargo test $FEATURES -- --test-threads=1 --nocapture tss-esapi-7.4.0/tests/coverage.sh000075500000000000000000000007651046102023000150500ustar 00000000000000#!/usr/bin/env bash # Copyright 2021 Contributors to the Parsec project. # SPDX-License-Identifier: Apache-2.0 set -euf -o pipefail ################################# # Run the TPM simulation server # ################################# tpm_server & sleep 5 tpm2_startup -c -T mssim ############################# # Install and run tarpaulin # ############################# cargo install cargo-tarpaulin cargo tarpaulin --tests --out Xml --exclude-files="tests/*,../*" -- --test-threads=1 --nocapture tss-esapi-7.4.0/tests/cross-compile.sh000075500000000000000000000055371046102023000160360ustar 00000000000000#!/usr/bin/env bash # Copyright 2021 Contributors to the Parsec project. # SPDX-License-Identifier: Apache-2.0 # Cross compile the `tss-esapi` crate (and its dependencies) for Armv7 and Aarch64 # In order to cross-compile the TSS library we need to also cross-compile OpenSSL set -euf -o pipefail OPENSSL_GIT="https://github.com/openssl/openssl.git" OPENSSL_VERSION="OpenSSL_1_1_1j" TPM2_TSS_GIT="https://github.com/tpm2-software/tpm2-tss.git" TPM2_TSS_VERSION="2.4.6" export SYSROOT="/tmp/sysroot" git_checkout() { if [ ! -d "/tmp/$(basename "$1" ".git")" ]; then pushd /tmp git clone "$1" --branch "$2" popd fi } prepare_sysroot() { # Prepare the SYSROOT [ -d "$SYSROOT" ] && rm -fr "$SYSROOT" mkdir -p "$SYSROOT" # Allow the `pkg-config` crate to cross-compile export PKG_CONFIG_ALLOW_CROSS=1 export PKG_CONFIG_PATH="$SYSROOT"/lib/pkgconfig:"$SYSROOT"/share/pkgconfig export PKG_CONFIG_SYSROOT_DIR="$SYSROOT" } cross-compile-openssl() { pushd /tmp/openssl # Compile and copy files over ./Configure $2 shared --prefix="$SYSROOT" --openssldir="$SYSROOT"/openssl --cross-compile-prefix=$1- make clean make depend make -j$(nproc) make install_sw popd } cross-compile-tpm2-tss() { pushd /tmp/tpm2-tss [ ! -f configure ] && ./bootstrap ./configure --enable-fapi=no --prefix=/ --build=x86_64-pc-linux-gnu --host=$1 --target=$1 CC=$1-gcc make clean make -j$(nproc) make DESTDIR="$SYSROOT" install popd } # Download cross-compilers apt update apt install -y gcc-multilib apt install -y gcc-arm-linux-gnueabi apt install -y gcc-aarch64-linux-gnu # Download other dependencies apt install -y autoconf apt install -y autoconf-archive apt install -y cmake apt install -y libclang-dev apt install -y libtool apt install -y pkgconf # Download OpenSSL, tpm2-tss and dependencies source code git_checkout "$OPENSSL_GIT" "$OPENSSL_VERSION" git_checkout "$TPM2_TSS_GIT" "$TPM2_TSS_VERSION" # Download OpenSSL source code if [ ! -d "/tmp/openssl" ]; then pushd /tmp git clone https://github.com/openssl/openssl.git --branch $OPENSSL_VERSION popd fi # Clean and prepare SYSROOT prepare_sysroot # Compile OpenSSL and TSS stack for aarch64-unknown-linux-gnu cross-compile-openssl aarch64-linux-gnu linux-generic64 cross-compile-tpm2-tss aarch64-linux-gnu rustup target add aarch64-unknown-linux-gnu cargo build --features generate-bindings --target aarch64-unknown-linux-gnu cargo build --target aarch64-unknown-linux-gnu # Clean and prepare SYSROOT prepare_sysroot # Compile OpenSSL and TSS stack for armv7-unknown-linux-gnueabi cross-compile-openssl arm-linux-gnueabi linux-generic32 cross-compile-tpm2-tss arm-linux-gnueabi rustup target add armv7-unknown-linux-gnueabi cargo build --features generate-bindings --target armv7-unknown-linux-gnueabi cargo build --target armv7-unknown-linux-gnueabi tss-esapi-7.4.0/tests/integration_tests/abstraction_tests/ak_tests.rs000064400000000000000000000136011046102023000243720ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::{TryFrom, TryInto}; use tss_esapi::{ abstraction::{ak, ek, KeyCustomization}, attributes::{ObjectAttributesBuilder, SessionAttributesBuilder}, constants::SessionType, handles::AuthHandle, interface_types::{ algorithm::{AsymmetricAlgorithm, HashingAlgorithm, SignatureSchemeAlgorithm}, session_handles::PolicySession, }, structures::{Auth, Digest, PublicBuilder, SymmetricDefinition}, }; use crate::common::create_ctx_without_session; #[test] fn test_create_ak_rsa_rsa() { let mut context = create_ctx_without_session(); let ek_rsa = ek::create_ek_object(&mut context, AsymmetricAlgorithm::Rsa, None).unwrap(); ak::create_ak( &mut context, ek_rsa, HashingAlgorithm::Sha256, SignatureSchemeAlgorithm::RsaPss, None, None, ) .unwrap(); } #[test] fn test_create_ak_rsa_ecc() { let mut context = create_ctx_without_session(); let ek_rsa = ek::create_ek_object(&mut context, AsymmetricAlgorithm::Rsa, None).unwrap(); if ak::create_ak( &mut context, ek_rsa, HashingAlgorithm::Sha256, SignatureSchemeAlgorithm::Sm2, None, None, ) .is_ok() { // We can't use unwrap_err because that requires Debug on the T panic!("Should have errored"); } } #[test] fn test_create_and_use_ak() { let mut context = create_ctx_without_session(); let ek_rsa = ek::create_ek_object(&mut context, AsymmetricAlgorithm::Rsa, None).unwrap(); let ak_auth = Auth::try_from(vec![0x1, 0x2, 0x42]).unwrap(); let att_key = ak::create_ak( &mut context, ek_rsa, HashingAlgorithm::Sha256, SignatureSchemeAlgorithm::RsaPss, Some(ak_auth.clone()), None, ) .unwrap(); let loaded_ak = ak::load_ak( &mut context, ek_rsa, Some(ak_auth), att_key.out_private, att_key.out_public, ) .unwrap(); let (_, key_name, _) = context.read_public(loaded_ak).unwrap(); let cred = vec![1, 2, 3, 4, 5]; let expected = Digest::try_from(vec![1, 2, 3, 4, 5]).unwrap(); let (session_aastributes, session_attributes_mask) = SessionAttributesBuilder::new().build(); let session_1 = context .start_auth_session( None, None, None, SessionType::Hmac, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) .expect("Failed to call start_auth_session") .expect("Failed invalid session value"); context .tr_sess_set_attributes(session_1, session_aastributes, session_attributes_mask) .unwrap(); let session_2 = context .start_auth_session( None, None, None, SessionType::Policy, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) .expect("Failed to call start_auth_session") .expect("Failed invalid session value"); context .tr_sess_set_attributes(session_2, session_aastributes, session_attributes_mask) .expect("Failed to call tr_sess_set_attributes"); let (credential_blob, secret) = context .execute_without_session(|ctx| { ctx.make_credential(ek_rsa, cred.try_into().unwrap(), key_name) }) .unwrap(); let _ = context .execute_with_session(Some(session_1), |ctx| { ctx.policy_secret( PolicySession::try_from(session_2) .expect("Failed to convert auth session to policy session"), AuthHandle::Endorsement, Default::default(), Default::default(), Default::default(), None, ) }) .unwrap(); context.set_sessions((Some(session_1), Some(session_2), None)); let decrypted = context .activate_credential(loaded_ak, ek_rsa, credential_blob, secret) .unwrap(); assert_eq!(expected, decrypted); } #[test] fn test_create_custom_ak() { struct CustomizeKey; impl KeyCustomization for &CustomizeKey { fn attributes( &self, attributes_builder: ObjectAttributesBuilder, ) -> ObjectAttributesBuilder { attributes_builder.with_st_clear(true) } fn template(&self, template_builder: PublicBuilder) -> PublicBuilder { template_builder.with_name_hashing_algorithm(HashingAlgorithm::Sha1) } } let mut context = create_ctx_without_session(); let ek_rsa = ek::create_ek_object(&mut context, AsymmetricAlgorithm::Rsa, None).unwrap(); let ak_auth = Auth::try_from(vec![0x1, 0x2, 0x42]).unwrap(); // Without customization, no st clear let att_key_without = ak::create_ak( &mut context, ek_rsa, HashingAlgorithm::Sha256, SignatureSchemeAlgorithm::RsaPss, Some(ak_auth.clone()), None, ) .unwrap(); assert!( !att_key_without.out_public.object_attributes().st_clear(), "ST Clear was set" ); // With a customization, we get a new attribute let att_key = ak::create_ak( &mut context, ek_rsa, HashingAlgorithm::Sha256, SignatureSchemeAlgorithm::RsaPss, Some(ak_auth), &CustomizeKey, ) .unwrap(); assert_eq!( att_key.out_public.object_attributes().0 & tss_esapi::constants::tss::TPMA_OBJECT_STCLEAR, tss_esapi::constants::tss::TPMA_OBJECT_STCLEAR ); assert_eq!( att_key.out_public.object_attributes().0, att_key_without.out_public.object_attributes().0 | tss_esapi::constants::tss::TPMA_OBJECT_STCLEAR ); assert_eq!( att_key.out_public.name_hashing_algorithm(), HashingAlgorithm::Sha1, ); } tss-esapi-7.4.0/tests/integration_tests/abstraction_tests/ek_tests.rs000064400000000000000000000025451046102023000244030ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use tss_esapi::{ abstraction::ek, constants::response_code::{FormatOneResponseCode, Tss2ResponseCode}, interface_types::algorithm::AsymmetricAlgorithm, Error, }; use crate::common::create_ctx_without_session; #[test] fn test_retrieve_ek_pubcert() { let mut context = create_ctx_without_session(); // The error 395 is for "handle could not be found" - this makes it that if the NV Index // did not exist (the test is run on a TPM without an endorsement cert), it still passes. match ek::retrieve_ek_pubcert(&mut context, AsymmetricAlgorithm::Rsa) { Ok(_) => (), Err(Error::Tss2Error(Tss2ResponseCode::FormatOne(FormatOneResponseCode(395)))) => (), Err(e) => panic!("Error was unexpected: {:?}", e), }; match ek::retrieve_ek_pubcert(&mut context, AsymmetricAlgorithm::Ecc) { Ok(_) => (), Err(Error::Tss2Error(Tss2ResponseCode::FormatOne(FormatOneResponseCode(395)))) => (), Err(e) => panic!("Error was unexpected: {:?}", e), }; } #[test] fn test_create_ek() { let mut context = create_ctx_without_session(); let _ = ek::create_ek_object(&mut context, AsymmetricAlgorithm::Rsa, None).unwrap(); let _ = ek::create_ek_object(&mut context, AsymmetricAlgorithm::Ecc, None).unwrap(); } tss-esapi-7.4.0/tests/integration_tests/abstraction_tests/mod.rs000064400000000000000000000003351046102023000233340ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod ak_tests; mod ek_tests; mod nv_tests; mod pcr_data_tests; mod pcr_tests; mod public_tests; mod transient_key_context_tests; tss-esapi-7.4.0/tests/integration_tests/abstraction_tests/nv_tests.rs000064400000000000000000000123061046102023000244230ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::{ convert::TryFrom, io::{ErrorKind, Seek, SeekFrom, Write}, }; use tss_esapi::{ abstraction::nv, attributes::NvIndexAttributesBuilder, handles::{NvIndexHandle, NvIndexTpmHandle}, interface_types::{ algorithm::HashingAlgorithm, resource_handles::{NvAuth, Provision}, }, structures::{MaxNvBuffer, NvPublicBuilder}, Context, }; use crate::common::create_ctx_with_session; fn write_nv_index(context: &mut Context, nv_index: NvIndexTpmHandle) -> NvIndexHandle { // Create owner nv public. let owner_nv_index_attributes = NvIndexAttributesBuilder::new() .with_owner_write(true) .with_owner_read(true) .with_pp_read(true) .with_owner_read(true) .build() .expect("Failed to create owner nv index attributes"); let owner_nv_public = NvPublicBuilder::new() .with_nv_index(nv_index) .with_index_name_algorithm(HashingAlgorithm::Sha256) .with_index_attributes(owner_nv_index_attributes) .with_data_area_size(1540) .build() .unwrap(); let owner_nv_index_handle = context .nv_define_space(Provision::Owner, None, owner_nv_public) .unwrap(); let value = [1, 2, 3, 4, 5, 6, 7]; let expected_data = MaxNvBuffer::try_from(value.to_vec()).unwrap(); // Write the data using Owner authorization context .nv_write( NvAuth::Owner, owner_nv_index_handle, expected_data.clone(), 0, ) .unwrap(); context .nv_write(NvAuth::Owner, owner_nv_index_handle, expected_data, 1024) .unwrap(); owner_nv_index_handle } #[test] fn list() { let mut context = create_ctx_with_session(); let nv_index = NvIndexTpmHandle::new(0x01500015).unwrap(); assert!(!nv::list(&mut context) .unwrap() .iter() .map(|(public, _)| public.nv_index()) .any(|x| x == nv_index)); let owner_nv_index_handle = write_nv_index(&mut context, nv_index); assert!(nv::list(&mut context) .unwrap() .iter() .map(|(public, _)| public.nv_index()) .any(|x| x == nv_index)); // Need to get the ESYS handle again, as it was closed by nv::list above let owner_nv_index_handle = context .tr_from_tpm_public(nv_index.into()) .unwrap_or_else(|_| owner_nv_index_handle.into()); context .nv_undefine_space(Provision::Owner, owner_nv_index_handle.into()) .expect("Call to nv_undefine_space failed"); } #[test] fn read_full() { let mut context = create_ctx_with_session(); let nv_index = NvIndexTpmHandle::new(0x01500015).unwrap(); let owner_nv_index_handle = write_nv_index(&mut context, nv_index); // Now read it back let read_result = nv::read_full(&mut context, NvAuth::Owner, nv_index); // Need to get the ESYS handle again, as it was closed by nv::read_full above let owner_nv_index_handle = context .tr_from_tpm_public(nv_index.into()) .unwrap_or_else(|_| owner_nv_index_handle.into()); context .nv_undefine_space(Provision::Owner, owner_nv_index_handle.into()) .expect("Call to nv_undefine_space failed"); let read_result = read_result.unwrap(); assert_eq!(read_result.len(), 1540); assert_eq!(read_result[0..7], [1, 2, 3, 4, 5, 6, 7]); assert_eq!(read_result[1024..1031], [1, 2, 3, 4, 5, 6, 7]); } #[test] fn write() { let mut context = create_ctx_with_session(); let nv_index = NvIndexTpmHandle::new(0x01500015).unwrap(); let owner_nv_index_attributes = NvIndexAttributesBuilder::new() .with_owner_write(true) .with_owner_read(true) .with_pp_read(true) .build() .expect("Failed to create owner nv index attributes"); let owner_nv_public = NvPublicBuilder::new() .with_nv_index(nv_index) .with_index_name_algorithm(HashingAlgorithm::Sha256) .with_index_attributes(owner_nv_index_attributes) .with_data_area_size(1540) .build() .unwrap(); let mut rw = nv::NvOpenOptions::NewIndex { nv_public: owner_nv_public, auth_handle: NvAuth::Owner, } .open(&mut context) .unwrap(); let value = [1, 2, 3, 4, 5, 6, 7]; rw.write_all(&value).unwrap(); rw.seek(SeekFrom::Start(1024)).unwrap(); rw.write_all(&value).unwrap(); rw.seek(SeekFrom::Start(1540)).unwrap(); let e = rw.write_all(&value).unwrap_err(); assert_eq!(e.kind(), ErrorKind::WriteZero); // Drop the reader/writer so we can use context again drop(rw); // Now read it back let read_result = nv::read_full(&mut context, NvAuth::Owner, nv_index).unwrap(); assert_eq!(read_result.len(), 1540); assert_eq!(read_result[0..7], [1, 2, 3, 4, 5, 6, 7]); assert_eq!(read_result[1024..1031], [1, 2, 3, 4, 5, 6, 7]); let owner_nv_index_handle = context .execute_without_session(|ctx| ctx.tr_from_tpm_public(nv_index.into())) .expect("Call to tr_from_tpm_public failed"); context .nv_undefine_space(Provision::Owner, owner_nv_index_handle.into()) .expect("Call to nv_undefine_space failed"); } tss-esapi-7.4.0/tests/integration_tests/abstraction_tests/pcr_data_tests.rs000064400000000000000000000101211046102023000255460ustar 00000000000000use tss_esapi::{ abstraction::pcr::PcrData, interface_types::algorithm::HashingAlgorithm, structures::{Digest, DigestList, PcrSelectionListBuilder, PcrSlot}, tss2_esys::TPML_DIGEST, Error, WrapperErrorKind, }; use std::convert::TryFrom; #[test] fn test_valid_to_tpml_digest_conversion() { let pcr_selection_list_1 = PcrSelectionListBuilder::new() .with_selection( HashingAlgorithm::Sha256, &[ PcrSlot::Slot0, PcrSlot::Slot1, PcrSlot::Slot2, PcrSlot::Slot3, PcrSlot::Slot4, PcrSlot::Slot5, PcrSlot::Slot6, PcrSlot::Slot7, ], ) .build() .expect("Failed to create PcrSelectionList 1"); let mut pcr_digest_list_1 = DigestList::new(); for i in 0u8..8u8 { let value: [u8; 1] = [i]; pcr_digest_list_1 .add(Digest::try_from(&value[..]).expect("Failed to create digest value")) .expect("Failed to add value to digest"); } let pcr_selection_list_2 = PcrSelectionListBuilder::new() .with_selection( HashingAlgorithm::Sha256, &[ PcrSlot::Slot8, PcrSlot::Slot9, PcrSlot::Slot10, PcrSlot::Slot11, PcrSlot::Slot12, PcrSlot::Slot13, PcrSlot::Slot14, PcrSlot::Slot15, ], ) .build() .expect("Failed to create PcrSelectionList 2"); let mut pcr_digest_list_2 = DigestList::new(); for i in 8u8..16u8 { let value: [u8; 1] = [i]; pcr_digest_list_2 .add(Digest::try_from(&value[..]).expect("Failed to create digest value")) .expect("Failed to add value to digest"); } let mut pcr_data = PcrData::new(); pcr_data .add(&pcr_selection_list_1, &pcr_digest_list_1) .expect("Failed to add selection and digests nr1"); pcr_data .add(&pcr_selection_list_2, &pcr_digest_list_2) .expect("Failed to add selection and digests nr2"); let tpml_digests: Vec = pcr_data.into(); assert_eq!( tpml_digests.len(), 2, "PcrData did not convert into 2 TPML_DIGEST items as expected" ); for (tpml_digest, count) in tpml_digests.iter().zip(0u8..2u8) { assert_eq!( tpml_digest.count as usize, DigestList::MAX_SIZE, "The converted digest list did not contain expected number of elements" ); for (tpm2b_digest, value) in tpml_digest.digests.iter().zip(8 * count..8 * (count + 1)) { assert_eq!( tpm2b_digest.size, 1, "The converted digest did not contain expected number of bytes" ); assert_eq!( tpm2b_digest.buffer[0], value, "The converted digest did not contain expected values" ); } } } #[test] fn test_invalid_to_tpml_digest_conversion() { let pcr_selection_list_1 = PcrSelectionListBuilder::new() .with_selection( HashingAlgorithm::Sha256, &[ PcrSlot::Slot0, PcrSlot::Slot1, PcrSlot::Slot2, PcrSlot::Slot3, PcrSlot::Slot4, PcrSlot::Slot5, PcrSlot::Slot6, PcrSlot::Slot7, ], ) .build() .expect("Failed to create PcrSelectionList 1"); let mut pcr_digest_list_1 = DigestList::new(); for i in 0u8..7u8 { let value: [u8; 1] = [i]; pcr_digest_list_1 .add(Digest::try_from(&value[..]).expect("Failed to create digest value")) .expect("Failed to add value to digest"); } let mut pcr_data = PcrData::new(); let pcr_data_add_result = pcr_data.add(&pcr_selection_list_1, &pcr_digest_list_1); assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InconsistentParams)), pcr_data_add_result, "Did not receive expected error" ); } tss-esapi-7.4.0/tests/integration_tests/abstraction_tests/pcr_tests.rs000064400000000000000000000111071046102023000245620ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::common::create_ctx_without_session; use tss_esapi::{ interface_types::algorithm::HashingAlgorithm, structures::{PcrSelectionListBuilder, PcrSlot}, }; #[test] fn test_pcr_read_all() { let mut context = create_ctx_without_session(); let pcr_selection_list = PcrSelectionListBuilder::new() .with_selection( HashingAlgorithm::Sha256, &[ PcrSlot::Slot0, PcrSlot::Slot1, PcrSlot::Slot2, PcrSlot::Slot3, PcrSlot::Slot4, PcrSlot::Slot5, PcrSlot::Slot6, PcrSlot::Slot7, PcrSlot::Slot8, PcrSlot::Slot9, PcrSlot::Slot10, PcrSlot::Slot11, PcrSlot::Slot12, PcrSlot::Slot13, PcrSlot::Slot14, PcrSlot::Slot15, PcrSlot::Slot16, PcrSlot::Slot17, PcrSlot::Slot18, PcrSlot::Slot19, PcrSlot::Slot20, PcrSlot::Slot21, PcrSlot::Slot22, PcrSlot::Slot23, ], ) .build() .expect("Failed to create PcrSelectionList for read_all call"); let pcr_data = tss_esapi::abstraction::pcr::read_all(&mut context, pcr_selection_list) .expect("Call to pcr_read_all failed"); assert_eq!( pcr_data .pcr_bank(HashingAlgorithm::Sha256) .expect("PcrData did not contain expected PcrBank") .len(), 24, "PcrData did not contain expected amount of digests" ); let (_count, _read_pcr_selection_1, read_pcrs_1) = context .pcr_read( PcrSelectionListBuilder::new() .with_selection( HashingAlgorithm::Sha256, &[ PcrSlot::Slot0, PcrSlot::Slot1, PcrSlot::Slot2, PcrSlot::Slot3, PcrSlot::Slot4, PcrSlot::Slot5, PcrSlot::Slot6, PcrSlot::Slot7, ], ) .build() .expect("Failed to create PcrSekectinList for first pcr_read call"), ) .expect("Call 1 to pcr_read failed"); let (_count, _read_pcr_selection_2, read_pcrs_2) = context .pcr_read( PcrSelectionListBuilder::new() .with_selection( HashingAlgorithm::Sha256, &[ PcrSlot::Slot8, PcrSlot::Slot9, PcrSlot::Slot10, PcrSlot::Slot11, PcrSlot::Slot12, PcrSlot::Slot13, PcrSlot::Slot14, PcrSlot::Slot15, ], ) .build() .expect("Failed to create PcrSekectinList for second pcr_read call"), ) .expect("Call 2 to pcr_read failed"); let (_count, _read_pcr_selection_3, read_pcrs_3) = context .pcr_read( PcrSelectionListBuilder::new() .with_selection( HashingAlgorithm::Sha256, &[ PcrSlot::Slot16, PcrSlot::Slot17, PcrSlot::Slot18, PcrSlot::Slot19, PcrSlot::Slot20, PcrSlot::Slot21, PcrSlot::Slot22, PcrSlot::Slot23, ], ) .build() .expect("Failed to create PcrSekectinList for third pcr_read call"), ) .expect("Call 3 to pcr_read failed"); [read_pcrs_1, read_pcrs_2, read_pcrs_3] .iter() .enumerate() .for_each(|(idx, dl)| { assert_eq!(dl.len(), 8); let d = pcr_data .pcr_bank(HashingAlgorithm::Sha256) .expect("PcrData did not contain expected PcrBank") .into_iter() .skip(idx * 8) .take(8); assert_eq!(d.len(), 8); dl.value() .iter() .zip(d) .for_each(|(actual, (_, expected))| { assert_eq!(actual, expected); }) }) } tss-esapi-7.4.0/tests/integration_tests/abstraction_tests/public_tests.rs000064400000000000000000000217331046102023000252620ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod public_rsa_test { use picky_asn1::wrapper::IntegerAsn1; use picky_asn1_x509::{AlgorithmIdentifier, PublicKey, SubjectPublicKeyInfo}; use std::convert::TryFrom; use tss_esapi::{ abstraction::public::DecodedKey, attributes::ObjectAttributesBuilder, interface_types::{ algorithm::{HashingAlgorithm, PublicAlgorithm, RsaSchemeAlgorithm}, key_bits::RsaKeyBits, }, structures::{Public, PublicBuilder, PublicKeyRsa, PublicRsaParametersBuilder, RsaScheme}, }; const RSA_KEY: [u8; 256] = [ 0xc9, 0x75, 0xf8, 0xb2, 0x30, 0xf4, 0x24, 0x6e, 0x95, 0xb1, 0x3c, 0x55, 0x0f, 0xe4, 0x48, 0xe9, 0xac, 0x06, 0x1f, 0xa8, 0xbe, 0xa4, 0xd7, 0x1c, 0xa5, 0x5e, 0x2a, 0xbf, 0x60, 0xc2, 0x98, 0x63, 0x6c, 0xb4, 0xe2, 0x61, 0x54, 0x31, 0xc3, 0x3e, 0x9d, 0x1a, 0x83, 0x84, 0x18, 0x51, 0xe9, 0x8c, 0x24, 0xcf, 0xac, 0xc6, 0x0d, 0x26, 0x2c, 0x9f, 0x2b, 0xd5, 0x91, 0x98, 0x89, 0xe3, 0x68, 0x97, 0x36, 0x02, 0xec, 0x16, 0x37, 0x24, 0x08, 0xb4, 0x77, 0xd1, 0x56, 0x10, 0x3e, 0xf0, 0x64, 0xf6, 0x68, 0x50, 0x68, 0x31, 0xf8, 0x9b, 0x88, 0xf2, 0xc5, 0xfb, 0xc9, 0x21, 0xd2, 0xdf, 0x93, 0x6f, 0x98, 0x94, 0x53, 0x68, 0xe5, 0x25, 0x8d, 0x8a, 0xf1, 0xd7, 0x5b, 0xf3, 0xf9, 0xdf, 0x8c, 0x77, 0x24, 0x9e, 0x28, 0x09, 0x36, 0xf0, 0xa2, 0x93, 0x17, 0xad, 0xbb, 0x1a, 0xd7, 0x6f, 0x25, 0x6b, 0x0c, 0xd3, 0x76, 0x7f, 0xcf, 0x3a, 0xe3, 0x1a, 0x84, 0x57, 0x62, 0x71, 0x8a, 0x6a, 0x42, 0x94, 0x71, 0x21, 0x6a, 0x13, 0x73, 0x17, 0x56, 0xa2, 0x38, 0xc1, 0x5e, 0x76, 0x0b, 0x67, 0x6b, 0x6e, 0xcd, 0xd3, 0xe2, 0x8a, 0x80, 0x61, 0x6c, 0x1c, 0x60, 0x9d, 0x65, 0xbd, 0x5a, 0x4e, 0xeb, 0xa2, 0x06, 0xd6, 0xbe, 0xf5, 0x49, 0xc1, 0x7d, 0xd9, 0x46, 0x3e, 0x9f, 0x2f, 0x92, 0xa4, 0x1a, 0x14, 0x2c, 0x1e, 0xb7, 0x6d, 0x71, 0x29, 0x92, 0x43, 0x7b, 0x76, 0xa4, 0x8b, 0x33, 0xf3, 0xd0, 0xda, 0x7c, 0x7f, 0x73, 0x50, 0xe2, 0xc5, 0x30, 0xad, 0x9e, 0x0f, 0x61, 0x73, 0xa0, 0xbb, 0x87, 0x1f, 0x0b, 0x70, 0xa9, 0xa6, 0xaa, 0x31, 0x2d, 0x62, 0x2c, 0xaf, 0xea, 0x49, 0xb2, 0xce, 0x6c, 0x23, 0x90, 0xdd, 0x29, 0x37, 0x67, 0xb1, 0xc9, 0x99, 0x3a, 0x3f, 0xa6, 0x69, 0xc9, 0x0d, 0x24, 0x3f, ]; pub fn get_ext_rsa_pub() -> Public { let object_attributes = ObjectAttributesBuilder::new() .with_user_with_auth(true) .with_decrypt(false) .with_sign_encrypt(true) .with_restricted(false) .build() .expect("Failed to build object attributes"); PublicBuilder::new() .with_public_algorithm(PublicAlgorithm::Rsa) .with_name_hashing_algorithm(HashingAlgorithm::Sha256) .with_object_attributes(object_attributes) .with_rsa_parameters( PublicRsaParametersBuilder::new_unrestricted_signing_key( RsaScheme::create(RsaSchemeAlgorithm::RsaSsa, Some(HashingAlgorithm::Sha256)) .expect("Failed to create rsa scheme"), RsaKeyBits::Rsa2048, Default::default(), // Default exponent is 0 but TPM internally this is mapped to 65537 ) .build() .expect("Failed to create rsa parameters for public structure"), ) .with_rsa_unique_identifier( PublicKeyRsa::try_from(&RSA_KEY[..]) .expect("Failed to create Public RSA key from buffer"), ) .build() .expect("Failed to build Public structure") } #[test] fn test_public_to_decoded_key_rsa() { let public_rsa = get_ext_rsa_pub(); let default_exponent = IntegerAsn1::from_bytes_be_signed(65537_u32.to_be_bytes().to_vec()); let decoded_key = DecodedKey::try_from(public_rsa) .expect("Failed to convert Public structure to DecodedKey (RSA)."); match decoded_key { DecodedKey::RsaPublicKey(key) => { assert_eq!( key.public_exponent, default_exponent, "RSA exponents are not equal." ); assert_eq!(key.modulus.as_unsigned_bytes_be(), RSA_KEY); } DecodedKey::EcPoint(..) => panic!("RSA key was decoded to EcPoint!"), } } #[test] fn test_public_to_subject_public_key_info_rsa() { let public_rsa = get_ext_rsa_pub(); let default_exponent = IntegerAsn1::from_bytes_be_signed(65537_u32.to_be_bytes().to_vec()); let key = SubjectPublicKeyInfo::try_from(public_rsa) .expect("Failed to convert Public structure to SubjectPublicKeyInfo (RSA)."); assert_eq!(key.algorithm, AlgorithmIdentifier::new_rsa_encryption()); match key.subject_public_key { PublicKey::Rsa(key) => { assert_eq!(key.public_exponent, default_exponent); assert_eq!(key.modulus.as_unsigned_bytes_be(), RSA_KEY) } _ => panic!("PublicKey of SubjectPublicKeyInfo is not an instance for RSA"), } } } mod public_ecc_test { use picky_asn1::bit_string::BitString; use picky_asn1_x509::{AlgorithmIdentifier, EcParameters, PublicKey, SubjectPublicKeyInfo}; use std::convert::TryFrom; use tss_esapi::{ abstraction::public::DecodedKey, attributes::ObjectAttributesBuilder, interface_types::{ algorithm::{HashingAlgorithm, PublicAlgorithm}, ecc::EccCurve, }, structures::{ EccParameter, EccPoint, EccScheme, KeyDerivationFunctionScheme, Public, PublicBuilder, PublicEccParametersBuilder, }, }; const EC_POINT: [u8; 65] = [ 0x04, 0x14, 0xd8, 0x59, 0xec, 0x31, 0xe5, 0x94, 0x0f, 0x2b, 0x3a, 0x08, 0x97, 0x64, 0xc4, 0xfb, 0xa6, 0xcd, 0xaf, 0x0e, 0xa2, 0x44, 0x7f, 0x30, 0xcf, 0xe8, 0x2e, 0xe5, 0x1b, 0x47, 0x70, 0x01, 0xc3, 0xd6, 0xb4, 0x69, 0x7e, 0xa1, 0xcf, 0x03, 0xdb, 0x05, 0x9c, 0x62, 0x3e, 0xc6, 0x15, 0x4f, 0xed, 0xab, 0xa0, 0xa0, 0xab, 0x84, 0x2e, 0x67, 0x0c, 0x98, 0xc7, 0x1e, 0xef, 0xd2, 0x51, 0x91, 0xce, ]; pub fn get_ecc_point() -> EccPoint { let x = EccParameter::try_from(&EC_POINT[1..33]).expect("Failed to construct x EccParameter"); let y: EccParameter = EccParameter::try_from(&EC_POINT[33..]).expect("Failed to construct y EccParameter"); EccPoint::new(x, y) } pub fn get_ext_ecc_pub() -> Public { let object_attributes = ObjectAttributesBuilder::new() .with_user_with_auth(true) .with_decrypt(false) .with_sign_encrypt(true) .with_restricted(false) .build() .expect("Failed to build object attributes"); let ecc_parameters = PublicEccParametersBuilder::new() .with_ecc_scheme(EccScheme::Null) .with_curve(EccCurve::NistP256) .with_is_signing_key(false) .with_is_decryption_key(true) .with_restricted(false) .with_key_derivation_function_scheme(KeyDerivationFunctionScheme::Null) .build() .expect("Failed to build PublicEccParameters"); PublicBuilder::new() .with_public_algorithm(PublicAlgorithm::Ecc) .with_name_hashing_algorithm(HashingAlgorithm::Sha256) .with_object_attributes(object_attributes) .with_ecc_parameters(ecc_parameters) .with_ecc_unique_identifier(get_ecc_point()) .build() .expect("Failed to build Public structure") } #[test] fn test_public_to_decoded_key_ecc() { let public_ecc = get_ext_ecc_pub(); let decoded_key = DecodedKey::try_from(public_ecc) .expect("Failed to convert Public structure to DecodedKey (ECC)."); match decoded_key { DecodedKey::RsaPublicKey(..) => panic!("ECC key was decoded to RsaPublicKey!"), DecodedKey::EcPoint(ec_point) => { assert_eq!(ec_point.to_vec(), EC_POINT.to_vec()); } } } #[test] fn test_public_to_subject_public_key_info_ecc() { let public_ecc = get_ext_ecc_pub(); let key = SubjectPublicKeyInfo::try_from(public_ecc) .expect("Failed to convert Public structure to SubjectPublicKeyInfo (ECC)."); assert_eq!( key.algorithm, AlgorithmIdentifier::new_elliptic_curve(EcParameters::NamedCurve( picky_asn1_x509::oids::secp256r1().into() )) ); match key.subject_public_key { PublicKey::Ec(ec_point) => { let ec_point_bitstring: BitString = ec_point.into(); let ec_point_vec: Vec = ec_point_bitstring.into(); assert_eq!(ec_point_vec, EC_POINT.to_vec()); } _ => panic!("PublicKey of SubjectPublicKeyInfo is not an instance for ECC"), } } } tss-esapi-7.4.0/tests/integration_tests/abstraction_tests/transient_key_context_tests.rs000064400000000000000000000667351046102023000304420ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::{TryFrom, TryInto}; use tss_esapi::{ abstraction::ek, abstraction::transient::{KeyParams, ObjectWrapper, TransientKeyContextBuilder}, constants::response_code::Tss2ResponseCodeKind, interface_types::{ algorithm::{ AsymmetricAlgorithm, EccSchemeAlgorithm, HashingAlgorithm, RsaSchemeAlgorithm, }, ecc::EccCurve, key_bits::RsaKeyBits, resource_handles::Hierarchy, }, structures::{ Auth, CreateKeyResult, Digest, EccScheme, Public, PublicKeyRsa, RsaExponent, RsaScheme, RsaSignature, Signature, SymmetricDefinitionObject, }, utils::{create_restricted_decryption_rsa_public, PublicKey}, Error, TransientKeyContext, WrapperErrorKind as ErrorKind, }; use crate::common::create_tcti; const HASH: [u8; 32] = [ 0x69, 0x3E, 0xDB, 0x1B, 0x22, 0x79, 0x03, 0xF4, 0xC0, 0xBF, 0xD6, 0x91, 0x76, 0x37, 0x84, 0xA2, 0x94, 0x8E, 0x92, 0x50, 0x35, 0xC2, 0x8C, 0x5C, 0x3C, 0xCA, 0xFE, 0x18, 0xE8, 0x81, 0x37, 0x78, ]; fn create_ctx() -> TransientKeyContext { TransientKeyContextBuilder::new() .with_tcti(create_tcti()) .build() .unwrap() } #[test] fn wrong_key_sizes() { assert_eq!( TransientKeyContextBuilder::new() .with_tcti(create_tcti()) .with_root_key_size(1023) .build() .unwrap_err(), Error::WrapperError(ErrorKind::InvalidParam) ); assert_eq!( TransientKeyContextBuilder::new() .with_tcti(create_tcti()) .with_root_key_size(1025) .build() .unwrap_err(), Error::WrapperError(ErrorKind::InvalidParam) ); assert_eq!( TransientKeyContextBuilder::new() .with_tcti(create_tcti()) .with_root_key_size(2047) .build() .unwrap_err(), Error::WrapperError(ErrorKind::InvalidParam) ); assert_eq!( TransientKeyContextBuilder::new() .with_tcti(create_tcti()) .with_root_key_size(2049) .build() .unwrap_err(), Error::WrapperError(ErrorKind::InvalidParam) ); } #[test] fn wrong_auth_size() { assert_eq!( TransientKeyContextBuilder::new() .with_tcti(create_tcti()) .with_root_key_auth_size(33) .build() .unwrap_err(), Error::WrapperError(ErrorKind::WrongParamSize) ); } #[test] fn load_bad_sized_key() { let mut ctx = create_ctx(); let key_params = KeyParams::Rsa { size: RsaKeyBits::Rsa1024, scheme: RsaScheme::create(RsaSchemeAlgorithm::RsaSsa, Some(HashingAlgorithm::Sha256)) .expect("Failed to create RSA scheme"), pub_exponent: RsaExponent::default(), }; let _ = ctx .load_external_public_key(PublicKey::Rsa(vec![0xDE, 0xAD, 0xBE, 0xEF]), key_params) .unwrap_err(); } #[test] fn load_with_invalid_params() { let pub_key = vec![ 0x96, 0xDC, 0x72, 0x77, 0x49, 0x82, 0xFD, 0x2D, 0x06, 0x65, 0x8C, 0xE5, 0x3A, 0xCD, 0xED, 0xBD, 0x50, 0xD7, 0x6F, 0x3B, 0xE5, 0x6A, 0x76, 0xED, 0x3E, 0xD8, 0xF9, 0x93, 0x40, 0x55, 0x86, 0x6F, 0xBE, 0x76, 0x60, 0xD2, 0x03, 0x23, 0x59, 0x19, 0x8D, 0xFC, 0x51, 0x6A, 0x95, 0xC8, 0x5D, 0x5A, 0x89, 0x4D, 0xE5, 0xEA, 0x44, 0x78, 0x29, 0x62, 0xDB, 0x3F, 0xF0, 0xF7, 0x49, 0x15, 0xA5, 0xAE, 0x6D, 0x81, 0x8F, 0x06, 0x7B, 0x0B, 0x50, 0x7A, 0x2F, 0xEB, 0x00, 0xB6, 0x12, 0xF3, 0x10, 0xAF, 0x4D, 0x4A, 0xA9, 0xD9, 0x81, 0xBB, 0x1E, 0x2B, 0xDF, 0xB9, 0x33, 0x3D, 0xD6, 0xB7, 0x8D, 0x23, 0x7C, 0x7F, 0xE7, 0x12, 0x48, 0x4F, 0x26, 0x73, 0xAF, 0x63, 0x51, 0xA9, 0xDB, 0xA4, 0xAB, 0xB7, 0x27, 0x00, 0xD7, 0x1C, 0xFC, 0x2F, 0x61, 0x2A, 0xB9, 0x5B, 0x66, 0xA0, 0xE0, 0xD8, 0xF3, 0xD9, ]; let key_params = KeyParams::Ecc { curve: EccCurve::NistP256, scheme: EccScheme::create( EccSchemeAlgorithm::EcDsa, Some(HashingAlgorithm::Sha256), None, ) .expect("Failed to create ecc scheme"), }; let mut ctx = create_ctx(); let _ = ctx .load_external_public_key(PublicKey::Rsa(pub_key), key_params) .unwrap_err(); } #[test] fn verify() { let pub_key = vec![ 0x96, 0xDC, 0x72, 0x77, 0x49, 0x82, 0xFD, 0x2D, 0x06, 0x65, 0x8C, 0xE5, 0x3A, 0xCD, 0xED, 0xBD, 0x50, 0xD7, 0x6F, 0x3B, 0xE5, 0x6A, 0x76, 0xED, 0x3E, 0xD8, 0xF9, 0x93, 0x40, 0x55, 0x86, 0x6F, 0xBE, 0x76, 0x60, 0xD2, 0x03, 0x23, 0x59, 0x19, 0x8D, 0xFC, 0x51, 0x6A, 0x95, 0xC8, 0x5D, 0x5A, 0x89, 0x4D, 0xE5, 0xEA, 0x44, 0x78, 0x29, 0x62, 0xDB, 0x3F, 0xF0, 0xF7, 0x49, 0x15, 0xA5, 0xAE, 0x6D, 0x81, 0x8F, 0x06, 0x7B, 0x0B, 0x50, 0x7A, 0x2F, 0xEB, 0x00, 0xB6, 0x12, 0xF3, 0x10, 0xAF, 0x4D, 0x4A, 0xA9, 0xD9, 0x81, 0xBB, 0x1E, 0x2B, 0xDF, 0xB9, 0x33, 0x3D, 0xD6, 0xB7, 0x8D, 0x23, 0x7C, 0x7F, 0xE7, 0x12, 0x48, 0x4F, 0x26, 0x73, 0xAF, 0x63, 0x51, 0xA9, 0xDB, 0xA4, 0xAB, 0xB7, 0x27, 0x00, 0xD7, 0x1C, 0xFC, 0x2F, 0x61, 0x2A, 0xB9, 0x5B, 0x66, 0xA0, 0xE0, 0xD8, 0xF3, 0xD9, ]; // "Les carottes sont cuites." hashed with SHA256 let digest = Digest::try_from(vec![ 0x02, 0x2b, 0x26, 0xb1, 0xc3, 0x18, 0xdb, 0x73, 0x36, 0xef, 0x6f, 0x50, 0x9c, 0x35, 0xdd, 0xaa, 0xe1, 0x3d, 0x21, 0xdf, 0x83, 0x68, 0x0f, 0x48, 0xae, 0x5d, 0x8a, 0x5d, 0x37, 0x3c, 0xc1, 0x05, ]) .unwrap(); let signature = Signature::RsaSsa( RsaSignature::create( HashingAlgorithm::Sha256, PublicKeyRsa::try_from(vec![ 0x8c, 0xf8, 0x87, 0x3a, 0xb2, 0x9a, 0x18, 0xf9, 0xe0, 0x2e, 0xb9, 0x2d, 0xe7, 0xc8, 0x32, 0x12, 0xd6, 0xd9, 0x2d, 0x98, 0xec, 0x9e, 0x47, 0xb7, 0x5b, 0x26, 0x86, 0x9d, 0xf5, 0xa2, 0x6b, 0x8b, 0x6f, 0x00, 0xd3, 0xbb, 0x68, 0x88, 0xe1, 0xad, 0xcf, 0x1c, 0x09, 0x81, 0x91, 0xbf, 0xee, 0xce, 0x4f, 0xb5, 0x83, 0x3c, 0xf5, 0xb0, 0xfa, 0x68, 0x69, 0xde, 0x7b, 0xe8, 0x49, 0x69, 0x40, 0xad, 0x90, 0xf1, 0x7f, 0x31, 0xf2, 0x75, 0x4e, 0x1c, 0x52, 0x92, 0x72, 0x2e, 0x0b, 0x06, 0xe7, 0x32, 0xb4, 0x5e, 0x82, 0x8b, 0x39, 0x72, 0x24, 0x5f, 0xee, 0x17, 0xae, 0x2d, 0x77, 0x53, 0xff, 0x1a, 0xad, 0x12, 0x83, 0x4f, 0xb5, 0x52, 0x92, 0x6e, 0xda, 0xb2, 0x55, 0x77, 0xa7, 0x58, 0xcc, 0x10, 0xa6, 0x7f, 0xc5, 0x26, 0x4e, 0x5b, 0x75, 0x9d, 0x83, 0x05, 0x9f, 0x99, 0xde, 0xc6, 0xf5, 0x12, ]) .expect("Failed to create Public RSA key structure for RSA signature"), ) .expect("Failed to create RSA signature"), ); let mut ctx = create_ctx(); let key_params = KeyParams::Rsa { size: RsaKeyBits::Rsa1024, scheme: RsaScheme::create(RsaSchemeAlgorithm::RsaSsa, Some(HashingAlgorithm::Sha256)) .expect("Failed to create RSA scheme"), pub_exponent: RsaExponent::default(), }; let pub_key = ctx .load_external_public_key(PublicKey::Rsa(pub_key), key_params) .unwrap(); let _ = ctx .verify_signature(pub_key, key_params, digest, signature) .expect("the signature should be valid"); } #[test] fn sign_with_bad_auth() { let mut ctx = create_ctx(); let key_params = KeyParams::Rsa { size: RsaKeyBits::Rsa2048, scheme: RsaScheme::create(RsaSchemeAlgorithm::RsaSsa, Some(HashingAlgorithm::Sha256)) .expect("Failed to create RSA scheme"), pub_exponent: RsaExponent::default(), }; let (key, key_auth) = ctx.create_key(key_params, 16).unwrap(); let auth_value = key_auth.unwrap(); let mut bad_auth_values = auth_value.value().to_vec(); bad_auth_values[6..10].copy_from_slice(&[0xDE, 0xAD, 0xBE, 0xEF]); ctx.sign( key, key_params, Some(Auth::try_from(bad_auth_values).unwrap()), Digest::try_from(HASH.to_vec()).unwrap(), ) .unwrap_err(); } #[test] fn sign_with_no_auth() { let mut ctx = create_ctx(); let key_params = KeyParams::Rsa { size: RsaKeyBits::Rsa2048, scheme: RsaScheme::create(RsaSchemeAlgorithm::RsaSsa, Some(HashingAlgorithm::Sha256)) .expect("Failed to create RSA scheme"), pub_exponent: RsaExponent::default(), }; let (key, _) = ctx.create_key(key_params, 16).unwrap(); ctx.sign( key, key_params, None, Digest::try_from(HASH.to_vec()).unwrap(), ) .unwrap_err(); } #[test] fn encrypt_decrypt() { let mut ctx = create_ctx(); let key_params = KeyParams::Rsa { size: RsaKeyBits::Rsa2048, scheme: RsaScheme::create(RsaSchemeAlgorithm::Oaep, Some(HashingAlgorithm::Sha256)) .expect("Failed to create RSA scheme"), pub_exponent: RsaExponent::default(), }; let (dec_key, auth) = ctx.create_key(key_params, 16).unwrap(); let enc_key = ctx .load_external_public_key(dec_key.public().clone(), key_params) .unwrap(); let message = vec![0x1, 0x2, 0x3]; let ciphertext = ctx .rsa_encrypt( enc_key, key_params, None, PublicKeyRsa::try_from(message.clone()).unwrap(), None, ) .unwrap(); assert_ne!(message, ciphertext.value()); let plaintext = ctx .rsa_decrypt(dec_key, key_params, auth, ciphertext, None) .unwrap(); assert_eq!(message, plaintext.value()); } #[test] fn two_signatures_different_digest() { let mut ctx = create_ctx(); let key_params1 = KeyParams::Rsa { size: RsaKeyBits::Rsa2048, scheme: RsaScheme::create(RsaSchemeAlgorithm::RsaSsa, Some(HashingAlgorithm::Sha256)) .expect("Failed to create RSA scheme"), pub_exponent: RsaExponent::default(), }; let (key1, auth1) = ctx.create_key(key_params1, 16).unwrap(); let key_params2 = KeyParams::Rsa { size: RsaKeyBits::Rsa2048, scheme: RsaScheme::create(RsaSchemeAlgorithm::RsaSsa, Some(HashingAlgorithm::Sha256)) .expect("Failed to create RSA scheme"), pub_exponent: RsaExponent::default(), }; let (key2, auth2) = ctx.create_key(key_params2, 16).unwrap(); let signature1 = ctx .sign( key1, key_params1, auth1, Digest::try_from(HASH.to_vec()).unwrap(), ) .unwrap(); let signature2 = ctx .sign( key2, key_params2, auth2, Digest::try_from(HASH.to_vec()).unwrap(), ) .unwrap(); if let Signature::RsaSsa(rsa_signature_1) = signature1 { if let Signature::RsaSsa(rsa_signature_2) = signature2 { assert!( rsa_signature_1.signature().value().to_vec() != rsa_signature_2.signature().value().to_vec() ); } else { panic!("Unexpected signature for signature 2"); } } else { panic!("Unexpected singature for signature 1"); } } #[test] fn verify_wrong_key() { let mut ctx = create_ctx(); let key_params1 = KeyParams::Rsa { size: RsaKeyBits::Rsa2048, scheme: RsaScheme::create(RsaSchemeAlgorithm::RsaSsa, Some(HashingAlgorithm::Sha256)) .expect("Failed to create RSA scheme"), pub_exponent: RsaExponent::default(), }; let (key1, auth1) = ctx.create_key(key_params1, 16).unwrap(); let key_params2 = KeyParams::Rsa { size: RsaKeyBits::Rsa2048, scheme: RsaScheme::create(RsaSchemeAlgorithm::RsaSsa, Some(HashingAlgorithm::Sha256)) .expect("Failed to create RSA scheme"), pub_exponent: RsaExponent::default(), }; let (key2, _) = ctx.create_key(key_params2, 16).unwrap(); // Sign with the first key let signature = ctx .sign( key1, key_params1, auth1, Digest::try_from(HASH.to_vec()).unwrap(), ) .unwrap(); // Import and verify with the second key let pub_key = ctx .load_external_public_key(key2.public().clone(), key_params2) .unwrap(); if let Error::Tss2Error(error) = ctx .verify_signature( pub_key, key_params2, Digest::try_from(HASH.to_vec()).unwrap(), signature, ) .unwrap_err() { assert_eq!(error.kind(), Some(Tss2ResponseCodeKind::Signature)); } else { panic!("The signature verification should have failed with an invalid signature error."); } } #[test] fn verify_wrong_digest() { let mut ctx = create_ctx(); let key_params = KeyParams::Rsa { size: RsaKeyBits::Rsa2048, scheme: RsaScheme::create(RsaSchemeAlgorithm::RsaSsa, Some(HashingAlgorithm::Sha256)) .expect("Failed to create RSA scheme"), pub_exponent: RsaExponent::default(), }; let (key, auth) = ctx.create_key(key_params, 16).unwrap(); let signature = ctx .sign( key.clone(), key_params, auth, Digest::try_from(HASH.to_vec()).unwrap(), ) .unwrap(); let pub_key = ctx .load_external_public_key(key.public().clone(), key_params) .unwrap(); let mut digest_values = HASH.to_vec(); digest_values[0..4].copy_from_slice(&[0xDE, 0xAD, 0xBE, 0xEF]); if let Error::Tss2Error(error) = ctx .verify_signature( pub_key, key_params, Digest::try_from(digest_values).unwrap(), signature, ) .unwrap_err() { assert_eq!(error.kind(), Some(Tss2ResponseCodeKind::Signature)); } else { panic!("The signature verification should have failed with an invalid signature error."); } } #[test] fn full_test() { let mut ctx = create_ctx(); for _ in 0..4 { let key_params = KeyParams::Rsa { size: RsaKeyBits::Rsa2048, scheme: RsaScheme::create(RsaSchemeAlgorithm::RsaSsa, Some(HashingAlgorithm::Sha256)) .expect("Failed to create RSA scheme"), pub_exponent: RsaExponent::default(), }; let (key, auth) = ctx.create_key(key_params, 16).unwrap(); let signature = ctx .sign( key.clone(), key_params, auth, Digest::try_from(HASH.to_vec()).unwrap(), ) .unwrap(); let pub_key = ctx .load_external_public_key(key.public().clone(), key_params) .unwrap(); let _ = ctx .verify_signature( pub_key, key_params, Digest::try_from(HASH.to_vec()).unwrap(), signature, ) .unwrap(); } } #[test] fn create_ecc_key() { let mut ctx = create_ctx(); let _ = ctx .create_key( KeyParams::Ecc { curve: EccCurve::NistP256, scheme: EccScheme::create( EccSchemeAlgorithm::EcDsa, Some(HashingAlgorithm::Sha256), None, ) .expect("Failed to create ecc scheme"), }, 16, ) .unwrap(); } #[test] fn create_ecc_key_decryption_scheme() { let mut ctx = create_ctx(); let _ = ctx .create_key( KeyParams::Ecc { curve: EccCurve::NistP256, scheme: EccScheme::create( EccSchemeAlgorithm::EcDh, Some(HashingAlgorithm::Sha256), None, ) .expect("Failed to create ecc scheme"), }, 16, ) .unwrap_err(); } #[test] fn full_ecc_test() { let mut ctx = create_ctx(); let key_params = KeyParams::Ecc { curve: EccCurve::NistP256, scheme: EccScheme::create( EccSchemeAlgorithm::EcDsa, Some(HashingAlgorithm::Sha256), None, ) .expect("Failed to create ecc scheme"), }; for _ in 0..4 { let (key, auth) = ctx.create_key(key_params, 16).unwrap(); let signature = ctx .sign( key.clone(), key_params, auth, Digest::try_from(HASH.to_vec()).unwrap(), ) .unwrap(); let pub_key = ctx .load_external_public_key(key.public().clone(), key_params) .unwrap(); let _ = ctx .verify_signature( pub_key, key_params, Digest::try_from(HASH.to_vec()).unwrap(), signature, ) .unwrap(); } } #[test] fn ctx_migration_test() { // Create two key contexts using `Context`, one for an RSA keypair, // one for just the public part of the key let mut basic_ctx = crate::common::create_ctx_with_session(); let random_digest = basic_ctx.get_random(16).unwrap(); let key_auth = Auth::try_from(random_digest.value().to_vec()).unwrap(); let prim_key_handle = basic_ctx .create_primary( Hierarchy::Owner, create_restricted_decryption_rsa_public( SymmetricDefinitionObject::AES_256_CFB, RsaKeyBits::Rsa2048, RsaExponent::create(0).unwrap(), ) .unwrap(), Some(key_auth.clone()), None, None, None, ) .unwrap() .key_handle; let result = basic_ctx .create( prim_key_handle, crate::common::signing_key_pub(), Some(key_auth.clone()), None, None, None, ) .unwrap(); let key_handle = basic_ctx .load( prim_key_handle, result.out_private.clone(), result.out_public.clone(), ) .unwrap(); let key_context = basic_ctx.context_save(key_handle.into()).unwrap(); let pub_key_handle = basic_ctx .load_external_public(result.out_public.clone(), Hierarchy::Owner) .unwrap(); let pub_key_context = basic_ctx.context_save(pub_key_handle.into()).unwrap(); // Drop the `Context` to free the comms channel to the TPM std::mem::drop(basic_ctx); // Migrate the keys and attempt to use them let mut ctx = create_ctx(); let key = ctx .migrate_key_from_ctx(key_context, Some(key_auth.clone())) .unwrap(); let pub_key = ctx .migrate_key_from_ctx(pub_key_context, Some(key_auth.clone())) .unwrap(); let key_params = KeyParams::Rsa { scheme: RsaScheme::create(RsaSchemeAlgorithm::RsaSsa, Some(HashingAlgorithm::Sha256)) .expect("Failed to create RSA scheme"), size: RsaKeyBits::Rsa2048, pub_exponent: RsaExponent::default(), }; let signature = ctx .sign( key.clone(), key_params, Some(key_auth), Digest::try_from(HASH.to_vec()).unwrap(), ) .unwrap(); let _ = ctx .verify_signature( pub_key.clone(), key_params, Digest::try_from(HASH.to_vec()).unwrap(), signature, ) .expect("the signature should be valid"); // Check that the public key is identical across the migration if let CreateKeyResult { out_public: Public::Rsa { unique, .. }, .. } = result { assert_eq!( PublicKey::Rsa(unique.value().to_vec()), pub_key.public().clone() ); assert_eq!( PublicKey::Rsa(unique.value().to_vec()), key.public().clone() ); } else { panic!("Got wrong type of key from TPM"); } } #[test] fn activate_credential() { // create a Transient key context, generate a key and // obtain the Make Credential parameters let mut ctx = create_ctx(); let params = KeyParams::Ecc { curve: EccCurve::NistP256, scheme: EccScheme::create( EccSchemeAlgorithm::EcDsa, Some(HashingAlgorithm::Sha256), None, ) .expect("Failed to create ecc scheme"), }; let (material, auth) = ctx.create_key(params, 16).unwrap(); let obj = ObjectWrapper { material, params, auth, }; let make_cred_params = ctx.get_make_cred_params(obj.clone(), None).unwrap(); drop(ctx); // create a normal Context and make the credential let mut basic_ctx = crate::common::create_ctx_with_session(); // the public part of the EK is used, so we retrieve the parameters let key_pub = ek::create_ek_public_from_default_template(AsymmetricAlgorithm::Rsa, None).unwrap(); let key_pub = if let Public::Rsa { object_attributes, name_hashing_algorithm, auth_policy, parameters, .. } = key_pub { Public::Rsa { object_attributes, name_hashing_algorithm, auth_policy, parameters, unique: if let PublicKey::Rsa(val) = make_cred_params.attesting_key_pub { PublicKeyRsa::try_from(val).unwrap() } else { panic!("Wrong public key type"); }, } } else { panic!("Wrong Public type"); }; let pub_handle = basic_ctx .load_external_public(key_pub, Hierarchy::Owner) .unwrap(); // Credential to expect back as proof for attestation let credential = vec![0x53; 16]; let (cred, secret) = basic_ctx .make_credential( pub_handle, credential.clone().try_into().unwrap(), make_cred_params.name.try_into().unwrap(), ) .unwrap(); drop(basic_ctx); // Create a new Transient key context and activate the credential let mut ctx = create_ctx(); let cred_back = ctx .activate_credential(obj, None, cred.value().to_vec(), secret.value().to_vec()) .unwrap(); assert_eq!(cred_back, credential); } #[test] fn make_cred_params_name() { // create a Transient key context, generate a key and // obtain the Make Credential parameters let mut ctx = create_ctx(); let params = KeyParams::Ecc { curve: EccCurve::NistP256, scheme: EccScheme::create( EccSchemeAlgorithm::EcDsa, Some(HashingAlgorithm::Sha256), None, ) .expect("Failed to create ecc scheme"), }; let (material, auth) = ctx.create_key(params, 16).unwrap(); let obj = ObjectWrapper { material, params, auth, }; let make_cred_params = ctx.get_make_cred_params(obj, None).unwrap(); // Verify that the name provided in the parameters is // consistent with the public buffer use sha2::Digest; let mut hasher = sha2::Sha256::new(); hasher.update(make_cred_params.public); let hash = hasher.finalize(); // The first 2 bytes of the name represent the hash algorithm used assert_eq!(make_cred_params.name[2..], hash[..]); } #[test] fn activate_credential_wrong_key() { // create a Transient key context, generate two keys and // obtain the Make Credential parameters for the first one let mut ctx = create_ctx(); let params = KeyParams::Ecc { curve: EccCurve::NistP256, scheme: EccScheme::create( EccSchemeAlgorithm::EcDsa, Some(HashingAlgorithm::Sha256), None, ) .expect("Failed to create ecc scheme"), }; // "Good" key (for which the credential will be generated) let (material, auth) = ctx.create_key(params, 16).unwrap(); let obj = ObjectWrapper { material, params, auth, }; let make_cred_params = ctx.get_make_cred_params(obj, None).unwrap(); // "Wrong" key (which will be used instead of the good key in attestation) let (material, auth) = ctx.create_key(params, 16).unwrap(); let wrong_obj = ObjectWrapper { material, params, auth, }; drop(ctx); // create a normal Context and make the credential let mut basic_ctx = crate::common::create_ctx_with_session(); // the public part of the EK is used, so we retrieve the parameters let key_pub = ek::create_ek_public_from_default_template(AsymmetricAlgorithm::Rsa, None).unwrap(); let key_pub = if let Public::Rsa { object_attributes, name_hashing_algorithm, auth_policy, parameters, .. } = key_pub { Public::Rsa { object_attributes, name_hashing_algorithm, auth_policy, parameters, unique: if let PublicKey::Rsa(val) = make_cred_params.attesting_key_pub { PublicKeyRsa::try_from(val).unwrap() } else { panic!("Wrong public key type"); }, } } else { panic!("Wrong Public type"); }; let pub_handle = basic_ctx .load_external_public(key_pub, Hierarchy::Owner) .unwrap(); // Credential to expect back as proof for attestation let credential = vec![0x53; 16]; let (cred, secret) = basic_ctx .make_credential( pub_handle, credential.try_into().unwrap(), make_cred_params.name.try_into().unwrap(), ) .unwrap(); drop(basic_ctx); // Create a new Transient key context and activate the credential // Validation fails within the TPM because the credential HMAC is // associated with a different object (so the integrity check fails). let mut ctx = create_ctx(); let e = ctx .activate_credential( wrong_obj, None, cred.value().to_vec(), secret.value().to_vec(), ) .unwrap_err(); if let Error::Tss2Error(e) = e { assert_eq!(e.kind(), Some(Tss2ResponseCodeKind::Integrity)); } else { panic!("Got crate error ({}) when expecting an error from TPM.", e); } } #[test] fn activate_credential_wrong_data() { let mut ctx = create_ctx(); let params = KeyParams::Ecc { curve: EccCurve::NistP256, scheme: EccScheme::create( EccSchemeAlgorithm::EcDsa, Some(HashingAlgorithm::Sha256), None, ) .expect("Failed to create ecc scheme"), }; // "Good" key (for which the credential will be generated) let (material, auth) = ctx.create_key(params, 16).unwrap(); let obj = ObjectWrapper { material, params, auth, }; // No data (essentially wrong size) let e = ctx .activate_credential(obj.clone(), None, vec![], vec![]) .unwrap_err(); if let Error::Tss2Error(e) = e { assert_eq!(e.kind(), Some(Tss2ResponseCodeKind::Size)); } else { panic!("Got crate error ({}) when expecting an error from TPM.", e); } // Correct size but gibberish let e = ctx .activate_credential(obj, None, vec![0xaa; 52], vec![0x55; 256]) .unwrap_err(); if let Error::Tss2Error(e) = e { // IBM software TPM returns Value, swtpm returns Failure... assert!(matches!( e.kind(), Some(Tss2ResponseCodeKind::Value) | Some(Tss2ResponseCodeKind::Failure) )); } else { panic!("Got crate error ({}) when expecting an error from TPM.", e); } } #[test] fn get_random_from_tkc() { // Check that we can convert a reference from TKC to Context let mut ctx = create_ctx(); let _rand_bytes = ctx .as_mut() .execute_without_session(|ctx| ctx.get_random(16)) .expect("Failed to get random bytes"); } tss-esapi-7.4.0/tests/integration_tests/attributes_tests/algorithm_attributes_tests.rs000064400000000000000000000142661046102023000301200ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::ops::Shl; use tss_esapi::{attributes::AlgorithmAttributes, tss2_esys::TPMA_ALGORITHM}; #[test] fn test_conversions() { let expected_tpma_algorithm: TPMA_ALGORITHM = 0x16; let expected_algorithm_attributes = AlgorithmAttributes(expected_tpma_algorithm); let actual_algorithm_attributes: AlgorithmAttributes = expected_tpma_algorithm.into(); let actual_tpma_algorithm: TPMA_ALGORITHM = expected_algorithm_attributes.into(); assert_eq!( expected_algorithm_attributes, actual_algorithm_attributes, "AlgorithmAttributes converted from TPMA_ALGORITHM did not contain expected value" ); assert_eq!( expected_tpma_algorithm, actual_tpma_algorithm, "TPMA_ALGORITHM converted from AlgorithmAttributes did not contain expected value" ); } #[test] fn test_all_set() { let attributes = AlgorithmAttributes::from(0xFFFFFFFF); assert!( attributes.asymmetric(), "'asymmetric' is unexpectedly not set" ); assert!( attributes.symmetric(), "'symmetric' is unexpectedly not set" ); assert!(attributes.hash(), "'hash' is unexpectedly not set"); assert!(attributes.object(), "'object' is unexpectedly not set"); assert!(attributes.signing(), "'signing' is unexpectedly not set"); assert!( attributes.encrypting(), "'encrypting' is unexpectedly not set" ); assert!(attributes.method(), "'method' is unexpectedly not set"); } #[test] fn test_none_set() { let attributes = AlgorithmAttributes::from(0x0); assert!(!attributes.asymmetric(), "'asymmetric' is unexpectedly set"); assert!(!attributes.symmetric(), "'symmetric' is unexpectedly set"); assert!(!attributes.hash(), "'hash' is unexpectedly set"); assert!(!attributes.object(), "'object' is unexpectedly set"); assert!(!attributes.signing(), "'signing' is unexpectedly set"); assert!(!attributes.encrypting(), "'encrypting' is unexpectedly set"); assert!(!attributes.method(), "'method' is unexpectedly set"); } #[test] fn test_asymmetric_set() { let attributes = AlgorithmAttributes::from(1u32.shl(0)); assert!( attributes.asymmetric(), "'asymmetric' is unexpectedly not set" ); assert!(!attributes.symmetric(), "'symmetric' is unexpectedly set"); assert!(!attributes.hash(), "'hash' is unexpectedly set"); assert!(!attributes.object(), "'object' is unexpectedly set"); assert!(!attributes.signing(), "'signing' is unexpectedly set"); assert!(!attributes.encrypting(), "'encrypting' is unexpectedly set"); assert!(!attributes.method(), "'method' is unexpectedly set"); } #[test] fn test_symmetric_set() { let attributes = AlgorithmAttributes::from(1u32.shl(1)); assert!(!attributes.asymmetric(), "'asymmetric' is unexpectedly set"); assert!( attributes.symmetric(), "'symmetric' is unexpectedly not set" ); assert!(!attributes.hash(), "'hash' is unexpectedly set"); assert!(!attributes.object(), "'object' is unexpectedly set"); assert!(!attributes.signing(), "'signing' is unexpectedly set"); assert!(!attributes.encrypting(), "'encrypting' is unexpectedly set"); assert!(!attributes.method(), "'method' is unexpectedly set"); } #[test] fn test_hash_set() { let attributes = AlgorithmAttributes::from(1u32.shl(2)); assert!(!attributes.asymmetric(), "'asymmetric' is unexpectedly set"); assert!(!attributes.symmetric(), "'symmetric' is unexpectedly set"); assert!(attributes.hash(), "'hash' is unexpectedly not set"); assert!(!attributes.object(), "'object' is unexpectedly set"); assert!(!attributes.signing(), "'signing' is unexpectedly set"); assert!(!attributes.encrypting(), "'encrypting' is unexpectedly set"); assert!(!attributes.method(), "'method' is unexpectedly set"); } #[test] fn test_object_set() { let attributes = AlgorithmAttributes::from(1u32.shl(3)); assert!(!attributes.asymmetric(), "'asymmetric' is unexpectedly set"); assert!(!attributes.symmetric(), "'symmetric' is unexpectedly set"); assert!(!attributes.hash(), "'hash' is unexpectedly set"); assert!(attributes.object(), "'object' is unexpectedly not set"); assert!(!attributes.signing(), "'signing' is unexpectedly set"); assert!(!attributes.encrypting(), "'encrypting' is unexpectedly set"); assert!(!attributes.method(), "'method' is unexpectedly set"); } #[test] fn test_signing_set() { let attributes = AlgorithmAttributes::from(1u32.shl(8)); assert!(!attributes.asymmetric(), "'asymmetric' is unexpectedly set"); assert!(!attributes.symmetric(), "'symmetric' is unexpectedly set"); assert!(!attributes.hash(), "'hash' is unexpectedly set"); assert!(!attributes.object(), "'object' is unexpectedly set"); assert!(attributes.signing(), "'signing' is unexpectedly not set"); assert!(!attributes.encrypting(), "'encrypting' is unexpectedly set"); assert!(!attributes.method(), "'method' is unexpectedly set"); } #[test] fn test_encrypting_set() { let attributes = AlgorithmAttributes::from(1u32.shl(9)); assert!(!attributes.asymmetric(), "'asymmetric' is unexpectedly set"); assert!(!attributes.symmetric(), "'symmetric' is unexpectedly set"); assert!(!attributes.hash(), "'hash' is unexpectedly set"); assert!(!attributes.object(), "'object' is unexpectedly set"); assert!(!attributes.signing(), "'signing' is unexpectedly set"); assert!( attributes.encrypting(), "'encrypting' is unexpectedly not set" ); assert!(!attributes.method(), "'method' is unexpectedly set"); } #[test] fn test_method_set() { let attributes = AlgorithmAttributes::from(1u32.shl(10)); assert!(!attributes.asymmetric(), "'asymmetric' is unexpectedly set"); assert!(!attributes.symmetric(), "'symmetric' is unexpectedly set"); assert!(!attributes.hash(), "'hash' is unexpectedly set"); assert!(!attributes.object(), "'object' is unexpectedly set"); assert!(!attributes.signing(), "'signing' is unexpectedly set"); assert!(!attributes.encrypting(), "'encrypting' is unexpectedly set"); assert!(attributes.method(), "'method' is unexpectedly not set"); } tss-esapi-7.4.0/tests/integration_tests/attributes_tests/command_code_attributes_tests.rs000064400000000000000000000252001046102023000305300ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use bitfield::bitfield; use std::convert::{TryFrom, TryInto}; use tss_esapi::{ attributes::CommandCodeAttributes, constants::CommandCode, tss2_esys::TPMA_CC, Error, WrapperErrorKind, }; bitfield! { #[derive(Copy, Clone, Eq, PartialEq)] struct ExpectedAttributes(TPMA_CC); impl Debug; u16, command_index, set_command_index: 15, 0; u8, reserved, set_reserved: 21, 16; nv, set_nv: 22; extensive, set_extensive: 23; flushed, set_flushed: 24; u8, c_handles, set_c_handles: 27, 25; r_handle, set_r_handle: 28; is_vendor_specific, set_vendor_specific: 29; u8, res, set_res: 31, 30; // shall be zero } #[test] fn test_conversions_non_vendor_specific() { let expected = { let mut ea = ExpectedAttributes(0); ea.set_vendor_specific(false); // Because it is not vendor specific it needs the // command index needs to be set to a value present // in CommandCodes. ea.set_command_index( u32::from(CommandCode::AcGetCapability) .try_into() .expect("Failed to convert CommandCode to an u16 command code index value"), ); ea.set_nv(true); ea.set_extensive(true); ea.set_flushed(true); ea.set_c_handles(6); ea.set_r_handle(true); ea }; let command_code_attributes: CommandCodeAttributes = expected .0 .try_into() .expect("Failed to convert TPMA_CC to CommandCodeAttributes"); assert_eq!( expected.command_index(), command_code_attributes.command_index(), "CommandCodeAttributes converted from TPMA_CC did not contain the expected value for command index" ); assert_eq!( expected.nv(), command_code_attributes.nv(), "CommandCodeAttributes converted from TPMA_CC did not contain the expected value for NV" ); assert_eq!( expected.extensive(), command_code_attributes.extensive(), "CommandCodeAttributes converted from TPMA_CC did not contain the expected value for Extensive" ); assert_eq!( expected.flushed(), command_code_attributes.flushed(), "CommandCodeAttributes converted from TPMA_CC did not contain the expected value for Flushed" ); assert_eq!( expected.c_handles(), command_code_attributes.c_handles(), "CommandCodeAttributes converted from TPMA_CC did not contain the expected value for CHandles" ); assert_eq!( expected.r_handle(), command_code_attributes.r_handle(), "CommandCodeAttributes converted from TPMA_CC did not contain the expected value for RHandle" ); assert_eq!( expected.is_vendor_specific(), command_code_attributes.is_vendor_specific(), "CommandCodeAttributes converted from TPMA_CC did not contain the expected value for Vendor Specific(V)" ); assert_eq!( expected.0, command_code_attributes.into(), "CommandCodeAttributes did not convert into the expected TPMA_CC value" ); } #[test] fn test_conversions_vendor_specific() { let expected = { let mut ea = ExpectedAttributes(0); ea.set_vendor_specific(true); // Vendor specific is set to true so any // u16 value is valid. ea.set_command_index(0xFFFFu16); ea.set_nv(true); ea.set_extensive(true); ea.set_flushed(true); ea.set_c_handles(6); ea.set_r_handle(true); ea }; let command_code_attributes: CommandCodeAttributes = expected .0 .try_into() .expect("Failed to convert TPMA_CC to CommandCodeAttributes"); assert_eq!( expected.command_index(), command_code_attributes.command_index(), "CommandCodeAttributes converted from TPMA_CC did not contain the expected value for command index" ); assert_eq!( expected.nv(), command_code_attributes.nv(), "CommandCodeAttributes converted from TPMA_CC did not contain the expected value for NV" ); assert_eq!( expected.extensive(), command_code_attributes.extensive(), "CommandCodeAttributes converted from TPMA_CC did not contain the expected value for Extensive" ); assert_eq!( expected.flushed(), command_code_attributes.flushed(), "CommandCodeAttributes converted from TPMA_CC did not contain the expected value for Flushed" ); assert_eq!( expected.c_handles(), command_code_attributes.c_handles(), "CommandCodeAttributes converted from TPMA_CC did not contain the expected value for CHandles" ); assert_eq!( expected.r_handle(), command_code_attributes.r_handle(), "CommandCodeAttributes converted from TPMA_CC did not contain the expected value for RHandle" ); assert_eq!( expected.is_vendor_specific(), command_code_attributes.is_vendor_specific(), "CommandCodeAttributes converted from TPMA_CC did not contain the expected value for Vendor Specific(V)" ); assert_eq!( expected.0, command_code_attributes.into(), "CommandCodeAttributes did not convert into the expected TPMA_CC value" ); } #[test] fn test_invalid_conversions_non_vendor_specific_invalid_command_index() { let invalid_tpma_cc = { let mut ea = ExpectedAttributes(0); ea.set_vendor_specific(false); // Vendor specific is set to false and // 0xFFFFu16 does not correspond to any // CommandCode so this will be invalid. ea.set_command_index(0xFFFFu16); ea.set_nv(true); ea.set_extensive(true); ea.set_flushed(true); ea.set_c_handles(6); ea.set_r_handle(true); ea.0 }; assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), CommandCodeAttributes::try_from(invalid_tpma_cc), "Converting TPMA_CC witrh invalid command code index into CommandCodeAttributes did no produce the expected error" ); } #[test] fn test_invalid_conversions_with_reserve_bits_set() { let invalid_tpma_cc_with_set_reserve_bits = { let mut ea = ExpectedAttributes(0); ea.set_reserved(2); // Specification says the reserved bits 21:16 shall be zero so this will be invalid. ea.set_vendor_specific(true); // Vendor specific is set to true so any // u16 value is valid. ea.set_command_index(0xFFFFu16); ea.set_nv(true); ea.set_extensive(true); ea.set_flushed(true); ea.set_c_handles(6); ea.set_r_handle(true); ea.0 }; assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), CommandCodeAttributes::try_from(invalid_tpma_cc_with_set_reserve_bits), "Converting TPMA_CC with reserved bits 21:16 set into CommandCodeAttributes did no produce the expected error" ); let invalid_tpma_cc_with_set_res_bits = { let mut ea = ExpectedAttributes(0); ea.set_vendor_specific(true); // Vendor specific is set to true so any // u16 value is valid. ea.set_command_index(0xFFFFu16); ea.set_nv(true); ea.set_extensive(true); ea.set_flushed(true); ea.set_c_handles(6); ea.set_r_handle(true); ea.set_res(1); // Speacification says res bits 31:30 shall be zero so this will be invalid. ea.0 }; assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), CommandCodeAttributes::try_from(invalid_tpma_cc_with_set_res_bits), "Converting TPMA_CC with reserved bits 31:30 set into CommandCodeAttributes did no produce the expected error" ); } #[test] fn test_builder() { let expected = { let mut ea = ExpectedAttributes(0); ea.set_vendor_specific(true); // Vendor specific is set to true so any // u16 value is valid. ea.set_command_index(0xFFFFu16); ea.set_nv(true); ea.set_extensive(true); ea.set_flushed(true); ea.set_c_handles(6); ea.set_r_handle(true); ea }; let actual = CommandCodeAttributes::builder() .with_vendor_specific(expected.is_vendor_specific()) .with_command_index(expected.command_index()) .with_nv(expected.nv()) .with_extensive(expected.extensive()) .with_flushed(expected.flushed()) .with_c_handles(expected.c_handles()) .with_r_handle(expected.r_handle()) .build() .expect("Failed to buiild command code attributes"); assert_eq!( expected.command_index(), actual.command_index(), "Command index value mismatch between expected and attributes built with builder" ); assert_eq!( expected.nv(), actual.nv(), "Nv value mismatch between expected and attributes built with builder" ); assert_eq!( expected.extensive(), actual.extensive(), "Extensive value mismatch between expected and attributes built with builder" ); assert_eq!( expected.flushed(), actual.flushed(), "Flushed value mismatch between expected and attributes built with builder" ); assert_eq!( expected.c_handles(), actual.c_handles(), "C Handles value mismatch between expected and attributes built with builder" ); assert_eq!( expected.r_handle(), actual.r_handle(), "R Handle value mismatch between expected and attributes built with builder" ); assert_eq!( expected.is_vendor_specific(), actual.is_vendor_specific(), "Vendor specific (V) value mismatch between expected and attributes built with builder" ); assert_eq!( expected.0, actual.into(), "CommandCodeAttributes built using the builder did not convert into the expected TPMA_CC value" ); } #[test] fn test_builder_errors() { let expected_result = Err(Error::WrapperError(WrapperErrorKind::InvalidParam)); let actual_result = CommandCodeAttributes::builder() .with_vendor_specific(false) // Vendor specific is false so the value must be a command code .with_command_index(0xFFFFu16) // This is not a command code so this should make the build fail. .with_nv(true) .with_extensive(true) .with_flushed(true) .with_c_handles(6) .with_r_handle(true) .build(); assert_eq!( expected_result, actual_result, "Building command code arguments with bad combination of vendor specific and command index did not produce the expected error", ); } tss-esapi-7.4.0/tests/integration_tests/attributes_tests/locality_attributes_tests.rs000064400000000000000000000152251046102023000277460ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use tss_esapi::{ attributes::{LocalityAttributes, LocalityAttributesBuilder}, tss2_esys::TPMA_LOCALITY, Error, WrapperErrorKind, }; #[test] fn test_conversions() { for locality in 0u8..=4u8 { let expected_locality_attributes = LocalityAttributesBuilder::new() .with_locality(locality) .build() .expect("Failed to build locality attributes"); let tpma_locality: TPMA_LOCALITY = expected_locality_attributes.into(); assert_eq!( 1u8.checked_shl(locality.into()) .expect("Unable to create locality value"), tpma_locality, "Locality did not convert into expected TPMA_LOCALITY value" ); assert_eq!( expected_locality_attributes, tpma_locality.into(), "The locality attributes converted from TPMA_LOCALITY did not match the expected value" ); } for locality in 32u8..=u8::MAX { let expected_locality_attributes = LocalityAttributesBuilder::new() .with_locality(locality) .build() .expect("Failed to build locality attributes"); let tpma_locality: TPMA_LOCALITY = expected_locality_attributes.into(); assert_eq!( locality, tpma_locality, "Locality did not convert into expected TPMA_LOCALITY value" ); assert_eq!( expected_locality_attributes, tpma_locality.into(), "The locality attributes converted from TPMA_LOCALITY did not match the expected value" ); } } #[test] fn test_constants() { assert_eq!( LocalityAttributes::LOCALITY_ZERO, LocalityAttributesBuilder::new() .with_locality(0) .build() .expect("Failed to build locality attributes"), "LOCALITY_ZERO constant does not have the correct value" ); assert_eq!( LocalityAttributes::LOCALITY_ONE, LocalityAttributesBuilder::new() .with_locality(1) .build() .expect("Failed to build locality attributes"), "LOCALITY_ONE constant does not have the correct value" ); assert_eq!( LocalityAttributes::LOCALITY_TWO, LocalityAttributesBuilder::new() .with_locality(2) .build() .expect("Failed to build locality attributes"), "LOCALITY_TWO constant does not have the correct value" ); assert_eq!( LocalityAttributes::LOCALITY_THREE, LocalityAttributesBuilder::new() .with_locality(3) .build() .expect("Failed to build locality attributes"), "LOCALITY_THREE constant does not have the correct value" ); assert_eq!( LocalityAttributes::LOCALITY_FOUR, LocalityAttributesBuilder::new() .with_locality(4) .build() .expect("Failed to build locality attributes"), "LOCALITY_FOUR constant does not have the correct value" ); } #[test] fn test_builder_valid_non_extended() { let locality_attributes = LocalityAttributesBuilder::new() .with_localities(&[0, 1, 2, 3, 4]) .build() .expect("Failed to build locality attributes"); assert!( locality_attributes.locality_zero(), "Locality ZERO was not properly set" ); assert!( locality_attributes.locality_one(), "Locality ONE was not properly set" ); assert!( locality_attributes.locality_two(), "Locality TWO was not properly set" ); assert!( locality_attributes.locality_three(), "Locality THREE was not properly set" ); assert!( locality_attributes.locality_four(), "Locality FOUR was not properly set" ); assert!( !locality_attributes.is_extended(), "Locality attributes unexpectedly indicated extended" ); } #[test] fn test_builder_valid_extended() { for expected_locality in 32u8..=u8::MAX { let locality_attributes = LocalityAttributesBuilder::new() .with_locality(expected_locality) .build() .expect("Failed to build locality attributes"); assert!( locality_attributes.is_extended(), "Locality attributes does not indicate to be 'extnded' as expected" ); assert_eq!( expected_locality, locality_attributes .as_extended() .expect("Failed to get local attributes as extended"), "The extended value does not match expected value.", ); } } #[test] fn test_invalid_locality() { for locality in 5u8..=31u8 { assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), LocalityAttributesBuilder::new() .with_locality(locality) .build(), "Locality builder did not produce expected error when using locality {}", locality ); } } #[test] fn test_invalid_extended_locality() { for locality in 0u8..=4u8 { let locality_attributes = LocalityAttributesBuilder::new() .with_locality(locality) .build() .expect("Failed to get local attributes as extended"); assert!( !locality_attributes.is_extended(), "The non extended locality {} is unexpectedly indicating that it is extended", locality ); assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), locality_attributes.as_extended(), "Calling as_extended() on locality {} that is not extended, did not result in the expected error", locality, ); } } #[test] fn test_invalid_locality_combinataions() { for locality in 0u8..=4u8 { assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), LocalityAttributesBuilder::new() .with_locality(32) .with_locality(locality) .build(), "Locality builder did not produce expected error when using locality 32 in combination with locality {}", locality, ); } for locality in 32u8..u8::MAX { assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), LocalityAttributesBuilder::new() .with_locality(1) .with_locality(locality) .build(), "Locality builder did not produce expected error when using locality 32 in combination with locality {}", locality, ); } } tss-esapi-7.4.0/tests/integration_tests/attributes_tests/mod.rs000064400000000000000000000003741046102023000232140ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod algorithm_attributes_tests; mod command_code_attributes_tests; mod locality_attributes_tests; mod nv_index_attributes_tests; mod session_attributes_tests; tss-esapi-7.4.0/tests/integration_tests/attributes_tests/nv_index_attributes_tests.rs000064400000000000000000000231131046102023000277330ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use tss_esapi::{ attributes::{NvIndexAttributes, NvIndexAttributesBuilder}, constants::NvIndexType, Error, WrapperErrorKind, }; #[test] fn test_invalid_index_type_value() { // 15(1111) - invalid let invalid_15 = NvIndexAttributes(0b0000_0000_0000_0000_0000_0000_1111_0000u32); let _ = invalid_15.index_type().unwrap_err(); // 14(1110) - invalid let invalid_14 = NvIndexAttributes(0b0000_0000_0000_0000_0000_0000_1110_0000u32); let _ = invalid_14.index_type().unwrap_err(); // 13(1101) - invalid let invalid_13 = NvIndexAttributes(0b0000_0000_0000_0000_0000_0000_1101_0000u32); let _ = invalid_13.index_type().unwrap_err(); // 12(1100) - invalid let invalid_12 = NvIndexAttributes(0b0000_0000_0000_0000_0000_0000_1100_0000u32); let _ = invalid_12.index_type().unwrap_err(); // 11(1011) - invalid let invalid_11 = NvIndexAttributes(0b0000_0000_0000_0000_0000_0000_1011_0000u32); let _ = invalid_11.index_type().unwrap_err(); // 10(1010) - invalid let invalid_10 = NvIndexAttributes(0b0000_0000_0000_0000_0000_0000_1011_0000u32); let _ = invalid_10.index_type().unwrap_err(); // 9(1001) - Valid // 8(1000) - Valid // 7(0111) - invalid let invalid_7 = NvIndexAttributes(0b0000_0000_0000_0000_0000_0000_0111_0000u32); let _ = invalid_7.index_type().unwrap_err(); // 6(0110) - invalid let invalid_6 = NvIndexAttributes(0b0000_0000_0000_0000_0000_0000_0110_0000u32); let _ = invalid_6.index_type().unwrap_err(); // 5(0101) - invalid let invalid_5 = NvIndexAttributes(0b0000_0000_0000_0000_0000_0000_0101_0000u32); let _ = invalid_5.index_type().unwrap_err(); // 4(0100) - valid // 3(0011) - invalid let invalid_3 = NvIndexAttributes(0b0000_0000_0000_0000_0000_0000_0011_0000u32); let _ = invalid_3.index_type().unwrap_err(); // 2(0010) - valid // 1(0001) - valid // 0(0000) - valid } macro_rules! single_attribute_error { ($method:ident) => { assert_eq!( Err(Error::WrapperError(WrapperErrorKind::ParamsMissing)), NvIndexAttributesBuilder::new().$method(true).build() ); }; } #[test] fn test_nv_index_attributes_builder_missing_read_attribute_failure() { // Test missing read error // Building with only PP write set this should result in an error single_attribute_error!(with_pp_write); // Building with only owner write set this should result in an error single_attribute_error!(with_owner_write); // Building with only auth write set this should result in an error single_attribute_error!(with_auth_write); // Building with only policy write set this should result in an error single_attribute_error!(with_policy_write); // Building with all of them set still results in an error assert_eq!( Err(Error::WrapperError(WrapperErrorKind::ParamsMissing)), NvIndexAttributesBuilder::new() .with_pp_write(true) .with_owner_write(true) .with_auth_write(true) .with_policy_write(true) .build() ); } #[test] fn test_nv_index_attributes_builder_missing_write_attribute_failure() { // Test missing write error // Building with only PP read set this should result in an error single_attribute_error!(with_pp_read); // Building with only owner read set this should result in an error single_attribute_error!(with_owner_read); // Building with only auth read set this should result in an error single_attribute_error!(with_auth_read); // Building with only policy read set this should result in an error single_attribute_error!(with_policy_read); // Building with all of them set still results in an error assert_eq!( Err(Error::WrapperError(WrapperErrorKind::ParamsMissing)), NvIndexAttributesBuilder::new() .with_pp_read(true) .with_owner_read(true) .with_auth_read(true) .with_policy_read(true) .build() ); } #[test] fn test_nv_index_attributes_builder_missing_no_da_attribute_with_pin_fail_index_type() { assert_eq!( Err(Error::WrapperError(WrapperErrorKind::ParamsMissing)), NvIndexAttributesBuilder::new() .with_nv_index_type(NvIndexType::PinFail) .build() ); } #[test] fn test_attributes_builder() { let mut builder = NvIndexAttributesBuilder::new(); // Need to set a read and write in order to be able to build. builder = builder.with_pp_write(true).with_pp_read(true); assert_eq!( 0b0000_0000_0000_0001_0000_0000_0000_0001u32, builder .build() .expect("Failed to build with pp_write and pp_read added") .0 ); builder = builder.with_owner_write(true); assert_eq!( 0b0000_0000_0000_0001_0000_0000_0000_0011u32, builder .build() .expect("Failed to build with owner_write added") .0 ); builder = builder.with_auth_write(true); assert_eq!( 0b0000_0000_0000_0001_0000_0000_0000_0111u32, builder .build() .expect("Failed to build with auth_write added") .0 ); builder = builder.with_policy_write(true); assert_eq!( 0b0000_0000_0000_0001_0000_0000_0000_1111u32, builder .build() .expect("Failed to build with policy_write added") .0 ); { // PinPass = 1001 (7,4) builder = builder.with_nv_index_type(NvIndexType::PinPass); let attributes = builder .build() .expect("Failed to build with nv index type PinPass added"); assert_eq!(0b0000_0000_0000_0001_0000_0000_1001_1111u32, attributes.0); assert_eq!(NvIndexType::PinPass, attributes.index_type().unwrap()); } // (8,9 Reserved) builder = builder.with_policy_delete(true); assert_eq!( 0b0000_0000_0000_0001_0000_0100_1001_1111u32, builder .build() .expect("Failed to build with policy_delete added") .0 ); builder = builder.with_write_locked(true); assert_eq!( 0b0000_0000_0000_0001_0000_1100_1001_1111u32, builder .build() .expect("Failed to build with write_locked added") .0 ); builder = builder.with_write_all(true); assert_eq!( 0b0000_0000_0000_0001_0001_1100_1001_1111u32, builder .build() .expect("Failed to build with write_all added") .0 ); builder = builder.with_write_define(true); assert_eq!( 0b0000_0000_0000_0001_0011_1100_1001_1111u32, builder .build() .expect("Failed to build with write_define added") .0 ); builder = builder.with_write_stclear(true); assert_eq!( 0b0000_0000_0000_0001_0111_1100_1001_1111u32, builder .build() .expect("Failed to build with write_stclear added") .0 ); builder = builder.with_global_lock(true); assert_eq!( 0b0000_0000_0000_0001_1111_1100_1001_1111u32, builder .build() .expect("Failed to build with global_lock added") .0 ); builder = builder.with_owner_read(true); assert_eq!( 0b0000_0000_0000_0011_1111_1100_1001_1111u32, builder .build() .expect("Failed to build with owner_read added") .0 ); builder = builder.with_auth_read(true); assert_eq!( 0b0000_0000_0000_0111_1111_1100_1001_1111u32, builder .build() .expect("Failed to build with auth_read added") .0 ); builder = builder.with_policy_read(true); assert_eq!( 0b0000_0000_0000_1111_1111_1100_1001_1111u32, builder .build() .expect("Failed to build with policy_read added") .0 ); // Reserved (24, 20) builder = builder.with_no_da(true); assert_eq!( 0b0000_0010_0000_1111_1111_1100_1001_1111u32, builder.build().expect("Failed to build with no_da added").0 ); builder = builder.with_orderly(true); assert_eq!( 0b0000_0110_0000_1111_1111_1100_1001_1111u32, builder .build() .expect("Failed to build with oderly added") .0 ); builder = builder.with_clear_stclear(true); assert_eq!( 0b0000_1110_0000_1111_1111_1100_1001_1111u32, builder .build() .expect("Failed to build with clear_stclear added") .0 ); builder = builder.with_read_locked(true); assert_eq!( 0b0001_1110_0000_1111_1111_1100_1001_1111u32, builder .build() .expect("Failed to build with read_locked added") .0 ); builder = builder.with_written(true); assert_eq!( 0b0011_1110_0000_1111_1111_1100_1001_1111u32, builder .build() .expect("Failed to build with written added") .0 ); builder = builder.with_platform_create(true); assert_eq!( 0b0111_1110_0000_1111_1111_1100_1001_1111u32, builder .build() .expect("Failed to build with platform_create added") .0 ); builder = builder.with_read_stclear(true); assert_eq!( 0b1111_1110_0000_1111_1111_1100_1001_1111u32, builder .build() .expect("Failed to build with read_stclear added") .0 ); } tss-esapi-7.4.0/tests/integration_tests/attributes_tests/session_attributes_tests.rs000064400000000000000000000155361046102023000276160ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use tss_esapi::{ attributes::{SessionAttributes, SessionAttributesBuilder, SessionAttributesMask}, tss2_esys::TPMA_SESSION, }; macro_rules! test_valid_conversion { ($tpm_value:expr, $method:ident) => { let tpma_session_attribute: TPMA_SESSION = $tpm_value; let session_attributes = SessionAttributes::from(tpma_session_attribute); assert_eq!( true, session_attributes.$method(), "SessionAttributes converted from TPMA_SESSION = {} did not produce the expected result with regard to {}.", tpma_session_attribute, stringify!($method), ); assert_eq!( tpma_session_attribute, session_attributes.into(), "Converting session attributes with {} set did not convert into the expected TPMA_SESSION value", std::stringify!($method), ); }; } macro_rules! test_valid_mask_conversion { ($tpm_value:expr, $attribute:tt) => { let tpma_session_attribute: TPMA_SESSION = $tpm_value; let session_attributes_mask = SessionAttributesMask::from(tpma_session_attribute); assert_eq!( tpma_session_attribute, session_attributes_mask.into(), "Converting session attributes mask with {} set did not convert into the expected TPMA_SESSION value", $attribute, ); }; } #[test] fn test_valid_session_attributes_conversions() { test_valid_conversion!( 1u8.checked_shl(0) .expect("Failed to create 'continue session' value"), continue_session ); test_valid_conversion!( 1u8.checked_shl(1) .expect("Failed to create 'audit exclusive' value"), audit_exclusive ); test_valid_conversion!( 1u8.checked_shl(2) .expect("Failed to create 'audit reset' value"), audit_reset ); test_valid_conversion!( 1u8.checked_shl(5) .expect("Failed to create 'decrypt' value"), decrypt ); test_valid_conversion!( 1u8.checked_shl(6) .expect("Failed to create 'encrypt' value"), encrypt ); test_valid_conversion!( 1u8.checked_shl(7).expect("Failed to create 'audit' value"), audit ); } #[ignore] #[test] fn test_invalid_session_attributes_conversions() { // bit 3 and 4 are reserved and shall be cleared. // No error for this is implemented. // See https://github.com/parallaxsecond/rust-tss-esapi/issues/330 } #[test] fn test_valid_session_attributes_mask_conversions() { test_valid_mask_conversion!( 1u8.checked_shl(0) .expect("Failed to create 'use continue session' mask value"), "use_continue_session" ); test_valid_mask_conversion!( 1u8.checked_shl(1) .expect("Failed to create 'use audit exclusive' mask value"), "use_audit_exclusive" ); test_valid_mask_conversion!( 1u8.checked_shl(2) .expect("Failed to create 'use audit reset' mask value"), "use_audit_reset" ); test_valid_mask_conversion!( 1u8.checked_shl(5) .expect("Failed to create 'use decrypt' mask value"), "use_decrypt" ); test_valid_mask_conversion!( 1u8.checked_shl(6) .expect("Failed to 'use encrypt' mask value"), "use encrypt" ); test_valid_mask_conversion!( 1u8.checked_shl(7) .expect("Failed to create 'use audit' session value"), "use audit" ); } #[ignore] #[test] fn test_invalid_session_attributes_mask_conversions() { // bit 3 and 4 are reserved and shall be cleared. // No error for this is implemented. // See https://github.com/parallaxsecond/rust-tss-esapi/issues/330 } #[test] fn test_session_attributes_builder_constructing() { let _b1 = SessionAttributes::builder(); let _b2 = SessionAttributesMask::builder(); let _b3 = SessionAttributesBuilder::default(); let _b4 = SessionAttributesBuilder::new(); } #[test] fn test_builder_from_session_attributes() { let (attributes, mask) = SessionAttributes::builder().build(); assert_eq!(SessionAttributes::from(0), attributes, "Building session attributes without anything set using SessionAttributes::builder() did not produce expected result"); assert_eq!(SessionAttributesMask::from(0), mask, "Building sesssion attributes mask without anything set using SessionAttributes::builder() did not produce expected result") } #[test] fn test_builder_from_session_attributes_mask() { let (attributes, mask) = SessionAttributesMask::builder().build(); assert_eq!(SessionAttributes::from(0), attributes, "Building session attributes without anything set using SessionAttributesMask::builder() did not produce expected result"); assert_eq!(SessionAttributesMask::from(0), mask, "Building sesssion attributes mask without anything set using SessionAttributesMask::builder() did not produce expected result") } #[test] fn test_builder_from_session_attributes_builder_default() { let (attributes, mask) = SessionAttributesBuilder::default().build(); assert_eq!(SessionAttributes::from(0), attributes, "Building session attributes without anything set using SessionAttributesBuilder::default() did not produce expected result"); assert_eq!(SessionAttributesMask::from(0), mask, "Building sesssion attributes mask without anything set using SessionAttributesBuilder::default() did not produce expected result") } #[test] fn test_builder_from_session_attributes_builder_new() { let (attributes, mask) = SessionAttributesBuilder::new().build(); assert_eq!(SessionAttributes::from(0), attributes, "Building session attributes without anything set using SessionAttributesBuilder::new() did not produce expected result"); assert_eq!(SessionAttributesMask::from(0), mask, "Building sesssion attributes mask without anything set using SessionAttributesBuilder::new() did not produce expected result") } #[test] fn test_session_attributes_builder() { let expected_session_attributes = SessionAttributes::from(0b11100111u8); let expected_session_attributes_mask = SessionAttributesMask::from(0b11100111u8); let (actual_session_attributes, actual_session_attributes_mask) = SessionAttributesBuilder::new() .with_continue_session(true) .with_audit_exclusive(true) .with_audit_reset(true) .with_decrypt(true) .with_encrypt(true) .with_audit(true) .build(); assert_eq!( expected_session_attributes, actual_session_attributes, "SessionAttributes builder did not produce the expected session attributes value" ); assert_eq!( expected_session_attributes_mask, actual_session_attributes_mask, "SessionAttributes builder did not produce the expected session attributes mask value" ) } tss-esapi-7.4.0/tests/integration_tests/common/marshall.rs000064400000000000000000000006361046102023000221210ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use tss_esapi::traits::{Marshall, UnMarshall}; pub fn check_marshall_unmarshall(val: &T) { let buf = val.marshall().expect("Failed to marshall value"); let unmarshalled = T::unmarshall(&buf).expect("Failed to unmarshall"); assert_eq!(val, &unmarshalled); } tss-esapi-7.4.0/tests/integration_tests/common/mod.rs000064400000000000000000000373651046102023000211060ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::{ convert::{TryFrom, TryInto}, env, str::FromStr, sync::Once, }; use tss_esapi::{ abstraction::{cipher::Cipher, pcr::PcrData}, attributes::ObjectAttributes, attributes::{ObjectAttributesBuilder, SessionAttributesBuilder}, constants::SessionType, interface_types::{ algorithm::SymmetricMode, algorithm::{HashingAlgorithm, PublicAlgorithm, RsaSchemeAlgorithm}, key_bits::RsaKeyBits, key_bits::{AesKeyBits, Sm4KeyBits}, resource_handles::Hierarchy, session_handles::PolicySession, }, structures::{ Digest, EccParameter, EccPoint, EccScheme, EccSignature, HashAgile, HashScheme, HmacScheme, KeyDerivationFunctionScheme, KeyedHashScheme, MaxBuffer, PcrSelectionListBuilder, PcrSlot, Public, PublicBuilder, PublicEccParameters, PublicKeyRsa, PublicKeyedHashParameters, PublicRsaParameters, RsaExponent, RsaScheme, RsaSignature, Sensitive, Signature, SymmetricCipherParameters, SymmetricDefinition, SymmetricDefinitionObject, }, tcti_ldr::TctiNameConf, utils, Context, }; mod marshall; mod tpma_types_equality_checks; mod tpml_types_equality_checks; mod tpms_types_equality_checks; mod tpmt_types_equality_checks; pub use marshall::*; pub use tpma_types_equality_checks::*; pub use tpml_types_equality_checks::*; pub use tpms_types_equality_checks::*; pub use tpmt_types_equality_checks::*; #[allow(dead_code)] pub const HASH: [u8; 64] = [ 0x69, 0x3E, 0xDB, 0x1B, 0x22, 0x79, 0x03, 0xF4, 0xC0, 0xBF, 0xD6, 0x91, 0x76, 0x37, 0x84, 0x69, 0x3E, 0xDB, 0x1B, 0x22, 0x79, 0x03, 0xF4, 0xC0, 0xBF, 0xD6, 0x91, 0x76, 0x37, 0x84, 0xA2, 0x94, 0x8E, 0x92, 0x50, 0x35, 0xC2, 0x8C, 0x5C, 0x3C, 0xCA, 0xFE, 0x18, 0xE8, 0x81, 0xA2, 0x94, 0x8E, 0x92, 0x50, 0x35, 0xC2, 0x8C, 0x5C, 0x3C, 0xCA, 0xFE, 0x18, 0xE8, 0x81, 0x37, 0x78, 0x37, 0x78, ]; #[allow(dead_code)] pub const KEY: [u8; 256] = [ 231, 97, 201, 180, 0, 1, 185, 150, 85, 90, 174, 188, 105, 133, 188, 3, 206, 5, 222, 71, 185, 1, 209, 243, 36, 130, 250, 116, 17, 0, 24, 4, 25, 225, 250, 198, 245, 210, 140, 23, 139, 169, 15, 193, 4, 145, 52, 138, 149, 155, 238, 36, 74, 152, 179, 108, 200, 248, 250, 100, 115, 214, 166, 165, 1, 27, 51, 11, 11, 244, 218, 157, 3, 174, 171, 142, 45, 8, 9, 36, 202, 171, 165, 43, 208, 186, 232, 15, 241, 95, 81, 174, 189, 30, 213, 47, 86, 115, 239, 49, 214, 235, 151, 9, 189, 174, 144, 238, 200, 201, 241, 157, 43, 37, 6, 96, 94, 152, 159, 205, 54, 9, 181, 14, 35, 246, 49, 150, 163, 118, 242, 59, 54, 42, 221, 215, 248, 23, 18, 223, 179, 229, 0, 204, 65, 69, 166, 180, 11, 49, 131, 96, 163, 96, 158, 7, 109, 119, 208, 17, 237, 125, 187, 121, 94, 65, 2, 86, 105, 68, 51, 197, 73, 108, 185, 231, 126, 199, 81, 1, 251, 211, 45, 47, 15, 113, 135, 197, 152, 239, 180, 111, 18, 192, 136, 222, 11, 99, 41, 248, 205, 253, 209, 56, 214, 32, 225, 3, 49, 161, 58, 57, 190, 69, 86, 95, 185, 184, 155, 76, 8, 122, 104, 81, 222, 234, 246, 40, 98, 182, 90, 160, 111, 74, 102, 36, 148, 99, 69, 207, 214, 104, 87, 128, 238, 26, 121, 107, 166, 4, 64, 5, 210, 164, 162, 189, ]; pub fn publics() -> [Public; 4] { [ Public::Rsa { object_attributes: ObjectAttributes::new_fixed_signing_key(), name_hashing_algorithm: HashingAlgorithm::Sha256, auth_policy: Digest::try_from(vec![0x55; 16]).unwrap(), parameters: PublicRsaParameters::new( SymmetricDefinitionObject::Aes { key_bits: AesKeyBits::Aes192, mode: SymmetricMode::Cfb, }, RsaScheme::RsaSsa(HashScheme::new(HashingAlgorithm::Sha256)), RsaKeyBits::Rsa2048, RsaExponent::default(), ), unique: PublicKeyRsa::default(), }, Public::Ecc { object_attributes: ObjectAttributes::new_fixed_signing_key(), name_hashing_algorithm: HashingAlgorithm::Sha256, auth_policy: Digest::try_from(vec![0x55; 16]).unwrap(), parameters: PublicEccParameters::new( SymmetricDefinitionObject::Camellia { key_bits: tss_esapi::interface_types::key_bits::CamelliaKeyBits::Camellia128, mode: SymmetricMode::Cfb, }, EccScheme::EcDsa(HashScheme::new(HashingAlgorithm::Sha384)), tss_esapi::interface_types::ecc::EccCurve::NistP192, KeyDerivationFunctionScheme::Null, ), unique: EccPoint::new(EccParameter::default(), EccParameter::default()), }, Public::KeyedHash { object_attributes: ObjectAttributes::new_fixed_signing_key(), name_hashing_algorithm: HashingAlgorithm::Sha256, auth_policy: Digest::try_from(vec![0x55; 16]).unwrap(), parameters: PublicKeyedHashParameters::new(KeyedHashScheme::Hmac { hmac_scheme: HmacScheme::new(HashingAlgorithm::Sha256), }), unique: Digest::try_from(vec![0x01; 16]).unwrap(), }, Public::SymCipher { object_attributes: ObjectAttributes::new_fixed_signing_key(), name_hashing_algorithm: HashingAlgorithm::Sha256, auth_policy: Digest::try_from(vec![0x55; 16]).unwrap(), parameters: SymmetricCipherParameters::new(SymmetricDefinitionObject::Sm4 { key_bits: Sm4KeyBits::Sm4_128, mode: SymmetricMode::Cfb, }), unique: Digest::try_from(vec![0x44; 16]).unwrap(), }, ] } pub fn signatures() -> [Signature; 4] { [ Signature::RsaSsa( RsaSignature::create( HashingAlgorithm::Sha256, PublicKeyRsa::try_from(vec![0xaa; 256]).expect("Failed to create signature data"), ) .expect("Failed to create signature"), ), Signature::EcDsa( EccSignature::create( HashingAlgorithm::Sha3_256, EccParameter::try_from(vec![0x33; 64]).expect("Failed to create s value"), EccParameter::try_from(vec![0x00; 64]).expect("Failed to create s value"), ) .expect("Failed to create signature"), ), Signature::Hmac(HashAgile::new( HashingAlgorithm::Sha384, Digest::try_from(vec![0xde; 48]).expect("Failed to create digest"), )), Signature::Null, ] } pub fn sensitives() -> [Sensitive; 4] { [ Sensitive::Rsa { auth_value: Default::default(), seed_value: Default::default(), sensitive: KEY.to_vec().try_into().unwrap(), }, Sensitive::Ecc { auth_value: vec![0x00; 8].try_into().unwrap(), seed_value: Default::default(), sensitive: vec![0x11; 32].try_into().unwrap(), }, Sensitive::Bits { auth_value: Default::default(), seed_value: vec![0x00; 8].try_into().unwrap(), sensitive: vec![0x11; 8].try_into().unwrap(), }, Sensitive::Symmetric { auth_value: vec![0xde; 8].try_into().unwrap(), seed_value: HASH.to_vec().try_into().unwrap(), sensitive: vec![0x11; 16].try_into().unwrap(), }, ] } static LOG_INIT: Once = Once::new(); #[allow(dead_code)] pub fn setup_logging() { LOG_INIT.call_once(|| { env_logger::init(); }); } #[allow(dead_code)] pub fn create_tcti() -> TctiNameConf { setup_logging(); match env::var("TEST_TCTI") { Err(_) => TctiNameConf::Mssim(Default::default()), Ok(tctistr) => TctiNameConf::from_str(&tctistr).expect("Error parsing TEST_TCTI"), } } #[allow(dead_code)] pub fn create_ctx_without_session() -> Context { let tcti = create_tcti(); Context::new(tcti).unwrap() } #[allow(dead_code)] pub fn create_ctx_with_session() -> Context { let mut ctx = create_ctx_without_session(); let session = ctx .start_auth_session( None, None, None, SessionType::Hmac, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) .unwrap(); let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new() .with_decrypt(true) .with_encrypt(true) .build(); ctx.tr_sess_set_attributes( session.unwrap(), session_attributes, session_attributes_mask, ) .unwrap(); ctx.set_sessions((session, None, None)); ctx } #[allow(dead_code)] pub fn decryption_key_pub() -> Public { utils::create_restricted_decryption_rsa_public( Cipher::aes_256_cfb() .try_into() .expect("Failed to create symmetric object"), RsaKeyBits::Rsa2048, RsaExponent::default(), ) .expect("Failed to create a restricted decryption rsa public structure") } #[allow(dead_code)] pub fn encryption_decryption_key_pub() -> Public { utils::create_unrestricted_encryption_decryption_rsa_public( RsaKeyBits::Rsa2048, RsaExponent::default(), ) .expect("Failed to create an unrestricted encryption decryption rsa public structure") } #[allow(dead_code)] pub fn signing_key_pub() -> Public { utils::create_unrestricted_signing_rsa_public( RsaScheme::create(RsaSchemeAlgorithm::RsaSsa, Some(HashingAlgorithm::Sha256)) .expect("Failed to create RSA scheme"), RsaKeyBits::Rsa2048, RsaExponent::default(), ) .expect("Failed to create an unrestricted signing rsa public structure") } #[allow(dead_code)] pub fn get_pcr_policy_digest( context: &mut Context, mangle: bool, do_trial: bool, ) -> (Digest, PolicySession) { let old_ses = context.sessions(); context.clear_sessions(); // Read the pcr values using pcr_read let pcr_selection_list = PcrSelectionListBuilder::new() .with_selection(HashingAlgorithm::Sha256, &[PcrSlot::Slot0, PcrSlot::Slot1]) .build() .expect("Failed to create PcrSelectionList"); let (_update_counter, pcr_selection_list_out, pcr_data) = context .pcr_read(pcr_selection_list.clone()) .map(|(update_counter, read_pcr_selections, read_pcr_digests)| { ( update_counter, read_pcr_selections.clone(), PcrData::create(&read_pcr_selections, &read_pcr_digests) .expect("Failed to create PcrData"), ) }) .expect("Failed to call pcr_read"); assert_eq!(pcr_selection_list, pcr_selection_list_out); // Run pcr_policy command. // // "If this command is used for a trial policySession, // policySession→policyDigest will be updated using the // values from the command rather than the values from a digest of the TPM PCR." // // "TPM2_Quote() and TPM2_PolicyPCR() digest the concatenation of PCR." let mut concatenated_pcr_values = [ pcr_data .pcr_bank(HashingAlgorithm::Sha256) .unwrap() .get_digest(PcrSlot::Slot0) .unwrap() .value(), pcr_data .pcr_bank(HashingAlgorithm::Sha256) .unwrap() .get_digest(PcrSlot::Slot1) .unwrap() .value(), ] .concat(); if mangle { concatenated_pcr_values[0] = 0x00; } let (hashed_data, _ticket) = context .hash( MaxBuffer::try_from(concatenated_pcr_values.to_vec()).unwrap(), HashingAlgorithm::Sha256, Hierarchy::Owner, ) .unwrap(); if do_trial { // Create a trial policy session to use in calls to the policy // context methods. let trial_policy_auth_session = context .start_auth_session( None, None, None, SessionType::Trial, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) .expect("Start auth session failed") .expect("Start auth session returned a NONE handle"); let (trial_policy_auth_session_attributes, trial_policy_auth_session_attributes_mask) = SessionAttributesBuilder::new() .with_decrypt(true) .with_encrypt(true) .build(); context .tr_sess_set_attributes( trial_policy_auth_session, trial_policy_auth_session_attributes, trial_policy_auth_session_attributes_mask, ) .expect("tr_sess_set_attributes call failed"); let trial_policy_session = PolicySession::try_from(trial_policy_auth_session) .expect("Failed to convert auth session into policy session"); // There should be no errors setting pcr policy for trial session. context .policy_pcr(trial_policy_session, hashed_data, pcr_selection_list) .expect("Failed to call policy pcr"); // There is now a policy digest that can be retrieved and used. let digest = context .policy_get_digest(trial_policy_session) .expect("Failed to call policy_get_digest"); // Restore old sessions context.set_sessions(old_ses); (digest, trial_policy_session) } else { // Create a policy session to use in calls to the policy // context methods. let policy_auth_session = context .start_auth_session( None, None, None, SessionType::Policy, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) .expect("Start auth session failed") .expect("Start auth session returned a NONE handle"); let (policy_auth_session_attributes, policy_auth_session_attributes_mask) = SessionAttributesBuilder::new() .with_decrypt(true) .with_encrypt(true) .build(); context .tr_sess_set_attributes( policy_auth_session, policy_auth_session_attributes, policy_auth_session_attributes_mask, ) .expect("tr_sess_set_attributes call failed"); let policy_session = PolicySession::try_from(policy_auth_session) .expect("Failed to convert auth session into policy session"); // There should be no errors setting pcr policy for trial session. context .policy_pcr(policy_session, hashed_data, pcr_selection_list) .expect("Failed to call policy_pcr"); // There is now a policy digest that can be retrieved and used. let digest = context .policy_get_digest(policy_session) .expect("Failed to call policy_get_digest"); // Restore old sessions context.set_sessions(old_ses); (digest, policy_session) } } #[allow(dead_code)] pub fn create_public_sealed_object() -> Public { let object_attributes = ObjectAttributesBuilder::new() .with_fixed_tpm(true) .with_fixed_parent(true) .with_no_da(true) .with_admin_with_policy(true) .with_user_with_auth(true) .build() .expect("Failed to create object attributes"); PublicBuilder::new() .with_public_algorithm(PublicAlgorithm::KeyedHash) .with_name_hashing_algorithm(HashingAlgorithm::Sha256) .with_object_attributes(object_attributes) .with_auth_policy(Default::default()) .with_keyed_hash_parameters(PublicKeyedHashParameters::new(KeyedHashScheme::Null)) .with_keyed_hash_unique_identifier(Default::default()) .build() .expect("Failed to create public structure.") } tss-esapi-7.4.0/tests/integration_tests/common/tpma_types_equality_checks.rs000064400000000000000000000004711046102023000257350ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use tss_esapi::tss2_esys::TPMA_CC; pub fn ensure_tpma_cc_equality(expected: &TPMA_CC, actual: &TPMA_CC) { assert_eq!( expected, actual, "mismatch between actual and expected TPMA_CC value" ); } tss-esapi-7.4.0/tests/integration_tests/common/tpml_types_equality_checks.rs000064400000000000000000000032661046102023000257550ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use tss_esapi::tss2_esys::{ TPML_ALG_PROPERTY, TPML_CCA, TPML_PCR_SELECTION, TPML_TAGGED_PCR_PROPERTY, TPML_TAGGED_TPM_PROPERTY, }; macro_rules! ensure_list_equality { ($name:ident, $list_type:ident, $items_field_name:ident, $item_equality_func:ident) => { pub fn $name(expected: &$list_type, actual: &$list_type) { assert_eq!( expected.count, actual.count, "'count' value in {}, mismatch between actual and expected", stringify!($list_type) ); expected.$items_field_name[..expected.count as usize] .iter() .zip(actual.$items_field_name[..actual.count as usize].iter()) .for_each(|(expected, actual)| { crate::common::$item_equality_func(expected, actual) }); } }; } ensure_list_equality!( ensure_tpml_pcr_selection_equality, TPML_PCR_SELECTION, pcrSelections, ensure_tpms_pcr_selection_equality ); ensure_list_equality!( ensure_tpml_tagged_tpm_property_equality, TPML_TAGGED_TPM_PROPERTY, tpmProperty, ensure_tpms_tagged_property_equality ); ensure_list_equality!( ensure_tpml_alg_property_equality, TPML_ALG_PROPERTY, algProperties, ensure_tpms_alg_property_equality ); ensure_list_equality!( ensure_tpml_tagged_pcr_property_equality, TPML_TAGGED_PCR_PROPERTY, pcrProperty, ensure_tpms_tagged_pcr_select_equality ); ensure_list_equality!( ensure_tpml_cca_equality, TPML_CCA, commandAttributes, ensure_tpma_cc_equality ); tss-esapi-7.4.0/tests/integration_tests/common/tpms_types_equality_checks.rs000064400000000000000000000302361046102023000257610ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use tss_esapi::{ constants::tss::{ TPM2_ST_ATTEST_CERTIFY, TPM2_ST_ATTEST_COMMAND_AUDIT, TPM2_ST_ATTEST_CREATION, TPM2_ST_ATTEST_NV, TPM2_ST_ATTEST_QUOTE, TPM2_ST_ATTEST_SESSION_AUDIT, TPM2_ST_ATTEST_TIME, }, tss2_esys::{ TPMS_ALG_PROPERTY, TPMS_ATTEST, TPMS_CERTIFY_INFO, TPMS_CLOCK_INFO, TPMS_COMMAND_AUDIT_INFO, TPMS_CREATION_INFO, TPMS_ECC_PARMS, TPMS_KEYEDHASH_PARMS, TPMS_NV_CERTIFY_INFO, TPMS_PCR_SELECTION, TPMS_QUOTE_INFO, TPMS_RSA_PARMS, TPMS_SCHEME_ECDAA, TPMS_SCHEME_HASH, TPMS_SCHEME_HMAC, TPMS_SCHEME_XOR, TPMS_SESSION_AUDIT_INFO, TPMS_SYMCIPHER_PARMS, TPMS_TAGGED_PCR_SELECT, TPMS_TAGGED_PROPERTY, TPMS_TIME_ATTEST_INFO, TPMS_TIME_INFO, }, }; macro_rules! ensure_sized_buffer_field_equality { ($expected:ident, $actual:ident, $field_name:ident, $buffer_field_name:ident, $tss_type:ident) => { assert_eq!( $expected.$field_name.size, $actual.$field_name.size, "'size' value for {} field in {}, mismatch between actual and expected", stringify!($field_name), stringify!($tss_type), ); assert_eq!( $expected.$field_name.$buffer_field_name, $actual.$field_name.$buffer_field_name, "'{}' value for {} field in {}, mismatch between actual and expected", stringify!($buffer_field_name), stringify!($field_name), stringify!($tss_type), ); }; } pub fn ensure_tpms_certify_info_equality(expected: &TPMS_CERTIFY_INFO, actual: &TPMS_CERTIFY_INFO) { ensure_sized_buffer_field_equality!(expected, actual, name, name, TPM2B_NAME); ensure_sized_buffer_field_equality!(expected, actual, qualifiedName, name, TPM2B_NAME); } pub fn ensure_tpms_clock_info_equality(expected: &TPMS_CLOCK_INFO, actual: &TPMS_CLOCK_INFO) { assert_eq!( expected.clock, actual.clock, "'clock' value in TPMS_CLOCK_INFO, mismatch between actual and expected", ); assert_eq!( expected.resetCount, actual.resetCount, "'resetCount' value in TPMS_CLOCK_INFO, mismatch between actual and expected", ); assert_eq!( expected.restartCount, actual.restartCount, "'restartCount' value in TPMS_CLOCK_INFO, mismatch between actual and expected", ); assert_eq!( expected.safe, actual.safe, "'safe' value in TPMS_CLOCK_INFO, mismatch between actual and expected", ); } pub fn ensure_tpms_quote_info_equality(expected: &TPMS_QUOTE_INFO, actual: &TPMS_QUOTE_INFO) { ensure_sized_buffer_field_equality!(expected, actual, pcrDigest, buffer, TPM2B_DIGEST); crate::common::ensure_tpml_pcr_selection_equality(&expected.pcrSelect, &actual.pcrSelect); } pub fn ensure_tpms_pcr_selection_equality( expected: &TPMS_PCR_SELECTION, actual: &TPMS_PCR_SELECTION, ) { assert_eq!( expected.hash, actual.hash, "'hash' value in TPMS_PCR_SELECTION, mismatch between actual and expected", ); assert_eq!( expected.sizeofSelect, actual.sizeofSelect, "'sizeofSelect' value in TPMS_PCR_SELECTION, mismatch between actual and expected", ); assert_eq!( expected.pcrSelect, actual.pcrSelect, "'pcrSelect' value in TPMS_PCR_SELECTION, mismatch between actual and expected", ); } pub fn ensure_tpms_time_info_equality(expected: &TPMS_TIME_INFO, actual: &TPMS_TIME_INFO) { assert_eq!( expected.time, actual.time, "'time' value in TPMS_TIME_INFO, mismatch between actual and expected", ); ensure_tpms_clock_info_equality(&expected.clockInfo, &actual.clockInfo); } pub fn ensure_tpms_time_attest_info_equality( expected: &TPMS_TIME_ATTEST_INFO, actual: &TPMS_TIME_ATTEST_INFO, ) { ensure_tpms_time_info_equality(&expected.time, &actual.time); assert_eq!( expected.firmwareVersion, actual.firmwareVersion, "'firmwareVersion' value in TPMS_TIME_ATTEST_INFO, mismatch between actual and expected", ); } pub fn ensure_tpms_command_audit_info_equality( expected: &TPMS_COMMAND_AUDIT_INFO, actual: &TPMS_COMMAND_AUDIT_INFO, ) { assert_eq!( expected.auditCounter, actual.auditCounter, "'auditCounter' value in TPMS_COMMAND_AUDIT_INFO, mismatch between actual and expected", ); assert_eq!( expected.digestAlg, actual.digestAlg, "'digestAlg' value in TPMS_COMMAND_AUDIT_INFO, mismatch between actual and expected", ); ensure_sized_buffer_field_equality!(expected, actual, auditDigest, buffer, TPM2B_DIGEST); ensure_sized_buffer_field_equality!(expected, actual, commandDigest, buffer, TPM2B_DIGEST); } pub fn ensure_tpms_session_audit_info_equality( expected: &TPMS_SESSION_AUDIT_INFO, actual: &TPMS_SESSION_AUDIT_INFO, ) { assert_eq!( expected.exclusiveSession, actual.exclusiveSession, "'exclusiveSession' value in TPMS_SESSION_AUDIT_INFO, mismatch between actual and expected", ); ensure_sized_buffer_field_equality!(expected, actual, sessionDigest, buffer, TPM2B_DIGEST); } pub fn ensure_tpms_creation_info_equality( expected: &TPMS_CREATION_INFO, actual: &TPMS_CREATION_INFO, ) { ensure_sized_buffer_field_equality!(expected, actual, objectName, name, TPM2B_NAME); ensure_sized_buffer_field_equality!(expected, actual, creationHash, buffer, TPM2B_DIGEST); } pub fn ensure_tpms_nv_certify_info_equality( expected: &TPMS_NV_CERTIFY_INFO, actual: &TPMS_NV_CERTIFY_INFO, ) { ensure_sized_buffer_field_equality!(expected, actual, indexName, name, TPM2B_NAME); assert_eq!( expected.offset, actual.offset, "'offset' value in TPMS_NV_CERTIFY_INFO, mismatch between actual and expected", ); ensure_sized_buffer_field_equality!(expected, actual, nvContents, buffer, TPM2B_MAX_NV_BUFFER); } pub fn ensure_tpms_attest_equality(expected: &TPMS_ATTEST, actual: &TPMS_ATTEST) { assert_eq!( expected.magic, actual.magic, "'magic' value in TPMS_ATTEST, mismatch between actual and expected" ); assert_eq!( expected.type_, actual.type_, "'type_' value in TPMS_ATTEST, mismatch between actual and expected", ); ensure_sized_buffer_field_equality!(expected, actual, qualifiedSigner, name, TPM2B_NAME); ensure_sized_buffer_field_equality!(expected, actual, extraData, buffer, TPM2B_DATA); ensure_tpms_clock_info_equality(&expected.clockInfo, &actual.clockInfo); assert_eq!( expected.firmwareVersion, actual.firmwareVersion, "'firmwareVersion' value in TPMS_ATTEST, mismatch between actual and expected", ); match expected.type_ { TPM2_ST_ATTEST_CERTIFY => { ensure_tpms_certify_info_equality(unsafe { &expected.attested.certify }, unsafe { &actual.attested.certify }); } TPM2_ST_ATTEST_QUOTE => { ensure_tpms_quote_info_equality(unsafe { &expected.attested.quote }, unsafe { &actual.attested.quote }); } TPM2_ST_ATTEST_SESSION_AUDIT => ensure_tpms_session_audit_info_equality( unsafe { &expected.attested.sessionAudit }, unsafe { &actual.attested.sessionAudit }, ), TPM2_ST_ATTEST_COMMAND_AUDIT => ensure_tpms_command_audit_info_equality( unsafe { &expected.attested.commandAudit }, unsafe { &actual.attested.commandAudit }, ), TPM2_ST_ATTEST_TIME => { ensure_tpms_time_attest_info_equality(unsafe { &expected.attested.time }, unsafe { &actual.attested.time }) } TPM2_ST_ATTEST_CREATION => { ensure_tpms_creation_info_equality(unsafe { &expected.attested.creation }, unsafe { &actual.attested.creation }) } TPM2_ST_ATTEST_NV => { ensure_tpms_nv_certify_info_equality(unsafe { &expected.attested.nv }, unsafe { &actual.attested.nv }) } _ => panic!("'type_' value in TPMS_ATTEST contained invalid or unsupported value"), } } pub fn ensure_tpms_tagged_property_equality( expected: &TPMS_TAGGED_PROPERTY, actual: &TPMS_TAGGED_PROPERTY, ) { assert_eq!( expected.property, actual.property, "'property' value in TPMS_TAGGED_PROPERTY, mismatch between actual and expected", ); assert_eq!( expected.value, actual.value, "'value' value in TPMS_TAGGED_PROPERTY, mismatch between actual and expected", ); } pub fn ensure_tpms_alg_property_equality(expected: &TPMS_ALG_PROPERTY, actual: &TPMS_ALG_PROPERTY) { assert_eq!( expected.alg, actual.alg, "'alg' value in TPMS_ALG_PROPERTY, mismatch between actual and expected" ); assert_eq!( expected.algProperties, actual.algProperties, "'algProperties' value in TPMS_ALG_PROPERTY, mismatch between actual and expected" ); } pub fn ensure_tpms_tagged_pcr_select_equality( expected: &TPMS_TAGGED_PCR_SELECT, actual: &TPMS_TAGGED_PCR_SELECT, ) { assert_eq!( expected.tag, actual.tag, "'tag' value TPMS_TAGGED_PCR_SELECT, mismatch between actual and expected" ); assert_eq!( expected.sizeofSelect, actual.sizeofSelect, "'sizeofSelect' value TPMS_TAGGED_PCR_SELECT, mismatch between actual and expected" ); assert_eq!( expected.pcrSelect, actual.pcrSelect, "'pcrSelect' value TPMS_TAGGED_PCR_SELECT, mismatch between actual and expected" ); } pub fn ensure_tpms_rsa_parms_equality(expected: &TPMS_RSA_PARMS, actual: &TPMS_RSA_PARMS) { crate::common::ensure_tpmt_sym_def_object_equality(&expected.symmetric, &actual.symmetric); crate::common::ensure_tpmt_rsa_scheme_equality(&expected.scheme, &actual.scheme); assert_eq!( expected.keyBits, actual.keyBits, "'keyBits' value TPMS_RSA_PARMS, mismatch between actual and expected" ); assert_eq!( expected.exponent, actual.exponent, "'exponent' value TPMS_RSA_PARMS, mismatch between actual and expected" ); } pub fn ensure_tpms_scheme_hash_equality(expected: &TPMS_SCHEME_HASH, actual: &TPMS_SCHEME_HASH) { assert_eq!( expected.hashAlg, actual.hashAlg, "'hashAlg' value TPMS_SCHEME_HASH, mismatch between actual and expected" ); } pub fn ensure_tpms_ecc_parms_equality(expected: &TPMS_ECC_PARMS, actual: &TPMS_ECC_PARMS) { crate::common::ensure_tpmt_sym_def_object_equality(&expected.symmetric, &actual.symmetric); crate::common::ensure_tpmt_ecc_scheme_equality(&expected.scheme, &actual.scheme); assert_eq!( expected.curveID, actual.curveID, "'curveID' value TPMS_ECC_PARMS, mismatch between actual and expected" ); crate::common::ensure_tpmt_kdf_scheme_equality(&expected.kdf, &actual.kdf); } pub fn ensure_tpms_scheme_ecdaa_equality(expected: &TPMS_SCHEME_ECDAA, actual: &TPMS_SCHEME_ECDAA) { assert_eq!( expected.hashAlg, actual.hashAlg, "'hashAlg' value TPMS_SCHEME_ECDAA, mismatch between actual and expected" ); assert_eq!( expected.count, actual.count, "'count' value TPMS_SCHEME_ECDAA, mismatch between actual and expected" ); } pub fn ensure_tpms_keyedhash_parms_equality( expected: &TPMS_KEYEDHASH_PARMS, actual: &TPMS_KEYEDHASH_PARMS, ) { crate::common::ensure_tpmt_keyedhash_scheme_equality(&expected.scheme, &actual.scheme); } pub fn ensure_tpms_scheme_xor_equality(expected: &TPMS_SCHEME_XOR, actual: &TPMS_SCHEME_XOR) { assert_eq!( expected.hashAlg, actual.hashAlg, "'hashAlg' value TPMS_SCHEME_XOR, mismatch between actual and expected" ); assert_eq!( expected.kdf, actual.kdf, "'count' value TPMS_SCHEME_XOR, mismatch between actual and expected" ); } pub fn ensure_tpms_scheme_hmac_equality(expected: &TPMS_SCHEME_HMAC, actual: &TPMS_SCHEME_HMAC) { assert_eq!( expected.hashAlg, actual.hashAlg, "'hashAlg' value TPMS_SCHEME_HMAC, mismatch between actual and expected" ); } pub fn ensure_tpms_symcipher_parms_equality( expected: &TPMS_SYMCIPHER_PARMS, actual: &TPMS_SYMCIPHER_PARMS, ) { crate::common::ensure_tpmt_sym_def_object_equality(&expected.sym, &actual.sym) } tss-esapi-7.4.0/tests/integration_tests/common/tpmt_types_equality_checks.rs000064400000000000000000000330651046102023000257650ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use tss_esapi::{ constants::tss::{ TPM2_ALG_AES, TPM2_ALG_CAMELLIA, TPM2_ALG_ECC, TPM2_ALG_ECDAA, TPM2_ALG_ECDH, TPM2_ALG_ECDSA, TPM2_ALG_ECMQV, TPM2_ALG_ECSCHNORR, TPM2_ALG_HMAC, TPM2_ALG_KDF1_SP800_108, TPM2_ALG_KDF1_SP800_56A, TPM2_ALG_KDF2, TPM2_ALG_KEYEDHASH, TPM2_ALG_MGF1, TPM2_ALG_NULL, TPM2_ALG_OAEP, TPM2_ALG_RSA, TPM2_ALG_RSAES, TPM2_ALG_RSAPSS, TPM2_ALG_RSASSA, TPM2_ALG_SM2, TPM2_ALG_SM4, TPM2_ALG_SYMCIPHER, TPM2_ALG_XOR, }, tss2_esys::{ TPMT_ECC_SCHEME, TPMT_KDF_SCHEME, TPMT_KEYEDHASH_SCHEME, TPMT_PUBLIC_PARMS, TPMT_RSA_SCHEME, TPMT_SYM_DEF, TPMT_SYM_DEF_OBJECT, }, }; pub fn ensure_tpmt_sym_def_equality(expected: &TPMT_SYM_DEF, actual: &TPMT_SYM_DEF) { assert_eq!( expected.algorithm, actual.algorithm, "'algorithm' value in TPMT_SYM_DEF, mismatch between actual and expected", ); match expected.algorithm { TPM2_ALG_AES => { let expected_key_bits = unsafe { expected.keyBits.aes }; let expected_mode = unsafe { expected.mode.aes }; let actual_key_bits = unsafe { actual.keyBits.aes }; let actual_mode = unsafe { actual.mode.aes }; assert_eq!( expected_key_bits, actual_key_bits, "'keyBits' value in TPMT_SYM_DEF, mismatch between actual and expected", ); assert_eq!( expected_mode, actual_mode, "'mode' value in TPMT_SYM_DEF, mismatch between actual and expected", ); } TPM2_ALG_SM4 => { let expected_key_bits = unsafe { expected.keyBits.sm4 }; let expected_mode = unsafe { expected.mode.sm4 }; let actual_key_bits = unsafe { actual.keyBits.sm4 }; let actual_mode = unsafe { actual.mode.sm4 }; assert_eq!( expected_key_bits, actual_key_bits, "'keyBits' value in TPMT_SYM_DEF, mismatch between actual and expected", ); assert_eq!( expected_mode, actual_mode, "'mode' value in TPMT_SYM_DEF, mismatch between actual and expected", ); } TPM2_ALG_CAMELLIA => { let expected_key_bits = unsafe { expected.keyBits.camellia }; let expected_mode = unsafe { expected.mode.camellia }; let actual_key_bits = unsafe { actual.keyBits.camellia }; let actual_mode = unsafe { actual.mode.camellia }; assert_eq!( expected_key_bits, actual_key_bits, "'keyBits' value in TPMT_SYM_DEF, mismatch between actual and expected", ); assert_eq!( expected_mode, actual_mode, "'mode' value in TPMT_SYM_DEF, mismatch between actual and expected", ); } TPM2_ALG_XOR => { let expected_key_bits = unsafe { expected.keyBits.exclusiveOr }; let actual_key_bits = unsafe { actual.keyBits.exclusiveOr }; assert_eq!( expected_key_bits, actual_key_bits, "'keyBits' value in TPMT_SYM_DEF, mismatch between actual and expected", ); } TPM2_ALG_NULL => {} _ => { panic!("Invalid algorithm in TPMT_SYM_DEF"); } } } pub fn ensure_tpmt_sym_def_object_equality( expected: &TPMT_SYM_DEF_OBJECT, actual: &TPMT_SYM_DEF_OBJECT, ) { assert_eq!( expected.algorithm, actual.algorithm, "'algorithm' value in TPMT_SYM_DEF_OBJECT, mismatch between actual and expected", ); match expected.algorithm { TPM2_ALG_AES => { let expected_key_bits = unsafe { expected.keyBits.aes }; let expected_mode = unsafe { expected.mode.aes }; let actual_key_bits = unsafe { actual.keyBits.aes }; let actual_mode = unsafe { actual.mode.aes }; assert_eq!( expected_key_bits, actual_key_bits, "'keyBits' value in TPMT_SYM_DEF_OBJECT, mismatch between actual and expected", ); assert_eq!( expected_mode, actual_mode, "'mode' value in TPMT_SYM_DEF_OBJECT, mismatch between actual and expected", ); } TPM2_ALG_SM4 => { let expected_key_bits = unsafe { expected.keyBits.sm4 }; let expected_mode = unsafe { expected.mode.sm4 }; let actual_key_bits = unsafe { actual.keyBits.sm4 }; let actual_mode = unsafe { actual.mode.sm4 }; assert_eq!( expected_key_bits, actual_key_bits, "'keyBits' value in TPMT_SYM_DEF_OBJECT, mismatch between actual and expected", ); assert_eq!( expected_mode, actual_mode, "'mode' value in TPMT_SYM_DEF_OBJECT, mismatch between actual and expected", ); } TPM2_ALG_CAMELLIA => { let expected_key_bits = unsafe { expected.keyBits.camellia }; let expected_mode = unsafe { expected.mode.camellia }; let actual_key_bits = unsafe { actual.keyBits.camellia }; let actual_mode = unsafe { actual.mode.camellia }; assert_eq!( expected_key_bits, actual_key_bits, "'keyBits' value in TPMT_SYM_DEF_OBJECT, mismatch between actual and expected", ); assert_eq!( expected_mode, actual_mode, "'mode' value in TPMT_SYM_DEF_OBJECT, mismatch between actual and expected", ); } TPM2_ALG_NULL => {} _ => { panic!("Invalid algorithm in TPMT_SYM_DEF_OBJECT"); } } } pub fn ensure_tpmt_public_parms_equality(expected: &TPMT_PUBLIC_PARMS, actual: &TPMT_PUBLIC_PARMS) { assert_eq!( expected.type_, actual.type_, "'type_' value in TPMT_PUBLIC_PARMS, mismatch between actual and expected", ); match expected.type_ { TPM2_ALG_RSA => { let expected_rsa_parms = unsafe { &expected.parameters.rsaDetail }; let actual_rsa_parms = unsafe { &actual.parameters.rsaDetail }; crate::common::ensure_tpms_rsa_parms_equality(expected_rsa_parms, actual_rsa_parms); } TPM2_ALG_KEYEDHASH => { let expected_keyed_hash_parms = unsafe { &expected.parameters.keyedHashDetail }; let actual_keyed_hash_parms = unsafe { &actual.parameters.keyedHashDetail }; crate::common::ensure_tpms_keyedhash_parms_equality( expected_keyed_hash_parms, actual_keyed_hash_parms, ); } TPM2_ALG_ECC => { let expected_ecc_parms = unsafe { &expected.parameters.eccDetail }; let actual_ecc_parms = unsafe { &actual.parameters.eccDetail }; crate::common::ensure_tpms_ecc_parms_equality(expected_ecc_parms, actual_ecc_parms); } TPM2_ALG_SYMCIPHER => { let expected_symcipher_parms = unsafe { &expected.parameters.symDetail }; let actual_symcipher_parms = unsafe { &actual.parameters.symDetail }; crate::common::ensure_tpms_symcipher_parms_equality( expected_symcipher_parms, actual_symcipher_parms, ); } _ => { panic!("Invalid algorithm in TPMT_PUBLIC_PARMS"); } } } pub fn ensure_tpmt_rsa_scheme_equality(expected: &TPMT_RSA_SCHEME, actual: &TPMT_RSA_SCHEME) { assert_eq!( expected.scheme, actual.scheme, "'scheme' value in TPMT_RSA_SCHEME, mismatch between actual and expected", ); match expected.scheme { TPM2_ALG_RSASSA => { let expected_hash_scheme = unsafe { &expected.details.rsassa }; let actual_hash_scheme = unsafe { &actual.details.rsassa }; crate::common::ensure_tpms_scheme_hash_equality( expected_hash_scheme, actual_hash_scheme, ); } TPM2_ALG_RSAES => {} TPM2_ALG_RSAPSS => { let expected_hash_scheme = unsafe { &expected.details.rsapss }; let actual_hash_scheme = unsafe { &actual.details.rsapss }; crate::common::ensure_tpms_scheme_hash_equality( expected_hash_scheme, actual_hash_scheme, ); } TPM2_ALG_OAEP => { let expected_hash_scheme = unsafe { &expected.details.oaep }; let actual_hash_scheme = unsafe { &actual.details.oaep }; crate::common::ensure_tpms_scheme_hash_equality( expected_hash_scheme, actual_hash_scheme, ); } TPM2_ALG_NULL => {} _ => panic!("Invalid algorithm in TPMT_RSA_SCHEME"), } } pub fn ensure_tpmt_ecc_scheme_equality(expected: &TPMT_ECC_SCHEME, actual: &TPMT_ECC_SCHEME) { assert_eq!( expected.scheme, actual.scheme, "'scheme' value in TPMT_ECC_SCHEME, mismatch between actual and expected", ); match expected.scheme { TPM2_ALG_ECDSA => { let expected_hash_scheme = unsafe { &expected.details.ecdsa }; let actual_hash_scheme = unsafe { &actual.details.ecdsa }; crate::common::ensure_tpms_scheme_hash_equality( expected_hash_scheme, actual_hash_scheme, ); } TPM2_ALG_ECDH => { let expected_hash_scheme = unsafe { &expected.details.ecdh }; let actual_hash_scheme = unsafe { &actual.details.ecdh }; crate::common::ensure_tpms_scheme_hash_equality( expected_hash_scheme, actual_hash_scheme, ); } TPM2_ALG_ECDAA => { let expected_ecdaa_scheme = unsafe { &expected.details.ecdaa }; let actual_ecdaa_scheme = unsafe { &actual.details.ecdaa }; crate::common::ensure_tpms_scheme_ecdaa_equality( expected_ecdaa_scheme, actual_ecdaa_scheme, ); } TPM2_ALG_SM2 => { let expected_hash_scheme = unsafe { &expected.details.sm2 }; let actual_hash_scheme = unsafe { &actual.details.sm2 }; crate::common::ensure_tpms_scheme_hash_equality( expected_hash_scheme, actual_hash_scheme, ); } TPM2_ALG_ECSCHNORR => { let expected_hash_scheme = unsafe { &expected.details.ecschnorr }; let actual_hash_scheme = unsafe { &actual.details.ecschnorr }; crate::common::ensure_tpms_scheme_hash_equality( expected_hash_scheme, actual_hash_scheme, ); } TPM2_ALG_ECMQV => { let expected_hash_scheme = unsafe { &expected.details.ecmqv }; let actual_hash_scheme = unsafe { &actual.details.ecmqv }; crate::common::ensure_tpms_scheme_hash_equality( expected_hash_scheme, actual_hash_scheme, ); } TPM2_ALG_NULL => {} _ => panic!("Invalid algorithm in TPMT_ECC_SCHEME"), } } pub fn ensure_tpmt_keyedhash_scheme_equality( expected: &TPMT_KEYEDHASH_SCHEME, actual: &TPMT_KEYEDHASH_SCHEME, ) { assert_eq!( expected.scheme, actual.scheme, "'scheme' value in TPMT_KEYEDHASH_SCHEME, mismatch between actual and expected", ); match expected.scheme { TPM2_ALG_XOR => { let expected_xor_scheme = unsafe { &expected.details.exclusiveOr }; let actual_xor_scheme = unsafe { &actual.details.exclusiveOr }; crate::common::ensure_tpms_scheme_xor_equality(expected_xor_scheme, actual_xor_scheme); } TPM2_ALG_HMAC => { let expected_hmac_scheme = unsafe { &expected.details.hmac }; let actual_hmac_scheme = unsafe { &actual.details.hmac }; crate::common::ensure_tpms_scheme_hmac_equality( expected_hmac_scheme, actual_hmac_scheme, ); } TPM2_ALG_NULL => {} _ => panic!("Invalid algorithm in TPMT_KEYEDHASH_SCHEME"), } } pub fn ensure_tpmt_kdf_scheme_equality(expected: &TPMT_KDF_SCHEME, actual: &TPMT_KDF_SCHEME) { assert_eq!( expected.scheme, actual.scheme, "'scheme' value in TPMT_KDF_SCHEME, mismatch between actual and expected", ); match expected.scheme { TPM2_ALG_KDF1_SP800_56A => { let expected_scheme = unsafe { &expected.details.kdf1_sp800_56a }; let actual_scheme = unsafe { &actual.details.kdf1_sp800_56a }; crate::common::ensure_tpms_scheme_hash_equality(expected_scheme, actual_scheme); } TPM2_ALG_KDF2 => { let expected_scheme = unsafe { &expected.details.kdf2 }; let actual_scheme = unsafe { &actual.details.kdf2 }; crate::common::ensure_tpms_scheme_hash_equality(expected_scheme, actual_scheme); } TPM2_ALG_KDF1_SP800_108 => { let expected_scheme = unsafe { &expected.details.kdf1_sp800_108 }; let actual_scheme = unsafe { &actual.details.kdf1_sp800_108 }; crate::common::ensure_tpms_scheme_hash_equality(expected_scheme, actual_scheme); } TPM2_ALG_MGF1 => { let expected_scheme = unsafe { &expected.details.mgf1 }; let actual_scheme = unsafe { &actual.details.mgf1 }; crate::common::ensure_tpms_scheme_hash_equality(expected_scheme, actual_scheme); } TPM2_ALG_NULL => {} _ => panic!("Invalid algorithm in TPMT_KDF_SCHEME"), } } tss-esapi-7.4.0/tests/integration_tests/constants_tests/algorithm_tests.rs000064400000000000000000000062131046102023000254710ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; use tss_esapi::constants::{ tss::{ TPM2_ALG_AES, TPM2_ALG_CAMELLIA, TPM2_ALG_CBC, TPM2_ALG_CFB, TPM2_ALG_CMAC, TPM2_ALG_CTR, TPM2_ALG_ECB, TPM2_ALG_ECC, TPM2_ALG_ECDAA, TPM2_ALG_ECDH, TPM2_ALG_ECDSA, TPM2_ALG_ECMQV, TPM2_ALG_ECSCHNORR, TPM2_ALG_ERROR, TPM2_ALG_HMAC, TPM2_ALG_KDF1_SP800_108, TPM2_ALG_KDF1_SP800_56A, TPM2_ALG_KDF2, TPM2_ALG_KEYEDHASH, TPM2_ALG_MGF1, TPM2_ALG_NULL, TPM2_ALG_OAEP, TPM2_ALG_OFB, TPM2_ALG_RSA, TPM2_ALG_RSAES, TPM2_ALG_RSAPSS, TPM2_ALG_RSASSA, TPM2_ALG_SHA1, TPM2_ALG_SHA256, TPM2_ALG_SHA384, TPM2_ALG_SHA3_256, TPM2_ALG_SHA3_384, TPM2_ALG_SHA3_512, TPM2_ALG_SHA512, TPM2_ALG_SM2, TPM2_ALG_SM3_256, TPM2_ALG_SM4, TPM2_ALG_SYMCIPHER, TPM2_ALG_TDES, TPM2_ALG_XOR, }, AlgorithmIdentifier, }; macro_rules! test_conversion { ($tpm_alg_id:ident, $algorithm:ident) => { assert_eq!($tpm_alg_id, AlgorithmIdentifier::$algorithm.into()); assert_eq!( AlgorithmIdentifier::$algorithm, AlgorithmIdentifier::try_from($tpm_alg_id).expect(&format!( "Failed to convert tpm_alg_id for {}", stringify!($tpm_alg_id) )) ); }; } #[test] fn test_algorithm_conversion() { test_conversion!(TPM2_ALG_AES, Aes); test_conversion!(TPM2_ALG_CAMELLIA, Camellia); test_conversion!(TPM2_ALG_CBC, Cbc); test_conversion!(TPM2_ALG_CFB, Cfb); test_conversion!(TPM2_ALG_CMAC, Cmac); test_conversion!(TPM2_ALG_CTR, Ctr); test_conversion!(TPM2_ALG_ECB, Ecb); test_conversion!(TPM2_ALG_ECC, Ecc); test_conversion!(TPM2_ALG_ECDAA, EcDaa); test_conversion!(TPM2_ALG_ECDH, EcDh); test_conversion!(TPM2_ALG_ECDSA, EcDsa); test_conversion!(TPM2_ALG_ECMQV, EcMqv); test_conversion!(TPM2_ALG_ECSCHNORR, EcSchnorr); test_conversion!(TPM2_ALG_ERROR, Error); test_conversion!(TPM2_ALG_HMAC, Hmac); test_conversion!(TPM2_ALG_KDF1_SP800_108, Kdf1Sp800_108); test_conversion!(TPM2_ALG_KDF1_SP800_56A, Kdf1Sp800_56a); test_conversion!(TPM2_ALG_KDF2, Kdf2); test_conversion!(TPM2_ALG_KEYEDHASH, KeyedHash); test_conversion!(TPM2_ALG_MGF1, Mgf1); test_conversion!(TPM2_ALG_NULL, Null); test_conversion!(TPM2_ALG_OAEP, Oaep); test_conversion!(TPM2_ALG_OFB, Ofb); test_conversion!(TPM2_ALG_RSA, Rsa); test_conversion!(TPM2_ALG_RSAES, RsaEs); test_conversion!(TPM2_ALG_RSAPSS, RsaPss); test_conversion!(TPM2_ALG_RSASSA, RsaSsa); test_conversion!(TPM2_ALG_SHA1, Sha1); test_conversion!(TPM2_ALG_SHA256, Sha256); test_conversion!(TPM2_ALG_SHA384, Sha384); test_conversion!(TPM2_ALG_SHA3_256, Sha3_256); test_conversion!(TPM2_ALG_SHA3_384, Sha3_384); test_conversion!(TPM2_ALG_SHA3_512, Sha3_512); test_conversion!(TPM2_ALG_SHA512, Sha512); test_conversion!(TPM2_ALG_SM2, Sm2); test_conversion!(TPM2_ALG_SM3_256, Sm3_256); test_conversion!(TPM2_ALG_SM4, Sm4); test_conversion!(TPM2_ALG_SYMCIPHER, SymCipher); test_conversion!(TPM2_ALG_TDES, Tdes); test_conversion!(TPM2_ALG_XOR, Xor); } tss-esapi-7.4.0/tests/integration_tests/constants_tests/capabilities_tests.rs000064400000000000000000000047171046102023000261430ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; use tss_esapi::{ constants::{ tss::{ TPM2_CAP_ACT, TPM2_CAP_ALGS, TPM2_CAP_AUDIT_COMMANDS, TPM2_CAP_AUTH_POLICIES, TPM2_CAP_COMMANDS, TPM2_CAP_ECC_CURVES, TPM2_CAP_HANDLES, TPM2_CAP_PCRS, TPM2_CAP_PCR_PROPERTIES, TPM2_CAP_PP_COMMANDS, TPM2_CAP_TPM_PROPERTIES, }, CapabilityType, }, tss2_esys::TPM2_CAP, Error, WrapperErrorKind, }; #[test] fn test_invalid_conversions() { const INVALID_CAPABILTY_TYPE_VALUE: TPM2_CAP = 0xFFFFFFFF; assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), CapabilityType::try_from(INVALID_CAPABILTY_TYPE_VALUE), "Expected an error when converting 0xFFFFFFFF to a CapabilityType" ); } macro_rules! test_valid_conversion { ($tpm_capabilities:ident, CapabilityType::$capabilities:ident) => { assert_eq!( $tpm_capabilities, TPM2_CAP::from(CapabilityType::$capabilities), "Failed to convert {} to TPM2_CAP", std::stringify!(CapabilityType::$capabilities), ); assert_eq!( CapabilityType::$capabilities, CapabilityType::try_from($tpm_capabilities).expect(&format!( "Failed to convert {} to a CapabilityType", std::stringify!($tpm_capabilities) )), "{} did not convert into {}", std::stringify!($tpm_capabilities), std::stringify!(CapabilityType::$capabilities), ) }; } #[test] fn test_valid_conversions() { test_valid_conversion!(TPM2_CAP_ALGS, CapabilityType::Algorithms); test_valid_conversion!(TPM2_CAP_HANDLES, CapabilityType::Handles); test_valid_conversion!(TPM2_CAP_COMMANDS, CapabilityType::Command); test_valid_conversion!(TPM2_CAP_PP_COMMANDS, CapabilityType::PpCommands); test_valid_conversion!(TPM2_CAP_AUDIT_COMMANDS, CapabilityType::AuditCommands); test_valid_conversion!(TPM2_CAP_PCRS, CapabilityType::AssignedPcr); test_valid_conversion!(TPM2_CAP_TPM_PROPERTIES, CapabilityType::TpmProperties); test_valid_conversion!(TPM2_CAP_PCR_PROPERTIES, CapabilityType::PcrProperties); test_valid_conversion!(TPM2_CAP_ECC_CURVES, CapabilityType::EccCurves); test_valid_conversion!(TPM2_CAP_AUTH_POLICIES, CapabilityType::AuthPolicies); test_valid_conversion!(TPM2_CAP_ACT, CapabilityType::Act); } tss-esapi-7.4.0/tests/integration_tests/constants_tests/command_code_tests.rs000064400000000000000000000265211046102023000261170ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; use tss_esapi::{ constants::{tss::*, CommandCode}, tss2_esys::TPM2_CC, Error, WrapperErrorKind, }; macro_rules! test_valid_conversion { ($tpm_command_code:ident, CommandCode::$command_code:ident) => { assert_eq!( $tpm_command_code, TPM2_CC::from(CommandCode::$command_code), "Failed to convert {} to TPM2_CC", std::stringify!(CommandCode::$command_code), ); assert_eq!( CommandCode::$command_code, CommandCode::try_from($tpm_command_code).expect(&format!( "Failed to convert {} to a CommandCode", std::stringify!($tpm_command_code) )), "{} did not convert into {}", std::stringify!($tpm_command_code), std::stringify!(CommandCode::$command_code), ) }; } #[test] fn test_valid_conversions() { test_valid_conversion!( TPM2_CC_NV_UndefineSpaceSpecial, CommandCode::NvUndefineSpaceSpecial ); test_valid_conversion!(TPM2_CC_EvictControl, CommandCode::EvictControl); test_valid_conversion!(TPM2_CC_HierarchyControl, CommandCode::HierarchyControl); test_valid_conversion!(TPM2_CC_NV_UndefineSpace, CommandCode::NvUndefineSpace); test_valid_conversion!(TPM2_CC_ChangeEPS, CommandCode::ChangeEps); test_valid_conversion!(TPM2_CC_ChangePPS, CommandCode::ChangePps); test_valid_conversion!(TPM2_CC_Clear, CommandCode::Clear); test_valid_conversion!(TPM2_CC_ClearControl, CommandCode::ClearControl); test_valid_conversion!(TPM2_CC_ClockSet, CommandCode::ClockSet); test_valid_conversion!( TPM2_CC_HierarchyChangeAuth, CommandCode::HierarchyChangeAuth ); test_valid_conversion!(TPM2_CC_NV_DefineSpace, CommandCode::NvDefineSpace); test_valid_conversion!(TPM2_CC_PCR_Allocate, CommandCode::PcrAllocate); test_valid_conversion!(TPM2_CC_PCR_SetAuthPolicy, CommandCode::PcrSetAuthPolicy); test_valid_conversion!(TPM2_CC_PP_Commands, CommandCode::PpCommands); test_valid_conversion!(TPM2_CC_SetPrimaryPolicy, CommandCode::SetPrimaryPolicy); test_valid_conversion!(TPM2_CC_FieldUpgradeStart, CommandCode::FieldUpgradeStart); test_valid_conversion!(TPM2_CC_ClockRateAdjust, CommandCode::ClockRateAdjust); test_valid_conversion!(TPM2_CC_CreatePrimary, CommandCode::CreatePrimary); test_valid_conversion!(TPM2_CC_NV_GlobalWriteLock, CommandCode::NvGlobalWriteLock); test_valid_conversion!( TPM2_CC_GetCommandAuditDigest, CommandCode::GetCommandAuditDigest ); test_valid_conversion!(TPM2_CC_NV_Increment, CommandCode::NvIncrement); test_valid_conversion!(TPM2_CC_NV_SetBits, CommandCode::NvSetBits); test_valid_conversion!(TPM2_CC_NV_Extend, CommandCode::NvExtend); test_valid_conversion!(TPM2_CC_NV_Write, CommandCode::NvWrite); test_valid_conversion!(TPM2_CC_NV_WriteLock, CommandCode::NvWriteLock); test_valid_conversion!( TPM2_CC_DictionaryAttackLockReset, CommandCode::DictionaryAttackLockReset ); test_valid_conversion!( TPM2_CC_DictionaryAttackParameters, CommandCode::DictionaryAttackParameters ); test_valid_conversion!(TPM2_CC_NV_ChangeAuth, CommandCode::NvChangeAuth); test_valid_conversion!(TPM2_CC_PCR_Event, CommandCode::PcrEvent); test_valid_conversion!(TPM2_CC_PCR_Reset, CommandCode::PcrReset); test_valid_conversion!(TPM2_CC_SequenceComplete, CommandCode::SequenceComplete); test_valid_conversion!(TPM2_CC_SetAlgorithmSet, CommandCode::SetAlgorithmSet); test_valid_conversion!( TPM2_CC_SetCommandCodeAuditStatus, CommandCode::SetCommandCodeAuditStatus ); test_valid_conversion!(TPM2_CC_FieldUpgradeData, CommandCode::FieldUpgradeData); test_valid_conversion!( TPM2_CC_IncrementalSelfTest, CommandCode::IncrementalSelfTest ); test_valid_conversion!(TPM2_CC_SelfTest, CommandCode::SelfTest); test_valid_conversion!(TPM2_CC_Startup, CommandCode::Startup); test_valid_conversion!(TPM2_CC_Shutdown, CommandCode::Shutdown); test_valid_conversion!(TPM2_CC_StirRandom, CommandCode::StirRandom); test_valid_conversion!(TPM2_CC_ActivateCredential, CommandCode::ActivateCredential); test_valid_conversion!(TPM2_CC_Certify, CommandCode::Certify); test_valid_conversion!(TPM2_CC_PolicyNV, CommandCode::PolicyNv); test_valid_conversion!(TPM2_CC_CertifyCreation, CommandCode::CertifyCreation); test_valid_conversion!(TPM2_CC_Duplicate, CommandCode::Duplicate); test_valid_conversion!(TPM2_CC_GetTime, CommandCode::GetTime); test_valid_conversion!( TPM2_CC_GetSessionAuditDigest, CommandCode::GetSessionAuditDigest ); test_valid_conversion!(TPM2_CC_NV_Read, CommandCode::NvRead); test_valid_conversion!(TPM2_CC_NV_ReadLock, CommandCode::NvReadLock); test_valid_conversion!(TPM2_CC_ObjectChangeAuth, CommandCode::ObjectChangeAuth); test_valid_conversion!(TPM2_CC_PolicySecret, CommandCode::PolicySecret); test_valid_conversion!(TPM2_CC_Rewrap, CommandCode::Rewrap); test_valid_conversion!(TPM2_CC_Create, CommandCode::Create); test_valid_conversion!(TPM2_CC_ECDH_ZGen, CommandCode::EcdhZGen); test_valid_conversion!(TPM2_CC_HMAC, CommandCode::Hmac); test_valid_conversion!(TPM2_CC_Import, CommandCode::Import); test_valid_conversion!(TPM2_CC_Load, CommandCode::Load); test_valid_conversion!(TPM2_CC_Quote, CommandCode::Quote); test_valid_conversion!(TPM2_CC_RSA_Decrypt, CommandCode::RsaDecrypt); test_valid_conversion!(TPM2_CC_HMAC_Start, CommandCode::HmacStart); test_valid_conversion!(TPM2_CC_SequenceUpdate, CommandCode::SequenceUpdate); test_valid_conversion!(TPM2_CC_Sign, CommandCode::Sign); test_valid_conversion!(TPM2_CC_Unseal, CommandCode::Unseal); test_valid_conversion!(TPM2_CC_PolicySigned, CommandCode::PolicySigned); test_valid_conversion!(TPM2_CC_ContextLoad, CommandCode::ContextLoad); test_valid_conversion!(TPM2_CC_ContextSave, CommandCode::ContextSave); test_valid_conversion!(TPM2_CC_ECDH_KeyGen, CommandCode::EcdhKeyGen); test_valid_conversion!(TPM2_CC_EncryptDecrypt, CommandCode::EncryptDecrypt); test_valid_conversion!(TPM2_CC_FlushContext, CommandCode::FlushContext); test_valid_conversion!(TPM2_CC_LoadExternal, CommandCode::LoadExternal); test_valid_conversion!(TPM2_CC_MakeCredential, CommandCode::MakeCredential); test_valid_conversion!(TPM2_CC_NV_ReadPublic, CommandCode::NvReadPublic); test_valid_conversion!(TPM2_CC_PolicyAuthorize, CommandCode::PolicyAuthorize); test_valid_conversion!(TPM2_CC_PolicyAuthValue, CommandCode::PolicyAuthValue); test_valid_conversion!(TPM2_CC_PolicyCommandCode, CommandCode::PolicyCommandCode); test_valid_conversion!(TPM2_CC_PolicyCounterTimer, CommandCode::PolicyCounterTimer); test_valid_conversion!(TPM2_CC_PolicyCpHash, CommandCode::PolicyCpHash); test_valid_conversion!(TPM2_CC_PolicyLocality, CommandCode::PolicyLocality); test_valid_conversion!(TPM2_CC_PolicyNameHash, CommandCode::PolicyNameHash); test_valid_conversion!(TPM2_CC_PolicyOR, CommandCode::PolicyOr); test_valid_conversion!(TPM2_CC_PolicyTicket, CommandCode::PolicyTicket); test_valid_conversion!(TPM2_CC_ReadPublic, CommandCode::ReadPublic); test_valid_conversion!(TPM2_CC_RSA_Encrypt, CommandCode::RsaEncrypt); test_valid_conversion!(TPM2_CC_StartAuthSession, CommandCode::StartAuthSession); test_valid_conversion!(TPM2_CC_VerifySignature, CommandCode::VerifySignature); test_valid_conversion!(TPM2_CC_ECC_Parameters, CommandCode::EccParameters); test_valid_conversion!(TPM2_CC_FirmwareRead, CommandCode::FirmwareRead); test_valid_conversion!(TPM2_CC_GetCapability, CommandCode::GetCapability); test_valid_conversion!(TPM2_CC_GetRandom, CommandCode::GetRandom); test_valid_conversion!(TPM2_CC_GetTestResult, CommandCode::GetTestResult); test_valid_conversion!(TPM2_CC_Hash, CommandCode::Hash); test_valid_conversion!(TPM2_CC_PCR_Read, CommandCode::PcrRead); test_valid_conversion!(TPM2_CC_PolicyPCR, CommandCode::PolicyPcr); test_valid_conversion!(TPM2_CC_PolicyRestart, CommandCode::PolicyRestart); test_valid_conversion!(TPM2_CC_ReadClock, CommandCode::ReadClock); test_valid_conversion!(TPM2_CC_PCR_Extend, CommandCode::PcrExtend); test_valid_conversion!(TPM2_CC_PCR_SetAuthValue, CommandCode::PcrSetAuthValue); test_valid_conversion!(TPM2_CC_NV_Certify, CommandCode::NvCertify); test_valid_conversion!( TPM2_CC_EventSequenceComplete, CommandCode::EventSequenceComplete ); test_valid_conversion!(TPM2_CC_HashSequenceStart, CommandCode::HashSequenceStart); test_valid_conversion!( TPM2_CC_PolicyPhysicalPresence, CommandCode::PolicyPhysicalPresence ); test_valid_conversion!( TPM2_CC_PolicyDuplicationSelect, CommandCode::PolicyDuplicationSelect ); test_valid_conversion!(TPM2_CC_PolicyGetDigest, CommandCode::PolicyGetDigest); test_valid_conversion!(TPM2_CC_TestParms, CommandCode::TestParms); test_valid_conversion!(TPM2_CC_Commit, CommandCode::Commit); test_valid_conversion!(TPM2_CC_PolicyPassword, CommandCode::PolicyPassword); test_valid_conversion!(TPM2_CC_ZGen_2Phase, CommandCode::ZGen2Phase); test_valid_conversion!(TPM2_CC_EC_Ephemeral, CommandCode::EcEphemeral); test_valid_conversion!(TPM2_CC_PolicyNvWritten, CommandCode::PolicyNvWritten); test_valid_conversion!(TPM2_CC_PolicyTemplate, CommandCode::PolicyTemplate); test_valid_conversion!(TPM2_CC_CreateLoaded, CommandCode::CreateLoaded); test_valid_conversion!(TPM2_CC_PolicyAuthorizeNV, CommandCode::PolicyAuthorizeNv); test_valid_conversion!(TPM2_CC_EncryptDecrypt2, CommandCode::EncryptDecrypt2); test_valid_conversion!(TPM2_CC_AC_GetCapability, CommandCode::AcGetCapability); test_valid_conversion!(TPM2_CC_AC_Send, CommandCode::AcSend); test_valid_conversion!( TPM2_CC_Policy_AC_SendSelect, CommandCode::PolicyAcSendSelect ); } #[test] fn test_invalid_conversions() { // Unsupported Vendor specific const VENDOR_SPECIFIC: TPM2_CC = 0b00100000000000000000000000000001u32; assert_eq!( Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam)), CommandCode::try_from(VENDOR_SPECIFIC), "Value indicating vendor specific command code did not produce expected error" ); // Set bits in in places marked as reserved const RES: TPM2_CC = 0b10000000000000000000000000000001u32; assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), CommandCode::try_from(RES), "Value with bit set a place marked as reserved (res) did not produce expected error" ); const RESERVED: TPM2_CC = 0b00000000000000010000000000000001u32; assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), CommandCode::try_from(RESERVED), "Value with bit set a place marked as reserved (reserved) did not produce expected error" ); // Valid but non existing command code const NON_EXISTING: TPM2_CC = 0b00000000000000001111111111111111u32; assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), CommandCode::try_from(NON_EXISTING), "A value representing a non existing command code did not produce the expected error" ); } tss-esapi-7.4.0/tests/integration_tests/constants_tests/mod.rs000064400000000000000000000003271046102023000230400ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod algorithm_tests; mod capabilities_tests; mod command_code_tests; mod nv_index_type_tests; mod pcr_property_tag_tests; tss-esapi-7.4.0/tests/integration_tests/constants_tests/nv_index_type_tests.rs000064400000000000000000000031401046102023000263520ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use tss_esapi::{ constants::{ tss::{ TPM2_NT_BITS, TPM2_NT_COUNTER, TPM2_NT_EXTEND, TPM2_NT_ORDINARY, TPM2_NT_PIN_FAIL, TPM2_NT_PIN_PASS, }, NvIndexType, }, tss2_esys::TPM2_NT, }; use std::convert::{From, TryFrom}; #[test] fn test_conversion_to_tss_type() { assert_eq!(TPM2_NT_ORDINARY, TPM2_NT::from(NvIndexType::Ordinary)); assert_eq!(TPM2_NT_COUNTER, TPM2_NT::from(NvIndexType::Counter)); assert_eq!(TPM2_NT_BITS, TPM2_NT::from(NvIndexType::Bits)); assert_eq!(TPM2_NT_EXTEND, TPM2_NT::from(NvIndexType::Extend)); assert_eq!(TPM2_NT_PIN_FAIL, TPM2_NT::from(NvIndexType::PinFail)); assert_eq!(TPM2_NT_PIN_PASS, TPM2_NT::from(NvIndexType::PinPass)); } #[test] fn test_conversion_from_tss_type() { assert_eq!( NvIndexType::Ordinary, NvIndexType::try_from(TPM2_NT_ORDINARY).unwrap() ); assert_eq!( NvIndexType::Counter, NvIndexType::try_from(TPM2_NT_COUNTER).unwrap() ); assert_eq!( NvIndexType::Bits, NvIndexType::try_from(TPM2_NT_BITS).unwrap() ); assert_eq!( NvIndexType::Extend, NvIndexType::try_from(TPM2_NT_EXTEND).unwrap() ); assert_eq!( NvIndexType::PinFail, NvIndexType::try_from(TPM2_NT_PIN_FAIL).unwrap() ); assert_eq!( NvIndexType::PinPass, NvIndexType::try_from(TPM2_NT_PIN_PASS).unwrap() ); const INVALID_VALUE: TPM2_NT = 15; let _ = NvIndexType::try_from(INVALID_VALUE).unwrap_err(); } tss-esapi-7.4.0/tests/integration_tests/constants_tests/pcr_property_tag_tests.rs000064400000000000000000000054641046102023000270750ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; use tss_esapi::{ constants::{ tss::{ TPM2_PT_PCR_AUTH, TPM2_PT_PCR_DRTM_RESET, TPM2_PT_PCR_EXTEND_L0, TPM2_PT_PCR_EXTEND_L1, TPM2_PT_PCR_EXTEND_L2, TPM2_PT_PCR_EXTEND_L3, TPM2_PT_PCR_EXTEND_L4, TPM2_PT_PCR_NO_INCREMENT, TPM2_PT_PCR_POLICY, TPM2_PT_PCR_RESET_L0, TPM2_PT_PCR_RESET_L1, TPM2_PT_PCR_RESET_L2, TPM2_PT_PCR_RESET_L3, TPM2_PT_PCR_RESET_L4, TPM2_PT_PCR_SAVE, }, PcrPropertyTag, }, tss2_esys::TPM2_PT_PCR, Error, WrapperErrorKind, }; macro_rules! test_valid_conversion { ($tpm_pt_pcrs:ident, PcrPropertyTag::$item:ident) => { assert_eq!( $tpm_pt_pcrs, TPM2_PT_PCR::from(PcrPropertyTag::$item), "Failed to convert {} to TPM2_PT_PCR", std::stringify!(PcrPropertyTag::$item), ); assert_eq!( PcrPropertyTag::$item, PcrPropertyTag::try_from($tpm_pt_pcrs).expect(&format!( "Failed to convert {} to a PcrPropertyTag", std::stringify!($tpm_pt_pcrs) )), "{} did not convert into {}", std::stringify!($tpm_pt_pcrs), std::stringify!(PcrPropertyTag::$item), ) }; } #[test] fn test_invalid_conversions() { const INVALID_PT_PCR_VALUE: TPM2_PT_PCR = 0xFFFFFFFF; assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), PcrPropertyTag::try_from(INVALID_PT_PCR_VALUE), "Expected an error when converting 0xFFFFFFFF to a PcrPropertyTag" ); } #[test] fn test_valid_conversions() { test_valid_conversion!(TPM2_PT_PCR_SAVE, PcrPropertyTag::Save); test_valid_conversion!(TPM2_PT_PCR_RESET_L0, PcrPropertyTag::ResetL0); test_valid_conversion!(TPM2_PT_PCR_EXTEND_L0, PcrPropertyTag::ExtendL0); test_valid_conversion!(TPM2_PT_PCR_RESET_L1, PcrPropertyTag::ResetL1); test_valid_conversion!(TPM2_PT_PCR_EXTEND_L1, PcrPropertyTag::ExtendL1); test_valid_conversion!(TPM2_PT_PCR_RESET_L2, PcrPropertyTag::ResetL2); test_valid_conversion!(TPM2_PT_PCR_EXTEND_L2, PcrPropertyTag::ExtendL2); test_valid_conversion!(TPM2_PT_PCR_RESET_L3, PcrPropertyTag::ResetL3); test_valid_conversion!(TPM2_PT_PCR_EXTEND_L3, PcrPropertyTag::ExtendL3); test_valid_conversion!(TPM2_PT_PCR_RESET_L4, PcrPropertyTag::ResetL4); test_valid_conversion!(TPM2_PT_PCR_EXTEND_L4, PcrPropertyTag::ExtendL4); test_valid_conversion!(TPM2_PT_PCR_NO_INCREMENT, PcrPropertyTag::NoIncrement); test_valid_conversion!(TPM2_PT_PCR_DRTM_RESET, PcrPropertyTag::DrtmReset); test_valid_conversion!(TPM2_PT_PCR_POLICY, PcrPropertyTag::Policy); test_valid_conversion!(TPM2_PT_PCR_AUTH, PcrPropertyTag::Auth); } tss-esapi-7.4.0/tests/integration_tests/context_tests/general_esys_tr_tests.rs000064400000000000000000000376451046102023000263550ustar 00000000000000mod test_tr_from_tpm_public { use crate::common::create_ctx_without_session; use tss_esapi::{ attributes::NvIndexAttributesBuilder, constants::{tss::TPM2_NV_INDEX_FIRST, CapabilityType}, handles::{NvIndexHandle, NvIndexTpmHandle, ObjectHandle}, interface_types::{ algorithm::HashingAlgorithm, resource_handles::{NvAuth, Provision}, session_handles::AuthSession, }, structures::{Auth, CapabilityData, MaxNvBuffer, NvPublicBuilder}, tss2_esys::TPM2_HANDLE, Context, }; use std::convert::TryFrom; fn remove_nv_index_handle_from_tpm(nv_index_tpm_handle: NvIndexTpmHandle, nv_auth: Provision) { let mut context = create_ctx_without_session(); let mut property = TPM2_NV_INDEX_FIRST; while let Ok((capability_data, more_data_available)) = context.get_capability(CapabilityType::Handles, property, 1) { if let CapabilityData::Handles(nv_index_handles) = capability_data { if let Some(&retrieved_nv_index_tpm_handle) = nv_index_handles.first() { if retrieved_nv_index_tpm_handle == nv_index_tpm_handle.into() { let handle = context .tr_from_tpm_public(nv_index_tpm_handle.into()) .map(NvIndexHandle::from) .expect("Failed to get nv index from tpm"); context.execute_with_session(Some(AuthSession::Password), |ctx| { ctx.nv_undefine_space(nv_auth, handle) .expect("Failed to undefine space"); }); return; } if more_data_available { property = TPM2_HANDLE::from(retrieved_nv_index_tpm_handle) + 1; } } } if !more_data_available { return; } } } // Need to set the shEnable in the TPMA_STARTUP in order for this to work. #[ignore] #[test] fn test_tr_from_tpm_public_owner_auth() { let mut context = create_ctx_without_session(); let nv_index_tpm_handle = NvIndexTpmHandle::new(0x01500021).unwrap(); // closure for cleaning up if a call fails. let cleanup = |context: &mut Context, e: tss_esapi::Error, handle: NvIndexHandle, fn_name: &str| -> tss_esapi::Error { // Set password authorization context .nv_undefine_space(Provision::Owner, handle) .expect("Call to nv_undefine_space failed"); panic!("{} failed: {}", fn_name, e); }; // Create nv public. let nv_index_attributes = NvIndexAttributesBuilder::new() .with_owner_write(true) .with_owner_read(true) .build() .expect("Failed to create owner nv index attributes"); let nv_public = NvPublicBuilder::new() .with_nv_index(nv_index_tpm_handle) .with_index_name_algorithm(HashingAlgorithm::Sha256) .with_index_attributes(nv_index_attributes) .with_data_area_size(32) .build() .unwrap(); let initial_nv_index_handle = context .nv_define_space(Provision::Owner, None, nv_public) .unwrap(); /////////////////////////////////////////// // Read the name from the tpm let (_expected_nv_public, expected_name) = context .nv_read_public(initial_nv_index_handle) .map_err(|e| cleanup(&mut context, e, initial_nv_index_handle, "nv_read_public")) .unwrap(); //////////////////////////////////////////////// // Close the handle let mut handle_to_be_closed: ObjectHandle = initial_nv_index_handle.into(); context .tr_close(&mut handle_to_be_closed) .map_err(|e| cleanup(&mut context, e, initial_nv_index_handle, "tr_close")) .unwrap(); assert_eq!(handle_to_be_closed, ObjectHandle::None); //////////////////////////////////////////////// // Make Esys create a new ObjectHandle from the // data in the TPM. let new_nv_index_handle = context .tr_from_tpm_public(nv_index_tpm_handle.into()) .expect("tr_from_tpm_public failed"); /////////////////////////////////////////////// // Get name of the object using the new handle let actual_name = context .tr_get_name(new_nv_index_handle) .map_err(|e| cleanup(&mut context, e, new_nv_index_handle.into(), "tr_get_name")) .unwrap(); ////////////////////////////////////////////// // Remove undefine the space context .nv_undefine_space(Provision::Owner, new_nv_index_handle.into()) .expect("Call to nv_undefine_space failed"); assert_eq!(expected_name, actual_name); } #[test] fn test_tr_from_tpm_public_password_auth() { let nv_index_tpm_handle = NvIndexTpmHandle::new(0x01500022).unwrap(); remove_nv_index_handle_from_tpm(nv_index_tpm_handle, Provision::Owner); let mut context = create_ctx_without_session(); let auth = Auth::try_from(vec![ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, ]) .expect("Failed to create auth"); // closure for cleaning up if a call fails. let cleanup = |context: &mut Context, e: tss_esapi::Error, handle: NvIndexHandle, fn_name: &str| -> tss_esapi::Error { // Set password authorization context.set_sessions((Some(AuthSession::Password), None, None)); context .nv_undefine_space(Provision::Owner, handle) .expect("Failed to call nv_undefine_space"); panic!("{} failed: {}", fn_name, e); }; // Create nv public. let nv_index_attributes = NvIndexAttributesBuilder::new() .with_auth_write(true) .with_auth_read(true) .build() .expect("Failed to create auth nv index attributes"); let nv_public = NvPublicBuilder::new() .with_nv_index(nv_index_tpm_handle) .with_index_name_algorithm(HashingAlgorithm::Sha256) .with_index_attributes(nv_index_attributes) .with_data_area_size(32) .build() .expect("Failed to build nv public"); /////////////////////////////////////////////////////////////// // Define space // // Set password authorization when creating the space. context.set_sessions((Some(AuthSession::Password), None, None)); let initial_nv_index_handle = context .nv_define_space(Provision::Owner, Some(auth), nv_public) .expect("Failed to call nv_define_space"); /////////////////////////////////////////////////////////////// // Read the name from the tpm // // No password authorization. context.clear_sessions(); let (_expected_nv_public, expected_name) = context .nv_read_public(initial_nv_index_handle) .map_err(|e| cleanup(&mut context, e, initial_nv_index_handle, "nv_read_public")) .expect("Failed to call nv_read_public"); /////////////////////////////////////////////////////////////// // Close the esys handle (remove all meta data). // let mut handle_to_be_closed: ObjectHandle = initial_nv_index_handle.into(); context .tr_close(&mut handle_to_be_closed) .map_err(|e| cleanup(&mut context, e, initial_nv_index_handle, "tr_close")) .expect("Failed to call tr_close"); assert_eq!(handle_to_be_closed, ObjectHandle::None); // The value of the handle_to_be_closed will be set to a 'None' handle // if the operations was successful. /////////////////////////////////////////////////////////////// // Make Esys create a new ObjectHandle from the // data in the TPM. // // The handle is gone so if this fails it is not // possible to remove the defined space. let new_nv_index_handle = context .tr_from_tpm_public(nv_index_tpm_handle.into()) .map_err(|e| -> tss_esapi::Result { panic!("tr_from_tpm_public failed: {}", e); }) .expect("Error when call tr_from_tpm_public"); /////////////////////////////////////////////////////////////// // Get name of the object using the new handle // let actual_name = context .tr_get_name(new_nv_index_handle) .map_err(|e| cleanup(&mut context, e, new_nv_index_handle.into(), "tr_get_name")) .expect("Failed to call tr_get_name"); /////////////////////////////////////////////////////////////// // Remove undefine the space // // Set password authorization context.set_sessions((Some(AuthSession::Password), None, None)); context .nv_undefine_space(Provision::Owner, new_nv_index_handle.into()) .expect("Call to nv_undefine_space failed"); /////////////////////////////////////////////////////////////// // Check that we got the correct name // assert_eq!(expected_name, actual_name); } #[test] fn read_from_retrieved_handle_using_password_authorization() { let nv_index_tpm_handle = NvIndexTpmHandle::new(0x01500023).unwrap(); remove_nv_index_handle_from_tpm(nv_index_tpm_handle, Provision::Owner); let mut context = create_ctx_without_session(); let auth = Auth::try_from(vec![ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, ]) .unwrap(); // closure for cleaning up if a call fails. let cleanup = |context: &mut Context, e: tss_esapi::Error, handle: NvIndexHandle, fn_name: &str| -> tss_esapi::Error { // Set password authorization context.set_sessions((Some(AuthSession::Password), None, None)); context .nv_undefine_space(Provision::Owner, handle) .expect("Call to nv_undefine_space failed"); panic!("{} failed: {}", fn_name, e); }; // Create nv public. Only use auth for write. let nv_index_attributes = NvIndexAttributesBuilder::new() .with_auth_write(true) .with_auth_read(true) .build() .expect("Failed to create auth nv index attributes"); let nv_public = NvPublicBuilder::new() .with_nv_index(nv_index_tpm_handle) .with_index_name_algorithm(HashingAlgorithm::Sha256) .with_index_attributes(nv_index_attributes) .with_data_area_size(32) .build() .unwrap(); /////////////////////////////////////////////////////////////// // Define space // // Set password authorization when creating the space. context.set_sessions((Some(AuthSession::Password), None, None)); let initial_nv_index_handle = context .nv_define_space(Provision::Owner, Some(auth.clone()), nv_public) .unwrap(); /////////////////////////////////////////////////////////////// // Read the name from the tpm // // No password authorization. context.clear_sessions(); let (_expected_nv_public, initial_name) = context .nv_read_public(initial_nv_index_handle) .map_err(|e| cleanup(&mut context, e, initial_nv_index_handle, "nv_read_public")) .unwrap(); /////////////////////////////////////////////////////////////// // Write data to created index. // // When the write succeeds the attributes will change // and there for the name will change. let expected_data = MaxNvBuffer::try_from(vec![ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, ]) .unwrap(); context.set_sessions((Some(AuthSession::Password), None, None)); context .nv_write( NvAuth::NvIndex(initial_nv_index_handle), initial_nv_index_handle, expected_data.clone(), 0, ) .map_err(|e| cleanup(&mut context, e, initial_nv_index_handle, "nv_write")) .unwrap(); /////////////////////////////////////////////////////////////// // Read the new name that have been calculated after the write. // // No password authorization. context.clear_sessions(); let (_expected_nv_public, expected_name) = context .nv_read_public(initial_nv_index_handle) .map_err(|e| cleanup(&mut context, e, initial_nv_index_handle, "nv_read_public")) .unwrap(); assert_ne!(initial_name, expected_name); /////////////////////////////////////////////////////////////// // Close the esys handle (remove all meta data). // let mut handle_to_be_closed: ObjectHandle = initial_nv_index_handle.into(); context .tr_close(&mut handle_to_be_closed) .map_err(|e| cleanup(&mut context, e, initial_nv_index_handle, "tr_close")) .unwrap(); assert_eq!(handle_to_be_closed, ObjectHandle::None); // The value of the handle_to_be_closed will be set to a 'None' handle // if the operations was successful. /////////////////////////////////////////////////////////////// // Make Esys create a new ObjectHandle from the // data in the TPM. // // The handle is gone so if this fails it is not // possible to remove the defined space. let new_nv_index_handle = context .tr_from_tpm_public(nv_index_tpm_handle.into()) .map(NvIndexHandle::from) .expect("tr_from_tpm_public failed: {}"); /////////////////////////////////////////////////////////////// // Get name of the object using the new handle // let actual_name = context .tr_get_name(new_nv_index_handle.into()) .map_err(|e| cleanup(&mut context, e, new_nv_index_handle, "tr_get_name")) .unwrap(); /////////////////////////////////////////////////////////////// // Call nv_read to get data from nv_index. // // Set authorization for the retrieved handle context .tr_set_auth(new_nv_index_handle.into(), auth) .map_err(|e| cleanup(&mut context, e, new_nv_index_handle, "tr_set_auth")) .unwrap(); // read the data context.set_sessions((Some(AuthSession::Password), None, None)); let actual_data = context .nv_read( NvAuth::NvIndex(new_nv_index_handle), new_nv_index_handle, 32, 0, ) .map_err(|e| cleanup(&mut context, e, new_nv_index_handle, "nv_read")) .unwrap(); /////////////////////////////////////////////////////////////// // Remove undefine the space // // Set password authorization context.set_sessions((Some(AuthSession::Password), None, None)); context .nv_undefine_space(Provision::Owner, new_nv_index_handle) .expect("Call to nv_undefine_space failed"); /////////////////////////////////////////////////////////////// // The name will have changed // assert_eq!(expected_name, actual_name); assert_eq!(expected_data, actual_data); } } tss-esapi-7.4.0/tests/integration_tests/context_tests/mod.rs000064400000000000000000000000551046102023000225060ustar 00000000000000mod general_esys_tr_tests; mod tpm_commands; tss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/asymmetric_primitives_tests.rs000064400000000000000000000074111046102023000322650ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod test_rsa_encrypt_decrypt { use crate::common::{create_ctx_with_session, encryption_decryption_key_pub}; use std::convert::TryFrom; use tss_esapi::attributes::ObjectAttributesBuilder; use tss_esapi::{ interface_types::{ algorithm::{HashingAlgorithm, PublicAlgorithm, RsaDecryptAlgorithm}, ecc::EccCurve, resource_handles::Hierarchy, }, structures::{ Auth, Data, EccPoint, EccScheme, HashScheme, KeyDerivationFunctionScheme, PublicBuilder, PublicEccParametersBuilder, PublicKeyRsa, RsaDecryptionScheme, }, }; #[test] fn test_encrypt_decrypt() { let mut context = create_ctx_with_session(); let random_digest = context.get_random(16).unwrap(); let key_auth = Auth::try_from(random_digest.value().to_vec()).unwrap(); let key_handle = context .create_primary( Hierarchy::Owner, encryption_decryption_key_pub(), Some(key_auth), None, None, None, ) .unwrap() .key_handle; // let scheme = AsymSchemeUnion::RSAOAEP(HashingAlgorithm::Sha256); let scheme = RsaDecryptionScheme::create(RsaDecryptAlgorithm::Oaep, Some(HashingAlgorithm::Sha256)) .expect("Failed to create rsa decryption scheme"); let plaintext_bytes: Vec = vec![0x01, 0x02, 0x03]; let plaintext = PublicKeyRsa::try_from(plaintext_bytes.clone()).unwrap(); let ciphertext = context .rsa_encrypt(key_handle, plaintext, scheme, Data::default()) .unwrap(); assert_ne!(plaintext_bytes, ciphertext.value()); let decrypted = context .rsa_decrypt(key_handle, ciphertext, scheme, Data::default()) .unwrap(); assert_eq!(plaintext_bytes, decrypted.value()); } #[test] fn test_ecdh() { let mut context = create_ctx_with_session(); let random_digest = context.get_random(16).unwrap(); let key_auth = Auth::try_from(random_digest.value().to_vec()).unwrap(); let ecc_parms = PublicEccParametersBuilder::new() .with_ecc_scheme(EccScheme::EcDh(HashScheme::new(HashingAlgorithm::Sha256))) .with_curve(EccCurve::NistP256) .with_is_signing_key(false) .with_is_decryption_key(true) .with_restricted(false) .with_key_derivation_function_scheme(KeyDerivationFunctionScheme::Null) .build() .unwrap(); let object_attributes = ObjectAttributesBuilder::new() .with_fixed_tpm(true) .with_fixed_parent(true) .with_sensitive_data_origin(true) .with_user_with_auth(true) .with_decrypt(true) .with_sign_encrypt(false) .with_restricted(false) .build() .unwrap(); let public = PublicBuilder::new() .with_public_algorithm(PublicAlgorithm::Ecc) .with_name_hashing_algorithm(HashingAlgorithm::Sha256) .with_object_attributes(object_attributes) .with_ecc_parameters(ecc_parms) .with_ecc_unique_identifier(EccPoint::default()) .build() .unwrap(); let key_handle = context .create_primary(Hierarchy::Owner, public, Some(key_auth), None, None, None) .unwrap() .key_handle; let (z_point, pub_point) = context.ecdh_key_gen(key_handle).unwrap(); let param = context.ecdh_z_gen(key_handle, pub_point).unwrap(); assert_eq!(z_point.x().value(), param.x().value()); } } tss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/attached_components_tests.rs000064400000000000000000000001351046102023000316530ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 tss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/attestation_commands_tests.rs000064400000000000000000000130301046102023000320470ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod test_quote { use crate::common::{create_ctx_with_session, decryption_key_pub, signing_key_pub}; use std::convert::TryFrom; use tss_esapi::{ constants::StructureTag, handles::KeyHandle, interface_types::{ algorithm::{HashingAlgorithm, SignatureSchemeAlgorithm}, resource_handles::Hierarchy, session_handles::AuthSession, structure_tags::AttestationType, }, structures::{ AttestInfo, Data, HashScheme, MaxBuffer, PcrSelectionListBuilder, PcrSlot, SignatureScheme, Ticket, }, traits::Marshall, }; #[test] fn pcr_quote() { let mut context = create_ctx_with_session(); // Quote PCR 0 let pcr_selection_list = PcrSelectionListBuilder::new() .with_selection(HashingAlgorithm::Sha256, &[PcrSlot::Slot0]) .build() .expect("Failed to create PcrSelectionList"); // No qualifying data let qualifying_data = vec![0xff; 16]; let key_handle = context .create_primary(Hierarchy::Owner, signing_key_pub(), None, None, None, None) .unwrap() .key_handle; let (attest, _signature) = context .quote( key_handle, Data::try_from(qualifying_data).unwrap(), SignatureScheme::Null, pcr_selection_list.clone(), ) .expect("Failed to get a quote"); assert_eq!( AttestationType::Quote, attest.attestation_type(), "Attestation type of the returned value is not indicating Quote" ); match attest.attested() { AttestInfo::Quote { info } => { assert!(info.pcr_digest().len() != 0, "Digest in QuoteInfo is empty"); assert_eq!( &pcr_selection_list, info.pcr_selection(), "QuoteInfo selection list did not match the input selection list" ); } _ => { panic!("Attested did not contain the expected variant.") } } } #[test] fn certify() { let mut context = create_ctx_with_session(); let qualifying_data = vec![0xff; 16]; let sign_key_handle = context .create_primary(Hierarchy::Owner, signing_key_pub(), None, None, None, None) .unwrap() .key_handle; let obj_key_handle = context .create_primary( Hierarchy::Owner, decryption_key_pub(), None, None, None, None, ) .unwrap() .key_handle; let (attest, signature) = context .execute_with_sessions( ( Some(AuthSession::Password), Some(AuthSession::Password), None, ), |ctx| { ctx.certify( obj_key_handle.into(), sign_key_handle, Data::try_from(qualifying_data.clone()).unwrap(), SignatureScheme::Null, ) }, ) .expect("Failed to certify object handle"); // Verify the signature is valid for the attestation data let data = MaxBuffer::try_from(attest.marshall().unwrap()) .expect("Failed to get data buffer from attestation data"); let (digest, _) = context .hash(data, HashingAlgorithm::Sha256, Hierarchy::Null) .expect("Failed to hash data"); let ticket = context .execute_with_nullauth_session(|ctx| { ctx.verify_signature(sign_key_handle, digest, signature) }) .expect("Failed to verify signature"); assert_eq!(ticket.tag(), StructureTag::Verified); // Verify the attestation data is as expected assert_eq!(attest.attestation_type(), AttestationType::Certify); assert!(matches!(attest.attested(), AttestInfo::Certify { .. })); assert_eq!(attest.extra_data().value(), qualifying_data); } #[test] fn certify_null() { let mut context = create_ctx_with_session(); let qualifying_data = vec![0xff; 16]; let sign_scheme = SignatureScheme::RsaPss { hash_scheme: HashScheme::new(HashingAlgorithm::Sha256), }; let obj_key_handle = context .create_primary( Hierarchy::Owner, decryption_key_pub(), None, None, None, None, ) .unwrap() .key_handle; let (_attest, signature) = context .execute_with_sessions( ( Some(AuthSession::Password), Some(AuthSession::Password), None, ), |ctx| { ctx.certify( obj_key_handle.into(), KeyHandle::Null, Data::try_from(qualifying_data).unwrap(), sign_scheme, ) }, ) .expect("Failed to certify object handle"); assert_eq!(signature.algorithm(), SignatureSchemeAlgorithm::Null); } } ././@LongLink00006440000000000000000000000152000000000000007771Lustar tss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/authenticated_countdown_timer_tests.rstss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/authenticated_countdown_timer_tes000064400000000000000000000001351046102023000327610ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 tss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/capability_commands_tests.rs000064400000000000000000000025211046102023000316340ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod test_get_capability { use crate::common::create_ctx_without_session; use tss_esapi::{ constants::{tss::TPM2_PT_VENDOR_STRING_1, CapabilityType, PropertyTag}, structures::CapabilityData, }; #[test] fn test_get_capability() { let mut context = create_ctx_without_session(); let (res, _more) = context .get_capability(CapabilityType::TpmProperties, TPM2_PT_VENDOR_STRING_1, 4) .unwrap(); match res { CapabilityData::TpmProperties(props) => { assert_ne!(props.len(), 0); } _ => panic!("Invalid properties returned"), }; } #[test] fn test_get_tpm_property() { let mut context = create_ctx_without_session(); let rev = context .get_tpm_property(PropertyTag::Revision) .expect("Failed to call get_tpm_property") .expect("The TPM did not have a value for the Reveision property tag"); assert_ne!(rev, 0); let year = context .get_tpm_property(PropertyTag::Year) .expect("Failed to call get_tpm_property") .expect("The TPM did not have a value for the Year property tag"); assert_ne!(year, 0); } } tss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/clocks_and_timers_tests.rs000064400000000000000000000001351046102023000313140ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 tss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/command_audit_tests.rs000064400000000000000000000001351046102023000304350ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 tss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/context_management_tests.rs000064400000000000000000000234761046102023000315260ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod test_ctx_save { use crate::common::{create_ctx_with_session, decryption_key_pub, signing_key_pub}; use std::convert::TryFrom; use tss_esapi::{interface_types::resource_handles::Hierarchy, structures::Auth}; #[test] fn test_ctx_save() { let mut context = create_ctx_with_session(); let random_digest = context.get_random(16).unwrap(); let key_auth = Auth::try_from(random_digest.value().to_vec()).unwrap(); let key_handle = context .create_primary( Hierarchy::Owner, signing_key_pub(), Some(key_auth), None, None, None, ) .unwrap() .key_handle; let _ = context.context_save(key_handle.into()).unwrap(); } #[test] fn test_ctx_save_leaf() { let mut context = create_ctx_with_session(); let random_digest = context.get_random(16).unwrap(); let key_auth = Auth::try_from(random_digest.value().to_vec()).unwrap(); let prim_key_handle = context .create_primary( Hierarchy::Owner, decryption_key_pub(), Some(key_auth.clone()), None, None, None, ) .unwrap() .key_handle; let result = context .create( prim_key_handle, signing_key_pub(), Some(key_auth), None, None, None, ) .unwrap(); let key_handle = context .load(prim_key_handle, result.out_private, result.out_public) .unwrap(); context.flush_context(prim_key_handle.into()).unwrap(); let _ = context.context_save(key_handle.into()).unwrap(); } } mod test_ctx_load { use crate::common::{create_ctx_with_session, decryption_key_pub, signing_key_pub}; use std::convert::TryFrom; use tss_esapi::{ handles::KeyHandle, interface_types::resource_handles::Hierarchy, structures::Auth, }; #[test] fn test_ctx_load() { let mut context = create_ctx_with_session(); let key_auth = context.get_random(16).unwrap(); let prim_key_handle = context .create_primary( Hierarchy::Owner, decryption_key_pub(), Some(Auth::try_from(key_auth.value().to_vec()).unwrap()), None, None, None, ) .unwrap() .key_handle; let result = context .create( prim_key_handle, signing_key_pub(), Some(Auth::try_from(key_auth.value().to_vec()).unwrap()), None, None, None, ) .unwrap(); let key_handle = context .load(prim_key_handle, result.out_private, result.out_public) .unwrap(); context.flush_context(prim_key_handle.into()).unwrap(); let key_ctx = context.context_save(key_handle.into()).unwrap(); let key_handle = context.context_load(key_ctx).map(KeyHandle::from).unwrap(); let _ = context.read_public(key_handle).unwrap(); } } mod test_flush_context { use crate::common::{create_ctx_with_session, decryption_key_pub, signing_key_pub}; use std::convert::TryFrom; use tss_esapi::{interface_types::resource_handles::Hierarchy, structures::Auth}; #[test] fn test_flush_ctx() { let mut context = create_ctx_with_session(); let random_digest = context.get_random(16).unwrap(); let key_auth = Auth::try_from(random_digest.value().to_vec()).unwrap(); let key_handle = context .create_primary( Hierarchy::Owner, signing_key_pub(), Some(key_auth), None, None, None, ) .unwrap() .key_handle; context.flush_context(key_handle.into()).unwrap(); assert!(context.read_public(key_handle).is_err()); } #[test] fn test_flush_parent_ctx() { let mut context = create_ctx_with_session(); let random_digest = context.get_random(16).unwrap(); let key_auth = Auth::try_from(random_digest.value().to_vec()).unwrap(); let prim_key_handle = context .create_primary( Hierarchy::Owner, decryption_key_pub(), Some(key_auth.clone()), None, None, None, ) .unwrap() .key_handle; let result = context .create( prim_key_handle, signing_key_pub(), Some(key_auth), None, None, None, ) .unwrap(); let key_handle = context .load(prim_key_handle, result.out_private, result.out_public) .unwrap(); context.flush_context(prim_key_handle.into()).unwrap(); let _ = context.read_public(key_handle).unwrap(); } } mod test_evict_control { use crate::common::{create_ctx_without_session, decryption_key_pub}; use std::convert::TryFrom; use tss_esapi::{ constants::{tss::TPM2_PERSISTENT_FIRST, CapabilityType}, handles::{ObjectHandle, PersistentTpmHandle, TpmHandle}, interface_types::{ dynamic_handles::Persistent, resource_handles::{Hierarchy, Provision}, session_handles::AuthSession, }, structures::{Auth, CapabilityData}, tss2_esys::TPM2_HANDLE, }; fn remove_persitent_handle(persistent_tpm_handle: PersistentTpmHandle) { let mut context = create_ctx_without_session(); let mut property = TPM2_PERSISTENT_FIRST; while let Ok((capability_data, more_data_available)) = context.get_capability(CapabilityType::Handles, property, 1) { if let CapabilityData::Handles(persistent_handles) = capability_data { if let Some(&retrieved_persistent_handle) = persistent_handles.first() { if retrieved_persistent_handle == persistent_tpm_handle.into() { let handle = context .tr_from_tpm_public(TpmHandle::Persistent(persistent_tpm_handle)) .expect("Failed to retrieve handle from TPM"); context .evict_control( Provision::Owner, handle, Persistent::Persistent(persistent_tpm_handle), ) .expect("Failed to evict persistent handle"); return; } if more_data_available { property = TPM2_HANDLE::from(retrieved_persistent_handle) + 1; } } } if !more_data_available { return; } } } #[test] fn test_basic_evict_control() { // Create persistent TPM handle with let persistent_tpm_handle = PersistentTpmHandle::new(u32::from_be_bytes([0x81, 0x00, 0x00, 0x01])) .expect("Failed to create persitent tpm handle"); // Create interface type Persistent by using the handle. let persistent = Persistent::Persistent(persistent_tpm_handle); // Make sure the handle is not already persistent remove_persitent_handle(persistent_tpm_handle); // Create context let mut context = create_ctx_without_session(); // Set Password session context.set_sessions((Some(AuthSession::Password), None, None)); // Create primary key handle let auth_value_primary = Auth::try_from(vec![1, 2, 3, 4, 5]) .expect("Failed to crate auth value for primary key"); let primary_key_handle = context .create_primary( Hierarchy::Owner, decryption_key_pub(), Some(auth_value_primary), None, None, None, ) .expect("Failed to create primary key") .key_handle; // Evict control to make primary_key_handle persistent let mut persistent_primary_key_handle = context .evict_control(Provision::Owner, primary_key_handle.into(), persistent) .expect("Failed to make the primary key handle persistent"); assert_ne!(persistent_primary_key_handle, ObjectHandle::Null); assert_ne!(persistent_primary_key_handle, ObjectHandle::None); // Flush out the primary_key_handle context .flush_context(ObjectHandle::from(primary_key_handle)) .expect("Failed to flush context"); // Close the persistent_handle returned by evict_control context .tr_close(&mut persistent_primary_key_handle) .expect("Failed to close persistent handle"); // Retrieve the handle from the tpm again. let retrieved_persistent_handle = context.execute_without_session(|ctx| { ctx.tr_from_tpm_public(TpmHandle::Persistent(persistent_tpm_handle)) .expect("Failed to load the persistent handle") }); // Evict the persitent handle from the tpm context .evict_control(Provision::Owner, retrieved_persistent_handle, persistent) .expect("Failed to evict persistent handle"); context.clear_sessions(); assert_ne!(retrieved_persistent_handle, ObjectHandle::None); } } ././@LongLink00006440000000000000000000000150000000000000007767Lustar tss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/dictionary_attack_functions_tests.rstss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/dictionary_attack_functions_tests000064400000000000000000000001351046102023000327720ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 tss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/duplication_commands_tests.rs000064400000000000000000000256761046102023000320460ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod test_duplicate { use crate::common::{create_ctx_with_session, create_ctx_without_session}; use std::convert::TryFrom; use std::convert::TryInto; use tss_esapi::attributes::{ObjectAttributesBuilder, SessionAttributesBuilder}; use tss_esapi::constants::SessionType; use tss_esapi::handles::ObjectHandle; use tss_esapi::interface_types::{ algorithm::{HashingAlgorithm, PublicAlgorithm}, ecc::EccCurve, resource_handles::Hierarchy, session_handles::PolicySession, }; use tss_esapi::structures::SymmetricDefinition; use tss_esapi::structures::{ EccPoint, EccScheme, KeyDerivationFunctionScheme, PublicBuilder, PublicEccParametersBuilder, SymmetricDefinitionObject, }; #[test] fn test_duplicate_and_import() { let mut context = create_ctx_with_session(); // First: create a target parent object. // The key that we will duplicate will be a child of this target parent. let parent_object_attributes = ObjectAttributesBuilder::new() .with_fixed_tpm(true) .with_fixed_parent(true) .with_sensitive_data_origin(true) .with_user_with_auth(true) .with_decrypt(true) .with_sign_encrypt(false) .with_restricted(true) .build() .expect("Attributes to be valid"); let public_parent = PublicBuilder::new() .with_public_algorithm(PublicAlgorithm::Ecc) .with_name_hashing_algorithm(HashingAlgorithm::Sha256) .with_object_attributes(parent_object_attributes) .with_ecc_parameters( PublicEccParametersBuilder::new() .with_ecc_scheme(EccScheme::Null) .with_curve(EccCurve::NistP256) .with_is_signing_key(false) .with_is_decryption_key(true) .with_restricted(true) .with_symmetric(SymmetricDefinitionObject::AES_128_CFB) .with_key_derivation_function_scheme(KeyDerivationFunctionScheme::Null) .build() .expect("Params to be valid"), ) .with_ecc_unique_identifier(EccPoint::default()) .build() .expect("public to be valid"); let new_parent_handle = context .create_primary( Hierarchy::Owner, public_parent.clone(), None, None, None, None, ) .unwrap() .key_handle; // The name of the parent will be used to restrict duplication to // only this one parent. let parent_name = context.read_public(new_parent_handle).unwrap().1; drop(context); // Trial session will be used to compute a policy digest. // The policy will allow key duplication to one specified target parent. // The target parent would be selected using "parent_name". let mut context = create_ctx_without_session(); let trial_session = context .start_auth_session( None, None, None, SessionType::Trial, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) .expect("Start auth session failed") .expect("Start auth session returned a NONE handle"); let (policy_auth_session_attributes, policy_auth_session_attributes_mask) = SessionAttributesBuilder::new() .with_decrypt(true) .with_encrypt(true) .build(); context .tr_sess_set_attributes( trial_session, policy_auth_session_attributes, policy_auth_session_attributes_mask, ) .expect("tr_sess_set_attributes call failed"); let policy_session = PolicySession::try_from(trial_session) .expect("Failed to convert auth session into policy session"); context .policy_duplication_select( policy_session, Vec::::new().try_into().unwrap(), parent_name.clone(), false, ) .expect("Policy duplication select"); // Policy digest will be used when constructing the child key. // It will allow the newly constructed key to be duplicated but // only to one specified parent. let digest = context .policy_get_digest(policy_session) .expect("Could retrieve digest"); drop(context); let mut context = create_ctx_with_session(); // Fixed TPM and Fixed Parent should be "false" for an object // to be eligible for duplication let object_attributes = ObjectAttributesBuilder::new() .with_fixed_tpm(false) .with_fixed_parent(false) .with_sensitive_data_origin(true) .with_user_with_auth(true) .with_decrypt(true) .with_sign_encrypt(true) .with_restricted(false) .build() .expect("Attributes to be valid"); let public_child = PublicBuilder::new() .with_public_algorithm(PublicAlgorithm::Ecc) .with_name_hashing_algorithm(HashingAlgorithm::Sha256) .with_object_attributes(object_attributes) // Use policy digest computed using the trial session .with_auth_policy(digest) .with_ecc_parameters( PublicEccParametersBuilder::new() .with_ecc_scheme(EccScheme::Null) .with_curve(EccCurve::NistP256) .with_is_signing_key(false) .with_is_decryption_key(true) .with_restricted(false) .with_key_derivation_function_scheme(KeyDerivationFunctionScheme::Null) .build() .expect("Params to be valid"), ) .with_ecc_unique_identifier(EccPoint::default()) .build() .expect("public to be valid"); // Re-create the new parent again. // Since the key specification did not change it will be the same parent // that was used to get the "parent_name". // In real world the new parent will likely be persisted in the TPM. let new_parent_handle: ObjectHandle = context .create_primary( Hierarchy::Owner, public_parent.clone(), None, None, None, None, ) .unwrap() .key_handle .into(); let parent_of_object_to_duplicate_handle = context .create_primary(Hierarchy::Owner, public_parent, None, None, None, None) .unwrap() .key_handle; let result = context .create( parent_of_object_to_duplicate_handle, public_child, None, None, None, None, ) .unwrap(); let object_to_duplicate_handle: ObjectHandle = context .load( parent_of_object_to_duplicate_handle, result.out_private.clone(), result.out_public, ) .unwrap() .into(); // Object name of the duplicated object is needed to satisfy // real policy session. let object_name = context .read_public(object_to_duplicate_handle.into()) .unwrap() .1; context.set_sessions((None, None, None)); let policy_auth_session = context .start_auth_session( None, None, None, SessionType::Policy, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) .expect("Start auth session failed") .expect("Start auth session returned a NONE handle"); let (policy_auth_session_attributes, policy_auth_session_attributes_mask) = SessionAttributesBuilder::new() .with_decrypt(true) .with_encrypt(true) .build(); context .tr_sess_set_attributes( policy_auth_session, policy_auth_session_attributes, policy_auth_session_attributes_mask, ) .expect("tr_sess_set_attributes call failed"); let policy_session = PolicySession::try_from(policy_auth_session) .expect("Failed to convert auth session into policy session"); // Even if object name is not included in the policy digest ("false" as 3rd parameter) // Correct name needs to be set or the policy will fail. context .policy_duplication_select(policy_session, object_name, parent_name, false) .unwrap(); context.set_sessions((Some(policy_auth_session), None, None)); // Duplicate the object to new parent. let (data, duplicate, secret) = context .duplicate( object_to_duplicate_handle, new_parent_handle, None, SymmetricDefinitionObject::Null, ) .unwrap(); eprintln!("D: {:?}, P: {:?}, S: {:?}", data, duplicate, secret); // Public is also needed when transferring the duplicatee // for integrity validation. let public = context .read_public(object_to_duplicate_handle.into()) .unwrap() .0; let session = context .start_auth_session( None, None, None, SessionType::Hmac, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) .unwrap(); let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new() .with_decrypt(true) .with_encrypt(true) .build(); context .tr_sess_set_attributes( session.unwrap(), session_attributes, session_attributes_mask, ) .unwrap(); context.set_sessions((session, None, None)); // Try to import the duplicated object. // Most parameters (with the exception of public) are passed from // the values returned from the call to `duplicate`. let private = context .import( new_parent_handle, Some(data), public, duplicate, secret, SymmetricDefinitionObject::Null, ) .unwrap(); eprintln!("P: {:?}", private); } } ././@LongLink00006440000000000000000000000157000000000000007776Lustar tss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/enhanced_authorization_ea_commands_tests.rstss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/enhanced_authorization_ea_command000064400000000000000000001035601046102023000326620ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod test_policy_signed { use crate::common::{create_ctx_with_session, signing_key_pub}; use std::{ convert::{TryFrom, TryInto}, time::Duration, }; use tss_esapi::{ attributes::SessionAttributesBuilder, constants::SessionType, interface_types::{ algorithm::HashingAlgorithm, resource_handles::Hierarchy, session_handles::PolicySession, }, structures::{Digest, Nonce, PublicKeyRsa, RsaSignature, Signature, SymmetricDefinition}, }; #[test] fn test_policy_signed() { let mut context = create_ctx_with_session(); let key_handle = context .create_primary(Hierarchy::Owner, signing_key_pub(), None, None, None, None) .unwrap() .key_handle; let trial_policy_auth_session = context .execute_without_session(|ctx| { ctx.start_auth_session( None, None, None, SessionType::Trial, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) }) .expect("Start auth session failed") .expect("Start auth session returned a NONE handle"); let (trial_policy_auth_session_attributes, trial_policy_auth_session_attributes_mask) = SessionAttributesBuilder::new() .with_decrypt(true) .with_encrypt(true) .build(); context .tr_sess_set_attributes( trial_policy_auth_session, trial_policy_auth_session_attributes, trial_policy_auth_session_attributes_mask, ) .expect("tr_sess_set_attributes call failed"); let nonce_tpm = Nonce::try_from(vec![1, 2, 3]).expect("Failed to convert data into Nonce"); let cp_hash_a = Digest::try_from(vec![1, 2, 3]).expect("Failed to convert data into Digest"); let policy_ref = Nonce::try_from(vec![1, 2, 3]).expect("Failed to convert data into Nonce"); let signature = Signature::RsaSsa( RsaSignature::create( HashingAlgorithm::Sha256, PublicKeyRsa::try_from(vec![0xab; 32]) .expect("Failed to create Public RSA key structure for RSA signature"), ) .expect("Failed to create RSA signature"), ); let trial_policy_session = PolicySession::try_from(trial_policy_auth_session) .expect("Failed to convert auth session into policy session"); context .policy_signed( trial_policy_session, key_handle.try_into().unwrap(), nonce_tpm, cp_hash_a, policy_ref, Some(Duration::from_secs(3600)), signature, ) .expect("Call to policy_signed failed"); } } mod test_policy_secret { use crate::common::create_ctx_with_session; use std::{convert::TryFrom, time::Duration}; use tss_esapi::{ attributes::SessionAttributesBuilder, constants::SessionType, handles::AuthHandle, interface_types::{algorithm::HashingAlgorithm, session_handles::PolicySession}, structures::{Digest, Nonce, SymmetricDefinition}, }; #[test] fn test_policy_secret() { let mut context = create_ctx_with_session(); let trial_policy_auth_session = context .execute_without_session(|ctx| { ctx.start_auth_session( None, None, None, SessionType::Trial, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) }) .expect("Start auth session failed") .expect("Start auth session returned a NONE handle"); let (trial_policy_auth_session_attributes, trial_policy_auth_session_attributes_mask) = SessionAttributesBuilder::new() .with_decrypt(true) .with_encrypt(true) .build(); context .tr_sess_set_attributes( trial_policy_auth_session, trial_policy_auth_session_attributes, trial_policy_auth_session_attributes_mask, ) .expect("tr_sess_set_attributes call failed"); let nonce_tpm = Nonce::try_from(vec![1, 2, 3]).unwrap(); let cp_hash_a = Digest::try_from(vec![1, 2, 3]).unwrap(); let policy_ref = Nonce::try_from(vec![1, 2, 3]).unwrap(); let trial_policy_session = PolicySession::try_from(trial_policy_auth_session) .expect("Failed to convert auth session into policy session"); context .policy_secret( trial_policy_session, AuthHandle::Endorsement, nonce_tpm, cp_hash_a, policy_ref, Some(Duration::from_secs(3600)), ) .expect("Failed to call policy_secret"); } } mod test_policy_or { use crate::common::{create_ctx_without_session, get_pcr_policy_digest}; use std::convert::TryFrom; use tss_esapi::{ attributes::SessionAttributesBuilder, constants::SessionType, interface_types::{algorithm::HashingAlgorithm, session_handles::PolicySession}, structures::{DigestList, SymmetricDefinition}, }; #[test] fn test_policy_or() { let mut context = create_ctx_without_session(); let trial_policy_auth_session = context .start_auth_session( None, None, None, SessionType::Trial, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) .expect("Start auth session failed") .expect("Start auth session returned a NONE handle"); let (trial_policy_auth_session_attributes, trial_policy_auth_session_attributes_mask) = SessionAttributesBuilder::new() .with_decrypt(true) .with_encrypt(true) .build(); context .tr_sess_set_attributes( trial_policy_auth_session, trial_policy_auth_session_attributes, trial_policy_auth_session_attributes_mask, ) .expect("tr_sess_set_attributes call failed"); let mut digest_list = DigestList::new(); digest_list .add(get_pcr_policy_digest(&mut context, true, true).0) .unwrap(); digest_list .add(get_pcr_policy_digest(&mut context, false, true).0) .unwrap(); let trial_policy_session = PolicySession::try_from(trial_policy_auth_session) .expect("Failed to convert auth session into policy session"); // There should be no errors setting an Or for a TRIAL session context .policy_or(trial_policy_session, digest_list) .unwrap(); } } mod test_policy_pcr { use crate::common::create_ctx_without_session; use std::convert::TryFrom; use tss_esapi::{ abstraction::pcr::PcrData, attributes::SessionAttributesBuilder, constants::SessionType, interface_types::{ algorithm::HashingAlgorithm, resource_handles::Hierarchy, session_handles::PolicySession, }, structures::{MaxBuffer, PcrSelectionListBuilder, PcrSlot, SymmetricDefinition}, }; #[test] fn test_policy_pcr_sha_256() { let mut context = create_ctx_without_session(); let trial_policy_auth_session = context .start_auth_session( None, None, None, SessionType::Trial, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) .expect("Start auth session failed") .expect("Start auth session returned a NONE handle"); let (trial_policy_auth_session_attributes, trial_policy_auth_session_attributes_mask) = SessionAttributesBuilder::new() .with_decrypt(true) .with_encrypt(true) .build(); context .tr_sess_set_attributes( trial_policy_auth_session, trial_policy_auth_session_attributes, trial_policy_auth_session_attributes_mask, ) .expect("tr_sess_set_attributes call failed"); // Read the pcr values using pcr_read let pcr_selection_list = PcrSelectionListBuilder::new() .with_selection(HashingAlgorithm::Sha256, &[PcrSlot::Slot0, PcrSlot::Slot1]) .build() .expect("Failed to create PcrSelectionList"); let (_update_counter, pcr_selection_list_out, pcr_data) = context .pcr_read(pcr_selection_list.clone()) .map(|(update_counter, read_pcr_selections, read_pcr_digests)| { ( update_counter, read_pcr_selections.clone(), PcrData::create(&read_pcr_selections, &read_pcr_digests) .expect("Failed to create PcrData"), ) }) .expect("Failed to call pcr_read"); assert_eq!(pcr_selection_list, pcr_selection_list_out); // Run pcr_policy command. // // "If this command is used for a trial policySession, // policySession→policyDigest will be updated using the // values from the command rather than the values from a digest of the TPM PCR." // // "TPM2_Quote() and TPM2_PolicyPCR() digest the concatenation of PCR." let concatenated_pcr_values = MaxBuffer::try_from( [ pcr_data .pcr_bank(HashingAlgorithm::Sha256) .unwrap() .get_digest(PcrSlot::Slot0) .unwrap() .value(), pcr_data .pcr_bank(HashingAlgorithm::Sha256) .unwrap() .get_digest(PcrSlot::Slot1) .unwrap() .value(), ] .concat() .to_vec(), ) .unwrap(); let (hashed_data, _ticket) = context .hash( concatenated_pcr_values, HashingAlgorithm::Sha256, Hierarchy::Owner, ) .expect("Failed to call hash"); let trial_policy_session = PolicySession::try_from(trial_policy_auth_session) .expect("Failed to convert auth session into policy session"); // There should be no errors setting pcr policy for trial session. context .policy_pcr(trial_policy_session, hashed_data, pcr_selection_list) .expect("Failed to call policy_pcr"); } } mod test_policy_locality { use crate::common::create_ctx_without_session; use std::convert::TryFrom; use tss_esapi::{ attributes::{LocalityAttributes, SessionAttributesBuilder}, constants::SessionType, interface_types::{algorithm::HashingAlgorithm, session_handles::PolicySession}, structures::SymmetricDefinition, }; #[test] fn test_policy_locality() { let mut context = create_ctx_without_session(); let trial_policy_auth_session = context .start_auth_session( None, None, None, SessionType::Trial, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) .expect("Start auth session failed") .expect("Start auth session returned a NONE handle"); let (trial_policy_auth_session_attributes, trial_policy_auth_session_attributes_mask) = SessionAttributesBuilder::new() .with_decrypt(true) .with_encrypt(true) .build(); context .tr_sess_set_attributes( trial_policy_auth_session, trial_policy_auth_session_attributes, trial_policy_auth_session_attributes_mask, ) .expect("tr_sess_set_attributes call failed"); let trial_policy_session = PolicySession::try_from(trial_policy_auth_session) .expect("Failed to convert auth session into policy session"); // There should be no errors setting an Or for a TRIAL session context .policy_locality(trial_policy_session, LocalityAttributes::LOCALITY_THREE) .unwrap(); } } mod test_policy_command_code { use crate::common::create_ctx_without_session; use std::convert::TryFrom; use tss_esapi::{ attributes::SessionAttributesBuilder, constants::{CommandCode, SessionType}, interface_types::{algorithm::HashingAlgorithm, session_handles::PolicySession}, structures::SymmetricDefinition, }; #[test] fn test_policy_command_code() { let mut context = create_ctx_without_session(); let trial_policy_auth_session = context .start_auth_session( None, None, None, SessionType::Trial, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) .expect("Start auth session failed") .expect("Start auth session returned a NONE handle"); let (trial_policy_auth_session_attributes, trial_policy_auth_session_attributes_mask) = SessionAttributesBuilder::new() .with_decrypt(true) .with_encrypt(true) .build(); context .tr_sess_set_attributes( trial_policy_auth_session, trial_policy_auth_session_attributes, trial_policy_auth_session_attributes_mask, ) .expect("tr_sess_set_attributes call failed"); let trial_policy_session = PolicySession::try_from(trial_policy_auth_session) .expect("Failed to convert auth session into policy session"); // There should be no errors setting an Or for a TRIAL session context .policy_command_code(trial_policy_session, CommandCode::Unseal) .unwrap(); } } mod test_policy_physical_presence { use crate::common::create_ctx_without_session; use std::convert::TryFrom; use tss_esapi::{ attributes::SessionAttributesBuilder, constants::SessionType, interface_types::{algorithm::HashingAlgorithm, session_handles::PolicySession}, structures::SymmetricDefinition, }; #[test] fn test_policy_physical_presence() { let mut context = create_ctx_without_session(); let trial_policy_auth_session = context .start_auth_session( None, None, None, SessionType::Trial, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) .expect("Start auth session failed") .expect("Start auth session returned a NONE handle"); let (trial_policy_auth_session_attributes, trial_policy_auth_session_attributes_mask) = SessionAttributesBuilder::new() .with_decrypt(true) .with_encrypt(true) .build(); context .tr_sess_set_attributes( trial_policy_auth_session, trial_policy_auth_session_attributes, trial_policy_auth_session_attributes_mask, ) .expect("tr_sess_set_attributes call failed"); let trial_policy_session = PolicySession::try_from(trial_policy_auth_session) .expect("Failed to convert auth session into policy session"); // There should be no errors setting an Or for a TRIAL session context .policy_physical_presence(trial_policy_session) .unwrap(); } } mod test_policy_cp_hash { use crate::common::create_ctx_without_session; use std::convert::TryFrom; use tss_esapi::{ attributes::SessionAttributesBuilder, constants::SessionType, interface_types::{algorithm::HashingAlgorithm, session_handles::PolicySession}, structures::{Digest, SymmetricDefinition}, }; #[test] fn test_policy_cp_hash() { let mut context = create_ctx_without_session(); let trial_policy_auth_session = context .start_auth_session( None, None, None, SessionType::Trial, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) .expect("Start auth session failed") .expect("Start auth session returned a NONE handle"); let (trial_policy_auth_session_attributes, trial_policy_auth_session_attributes_mask) = SessionAttributesBuilder::new() .with_decrypt(true) .with_encrypt(true) .build(); context .tr_sess_set_attributes( trial_policy_auth_session, trial_policy_auth_session_attributes, trial_policy_auth_session_attributes_mask, ) .expect("tr_sess_set_attributes call failed"); let test_dig = Digest::try_from(vec![ 252, 200, 17, 232, 137, 217, 130, 51, 54, 22, 184, 131, 2, 134, 99, 130, 175, 216, 159, 174, 203, 165, 35, 19, 187, 56, 167, 208, 3, 128, 11, 12, ]) .expect("Failed to create digest from data"); let trial_policy_session = PolicySession::try_from(trial_policy_auth_session) .expect("Failed to convert auth session into policy session"); // There should be no errors setting an Or for a TRIAL session context .policy_cp_hash(trial_policy_session, test_dig) .unwrap(); } } mod test_policy_name_hash { use crate::common::create_ctx_without_session; use std::convert::TryFrom; use tss_esapi::{ attributes::SessionAttributesBuilder, constants::SessionType, interface_types::{algorithm::HashingAlgorithm, session_handles::PolicySession}, structures::{Digest, SymmetricDefinition}, }; #[test] fn test_policy_name_hash() { let mut context = create_ctx_without_session(); let trial_policy_auth_session = context .start_auth_session( None, None, None, SessionType::Trial, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) .expect("Start auth session failed") .expect("Start auth session returned a NONE handle"); let (trial_policy_auth_session_attributes, trial_policy_auth_session_attributes_mask) = SessionAttributesBuilder::new() .with_decrypt(true) .with_encrypt(true) .build(); context .tr_sess_set_attributes( trial_policy_auth_session, trial_policy_auth_session_attributes, trial_policy_auth_session_attributes_mask, ) .expect("tr_sess_set_attributes call failed"); let test_dig = Digest::try_from(vec![ 252, 200, 17, 232, 137, 217, 130, 51, 54, 22, 184, 131, 2, 134, 99, 130, 175, 216, 159, 174, 203, 165, 35, 19, 187, 56, 167, 208, 3, 128, 11, 12, ]) .expect("Failed to create digest from data"); let trial_policy_session = PolicySession::try_from(trial_policy_auth_session) .expect("Failed to convert auth session into policy session"); // There should be no errors setting an Or for a TRIAL session context .policy_name_hash(trial_policy_session, test_dig) .expect("Call to policy_name_hash failed"); } } mod test_policy_authorize { use crate::common::{create_ctx_with_session, get_pcr_policy_digest, signing_key_pub}; use std::convert::{TryFrom, TryInto}; use tss_esapi::{ constants::tss::{TPM2_RH_NULL, TPM2_ST_HASHCHECK}, interface_types::{algorithm::HashingAlgorithm, resource_handles::Hierarchy}, structures::{Auth, MaxBuffer, Nonce, SignatureScheme}, tss2_esys::{TPM2B_NONCE, TPMT_TK_HASHCHECK}, }; #[test] fn test_policy_authorize() { let mut context = create_ctx_with_session(); let random_digest = context.get_random(16).unwrap(); let key_auth = Auth::try_from(random_digest.value().to_vec()).unwrap(); let key_handle = context .create_primary( Hierarchy::Owner, signing_key_pub(), Some(key_auth), None, None, None, ) .unwrap() .key_handle; let key_name = context.tr_get_name(key_handle.into()).unwrap(); let policy_ref: TPM2B_NONCE = Default::default(); let (policy_digest, policy_ses) = get_pcr_policy_digest(&mut context, false, false); // aHash ≔ H_{aHashAlg}(approvedPolicy || policyRef) let ahash = context .hash( MaxBuffer::try_from(policy_digest.value().to_vec()).unwrap(), HashingAlgorithm::Sha256, Hierarchy::Null, ) .unwrap() .0; let validation = TPMT_TK_HASHCHECK { tag: TPM2_ST_HASHCHECK, hierarchy: TPM2_RH_NULL, digest: Default::default(), }; // A signature over just the policy_digest, since the policy_ref is empty let signature = context .sign( key_handle, ahash.clone(), SignatureScheme::Null, validation.try_into().unwrap(), ) .unwrap(); let tkt = context .verify_signature(key_handle, ahash, signature) .unwrap(); // Since the signature is over this sessions' state, it should be valid context .policy_authorize( policy_ses, policy_digest, Nonce::try_from(policy_ref).unwrap(), &key_name, tkt, ) .unwrap(); } } mod test_policy_auth_value { use crate::common::create_ctx_without_session; use std::convert::TryFrom; use tss_esapi::{ attributes::SessionAttributesBuilder, constants::SessionType, interface_types::{algorithm::HashingAlgorithm, session_handles::PolicySession}, structures::SymmetricDefinition, }; #[test] fn test_policy_auth_value() { let mut context = create_ctx_without_session(); let trial_policy_auth_session = context .start_auth_session( None, None, None, SessionType::Trial, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) .expect("Start auth session failed") .expect("Start auth session returned a NONE handle"); let (trial_policy_auth_session_attributes, trial_policy_auth_session_attributes_mask) = SessionAttributesBuilder::new() .with_decrypt(true) .with_encrypt(true) .build(); context .tr_sess_set_attributes( trial_policy_auth_session, trial_policy_auth_session_attributes, trial_policy_auth_session_attributes_mask, ) .expect("tr_sess_set_attributes call failed"); let trial_policy_session = PolicySession::try_from(trial_policy_auth_session) .expect("Failed to convert auth session into policy session"); // There should be no errors setting an Or for a TRIAL session context .policy_auth_value(trial_policy_session) .expect("Failed to call policy auth value"); } } mod test_policy_password { use crate::common::create_ctx_without_session; use std::convert::TryFrom; use tss_esapi::{ attributes::SessionAttributesBuilder, constants::SessionType, interface_types::{algorithm::HashingAlgorithm, session_handles::PolicySession}, structures::SymmetricDefinition, }; #[test] fn test_policy_password() { let mut context = create_ctx_without_session(); let trial_policy_auth_session = context .start_auth_session( None, None, None, SessionType::Trial, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) .expect("Start auth session failed") .expect("Start auth session returned a NONE handle"); let (trial_policy_auth_session_attributes, trial_policy_auth_session_attributes_mask) = SessionAttributesBuilder::new() .with_decrypt(true) .with_encrypt(true) .build(); context .tr_sess_set_attributes( trial_policy_auth_session, trial_policy_auth_session_attributes, trial_policy_auth_session_attributes_mask, ) .expect("tr_sess_set_attributes call failed"); let trial_policy_session = PolicySession::try_from(trial_policy_auth_session) .expect("Failed to convert auth session into policy session"); // There should be no errors setting an Or for a TRIAL session context .policy_password(trial_policy_session) .expect("Failed to call policy_password"); } } mod test_policy_get_digest { use crate::common::create_ctx_without_session; use std::convert::TryFrom; use tss_esapi::{ abstraction::pcr::PcrData, attributes::SessionAttributesBuilder, constants::SessionType, interface_types::{ algorithm::HashingAlgorithm, resource_handles::Hierarchy, session_handles::PolicySession, }, structures::{MaxBuffer, PcrSelectionListBuilder, PcrSlot, SymmetricDefinition}, }; #[test] fn get_policy_digest() { let mut context = create_ctx_without_session(); let trial_policy_auth_session = context .start_auth_session( None, None, None, SessionType::Trial, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) .expect("Start auth session failed") .expect("Start auth session returned a NONE handle"); let (trial_policy_auth_session_attributes, trial_policy_auth_session_attributes_mask) = SessionAttributesBuilder::new() .with_decrypt(true) .with_encrypt(true) .build(); context .tr_sess_set_attributes( trial_policy_auth_session, trial_policy_auth_session_attributes, trial_policy_auth_session_attributes_mask, ) .expect("tr_sess_set_attributes call failed"); // Read the pcr values using pcr_read let pcr_selection_list = PcrSelectionListBuilder::new() .with_selection(HashingAlgorithm::Sha256, &[PcrSlot::Slot0, PcrSlot::Slot1]) .build() .expect("Failed to create PcrSelectionList"); let trial_policy_session = PolicySession::try_from(trial_policy_auth_session) .expect("Failed to convert auth session into policy session"); let (_update_counter, pcr_selection_list_out, pcr_data) = context .pcr_read(pcr_selection_list.clone()) .map(|(update_counter, read_pcr_selections, read_pcr_digests)| { ( update_counter, read_pcr_selections.clone(), PcrData::create(&read_pcr_selections, &read_pcr_digests) .expect("Failed to create PcrData"), ) }) .expect("Failed to call pcr_read"); assert_eq!(pcr_selection_list, pcr_selection_list_out); // Run pcr_policy command. // // "If this command is used for a trial policySession, // policySession→policyDigest will be updated using the // values from the command rather than the values from a digest of the TPM PCR." // // "TPM2_Quote() and TPM2_PolicyPCR() digest the concatenation of PCR." let concatenated_pcr_values = MaxBuffer::try_from( [ pcr_data .pcr_bank(HashingAlgorithm::Sha256) .unwrap() .get_digest(PcrSlot::Slot0) .unwrap() .value(), pcr_data .pcr_bank(HashingAlgorithm::Sha256) .unwrap() .get_digest(PcrSlot::Slot1) .unwrap() .value(), ] .concat() .to_vec(), ) .unwrap(); let (hashed_data, _ticket) = context .hash( concatenated_pcr_values, HashingAlgorithm::Sha256, Hierarchy::Owner, ) .unwrap(); // There should be no errors setting pcr policy for trial session. context .policy_pcr(trial_policy_session, hashed_data, pcr_selection_list) .unwrap(); // There is now a policy digest that can be retrieved and used. let retrieved_policy_digest = context.policy_get_digest(trial_policy_session).unwrap(); // The algorithm is SHA256 so the expected size of the digest should be 32. assert_eq!(retrieved_policy_digest.value().len(), 32); } } mod test_policy_nv_written { use crate::common::create_ctx_without_session; use std::convert::TryFrom; use tss_esapi::{ attributes::SessionAttributesBuilder, constants::SessionType, interface_types::{algorithm::HashingAlgorithm, session_handles::PolicySession}, structures::SymmetricDefinition, }; #[test] fn test_policy_nv_written() { let mut context = create_ctx_without_session(); let trial_policy_auth_session = context .start_auth_session( None, None, None, SessionType::Trial, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) .expect("Start auth session failed") .expect("Start auth session returned a NONE handle"); let (trial_policy_auth_session_attributes, trial_policy_auth_session_attributes_mask) = SessionAttributesBuilder::new() .with_decrypt(true) .with_encrypt(true) .build(); context .tr_sess_set_attributes( trial_policy_auth_session, trial_policy_auth_session_attributes, trial_policy_auth_session_attributes_mask, ) .expect("tr_sess_set_attributes call failed"); let trial_policy_session = PolicySession::try_from(trial_policy_auth_session) .expect("Failed to convert auth session into policy session"); // There should be no errors setting an Or for a TRIAL session context .policy_nv_written(trial_policy_session, true) .unwrap(); } } mod test_policy_template { use crate::common::create_ctx_without_session; use std::convert::TryFrom; use tss_esapi::{ constants::SessionType, interface_types::{algorithm::HashingAlgorithm, session_handles::PolicySession}, structures::{Digest, Nonce, SymmetricDefinition}, }; #[test] fn basic_policy_template_test() { let trial_session_nonce = Nonce::try_from(vec![ 11, 12, 13, 14, 15, 16, 17, 18, 19, 11, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, ]) .expect("Failed to create Nonce for trial session"); let mut context = create_ctx_without_session(); let trial_policy_auth_session = context .start_auth_session( None, None, Some(trial_session_nonce), SessionType::Trial, SymmetricDefinition::AES_128_CFB, HashingAlgorithm::Sha1, ) .expect("Call to start_auth_session failed") .expect("Failed to get proper session"); let template_hash = Digest::try_from(vec![ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ]) .expect("Failed to create template hash digest"); let trial_policy_session = PolicySession::try_from(trial_policy_auth_session) .expect("Failed to convert auth session into policy session"); // TODO. DO not just panic but instead check error code // to see if the command is supported by the TPM and if // not log a warning but let the test pass. context .policy_template(trial_policy_session, template_hash) .expect("Failed to call policy_template"); let expected_policy_template = Digest::try_from(vec![ 0xf6, 0x6d, 0x2a, 0x9c, 0x6e, 0xa8, 0xdf, 0x1a, 0x49, 0x3c, 0x42, 0xcc, 0xac, 0x6e, 0x3d, 0x08, 0xc0, 0x84, 0xcf, 0x73, ]) .expect("Failed to create the expected policy template digest"); let policy_digest = context .policy_get_digest(trial_policy_session) .expect("Failed to get policy digest for trial session"); assert_eq!(expected_policy_template, policy_digest); } } tss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/ephemeral_ec_keys_tests.rs000064400000000000000000000001351046102023000312750ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 tss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/field_upgrade_tests.rs000064400000000000000000000001351046102023000304230ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 ././@LongLink00006440000000000000000000000146000000000000007774Lustar tss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/hash_hmac_event_sequences_tests.rstss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/hash_hmac_event_sequences_tests.r000064400000000000000000000001351046102023000326350ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 tss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/hierarchy_commands_tests.rs000064400000000000000000000077641046102023000315070ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod test_create_primary { use crate::common::{create_ctx_with_session, decryption_key_pub}; use std::convert::TryFrom; use tss_esapi::{ handles::ObjectHandle, interface_types::resource_handles::Hierarchy, structures::Auth, }; #[test] fn test_create_primary() { let mut context = create_ctx_with_session(); let random_digest = context.get_random(16).unwrap(); let key_auth = Auth::try_from(random_digest.value().to_vec()).unwrap(); let key_handle = context .create_primary( Hierarchy::Owner, decryption_key_pub(), Some(key_auth), None, None, None, ) .unwrap() .key_handle; assert!(ObjectHandle::from(key_handle) != ObjectHandle::Null); } } mod test_clear { use crate::common::create_ctx_with_session; use tss_esapi::handles::AuthHandle; #[test] fn test_clear() { let mut context = create_ctx_with_session(); context.clear(AuthHandle::Platform).unwrap(); } } mod test_clear_control { use crate::common::create_ctx_with_session; use tss_esapi::handles::AuthHandle; #[test] fn test_clear_control() { let mut context = create_ctx_with_session(); context.clear(AuthHandle::Platform).unwrap(); context.clear_control(AuthHandle::Platform, true).unwrap(); context.clear(AuthHandle::Platform).unwrap_err(); context.clear_control(AuthHandle::Platform, false).unwrap(); context.clear(AuthHandle::Platform).unwrap(); } } mod test_change_auth { use crate::common::{create_ctx_with_session, decryption_key_pub}; use std::convert::TryFrom; use tss_esapi::{ handles::AuthHandle, interface_types::resource_handles::Hierarchy, structures::Auth, }; #[test] fn test_object_change_auth() { let mut context = create_ctx_with_session(); let prim_key_handle = context .create_primary( Hierarchy::Owner, decryption_key_pub(), None, None, None, None, ) .unwrap() .key_handle; let keyresult = context .create( prim_key_handle, decryption_key_pub(), None, None, None, None, ) .unwrap(); let loaded_key = context .load( prim_key_handle, keyresult.out_private, keyresult.out_public.clone(), ) .unwrap(); let random_digest = context.get_random(16).unwrap(); let new_key_auth = Auth::try_from(random_digest.value().to_vec()).unwrap(); let new_private = context .object_change_auth(loaded_key.into(), prim_key_handle.into(), new_key_auth) .unwrap(); context .load(prim_key_handle, new_private, keyresult.out_public) .unwrap(); } #[test] fn test_hierarchy_change_auth() { let mut context = create_ctx_with_session(); let random_digest = context.get_random(16).unwrap(); let new_auth = Auth::try_from(random_digest.value().to_vec()).unwrap(); // NOTE: If this test failed on your system, you are probably running it against a // real (hardware) TPM or one that is provisioned. This hierarchy is supposed to be // used by the platform. It's used in this test because if we fail at restoring auth, // it should not be a big deal on a software TPM, and it won't impact the other tests. context .hierarchy_change_auth(AuthHandle::Platform, new_auth) .unwrap(); context .hierarchy_change_auth(AuthHandle::Platform, Default::default()) .unwrap(); } } tss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/integrity_collection_pcr_tests.rs000064400000000000000000000246631046102023000327420ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod test_pcr_extend_reset { use crate::common::create_ctx_with_session; use std::convert::TryFrom; use tss_esapi::{ abstraction::pcr::PcrData, handles::PcrHandle, interface_types::algorithm::HashingAlgorithm, structures::{Digest, DigestValues, PcrSelectionListBuilder, PcrSlot}, }; #[test] fn test_pcr_extend_reset_commands() { // In this test, we use PCR16. This was chosen because it's the only one that is // resettable and extendable from the locality in which we are running, and does not // get reset by any D-RTPM events. // PCR (TCG PC Client Platform TPM Profile (PTP) for TPM 2.0 Version 1.05 Rev 14) let mut context = create_ctx_with_session(); let pcr_ses = context.sessions().0; // We start by resetting. We do not place any expectations on the prior contents context.execute_with_session(pcr_ses, |ctx| ctx.pcr_reset(PcrHandle::Pcr16).unwrap()); // Read PCR contents let pcr_selection_list = PcrSelectionListBuilder::new() .with_selection(HashingAlgorithm::Sha1, &[PcrSlot::Slot16]) .with_selection(HashingAlgorithm::Sha256, &[PcrSlot::Slot16]) .build() .expect("Failed to create first PcrSelectionList for pcr_read call"); // pcr_read is NO_SESSIONS let (_, read_pcr_selections, read_pcr_digests) = context.execute_without_session(|ctx| { ctx.pcr_read(pcr_selection_list.clone()) .expect("Failed to call pcr_read") }); // Needs to have the length of associated with the hashing algorithm read_pcr_selections .get_selections() .iter() .zip(read_pcr_digests.value().iter()) .for_each(|(pcr_selection, digest)| { if pcr_selection.hashing_algorithm() == HashingAlgorithm::Sha1 { assert_eq!(digest.len(), 20); assert_eq!(digest.value(), [0; 20]); } else if pcr_selection.hashing_algorithm() == HashingAlgorithm::Sha256 { assert_eq!(digest.len(), 32); assert_eq!(digest.value(), [0; 32]); } else { panic!("Read pcr selections contained unexpected HashingAlgorithm"); } }); // Extend both sha256 and sha1 let mut vals = DigestValues::new(); vals.set( HashingAlgorithm::Sha1, Digest::try_from(vec![ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ]) .unwrap(), ); vals.set( HashingAlgorithm::Sha256, Digest::try_from(vec![ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, ]) .unwrap(), ); // The extend and reset functions are all SESSIONS context.execute_with_session(pcr_ses, |ctx| { ctx.pcr_extend(PcrHandle::Pcr16, vals).unwrap() }); // Read PCR contents let (_, read_pcr_selections_2, read_pcr_digests_2) = context.execute_without_session(|ctx| ctx.pcr_read(pcr_selection_list).unwrap()); // Needs to have the length of associated with the hashing algorithm /* Right Hand Side determined by: python3 >>> from hashlib import sha1 >>> m = sha1() >>> m.update(b"\0" * 20) >>> m.update(bytes(range(1,21))) >>> it = iter(m.hexdigest()) >>> res = ["0x"+a+b for a,b in zip(it, it)] >>> ", ".join(res) */ read_pcr_selections_2 .get_selections() .iter() .zip(read_pcr_digests_2.value().iter()) .for_each(|(pcr_selection, digest)| { if pcr_selection.hashing_algorithm() == HashingAlgorithm::Sha1 { assert_eq!(digest.len(), 20); assert_eq!( digest.value(), [ 0x5f, 0x42, 0x0e, 0x04, 0x95, 0x8b, 0x2e, 0x3f, 0x18, 0x07, 0x39, 0x1e, 0x99, 0xd9, 0x49, 0x2c, 0x67, 0xaa, 0xef, 0xfd ] ); } else if pcr_selection.hashing_algorithm() == HashingAlgorithm::Sha256 { assert_eq!(digest.len(), 32); assert_eq!( digest.value(), [ 0x0b, 0x8f, 0x4c, 0x5b, 0x6a, 0xdc, 0x4c, 0x08, 0x7a, 0xb9, 0xf4, 0x3a, 0xae, 0xb6, 0x00, 0x70, 0x84, 0xc2, 0x64, 0xad, 0xca, 0xa3, 0xcb, 0x07, 0x17, 0x6b, 0x79, 0x23, 0x42, 0x85, 0x04, 0x12 ] ); } else { panic!("Read pcr selections contained unexpected HashingAlgorithm"); } }); // Now reset it again to test it's again zeroes context.execute_with_session(pcr_ses, |ctx| ctx.pcr_reset(PcrHandle::Pcr16).unwrap()); // Read PCR contents let pcr_selection_list = PcrSelectionListBuilder::new() .with_selection(HashingAlgorithm::Sha1, &[PcrSlot::Slot16]) .with_selection(HashingAlgorithm::Sha256, &[PcrSlot::Slot16]) .build() .expect("Failed to create PcrSelectionList for pcr_read call after pcr_reset"); let pcr_data = context .execute_without_session(|ctx| { ctx.pcr_read(pcr_selection_list).map( |(_, read_pcr_selections, read_pcr_digests)| { PcrData::create(&read_pcr_selections, &read_pcr_digests) .expect("Failed to create PcrData") }, ) }) .expect("Failed to call pcr_read"); let pcr_sha1_bank = pcr_data.pcr_bank(HashingAlgorithm::Sha1).unwrap(); let pcr_sha256_bank = pcr_data.pcr_bank(HashingAlgorithm::Sha256).unwrap(); let pcr_sha1_value = pcr_sha1_bank.get_digest(PcrSlot::Slot16).unwrap(); let pcr_sha256_value = pcr_sha256_bank.get_digest(PcrSlot::Slot16).unwrap(); // Needs to have the length of associated with the hashing algorithm assert_eq!(pcr_sha1_value.value(), [0; 20]); assert_eq!(pcr_sha256_value.value(), [0; 32]); } } mod test_pcr_read { use crate::common::create_ctx_without_session; use tss_esapi::{ interface_types::algorithm::HashingAlgorithm, structures::{PcrSelectionListBuilder, PcrSlot}, tss2_esys::{TPM2_SHA256_DIGEST_SIZE, TPML_PCR_SELECTION}, }; #[test] fn test_pcr_read_command() { let mut context = create_ctx_without_session(); // Read PCR 0 let pcr_selection_list = PcrSelectionListBuilder::new() .with_selection(HashingAlgorithm::Sha256, &[PcrSlot::Slot0]) .build() .expect("Failed to create PcrSelectionList"); let input: TPML_PCR_SELECTION = pcr_selection_list.clone().into(); // Verify input assert_eq!(pcr_selection_list.len(), 1); assert_eq!(input.count as usize, pcr_selection_list.len()); assert_eq!(input.pcrSelections[0].sizeofSelect, 3); assert_eq!(input.pcrSelections[0].hash, HashingAlgorithm::Sha256.into()); assert_eq!(input.pcrSelections[0].pcrSelect[0], 0b0000_0001); assert_eq!(input.pcrSelections[0].pcrSelect[1], 0b0000_0000); assert_eq!(input.pcrSelections[0].pcrSelect[2], 0b0000_0000); // Read the pcr slots. let (update_counter, read_pcr_selections, read_pcr_digests) = context .pcr_read(pcr_selection_list) .expect("Failed to call pcr_read"); // Verify that the selected slots have been read. assert_ne!(update_counter, 0); let output: TPML_PCR_SELECTION = read_pcr_selections.into(); assert_eq!(output.count, input.count); assert_eq!( output.pcrSelections[0].sizeofSelect, input.pcrSelections[0].sizeofSelect ); assert_eq!(input.pcrSelections[0].hash, output.pcrSelections[0].hash); assert_eq!( input.pcrSelections[0].pcrSelect[0], output.pcrSelections[0].pcrSelect[0] ); assert_eq!( input.pcrSelections[0].pcrSelect[1], output.pcrSelections[0].pcrSelect[1] ); assert_eq!( input.pcrSelections[0].pcrSelect[2], output.pcrSelections[0].pcrSelect[2] ); // Only the specified in the selection should be present. assert_eq!(read_pcr_digests.len(), 1); assert_eq!(read_pcr_digests.len(), output.count as usize); // Needs to have the length of associated with the hashing algorithm assert_eq!( read_pcr_digests.value()[0].len(), TPM2_SHA256_DIGEST_SIZE as usize ); } #[test] fn test_pcr_read_large_pcr_selections() { // If the pcr Selection contains more then 16 values // then not all can be read at once and the returned // pcr selections will differ from the original. let mut context = create_ctx_without_session(); let pcr_selection_list_in = PcrSelectionListBuilder::new() .with_selection( HashingAlgorithm::Sha256, &[ PcrSlot::Slot0, PcrSlot::Slot1, PcrSlot::Slot2, PcrSlot::Slot3, PcrSlot::Slot4, PcrSlot::Slot5, PcrSlot::Slot6, PcrSlot::Slot7, PcrSlot::Slot8, PcrSlot::Slot9, PcrSlot::Slot10, PcrSlot::Slot11, PcrSlot::Slot12, PcrSlot::Slot13, PcrSlot::Slot14, PcrSlot::Slot15, PcrSlot::Slot16, ], ) .build() .expect("Failed to create PcrSelectionList"); let (_update_counter, pcr_selection_list_out, _pcr_data) = context .pcr_read(pcr_selection_list_in.clone()) .expect("pcr_read call failed"); assert_ne!(pcr_selection_list_in, pcr_selection_list_out); } } ././@LongLink00006440000000000000000000000157000000000000007776Lustar tss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/miscellaneous_management_functions_tests.rstss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/miscellaneous_management_function000064400000000000000000000001351046102023000327300ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 tss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/mod.rs000064400000000000000000000016421046102023000251720ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod asymmetric_primitives_tests; mod attached_components_tests; mod attestation_commands_tests; mod authenticated_countdown_timer_tests; mod capability_commands_tests; mod clocks_and_timers_tests; mod command_audit_tests; mod context_management_tests; mod dictionary_attack_functions_tests; mod duplication_commands_tests; mod enhanced_authorization_ea_commands_tests; mod ephemeral_ec_keys_tests; mod field_upgrade_tests; mod hash_hmac_event_sequences_tests; mod hierarchy_commands_tests; mod integrity_collection_pcr_tests; mod miscellaneous_management_functions_tests; mod non_volatile_storage_tests; mod object_commands_tests; mod random_number_generator_tests; mod session_commands_tests; mod signing_and_signature_verification_tests; mod startup_tests; mod symmetric_primitives_tests; mod testing_tests; mod vendor_specific_tests; tss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/non_volatile_storage_tests.rs000064400000000000000000000352221046102023000320530ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod test_nv_define_space { use crate::common::create_ctx_with_session; use tss_esapi::{ attributes::NvIndexAttributesBuilder, handles::NvIndexTpmHandle, interface_types::{algorithm::HashingAlgorithm, resource_handles::Provision}, structures::NvPublicBuilder, }; #[test] fn test_nv_define_space_failures() { let mut context = create_ctx_with_session(); let nv_index = NvIndexTpmHandle::new(0x01500015).unwrap(); // Create owner nv public. let owner_nv_index_attributes = NvIndexAttributesBuilder::new() .with_owner_write(true) .with_owner_read(true) .build() .expect("Failed to create owner nv index attributes"); let owner_nv_public = NvPublicBuilder::new() .with_nv_index(nv_index) .with_index_name_algorithm(HashingAlgorithm::Sha256) .with_index_attributes(owner_nv_index_attributes) .with_data_area_size(32) .build() .unwrap(); // Create platform nv public. let platform_nv_index_attributes = NvIndexAttributesBuilder::new() .with_pp_write(true) .with_pp_read(true) .with_platform_create(true) .build() .expect("Failed to create platform nv index attributes"); let platform_nv_public = NvPublicBuilder::new() .with_nv_index(nv_index) .with_index_name_algorithm(HashingAlgorithm::Sha256) .with_index_attributes(platform_nv_index_attributes) .with_data_area_size(32) .build() .unwrap(); // Fails because attributes dont match hierarchy auth. let _ = context .nv_define_space(Provision::Platform, None, owner_nv_public) .unwrap_err(); let _ = context .nv_define_space(Provision::Owner, None, platform_nv_public) .unwrap_err(); } #[test] fn test_nv_define_space() { let mut context = create_ctx_with_session(); let nv_index = NvIndexTpmHandle::new(0x01500016).unwrap(); // Create owner nv public. let owner_nv_index_attributes = NvIndexAttributesBuilder::new() .with_owner_write(true) .with_owner_read(true) .build() .expect("Failed to create owner nv index attributes"); let owner_nv_public = NvPublicBuilder::new() .with_nv_index(nv_index) .with_index_name_algorithm(HashingAlgorithm::Sha256) .with_index_attributes(owner_nv_index_attributes) .with_data_area_size(32) .build() .expect("Failed to build NvPublic for owner"); // Create platform nv public. let platform_nv_index_attributes = NvIndexAttributesBuilder::new() .with_pp_write(true) .with_pp_read(true) .with_platform_create(true) .build() .expect("Failed to create platform nv index attributes"); let platform_nv_public = NvPublicBuilder::new() .with_nv_index(nv_index) .with_index_name_algorithm(HashingAlgorithm::Sha256) .with_index_attributes(platform_nv_index_attributes) .with_data_area_size(32) .build() .expect("Failed to build NvPublic for platform"); let owner_nv_index_handle = context .nv_define_space(Provision::Owner, None, owner_nv_public) .expect("Call to nv_define_space failed"); context .nv_undefine_space(Provision::Owner, owner_nv_index_handle) .expect("Call to nv_undefine_space failed"); // If you see this line fail, you are likely running it against a live TPM. // On many TPMs, you will get error 0x00000185, indicating the Platform hierarchy to // be unavailable (because the system went to operating system) let platform_nv_index_handle = context .nv_define_space(Provision::Platform, None, platform_nv_public) .expect("Call to nv_define_space failed"); context .nv_undefine_space(Provision::Platform, platform_nv_index_handle) .expect("Call to nv_undefine_space failed"); } } mod test_nv_undefine_space { use crate::common::create_ctx_with_session; use tss_esapi::{ attributes::NvIndexAttributesBuilder, handles::NvIndexTpmHandle, interface_types::{algorithm::HashingAlgorithm, resource_handles::Provision}, structures::NvPublicBuilder, }; #[test] fn test_nv_undefine_space() { let mut context = create_ctx_with_session(); let nv_index = NvIndexTpmHandle::new(0x01500017).unwrap(); // Create owner nv public. let owner_nv_index_attributes = NvIndexAttributesBuilder::new() .with_owner_write(true) .with_owner_read(true) .build() .expect("Failed to create owner nv index attributes"); let owner_nv_public = NvPublicBuilder::new() .with_nv_index(nv_index) .with_index_name_algorithm(HashingAlgorithm::Sha256) .with_index_attributes(owner_nv_index_attributes) .with_data_area_size(32) .build() .expect("Failed to build NvPublic for owner"); let owner_nv_index_handle = context .nv_define_space(Provision::Owner, None, owner_nv_public) .expect("Call to nv_define_space failed"); // Succeeds context .nv_undefine_space(Provision::Owner, owner_nv_index_handle) .expect("Call to nv_undefine_space failed"); } } mod test_nv_read_public { use crate::common::create_ctx_with_session; use tss_esapi::{ attributes::NvIndexAttributesBuilder, handles::NvIndexTpmHandle, interface_types::{algorithm::HashingAlgorithm, resource_handles::Provision}, structures::NvPublicBuilder, }; #[test] fn test_nv_read_public() { let mut context = create_ctx_with_session(); let nv_index = NvIndexTpmHandle::new(0x01500019).unwrap(); let nv_index_attributes = NvIndexAttributesBuilder::new() .with_owner_write(true) .with_owner_read(true) .build() .expect("Failed to create owner nv index attributes"); let expected_nv_public = NvPublicBuilder::new() .with_nv_index(nv_index) .with_index_name_algorithm(HashingAlgorithm::Sha256) .with_index_attributes(nv_index_attributes) .with_data_area_size(32) .build() .expect("Failed to build the expected NvPublic"); let nv_index_handle = context .nv_define_space(Provision::Owner, None, expected_nv_public.clone()) .expect("Call to nv_define_space failed"); let read_public_result = context.nv_read_public(nv_index_handle); context .nv_undefine_space(Provision::Owner, nv_index_handle) .expect("Call to nv_undefine_space failed"); // Report error if let Err(e) = read_public_result { panic!("Failed to read public of nv index: {}", e); } // Check result. let (actual_nv_public, _name) = read_public_result.unwrap(); assert_eq!(expected_nv_public, actual_nv_public); } } mod test_nv_write { use crate::common::create_ctx_with_session; use std::convert::TryFrom; use tss_esapi::{ attributes::NvIndexAttributesBuilder, handles::NvIndexTpmHandle, interface_types::{ algorithm::HashingAlgorithm, resource_handles::{NvAuth, Provision}, }, structures::{MaxNvBuffer, NvPublicBuilder}, }; #[test] fn test_nv_write() { let mut context = create_ctx_with_session(); let nv_index = NvIndexTpmHandle::new(0x01500018).unwrap(); // Create owner nv public. let owner_nv_index_attributes = NvIndexAttributesBuilder::new() .with_owner_write(true) .with_owner_read(true) .build() .expect("Failed to create owner nv index attributes"); let owner_nv_public = NvPublicBuilder::new() .with_nv_index(nv_index) .with_index_name_algorithm(HashingAlgorithm::Sha256) .with_index_attributes(owner_nv_index_attributes) .with_data_area_size(32) .build() .expect("Failed to build NvPublic for owner"); let owner_nv_index_handle = context .nv_define_space(Provision::Owner, None, owner_nv_public) .expect("Call to nv_define_space failed"); // Use owner authorization let write_result = context.nv_write( NvAuth::Owner, owner_nv_index_handle, MaxNvBuffer::try_from([1, 2, 3, 4, 5, 6, 7].to_vec()).unwrap(), 0, ); context .nv_undefine_space(Provision::Owner, owner_nv_index_handle) .expect("Call to nv_undefine_space failed"); if let Err(e) = write_result { panic!("Failed to perform nv write: {}", e); } } } mod test_nv_read { use crate::common::create_ctx_with_session; use std::convert::TryFrom; use tss_esapi::{ attributes::NvIndexAttributesBuilder, handles::NvIndexTpmHandle, interface_types::{ algorithm::HashingAlgorithm, resource_handles::{NvAuth, Provision}, }, structures::{MaxNvBuffer, NvPublicBuilder}, }; #[test] fn test_nv_read() { let mut context = create_ctx_with_session(); let nv_index = NvIndexTpmHandle::new(0x01500020).unwrap(); // Create owner nv public. let owner_nv_index_attributes = NvIndexAttributesBuilder::new() .with_owner_write(true) .with_owner_read(true) .build() .expect("Failed to create owner nv index attributes"); let owner_nv_public = NvPublicBuilder::new() .with_nv_index(nv_index) .with_index_name_algorithm(HashingAlgorithm::Sha256) .with_index_attributes(owner_nv_index_attributes) .with_data_area_size(32) .build() .expect("Failed to build NvPublic for owner"); let owner_nv_index_handle = context .nv_define_space(Provision::Owner, None, owner_nv_public) .expect("Call to nv_define_space failed"); let value = [1, 2, 3, 4, 5, 6, 7]; let expected_data = MaxNvBuffer::try_from(value.to_vec()).expect("Failed to create MaxBuffer from data"); // Write the data using Owner authorization let write_result = context.nv_write( NvAuth::Owner, owner_nv_index_handle, expected_data.clone(), 0, ); // read data using owner authorization let read_result = context.nv_read(NvAuth::Owner, owner_nv_index_handle, value.len() as u16, 0); context .nv_undefine_space(Provision::Owner, owner_nv_index_handle) .expect("Call to nv_undefine_space failed"); // Report error if let Err(e) = write_result { panic!("Failed to perform nv write: {}", e); } if let Err(e) = read_result { panic!("Failed to read public of nv index: {}", e); } // Check result. let actual_data = read_result.unwrap(); assert_eq!(expected_data, actual_data); } } mod test_nv_increment { use crate::common::create_ctx_with_session; use std::convert::TryInto; use tss_esapi::{ attributes::NvIndexAttributesBuilder, constants::nv_index_type::NvIndexType, handles::NvIndexTpmHandle, interface_types::{ algorithm::HashingAlgorithm, resource_handles::{NvAuth, Provision}, }, structures::NvPublicBuilder, }; #[test] fn test_nv_increment() { let mut context = create_ctx_with_session(); let nv_index = NvIndexTpmHandle::new(0x01500021).unwrap(); // Create owner nv public. let owner_nv_index_attributes = NvIndexAttributesBuilder::new() .with_owner_write(true) .with_owner_read(true) .with_nv_index_type(NvIndexType::Counter) .build() .expect("Failed to create owner nv index attributes"); let owner_nv_public = NvPublicBuilder::new() .with_nv_index(nv_index) .with_index_name_algorithm(HashingAlgorithm::Sha256) .with_index_attributes(owner_nv_index_attributes) .with_data_area_size(8) .build() .expect("Failed to build NvPublic for owner"); let owner_nv_index_handle = context .nv_define_space(Provision::Owner, None, owner_nv_public) .expect("Call to nv_define_space failed"); // Increment the counter using Owner authorization. This call initializes the counter let increment_result = context.nv_increment(NvAuth::Owner, owner_nv_index_handle); if let Err(e) = increment_result { panic!("Failed to perform nv increment: {}", e); } // Read the counter using owner authorization (first call) let read_result_first_value = context.nv_read(NvAuth::Owner, owner_nv_index_handle, 8, 0); // Increment the counter using Owner authorization (second increment) let increment_result = context.nv_increment(NvAuth::Owner, owner_nv_index_handle); if let Err(e) = increment_result { panic!("Failed to perform nv increment: {}", e); } // Read the counter using owner authorization let read_result_second_value = context.nv_read(NvAuth::Owner, owner_nv_index_handle, 8, 0); context .nv_undefine_space(Provision::Owner, owner_nv_index_handle) .expect("Call to nv_undefine_space failed"); // Report error if let Err(e) = read_result_first_value { panic!("Failed to read public of nv index: {}", e); } if let Err(e) = read_result_second_value { panic!("Failed to read public of nv index: {}", e); } // Check result. let first_value = u64::from_be_bytes( read_result_first_value .unwrap() .to_vec() .try_into() .unwrap(), ); let second_value = u64::from_be_bytes( read_result_second_value .unwrap() .to_vec() .try_into() .unwrap(), ); assert_eq!(first_value + 1, second_value); } } tss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/object_commands_tests.rs000064400000000000000000000363631046102023000307740ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod test_create { use crate::common::{create_ctx_with_session, decryption_key_pub}; use std::convert::TryFrom; use tss_esapi::{interface_types::resource_handles::Hierarchy, structures::Auth}; #[test] fn test_create() { let mut context = create_ctx_with_session(); let random_digest = context.get_random(16).unwrap(); let key_auth = Auth::try_from(random_digest.value().to_vec()).unwrap(); let prim_key_handle = context .create_primary( Hierarchy::Owner, decryption_key_pub(), Some(key_auth.clone()), None, None, None, ) .unwrap() .key_handle; let _ = context .create( prim_key_handle, decryption_key_pub(), Some(key_auth), None, None, None, ) .unwrap(); } } mod test_load { use crate::common::{create_ctx_with_session, decryption_key_pub, signing_key_pub}; use std::convert::TryFrom; use tss_esapi::{interface_types::resource_handles::Hierarchy, structures::Auth}; #[test] fn test_load() { let mut context = create_ctx_with_session(); let random_digest = context.get_random(16).unwrap(); let key_auth = Auth::try_from(random_digest.value().to_vec()).unwrap(); let prim_key_handle = context .create_primary( Hierarchy::Owner, decryption_key_pub(), Some(key_auth.clone()), None, None, None, ) .unwrap() .key_handle; let result = context .create( prim_key_handle, signing_key_pub(), Some(key_auth), None, None, None, ) .unwrap(); let _ = context .load(prim_key_handle, result.out_private, result.out_public) .unwrap(); } } mod test_load_external_public { use crate::common::{create_ctx_with_session, KEY}; use std::convert::TryFrom; use tss_esapi::{ attributes::ObjectAttributesBuilder, interface_types::{ algorithm::{HashingAlgorithm, PublicAlgorithm, RsaSchemeAlgorithm}, key_bits::RsaKeyBits, resource_handles::Hierarchy, }, structures::{Public, PublicBuilder, PublicKeyRsa, PublicRsaParametersBuilder, RsaScheme}, }; pub fn get_ext_rsa_pub() -> Public { let object_attributes = ObjectAttributesBuilder::new() .with_user_with_auth(true) .with_decrypt(false) .with_sign_encrypt(true) .with_restricted(false) .build() .expect("Failed to build object attributes"); PublicBuilder::new() .with_public_algorithm(PublicAlgorithm::Rsa) .with_name_hashing_algorithm(HashingAlgorithm::Sha256) .with_object_attributes(object_attributes) .with_rsa_parameters( PublicRsaParametersBuilder::new_unrestricted_signing_key( RsaScheme::create(RsaSchemeAlgorithm::RsaSsa, Some(HashingAlgorithm::Sha256)) .expect("Failed to create rsa scheme"), RsaKeyBits::Rsa2048, Default::default(), ) .build() .expect("Failed to create rsa parameters for public structure"), ) .with_rsa_unique_identifier( PublicKeyRsa::try_from(&KEY[..256]) .expect("Failed to create Public RSA key from buffer"), ) .build() .expect("Failed to build Public structure") } #[test] fn test_load_external_public() { let mut context = create_ctx_with_session(); let pub_key = get_ext_rsa_pub(); context .load_external_public(pub_key, Hierarchy::Owner) .unwrap(); } } mod test_load_external { use crate::common::create_ctx_with_session; use std::convert::{TryFrom, TryInto}; use tss_esapi::{ attributes::ObjectAttributesBuilder, interface_types::{ algorithm::{HashingAlgorithm, PublicAlgorithm, RsaSchemeAlgorithm}, key_bits::RsaKeyBits, resource_handles::Hierarchy, }, structures::{ Public, PublicBuilder, PublicKeyRsa, PublicRsaParametersBuilder, RsaScheme, Sensitive, }, }; const KEY: [u8; 256] = [ 0xc9, 0x75, 0xf8, 0xb2, 0x30, 0xf4, 0x24, 0x6e, 0x95, 0xb1, 0x3c, 0x55, 0x0f, 0xe4, 0x48, 0xe9, 0xac, 0x06, 0x1f, 0xa8, 0xbe, 0xa4, 0xd7, 0x1c, 0xa5, 0x5e, 0x2a, 0xbf, 0x60, 0xc2, 0x98, 0x63, 0x6c, 0xb4, 0xe2, 0x61, 0x54, 0x31, 0xc3, 0x3e, 0x9d, 0x1a, 0x83, 0x84, 0x18, 0x51, 0xe9, 0x8c, 0x24, 0xcf, 0xac, 0xc6, 0x0d, 0x26, 0x2c, 0x9f, 0x2b, 0xd5, 0x91, 0x98, 0x89, 0xe3, 0x68, 0x97, 0x36, 0x02, 0xec, 0x16, 0x37, 0x24, 0x08, 0xb4, 0x77, 0xd1, 0x56, 0x10, 0x3e, 0xf0, 0x64, 0xf6, 0x68, 0x50, 0x68, 0x31, 0xf8, 0x9b, 0x88, 0xf2, 0xc5, 0xfb, 0xc9, 0x21, 0xd2, 0xdf, 0x93, 0x6f, 0x98, 0x94, 0x53, 0x68, 0xe5, 0x25, 0x8d, 0x8a, 0xf1, 0xd7, 0x5b, 0xf3, 0xf9, 0xdf, 0x8c, 0x77, 0x24, 0x9e, 0x28, 0x09, 0x36, 0xf0, 0xa2, 0x93, 0x17, 0xad, 0xbb, 0x1a, 0xd7, 0x6f, 0x25, 0x6b, 0x0c, 0xd3, 0x76, 0x7f, 0xcf, 0x3a, 0xe3, 0x1a, 0x84, 0x57, 0x62, 0x71, 0x8a, 0x6a, 0x42, 0x94, 0x71, 0x21, 0x6a, 0x13, 0x73, 0x17, 0x56, 0xa2, 0x38, 0xc1, 0x5e, 0x76, 0x0b, 0x67, 0x6b, 0x6e, 0xcd, 0xd3, 0xe2, 0x8a, 0x80, 0x61, 0x6c, 0x1c, 0x60, 0x9d, 0x65, 0xbd, 0x5a, 0x4e, 0xeb, 0xa2, 0x06, 0xd6, 0xbe, 0xf5, 0x49, 0xc1, 0x7d, 0xd9, 0x46, 0x3e, 0x9f, 0x2f, 0x92, 0xa4, 0x1a, 0x14, 0x2c, 0x1e, 0xb7, 0x6d, 0x71, 0x29, 0x92, 0x43, 0x7b, 0x76, 0xa4, 0x8b, 0x33, 0xf3, 0xd0, 0xda, 0x7c, 0x7f, 0x73, 0x50, 0xe2, 0xc5, 0x30, 0xad, 0x9e, 0x0f, 0x61, 0x73, 0xa0, 0xbb, 0x87, 0x1f, 0x0b, 0x70, 0xa9, 0xa6, 0xaa, 0x31, 0x2d, 0x62, 0x2c, 0xaf, 0xea, 0x49, 0xb2, 0xce, 0x6c, 0x23, 0x90, 0xdd, 0x29, 0x37, 0x67, 0xb1, 0xc9, 0x99, 0x3a, 0x3f, 0xa6, 0x69, 0xc9, 0x0d, 0x24, 0x3f, ]; /// prime2 a.k.a. "q" const PRIV_KEY: [u8; 128] = [ 0xcf, 0x7c, 0xe8, 0xa1, 0x9c, 0x47, 0xe1, 0x70, 0xbd, 0x38, 0x0a, 0xaf, 0x26, 0x5c, 0x48, 0x94, 0x48, 0x54, 0x98, 0x07, 0xae, 0xb9, 0x5c, 0x46, 0xaf, 0x8f, 0x59, 0xc8, 0x30, 0x1b, 0x98, 0xe3, 0x2a, 0x93, 0xb2, 0xdb, 0xab, 0x81, 0xbf, 0xd2, 0xad, 0x0d, 0xb6, 0x5b, 0x57, 0xbf, 0x98, 0xcb, 0xbc, 0x97, 0xb8, 0xc3, 0xa4, 0xb0, 0xc9, 0xf1, 0x05, 0x46, 0xed, 0x06, 0xdf, 0xdc, 0x58, 0xf4, 0xe0, 0x23, 0x15, 0x77, 0x25, 0x7b, 0x46, 0x6f, 0xea, 0x0c, 0xeb, 0xa5, 0x49, 0x53, 0x1d, 0xa0, 0x2e, 0x3a, 0x7e, 0x8e, 0x8d, 0xec, 0xdd, 0xa6, 0x07, 0x95, 0x40, 0xab, 0x3e, 0x10, 0x9b, 0x07, 0xce, 0xe9, 0xf3, 0xdb, 0x99, 0xb7, 0x52, 0xab, 0xa6, 0x22, 0x43, 0x70, 0xc2, 0x2c, 0xdc, 0x98, 0x4e, 0x05, 0x62, 0xdf, 0xe4, 0x6a, 0xba, 0xbd, 0x28, 0x4c, 0xbe, 0xbd, 0xb9, 0x80, 0x54, 0xed, ]; pub fn get_ext_rsa_priv() -> Sensitive { Sensitive::Rsa { sensitive: PRIV_KEY.to_vec().try_into().unwrap(), auth_value: Default::default(), seed_value: Default::default(), } } pub fn get_ext_rsa_pub() -> Public { let object_attributes = ObjectAttributesBuilder::new() .with_user_with_auth(true) .with_decrypt(false) .with_sign_encrypt(true) .with_restricted(false) .build() .expect("Failed to build object attributes"); PublicBuilder::new() .with_public_algorithm(PublicAlgorithm::Rsa) .with_name_hashing_algorithm(HashingAlgorithm::Sha256) .with_object_attributes(object_attributes) .with_rsa_parameters( PublicRsaParametersBuilder::new_unrestricted_signing_key( RsaScheme::create(RsaSchemeAlgorithm::RsaSsa, Some(HashingAlgorithm::Sha256)) .expect("Failed to create rsa scheme"), RsaKeyBits::Rsa2048, Default::default(), ) .build() .expect("Failed to create rsa parameters for public structure"), ) .with_rsa_unique_identifier( PublicKeyRsa::try_from(&KEY[..]) .expect("Failed to create Public RSA key from buffer"), ) .build() .expect("Failed to build Public structure") } #[test] fn test_load_external() { let mut context = create_ctx_with_session(); let pub_key = get_ext_rsa_pub(); let priv_key = get_ext_rsa_priv(); let key_handle = context .load_external(priv_key, pub_key, Hierarchy::Null) .unwrap(); context.flush_context(key_handle.into()).unwrap(); } } mod test_read_public { use crate::common::{create_ctx_with_session, signing_key_pub}; use std::convert::TryFrom; use tss_esapi::{interface_types::resource_handles::Hierarchy, structures::Auth}; #[test] fn test_read_public() { let mut context = create_ctx_with_session(); let random_digest = context.get_random(16).unwrap(); let key_auth = Auth::try_from(random_digest.value().to_vec()).unwrap(); let key_handle = context .create_primary( Hierarchy::Owner, signing_key_pub(), Some(key_auth), None, None, None, ) .unwrap() .key_handle; let _ = context.read_public(key_handle).unwrap(); } } mod test_make_credential { use crate::common::{create_ctx_with_session, decryption_key_pub}; use std::convert::TryInto; use tss_esapi::interface_types::resource_handles::Hierarchy; #[test] fn test_make_credential() { let mut context = create_ctx_with_session(); let key_handle = context .create_primary( Hierarchy::Owner, decryption_key_pub(), None, None, None, None, ) .unwrap() .key_handle; let (_, key_name, _) = context.read_public(key_handle).unwrap(); let cred = vec![1, 2, 3, 4, 5]; context .execute_without_session(|ctx| { ctx.make_credential(key_handle, cred.try_into().unwrap(), key_name) }) .unwrap(); } } mod test_activate_credential { use crate::common::{create_ctx_with_session, decryption_key_pub}; use std::convert::{TryFrom, TryInto}; use tss_esapi::{ attributes::SessionAttributesBuilder, constants::SessionType, interface_types::{algorithm::HashingAlgorithm, resource_handles::Hierarchy}, structures::{Digest, SymmetricDefinition}, }; #[test] fn test_make_activate_credential() { let mut context = create_ctx_with_session(); let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new().build(); let session_1 = context .execute_without_session(|ctx| { ctx.start_auth_session( None, None, None, SessionType::Hmac, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) }) .expect("session_1: Call to start_auth_session failed.") .expect("session_1: The auth session returned was NONE"); context .tr_sess_set_attributes(session_1, session_attributes, session_attributes_mask) .expect("Call to tr_sess_set_attributes failed"); let session_2 = context .execute_without_session(|ctx| { ctx.start_auth_session( None, None, None, SessionType::Hmac, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) }) .expect("session_2: Call to start_auth_session failed.") .expect("session_2: The auth session returned was NONE"); context .tr_sess_set_attributes(session_2, session_attributes, session_attributes_mask) .unwrap(); let key_handle = context .create_primary( Hierarchy::Owner, decryption_key_pub(), None, None, None, None, ) .unwrap() .key_handle; let (_, key_name, _) = context .read_public(key_handle) .expect("Call to read_public failed"); let cred = vec![1, 2, 3, 4, 5]; let (credential_blob, secret) = context .execute_without_session(|ctx| { ctx.make_credential(key_handle, cred.try_into().unwrap(), key_name) }) .expect("Call to make_credential failed"); context.set_sessions((Some(session_1), Some(session_2), None)); let decrypted = context .activate_credential(key_handle, key_handle, credential_blob, secret) .expect("Call to active_credential failed"); let expected = Digest::try_from(vec![1, 2, 3, 4, 5]).expect("Failed to create digest for expected"); assert_eq!(expected, decrypted); } } mod test_unseal { use crate::common::{create_ctx_with_session, create_public_sealed_object, decryption_key_pub}; use std::convert::TryFrom; use tss_esapi::{interface_types::resource_handles::Hierarchy, structures::SensitiveData}; #[test] fn unseal() { let testbytes: [u8; 5] = [0x01, 0x02, 0x03, 0x04, 0x42]; let mut context = create_ctx_with_session(); let key_handle_seal = context .create_primary( Hierarchy::Owner, decryption_key_pub(), None, None, None, None, ) .unwrap() .key_handle; let key_handle_unseal = context .create_primary( Hierarchy::Owner, decryption_key_pub(), None, None, None, None, ) .unwrap() .key_handle; let key_pub = create_public_sealed_object(); let result = context .create( key_handle_seal, key_pub, None, Some(SensitiveData::try_from(testbytes.to_vec()).unwrap()), None, None, ) .unwrap(); let loaded_key = context .load(key_handle_unseal, result.out_private, result.out_public) .unwrap(); let unsealed = context.unseal(loaded_key.into()).unwrap(); let unsealed = unsealed.value(); assert!(unsealed == testbytes); } } tss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/random_number_generator_tests.rs000064400000000000000000000045761046102023000325440ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod test_random { use crate::common::create_ctx_without_session; use std::convert::TryFrom; use tss_esapi::{ attributes::SessionAttributesBuilder, constants::SessionType, interface_types::algorithm::HashingAlgorithm, structures::{SensitiveData, SymmetricDefinition}, }; #[test] fn test_encrypted_get_rand() { let mut context = create_ctx_without_session(); let encrypted_sess = context .start_auth_session( None, None, None, SessionType::Hmac, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) .expect("Start auth session failed") .expect("Start auth session returned a NONE handle"); let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new() .with_decrypt(true) .with_encrypt(true) .with_audit(true) .build(); context .tr_sess_set_attributes(encrypted_sess, session_attributes, session_attributes_mask) .expect("tr_sess_set_attributes call failed"); context.set_sessions((Some(encrypted_sess), None, None)); let _ = context.get_random(10).expect("call to get_rand failed"); } #[test] fn test_authenticated_get_rand() { let mut context = create_ctx_without_session(); let auth_sess = context .start_auth_session( None, None, None, SessionType::Hmac, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) .expect("Start auth session failed") .expect("Start auth session returned a NONE handle"); context.set_sessions((Some(auth_sess), None, None)); let _ = context.get_random(10).unwrap_err(); } #[test] fn test_get_0_rand() { let mut context = create_ctx_without_session(); let _ = context.get_random(0); } #[test] fn test_stir_random() { let mut context = create_ctx_without_session(); let additional_data = SensitiveData::try_from(vec![1, 2, 3]).unwrap(); context.stir_random(additional_data).unwrap(); } } tss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/session_commands_tests.rs000064400000000000000000000152141046102023000312010ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod test_start_auth_session { use crate::common::{create_ctx_with_session, create_ctx_without_session, decryption_key_pub}; use std::convert::TryFrom; use tss_esapi::{ attributes::SessionAttributesBuilder, constants::SessionType, interface_types::{algorithm::HashingAlgorithm, resource_handles::Hierarchy}, structures::{Nonce, SymmetricDefinition}, }; #[test] fn test_simple_sess() { let mut context = create_ctx_without_session(); context .start_auth_session( None, None, None, SessionType::Hmac, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) .unwrap(); } #[test] fn test_nonce_sess() { let mut context = create_ctx_without_session(); context .start_auth_session( None, None, Some( Nonce::try_from( [ 128, 85, 22, 124, 85, 9, 12, 55, 23, 73, 1, 244, 102, 44, 95, 39, 10, ] .to_vec(), ) .unwrap(), ), SessionType::Hmac, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) .unwrap(); } #[test] fn test_bound_sess() { let mut context = create_ctx_with_session(); let prim_key_handle = context .create_primary( Hierarchy::Owner, decryption_key_pub(), None, None, None, None, ) .unwrap() .key_handle; context .start_auth_session( Some(prim_key_handle), Some(prim_key_handle.into()), None, SessionType::Hmac, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) .unwrap(); } #[test] fn test_encrypted_start_sess() { let mut context = create_ctx_without_session(); let encrypted_sess = context .start_auth_session( None, None, None, SessionType::Hmac, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) .unwrap(); let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new() .with_encrypt(true) .with_audit(true) .build(); context .tr_sess_set_attributes( encrypted_sess.unwrap(), session_attributes, session_attributes_mask, ) .expect("tr_sess_set_attributes call failed"); let _ = context .start_auth_session( None, None, None, SessionType::Hmac, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) .unwrap(); } #[test] fn test_authenticated_start_sess() { let mut context = create_ctx_without_session(); let auth_sess = context .start_auth_session( None, None, None, SessionType::Hmac, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) .unwrap(); context.execute_with_session(auth_sess, |ctx| { ctx.start_auth_session( None, None, None, SessionType::Hmac, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) .unwrap_err(); }); } } mod test_policy_restart { use crate::common::{create_ctx_without_session, get_pcr_policy_digest}; use std::convert::TryFrom; use tss_esapi::{ attributes::SessionAttributesBuilder, constants::SessionType, interface_types::{algorithm::HashingAlgorithm, session_handles::PolicySession}, structures::{Digest, DigestList, SymmetricDefinition}, }; #[test] fn test_policy_restart() { let mut context = create_ctx_without_session(); let trial_policy_auth_session = context .start_auth_session( None, None, None, SessionType::Trial, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) .expect("Start auth session failed") .expect("Start auth session returned a NONE handle"); let (trial_policy_auth_session_attributes, trial_policy_auth_session_attributes_mask) = SessionAttributesBuilder::new() .with_decrypt(true) .with_encrypt(true) .build(); context .tr_sess_set_attributes( trial_policy_auth_session, trial_policy_auth_session_attributes, trial_policy_auth_session_attributes_mask, ) .expect("tr_sess_set_attributes call failed"); let trial_policy_session = PolicySession::try_from(trial_policy_auth_session) .expect("Failed to convert auth session into policy session"); let dig = context.policy_get_digest(trial_policy_session).unwrap(); assert_eq!( dig, Digest::try_from(vec![ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]) .unwrap() ); let mut digest_list = DigestList::new(); digest_list .add(get_pcr_policy_digest(&mut context, true, true).0) .unwrap(); digest_list .add(get_pcr_policy_digest(&mut context, false, true).0) .unwrap(); context .policy_or(trial_policy_session, digest_list) .unwrap(); context.policy_restart(trial_policy_session).unwrap(); let dig = context.policy_get_digest(trial_policy_session).unwrap(); assert_eq!( dig, Digest::try_from(vec![ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]) .unwrap() ); } } ././@LongLink00006440000000000000000000000157000000000000007776Lustar tss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/signing_and_signature_verification_tests.rstss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/signing_and_signature_verificatio000064400000000000000000000211161046102023000327130ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod test_verify_signature { use crate::common::{create_ctx_with_session, signing_key_pub, HASH}; use std::convert::{TryFrom, TryInto}; use tss_esapi::{ constants::tss::{TPM2_RH_NULL, TPM2_ST_HASHCHECK}, interface_types::{algorithm::HashingAlgorithm, resource_handles::Hierarchy}, structures::{Auth, Digest, PublicKeyRsa, RsaSignature, Signature, SignatureScheme}, tss2_esys::TPMT_TK_HASHCHECK, }; #[test] fn test_verify_signature() { let mut context = create_ctx_with_session(); let random_digest = context.get_random(16).unwrap(); let key_auth = Auth::try_from(random_digest.value().to_vec()).unwrap(); let key_handle = context .create_primary( Hierarchy::Owner, signing_key_pub(), Some(key_auth), None, None, None, ) .unwrap() .key_handle; let validation = TPMT_TK_HASHCHECK { tag: TPM2_ST_HASHCHECK, hierarchy: TPM2_RH_NULL, digest: Default::default(), }; let signature = context .sign( key_handle, Digest::try_from(HASH[..32].to_vec()).unwrap(), SignatureScheme::Null, validation.try_into().unwrap(), ) .unwrap(); context .verify_signature( key_handle, Digest::try_from(HASH[..32].to_vec()).unwrap(), signature, ) .unwrap(); } #[test] fn test_verify_wrong_signature() { let mut context = create_ctx_with_session(); let random_digest = context.get_random(16).unwrap(); let key_auth = Auth::try_from(random_digest.value().to_vec()).unwrap(); let key_handle = context .create_primary( Hierarchy::Owner, signing_key_pub(), Some(key_auth), None, None, None, ) .unwrap() .key_handle; let validation = TPMT_TK_HASHCHECK { tag: TPM2_ST_HASHCHECK, hierarchy: TPM2_RH_NULL, digest: Default::default(), }; let mut signature = context .sign( key_handle, Digest::try_from(HASH[..32].to_vec()).unwrap(), SignatureScheme::Null, validation.try_into().unwrap(), ) .unwrap(); if let Signature::RsaSsa(rsa_signature) = &mut signature { let mut key_data: Vec = rsa_signature.signature().value().to_vec(); key_data.reverse(); *rsa_signature = RsaSignature::create( rsa_signature.hashing_algorithm(), PublicKeyRsa::try_from(key_data).expect("Failed to create oublic key rsa,"), ) .expect("Failed to create signature"); } assert!(context .verify_signature( key_handle, Digest::try_from(HASH[..32].to_vec()).unwrap(), signature, ) .is_err()); } #[test] fn test_verify_wrong_signature_2() { let mut context = create_ctx_with_session(); let random_digest = context.get_random(16).unwrap(); let key_auth = Auth::try_from(random_digest.value().to_vec()).unwrap(); let key_handle = context .create_primary( Hierarchy::Owner, signing_key_pub(), Some(key_auth), None, None, None, ) .unwrap() .key_handle; let signature = Signature::RsaSsa( RsaSignature::create( HashingAlgorithm::Sha256, PublicKeyRsa::try_from(vec![0xab; 500]) .expect("Failed to create public key rsa structure"), ) .expect("Failed to create RSA SSA signature"), ); assert!(context .verify_signature( key_handle, Digest::try_from(HASH[..32].to_vec()).unwrap(), signature, ) .is_err()); } #[test] fn test_verify_wrong_signature_3() { let mut context = create_ctx_with_session(); let random_digest = context.get_random(16).unwrap(); let key_auth = Auth::try_from(random_digest.value().to_vec()).unwrap(); let key_handle = context .create_primary( Hierarchy::Owner, signing_key_pub(), Some(key_auth), None, None, None, ) .unwrap() .key_handle; let signature = Signature::RsaSsa( RsaSignature::create( HashingAlgorithm::Sha256, PublicKeyRsa::try_from(vec![0; 0]) .expect("Failed to create public key rsa structure"), ) .expect("Failed to create RSA SSA signature"), ); assert!(context .verify_signature( key_handle, Digest::try_from(HASH[..32].to_vec()).unwrap(), signature, ) .is_err()); } } mod test_sign { use crate::common::{create_ctx_with_session, signing_key_pub, HASH}; use std::convert::{TryFrom, TryInto}; use tss_esapi::{ constants::tss::{TPM2_RH_NULL, TPM2_ST_HASHCHECK}, interface_types::resource_handles::Hierarchy, structures::{Auth, Digest, SignatureScheme}, tss2_esys::TPMT_TK_HASHCHECK, }; #[test] fn test_sign() { let mut context = create_ctx_with_session(); let random_digest = context.get_random(16).unwrap(); let key_auth = Auth::try_from(random_digest.value().to_vec()).unwrap(); let key_handle = context .create_primary( Hierarchy::Owner, signing_key_pub(), Some(key_auth), None, None, None, ) .unwrap() .key_handle; let validation = TPMT_TK_HASHCHECK { tag: TPM2_ST_HASHCHECK, hierarchy: TPM2_RH_NULL, digest: Default::default(), }; context .sign( key_handle, Digest::try_from(HASH[..32].to_vec()).unwrap(), SignatureScheme::Null, validation.try_into().unwrap(), ) .unwrap(); } #[test] fn test_sign_empty_digest() { let mut context = create_ctx_with_session(); let random_digest = context.get_random(16).unwrap(); let key_auth = Auth::try_from(random_digest.value().to_vec()).unwrap(); let key_handle = context .create_primary( Hierarchy::Owner, signing_key_pub(), Some(key_auth), None, None, None, ) .unwrap() .key_handle; let validation = TPMT_TK_HASHCHECK { tag: TPM2_ST_HASHCHECK, hierarchy: TPM2_RH_NULL, digest: Default::default(), }; context .sign( key_handle, Digest::try_from(Vec::::new()).unwrap(), SignatureScheme::Null, validation.try_into().unwrap(), ) .unwrap_err(); } #[test] fn test_sign_large_digest() { let mut context = create_ctx_with_session(); let random_digest = context.get_random(16).unwrap(); let key_auth = Auth::try_from(random_digest.value().to_vec()).unwrap(); let key_handle = context .create_primary( Hierarchy::Owner, signing_key_pub(), Some(key_auth), None, None, None, ) .unwrap() .key_handle; let validation = TPMT_TK_HASHCHECK { tag: TPM2_ST_HASHCHECK, hierarchy: TPM2_RH_NULL, digest: Default::default(), }; context .sign( key_handle, Digest::try_from([0xbb; 40].to_vec()).unwrap(), SignatureScheme::Null, validation.try_into().unwrap(), ) .unwrap_err(); } } tss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/startup_tests.rs000064400000000000000000000013421046102023000273340ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod test_startup { use crate::common::create_ctx_without_session; use tss_esapi::constants::StartupType; #[test] fn test_startup() { let mut context = create_ctx_without_session(); context.startup(StartupType::Clear).unwrap(); } } mod test_shutdown { use crate::common::create_ctx_without_session; use tss_esapi::constants::StartupType; #[test] fn test_shutdown() { let mut context = create_ctx_without_session(); context.shutdown(StartupType::Clear).unwrap(); // Re-start the TPM so our tests won't fail context.startup(StartupType::Clear).unwrap(); } } tss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/symmetric_primitives_tests.rs000064400000000000000000000215011046102023000321200ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod test_encrypt_decrypt_2 { use crate::common::create_ctx_without_session; use std::convert::{TryFrom, TryInto}; use tss_esapi::{ abstraction::cipher::Cipher, attributes::ObjectAttributesBuilder, interface_types::{ algorithm::{HashingAlgorithm, PublicAlgorithm, SymmetricMode}, key_bits::RsaKeyBits, resource_handles::Hierarchy, session_handles::AuthSession, }, structures::{ Auth, InitialValue, MaxBuffer, PublicBuilder, RsaExponent, SensitiveData, SymmetricCipherParameters, }, }; #[test] fn test_encrypt_decrypt_with_aes_128_cfb_symmetric_key() { let mut context = create_ctx_without_session(); context .tr_set_auth(Hierarchy::Owner.into(), Auth::default()) .expect("Failed to set auth to empty for owner"); let primary_key_auth = Auth::try_from( context .get_random(16) .expect("get_rand call failed") .value() .to_vec(), ) .expect("Failed to create primary key auth"); let primary_key_handle = context.execute_with_session(Some(AuthSession::Password), |ctx| { ctx.create_primary( Hierarchy::Owner, tss_esapi::utils::create_restricted_decryption_rsa_public( Cipher::aes_128_cfb() .try_into() .expect("Failed to convert from Cipher"), RsaKeyBits::Rsa2048, RsaExponent::default(), ) .expect("Failed to create public for primary key"), Some(primary_key_auth.clone()), None, None, None, ) .expect("Failed to create primary handle") .key_handle }); context .tr_set_auth(primary_key_handle.into(), primary_key_auth) .expect("Failed to set auth from primary key handle."); let symmetric_key_object_attributes = ObjectAttributesBuilder::new() .with_user_with_auth(true) .with_sign_encrypt(true) .with_decrypt(true) .build() .expect("Failed to create object attributes for symmetric key"); let symmetric_key_public = PublicBuilder::new() .with_public_algorithm(PublicAlgorithm::SymCipher) .with_name_hashing_algorithm(HashingAlgorithm::Sha256) .with_object_attributes(symmetric_key_object_attributes) .with_symmetric_cipher_parameters(SymmetricCipherParameters::new( Cipher::aes_128_cfb() .try_into() .expect("Failed to create symmteric cipher parameters from cipher"), )) .with_symmetric_cipher_unique_identifier(Default::default()) .build() .expect("Failed to create public for symmetric key public"); let symmetric_key_auth = Auth::try_from( context .get_random(16) .expect("get_rand call failed") .value() .to_vec(), ) .expect("Failed to create symmetric key auth"); let symmetric_key_value = SensitiveData::try_from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]) .expect("Failed to create sensitive data from data"); // if this fails with "tpm:parameter(2):inconsistent attributes" then the symmetric // cipher is probably not supported. let symmetric_key_creation_data = context.execute_with_session(Some(AuthSession::Password), |ctx| { ctx.create( primary_key_handle, symmetric_key_public, Some(symmetric_key_auth.clone()), Some(symmetric_key_value), None, None, ) .expect("Failed to create symmetric key") }); let symmetric_key_handle = context.execute_with_session(Some(AuthSession::Password), |ctx| { ctx.load( primary_key_handle, symmetric_key_creation_data.out_private, symmetric_key_creation_data.out_public, ) .expect("Failed to load symmetric key") }); context .tr_set_auth(symmetric_key_handle.into(), symmetric_key_auth) .expect("Failed to set auth on symmetric key handle"); let initial_value = InitialValue::try_from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]) .expect("Failed to create InitialValue from data"); let data = MaxBuffer::try_from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 16]) .expect("Failed to create MaxBuffer from data"); let (encrypted_data, _) = context.execute_with_session(Some(AuthSession::Password), |ctx| { ctx.encrypt_decrypt_2( symmetric_key_handle, false, SymmetricMode::Cfb, data.clone(), initial_value.clone(), ) .expect("Call to encrypt_decrypt_2 failed when encrypting data") }); assert_ne!(data, encrypted_data); let (decrypted_data, _) = context.execute_with_session(Some(AuthSession::Password), |ctx| { ctx.encrypt_decrypt_2( symmetric_key_handle, true, SymmetricMode::Cfb, encrypted_data, initial_value, ) .expect("Call to encrypt_decrypt_2 failed when decrypting data") }); debug_assert_eq!(data, decrypted_data); } } mod test_hash { use crate::common::create_ctx_without_session; use std::convert::TryFrom; use tss_esapi::{ interface_types::{algorithm::HashingAlgorithm, resource_handles::Hierarchy}, structures::{MaxBuffer, Ticket}, }; #[test] fn test_hash_with_sha_256() { let mut context = create_ctx_without_session(); let data = "There is no spoon"; let expected_hashed_data: [u8; 32] = [ 0x6b, 0x38, 0x4d, 0x2b, 0xfb, 0x0e, 0x0d, 0xfb, 0x64, 0x89, 0xdb, 0xf4, 0xf8, 0xe9, 0xe5, 0x2f, 0x71, 0xee, 0xb1, 0x0d, 0x06, 0x4c, 0x56, 0x59, 0x70, 0xcd, 0xd9, 0x44, 0x43, 0x18, 0x5d, 0xc1, ]; let expected_hierarchy = Hierarchy::Owner; let (actual_hashed_data, ticket) = context .hash( MaxBuffer::try_from(data.as_bytes().to_vec()).unwrap(), HashingAlgorithm::Sha256, expected_hierarchy, ) .unwrap(); assert_eq!(expected_hashed_data.len(), actual_hashed_data.len()); assert_eq!(&expected_hashed_data[..], &actual_hashed_data[..]); assert_eq!(ticket.hierarchy(), expected_hierarchy); assert_ne!(ticket.digest().len(), 0); // Should do some better checking of the digest } } mod test_hmac { use crate::common::create_ctx_with_session; use std::convert::TryFrom; use tss_esapi::{ attributes::ObjectAttributesBuilder, interface_types::{ algorithm::{HashingAlgorithm, PublicAlgorithm}, resource_handles::Hierarchy, }, structures::{KeyedHashScheme, MaxBuffer, PublicBuilder, PublicKeyedHashParameters}, }; #[test] fn test_hmac() { let mut context = create_ctx_with_session(); let object_attributes = ObjectAttributesBuilder::new() .with_sign_encrypt(true) .with_sensitive_data_origin(true) .with_user_with_auth(true) .build() .expect("Failed to build object attributes"); let key_pub = PublicBuilder::new() .with_public_algorithm(PublicAlgorithm::KeyedHash) .with_name_hashing_algorithm(HashingAlgorithm::Sha256) .with_object_attributes(object_attributes) .with_keyed_hash_parameters(PublicKeyedHashParameters::new( KeyedHashScheme::HMAC_SHA_256, )) .with_keyed_hash_unique_identifier(Default::default()) .build() .expect("Failed to build public structure for key."); let key = context .create_primary(Hierarchy::Owner, key_pub, None, None, None, None) .unwrap(); let data = vec![1, 2, 3, 4]; let buf = MaxBuffer::try_from(data).unwrap(); context .hmac(key.key_handle.into(), buf, HashingAlgorithm::Sha256) .unwrap(); } } tss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/testing_tests.rs000064400000000000000000000011531046102023000273070ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod test_self_test { use crate::common::create_ctx_without_session; #[test] fn test_self_test() { let mut context = create_ctx_without_session(); context.self_test(false).unwrap(); context.self_test(true).unwrap(); } } mod test_get_test_result { use crate::common::create_ctx_without_session; #[test] fn test_get_test_result() { let mut context = create_ctx_without_session(); let (_, rc) = context.get_test_result().unwrap(); rc.unwrap(); } } tss-esapi-7.4.0/tests/integration_tests/context_tests/tpm_commands/vendor_specific_tests.rs000064400000000000000000000001351046102023000307730ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 tss-esapi-7.4.0/tests/integration_tests/handles_tests/auth_handle_tests.rs000064400000000000000000000023131046102023000253560ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use tss_esapi::{ handles::{AuthHandle, ObjectHandle}, tss2_esys::{ ESYS_TR, ESYS_TR_RH_ENDORSEMENT, ESYS_TR_RH_LOCKOUT, ESYS_TR_RH_OWNER, ESYS_TR_RH_PLATFORM, }, }; #[test] fn test_constants_conversions() { let conversion_check = |esys_handle: ESYS_TR, object_handle: ObjectHandle, auth_handle: AuthHandle| { assert_eq!(esys_handle, ESYS_TR::from(auth_handle)); assert_eq!(auth_handle, AuthHandle::from(esys_handle)); assert_eq!(object_handle, ObjectHandle::from(auth_handle)); assert_eq!(auth_handle, AuthHandle::from(object_handle)); }; // Check conversion of esys handles to TPM constants conversion_check(ESYS_TR_RH_OWNER, ObjectHandle::Owner, AuthHandle::Owner); conversion_check( ESYS_TR_RH_LOCKOUT, ObjectHandle::Lockout, AuthHandle::Lockout, ); conversion_check( ESYS_TR_RH_ENDORSEMENT, ObjectHandle::Endorsement, AuthHandle::Endorsement, ); conversion_check( ESYS_TR_RH_PLATFORM, ObjectHandle::Platform, AuthHandle::Platform, ); } tss-esapi-7.4.0/tests/integration_tests/handles_tests/mod.rs000064400000000000000000000003241046102023000224370ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod auth_handle_tests; mod object_handle_tests; mod pcr_handle_tests; mod session_handle_tests; mod tpm_handles_tests; tss-esapi-7.4.0/tests/integration_tests/handles_tests/object_handle_tests.rs000064400000000000000000000022211046102023000256610ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::From; use tss_esapi::{ handles::ObjectHandle, tss2_esys::{ ESYS_TR, ESYS_TR_NONE, ESYS_TR_RH_ENDORSEMENT, ESYS_TR_RH_LOCKOUT, ESYS_TR_RH_NULL, ESYS_TR_RH_OWNER, ESYS_TR_RH_PLATFORM, ESYS_TR_RH_PLATFORM_NV, }, }; #[test] fn test_constants_conversions() { // closure used for the repeated tests let conversion_check = |esys_handle: ESYS_TR, object_handle: ObjectHandle| { assert_eq!(esys_handle, ESYS_TR::from(object_handle)); assert_eq!(object_handle, ObjectHandle::from(esys_handle)); }; // Check conversion of esys handles to TPM constants conversion_check(ESYS_TR_RH_OWNER, ObjectHandle::Owner); conversion_check(ESYS_TR_RH_NULL, ObjectHandle::Null); conversion_check(ESYS_TR_RH_LOCKOUT, ObjectHandle::Lockout); conversion_check(ESYS_TR_RH_ENDORSEMENT, ObjectHandle::Endorsement); conversion_check(ESYS_TR_RH_PLATFORM, ObjectHandle::Platform); conversion_check(ESYS_TR_RH_PLATFORM_NV, ObjectHandle::PlatformNv); conversion_check(ESYS_TR_NONE, ObjectHandle::None); } tss-esapi-7.4.0/tests/integration_tests/handles_tests/pcr_handle_tests.rs000064400000000000000000000077511046102023000252140ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::{From, TryFrom}; use tss_esapi::{ handles::{ObjectHandle, PcrHandle}, tss2_esys::{ ESYS_TR, ESYS_TR_PCR0, ESYS_TR_PCR1, ESYS_TR_PCR10, ESYS_TR_PCR11, ESYS_TR_PCR12, ESYS_TR_PCR13, ESYS_TR_PCR14, ESYS_TR_PCR15, ESYS_TR_PCR16, ESYS_TR_PCR17, ESYS_TR_PCR18, ESYS_TR_PCR19, ESYS_TR_PCR2, ESYS_TR_PCR20, ESYS_TR_PCR21, ESYS_TR_PCR22, ESYS_TR_PCR23, ESYS_TR_PCR24, ESYS_TR_PCR25, ESYS_TR_PCR26, ESYS_TR_PCR27, ESYS_TR_PCR28, ESYS_TR_PCR29, ESYS_TR_PCR3, ESYS_TR_PCR30, ESYS_TR_PCR31, ESYS_TR_PCR4, ESYS_TR_PCR5, ESYS_TR_PCR6, ESYS_TR_PCR7, ESYS_TR_PCR8, ESYS_TR_PCR9, }, }; #[test] fn test_conversion_of_invalid_handle() { let invalid_value: ESYS_TR = 0xFFFFFFFF; let invalid_object_handle: ObjectHandle = ObjectHandle::from(invalid_value); let _ = PcrHandle::try_from(invalid_value).unwrap_err(); let _ = PcrHandle::try_from(invalid_object_handle).unwrap_err(); } macro_rules! test_valid_conversions { ($esys_tr_handle:ident, PcrHandle::$pcr_handle:ident) => { assert_eq!( ObjectHandle::from(PcrHandle::$pcr_handle), ObjectHandle::from($esys_tr_handle), "ObjectHandle conversion failed for PcrHandle::{}", std::stringify!($pcr_handle) ); assert_eq!( $esys_tr_handle, ESYS_TR::from(PcrHandle::$pcr_handle), "Esys TR handle conversion failed for PcrHandle::{}", std::stringify!($pcr_handle), ); assert_eq!( PcrHandle::$pcr_handle, PcrHandle::try_from($esys_tr_handle).expect(&format!( "Failed to convert {} to PcrHandle", std::stringify!($esys_tr_handle) )), "{} did not convert to the expected value PcrHandle::{}", std::stringify!($esys_tr_handle), std::stringify!($pcr_handle), ); }; } #[test] fn test_conversion_of_valid_handle() { // Check the valid values test_valid_conversions!(ESYS_TR_PCR0, PcrHandle::Pcr0); test_valid_conversions!(ESYS_TR_PCR1, PcrHandle::Pcr1); test_valid_conversions!(ESYS_TR_PCR2, PcrHandle::Pcr2); test_valid_conversions!(ESYS_TR_PCR3, PcrHandle::Pcr3); test_valid_conversions!(ESYS_TR_PCR4, PcrHandle::Pcr4); test_valid_conversions!(ESYS_TR_PCR5, PcrHandle::Pcr5); test_valid_conversions!(ESYS_TR_PCR6, PcrHandle::Pcr6); test_valid_conversions!(ESYS_TR_PCR7, PcrHandle::Pcr7); test_valid_conversions!(ESYS_TR_PCR8, PcrHandle::Pcr8); test_valid_conversions!(ESYS_TR_PCR9, PcrHandle::Pcr9); test_valid_conversions!(ESYS_TR_PCR10, PcrHandle::Pcr10); test_valid_conversions!(ESYS_TR_PCR11, PcrHandle::Pcr11); test_valid_conversions!(ESYS_TR_PCR12, PcrHandle::Pcr12); test_valid_conversions!(ESYS_TR_PCR13, PcrHandle::Pcr13); test_valid_conversions!(ESYS_TR_PCR14, PcrHandle::Pcr14); test_valid_conversions!(ESYS_TR_PCR15, PcrHandle::Pcr15); test_valid_conversions!(ESYS_TR_PCR16, PcrHandle::Pcr16); test_valid_conversions!(ESYS_TR_PCR17, PcrHandle::Pcr17); test_valid_conversions!(ESYS_TR_PCR18, PcrHandle::Pcr18); test_valid_conversions!(ESYS_TR_PCR19, PcrHandle::Pcr19); test_valid_conversions!(ESYS_TR_PCR20, PcrHandle::Pcr20); test_valid_conversions!(ESYS_TR_PCR21, PcrHandle::Pcr21); test_valid_conversions!(ESYS_TR_PCR22, PcrHandle::Pcr22); test_valid_conversions!(ESYS_TR_PCR23, PcrHandle::Pcr23); test_valid_conversions!(ESYS_TR_PCR24, PcrHandle::Pcr24); test_valid_conversions!(ESYS_TR_PCR25, PcrHandle::Pcr25); test_valid_conversions!(ESYS_TR_PCR26, PcrHandle::Pcr26); test_valid_conversions!(ESYS_TR_PCR27, PcrHandle::Pcr27); test_valid_conversions!(ESYS_TR_PCR28, PcrHandle::Pcr28); test_valid_conversions!(ESYS_TR_PCR29, PcrHandle::Pcr29); test_valid_conversions!(ESYS_TR_PCR30, PcrHandle::Pcr30); test_valid_conversions!(ESYS_TR_PCR31, PcrHandle::Pcr31); } tss-esapi-7.4.0/tests/integration_tests/handles_tests/session_handle_tests.rs000064400000000000000000000016121046102023000261010ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::From; use tss_esapi::{ handles::{ObjectHandle, SessionHandle}, tss2_esys::{ESYS_TR, ESYS_TR_NONE, ESYS_TR_PASSWORD}, }; #[test] fn test_constants_conversions() { let conversion_check = |esys_handle: ESYS_TR, object_handle: ObjectHandle, session_handle: SessionHandle| { assert_eq!(esys_handle, ESYS_TR::from(session_handle)); assert_eq!(session_handle, SessionHandle::from(esys_handle)); assert_eq!(object_handle, ObjectHandle::from(session_handle)); assert_eq!(session_handle, SessionHandle::from(object_handle)); }; conversion_check( ESYS_TR_PASSWORD, ObjectHandle::Password, SessionHandle::Password, ); conversion_check(ESYS_TR_NONE, ObjectHandle::None, SessionHandle::None); } tss-esapi-7.4.0/tests/integration_tests/handles_tests/tpm_handles_tests.rs000064400000000000000000000256471046102023000254170ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::{Into, TryFrom}; use tss_esapi::{ constants::tss::{ TPM2_AC_LAST, TPM2_HMAC_SESSION_LAST, TPM2_HT_AC, TPM2_HT_HMAC_SESSION, TPM2_HT_LOADED_SESSION, TPM2_HT_NV_INDEX, TPM2_HT_PCR, TPM2_HT_PERMANENT, TPM2_HT_PERSISTENT, TPM2_HT_POLICY_SESSION, TPM2_HT_SAVED_SESSION, TPM2_HT_TRANSIENT, TPM2_LOADED_SESSION_LAST, TPM2_NV_INDEX_LAST, TPM2_PCR_LAST, TPM2_PERMANENT_LAST, TPM2_PERSISTENT_LAST, TPM2_POLICY_SESSION_LAST, TPM2_TRANSIENT_LAST, }, handles::{ AttachedComponentTpmHandle, HmacSessionTpmHandle, LoadedSessionTpmHandle, NvIndexTpmHandle, PcrTpmHandle, PermanentTpmHandle, PersistentTpmHandle, PolicySessionTpmHandle, SavedSessionTpmHandle, TpmHandle, TransientTpmHandle, }, tss2_esys::TPM2_HANDLE, }; mod test_tpm_handles { use super::*; #[test] fn test_pcr_tpm_handle() { // Invalid (wrong type) let value_with_wrong_type: u32 = 0xFF000000; let _ = PcrTpmHandle::new(value_with_wrong_type).unwrap_err(); // Invalid (not in range) let value_not_in_range = TPM2_PCR_LAST + 1; let _ = PcrTpmHandle::new(value_not_in_range).unwrap_err(); // Valid let valid_value: u32 = TPM2_PCR_LAST; let _ = PcrTpmHandle::new(valid_value).unwrap(); } #[test] fn test_nv_index_tpm_handle() { // Invalid (wrong type) let value_with_wrong_type: u32 = 0xFF000000; let _ = NvIndexTpmHandle::new(value_with_wrong_type).unwrap_err(); // Invalid (not in range) let value_not_in_range = TPM2_NV_INDEX_LAST + 1; let _ = NvIndexTpmHandle::new(value_not_in_range).unwrap_err(); // Valid let valid_value: u32 = TPM2_NV_INDEX_LAST; let _ = NvIndexTpmHandle::new(valid_value).unwrap(); } #[test] fn test_hmac_session_tpm_handle() { // Invalid (wrong type) let value_with_wrong_type: u32 = 0xFF000000; let _ = HmacSessionTpmHandle::new(value_with_wrong_type).unwrap_err(); // Invalid (not in range) let value_not_in_range = TPM2_HMAC_SESSION_LAST + 1; let _ = HmacSessionTpmHandle::new(value_not_in_range).unwrap_err(); // Valid let valid_value: u32 = TPM2_HMAC_SESSION_LAST; let _ = HmacSessionTpmHandle::new(valid_value).unwrap(); } #[test] fn test_loaded_session_tpm_handle() { // Invalid (wrong type) let value_with_wrong_type: u32 = 0xFF000000; let _ = LoadedSessionTpmHandle::new(value_with_wrong_type).unwrap_err(); // Invalid (not in range) let value_not_in_range = TPM2_LOADED_SESSION_LAST + 1; let _ = LoadedSessionTpmHandle::new(value_not_in_range).unwrap_err(); // Valid let valid_value: u32 = TPM2_LOADED_SESSION_LAST; let _ = LoadedSessionTpmHandle::new(valid_value).unwrap(); } #[test] fn test_policy_session_tpm_handle() { // Invalid (wrong type) let value_with_wrong_type: u32 = 0xFF000000; let _ = PolicySessionTpmHandle::new(value_with_wrong_type).unwrap_err(); // Invalid (not in range) let value_not_in_range = TPM2_POLICY_SESSION_LAST + 1; let _ = PolicySessionTpmHandle::new(value_not_in_range).unwrap_err(); // Valid let valid_value: u32 = TPM2_POLICY_SESSION_LAST; let _ = PolicySessionTpmHandle::new(valid_value).unwrap(); } #[test] fn test_saved_session_tpm_handle() { // Invalid (wrong type) let value_with_wrong_type: u32 = 0xFF000000; let _ = SavedSessionTpmHandle::new(value_with_wrong_type).unwrap_err(); // Invalid (not in range) let value_not_in_range = TPM2_POLICY_SESSION_LAST + 1; let _ = SavedSessionTpmHandle::new(value_not_in_range).unwrap_err(); // Valid let valid_value: u32 = TPM2_POLICY_SESSION_LAST; let _ = SavedSessionTpmHandle::new(valid_value).unwrap(); } #[test] fn test_permanent_tpm_handle() { // Invalid (wrong type) let value_with_wrong_type: u32 = 0xFF000000; let _ = PermanentTpmHandle::new(value_with_wrong_type).unwrap_err(); // Invalid (not in range) let value_not_in_range = TPM2_PERMANENT_LAST + 1; let _ = PermanentTpmHandle::new(value_not_in_range).unwrap_err(); // Valid let valid_value: u32 = TPM2_PERMANENT_LAST; let _ = PermanentTpmHandle::new(valid_value).unwrap(); } #[test] fn test_transient_tpm_handle() { // Invalid (wrong type) let value_with_wrong_type: u32 = 0xFF000000; let _ = TransientTpmHandle::new(value_with_wrong_type).unwrap_err(); // Invalid (not in range) let value_not_in_range = TPM2_TRANSIENT_LAST + 1; let _ = TransientTpmHandle::new(value_not_in_range).unwrap_err(); // Valid let valid_value: u32 = TPM2_TRANSIENT_LAST; let _ = TransientTpmHandle::new(valid_value).unwrap(); } #[test] fn test_persistent_tpm_handle() { // Invalid (wrong type) let value_with_wrong_type: u32 = 0xFF000000; let _ = PersistentTpmHandle::new(value_with_wrong_type).unwrap_err(); // Invalid (not in range) let value_not_in_range = TPM2_PERSISTENT_LAST + 1; let _ = PersistentTpmHandle::new(value_not_in_range).unwrap_err(); // Valid let valid_value: u32 = TPM2_PERSISTENT_LAST; let _ = PersistentTpmHandle::new(valid_value).unwrap(); } #[test] fn test_ac_tpm_handle() { // Invalid (wrong type) let value_with_wrong_type: u32 = 0xFF000000; let _ = AttachedComponentTpmHandle::new(value_with_wrong_type).unwrap_err(); // Invalid (not in range) let value_not_in_range = TPM2_AC_LAST + 1; let _ = AttachedComponentTpmHandle::new(value_not_in_range).unwrap_err(); // Valid let valid_value: u32 = TPM2_AC_LAST; let _ = AttachedComponentTpmHandle::new(valid_value).unwrap(); } #[test] fn test_general_tpm_handle_from_tss_tpm_handle_conversion() { let invalid_value: TPM2_HANDLE = 0xFFFFFFFF; let _ = TpmHandle::try_from(invalid_value).unwrap_err(); assert_eq!( TpmHandle::try_from(TPM2_PCR_LAST).unwrap(), TpmHandle::Pcr(PcrTpmHandle::new(TPM2_PCR_LAST).unwrap()) ); assert_eq!( TpmHandle::try_from(TPM2_NV_INDEX_LAST).unwrap(), TpmHandle::NvIndex(NvIndexTpmHandle::new(TPM2_NV_INDEX_LAST).unwrap()) ); assert_eq!( TpmHandle::try_from(TPM2_HMAC_SESSION_LAST).unwrap(), TpmHandle::HmacSession(HmacSessionTpmHandle::new(TPM2_HMAC_SESSION_LAST).unwrap()) ); // TPM2_HT_LOADED_SESSION is the same as TPM2_HT_HMAC_SESSION assert_eq!( TpmHandle::try_from(TPM2_POLICY_SESSION_LAST).unwrap(), TpmHandle::PolicySession( PolicySessionTpmHandle::new(TPM2_POLICY_SESSION_LAST).unwrap() ) ); // TPM2_HT_SAVED_SESSION is the same as TPM2_HT_POLICY_SESSION assert_eq!( TpmHandle::try_from(TPM2_PERMANENT_LAST).unwrap(), TpmHandle::Permanent(PermanentTpmHandle::new(TPM2_PERMANENT_LAST).unwrap()) ); assert_eq!( TpmHandle::try_from(TPM2_TRANSIENT_LAST).unwrap(), TpmHandle::Transient(TransientTpmHandle::new(TPM2_TRANSIENT_LAST).unwrap()) ); assert_eq!( TpmHandle::try_from(TPM2_PERSISTENT_LAST).unwrap(), TpmHandle::Persistent(PersistentTpmHandle::new(TPM2_PERSISTENT_LAST).unwrap()) ); assert_eq!( TpmHandle::try_from(TPM2_AC_LAST).unwrap(), TpmHandle::AttachedComponent(AttachedComponentTpmHandle::new(TPM2_AC_LAST).unwrap()) ); } #[test] fn test_general_tpm_handle_to_tss_tpm_handle_conversion() { { let expected = u32::from_be_bytes([TPM2_HT_PCR, 0x00, 0x00, 0x01]); let tpm_handle = TpmHandle::Pcr(PcrTpmHandle::new(expected).unwrap()); let actual: TPM2_HANDLE = tpm_handle.into(); assert_eq!(expected, actual); } { let expected = u32::from_be_bytes([TPM2_HT_NV_INDEX, 0x00, 0x00, 0x01]); let tpm_handle = TpmHandle::NvIndex(NvIndexTpmHandle::new(expected).unwrap()); let actual: TPM2_HANDLE = tpm_handle.into(); assert_eq!(expected, actual); } { let expected = u32::from_be_bytes([TPM2_HT_HMAC_SESSION, 0x00, 0x00, 0x01]); let tpm_handle = TpmHandle::HmacSession(HmacSessionTpmHandle::new(expected).unwrap()); let actual: TPM2_HANDLE = tpm_handle.into(); assert_eq!(expected, actual); } { let expected = u32::from_be_bytes([TPM2_HT_LOADED_SESSION, 0x00, 0x00, 0x01]); let tpm_handle = TpmHandle::LoadedSession(LoadedSessionTpmHandle::new(expected).unwrap()); let actual: TPM2_HANDLE = tpm_handle.into(); assert_eq!(expected, actual); } { let expected = u32::from_be_bytes([TPM2_HT_POLICY_SESSION, 0x00, 0x00, 0x01]); let tpm_handle = TpmHandle::PolicySession(PolicySessionTpmHandle::new(expected).unwrap()); let actual: TPM2_HANDLE = tpm_handle.into(); assert_eq!(expected, actual); } { let expected = u32::from_be_bytes([TPM2_HT_SAVED_SESSION, 0x00, 0x00, 0x01]); let tpm_handle = TpmHandle::SavedSession(SavedSessionTpmHandle::new(expected).unwrap()); let actual: TPM2_HANDLE = tpm_handle.into(); assert_eq!(expected, actual); } { let expected = u32::from_be_bytes([TPM2_HT_PERMANENT, 0x00, 0x00, 0x01]); let tpm_handle = TpmHandle::Permanent(PermanentTpmHandle::new(expected).unwrap()); let actual: TPM2_HANDLE = tpm_handle.into(); assert_eq!(expected, actual); } { let expected = u32::from_be_bytes([TPM2_HT_TRANSIENT, 0x00, 0x00, 0x01]); let tpm_handle = TpmHandle::Transient(TransientTpmHandle::new(expected).unwrap()); let actual: TPM2_HANDLE = tpm_handle.into(); assert_eq!(expected, actual); } { let expected = u32::from_be_bytes([TPM2_HT_PERSISTENT, 0x00, 0x00, 0x01]); let tpm_handle = TpmHandle::Persistent(PersistentTpmHandle::new(expected).unwrap()); let actual: TPM2_HANDLE = tpm_handle.into(); assert_eq!(expected, actual); } { let expected = u32::from_be_bytes([TPM2_HT_AC, 0x00, 0x00, 0x01]); let tpm_handle = TpmHandle::AttachedComponent(AttachedComponentTpmHandle::new(expected).unwrap()); let actual: TPM2_HANDLE = tpm_handle.into(); assert_eq!(expected, actual); } } } tss-esapi-7.4.0/tests/integration_tests/interface_types_tests/algorithms_tests.rs000064400000000000000000000320131046102023000270210ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; macro_rules! test_conversion { ($tpm_alg_id:ident, $interface_type:ident::$interface_type_item:ident) => { assert_eq!( AlgorithmIdentifier::$interface_type_item, $interface_type::$interface_type_item.into() ); assert_eq!( $interface_type::try_from(AlgorithmIdentifier::$interface_type_item).expect(&format!( "Failed to parse from Algorithm for {}", stringify!($interface_type_item) )), $interface_type::$interface_type_item ); assert_eq!( $tpm_alg_id, AlgorithmIdentifier::from($interface_type::$interface_type_item).into() ); assert_eq!($tpm_alg_id, $interface_type::$interface_type_item.into()); assert_eq!( $interface_type::$interface_type_item, $interface_type::try_from($tpm_alg_id).expect(&format!( "Failed to parse from alg if for {}", stringify!($tpm_alg_id) )) ); }; } macro_rules! test_invalid_tpm_alg_conversion { ($invalid_tpm_alg_id:ident, $interface_type:ident, WrapperErrorKind::$expected_error:ident) => { assert_eq!( $interface_type::try_from(tss_esapi::constants::tss::$invalid_tpm_alg_id), Err(tss_esapi::Error::WrapperError( tss_esapi::WrapperErrorKind::$expected_error )), ); }; } macro_rules! test_invalid_algorithm_conversion { (AlgorithmIdentifier::$invalid_algorithm_item:ident, $interface_type:ident, WrapperErrorKind::$expected_error:ident) => { assert_eq!( $interface_type::try_from(AlgorithmIdentifier::$invalid_algorithm_item), Err(tss_esapi::Error::WrapperError( tss_esapi::WrapperErrorKind::$expected_error )), ) }; } mod hashing_algorithm_tests { use super::*; use tss_esapi::{ constants::{ tss::{ TPM2_ALG_NULL, TPM2_ALG_SHA1, TPM2_ALG_SHA256, TPM2_ALG_SHA384, TPM2_ALG_SHA3_256, TPM2_ALG_SHA3_384, TPM2_ALG_SHA3_512, TPM2_ALG_SHA512, TPM2_ALG_SM3_256, }, AlgorithmIdentifier, }, interface_types::algorithm::HashingAlgorithm, }; #[test] fn test_hashing_algorithm_conversion() { test_conversion!(TPM2_ALG_SHA1, HashingAlgorithm::Sha1); test_conversion!(TPM2_ALG_SHA256, HashingAlgorithm::Sha256); test_conversion!(TPM2_ALG_SHA384, HashingAlgorithm::Sha384); test_conversion!(TPM2_ALG_SHA512, HashingAlgorithm::Sha512); test_conversion!(TPM2_ALG_SM3_256, HashingAlgorithm::Sm3_256); test_conversion!(TPM2_ALG_SHA3_256, HashingAlgorithm::Sha3_256); test_conversion!(TPM2_ALG_SHA3_384, HashingAlgorithm::Sha3_384); test_conversion!(TPM2_ALG_SHA3_512, HashingAlgorithm::Sha3_512); test_conversion!(TPM2_ALG_NULL, HashingAlgorithm::Null); } #[test] fn test_conversion_of_incorrect_algorithm() { test_invalid_tpm_alg_conversion!( TPM2_ALG_RSA, HashingAlgorithm, WrapperErrorKind::InvalidParam ); test_invalid_algorithm_conversion!( AlgorithmIdentifier::Ecc, HashingAlgorithm, WrapperErrorKind::InvalidParam ) } } mod keyed_hash_scheme_tests { use super::*; use tss_esapi::{ constants::{ tss::{TPM2_ALG_HMAC, TPM2_ALG_NULL, TPM2_ALG_XOR}, AlgorithmIdentifier, }, interface_types::algorithm::KeyedHashSchemeAlgorithm, }; #[test] fn test_keyed_hash_scheme_conversion() { test_conversion!(TPM2_ALG_HMAC, KeyedHashSchemeAlgorithm::Hmac); test_conversion!(TPM2_ALG_XOR, KeyedHashSchemeAlgorithm::Xor); test_conversion!(TPM2_ALG_NULL, KeyedHashSchemeAlgorithm::Null); } #[test] fn test_conversion_of_incorrect_algorithm() { test_invalid_tpm_alg_conversion!( TPM2_ALG_RSA, KeyedHashSchemeAlgorithm, WrapperErrorKind::InvalidParam ); test_invalid_algorithm_conversion!( AlgorithmIdentifier::Ecc, KeyedHashSchemeAlgorithm, WrapperErrorKind::InvalidParam ) } } mod key_derivation_function_tests { use super::*; use tss_esapi::{ constants::{ tss::{TPM2_ALG_KDF1_SP800_108, TPM2_ALG_KDF1_SP800_56A, TPM2_ALG_KDF2, TPM2_ALG_MGF1}, AlgorithmIdentifier, }, interface_types::algorithm::KeyDerivationFunction, }; #[test] fn test_key_derivation_function_conversion() { test_conversion!( TPM2_ALG_KDF1_SP800_56A, KeyDerivationFunction::Kdf1Sp800_56a ); test_conversion!( TPM2_ALG_KDF1_SP800_108, KeyDerivationFunction::Kdf1Sp800_108 ); test_conversion!(TPM2_ALG_KDF2, KeyDerivationFunction::Kdf2); test_conversion!(TPM2_ALG_MGF1, KeyDerivationFunction::Mgf1); } #[test] fn test_conversion_of_incorrect_algorithm() { test_invalid_tpm_alg_conversion!( TPM2_ALG_RSA, KeyDerivationFunction, WrapperErrorKind::InvalidParam ); test_invalid_algorithm_conversion!( AlgorithmIdentifier::Ecc, KeyDerivationFunction, WrapperErrorKind::InvalidParam ) } } mod symmetric_algorithm_tests { use super::*; use tss_esapi::{ constants::{ tss::{ TPM2_ALG_AES, TPM2_ALG_CAMELLIA, TPM2_ALG_NULL, TPM2_ALG_SM4, TPM2_ALG_TDES, TPM2_ALG_XOR, }, AlgorithmIdentifier, }, interface_types::algorithm::SymmetricAlgorithm, }; #[test] fn test_symmetric_algorithm_conversion() { test_conversion!(TPM2_ALG_TDES, SymmetricAlgorithm::Tdes); test_conversion!(TPM2_ALG_AES, SymmetricAlgorithm::Aes); test_conversion!(TPM2_ALG_SM4, SymmetricAlgorithm::Sm4); test_conversion!(TPM2_ALG_CAMELLIA, SymmetricAlgorithm::Camellia); test_conversion!(TPM2_ALG_XOR, SymmetricAlgorithm::Xor); test_conversion!(TPM2_ALG_NULL, SymmetricAlgorithm::Null); } #[test] fn test_conversion_of_incorrect_algorithm() { test_invalid_tpm_alg_conversion!( TPM2_ALG_RSA, SymmetricAlgorithm, WrapperErrorKind::InvalidParam ); test_invalid_algorithm_conversion!( AlgorithmIdentifier::Ecc, SymmetricAlgorithm, WrapperErrorKind::InvalidParam ) } } mod symmetric_mode_tests { use super::*; use tss_esapi::{ constants::{ tss::{ TPM2_ALG_CBC, TPM2_ALG_CFB, TPM2_ALG_CTR, TPM2_ALG_ECB, TPM2_ALG_NULL, TPM2_ALG_OFB, }, AlgorithmIdentifier, }, interface_types::algorithm::SymmetricMode, }; #[test] fn test_symmetric_mode_conversion() { test_conversion!(TPM2_ALG_CTR, SymmetricMode::Ctr); test_conversion!(TPM2_ALG_OFB, SymmetricMode::Ofb); test_conversion!(TPM2_ALG_CBC, SymmetricMode::Cbc); test_conversion!(TPM2_ALG_CFB, SymmetricMode::Cfb); test_conversion!(TPM2_ALG_ECB, SymmetricMode::Ecb); test_conversion!(TPM2_ALG_NULL, SymmetricMode::Null); } #[test] fn test_conversion_of_incorrect_algorithm() { test_invalid_tpm_alg_conversion!( TPM2_ALG_RSA, SymmetricMode, WrapperErrorKind::InvalidParam ); test_invalid_algorithm_conversion!( AlgorithmIdentifier::Ecc, SymmetricMode, WrapperErrorKind::InvalidParam ) } } mod asymmetric_algorithm_tests { use super::*; use tss_esapi::{ constants::{ tss::{TPM2_ALG_ECC, TPM2_ALG_NULL, TPM2_ALG_RSA}, AlgorithmIdentifier, }, interface_types::algorithm::AsymmetricAlgorithm, }; #[test] fn test_asymmetric_algorithm_conversion() { test_conversion!(TPM2_ALG_RSA, AsymmetricAlgorithm::Rsa); test_conversion!(TPM2_ALG_ECC, AsymmetricAlgorithm::Ecc); test_conversion!(TPM2_ALG_NULL, AsymmetricAlgorithm::Null); } #[test] fn test_conversion_of_incorrect_algorithm() { test_invalid_tpm_alg_conversion!( TPM2_ALG_AES, AsymmetricAlgorithm, WrapperErrorKind::InvalidParam ); test_invalid_algorithm_conversion!( AlgorithmIdentifier::Sm4, AsymmetricAlgorithm, WrapperErrorKind::InvalidParam ) } } mod signature_scheme_tests { use super::*; use std::convert::TryInto; use tss_esapi::{ constants::{ tss::{ TPM2_ALG_ECDAA, TPM2_ALG_ECDSA, TPM2_ALG_ECSCHNORR, TPM2_ALG_HMAC, TPM2_ALG_NULL, TPM2_ALG_RSAPSS, TPM2_ALG_RSASSA, TPM2_ALG_SM2, }, AlgorithmIdentifier, }, interface_types::algorithm::{AsymmetricAlgorithm, SignatureSchemeAlgorithm}, }; #[test] fn test_signature_scheme_conversion() { test_conversion!(TPM2_ALG_RSASSA, SignatureSchemeAlgorithm::RsaSsa); test_conversion!(TPM2_ALG_RSAPSS, SignatureSchemeAlgorithm::RsaPss); test_conversion!(TPM2_ALG_ECDSA, SignatureSchemeAlgorithm::EcDsa); test_conversion!(TPM2_ALG_ECDAA, SignatureSchemeAlgorithm::EcDaa); test_conversion!(TPM2_ALG_SM2, SignatureSchemeAlgorithm::Sm2); test_conversion!(TPM2_ALG_ECSCHNORR, SignatureSchemeAlgorithm::EcSchnorr); test_conversion!(TPM2_ALG_HMAC, SignatureSchemeAlgorithm::Hmac); test_conversion!(TPM2_ALG_NULL, SignatureSchemeAlgorithm::Null); } #[test] fn test_special_conversion_into_asymmetric_algorithm() { assert_eq!( AsymmetricAlgorithm::Rsa, SignatureSchemeAlgorithm::RsaSsa .try_into() .expect("Failed to convert RsaSsa into asymmetric algorithm") ); assert_eq!( AsymmetricAlgorithm::Rsa, SignatureSchemeAlgorithm::RsaPss .try_into() .expect("Failed to convert RsaPss into asymmetric algorithm") ); assert_eq!( AsymmetricAlgorithm::Ecc, SignatureSchemeAlgorithm::EcDsa .try_into() .expect("Failed to convert EcDsa into asymmetric algorithm") ); assert_eq!( AsymmetricAlgorithm::Ecc, SignatureSchemeAlgorithm::EcDaa .try_into() .expect("Failed to convert EcDaa into asymmetric algorithm") ); assert_eq!( AsymmetricAlgorithm::Ecc, SignatureSchemeAlgorithm::Sm2 .try_into() .expect("Failed to convert Sm2 into asymmetric algorithm") ); assert_eq!( AsymmetricAlgorithm::Ecc, SignatureSchemeAlgorithm::EcSchnorr .try_into() .expect("Failed to convert EcSchnorr into asymmetric algorithm") ); if AsymmetricAlgorithm::try_from(SignatureSchemeAlgorithm::Hmac).is_ok() { panic!("It should not be possible to convert Hmac into an asymmetric algorithm"); } // TODO: Change this if Null should be able to be converted into // an asymmetric algorithm if AsymmetricAlgorithm::try_from(SignatureSchemeAlgorithm::Null).is_ok() { panic!("It should not be possible to convert Null into an asymmetric algorithm"); } } #[test] fn test_conversion_of_incorrect_algorithm() { test_invalid_tpm_alg_conversion!( TPM2_ALG_AES, AsymmetricAlgorithm, WrapperErrorKind::InvalidParam ); test_invalid_algorithm_conversion!( AlgorithmIdentifier::Sm4, AsymmetricAlgorithm, WrapperErrorKind::InvalidParam ) } } mod symmetric_object_tests { use super::*; use tss_esapi::{ constants::{ tss::{TPM2_ALG_AES, TPM2_ALG_CAMELLIA, TPM2_ALG_NULL, TPM2_ALG_SM4, TPM2_ALG_TDES}, AlgorithmIdentifier, }, interface_types::algorithm::SymmetricObject, }; #[test] fn test_symmetric_object_conversion() { test_conversion!(TPM2_ALG_TDES, SymmetricObject::Tdes); test_conversion!(TPM2_ALG_AES, SymmetricObject::Aes); test_conversion!(TPM2_ALG_SM4, SymmetricObject::Sm4); test_conversion!(TPM2_ALG_CAMELLIA, SymmetricObject::Camellia); test_conversion!(TPM2_ALG_NULL, SymmetricObject::Null); } #[test] fn test_conversion_of_incorrect_algorithm() { test_invalid_tpm_alg_conversion!( TPM2_ALG_RSA, SymmetricObject, WrapperErrorKind::InvalidParam ); test_invalid_algorithm_conversion!( AlgorithmIdentifier::Ecc, SymmetricObject, WrapperErrorKind::InvalidParam ) } } tss-esapi-7.4.0/tests/integration_tests/interface_types_tests/key_bits_tests.rs000064400000000000000000000123541046102023000264670ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 macro_rules! test_conversions { ($tss_ket_bits_interface_type:ident, $value:tt, $interface_type:ident::$interface_type_item:ident) => { assert_eq!( $value as $tss_ket_bits_interface_type, $interface_type::$interface_type_item.into() ); assert_eq!( $interface_type::try_from($value as $tss_ket_bits_interface_type).expect(&format!( "Failed to parse from a value {}", $value as $tss_ket_bits_interface_type )), $interface_type::$interface_type_item, ); }; } macro_rules! test_invalid_conversions { ($tss_ket_bits_interface_type:ident, $value:tt, $interface_type:ident, WrapperErrorKind::$expected_error:ident) => { assert_eq!( $interface_type::try_from($value as $tss_ket_bits_interface_type), Err(tss_esapi::Error::WrapperError( tss_esapi::WrapperErrorKind::$expected_error )), ); }; } mod aes_key_bits_tests { use std::convert::TryFrom; use tss_esapi::{interface_types::key_bits::AesKeyBits, tss2_esys::TPMI_AES_KEY_BITS}; #[test] fn test_valid_conversions() { test_conversions!(TPMI_AES_KEY_BITS, 128, AesKeyBits::Aes128); test_conversions!(TPMI_AES_KEY_BITS, 192, AesKeyBits::Aes192); test_conversions!(TPMI_AES_KEY_BITS, 256, AesKeyBits::Aes256); } #[test] fn test_invalid_conversions() { test_invalid_conversions!( TPMI_AES_KEY_BITS, 0, AesKeyBits, WrapperErrorKind::InvalidParam ); test_invalid_conversions!( TPMI_AES_KEY_BITS, 129, AesKeyBits, WrapperErrorKind::InvalidParam ); test_invalid_conversions!( TPMI_AES_KEY_BITS, 193, AesKeyBits, WrapperErrorKind::InvalidParam ); test_invalid_conversions!( TPMI_AES_KEY_BITS, 257, AesKeyBits, WrapperErrorKind::InvalidParam ); } } mod sm4_key_bits_tests { use std::convert::TryFrom; use tss_esapi::{interface_types::key_bits::Sm4KeyBits, tss2_esys::TPMI_SM4_KEY_BITS}; #[test] fn test_valid_conversions() { test_conversions!(TPMI_SM4_KEY_BITS, 128, Sm4KeyBits::Sm4_128); } #[test] fn test_invalid_conversions() { test_invalid_conversions!( TPMI_SM4_KEY_BITS, 0, Sm4KeyBits, WrapperErrorKind::InvalidParam ); test_invalid_conversions!( TPMI_SM4_KEY_BITS, 129, Sm4KeyBits, WrapperErrorKind::InvalidParam ); } } mod camellia_key_bits_tests { use std::convert::TryFrom; use tss_esapi::{interface_types::key_bits::CamelliaKeyBits, tss2_esys::TPM2_KEY_BITS}; #[test] fn test_valid_conversions() { test_conversions!(TPM2_KEY_BITS, 128, CamelliaKeyBits::Camellia128); test_conversions!(TPM2_KEY_BITS, 192, CamelliaKeyBits::Camellia192); test_conversions!(TPM2_KEY_BITS, 256, CamelliaKeyBits::Camellia256); } #[test] fn test_invalid_conversions() { test_invalid_conversions!( TPM2_KEY_BITS, 0, CamelliaKeyBits, WrapperErrorKind::InvalidParam ); test_invalid_conversions!( TPM2_KEY_BITS, 129, CamelliaKeyBits, WrapperErrorKind::InvalidParam ); test_invalid_conversions!( TPM2_KEY_BITS, 193, CamelliaKeyBits, WrapperErrorKind::InvalidParam ); test_invalid_conversions!( TPM2_KEY_BITS, 257, CamelliaKeyBits, WrapperErrorKind::InvalidParam ); } } mod rsa_key_bits_tests { use std::convert::TryFrom; use tss_esapi::{interface_types::key_bits::RsaKeyBits, tss2_esys::TPMI_RSA_KEY_BITS}; #[test] fn test_valid_conversions() { test_conversions!(TPMI_RSA_KEY_BITS, 1024, RsaKeyBits::Rsa1024); test_conversions!(TPMI_RSA_KEY_BITS, 2048, RsaKeyBits::Rsa2048); test_conversions!(TPMI_RSA_KEY_BITS, 3072, RsaKeyBits::Rsa3072); test_conversions!(TPMI_RSA_KEY_BITS, 4096, RsaKeyBits::Rsa4096); } #[test] fn test_invalid_conversions() { test_invalid_conversions!( TPMI_RSA_KEY_BITS, 0, RsaKeyBits, WrapperErrorKind::InvalidParam ); test_invalid_conversions!( TPMI_RSA_KEY_BITS, 1025, RsaKeyBits, WrapperErrorKind::InvalidParam ); test_invalid_conversions!( TPMI_RSA_KEY_BITS, 2049, RsaKeyBits, WrapperErrorKind::InvalidParam ); test_invalid_conversions!( TPMI_RSA_KEY_BITS, 2073, RsaKeyBits, WrapperErrorKind::InvalidParam ); test_invalid_conversions!( TPMI_RSA_KEY_BITS, 4097, RsaKeyBits, WrapperErrorKind::InvalidParam ); } } tss-esapi-7.4.0/tests/integration_tests/interface_types_tests/mod.rs000064400000000000000000000003171046102023000242070ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod algorithms_tests; mod key_bits_tests; mod resource_handles_tests; mod structure_tags_tests; mod yes_no_tests; tss-esapi-7.4.0/tests/integration_tests/interface_types_tests/resource_handles_tests.rs000064400000000000000000000242771046102023000302120ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; use tss_esapi::{ handles::{AuthHandle, NvIndexHandle, ObjectHandle, PermanentTpmHandle, TpmHandle}, interface_types::resource_handles::{ Clear, Enables, Endorsement, Hierarchy, HierarchyAuth, Lockout, NvAuth, Owner, Platform, Provision, }, tss2_esys::ESYS_TR, }; mod test_hierarchy { use super::*; #[test] fn test_conversions() { let test_conversion = |hierarchy: Hierarchy, tpm_rh: TpmHandle, esys_rh: ObjectHandle, name: &str| { assert_eq!(ObjectHandle::from(hierarchy), esys_rh); assert_eq!(TpmHandle::from(hierarchy), tpm_rh); let from_esys_rh = Hierarchy::try_from(esys_rh).unwrap_or_else(|_| { panic!("Failed to create Hierarchy from ESYS_TR_RH={}", name) }); assert_eq!(from_esys_rh, hierarchy); assert_eq!(ObjectHandle::from(from_esys_rh), esys_rh); assert_eq!(TpmHandle::from(from_esys_rh), tpm_rh); let from_tpm_rh = Hierarchy::try_from(tpm_rh) .unwrap_or_else(|_| panic!("Failed to create Hierarchy from TPM2_RH={}", name)); assert_eq!(from_tpm_rh, hierarchy); assert_eq!(ObjectHandle::from(from_tpm_rh), esys_rh); assert_eq!(TpmHandle::from(from_tpm_rh), tpm_rh); }; test_conversion( Hierarchy::Owner, TpmHandle::Permanent(PermanentTpmHandle::Owner), ObjectHandle::Owner, "OWNER", ); test_conversion( Hierarchy::Platform, TpmHandle::Permanent(PermanentTpmHandle::Platform), ObjectHandle::Platform, "PLATFORM", ); test_conversion( Hierarchy::Endorsement, TpmHandle::Permanent(PermanentTpmHandle::Endorsement), ObjectHandle::Endorsement, "ENDORSEMENT", ); test_conversion( Hierarchy::Null, TpmHandle::Permanent(PermanentTpmHandle::Null), ObjectHandle::Null, "NULL", ); } } mod test_enables { use super::*; #[test] fn test_conversions() { let test_conversion = |enables: Enables, tpm_rh: TpmHandle, esys_rh: ObjectHandle, name: &str| { assert_eq!(ObjectHandle::from(enables), esys_rh); assert_eq!(TpmHandle::from(enables), tpm_rh); let from_esys_rh = Enables::try_from(esys_rh).unwrap_or_else(|_| { panic!("Failed to create Enables from ESYS_TR_RH={}", name) }); assert_eq!(from_esys_rh, enables); assert_eq!(ObjectHandle::from(from_esys_rh), esys_rh); assert_eq!(TpmHandle::from(from_esys_rh), tpm_rh); let from_tpm_rh = Enables::try_from(tpm_rh) .unwrap_or_else(|_| panic!("Failed to create Enables from TPM2_RH={}", name)); assert_eq!(from_tpm_rh, enables); assert_eq!(ObjectHandle::from(from_tpm_rh), esys_rh); assert_eq!(TpmHandle::from(from_tpm_rh), tpm_rh); }; test_conversion( Enables::Owner, TpmHandle::Permanent(PermanentTpmHandle::Owner), ObjectHandle::Owner, "OWNER", ); test_conversion( Enables::Platform, TpmHandle::Permanent(PermanentTpmHandle::Platform), ObjectHandle::Platform, "PLATFORM", ); test_conversion( Enables::Endorsement, TpmHandle::Permanent(PermanentTpmHandle::Endorsement), ObjectHandle::Endorsement, "ENDORSEMENT", ); test_conversion( Enables::Endorsement, TpmHandle::Permanent(PermanentTpmHandle::Endorsement), ObjectHandle::Endorsement, "PLATFORM_NV", ); test_conversion( Enables::Null, TpmHandle::Permanent(PermanentTpmHandle::Null), ObjectHandle::Null, "NULL", ); } } mod test_hierarchy_auth { use super::*; #[test] fn test_conversions() { let test_conversion = |hierarchy_auth: HierarchyAuth, tpm_rh: TpmHandle, esys_rh: ObjectHandle, name: &str| { assert_eq!(ObjectHandle::from(hierarchy_auth), esys_rh); assert_eq!(TpmHandle::from(hierarchy_auth), tpm_rh); let from_esys_rh = HierarchyAuth::try_from(esys_rh).unwrap_or_else(|_| { panic!("Failed to create HierarchyAuth from ESYS_TR_RH={}", name) }); assert_eq!(from_esys_rh, hierarchy_auth); assert_eq!(ObjectHandle::from(from_esys_rh), esys_rh); assert_eq!(TpmHandle::from(from_esys_rh), tpm_rh); let from_tpm_rh = HierarchyAuth::try_from(tpm_rh) .unwrap_or_else(|_| panic!("Failed to create HierarchyAuth from TPM2_RH={}", name)); assert_eq!(from_tpm_rh, hierarchy_auth); assert_eq!(ObjectHandle::from(from_tpm_rh), esys_rh); assert_eq!(TpmHandle::from(from_tpm_rh), tpm_rh); }; test_conversion( HierarchyAuth::Owner, TpmHandle::Permanent(PermanentTpmHandle::Owner), ObjectHandle::Owner, "OWNER", ); test_conversion( HierarchyAuth::Platform, TpmHandle::Permanent(PermanentTpmHandle::Platform), ObjectHandle::Platform, "PLATFORM", ); test_conversion( HierarchyAuth::Endorsement, TpmHandle::Permanent(PermanentTpmHandle::Endorsement), ObjectHandle::Endorsement, "ENDORSEMENT", ); test_conversion( HierarchyAuth::Lockout, TpmHandle::Permanent(PermanentTpmHandle::Lockout), ObjectHandle::Lockout, "LOCKOUT", ); } } mod test_platform { use super::*; #[test] fn test_conversions() { assert_eq!(AuthHandle::from(Platform::Platform), AuthHandle::Platform); assert_eq!( Platform::try_from(AuthHandle::Platform) .expect("Failed to convert AuthHandle into Platform"), Platform::Platform ); } } mod test_owner { use super::*; #[test] fn test_conversions() { assert_eq!(ObjectHandle::from(Owner::Owner), ObjectHandle::Owner); assert_eq!(ObjectHandle::from(Owner::Null), ObjectHandle::Null); assert_eq!( Owner::try_from(ObjectHandle::Owner) .expect("Failed to convert TpmConstantHandle into Owner"), Owner::Owner ); assert_eq!( Owner::try_from(ObjectHandle::Null) .expect("Failed to convert TpmConstantHandle into Owner"), Owner::Null ); } } mod test_endorsement { use super::*; #[test] fn test_conversions() { assert_eq!( ObjectHandle::from(Endorsement::Endorsement), ObjectHandle::Endorsement ); assert_eq!(ObjectHandle::from(Endorsement::Null), ObjectHandle::Null); assert_eq!( Endorsement::try_from(ObjectHandle::Endorsement) .expect("Failed to convert TpmConstantHandle into Endorsement"), Endorsement::Endorsement ); assert_eq!( Endorsement::try_from(ObjectHandle::Null) .expect("Failed to convert TpmConstantHandle into Endorsement"), Endorsement::Null ); } } mod test_provision { use super::*; #[test] fn test_conversions() { assert_eq!(AuthHandle::from(Provision::Owner), AuthHandle::Owner); assert_eq!(AuthHandle::from(Provision::Platform), AuthHandle::Platform); assert_eq!( Provision::try_from(AuthHandle::Owner) .expect("Failed to convert AuthHandle into Provision"), Provision::Owner ); assert_eq!( Provision::try_from(AuthHandle::Platform) .expect("Failed to convert AuthHandle into Provision"), Provision::Platform ); } } mod test_clear { use super::*; #[test] fn test_conversions() { assert_eq!(AuthHandle::from(Clear::Owner), AuthHandle::Owner); assert_eq!(AuthHandle::from(Clear::Platform), AuthHandle::Platform); assert_eq!( Clear::try_from(AuthHandle::Owner).expect("Failed to convert AuthHandle into Clear"), Clear::Owner ); assert_eq!( Clear::try_from(AuthHandle::Platform) .expect("Failed to convert AuthHandle into Provision"), Clear::Platform ); } } mod test_nv_auth { use super::*; #[test] fn test_conversions() { assert_eq!(AuthHandle::from(NvAuth::Platform), AuthHandle::Platform); assert_eq!(AuthHandle::from(NvAuth::Owner), AuthHandle::Owner); let esys_handle: ESYS_TR = 0x12345678; let nv_index_handle = NvIndexHandle::from(esys_handle); assert_eq!( AuthHandle::from(NvAuth::NvIndex(nv_index_handle)), AuthHandle::from(esys_handle) ); assert_eq!( NvAuth::try_from(AuthHandle::Platform) .expect("Failed to convert AuthHandle into NvAuth"), NvAuth::Platform ); assert_eq!( NvAuth::try_from(AuthHandle::Owner).expect("Failed to convert AuthHandle into NvAuth"), NvAuth::Owner ); assert_eq!( NvAuth::try_from(AuthHandle::from(esys_handle)) .expect("Failed to convert AuthHandle into NvAuth"), NvAuth::NvIndex(nv_index_handle) ); } } mod test_lockout { use super::*; #[test] fn test_conversions() { assert_eq!(ObjectHandle::from(Lockout::Lockout), ObjectHandle::Lockout); assert_eq!( Lockout::try_from(ObjectHandle::Lockout) .expect("Failed to convert TpmConstantHandle into Lockout"), Lockout::Lockout ); } } tss-esapi-7.4.0/tests/integration_tests/interface_types_tests/structure_tags_tests.rs000064400000000000000000000045111046102023000277300ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 macro_rules! test_valid_conversions { (AttestationType::$attestation_type_item:ident, StructureTag::$strucutre_tag_item:ident) => { assert_eq!( AttestationType::$attestation_type_item, AttestationType::try_from(StructureTag::$strucutre_tag_item).expect(&format!( "Could not convert StructureTag {}", stringify!($attestation_type_item) )), "StructureTag {} did not convert to the correct AttestationType {}", stringify!($strucutre_tag_item), stringify!($attestation_type_item), ); assert_eq!( StructureTag::$strucutre_tag_item, StructureTag::from(AttestationType::$attestation_type_item), "AttestationType {} did not convert to the correct StructureTag {}", stringify!($attestation_type_item), stringify!($strucutre_tag_item), ); }; } mod attestation_type_tests { use std::convert::TryFrom; use tss_esapi::{ constants::StructureTag, interface_types::structure_tags::AttestationType, Error, WrapperErrorKind, }; #[test] fn test_conversions() { test_valid_conversions!(AttestationType::Certify, StructureTag::AttestCertify); test_valid_conversions!(AttestationType::Quote, StructureTag::AttestQuote); test_valid_conversions!( AttestationType::SessionAudit, StructureTag::AttestSessionAudit ); test_valid_conversions!( AttestationType::CommandAudit, StructureTag::AttestCommandAudit ); test_valid_conversions!(AttestationType::Time, StructureTag::AttestTime); test_valid_conversions!(AttestationType::Creation, StructureTag::AttestCreation); test_valid_conversions!(AttestationType::Nv, StructureTag::AttestNv); test_valid_conversions!(AttestationType::NvDigest, StructureTag::AttestNvDigest); } #[test] fn test_invalid_conversions() { assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), AttestationType::try_from(StructureTag::FuManifest), "Expected an error when converting StructureTag FuManifest into AttestationType", ) } } tss-esapi-7.4.0/tests/integration_tests/interface_types_tests/yes_no_tests.rs000064400000000000000000000027561046102023000261570ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; use tss_esapi::{interface_types::YesNo, tss2_esys::TPMI_YES_NO, Error, WrapperErrorKind}; #[test] fn test_conversions() { let expected_yes_value: TPMI_YES_NO = 1; let expected_no_value: TPMI_YES_NO = 0; assert_eq!( expected_yes_value, TPMI_YES_NO::from(YesNo::Yes), "Yes did not convert to the correct value '{}'", expected_yes_value, ); assert_eq!( expected_no_value, TPMI_YES_NO::from(YesNo::No), "No did not convert to the correct value '{}'", expected_no_value, ); assert_eq!( YesNo::Yes, YesNo::try_from(1).expect("Failed to convert interface type to enum for Yes"), "'1' did not convert to the correct value Yes" ); assert_eq!( YesNo::No, YesNo::try_from(0).expect("Failed to convert interface type to enum for No"), "'0' did not convert to the correct value No" ); assert!( bool::from(YesNo::Yes), "Yes did not convert to the correct boolean value 'true'" ); assert!( !bool::from(YesNo::No), "No did not convert to the correct boolean value 'false'" ); } #[test] fn test_invalid_conversions() { assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), YesNo::try_from(100), "Conversion of invalid value did not result in expected result" ); } tss-esapi-7.4.0/tests/integration_tests/main.rs000064400000000000000000000005021046102023000177420ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 #[path = "common/mod.rs"] mod common; mod abstraction_tests; mod attributes_tests; mod constants_tests; mod context_tests; mod handles_tests; mod interface_types_tests; mod structures_tests; mod tcti_ldr_tests; mod utils_tests; tss-esapi-7.4.0/tests/integration_tests/structures_tests/algorithm_property_tests.rs000064400000000000000000000042431046102023000276450ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryInto; use tss_esapi::{ attributes::AlgorithmAttributes, constants::AlgorithmIdentifier, structures::AlgorithmProperty, tss2_esys::TPMS_ALG_PROPERTY, }; #[test] fn test_new() { let expected_algorithm_identifier = AlgorithmIdentifier::Rsa; let expected_algorithm_properties = AlgorithmAttributes(0x1); let algorithm_proprty = AlgorithmProperty::new(expected_algorithm_identifier, expected_algorithm_properties); assert_eq!( expected_algorithm_identifier, algorithm_proprty.algorithm_identifier(), "AlgorithmProperty, created with new, did not contain expected algorithm identifier value" ); assert_eq!( expected_algorithm_properties, algorithm_proprty.algorithm_properties(), "AlgorithmProperty, created with new, did not contain expected algorithm properties value" ); } #[test] fn test_conversions() { let expected_algorithm_identifier = AlgorithmIdentifier::Rsa; let expected_algorithm_properties = AlgorithmAttributes(0x1); let expected_tpms_algorithm_property = TPMS_ALG_PROPERTY { alg: expected_algorithm_identifier.into(), algProperties: expected_algorithm_properties.into(), }; let algorithm_property: AlgorithmProperty = expected_tpms_algorithm_property .try_into() .expect("Failed to convert TPMS_ALG_PROPERTY into AlgorithmProperty"); assert_eq!( expected_algorithm_identifier, algorithm_property.algorithm_identifier(), "AlgorithmProperty, converted from TPMS_ALG_PROPERTY, did not contain the expected algorithm identifier value" ); assert_eq!( expected_algorithm_properties, algorithm_property.algorithm_properties(), "AlgorithmProperty, converted from TPMS_ALG_PROPERTY, did not contain the expected algorithm properties value" ); let actual_tpms_algorithm_property: TPMS_ALG_PROPERTY = algorithm_property.into(); crate::common::ensure_tpms_alg_property_equality( &expected_tpms_algorithm_property, &actual_tpms_algorithm_property, ); } tss-esapi-7.4.0/tests/integration_tests/structures_tests/attest_info_test.rs000064400000000000000000000152421046102023000260500ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use tss_esapi::{ constants::AlgorithmIdentifier, interface_types::{algorithm::HashingAlgorithm, YesNo}, structures::{AttestInfo, Digest, MaxNvBuffer, Name, PcrSelectionListBuilder, PcrSlot}, tss2_esys::{ TPMS_CERTIFY_INFO, TPMS_CLOCK_INFO, TPMS_COMMAND_AUDIT_INFO, TPMS_CREATION_INFO, TPMS_NV_CERTIFY_INFO, TPMS_QUOTE_INFO, TPMS_SESSION_AUDIT_INFO, TPMS_TIME_ATTEST_INFO, TPMS_TIME_INFO, TPMU_ATTEST, }, }; use std::convert::{TryFrom, TryInto}; #[test] fn test_certify_into_tpm_type_conversions() { let expected_tpms_certify_info = TPMS_CERTIFY_INFO { name: Name::try_from(vec![0xffu8; 64]) .expect("Failed to create name") .try_into() .expect("Failed to convert name to tss type"), qualifiedName: Name::try_from(vec![0x0fu8; 64]) .expect("Failed to create qualified name") .try_into() .expect("failed to convert qualified name to tss type"), }; let tpmu_attest: TPMU_ATTEST = AttestInfo::Certify { info: expected_tpms_certify_info .try_into() .expect("Failed to convert TPMS_CERTIFY_INFO to certifyInfo"), } .into(); let actual_tpms_certify_info = unsafe { &tpmu_attest.certify }; crate::common::ensure_tpms_certify_info_equality( &expected_tpms_certify_info, actual_tpms_certify_info, ); } #[test] fn test_quote_into_tpm_type_conversions() { let expected_tpms_quote_info = TPMS_QUOTE_INFO { pcrSelect: PcrSelectionListBuilder::new() .with_selection( HashingAlgorithm::Sha256, &[ PcrSlot::Slot1, PcrSlot::Slot2, PcrSlot::Slot3, PcrSlot::Slot4, ], ) .build() .expect("Failed to createm PcrSelectionList") .into(), pcrDigest: Digest::try_from(vec![0xffu8; 32]) .expect("Failed to create digest") .into(), }; let tpmu_attest: TPMU_ATTEST = AttestInfo::Quote { info: expected_tpms_quote_info .try_into() .expect("Failed to create QuoteInfo from TPMS_QUOTE_INFO"), } .into(); let actual_tpms_quote_info = unsafe { &tpmu_attest.quote }; crate::common::ensure_tpms_quote_info_equality( &expected_tpms_quote_info, actual_tpms_quote_info, ); } #[test] fn test_session_audit_into_tpm_type_conversions() { let expected_tpms_session_audit_info = TPMS_SESSION_AUDIT_INFO { exclusiveSession: YesNo::Yes.into(), sessionDigest: Digest::try_from(vec![0xffu8; 32]) .expect("Failed to session digest") .into(), }; let tpmu_attest: TPMU_ATTEST = AttestInfo::SessionAudit { info: expected_tpms_session_audit_info .try_into() .expect("Unable to convert TPMS_SESSION_AUDIT_INFO into SessionAuditInfo"), } .into(); let actual_tpms_session_audit = unsafe { &tpmu_attest.sessionAudit }; crate::common::ensure_tpms_session_audit_info_equality( &expected_tpms_session_audit_info, actual_tpms_session_audit, ); } #[test] fn test_command_audit_into_tpm_type_conversions() { let expected_tpms_command_audit_info = TPMS_COMMAND_AUDIT_INFO { auditCounter: 1u64, digestAlg: AlgorithmIdentifier::from(HashingAlgorithm::Sha512).into(), auditDigest: Digest::try_from(vec![0xffu8; 32]) .expect("Failed to create audit digest") .into(), commandDigest: Digest::try_from(vec![0xf0u8; 32]) .expect("Failed to create command digest") .into(), }; let tpmu_attest: TPMU_ATTEST = AttestInfo::CommandAudit { info: expected_tpms_command_audit_info .try_into() .expect("Unable to convert TPMS_SESSION_AUDIT_INFO into SessionAuditInfo"), } .into(); let actual_tpms_command_audit = unsafe { &tpmu_attest.commandAudit }; crate::common::ensure_tpms_command_audit_info_equality( &expected_tpms_command_audit_info, actual_tpms_command_audit, ); } #[test] fn test_time_into_tpm_type_conversions() { let expected_tpms_time_attest_info = TPMS_TIME_ATTEST_INFO { time: TPMS_TIME_INFO { time: 12u64, clockInfo: TPMS_CLOCK_INFO { clock: 1u64, resetCount: 2u32, restartCount: 3u32, safe: YesNo::Yes.into(), }, }, firmwareVersion: 0xfffffu64, }; let tpmu_attest: TPMU_ATTEST = AttestInfo::Time { info: expected_tpms_time_attest_info .try_into() .expect("Unable to convert TPMS_TIME_ATTEST_INFO into TimeAttestInfo"), } .into(); let actual_tpms_time_attest_info = unsafe { &tpmu_attest.time }; crate::common::ensure_tpms_time_attest_info_equality( &expected_tpms_time_attest_info, actual_tpms_time_attest_info, ); } #[test] fn test_creation_into_tpm_type_conversions() { let expected_tpms_creation_info = TPMS_CREATION_INFO { objectName: Name::try_from(vec![0xf0u8; 68]) .expect("Failed to create object name") .into(), creationHash: Digest::try_from(vec![0xffu8; 32]) .expect("Failed to create creation digest") .into(), }; let tpmu_attest: TPMU_ATTEST = AttestInfo::Creation { info: expected_tpms_creation_info .try_into() .expect("Failed to convert TPMS_CREATION_INFO into CreationInfo"), } .into(); let actual_tpms_creation_info = unsafe { &tpmu_attest.creation }; crate::common::ensure_tpms_creation_info_equality( &expected_tpms_creation_info, actual_tpms_creation_info, ); } #[test] fn test_nv_into_tpm_type_conversions() { let expected_tpms_nv_certify_info = TPMS_NV_CERTIFY_INFO { indexName: Name::try_from(vec![0xf0u8; 68]) .expect("Failed to create index name") .into(), offset: 12u16, nvContents: MaxNvBuffer::try_from(vec![0xfc; 2048]) .expect("Failed to create nv contents") .into(), }; let tpmu_attest: TPMU_ATTEST = AttestInfo::Nv { info: expected_tpms_nv_certify_info .try_into() .expect("Failed to convert TPMS_NV_CERTIFY_INFO into NvCertifyInfo"), } .into(); let actual_tpms_nv_certify_info = unsafe { &tpmu_attest.nv }; crate::common::ensure_tpms_nv_certify_info_equality( &expected_tpms_nv_certify_info, actual_tpms_nv_certify_info, ); } tss-esapi-7.4.0/tests/integration_tests/structures_tests/attest_tests.rs000064400000000000000000000421301046102023000252140ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use tss_esapi::{ constants::{tss::TPM2_GENERATED_VALUE, AlgorithmIdentifier}, interface_types::{algorithm::HashingAlgorithm, structure_tags::AttestationType, YesNo}, structures::{ Attest, AttestInfo, ClockInfo, Data, Digest, MaxNvBuffer, Name, PcrSelectionListBuilder, PcrSlot, TimeAttestInfo, }, traits::{Marshall, UnMarshall}, tss2_esys::{ TPMS_ATTEST, TPMS_CERTIFY_INFO, TPMS_CLOCK_INFO, TPMS_COMMAND_AUDIT_INFO, TPMS_CREATION_INFO, TPMS_NV_CERTIFY_INFO, TPMS_QUOTE_INFO, TPMS_SESSION_AUDIT_INFO, TPMS_TIME_ATTEST_INFO, TPMS_TIME_INFO, }, }; use std::convert::{TryFrom, TryInto}; #[test] fn test_attest_with_certify_info_into_tpm_type_conversions() { let expected_certify_info_name = Name::try_from(vec![0xffu8; 64]).expect("Failed to create name"); let expected_certify_info_qualified_name = Name::try_from(vec![0x0fu8; 64]).expect("Failed to create qualified name"); let expected_attest_info = AttestInfo::Certify { info: TPMS_CERTIFY_INFO { name: expected_certify_info_name .clone() .try_into() .expect("Failed to convert name to tss type"), qualifiedName: expected_certify_info_qualified_name .clone() .try_into() .expect("failed to convert qualified name to tss type"), } .try_into() .expect("Failed to convert TPMS_CERTIFY_INFO to CertifyInfo"), }; let (attest, expected_tpms_attest) = create_validated_test_parameters(expected_attest_info, AttestationType::Certify); if let AttestInfo::Certify { info } = attest.attested() { assert_eq!( &expected_certify_info_name, info.name(), "CertifyInfo did not contain expected name", ); assert_eq!( &expected_certify_info_qualified_name, info.qualified_name(), "CertifyInfo did not contain expected qualified name", ); } else { panic!("Converted Attest did not contain expected value for 'attest info'"); } let actual_tpms_attest: TPMS_ATTEST = attest.into(); crate::common::ensure_tpms_attest_equality(&expected_tpms_attest, &actual_tpms_attest); } #[test] fn test_attest_with_quote_info_into_tpm_type_conversions() { let expected_pcr_selection = PcrSelectionListBuilder::new() .with_selection( HashingAlgorithm::Sha256, &[ PcrSlot::Slot1, PcrSlot::Slot2, PcrSlot::Slot3, PcrSlot::Slot4, ], ) .build() .expect("Failed to createm PcrSelectionList"); let expected_pcr_digest = Digest::try_from(vec![0xffu8; 32]).expect("Failed to create digest"); let expected_attest_info = AttestInfo::Quote { info: TPMS_QUOTE_INFO { pcrSelect: expected_pcr_selection.clone().into(), pcrDigest: expected_pcr_digest.clone().into(), } .try_into() .expect("Failed to convert TPMS_QUOTE_INFO to QuoteInfo"), }; let (attest, expected_tpms_attest) = create_validated_test_parameters(expected_attest_info, AttestationType::Quote); if let AttestInfo::Quote { info } = attest.attested() { assert_eq!( &expected_pcr_selection, info.pcr_selection(), "QuoteInfo did not contain expected pcr selection", ); assert_eq!( &expected_pcr_digest, info.pcr_digest(), "QuoteInfo did not contain expected pcr digest", ); } else { panic!("Converted Attest did not contain expected value for 'attest info'"); } let actual_tpms_attest: TPMS_ATTEST = attest.into(); crate::common::ensure_tpms_attest_equality(&expected_tpms_attest, &actual_tpms_attest); } #[test] fn test_attest_with_session_audit_info_into_tpm_type_conversions() { let expected_exclusive_session = YesNo::Yes; let expected_session_digest = Digest::try_from(vec![0xffu8; 32]).expect("Failed to session digest"); let expected_attest_info = AttestInfo::SessionAudit { info: TPMS_SESSION_AUDIT_INFO { exclusiveSession: expected_exclusive_session.into(), sessionDigest: expected_session_digest.clone().into(), } .try_into() .expect("Failed to convert TPMS_SESSION_AUDIT_INFO to SessionAuditInfo"), }; let (attest, expected_tpms_attest) = create_validated_test_parameters(expected_attest_info, AttestationType::SessionAudit); if let AttestInfo::SessionAudit { info } = attest.attested() { assert_eq!( expected_exclusive_session, info.exlusive_session().into(), "SessionAuditInfo did not contain expected exclusive session", ); assert_eq!( &expected_session_digest, info.session_digest(), "SessionAuditInfo did not contain expected session digest", ); } else { panic!("Converted Attest did not contain expected value for 'attest info'"); } let actual_tpms_attest: TPMS_ATTEST = attest.into(); crate::common::ensure_tpms_attest_equality(&expected_tpms_attest, &actual_tpms_attest); } #[test] fn test_attest_with_command_audit_info_into_tpm_type_conversions() { let expected_audit_counter = 1u64; let expected_digest_alg = HashingAlgorithm::Sha512; let expected_audit_digest = Digest::try_from(vec![0xffu8; 32]).expect("Failed to create audit digest"); let expected_command_digest = Digest::try_from(vec![0xf0u8; 32]).expect("Failed to create command digest"); let expected_attest_info = AttestInfo::CommandAudit { info: TPMS_COMMAND_AUDIT_INFO { auditCounter: expected_audit_counter, digestAlg: AlgorithmIdentifier::from(expected_digest_alg).into(), auditDigest: expected_audit_digest.clone().into(), commandDigest: expected_command_digest.clone().into(), } .try_into() .expect("Failed to convert TPMS_COMMAND_AUDIT_INFO to CommandAuditInfo"), }; let (attest, expected_tpms_attest) = create_validated_test_parameters(expected_attest_info, AttestationType::CommandAudit); if let AttestInfo::CommandAudit { info } = attest.attested() { assert_eq!( expected_audit_counter, info.audit_counter(), "CommandAuditInfo did not contain expected audit counter", ); assert_eq!( expected_digest_alg, info.hashing_algorithm(), "CommandAuditInfo did not contain expected hashing algorithm", ); assert_eq!( &expected_audit_digest, info.audit_digest(), "CommandAuditInfo did not contain expected audit digest", ); assert_eq!( &expected_command_digest, info.command_digest(), "CommandAuditInfo did not contain expected command digest", ); } else { panic!("Converted Attest did not contain expected value for 'attest info'"); } let actual_tpms_attest: TPMS_ATTEST = attest.into(); crate::common::ensure_tpms_attest_equality(&expected_tpms_attest, &actual_tpms_attest); } #[test] fn test_attest_with_time_info_into_tpm_type_conversions() { let expected_time_attest_info: TimeAttestInfo = TPMS_TIME_ATTEST_INFO { time: TPMS_TIME_INFO { time: 12u64, clockInfo: TPMS_CLOCK_INFO { clock: 1u64, resetCount: 2u32, restartCount: 3u32, safe: YesNo::Yes.into(), }, }, firmwareVersion: 0xfffffu64, } .try_into() .expect("Failed to convert TPMS_TIME_ATTEST_INFO to TimeAttestInfo"); let expected_attest_info = AttestInfo::Time { info: expected_time_attest_info, }; let (attest, expected_tpms_attest) = create_validated_test_parameters(expected_attest_info, AttestationType::Time); if let AttestInfo::Time { info } = attest.attested() { assert_eq!( &expected_time_attest_info, info, "TimeAttestValue did not contain expected values", ); } else { panic!("Converted Attest did not contain expected value for 'attest info'"); } let actual_tpms_attest: TPMS_ATTEST = attest.into(); crate::common::ensure_tpms_attest_equality(&expected_tpms_attest, &actual_tpms_attest); } #[test] fn test_attest_with_creation_info_into_tpm_type_conversions() { let expected_object_name = Name::try_from(vec![0xf0u8; 68]).expect("Failed to create object name"); let expected_creation_hash = Digest::try_from(vec![0xffu8; 32]).expect("Failed to create creation digest"); let expected_attest_info = AttestInfo::Creation { info: TPMS_CREATION_INFO { objectName: expected_object_name.clone().into(), creationHash: expected_creation_hash.clone().into(), } .try_into() .expect("Failed to convert TPMS_CREATION_INFO to CreationInfo"), }; let (attest, expected_tpms_attest) = create_validated_test_parameters(expected_attest_info, AttestationType::Creation); if let AttestInfo::Creation { info } = attest.attested() { assert_eq!( &expected_object_name, info.object_name(), "CreationInfo did not contain expected value for object name", ); assert_eq!( &expected_creation_hash, info.creation_hash(), "CreationInfo did not contain expected value for creation hash", ); } else { panic!("Converted Attest did not contain expected value for 'attest info'"); } let actual_tpms_attest: TPMS_ATTEST = attest.into(); crate::common::ensure_tpms_attest_equality(&expected_tpms_attest, &actual_tpms_attest); } #[test] fn test_attest_with_nv_creation_info_into_tpm_type_conversions() { let expected_index_name = Name::try_from(vec![0xf0u8; 68]).expect("Failed to create index name"); let expected_offset = 12u16; let expected_nv_contents = MaxNvBuffer::try_from(vec![0xfc; 2048]).expect("Failed to create nv contents"); let expected_attest_info = AttestInfo::Nv { info: TPMS_NV_CERTIFY_INFO { indexName: expected_index_name.clone().into(), offset: expected_offset, nvContents: expected_nv_contents.clone().into(), } .try_into() .expect("Failed to convert TPMS_NV_CERTIFY_INFO to NvCreationInfo"), }; let (attest, expected_tpms_attest) = create_validated_test_parameters(expected_attest_info, AttestationType::Nv); if let AttestInfo::Nv { info } = attest.attested() { assert_eq!( &expected_index_name, info.index_name(), "NvCreationInfo did not contain expected value for index name", ); assert_eq!( expected_offset, info.offset(), "NvCreationInfo did not contain expected value for offset", ); assert_eq!( &expected_nv_contents, info.nv_contents(), "NvCreationInfo did not contain expected value for nv contents", ); } else { panic!("Converted Attest did not contain expected value for 'attest info'"); } let actual_tpms_attest: TPMS_ATTEST = attest.into(); crate::common::ensure_tpms_attest_equality(&expected_tpms_attest, &actual_tpms_attest); } #[test] fn test_marshall_and_unmarshall() { let expected_index_name = Name::try_from(vec![0xf0u8; 68]).expect("Failed to create index name"); let expected_offset = 12u16; let expected_nv_contents = MaxNvBuffer::try_from(vec![0xfc; 2048]).expect("Failed to create nv contents"); let expected_attest_info = AttestInfo::Nv { info: TPMS_NV_CERTIFY_INFO { indexName: expected_index_name.clone().into(), offset: expected_offset, nvContents: expected_nv_contents.clone().into(), } .try_into() .expect("Failed to convert TPMS_NV_CERTIFY_INFO to NvCreationInfo"), }; let expected_qualified_signer = Name::try_from(vec![0x0eu8; 64]).expect("Failed to create qualified name"); let expected_extra_data = Data::try_from(vec![0x0du8; 64]).expect("Failed to create extra data"); let expected_clock_info = ClockInfo::try_from(TPMS_CLOCK_INFO { clock: 1u64, resetCount: 2u32, restartCount: 3u32, safe: YesNo::Yes.into(), }) .expect("Failed to create clock info"); let expected_firmware_version = 1u64; let expected_tpms_attest = TPMS_ATTEST { magic: TPM2_GENERATED_VALUE, type_: AttestationType::Nv.into(), qualifiedSigner: expected_qualified_signer.clone().into(), extraData: expected_extra_data.clone().into(), clockInfo: expected_clock_info.into(), firmwareVersion: expected_firmware_version, attested: expected_attest_info.into(), }; let attest = Attest::try_from(expected_tpms_attest).expect("Failed to convert TPMS_ATTEST to Attest"); let marshalled_attest = attest.marshall().expect("Failed to marshall data"); assert!( !marshalled_attest.is_empty(), "The marshalled attest did not contain any data" ); let un_marshalled_data = Attest::unmarshall(&marshalled_attest).expect("Failed to unmarshall data"); assert_eq!( AttestationType::Nv, un_marshalled_data.attestation_type(), "UnMarshalled Attest did not contain expected value for 'attestation type'" ); assert_eq!( &expected_qualified_signer, un_marshalled_data.qualified_signer(), "UnMarshalled Attest did not contain expected value for 'qualified signer'" ); assert_eq!( &expected_extra_data, un_marshalled_data.extra_data(), "UnMarshalled Attest did not contain expected value for 'extra data'", ); assert_eq!( &expected_clock_info, un_marshalled_data.clock_info(), "UnMarshalled Attest did not contain expected value for 'clock info'", ); assert_eq!( expected_firmware_version, un_marshalled_data.firmware_version(), "UnMarshalled Attest did not contain expected value for 'firmware version'", ); if let AttestInfo::Nv { info } = un_marshalled_data.attested() { assert_eq!( &expected_index_name, info.index_name(), "NvCreationInfo, in the UnMarshalled data, did not contain expected value for index name", ); assert_eq!( expected_offset, info.offset(), "NvCreationInfo, in the UnMarshalled data, did not contain expected value for offset", ); assert_eq!( &expected_nv_contents, info.nv_contents(), "NvCreationInfo, in the UnMarshalled data, did not contain expected value for nv contents", ); } else { panic!("UnMarshalled Attest did not contain expected value for 'attest info'"); } } fn create_validated_test_parameters( expected_attest_info: AttestInfo, expected_attestation_type: AttestationType, ) -> (Attest, TPMS_ATTEST) { let expected_qualified_signer = Name::try_from(vec![0x0eu8; 64]).expect("Failed to create qualified name"); let expected_extra_data = Data::try_from(vec![0x0du8; 64]).expect("Failed to create extra data"); let expected_clock_info = ClockInfo::try_from(TPMS_CLOCK_INFO { clock: 1u64, resetCount: 2u32, restartCount: 3u32, safe: YesNo::Yes.into(), }) .expect("Failed to create clock info"); let expected_firmware_version = 1u64; let expected_tpms_attest = TPMS_ATTEST { magic: TPM2_GENERATED_VALUE, type_: expected_attestation_type.into(), qualifiedSigner: expected_qualified_signer.clone().into(), extraData: expected_extra_data.clone().into(), clockInfo: expected_clock_info.into(), firmwareVersion: expected_firmware_version, attested: expected_attest_info.into(), }; let attest = Attest::try_from(expected_tpms_attest).expect("Failed to convert TPMS_ATTEST to Attest"); assert_eq!( expected_attestation_type, attest.attestation_type(), "Converted Attest did not contain expected value for 'attestation type'" ); assert_eq!( &expected_qualified_signer, attest.qualified_signer(), "Converted Attest did not contain expected value for 'qualified signer'" ); assert_eq!( &expected_extra_data, attest.extra_data(), "Converted Attest did not contain expected value for 'extra data'", ); assert_eq!( &expected_clock_info, attest.clock_info(), "Converted Attest did not contain expected value for 'clock info'", ); assert_eq!( expected_firmware_version, attest.firmware_version(), "Converted Attest did not contain expected value for 'firmware version'", ); (attest, expected_tpms_attest) } tss-esapi-7.4.0/tests/integration_tests/structures_tests/buffers_tests/attest_buffer_tests.rs000064400000000000000000000034301046102023000314230ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; use tss_esapi::{structures::AttestBuffer, tss2_esys::TPM2B_ATTEST, Error, WrapperErrorKind}; const ATTEST_BUFFER_MAX_SIZE: usize = 2304; #[test] fn test_max_sized_data() { let _ = AttestBuffer::try_from(vec![0xffu8; ATTEST_BUFFER_MAX_SIZE]) .expect("Failed to parse buffer if maximum size as AttestBuffer"); } #[test] fn test_to_large_data() { assert_eq!( AttestBuffer::try_from(vec![0xffu8; ATTEST_BUFFER_MAX_SIZE + 1]) .expect_err("Converting a buffer that is to large did not produce an error"), Error::WrapperError(WrapperErrorKind::WrongParamSize), "Wrong kind of error when converting a buffer with size {} to AttestBuffer", ATTEST_BUFFER_MAX_SIZE + 1 ); } #[test] fn test_default() { { let attest_buffer: AttestBuffer = Default::default(); let expected: TPM2B_ATTEST = Default::default(); let actual = TPM2B_ATTEST::try_from(attest_buffer).unwrap(); assert_eq!(expected.size, actual.size); assert_eq!( expected.attestationData.len(), actual.attestationData.len(), "Native and TSS attest buffer don't have the same length" ); assert!( expected .attestationData .iter() .zip(actual.attestationData.iter()) .all(|(a, b)| a == b), "Native and TSS attest buffer is not equal" ); } { let tss_attest_buffer: TPM2B_ATTEST = Default::default(); let expected: AttestBuffer = Default::default(); let actual = AttestBuffer::try_from(tss_attest_buffer).unwrap(); assert_eq!(expected, actual); } } tss-esapi-7.4.0/tests/integration_tests/structures_tests/buffers_tests/auth_tests.rs000064400000000000000000000035151046102023000275330ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; use tss_esapi::structures::Auth; use tss_esapi::tss2_esys::TPM2B_AUTH; // The TPM2B_AUTH is currently // just a typedef in the C code which results // in it being just a type alias for TPM2B_DIGEST // in the rust code. So the same size restrictions that // TPM2B_DIGEST have will apply here as well. mod test_auth { use super::*; #[test] fn test_max_sized_data() { let _ = Auth::try_from([0xff; 64].to_vec()).unwrap(); } #[test] fn test_to_large_data() { // Removed: // - test_handle_auth::test_set_large_handle // - test_create::test_long_auth_create // - test_create_primary::test_long_auth_create_primary // from the context tests and put here instead. let _ = Auth::try_from([0xff; 100].to_vec()).unwrap_err(); } #[test] fn test_default() { { let auth: Auth = Default::default(); let expected: TPM2B_AUTH = Default::default(); let actual = TPM2B_AUTH::try_from(auth).unwrap(); assert_eq!(expected.size, actual.size); assert_eq!( expected.buffer.len(), actual.buffer.len(), "Buffers don't have the same length" ); assert!( expected .buffer .iter() .zip(actual.buffer.iter()) .all(|(a, b)| a == b), "Buffers are not equal" ); } { let tss_auth: TPM2B_AUTH = Default::default(); let expected: Auth = Default::default(); let actual = Auth::try_from(tss_auth).unwrap(); assert_eq!(expected, actual); } } } tss-esapi-7.4.0/tests/integration_tests/structures_tests/buffers_tests/data_tests.rs000064400000000000000000000031511046102023000274770ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; use tss_esapi::structures::Data; use tss_esapi::tss2_esys::TPM2B_DATA; // The TPM2B_DATA has aisze of 64 bytes mod test_data { use super::*; #[test] fn test_max_sized_data() { let _ = Data::try_from([0xff; 64].to_vec()).unwrap(); } #[test] fn test_to_large_data() { // Removed: // - test_create::test_long_outside_info_create // - test_create_primary::test_long_outside_info_create_primary // from the context tests and put here instead. let _ = Data::try_from([0xff; 100].to_vec()).unwrap_err(); } #[test] fn test_default() { { let data: Data = Default::default(); let expected: TPM2B_DATA = Default::default(); let actual = TPM2B_DATA::try_from(data).unwrap(); assert_eq!(expected.size, actual.size); assert_eq!( expected.buffer.len(), actual.buffer.len(), "Buffers don't have the same length" ); assert!( expected .buffer .iter() .zip(actual.buffer.iter()) .all(|(a, b)| a == b), "Buffers are not equal" ); } { let tss_data: TPM2B_DATA = Default::default(); let expected: Data = Default::default(); let actual = Data::try_from(tss_data).unwrap(); assert_eq!(expected, actual); } } } tss-esapi-7.4.0/tests/integration_tests/structures_tests/buffers_tests/digest_tests.rs000064400000000000000000000040561046102023000300520ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::{TryFrom, TryInto}; use tss_esapi::structures::Digest; // Digest has some custom functions for conversion to [u8; N] for common values of N mod test_digests { use super::*; #[test] fn test_correctly_sized_digests() { // N = 20 let sha1_ex = Digest::try_from((1..21).collect::>()).unwrap(); let sha1: [u8; 20] = sha1_ex.try_into().unwrap(); assert_eq!(sha1.to_vec(), (1..21).collect::>()); // N = 32 let sha256_ex = Digest::try_from((1..33).collect::>()).unwrap(); let sha256: [u8; 32] = sha256_ex.try_into().unwrap(); assert_eq!(sha256.to_vec(), (1..33).collect::>()); // N = 48 let sha384_ex = Digest::try_from((1..49).collect::>()).unwrap(); let sha384: [u8; 48] = sha384_ex.try_into().unwrap(); assert_eq!(sha384.to_vec(), (1..49).collect::>()); // N = 64 let sha512_ex = Digest::try_from((1..65).collect::>()).unwrap(); let sha512: [u8; 64] = sha512_ex.try_into().unwrap(); assert_eq!(sha512.to_vec(), (1..65).collect::>()); } #[test] fn test_incorrectly_sized_digests() { // This test uses .err().unwrap() to get around the fact that [u8; N] is only // Debug if N is LengthAtMost32, since .unwrap_err() requires T ([u8; N]): Debug // N = 20 let example = Digest::try_from([0xff; 10].to_vec()).unwrap(); TryInto::<[u8; 20]>::try_into(example).err().unwrap(); // N = 32 let example = Digest::try_from([0xff; 10].to_vec()).unwrap(); TryInto::<[u8; 32]>::try_into(example).err().unwrap(); // N = 48 let example = Digest::try_from([0xff; 10].to_vec()).unwrap(); TryInto::<[u8; 48]>::try_into(example).err().unwrap(); // N = 64 let example = Digest::try_from([0xff; 10].to_vec()).unwrap(); TryInto::<[u8; 64]>::try_into(example).err().unwrap(); } } tss-esapi-7.4.0/tests/integration_tests/structures_tests/buffers_tests/max_buffer_tests.rs000064400000000000000000000030741046102023000307100ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; use tss_esapi::structures::MaxBuffer; use tss_esapi::tss2_esys::{TPM2B_MAX_BUFFER, TPM2_MAX_DIGEST_BUFFER}; mod test_auth { use super::*; const ABOVE_MAX: usize = TPM2_MAX_DIGEST_BUFFER as usize + 1; #[test] fn test_max_sized_data() { let _ = MaxBuffer::try_from([0xff; TPM2_MAX_DIGEST_BUFFER as usize].to_vec()).unwrap(); } #[test] fn test_to_large_data() { let _ = MaxBuffer::try_from([0xff; ABOVE_MAX].to_vec()).unwrap_err(); } #[test] fn test_default() { { let max_buffer: MaxBuffer = Default::default(); let expected: TPM2B_MAX_BUFFER = Default::default(); let actual = TPM2B_MAX_BUFFER::try_from(max_buffer).unwrap(); assert_eq!(expected.size, actual.size); assert_eq!( expected.buffer.len(), actual.buffer.len(), "Buffers don't have the same length" ); assert!( expected .buffer .iter() .zip(actual.buffer.iter()) .all(|(a, b)| a == b), "Buffers are not equal" ); } { let tss_max_buffer: TPM2B_MAX_BUFFER = Default::default(); let expected: MaxBuffer = Default::default(); let actual = MaxBuffer::try_from(tss_max_buffer).unwrap(); assert_eq!(expected, actual); } } } tss-esapi-7.4.0/tests/integration_tests/structures_tests/buffers_tests/mod.rs000064400000000000000000000003521046102023000261230ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod attest_buffer_tests; mod auth_tests; mod data_tests; mod digest_tests; mod max_buffer_tests; mod nonce_tests; mod public; mod sensitive; tss-esapi-7.4.0/tests/integration_tests/structures_tests/buffers_tests/nonce_tests.rs000064400000000000000000000043571046102023000277010ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; use tss_esapi::structures::Nonce; use tss_esapi::tss2_esys::TPM2B_NONCE; // The TPM2B_NONCE is currently // just a typedef in the C code which results // in it being just a type alias for TPM2B_DIGEST // in the rust code. So the same size restrictions that // TPM2B_DIGEST have will apply here as well. #[test] fn test_max_sized_data() { let _ = Nonce::try_from([0xff; 64].to_vec()).unwrap(); } #[test] fn test_to_large_data() { // Removed test_start_sess::test_long_nonce_sess // from context tests. let _ = Nonce::try_from( [ 231, 97, 201, 180, 0, 1, 185, 150, 85, 90, 174, 188, 105, 133, 188, 3, 206, 5, 222, 71, 185, 1, 209, 243, 36, 130, 250, 116, 17, 0, 24, 4, 25, 225, 250, 198, 245, 210, 140, 23, 139, 169, 15, 193, 4, 145, 52, 138, 149, 155, 238, 36, 74, 152, 179, 108, 200, 248, 250, 100, 115, 214, 166, 165, 1, 27, 51, 11, 11, 244, 218, 157, 3, 174, 171, 142, 45, 8, 9, 36, 202, 171, 165, 43, 208, 186, 232, 15, 241, 95, 81, 174, 189, 30, 213, 47, 86, 115, 239, 49, 214, 235, 151, 9, 189, 174, 144, 238, 200, 201, 241, 157, 43, 37, 6, 96, 94, 152, 159, 205, 54, 9, 181, 14, 35, 246, 49, 150, 163, 118, 242, 59, 54, 42, 221, 215, 248, 23, 18, 223, ] .to_vec(), ) .unwrap_err(); } #[test] fn test_default() { { let nonce: Nonce = Default::default(); let expected: TPM2B_NONCE = Default::default(); let actual = TPM2B_NONCE::try_from(nonce).unwrap(); assert_eq!(expected.size, actual.size); assert_eq!( expected.buffer.len(), actual.buffer.len(), "Buffers don't have the same length" ); assert!( expected .buffer .iter() .zip(actual.buffer.iter()) .all(|(a, b)| a == b), "Buffers are not equal" ); } { let tss_nonce: TPM2B_NONCE = Default::default(); let expected: Nonce = Default::default(); let actual = Nonce::try_from(tss_nonce).unwrap(); assert_eq!(expected, actual); } } tss-esapi-7.4.0/tests/integration_tests/structures_tests/buffers_tests/public.rs000064400000000000000000000024511046102023000266240ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; use tss_esapi::{ structures::{Public, PublicBuffer}, Error, WrapperErrorKind, }; const PUBLIC_BUFFER_MAX_SIZE: usize = 612; #[test] fn test_max_sized_data() { let _ = PublicBuffer::try_from(vec![0xffu8; PUBLIC_BUFFER_MAX_SIZE]) .expect("Failed to parse buffer of maximum size as PublicBuffer"); } #[test] fn test_to_large_data() { assert_eq!( PublicBuffer::try_from(vec![0xffu8; PUBLIC_BUFFER_MAX_SIZE + 1]) .expect_err("Converting a buffer that is to large did not produce an error"), Error::WrapperError(WrapperErrorKind::WrongParamSize), "Wrong kind of error when converting a buffer with size {} to PublicBuffer", PUBLIC_BUFFER_MAX_SIZE + 1 ); } #[test] fn marshall_unmarshall() { crate::common::publics().iter().for_each(|public| { let public = public.clone(); let pub_buf = PublicBuffer::try_from(public.clone()) .expect("Failed to convert from Public to PublicBuffer"); crate::common::check_marshall_unmarshall(&pub_buf); assert_eq!( public, Public::try_from(pub_buf).expect("Failed to convert from PublicBuffer to Public") ); }); } tss-esapi-7.4.0/tests/integration_tests/structures_tests/buffers_tests/sensitive.rs000064400000000000000000000025751046102023000273660ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; use tss_esapi::{ structures::{Sensitive, SensitiveBuffer}, Error, WrapperErrorKind, }; const SENSITIVE_BUFFER_MAX_SIZE: usize = 1416; #[test] fn test_max_sized_data() { let _ = SensitiveBuffer::try_from(vec![0xffu8; SENSITIVE_BUFFER_MAX_SIZE]) .expect("Failed to parse buffer of maximum size as SensitiveBuffer"); } #[test] fn test_to_large_data() { assert_eq!( SensitiveBuffer::try_from(vec![0xffu8; SENSITIVE_BUFFER_MAX_SIZE + 1]) .expect_err("Converting a buffer that is to large did not produce an error"), Error::WrapperError(WrapperErrorKind::WrongParamSize), "Wrong kind of error when converting a buffer with size {} to SensitiveBuffer", SENSITIVE_BUFFER_MAX_SIZE + 1 ); } #[test] fn marshall_unmarshall() { crate::common::sensitives().iter().for_each(|sensitive| { let sensitive = sensitive.clone(); let pub_buf = SensitiveBuffer::try_from(sensitive.clone()) .expect("Failed to convert from Sensitive to SensitiveBuffer"); crate::common::check_marshall_unmarshall(&pub_buf); assert_eq!( sensitive, Sensitive::try_from(pub_buf) .expect("Failed to convert from SensitiveBuffer to Sensitive") ); }); } tss-esapi-7.4.0/tests/integration_tests/structures_tests/capability_data_tests.rs000064400000000000000000000110441046102023000270220ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use tss_esapi::constants::CapabilityType; use tss_esapi::structures::CapabilityData; use crate::common::create_ctx_without_session; #[test] fn test_algorithms() { let mut context = create_ctx_without_session(); let (capabs, _more) = context .get_capability(CapabilityType::Algorithms, 0, 80) .unwrap(); if let CapabilityData::Algorithms(list) = capabs { assert!(!list.is_empty()); } else { panic!("Got wrong type of capability data: {:?}", capabs); } } #[test] fn test_handles() { let mut context = create_ctx_without_session(); let (capabs, _more) = context .get_capability(CapabilityType::Handles, 0, 80) .unwrap(); if let CapabilityData::Handles(vec) = capabs { assert!(!vec.is_empty()); } else { panic!("Got wrong type of capability data: {:?}", capabs); } } #[test] fn test_command() { let mut context = create_ctx_without_session(); let (capabs, _more) = context .get_capability(CapabilityType::Command, 0, 80) .unwrap(); if let CapabilityData::Commands(vec) = capabs { assert!(!vec.is_empty()); } else { panic!("Got wrong type of capability data: {:?}", capabs); } } #[test] fn test_pp_commands() { let mut context = create_ctx_without_session(); let (capabs, _more) = context .get_capability(CapabilityType::PpCommands, 0, 80) .unwrap(); if let CapabilityData::PpCommands(list) = capabs { assert!(!list.is_empty()); } else { panic!("Got wrong type of capability data: {:?}", capabs); } } #[test] fn test_audit_commands() { let mut context = create_ctx_without_session(); let (capabs, _more) = context .get_capability(CapabilityType::AuditCommands, 0, 80) .unwrap(); if let CapabilityData::AuditCommands(list) = capabs { assert!(!list.is_empty()); } else { panic!("Got wrong type of capability data: {:?}", capabs); } } #[test] fn test_assigned_pcr() { let mut context = create_ctx_without_session(); let (capabs, _more) = context .get_capability(CapabilityType::AssignedPcr, 0, 80) .unwrap(); if let CapabilityData::AssignedPcr(list) = capabs { assert!(!list.is_empty()); } else { panic!("Got wrong type of capability data: {:?}", capabs); } } #[test] fn test_tpm_properties() { let mut context = create_ctx_without_session(); let (capabs, _more) = context .get_capability(CapabilityType::TpmProperties, 0, 80) .unwrap(); if let CapabilityData::TpmProperties(list) = capabs { assert!(!list.is_empty()); } else { panic!("Got wrong type of capability data: {:?}", capabs); } } #[test] fn test_pcr_properties() { let mut context = create_ctx_without_session(); let (capabs, _more) = context .get_capability(CapabilityType::PcrProperties, 0, 80) .unwrap(); if let CapabilityData::PcrProperties(list) = capabs { assert!(!list.is_empty()); } else { panic!("Got wrong type of capability data: {:?}", capabs); } } #[test] fn test_ecc_curves() { let mut context = create_ctx_without_session(); let (capabs, _more) = context .get_capability(CapabilityType::EccCurves, 0, 80) .unwrap(); if let CapabilityData::EccCurves(vec) = capabs { assert!(!vec.is_empty()); } else { panic!("Got wrong type of capability data: {:?}", capabs); } } // For these tests to work the tpm2-tss library need to have the // authPolicies field in the TPMU_CAPABILITIES union. // #[test] // fn test_auth_policies() { // let mut context = create_ctx_without_session(); // let (capabs, _more) = context // .get_capability(CapabilityType::AuthPolicies, 0, 80) // .unwrap(); // if let CapabilityData::AuthPolicies(list) = capabs { // assert!(!list.is_empty()); // } else { // panic!("Got wrong type of capability data: {:?}", capabs); // } // } // For these tests to work the tpm2-tss library need to have the // actData field in the TPMU_CAPABILITIES union. // #[test] // fn test_act() { // let mut context = create_ctx_without_session(); // let (capabs, _more) = context.get_capability(CapabilityType::Act, 0, 80).unwrap(); // if let CapabilityData::ActData(list) = capabs { // assert!(!list.is_empty()); // } else { // panic!("Got wrong type of capability data: {:?}", capabs); // } // } tss-esapi-7.4.0/tests/integration_tests/structures_tests/certify_info_tests.rs000064400000000000000000000027151046102023000263750ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::{TryFrom, TryInto}; use tss_esapi::{ structures::{CertifyInfo, Name}, tss2_esys::TPMS_CERTIFY_INFO, }; #[test] fn test_conversion() { let expected_name = Name::try_from(vec![0xffu8; 64]).expect("Failed to create name"); let expected_qualified_name = Name::try_from(vec![0x0fu8; 64]).expect("Failed to create qualified name"); let expected_tpms_certify_info = TPMS_CERTIFY_INFO { name: expected_name .clone() .try_into() .expect("Failed to convert name to tss type"), qualifiedName: expected_qualified_name .clone() .try_into() .expect("failed to convert qualified name to tss type"), }; let certify_info = CertifyInfo::try_from(expected_tpms_certify_info) .expect("Failed to convert TPMS_CERTIFY_INFO to certifyInfo"); assert_eq!( &expected_name, certify_info.name(), "Converted certify info did not contain expected name" ); assert_eq!( &expected_qualified_name, certify_info.qualified_name(), "Converted certify info did not contain expected qualified name" ); let actual_tpms_certify_info: TPMS_CERTIFY_INFO = certify_info.into(); crate::common::ensure_tpms_certify_info_equality( &expected_tpms_certify_info, &actual_tpms_certify_info, ); } tss-esapi-7.4.0/tests/integration_tests/structures_tests/clock_info_tests.rs000064400000000000000000000037771046102023000260340ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; use tss_esapi::{ interface_types::YesNo, structures::ClockInfo, tss2_esys::TPMS_CLOCK_INFO, Error, WrapperErrorKind, }; #[test] fn test_conversions() { let expected_clock = 1u64; let expected_reset_count = 2u32; let expected_restart_count = 3u32; let expected_safe = YesNo::Yes; let expected_tpms_clock_info = TPMS_CLOCK_INFO { clock: expected_clock, resetCount: expected_reset_count, restartCount: expected_restart_count, safe: expected_safe.into(), }; let clock_info = ClockInfo::try_from(expected_tpms_clock_info) .expect("Failed to convert TPMS_CLOCK_INFO into ClockInfo"); assert_eq!( expected_clock, clock_info.clock(), "'clock' value mismatch between actual and expected values" ); assert_eq!( expected_reset_count, clock_info.reset_count(), "'reset count' value mismatch between actual and expected values" ); assert_eq!( expected_restart_count, clock_info.restart_count(), "'restart count' value mismatch between actual and expected values" ); assert_eq!( bool::from(expected_safe), clock_info.safe(), "'safe' value mismatch between actual and expected values" ); let actual_tpms_clock_info: TPMS_CLOCK_INFO = clock_info.into(); crate::common::ensure_tpms_clock_info_equality( &expected_tpms_clock_info, &actual_tpms_clock_info, ); } #[test] fn test_invalid_conversion() { assert_eq!( Error::WrapperError(WrapperErrorKind::InvalidParam), ClockInfo::try_from(TPMS_CLOCK_INFO { clock: 1u64, resetCount: 2u32, restartCount: 3u32, safe: 4u8, }) .expect_err("Conversion of invalid ClockInfo parameters did not produce an error"), "Error produced did not match the expected error.", ); } tss-esapi-7.4.0/tests/integration_tests/structures_tests/command_audit_info_tests.rs000064400000000000000000000044501046102023000275320ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::{TryFrom, TryInto}; use tss_esapi::{ constants::AlgorithmIdentifier, interface_types::algorithm::HashingAlgorithm, structures::{CommandAuditInfo, Digest}, tss2_esys::TPMS_COMMAND_AUDIT_INFO, }; #[test] fn test_conversion() { let expected_audit_counter = 1u64; let expected_hashing_algorithm = HashingAlgorithm::Sha512; let expected_audit_digest = Digest::try_from(vec![0xffu8; 32]).expect("Failed to create audit digest"); let expected_command_digest = Digest::try_from(vec![0xf0u8; 32]).expect("Failed to create command digest"); let expected_tpms_command_audit_info = TPMS_COMMAND_AUDIT_INFO { auditCounter: expected_audit_counter, digestAlg: AlgorithmIdentifier::from(expected_hashing_algorithm).into(), auditDigest: expected_audit_digest.clone().into(), commandDigest: expected_command_digest.clone().into(), }; let command_audit_info: CommandAuditInfo = expected_tpms_command_audit_info .try_into() .expect("Failed to convert TPMS_COMMAND_AUDIT_INFO into CommandAuditInfo"); assert_eq!( expected_audit_counter, command_audit_info.audit_counter(), "The CommandAuditInfo converted from TPMS_COMMAND_AUDIT_INFO did not contain correct value for 'audit counter'", ); assert_eq!( expected_hashing_algorithm, command_audit_info.hashing_algorithm(), "The CommandAuditInfo converted from TPMS_COMMAND_AUDIT_INFO did not contain correct value for 'hashing algorithm'", ); assert_eq!( &expected_audit_digest, command_audit_info.audit_digest(), "The CommandAuditInfo converted from TPMS_COMMAND_AUDIT_INFO did not contain correct value for 'audit digest'", ); assert_eq!( &expected_command_digest, command_audit_info.command_digest(), "The CommandAuditInfo converted from TPMS_COMMAND_AUDIT_INFO did not contain correct value for 'command digest'", ); let actual_tpms_command_audit_info: TPMS_COMMAND_AUDIT_INFO = command_audit_info.into(); crate::common::ensure_tpms_command_audit_info_equality( &expected_tpms_command_audit_info, &actual_tpms_command_audit_info, ); } tss-esapi-7.4.0/tests/integration_tests/structures_tests/creation_info_tests.rs000064400000000000000000000027071046102023000265350ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::{TryFrom, TryInto}; use tss_esapi::{ structures::{CreationInfo, Digest, Name}, tss2_esys::TPMS_CREATION_INFO, }; #[test] fn test_conversion() { let expected_object_name = Name::try_from(vec![0xf0u8; 68]).expect("Failed to create object name"); let expected_creation_hash = Digest::try_from(vec![0xffu8; 32]).expect("Failed to create creation digest"); let expected_tpms_creation_info = TPMS_CREATION_INFO { objectName: expected_object_name.clone().into(), creationHash: expected_creation_hash.clone().into(), }; let creation_info: CreationInfo = expected_tpms_creation_info .try_into() .expect("Failed to convert TPMS_CREATION_INFO into CreationInfo"); assert_eq!( &expected_object_name, creation_info.object_name(), "The CommandAuditInfo converted from TPMS_CREATION_INFO did not contain correct value for 'object name'", ); assert_eq!( &expected_creation_hash, creation_info.creation_hash(), "The CommandAuditInfo converted from TPMS_CREATION_INFO did not contain correct value for 'creation hash'", ); let actual_tpms_creation_info: TPMS_CREATION_INFO = creation_info.into(); crate::common::ensure_tpms_creation_info_equality( &expected_tpms_creation_info, &actual_tpms_creation_info, ); } ././@LongLink00006440000000000000000000000146000000000000007774Lustar tss-esapi-7.4.0/tests/integration_tests/structures_tests/lists_tests/algorithm_property_list_tests.rstss-esapi-7.4.0/tests/integration_tests/structures_tests/lists_tests/algorithm_property_list_tests.r000064400000000000000000000130731046102023000330760ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use tss_esapi::{ attributes::AlgorithmAttributes, constants::AlgorithmIdentifier, structures::{AlgorithmProperty, AlgorithmPropertyList}, tss2_esys::{TPML_ALG_PROPERTY, TPMS_ALG_PROPERTY}, Error, WrapperErrorKind, }; use std::convert::{TryFrom, TryInto}; #[test] fn test_conversions() { let expected_algorithm_properties = [ (AlgorithmIdentifier::Rsa, AlgorithmAttributes(1)), (AlgorithmIdentifier::Aes, AlgorithmAttributes(2)), ]; let expected_tpml_alg_property = expected_algorithm_properties.iter().fold( TPML_ALG_PROPERTY::default(), |mut acc, (aid, aa)| { acc.algProperties[acc.count as usize].alg = (*aid).into(); acc.algProperties[acc.count as usize].algProperties = (*aa).into(); acc.count += 1; acc }, ); let actual_algorithm_property_list: AlgorithmPropertyList = expected_tpml_alg_property .try_into() .expect("Failed to convert TPML_ALG_PROPERTY into AlgorithmPropertyList"); assert_eq!( expected_algorithm_properties.len(), actual_algorithm_property_list.len(), "The algorithm property list converted from TPML_ALG_PROPERTY did not contain the expected amount of elements" ); expected_algorithm_properties .iter() .zip(actual_algorithm_property_list.iter()) .for_each(|((expected_aid, expected_aa), ap)| { assert_eq!( expected_aid, &ap.algorithm_identifier(), "An AlgorithmProperty in the AlgorithmPropertyList converted from TPML_ALG_PROPERTY did not contain the expected algorithm identifer" ); assert_eq!( expected_aa, &ap.algorithm_properties(), "An AlgorithmProperty in the AlgorithmPropertyList converted from TPML_ALG_PROPERTY did not contain the expected algorithm properties" ); }); let actual_tpml_alg_property: TPML_ALG_PROPERTY = actual_algorithm_property_list.into(); crate::common::ensure_tpml_alg_property_equality( &expected_tpml_alg_property, &actual_tpml_alg_property, ); } #[test] fn test_valid_conversion_vector() { let expected_algorithm_properties = [ (AlgorithmIdentifier::Rsa, AlgorithmAttributes(1)), (AlgorithmIdentifier::Aes, AlgorithmAttributes(2)), ]; let expected_tpml_alg_property = expected_algorithm_properties.iter().fold( TPML_ALG_PROPERTY::default(), |mut acc, (aid, aa)| { acc.algProperties[acc.count as usize].alg = (*aid).into(); acc.algProperties[acc.count as usize].algProperties = (*aa).into(); acc.count += 1; acc }, ); let expected_algorithm_property_list: AlgorithmPropertyList = expected_tpml_alg_property .try_into() .expect("Failed to convert TPML_ALG_PROPERTY into AlgorithmPropertyList"); assert_eq!( expected_algorithm_properties.len(), expected_algorithm_property_list.len(), "The algorithm property list converted from TPML_ALG_PROPERTY did not contain the expected amount of elements" ); let algorithm_properties_vector: Vec = expected_algorithm_property_list.clone().into(); expected_algorithm_properties .iter() .zip(algorithm_properties_vector.iter()) .for_each(|((expected_aid, expected_aa), ap)| { assert_eq!( expected_aid, &ap.algorithm_identifier(), "An AlgorithmProperty in the Vec converted from AlgorithmPropertyList did not contain the expected algorithm identifer" ); assert_eq!( expected_aa, &ap.algorithm_properties(), "An AlgorithmProperty in the Vec converted from AlgorithmPropertyList did not contain the expected algorithm properties" ); }); let actual_algorithm_property_list: AlgorithmPropertyList = algorithm_properties_vector .try_into() .expect("Failed to convert Vec into AlgorithmPropertyList"); expected_algorithm_property_list .iter() .zip(actual_algorithm_property_list.iter()) .for_each(|(expected, actual)| { assert_eq!( expected, actual, "AlgorithmPropertyList converted from Vec did not contain the expected algorithm property" ); }); } #[test] fn test_invalid_conversion_from_tpml_alg_property() { assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), AlgorithmPropertyList::try_from(TPML_ALG_PROPERTY { count: AlgorithmPropertyList::MAX_SIZE as u32 + 1u32, ..Default::default() }), "Converting a TPML_ALG_PROPERTY with invalid 'count' into AlgorithmPropertyList did not produce the expected error" ); } #[test] fn test_invalid_conversion_from_vector() { let value: AlgorithmProperty = TPMS_ALG_PROPERTY { alg: AlgorithmIdentifier::Aes.into(), algProperties: AlgorithmAttributes(2).into(), } .try_into() .expect("Failed to convert TPMS_ALG_PROPERTY into AlgorithmProperty"); assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), AlgorithmPropertyList::try_from(vec![value; AlgorithmPropertyList::MAX_SIZE + 1]), "Converting a Vec with invalid number of items into AlgorithmPropertyList did not produce the expected error" ); } ././@LongLink00006440000000000000000000000153000000000000007772Lustar tss-esapi-7.4.0/tests/integration_tests/structures_tests/lists_tests/command_code_attributes_list_tests.rstss-esapi-7.4.0/tests/integration_tests/structures_tests/lists_tests/command_code_attributes_list_te000064400000000000000000000147261046102023000330360ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::{TryFrom, TryInto}; use tss_esapi::{ attributes::CommandCodeAttributes, constants::CommandCode, structures::CommandCodeAttributesList, tss2_esys::TPML_CCA, Error, WrapperErrorKind, }; #[test] fn test_valid_conversions() { let expected_command_code_attributes = vec![ CommandCodeAttributes::try_from(u32::from(CommandCode::NvUndefineSpaceSpecial)).expect( "Failed to create CommandCodeAttributes using CommandCode::NvUndefineSpaceSpecia", ), CommandCodeAttributes::try_from(u32::from(CommandCode::EvictControl)) .expect("Failed to create CommandCodeAttributes using CommandCode::EvictControl"), CommandCodeAttributes::try_from(u32::from(CommandCode::PcrRead)) .expect("Failed to create CommandCodeAttributes using CommandCode::PcrRead"), ]; let expected_tpml_cca: TPML_CCA = expected_command_code_attributes .iter() .fold(Default::default(), |mut acc, &v| { acc.commandAttributes[acc.count as usize] = v.into(); acc.count += 1; acc }); let command_code_attributes_list_from_vec: CommandCodeAttributesList = expected_command_code_attributes .clone() .try_into() .expect("Failed to convert Vec to CommandCodeAttributesList"); assert_eq!( expected_command_code_attributes.len(), command_code_attributes_list_from_vec.len(), "Mismatch in 'len()' between the Vec and the CommandCodeAttributesList(from vec)" ); expected_command_code_attributes .iter() .zip(command_code_attributes_list_from_vec.as_ref()) .for_each(|(expected, actual)| { assert_eq!(expected, actual, "Mismatch between an expected CommandCodeAttributes in the Vec the actual command code attributes in CommandCodeAttributesList(from vec)"); }); let command_code_attributes_list_from_tss: CommandCodeAttributesList = expected_tpml_cca .try_into() .expect("Failed to convert expected_tpml_cca into CommandCodeAttributesList"); assert_eq!( expected_command_code_attributes.len(), command_code_attributes_list_from_tss.len(), "Mismatch in 'len()' between the Vec and the CommandCodeAttributesList(from tss)" ); expected_command_code_attributes .iter() .zip(command_code_attributes_list_from_tss.as_ref()) .for_each(|(expected, actual)| { assert_eq!(expected, actual, "Mismatch between an expected CommandCodeAttributes in the Vec the actual tagged property in CommandCodeAttributesList(from tss)"); }); let actual_tpml_cca: TPML_CCA = command_code_attributes_list_from_vec.into(); crate::common::ensure_tpml_cca_equality(&expected_tpml_cca, &actual_tpml_cca); } #[test] fn test_invalid_conversions() { assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), CommandCodeAttributesList::try_from(vec![CommandCodeAttributes::try_from(u32::from(CommandCode::NvUndefineSpaceSpecial)).expect( "Failed to create CommandCodeAttributes using CommandCode::NvUndefineSpaceSpecia", ); CommandCodeAttributesList::MAX_SIZE + 1]), "Converting a vector with to many elements into a CommandCodeAttributesList did not produce the expected error", ); assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), CommandCodeAttributesList::try_from(TPML_CCA { count: CommandCodeAttributesList::MAX_SIZE as u32 + 1u32, commandAttributes: [Default::default(); 256], }), "Converting a TPML_CCA with an invalid 'count' value into a CommandCodeAttributesList did not produce the expected error", ); } #[test] fn test_find() { let command_code_attributes_list = CommandCodeAttributesList::try_from(vec![ CommandCodeAttributes::try_from(u32::from(CommandCode::NvUndefineSpaceSpecial)).expect( "Failed to create CommandCodeAttributes using CommandCode::NvUndefineSpaceSpecial", ), CommandCodeAttributes::try_from(u32::from(CommandCode::EvictControl)) .expect("Failed to create CommandCodeAttributes using CommandCode::EvictControl"), CommandCodeAttributes::try_from(u32::from(CommandCode::PcrRead)) .expect("Failed to create CommandCodeAttributes using CommandCode::PcrRead"), ]) .expect("Failed to convert Vec to CommandCodeAttributesList"); assert_eq!( &CommandCodeAttributes::try_from(u32::from(CommandCode::NvUndefineSpaceSpecial)).expect( "Failed to create CommandCodeAttributes using CommandCode::NvUndefineSpaceSpecial", ), command_code_attributes_list .find( u16::try_from(u32::from(CommandCode::NvUndefineSpaceSpecial)) .expect("Failed to convert CommandCode::NvUndefineSpaceSpecial into command code index") ) .expect("Calling 'find' using CommandCode::NvUndefineSpaceSpecial as command code index returned an unexpected 'None'"), "Calling 'find' using CommandCode::NvUndefineSpaceSpecial as command code index did not return the expected CommandCodeAttributes value" ); assert_eq!( &CommandCodeAttributes::try_from(u32::from(CommandCode::EvictControl)).expect( "Failed to create CommandCodeAttributes using CommandCode::EvictControl", ), command_code_attributes_list .find( u16::try_from(u32::from(CommandCode::EvictControl)) .expect("Failed to convert CommandCode::EvictControl into command code index") ) .expect("Calling 'find' using CommandCode::NvUndefineSpaceSpecial as command code index returned an unexpected 'None'"), "Calling 'find' using CommandCode::EvictControl as command code index did not return the expected CommandCodeAttributes value" ); assert!( command_code_attributes_list .find( u16::try_from(u32::from(CommandCode::PcrAllocate)) .expect("Failed to convert CommandCode::PcrRead into command code index") ) .is_none(), "A value that should not exist was found in the CommandCodeAttributesList" ); } tss-esapi-7.4.0/tests/integration_tests/structures_tests/lists_tests/command_code_list_tests.rs000064400000000000000000000127521046102023000317420ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use tss_esapi::{ constants::CommandCode, structures::CommandCodeList, tss2_esys::{TPM2_CC, TPML_CC}, Error, WrapperErrorKind, }; use std::convert::{TryFrom, TryInto}; #[test] fn test_conversions() { let expected_command_codes = [ CommandCode::ChangeEps, CommandCode::ChangePps, CommandCode::Clear, ]; let mut command_code_list = CommandCodeList::new(); for command_code in expected_command_codes.iter() { command_code_list .add(*command_code) .expect("Failed to add command code to command code list"); } assert_eq!( expected_command_codes.len(), command_code_list.len(), "The created command code list did not contain the expected number of elements" ); expected_command_codes .iter() .zip(command_code_list.as_ref().iter()) .for_each(|(expected, actual)| { assert_eq!( expected, actual, "The created command code list did not contain the expected value" ) }); let tpml_cc: TPML_CC = command_code_list .try_into() .expect("Failed to convert CommandCodeList into TPML_CC"); assert_eq!( expected_command_codes.len(), tpml_cc.count as usize, "The number count field in TPML_CC did not contain the expected value" ); expected_command_codes .iter() .zip(tpml_cc.commandCodes[0..tpml_cc.count as usize].iter()) .for_each(|(expected, actual)| { assert_eq!( TPM2_CC::from(*expected), *actual, "Command code missmatch between command codes in CommandCodeList and converted CommandCodeList" ) }); let converted_command_code_list: CommandCodeList = tpml_cc .try_into() .expect("Failed to convert TPML_CC to CommandCodeList"); assert_eq!( expected_command_codes.len(), converted_command_code_list.len(), "The command code list converted from TPML_CC did not contain the expected number of elements" ); expected_command_codes .iter() .zip(converted_command_code_list.as_ref().iter()) .for_each(|(expected, actual)| { assert_eq!( expected, actual, "Command code in command code list converted from TPML_CC did not match the expected value" ) }); } #[test] fn test_valid_conversion_vector() { let expected_command_codes = [ CommandCode::ChangeEps, CommandCode::ChangePps, CommandCode::Clear, ]; let mut command_code_list = CommandCodeList::new(); for command_code in expected_command_codes.iter() { command_code_list .add(*command_code) .expect("Failed to add command code to command code list"); } assert_eq!( expected_command_codes.len(), command_code_list.len(), "The created command code list did not contain the expected number of elements" ); expected_command_codes .iter() .zip(command_code_list.as_ref().iter()) .for_each(|(expected, actual)| { assert_eq!( expected, actual, "The created command code list did not contain the expected value" ) }); let actual_command_codes: Vec = command_code_list .try_into() .expect("Failed to convert CommandCodeList to Vec"); assert_eq!( expected_command_codes.len(), actual_command_codes.len(), "The Vec converted from CommandCodeList did not contain the expected number of elements" ); expected_command_codes .iter() .zip(actual_command_codes.iter()) .for_each(|(expected, actual)| { assert_eq!( expected, actual, "Command code in command code list converted from TPML_CC did not match the expected value" ) }); } #[test] fn test_invalid_conversions() { let mut command_code_list = CommandCodeList::new(); for _ in 0..CommandCodeList::MAX_SIZE { command_code_list .add(CommandCode::ChangeEps) .expect("Failed to command code to list"); } assert_eq!( Err(Error::WrapperError(WrapperErrorKind::WrongParamSize)), command_code_list.add(CommandCode::ChangeEps), "Adding more command codes to command code list then it supports did not produce the expected error" ); } #[test] fn test_invalid_conversion_from_tpml_cc() { let invalid_value = TPML_CC { count: CommandCodeList::MAX_SIZE as u32 + 1u32, commandCodes: [0; 256], }; assert_eq!( Error::WrapperError(WrapperErrorKind::InvalidParam), CommandCodeList::try_from(invalid_value).expect_err( "Converting a TPML_CC with invalid values to ComandCodeList did not produce an error" ), "Converting invalid TPML_CC did not produce the expected error", ); } #[test] fn test_invalid_conversions_from_vector() { assert_eq!( Error::WrapperError(WrapperErrorKind::InvalidParam), CommandCodeList::try_from(vec![CommandCode::ChangeEps; CommandCodeList::MAX_SIZE + 1]).expect_err( "Converting Vec of invalid length to CommandCodeList did not produce an error" ), "Converting invalid Vec did not produce the expected error", ); } tss-esapi-7.4.0/tests/integration_tests/structures_tests/lists_tests/digest_list_tests.rs000064400000000000000000000031141046102023000306010ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; use tss_esapi::structures::{Digest, DigestList}; use tss_esapi::tss2_esys::{TPM2B_DIGEST, TPML_DIGEST}; #[test] fn test_conversion_from_tss_digest_list() { let mut expected_digests = Vec::::new(); let mut tss_digest_list: TPML_DIGEST = Default::default(); for i in 0..3 { let mut tss_digest = TPM2B_DIGEST { size: 32, ..Default::default() }; tss_digest.buffer[..32].copy_from_slice(&[i; 32]); expected_digests.push(Digest::try_from(tss_digest).unwrap()); tss_digest_list.digests[i as usize] = tss_digest; tss_digest_list.count += 1; } let digest_list = DigestList::try_from(tss_digest_list).unwrap(); assert_eq!(digest_list.value().len(), tss_digest_list.count as usize); for actual_digest in digest_list.value().iter() { match expected_digests .iter() .position(|v| v.value() == actual_digest.value()) { Some(pos) => { expected_digests.remove(pos); } None => panic!("Digest did not exist in the expected digests"), } } assert_eq!(expected_digests.len(), 0); } #[test] fn test_add_exceeding_max_limit() { let digest = Digest::try_from(vec![1, 2, 3, 4, 5, 6, 7]).unwrap(); let mut digest_list: DigestList = Default::default(); for _ in 0..DigestList::MAX_SIZE { digest_list.add(digest.clone()).unwrap(); } digest_list.add(digest).unwrap_err(); } tss-esapi-7.4.0/tests/integration_tests/structures_tests/lists_tests/ecc_curve_list_tests.rs000064400000000000000000000101601046102023000312570ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; use tss_esapi::{ constants::ecc::EccCurveIdentifier, structures::EccCurveList, tss2_esys::{TPM2_ECC_CURVE, TPML_ECC_CURVE}, Error, WrapperErrorKind, }; #[test] fn test_conversions() { let expected_ecc_curves: Vec = vec![]; let mut ecc_curve_list = EccCurveList::new(); for curve in expected_ecc_curves.iter() { ecc_curve_list .add(*curve) .expect("Failed to add curve to list"); } assert_eq!(expected_ecc_curves.len(), ecc_curve_list.len()); expected_ecc_curves .iter() .zip(ecc_curve_list.as_ref().iter()) .for_each(|(expected, actual)| { assert_eq!( expected, actual, "The created ECC curve list did not contain the expected values" ); }); let tpml_ecc_curve = TPML_ECC_CURVE::try_from(ecc_curve_list).expect("failed to convert to TPML_ECC_CURVE"); assert_eq!( expected_ecc_curves.len(), tpml_ecc_curve.count as usize, "The number of ecc_curves in the TPML_ECC_CURVE is different than expected" ); expected_ecc_curves .iter() .zip(tpml_ecc_curve.eccCurves[..expected_ecc_curves.len()].iter()) .for_each(|(expected, actual)| { assert_eq!( TPM2_ECC_CURVE::from(*expected), *actual, "Got mismatch between expected FFI ECC curve and actual ECC curve" ) }); let ecc_curve_list = EccCurveList::try_from(tpml_ecc_curve).expect("Failed to convert from TPML_ECC_CURVE"); assert_eq!( expected_ecc_curves.len(), ecc_curve_list.len(), "Converted ECC curve list has a different length" ); expected_ecc_curves .iter() .zip(ecc_curve_list.as_ref().iter()) .for_each(|(expected, actual)| { assert_eq!( expected, actual, "The converted ECC curve list did not contain the expected values" ); }); } #[test] fn test_vector_conversion() { let expected_ecc_curves: Vec = vec![ EccCurveIdentifier::NistP256, EccCurveIdentifier::NistP192, EccCurveIdentifier::NistP384, ]; let ecc_curve_list = EccCurveList::try_from(expected_ecc_curves.clone()).expect("Failed to convert from vector"); expected_ecc_curves .iter() .zip(ecc_curve_list.as_ref().iter()) .for_each(|(expected, actual)| { assert_eq!( expected, actual, "The converted curve list did not contain the expected values" ); }); let converted_ecc_curves = Vec::::from(ecc_curve_list); assert_eq!( expected_ecc_curves, converted_ecc_curves, "Converted vector did not match initial vector" ); } #[test] fn test_add_too_many() { let mut ecc_curve_list = EccCurveList::new(); for _ in 0..EccCurveList::MAX_SIZE { ecc_curve_list .add(EccCurveIdentifier::NistP256) .expect("Failed to add the maximum amount of ECC curves"); } assert_eq!( Err(Error::WrapperError(WrapperErrorKind::WrongParamSize)), ecc_curve_list.add(EccCurveIdentifier::NistP256), "Added more ECC curves than should've been possible" ); } #[test] fn test_invalid_size_tpml() { let tpml = TPML_ECC_CURVE { count: (EccCurveList::MAX_SIZE + 1) as u32, eccCurves: [0; 508], }; assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), EccCurveList::try_from(tpml), "Converting from TPML_ECC_CURVE did not produce the expected failure" ); } #[test] fn test_invalid_size_vec() { let vec = vec![EccCurveIdentifier::NistP256; EccCurveList::MAX_SIZE + 1]; assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), EccCurveList::try_from(vec), "Converting from vector of curves did not produce the expected failure" ); } tss-esapi-7.4.0/tests/integration_tests/structures_tests/lists_tests/handle_list_tests.rs000064400000000000000000000105221046102023000305560ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; use tss_esapi::{ constants::tss::{TPM2_PERSISTENT_FIRST, TPM2_TRANSIENT_FIRST}, handles::{PermanentTpmHandle, PersistentTpmHandle, TpmHandle, TransientTpmHandle}, structures::HandleList, tss2_esys::{TPM2_HANDLE, TPML_HANDLE}, Error, WrapperErrorKind, }; #[test] fn test_conversions() { let expected_handles: Vec = vec![ PermanentTpmHandle::First.into(), (PersistentTpmHandle::try_from(TPM2_PERSISTENT_FIRST).unwrap()).into(), (TransientTpmHandle::try_from(TPM2_TRANSIENT_FIRST).unwrap()).into(), ]; let mut handle_list = HandleList::new(); for handle in expected_handles.iter() { handle_list .add(*handle) .expect("Failed to add handle to list"); } assert_eq!(expected_handles.len(), handle_list.len()); expected_handles .iter() .zip(handle_list.as_ref().iter()) .for_each(|(expected, actual)| { assert_eq!( expected, actual, "The created handle list did not contain the expected values" ); }); let tpml_handle = TPML_HANDLE::try_from(handle_list).expect("failed to convert to TPML_HANDLE"); assert_eq!( expected_handles.len(), tpml_handle.count as usize, "The number of handles in the TPML_HANDLE is different than expected" ); expected_handles .iter() .zip(tpml_handle.handle[..expected_handles.len()].iter()) .for_each(|(expected, actual)| { assert_eq!( TPM2_HANDLE::from(*expected), *actual, "Got mismatch between expected FFI handle and actual handle" ) }); let handle_list = HandleList::try_from(tpml_handle).expect("Failed to convert from TPML_HANDLE"); assert_eq!( expected_handles.len(), handle_list.len(), "Converted handle list has a different length" ); expected_handles .iter() .zip(handle_list.as_ref().iter()) .for_each(|(expected, actual)| { assert_eq!( expected, actual, "The converted handle list did not contain the expected values" ); }); } #[test] fn test_vector_conversion() { let expected_handles: Vec = vec![ PermanentTpmHandle::First.into(), (PersistentTpmHandle::try_from(TPM2_PERSISTENT_FIRST).unwrap()).into(), (TransientTpmHandle::try_from(TPM2_TRANSIENT_FIRST).unwrap()).into(), ]; let handle_list = HandleList::try_from(expected_handles.clone()).expect("Failed to convert from vector"); expected_handles .iter() .zip(handle_list.as_ref().iter()) .for_each(|(expected, actual)| { assert_eq!( expected, actual, "The converted handle list did not contain the expected values" ); }); let converted_handles = Vec::::from(handle_list); assert_eq!( expected_handles, converted_handles, "Converted vector did not match initial vector" ); } #[test] fn test_add_too_many() { let mut handle_list = HandleList::new(); for _ in 0..HandleList::MAX_SIZE { handle_list .add(PermanentTpmHandle::First.into()) .expect("Failed to add the maximum amount of handles"); } assert_eq!( Err(Error::WrapperError(WrapperErrorKind::WrongParamSize)), handle_list.add(PermanentTpmHandle::First.into()), "Added more handles than should've been possible" ); } #[test] fn test_invalid_size_tpml() { let tpml = TPML_HANDLE { count: (HandleList::MAX_SIZE + 1) as u32, handle: [0; 254], }; assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), HandleList::try_from(tpml), "Converting from TPML_HANDLE did not produce the expected failure" ); } #[test] fn test_invalid_size_vec() { let vec = vec![TpmHandle::Permanent(PermanentTpmHandle::First); HandleList::MAX_SIZE + 1]; assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), HandleList::try_from(vec), "Converting from vector of handles did not produce the expected failure" ); } tss-esapi-7.4.0/tests/integration_tests/structures_tests/lists_tests/mod.rs000064400000000000000000000006311046102023000256250ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod algorithm_property_list_tests; mod command_code_attributes_list_tests; mod command_code_list_tests; mod digest_list_tests; mod ecc_curve_list_tests; mod handle_list_tests; mod pcr_selection_list_builder_tests; mod pcr_selection_list_tests; mod tagged_pcr_property_list_tests; mod tagged_tpm_property_list_tests; ././@LongLink00006440000000000000000000000151000000000000007770Lustar tss-esapi-7.4.0/tests/integration_tests/structures_tests/lists_tests/pcr_selection_list_builder_tests.rstss-esapi-7.4.0/tests/integration_tests/structures_tests/lists_tests/pcr_selection_list_builder_test000064400000000000000000000156021046102023000330600ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use num_traits::ToPrimitive; use std::convert::TryFrom; use tss_esapi::{ constants::tss::TPM2_ALG_LAST, interface_types::algorithm::HashingAlgorithm, structures::{PcrSelectSize, PcrSelectionList, PcrSelectionListBuilder, PcrSlot}, tss2_esys::{TPM2_ALG_ID, TPML_PCR_SELECTION}, }; #[test] fn test_one_selection() { let pcr_selection_list = PcrSelectionListBuilder::new() .with_selection( HashingAlgorithm::Sha256, &[PcrSlot::Slot0, PcrSlot::Slot8, PcrSlot::Slot16], ) .build() .expect("Failed to createm PcrSelectionList"); let pcr_selection_list_size = pcr_selection_list.len(); let actual: TPML_PCR_SELECTION = pcr_selection_list.into(); assert_eq!(actual.count as usize, pcr_selection_list_size); // No size has been chosen so the default will be set. assert_eq!( actual.pcrSelections[0].sizeofSelect, PcrSelectSize::default().to_u8().unwrap() ); assert_eq!( actual.pcrSelections[0].hash, Into::::into(HashingAlgorithm::Sha256) ); assert_eq!(actual.pcrSelections[0].pcrSelect[0], 0b0000_0001); assert_eq!(actual.pcrSelections[0].pcrSelect[1], 0b0000_0001); assert_eq!(actual.pcrSelections[0].pcrSelect[2], 0b0000_0001); } #[test] fn test_multiple_selection() { let pcr_selection_list = PcrSelectionListBuilder::new() .with_selection( HashingAlgorithm::Sha256, &[PcrSlot::Slot0, PcrSlot::Slot8, PcrSlot::Slot16], ) .with_selection( HashingAlgorithm::Sha1, &[ PcrSlot::Slot1, PcrSlot::Slot8, PcrSlot::Slot10, PcrSlot::Slot20, PcrSlot::Slot23, ], ) .build() .expect("Failed to createm PcrSelectionList"); let pcr_selection_list_size = pcr_selection_list.len(); let actual: TPML_PCR_SELECTION = pcr_selection_list.into(); assert_eq!(actual.count as usize, pcr_selection_list_size); for pcr_selection in actual.pcrSelections[..actual.count as usize].iter() { assert_eq!( pcr_selection.sizeofSelect, PcrSelectSize::default().to_u8().unwrap() ); // The order is not specified. match HashingAlgorithm::try_from(pcr_selection.hash).unwrap() { HashingAlgorithm::Sha256 => { assert_eq!(pcr_selection.pcrSelect[0], 0b0000_0001); assert_eq!(pcr_selection.pcrSelect[1], 0b0000_0001); assert_eq!(pcr_selection.pcrSelect[2], 0b0000_0001); } HashingAlgorithm::Sha1 => { assert_eq!(pcr_selection.pcrSelect[0], 0b0000_0010); assert_eq!(pcr_selection.pcrSelect[1], 0b0000_0101); assert_eq!(pcr_selection.pcrSelect[2], 0b1001_0000); } _ => panic!("Encountered incorrect Hashing Algorithm"), } } } #[test] fn test_multiple_conversions() { let pcr_selection_list = PcrSelectionListBuilder::new() .with_size_of_select(Default::default()) .with_selection( HashingAlgorithm::Sha256, &[PcrSlot::Slot0, PcrSlot::Slot8, PcrSlot::Slot16], ) .build() .expect("Failed to create PcrSelectionList"); let pcr_selection_list_size = pcr_selection_list.len(); let converted: TPML_PCR_SELECTION = pcr_selection_list.into(); assert_eq!(converted.count as usize, pcr_selection_list_size); let from_converted = PcrSelectionList::try_from(converted).unwrap(); let re_converted: TPML_PCR_SELECTION = from_converted.into(); assert_eq!(converted.count, re_converted.count); assert_eq!( converted.pcrSelections[0].sizeofSelect, re_converted.pcrSelections[0].sizeofSelect ); assert_eq!( converted.pcrSelections[0].hash, re_converted.pcrSelections[0].hash ); assert_eq!( converted.pcrSelections[0].pcrSelect[0], re_converted.pcrSelections[0].pcrSelect[0] ); assert_eq!( converted.pcrSelections[0].pcrSelect[1], re_converted.pcrSelections[0].pcrSelect[1] ); assert_eq!( converted.pcrSelections[0].pcrSelect[2], re_converted.pcrSelections[0].pcrSelect[2] ); } #[test] fn test_conversion_of_data_with_invalid_pcr_select_bit_flags() { let expected_hash_algorithm = HashingAlgorithm::Sha256; let expected_pcr_slots = [PcrSlot::Slot0, PcrSlot::Slot8, PcrSlot::Slot16]; let mut tpml_pcr_selection: TPML_PCR_SELECTION = PcrSelectionListBuilder::new() .with_selection(expected_hash_algorithm, &expected_pcr_slots) .build() .expect("Failed to create PcrSelectionList") .into(); // Size of select is 3 indicating that only 3 first octets // should be parsed. Setting a value in the fourth // octet should not in any way affect the result. tpml_pcr_selection.pcrSelections[0].pcrSelect[3] = 1; let pcr_selection_list = PcrSelectionList::try_from(tpml_pcr_selection) .expect("Failed to parse TPML_PCR_SELECTION as PcrSelectionList"); assert_eq!( pcr_selection_list.len(), 1, "The converted pcr selection list contained more items then expected" ); assert_eq!( pcr_selection_list.get_selections()[0].size_of_select(), PcrSelectSize::ThreeOctets, "PcrSelection in index 0, in the converted pcr selection list, contained an unexpected 'size of select' value", ); assert_eq!( &pcr_selection_list.get_selections()[0].selected(), &expected_pcr_slots, "PcrSelection in index 0, in the converted pcr selection list, contained one or more unexpected PcrSlot values", ); } #[test] fn test_conversion_of_data_with_invalid_size_of_select() { let mut tpml_pcr_selection: TPML_PCR_SELECTION = PcrSelectionListBuilder::new() .with_selection( HashingAlgorithm::Sha256, &[PcrSlot::Slot0, PcrSlot::Slot8, PcrSlot::Slot16], ) .build() .expect("Failed to create PcrSelectionList") .into(); // 1,2,3,4 are theonly valid values for sizeofSelect. tpml_pcr_selection.pcrSelections[0].sizeofSelect = 20; // The try_from should then fail. PcrSelectionList::try_from(tpml_pcr_selection).unwrap_err(); } #[test] fn test_conversion_of_data_with_invalid_hash_alg_id() { let mut tpml_pcr_selection: TPML_PCR_SELECTION = PcrSelectionListBuilder::new() .with_selection( HashingAlgorithm::Sha256, &[PcrSlot::Slot0, PcrSlot::Slot8, PcrSlot::Slot16], ) .build() .expect("Failed to create PcrSelectionList") .into(); // Si tpml_pcr_selection.pcrSelections[0].hash = TPM2_ALG_LAST + 1; // The try_from should then fail. PcrSelectionList::try_from(tpml_pcr_selection).unwrap_err(); } tss-esapi-7.4.0/tests/integration_tests/structures_tests/lists_tests/pcr_selection_list_tests.rs000064400000000000000000000421611046102023000321600ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; use tss_esapi::{ interface_types::algorithm::HashingAlgorithm, structures::{PcrSelectSize, PcrSelection, PcrSelectionList, PcrSlot}, tss2_esys::{TPML_PCR_SELECTION, TPMS_PCR_SELECTION}, Error, WrapperErrorKind, }; #[test] fn from_tpml_retains_order() { let selection_1 = PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::ThreeOctets, &[PcrSlot::Slot10], ) .expect("Failed to create PcrSelection 1"); let selection_1 = TPMS_PCR_SELECTION::try_from(selection_1) .expect("Failed to convert PcrSelection 1 into TPMS_PCR_SELECTION"); let selection_2 = PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::ThreeOctets, &[PcrSlot::Slot11], ) .expect("Failed to create PcrSelection 2"); let selection_2 = TPMS_PCR_SELECTION::try_from(selection_2) .expect("Failed to convert PcrSelection 2 into TPMS_PCR_SELECTION"); let selection_3 = PcrSelection::create( HashingAlgorithm::Sha1, PcrSelectSize::ThreeOctets, &[PcrSlot::Slot16], ) .expect("Failed to create PcrSelection 3"); let selection_3 = TPMS_PCR_SELECTION::try_from(selection_3) .expect("Failed to convert PcrSelection 3 into TPMS_PCR_SELECTION"); let selection_4 = PcrSelection::create( HashingAlgorithm::Sha1, PcrSelectSize::ThreeOctets, &[PcrSlot::Slot2], ) .expect("Failed to create PcrSelection 4"); let selection_4 = TPMS_PCR_SELECTION::try_from(selection_4) .expect("Failed to convert PcrSelection 4 into TPMS_PCR_SELECTION"); let tpml_selections = TPML_PCR_SELECTION { count: 4, pcrSelections: [ selection_1, selection_2, selection_3, selection_4, TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), ], }; let selections = PcrSelectionList::try_from(tpml_selections).unwrap(); let tpml_selections = TPML_PCR_SELECTION::try_from(selections).unwrap(); let selections = PcrSelectionList::try_from(tpml_selections).unwrap(); assert_eq!(selections.len(), 4); let sel_1 = selections.get_selections()[0]; let sel_2 = selections.get_selections()[1]; let sel_3 = selections.get_selections()[2]; let sel_4 = selections.get_selections()[3]; assert_eq!(sel_1.hashing_algorithm(), HashingAlgorithm::Sha256); assert!(!sel_1.is_empty()); assert!(sel_1.is_selected(PcrSlot::Slot10)); assert!(!sel_1.is_selected(PcrSlot::Slot11)); assert_eq!(sel_2.hashing_algorithm(), HashingAlgorithm::Sha256); assert!(!sel_2.is_empty()); assert!(sel_2.is_selected(PcrSlot::Slot11)); assert_eq!(sel_3.hashing_algorithm(), HashingAlgorithm::Sha1); assert!(!sel_3.is_empty()); assert!(sel_3.is_selected(PcrSlot::Slot16)); assert_eq!(sel_4.hashing_algorithm(), HashingAlgorithm::Sha1); assert!(!sel_4.is_empty()); assert!(sel_4.is_selected(PcrSlot::Slot2)); } #[test] fn test_subtract() { let pcr_selection_1 = PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::ThreeOctets, &[PcrSlot::Slot10], ) .expect("Failed to create PcrSelection 1"); let tpms_pcr_selection_1 = TPMS_PCR_SELECTION::try_from(pcr_selection_1) .expect("Failed to convert PcrSelection 1 into TPMS_PCR_SELECTION"); let pcr_selection_2 = PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::ThreeOctets, &[PcrSlot::Slot11], ) .expect("Failed to create PcrSelection 2"); let tpms_pcr_selection_2 = TPMS_PCR_SELECTION::try_from(pcr_selection_2) .expect("Failed to convert PcrSelection 2 into TPMS_PCR_SELECTION"); let tpms_pcr_selection_3 = TPMS_PCR_SELECTION::try_from( PcrSelection::create( HashingAlgorithm::Sha1, PcrSelectSize::ThreeOctets, &[PcrSlot::Slot16], ) .expect("Failed to create PcrSelection 3"), ) .expect("Failed to convert PcrSelection 3 into TPMS_PCR_SELECTION"); let tpms_pcr_selection_4 = TPMS_PCR_SELECTION::try_from( PcrSelection::create( HashingAlgorithm::Sha1, PcrSelectSize::ThreeOctets, &[PcrSlot::Slot2], ) .expect("Failed to create PcrSelection 4"), ) .expect("Failed to convert PcrSelection 4 into TPMS_PCR_SELECTION"); let mut selection_list_1 = PcrSelectionList::try_from(TPML_PCR_SELECTION { count: 4, pcrSelections: [ tpms_pcr_selection_1, tpms_pcr_selection_2, tpms_pcr_selection_3, tpms_pcr_selection_4, TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), ], }) .expect("Failed to convert selection list 1"); let selection_list_2 = PcrSelectionList::try_from(TPML_PCR_SELECTION { count: 2, pcrSelections: [ tpms_pcr_selection_3, tpms_pcr_selection_4, TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), ], }) .expect("Failed to convert selection list 2"); selection_list_1 .subtract(&selection_list_2) .expect("Failed to subtract selection_list_2 from selection_list_1"); let selected_pcrs = selection_list_1.get_selections(); assert_eq!( selected_pcrs.len(), 2, "There are more pcr selections in the pcr selection list then expected" ); assert_eq!( selected_pcrs[0], pcr_selection_1, "The first selection does not have expected values" ); assert_eq!( selected_pcrs[1], pcr_selection_2, "The second selection does not have expected values" ); } #[test] fn test_subtract_overlapping_without_remaining() { let tpms_pcr_selection_1 = TPMS_PCR_SELECTION::try_from( PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::ThreeOctets, &[PcrSlot::Slot10], ) .expect("Failed to create PcrSelection 1"), ) .expect("Failed to convert PcrSelection 1 into TPMS_PCR_SELECTION"); let tpms_pcr_selection_2 = TPMS_PCR_SELECTION::try_from( PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::ThreeOctets, &[PcrSlot::Slot11], ) .expect("Failed to create PcrSelection 2"), ) .expect("Failed to convert PcrSelection 2 into TPMS_PCR_SELECTION"); let tpms_pcr_selection_3 = TPMS_PCR_SELECTION::try_from( PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::ThreeOctets, &[PcrSlot::Slot10, PcrSlot::Slot11], ) .expect("Failed to create PcrSelection 3"), ) .expect("Failed to convert PcrSelection 3 into TPMS_PCR_SELECTION"); let mut selection_list_1 = PcrSelectionList::try_from(TPML_PCR_SELECTION { count: 2, pcrSelections: [ tpms_pcr_selection_1, tpms_pcr_selection_2, TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), ], }) .expect("Failed to convert selection list 1"); let selection_list_2 = PcrSelectionList::try_from(TPML_PCR_SELECTION { count: 1, pcrSelections: [ tpms_pcr_selection_3, TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), ], }) .expect("Failed to convert selection list 2"); selection_list_1 .subtract(&selection_list_2) .expect("Failed to subtract selection_list_2 from selection_list_1"); let selected_pcrs = selection_list_1.get_selections(); assert_eq!( selected_pcrs.len(), 0, "There are more pcr selections in the pcr selection list then expected" ); } #[test] fn test_subtract_overlapping_with_remaining() { let tpms_pcr_selection_1 = TPMS_PCR_SELECTION::try_from( PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::ThreeOctets, &[PcrSlot::Slot10], ) .expect("Failed to create PcrSelection 1"), ) .expect("Failed to convert PcrSelection 1 into TPMS_PCR_SELECTION"); let tpms_pcr_selection_2 = TPMS_PCR_SELECTION::try_from( PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::ThreeOctets, &[PcrSlot::Slot11], ) .expect("Failed to create PcrSelection 2"), ) .expect("Failed to convert PcrSelection 2 into TPMS_PCR_SELECTION"); let expected = PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::ThreeOctets, &[PcrSlot::Slot12], ) .expect("Failed to create PcrSelection 'expected'"); let tpms_pcr_selection_3 = TPMS_PCR_SELECTION::try_from(expected) .expect("Failed to convert PcrSelection 'expected' into TPMS_PCR_SELECTION"); let tpms_pcr_selection_4 = TPMS_PCR_SELECTION::try_from( PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::ThreeOctets, &[PcrSlot::Slot10, PcrSlot::Slot11], ) .expect("Failed to create PcrSelection 4"), ) .expect("Failed to convert PcrSelection 4 into TPMS_PCR_SELECTION"); let mut selection_list_1 = PcrSelectionList::try_from(TPML_PCR_SELECTION { count: 3, pcrSelections: [ tpms_pcr_selection_1, tpms_pcr_selection_2, tpms_pcr_selection_3, TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), ], }) .expect("Failed to convert selection list 1"); let selection_list_2 = PcrSelectionList::try_from(TPML_PCR_SELECTION { count: 1, pcrSelections: [ tpms_pcr_selection_4, TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), ], }) .expect("Failed to convert selection list 2"); selection_list_1 .subtract(&selection_list_2) .expect("Failed to subtract selection_list_2 from selection_list_1"); let selected_pcrs = selection_list_1.get_selections(); assert_eq!( selected_pcrs.len(), 1, "There are more pcr selections in the pcr selection list then expected" ); assert_eq!( selected_pcrs[0], expected, "The first selection does not have expected values" ); } #[test] fn test_invalid_subtraction() { let pcr_selection_1 = PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::ThreeOctets, &[PcrSlot::Slot10], ) .expect("Failed to create PcrSelection 1"); let tpms_pcr_selection_1 = TPMS_PCR_SELECTION::try_from(pcr_selection_1) .expect("Failed to convert PcrSelection 1 into TPMS_PCR_SELECTION"); let pcr_selection_2 = PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::ThreeOctets, &[PcrSlot::Slot11], ) .expect("Failed to create PcrSelection 2"); let tpms_pcr_selection_2 = TPMS_PCR_SELECTION::try_from(pcr_selection_2) .expect("Failed to convert PcrSelection 2 into TPMS_PCR_SELECTION"); let tpms_pcr_selection_3 = TPMS_PCR_SELECTION::try_from( PcrSelection::create( HashingAlgorithm::Sha1, PcrSelectSize::ThreeOctets, &[PcrSlot::Slot16], ) .expect("Failed to create PcrSelection 3"), ) .expect("Failed to convert PcrSelection 3 into TPMS_PCR_SELECTION"); let tpms_pcr_selection_4 = TPMS_PCR_SELECTION::try_from( PcrSelection::create( HashingAlgorithm::Sha1, PcrSelectSize::ThreeOctets, &[PcrSlot::Slot2], ) .expect("Failed to create PcrSelection 4"), ) .expect("Failed to convert PcrSelection 4 into TPMS_PCR_SELECTION"); let mut selection_list_1 = PcrSelectionList::try_from(TPML_PCR_SELECTION { count: 2, pcrSelections: [ tpms_pcr_selection_1, tpms_pcr_selection_2, TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), ], }) .expect("Failed to convert selection list 1"); let selection_list_2 = PcrSelectionList::try_from(TPML_PCR_SELECTION { count: 4, pcrSelections: [ tpms_pcr_selection_1, tpms_pcr_selection_2, tpms_pcr_selection_3, tpms_pcr_selection_4, TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), TPMS_PCR_SELECTION::default(), ], }) .expect("Failed to convert selection list 2"); let subtract_result = selection_list_1.subtract(&selection_list_2); assert_eq!( subtract_result, Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), "PcrSelectionList subtract method did not produce expected error for invalid parameters" ); } ././@LongLink00006440000000000000000000000147000000000000007775Lustar tss-esapi-7.4.0/tests/integration_tests/structures_tests/lists_tests/tagged_pcr_property_list_tests.rstss-esapi-7.4.0/tests/integration_tests/structures_tests/lists_tests/tagged_pcr_property_list_tests.000064400000000000000000000065371046102023000330340ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryInto; use tss_esapi::{ constants::PcrPropertyTag, structures::{PcrSelectSize, PcrSlot, TaggedPcrPropertyList, TaggedPcrSelect}, tss2_esys::TPML_TAGGED_PCR_PROPERTY, }; #[test] fn test_valid_conversions() { let expected_tagged_pcr_properties = vec![ TaggedPcrSelect::create( PcrPropertyTag::Auth, PcrSelectSize::ThreeOctets, &[PcrSlot::Slot1, PcrSlot::Slot8, PcrSlot::Slot17], ) .expect("Failed to create TaggedPcrSelect 1"), TaggedPcrSelect::create( PcrPropertyTag::DrtmReset, PcrSelectSize::TwoOctets, &[PcrSlot::Slot2, PcrSlot::Slot9], ) .expect("Failed to create TaggedPcrSelect 2"), TaggedPcrSelect::create( PcrPropertyTag::ExtendL0, PcrSelectSize::OneOctet, &[ PcrSlot::Slot4, PcrSlot::Slot5, PcrSlot::Slot6, PcrSlot::Slot7, ], ) .expect("Failed to create TaggedPcrSelect 3"), ]; let expected_tpml_tagged_pcr_property: TPML_TAGGED_PCR_PROPERTY = expected_tagged_pcr_properties .iter() .fold(Default::default(), |mut acc, &v| { acc.pcrProperty[acc.count as usize] = v.into(); acc.count += 1; acc }); let tagged_pcr_property_list_from_vec: TaggedPcrPropertyList = expected_tagged_pcr_properties .clone() .try_into() .expect("Failed to convert Vec into TaggedPcrPropertyList"); assert_eq!( expected_tagged_pcr_properties.len(), tagged_pcr_property_list_from_vec.len(), "Mismatch in 'len()' between the Vec and the TaggedPcrPropertyList(from vec)" ); expected_tagged_pcr_properties .iter() .zip(tagged_pcr_property_list_from_vec.as_ref()) .for_each(|(expected, actual)| { assert_eq!(expected, actual, "Mismatch between an expected TaggedPcrSelect in the Vec the actual tagged property in TaggedPcrPropertyList(from vec)"); }); let tagged_pcr_property_list_from_tss: TaggedPcrPropertyList = expected_tpml_tagged_pcr_property .try_into() .expect("Failed to convert TPML_TAGGED_PCR_PROPERTY into TaggedPcrPropertyList"); assert_eq!( expected_tagged_pcr_properties.len(), tagged_pcr_property_list_from_tss.len(), "Mismatch in 'len()' between the Vec and the TaggedPcrPropertyList(from tss)" ); expected_tagged_pcr_properties .iter() .zip(tagged_pcr_property_list_from_tss.as_ref()) .for_each(|(expected, actual)| { assert_eq!(expected, actual, "Mismatch between an expected TaggedPcrSelect in the Vec and the actual tagged property in TaggedPcrPropertyList(from tss)"); }); let actual_tpml_tagged_pcr_property: TPML_TAGGED_PCR_PROPERTY = tagged_pcr_property_list_from_vec.into(); crate::common::ensure_tpml_tagged_pcr_property_equality( &expected_tpml_tagged_pcr_property, &actual_tpml_tagged_pcr_property, ); } ././@LongLink00006440000000000000000000000147000000000000007775Lustar tss-esapi-7.4.0/tests/integration_tests/structures_tests/lists_tests/tagged_tpm_property_list_tests.rstss-esapi-7.4.0/tests/integration_tests/structures_tests/lists_tests/tagged_tpm_property_list_tests.000064400000000000000000000121251046102023000330360ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::{TryFrom, TryInto}; use tss_esapi::{ constants::PropertyTag, structures::{TaggedProperty, TaggedTpmPropertyList}, tss2_esys::{TPML_TAGGED_TPM_PROPERTY, TPMS_TAGGED_PROPERTY}, Error, WrapperErrorKind, }; #[test] fn test_valid_conversions() { let expected_tagged_properties: Vec = vec![ TaggedProperty::new(PropertyTag::FamilyIndicator, 8u32), TaggedProperty::new(PropertyTag::Level, 12u32), TaggedProperty::new(PropertyTag::HrLoadedMin, 24u32), ]; let expected_tpml_tagged_tpm_property: TPML_TAGGED_TPM_PROPERTY = expected_tagged_properties .iter() .fold(Default::default(), |mut acc, v| { acc.tpmProperty[acc.count as usize] = TPMS_TAGGED_PROPERTY::from(*v); acc.count += 1; acc }); let tagged_tpm_property_list_from_vec: TaggedTpmPropertyList = expected_tagged_properties .clone() .try_into() .expect("Failed to convert Vec into TaggedTpmPropertyList"); assert_eq!( expected_tagged_properties.len(), tagged_tpm_property_list_from_vec.len(), "Mismatch in 'len()' between the Vec and the TaggedTpmPropertyList(from vec)" ); expected_tagged_properties .iter() .zip(tagged_tpm_property_list_from_vec.as_ref()) .for_each(|(expected, actual)| { assert_eq!(expected, actual, "Mismatch between an expected TaggedProperty in the Vec the actual tagged property in TaggedTpmPropertyList(from vec)"); }); let tagged_tpm_property_list_from_tss: TaggedTpmPropertyList = expected_tpml_tagged_tpm_property .try_into() .expect("Failed to convert TPML_TAGGED_TPM_PROPERTY into TaggedTpmPropertyList"); assert_eq!( expected_tagged_properties.len(), tagged_tpm_property_list_from_tss.len(), "Mismatch in 'len()' between the Vec and the TaggedTpmPropertyList(from tss)" ); expected_tagged_properties .iter() .zip(tagged_tpm_property_list_from_tss.as_ref()) .for_each(|(expected, actual)| { assert_eq!(expected, actual, "Mismatch between an expected TaggedProperty in the Vec the actual tagged property in TaggedTpmPropertyList(from tss)"); }); let actual_tpml_tagged_tpm_property: TPML_TAGGED_TPM_PROPERTY = tagged_tpm_property_list_from_vec.into(); crate::common::ensure_tpml_tagged_tpm_property_equality( &expected_tpml_tagged_tpm_property, &actual_tpml_tagged_tpm_property, ); } #[test] fn test_invalid_conversions() { assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), TaggedTpmPropertyList::try_from(vec![TaggedProperty::new(PropertyTag::FamilyIndicator, 8u32); TaggedTpmPropertyList::MAX_SIZE + 1]), "Converting a vector with to many elements into a TaggedTpmPropertyList did not produce the expected error", ); assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), TaggedTpmPropertyList::try_from(TPML_TAGGED_TPM_PROPERTY { count: TaggedTpmPropertyList::MAX_SIZE as u32 + 1u32, tpmProperty: [Default::default(); 127], }), "Converting a TPML_TAGGED_TPM_PROPERTY with an invalid 'count' value into a TaggedTpmPropertyList did not produce the expected error", ); } #[test] fn test_find() { let tagged_tpm_property_list: TaggedTpmPropertyList = vec![ TaggedProperty::new(PropertyTag::FamilyIndicator, 8u32), TaggedProperty::new(PropertyTag::Level, 12u32), TaggedProperty::new(PropertyTag::HrLoadedMin, 24u32), ] .try_into() .expect("Failed to convert Vec into TaggedTpmPropertyList"); assert_eq!( &TaggedProperty::new(PropertyTag::FamilyIndicator, 8u32), tagged_tpm_property_list .find(PropertyTag::FamilyIndicator) .expect("Calling find with PropertyTag::FamilyIndicator returned an unexpected 'None'"), "'find(PropertyTag::FamilyIndicator)' did not return the expected TaggedProperty value", ); assert_eq!( &TaggedProperty::new(PropertyTag::Level, 12u32), tagged_tpm_property_list .find(PropertyTag::Level) .expect("Calling find with PropertyTag::Level returned an unexpected 'None'"), "'find(PropertyTag::Level)' did not return the expected TaggedProperty value", ); assert_eq!( &TaggedProperty::new(PropertyTag::HrLoadedMin, 24u32), tagged_tpm_property_list .find(PropertyTag::HrLoadedMin) .expect("Calling find with PropertyTag::HrLoadedMin returned an unexpected 'None'"), "'find(PropertyTag::HrLoadedMin)' did not return the expected TaggedProperty value", ); assert!( tagged_tpm_property_list .find(PropertyTag::AlgorithmSet) .is_none(), "A value that should not exist was found in the TaggedTpmPropertyList" ); } tss-esapi-7.4.0/tests/integration_tests/structures_tests/mod.rs000064400000000000000000000010401046102023000232400ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod algorithm_property_tests; mod attest_info_test; mod attest_tests; mod buffers_tests; mod capability_data_tests; mod certify_info_tests; mod clock_info_tests; mod command_audit_info_tests; mod creation_info_tests; mod lists_tests; mod nv_certify_info_tests; mod pcr_tests; mod quote_info_tests; mod session_audit_info_tests; mod tagged_pcr_select_tests; mod tagged_property_tests; mod tagged_tests; mod time_attest_info_tests; mod time_info_tests; tss-esapi-7.4.0/tests/integration_tests/structures_tests/nv_certify_info_tests.rs000064400000000000000000000033251046102023000270760ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::{TryFrom, TryInto}; use tss_esapi::{ structures::{MaxNvBuffer, Name, NvCertifyInfo}, tss2_esys::TPMS_NV_CERTIFY_INFO, }; #[test] fn test_conversion() { let expected_index_name = Name::try_from(vec![0xf0u8; 68]).expect("Failed to create index name"); let expected_offset = 12u16; let expected_nv_contents = MaxNvBuffer::try_from(vec![0xfc; 2048]).expect("Failed to create nv contents"); let expected_tpms_nv_certify_info = TPMS_NV_CERTIFY_INFO { indexName: expected_index_name.clone().into(), offset: expected_offset, nvContents: expected_nv_contents.clone().into(), }; let nv_certify_info: NvCertifyInfo = expected_tpms_nv_certify_info .try_into() .expect("Failed to convert TPMS_NV_CERTIFY_INFO into NvCertifyInfo"); assert_eq!( &expected_index_name, nv_certify_info.index_name(), "The NvCertifyInfo converted from TPMS_NV_CERTIFY_INFO did not contain correct value for 'index name'", ); assert_eq!( expected_offset, nv_certify_info.offset(), "The NvCertifyInfo converted from TPMS_NV_CERTIFY_INFO did not contain correct value for 'offset'", ); assert_eq!( &expected_nv_contents, nv_certify_info.nv_contents(), "The NvCertifyInfo converted from TPMS_NV_CERTIFY_INFO did not contain correct value for 'nv contents'", ); let actual_tpms_nv_certify_info: TPMS_NV_CERTIFY_INFO = nv_certify_info.into(); crate::common::ensure_tpms_nv_certify_info_equality( &expected_tpms_nv_certify_info, &actual_tpms_nv_certify_info, ); } tss-esapi-7.4.0/tests/integration_tests/structures_tests/pcr_tests/mod.rs000064400000000000000000000002731046102023000252550ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod pcr_select_size_tests; mod pcr_select_tests; mod pcr_selection_tests; mod pcr_slot_tests; tss-esapi-7.4.0/tests/integration_tests/structures_tests/pcr_tests/pcr_select_size_tests.rs000064400000000000000000000124601046102023000310760ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; use tss_esapi::{structures::PcrSelectSize, Error, WrapperErrorKind}; fn bad_u8_values() -> Vec { let mut bad_values = Vec::::with_capacity(u8::MAX as usize); bad_values.push(0); bad_values.extend(5u8..=u8::MAX); bad_values } macro_rules! test_valid_conversions { (PcrSelectSize::$expected:ident, $value:expr) => { let expected_u8 = $value; let expected_u32 = $value; let expected_usize = $value; assert_eq!( expected_u8, PcrSelectSize::$expected.as_u8(), "The PcrSelectSize as_u8() method for {} did not give the expected u8 value {}", stringify!(PcrSelectSize::$expected), expected_u8 ); assert_eq!( expected_u32, PcrSelectSize::$expected.as_u32(), "The PcrSelectSize as_u32() method for {} did not give the expected u32 value {}", stringify!(PcrSelectSize::$expected), expected_u32 ); assert_eq!( expected_usize, PcrSelectSize::$expected.as_usize(), "The PcrSelectSize as_usize() method for {} did not give the expected usize value {}", stringify!(PcrSelectSize::$expected), expected_usize ); assert_eq!( PcrSelectSize::$expected, PcrSelectSize::try_parse_u8(expected_u8).expect(&format!( "try_parse_u8 failed to parse value {}", expected_u8 )), "The u8 value {} did not get parsed as the expected {}", expected_u8, stringify!(PcrSelectSize::$expected), ); assert_eq!( PcrSelectSize::$expected, PcrSelectSize::try_parse_u32(expected_u32).expect(&format!( "try_parse_u32 failed to parse value {}", expected_u32 )), "The u32 value {} did not get parsed as the expected {}", expected_u32, stringify!(PcrSelectSize::$expected), ); assert_eq!( PcrSelectSize::$expected, PcrSelectSize::try_parse_usize(expected_usize).expect(&format!( "try_parse_usize failed to parse value {}", expected_usize )), "The usize value {} did not get parsed as the expected {}", expected_u32, stringify!(PcrSelectSize::$expected), ); assert_eq!( PcrSelectSize::$expected, PcrSelectSize::try_from(expected_u8).expect(&format!( "Failed to convert u8 value {} to a PcrSelectSize", expected_u8 )), "The value {} did not get converted into the expected {}", expected_u8, stringify!(PcrSelectSize::$expected), ); assert_eq!( expected_u8, u8::try_from(PcrSelectSize::$expected).expect(&format!( "Failed to convert {} to u8 value", stringify!(PcrSelectSize::$expected) )), "{} did not get converted into the expected u8 value {}", stringify!(PcrSelectSize::$expected), expected_u8, ); }; } #[test] fn test_valid_conversions() { test_valid_conversions!(PcrSelectSize::OneOctet, 1); test_valid_conversions!(PcrSelectSize::TwoOctets, 2); test_valid_conversions!(PcrSelectSize::ThreeOctets, 3); test_valid_conversions!(PcrSelectSize::FourOctets, 4); } #[test] fn test_invalid_conversions() { for value in bad_u8_values() { assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), PcrSelectSize::try_from(value), "Converting an invalid size_of_select value {} did not result in the expected error", value, ); } } #[test] fn test_default() { // The default valuen should be the value that // works on most platforms i.e. three octets. assert_eq!( PcrSelectSize::ThreeOctets, PcrSelectSize::default(), "PcrSelectSize did not have the expected default value", ); } #[test] fn test_try_parse_u8_with_invalid_values() { for value in bad_u8_values() { assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), PcrSelectSize::try_parse_u8(value), "try_parse_u8 using an invalid size_of_select value {} did not result in the expected error", value, ); } } #[test] fn test_try_parse_u32_with_invalid_values() { for value in bad_u8_values() { assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), PcrSelectSize::try_parse_u32(value as u32), "try_parse_u32 using an invalid size_of_select value {} did not result in the expected error", value, ); } } #[test] fn test_try_parse_usize_with_invalid_values() { for value in bad_u8_values() { assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), PcrSelectSize::try_parse_usize(value as usize), "try_parse_usize using an invalid size_of_select value {} did not result in the expected error", value, ); } } tss-esapi-7.4.0/tests/integration_tests/structures_tests/pcr_tests/pcr_select_tests.rs000064400000000000000000000051561046102023000300500ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; use tss_esapi::{ structures::{PcrSelect, PcrSelectSize, PcrSlot}, tss2_esys::TPMS_PCR_SELECT, }; #[test] fn test_conversion_to_tss_pcr_select() { let actual = TPMS_PCR_SELECT::try_from( PcrSelect::create(PcrSelectSize::TwoOctets, &[PcrSlot::Slot0, PcrSlot::Slot8]) .expect("Failed to create PcrSelect"), ) .expect("Failed to convert PcrSelect into TPMS_PCR_SELECT"); let expected = TPMS_PCR_SELECT { sizeofSelect: 2, pcrSelect: [1, 1, 0, 0], }; assert_eq!(expected.sizeofSelect, actual.sizeofSelect); assert_eq!(expected.pcrSelect, actual.pcrSelect); } #[test] fn test_size_of_select_handling() { let actual = PcrSelect::try_from(TPMS_PCR_SELECT { sizeofSelect: 3, pcrSelect: [2, 1, 3, 5], }) .expect("Failed to convert TPMS_PCR_SELECT to PcrSelect"); // Size of select is 3 so no values set in the fourth // octet should be present. let expected = PcrSelect::create( PcrSelectSize::ThreeOctets, &[ PcrSlot::Slot1, PcrSlot::Slot8, PcrSlot::Slot16, PcrSlot::Slot17, ], ) .expect("Failed to create PcrSelect"); assert_eq!(expected, actual); } #[test] fn test_conversion_from_tss_pcr_select() { let actual = PcrSelect::try_from(TPMS_PCR_SELECT { sizeofSelect: 3, pcrSelect: [2, 1, 3, 0], }) .unwrap(); let expected = PcrSelect::create( PcrSelectSize::ThreeOctets, &[ PcrSlot::Slot1, PcrSlot::Slot8, PcrSlot::Slot16, PcrSlot::Slot17, ], ) .expect("Failed to create PcrSelect"); assert_eq!(expected, actual); } #[test] fn test_size_of_select() { let expected_pcr_select_size = PcrSelectSize::ThreeOctets; let pcr_select = PcrSelect::create( expected_pcr_select_size, &[ PcrSlot::Slot1, PcrSlot::Slot8, PcrSlot::Slot16, PcrSlot::Slot17, ], ) .expect("Failed to create PcrSelect"); assert_eq!(expected_pcr_select_size, pcr_select.size_of_select()); } #[test] fn test_selected_pcrs() { let expected_selected_pcrs = vec![ PcrSlot::Slot1, PcrSlot::Slot8, PcrSlot::Slot16, PcrSlot::Slot17, ]; let pcr_select = PcrSelect::create(PcrSelectSize::default(), expected_selected_pcrs.as_slice()) .expect("Failed to create PcrSelect"); assert_eq!(expected_selected_pcrs, pcr_select.selected_pcrs()); } tss-esapi-7.4.0/tests/integration_tests/structures_tests/pcr_tests/pcr_selection_tests.rs000064400000000000000000000227711046102023000305600ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; use tss_esapi::{ constants::tss::{TPM2_ALG_SHA256, TPM2_ALG_SHA512}, interface_types::algorithm::HashingAlgorithm, structures::{PcrSelectSize, PcrSelection, PcrSlot}, tss2_esys::TPMS_PCR_SELECTION, Error, WrapperErrorKind, }; #[test] fn test_conversion_to_tss_pcr_selection() { let actual = TPMS_PCR_SELECTION::try_from( PcrSelection::create( HashingAlgorithm::Sha512, PcrSelectSize::ThreeOctets, &[PcrSlot::Slot3, PcrSlot::Slot9, PcrSlot::Slot23], ) .expect("Failed to create pcr selection"), ) .expect("Failed to convert PcrSelection to TPMS_PCR_SELECTION"); let expected = TPMS_PCR_SELECTION { hash: TPM2_ALG_SHA512, sizeofSelect: 3, pcrSelect: [8, 2, 128, 0], }; assert_eq!(expected.hash, actual.hash); assert_eq!(expected.sizeofSelect, actual.sizeofSelect); assert_eq!(expected.pcrSelect, actual.pcrSelect); } #[test] fn test_conversion_from_tss_pcr_selection() { let actual = PcrSelection::try_from(TPMS_PCR_SELECTION { hash: TPM2_ALG_SHA256, sizeofSelect: 2, pcrSelect: [16, 128, 0, 0], }) .unwrap(); let expected = PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::TwoOctets, &[PcrSlot::Slot4, PcrSlot::Slot15], ) .expect("Failed to create pcr selection"); assert_eq!(expected, actual); } #[test] fn test_size_of_select_handling() { let actual = PcrSelection::try_from(TPMS_PCR_SELECTION { hash: TPM2_ALG_SHA256, sizeofSelect: 2, pcrSelect: [16, 128, 5, 1], }) .expect("Failed to convert TPMS_PCR_SELECTION into a PcrSelection"); // Size of select is 2 so the values in octet 3 and 4 // should not appear in the converted pcr selection. let expected = PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::TwoOctets, &[PcrSlot::Slot4, PcrSlot::Slot15], ) .expect("Failed to create PcrSelection"); assert_eq!(expected, actual); } #[test] fn test_subtract() { let mut pcr_selection_1 = PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::TwoOctets, &[PcrSlot::Slot4, PcrSlot::Slot15], ) .expect("Failed to create PcrSelection pcr_selection_1"); let pcr_selection_2 = PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::TwoOctets, &[PcrSlot::Slot4], ) .expect("Failed to create PcrSelection pcr_selection_2"); pcr_selection_1 .subtract_exact(&pcr_selection_2) .expect("Failed to subtract pcr_selection_2 from pcr_selection_1"); assert_eq!( pcr_selection_1.hashing_algorithm(), HashingAlgorithm::Sha256, "The pcr_selection_1 did not contain expected HashingAlgorithm after subtract" ); assert_eq!( pcr_selection_1.size_of_select(), PcrSelectSize::TwoOctets, "The pcr_selection_1 did not have the expected size of select after subtract" ); assert_eq!( pcr_selection_1.selected(), vec![PcrSlot::Slot15], "The pcr_selection_1 did not contain expected PcrSlots after subtract" ); } #[test] fn test_deselect() { let mut pcr_selection = PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::TwoOctets, &[ PcrSlot::Slot4, PcrSlot::Slot5, PcrSlot::Slot6, PcrSlot::Slot7, PcrSlot::Slot15, ], ) .expect("Failed to create PcrSelection pcr_selection"); pcr_selection.deselect(PcrSlot::Slot7); assert_eq!( PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::TwoOctets, &[ PcrSlot::Slot4, PcrSlot::Slot5, PcrSlot::Slot6, PcrSlot::Slot15, ], ) .expect("Failed to create PcrSelection"), pcr_selection, "PcrSelection did not match expected value after calling deselect." ) } #[test] fn test_merge_exact() { let mut pcr_selection_1 = PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::TwoOctets, &[PcrSlot::Slot4, PcrSlot::Slot15], ) .expect("Failed to create PcrSelection pcr_selection_1"); let pcr_selection_2 = PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::TwoOctets, &[PcrSlot::Slot5], ) .expect("Failed to create PcrSelection pcr_selection_2"); pcr_selection_1 .merge_exact(&pcr_selection_2) .expect("Failed to exactly merge pcr_selection_2 into pcr_selection_1"); assert_eq!( PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::TwoOctets, &[PcrSlot::Slot4, PcrSlot::Slot5, PcrSlot::Slot15], ) .expect("Failed to create PcrSelection"), pcr_selection_1, "PcrSelection did not contain expected value calling merge_exact", ); } #[test] fn test_merge_exact_hasahing_algorithm_mismatch_errors() { let mut pcr_selection_1 = PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::TwoOctets, &[PcrSlot::Slot5], ) .expect("Failed to create PcrSelection pcr_selection_1"); let pcr_selection_2 = PcrSelection::create( HashingAlgorithm::Sha384, PcrSelectSize::TwoOctets, &[PcrSlot::Slot6], ) .expect("Failed to create PcrSelection pcr_selection_2"); assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), pcr_selection_1.merge_exact(&pcr_selection_2), "Merge exact PcrSelections with different hashing algorithm did not produce the expected error", ); } #[test] fn test_merge_exact_size_of_select_mismatch_errors() { let mut pcr_selection_1 = PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::ThreeOctets, &[PcrSlot::Slot5], ) .expect("Failed to create PcrSelection pcr_selection_1"); let pcr_selection_2 = PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::TwoOctets, &[PcrSlot::Slot6], ) .expect("Failed to create PcrSelection pcr_selection_2"); assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), pcr_selection_1.merge_exact(&pcr_selection_2), "Merge exact PcrSelections with different size of select did not produce the expected error", ); } #[test] fn test_merge_exact_non_unique_pcr_slot_errors() { let mut pcr_selection_1 = PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::ThreeOctets, &[PcrSlot::Slot5], ) .expect("Failed to create PcrSelection pcr_selection_1"); let pcr_selection_2 = PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::ThreeOctets, &[PcrSlot::Slot5], ) .expect("Failed to create PcrSelection pcr_selection_2"); assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), pcr_selection_1.merge_exact(&pcr_selection_2), "Merge exact PcrSelections with non unique PcrSlot did not produce the expected error", ); } #[test] fn test_subtract_exact_hasahing_algorithm_mismatch_errors() { let mut pcr_selection_1 = PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::TwoOctets, &[PcrSlot::Slot5], ) .expect("Failed to create PcrSelection pcr_selection_1"); let pcr_selection_2 = PcrSelection::create( HashingAlgorithm::Sha384, PcrSelectSize::TwoOctets, &[PcrSlot::Slot5], ) .expect("Failed to create PcrSelection pcr_selection_2"); assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InconsistentParams)), pcr_selection_1.subtract_exact(&pcr_selection_2), "Subtract exact PcrSelections with different hashing algorithm did not produce the expected error", ); } #[test] fn test_subtract_exact_size_of_select_mismatch_errors() { let mut pcr_selection_1 = PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::ThreeOctets, &[PcrSlot::Slot5], ) .expect("Failed to create PcrSelection pcr_selection_1"); let pcr_selection_2 = PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::TwoOctets, &[PcrSlot::Slot5], ) .expect("Failed to create PcrSelection pcr_selection_2"); assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), pcr_selection_1.subtract_exact(&pcr_selection_2), "Subtract exact PcrSelections with different size of select did not produce the expected error", ); } #[test] fn test_subtract_exact_unique_pcr_slot_errors() { let mut pcr_selection_1 = PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::ThreeOctets, &[PcrSlot::Slot5], ) .expect("Failed to create PcrSelection pcr_selection_1"); let pcr_selection_2 = PcrSelection::create( HashingAlgorithm::Sha256, PcrSelectSize::ThreeOctets, &[PcrSlot::Slot6], ) .expect("Failed to create PcrSelection pcr_selection_2"); assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), pcr_selection_1.subtract_exact(&pcr_selection_2), "Subtract exact PcrSelections with unique PcrSlot did not produce the expected error", ); } tss-esapi-7.4.0/tests/integration_tests/structures_tests/pcr_tests/pcr_slot_tests.rs000064400000000000000000000166741046102023000275610ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; use tss_esapi::{structures::PcrSlot, tss2_esys::TPM2_PCR_SELECT_MAX, Error, WrapperErrorKind}; #[test] fn test_conversion_to_u32() { assert_eq!(0x0000_0001u32, PcrSlot::Slot0.into()); assert_eq!(0x0000_0002u32, PcrSlot::Slot1.into()); assert_eq!(0x0000_0004u32, PcrSlot::Slot2.into()); assert_eq!(0x0000_0008u32, PcrSlot::Slot3.into()); assert_eq!(0x0000_0010u32, PcrSlot::Slot4.into()); assert_eq!(0x0000_0020u32, PcrSlot::Slot5.into()); assert_eq!(0x0000_0040u32, PcrSlot::Slot6.into()); assert_eq!(0x0000_0080u32, PcrSlot::Slot7.into()); assert_eq!(0x0000_0100u32, PcrSlot::Slot8.into()); assert_eq!(0x0000_0200u32, PcrSlot::Slot9.into()); assert_eq!(0x0000_0400u32, PcrSlot::Slot10.into()); assert_eq!(0x0000_0800u32, PcrSlot::Slot11.into()); assert_eq!(0x0000_1000u32, PcrSlot::Slot12.into()); assert_eq!(0x0000_2000u32, PcrSlot::Slot13.into()); assert_eq!(0x0000_4000u32, PcrSlot::Slot14.into()); assert_eq!(0x0000_8000u32, PcrSlot::Slot15.into()); assert_eq!(0x0001_0000u32, PcrSlot::Slot16.into()); assert_eq!(0x0002_0000u32, PcrSlot::Slot17.into()); assert_eq!(0x0004_0000u32, PcrSlot::Slot18.into()); assert_eq!(0x0008_0000u32, PcrSlot::Slot19.into()); assert_eq!(0x0010_0000u32, PcrSlot::Slot20.into()); assert_eq!(0x0020_0000u32, PcrSlot::Slot21.into()); assert_eq!(0x0040_0000u32, PcrSlot::Slot22.into()); assert_eq!(0x0080_0000u32, PcrSlot::Slot23.into()); } macro_rules! convert_from_u32_test { ($value:expr, $slot_number:path) => { assert_eq!( PcrSlot::try_from($value).expect(&format!( "Failed to convert {} to {}", $value, stringify!($slot_number) )), $slot_number, ); }; } #[test] fn test_conversion_from_u32() { convert_from_u32_test!(0x0000_0001u32, PcrSlot::Slot0); convert_from_u32_test!(0x0000_0002u32, PcrSlot::Slot1); convert_from_u32_test!(0x0000_0004u32, PcrSlot::Slot2); convert_from_u32_test!(0x0000_0008u32, PcrSlot::Slot3); convert_from_u32_test!(0x0000_0010u32, PcrSlot::Slot4); convert_from_u32_test!(0x0000_0020u32, PcrSlot::Slot5); convert_from_u32_test!(0x0000_0040u32, PcrSlot::Slot6); convert_from_u32_test!(0x0000_0080u32, PcrSlot::Slot7); convert_from_u32_test!(0x0000_0100u32, PcrSlot::Slot8); convert_from_u32_test!(0x0000_0200u32, PcrSlot::Slot9); convert_from_u32_test!(0x0000_0400u32, PcrSlot::Slot10); convert_from_u32_test!(0x0000_0800u32, PcrSlot::Slot11); convert_from_u32_test!(0x0000_1000u32, PcrSlot::Slot12); convert_from_u32_test!(0x0000_2000u32, PcrSlot::Slot13); convert_from_u32_test!(0x0000_4000u32, PcrSlot::Slot14); convert_from_u32_test!(0x0000_8000u32, PcrSlot::Slot15); convert_from_u32_test!(0x0001_0000u32, PcrSlot::Slot16); convert_from_u32_test!(0x0002_0000u32, PcrSlot::Slot17); convert_from_u32_test!(0x0004_0000u32, PcrSlot::Slot18); convert_from_u32_test!(0x0008_0000u32, PcrSlot::Slot19); convert_from_u32_test!(0x0010_0000u32, PcrSlot::Slot20); convert_from_u32_test!(0x0020_0000u32, PcrSlot::Slot21); convert_from_u32_test!(0x0040_0000u32, PcrSlot::Slot22); convert_from_u32_test!(0x0080_0000u32, PcrSlot::Slot23); } #[test] fn test_conversion_from_u32_errors() { assert_eq!( PcrSlot::try_from(0u32), Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), ); assert_eq!( PcrSlot::try_from(1234u32), Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), ); } macro_rules! convert_to_tss_type_test { ($value:expr, $slot_number:path) => { let expected: [u8; TPM2_PCR_SELECT_MAX as usize] = $value.to_le_bytes(); let actual: [u8; TPM2_PCR_SELECT_MAX as usize] = $slot_number.into(); assert_eq!(expected, actual); }; } #[test] fn test_conversion_to_tss_type() { convert_to_tss_type_test!(0x0000_0001u32, PcrSlot::Slot0); convert_to_tss_type_test!(0x0000_0002u32, PcrSlot::Slot1); convert_to_tss_type_test!(0x0000_0004u32, PcrSlot::Slot2); convert_to_tss_type_test!(0x0000_0008u32, PcrSlot::Slot3); convert_to_tss_type_test!(0x0000_0010u32, PcrSlot::Slot4); convert_to_tss_type_test!(0x0000_0020u32, PcrSlot::Slot5); convert_to_tss_type_test!(0x0000_0040u32, PcrSlot::Slot6); convert_to_tss_type_test!(0x0000_0080u32, PcrSlot::Slot7); convert_to_tss_type_test!(0x0000_0100u32, PcrSlot::Slot8); convert_to_tss_type_test!(0x0000_0200u32, PcrSlot::Slot9); convert_to_tss_type_test!(0x0000_0400u32, PcrSlot::Slot10); convert_to_tss_type_test!(0x0000_0800u32, PcrSlot::Slot11); convert_to_tss_type_test!(0x0000_1000u32, PcrSlot::Slot12); convert_to_tss_type_test!(0x0000_2000u32, PcrSlot::Slot13); convert_to_tss_type_test!(0x0000_4000u32, PcrSlot::Slot14); convert_to_tss_type_test!(0x0000_8000u32, PcrSlot::Slot15); convert_to_tss_type_test!(0x0001_0000u32, PcrSlot::Slot16); convert_to_tss_type_test!(0x0002_0000u32, PcrSlot::Slot17); convert_to_tss_type_test!(0x0004_0000u32, PcrSlot::Slot18); convert_to_tss_type_test!(0x0008_0000u32, PcrSlot::Slot19); convert_to_tss_type_test!(0x0010_0000u32, PcrSlot::Slot20); convert_to_tss_type_test!(0x0020_0000u32, PcrSlot::Slot21); convert_to_tss_type_test!(0x0040_0000u32, PcrSlot::Slot22); convert_to_tss_type_test!(0x0080_0000u32, PcrSlot::Slot23); } macro_rules! convert_from_tss_type_test { ($value:expr, $slot_number:path) => { assert_eq!( PcrSlot::try_from($value).expect(&format!("TSS data to {}", stringify!($slot_number))), $slot_number, ); }; } #[test] fn test_conversion_from_tss_type() { convert_from_tss_type_test!([1u8, 0u8, 0u8, 0u8], PcrSlot::Slot0); convert_from_tss_type_test!([2u8, 0u8, 0u8, 0u8], PcrSlot::Slot1); convert_from_tss_type_test!([4u8, 0u8, 0u8, 0u8], PcrSlot::Slot2); convert_from_tss_type_test!([8u8, 0u8, 0u8, 0u8], PcrSlot::Slot3); convert_from_tss_type_test!([16u8, 0u8, 0u8, 0u8], PcrSlot::Slot4); convert_from_tss_type_test!([32u8, 0u8, 0u8, 0u8], PcrSlot::Slot5); convert_from_tss_type_test!([64u8, 0u8, 0u8, 0u8], PcrSlot::Slot6); convert_from_tss_type_test!([128u8, 0u8, 0u8, 0u8], PcrSlot::Slot7); convert_from_tss_type_test!([0u8, 1u8, 0u8, 0u8], PcrSlot::Slot8); convert_from_tss_type_test!([0u8, 2u8, 0u8, 0u8], PcrSlot::Slot9); convert_from_tss_type_test!([0u8, 4u8, 0u8, 0u8], PcrSlot::Slot10); convert_from_tss_type_test!([0u8, 8u8, 0u8, 0u8], PcrSlot::Slot11); convert_from_tss_type_test!([0u8, 16u8, 0u8, 0u8], PcrSlot::Slot12); convert_from_tss_type_test!([0u8, 32u8, 0u8, 0u8], PcrSlot::Slot13); convert_from_tss_type_test!([0u8, 64u8, 0u8, 0u8], PcrSlot::Slot14); convert_from_tss_type_test!([0u8, 128u8, 0u8, 0u8], PcrSlot::Slot15); convert_from_tss_type_test!([0u8, 0u8, 1u8, 0u8], PcrSlot::Slot16); convert_from_tss_type_test!([0u8, 0u8, 2u8, 0u8], PcrSlot::Slot17); convert_from_tss_type_test!([0u8, 0u8, 4u8, 0u8], PcrSlot::Slot18); convert_from_tss_type_test!([0u8, 0u8, 8u8, 0u8], PcrSlot::Slot19); convert_from_tss_type_test!([0u8, 0u8, 16u8, 0u8], PcrSlot::Slot20); convert_from_tss_type_test!([0u8, 0u8, 32u8, 0u8], PcrSlot::Slot21); convert_from_tss_type_test!([0u8, 0u8, 64u8, 0u8], PcrSlot::Slot22); convert_from_tss_type_test!([0u8, 0u8, 128u8, 0u8], PcrSlot::Slot23); } tss-esapi-7.4.0/tests/integration_tests/structures_tests/quote_info_tests.rs000064400000000000000000000032031046102023000260560ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; use tss_esapi::{ interface_types::algorithm::HashingAlgorithm, structures::{Digest, PcrSelectionListBuilder, PcrSlot, QuoteInfo}, tss2_esys::TPMS_QUOTE_INFO, }; #[test] fn test_conversion() { let expected_pcr_selection = PcrSelectionListBuilder::new() .with_selection( HashingAlgorithm::Sha256, &[ PcrSlot::Slot1, PcrSlot::Slot2, PcrSlot::Slot3, PcrSlot::Slot4, ], ) .build() .expect("Failed to pcr selection list"); let expected_pcr_digest = Digest::try_from(vec![0xffu8; 32]).expect("Failed to create digest"); let expected_tpms_quote_info = TPMS_QUOTE_INFO { pcrSelect: expected_pcr_selection.clone().into(), pcrDigest: expected_pcr_digest.clone().into(), }; let quote_info = QuoteInfo::try_from(expected_tpms_quote_info) .expect("Failed to create QuoteInfo from TPMS_QUOTE_INFO"); assert_eq!( &expected_pcr_selection, quote_info.pcr_selection(), "The QuoteInfo converted from TPMS_QUOTE_INFO did not contain the expected PCR selection" ); assert_eq!( &expected_pcr_digest, quote_info.pcr_digest(), "The QuoteInfo converted from TPMS_QUOTE_INFO did not contain the expected PCR digest" ); let actual_tpms_quote_info: TPMS_QUOTE_INFO = quote_info.into(); crate::common::ensure_tpms_quote_info_equality( &expected_tpms_quote_info, &actual_tpms_quote_info, ); } tss-esapi-7.4.0/tests/integration_tests/structures_tests/session_audit_info_tests.rs000064400000000000000000000030411046102023000275720ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; use tss_esapi::{ interface_types::YesNo, structures::{Digest, SessionAuditInfo}, tss2_esys::TPMS_SESSION_AUDIT_INFO, }; #[test] fn test_conversion() { let expected_exclusive_session = YesNo::Yes; let expected_session_digest = Digest::try_from(vec![0xffu8; 32]).expect("Failed to session digest"); let expected_tpms_session_audit_info = TPMS_SESSION_AUDIT_INFO { exclusiveSession: expected_exclusive_session.into(), sessionDigest: expected_session_digest.clone().into(), }; let session_audit_info = SessionAuditInfo::try_from(expected_tpms_session_audit_info) .expect("Unable to convert TPMS_SESSION_AUDIT_INFO into SessionAuditInfo"); assert_eq!( bool::from(expected_exclusive_session), session_audit_info.exlusive_session(), "The SessionAuditInfo that was converted from TPMS_SESSION_AUDIT_INFO, did not contain the expected value for 'exclusive session'", ); assert_eq!( &expected_session_digest, session_audit_info.session_digest(), "The SessionAuditInfo that was converted from TPMS_SESSION_AUDIT_INFO, did not contain the expected value for 'session digest'", ); let actual_tpms_session_audit_info: TPMS_SESSION_AUDIT_INFO = session_audit_info.into(); crate::common::ensure_tpms_session_audit_info_equality( &expected_tpms_session_audit_info, &actual_tpms_session_audit_info, ); } tss-esapi-7.4.0/tests/integration_tests/structures_tests/tagged_pcr_select_tests.rs000064400000000000000000000034431046102023000273520ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryInto; use tss_esapi::{ constants::PcrPropertyTag, structures::{PcrSelectSize, PcrSlot, TaggedPcrSelect}, tss2_esys::TPMS_TAGGED_PCR_SELECT, }; #[test] fn test_conversions() { let expected_pcr_property_tag = PcrPropertyTag::ExtendL0; let expected_size_of_select = PcrSelectSize::ThreeOctets; let expected_pcr_slots = vec![ PcrSlot::Slot1, PcrSlot::Slot8, PcrSlot::Slot16, PcrSlot::Slot17, ]; // [2, 1, 3, X], X doesn't matter because size of select is three octets let expected_tpms_tagged_pcr_select = TPMS_TAGGED_PCR_SELECT { tag: expected_pcr_property_tag.into(), sizeofSelect: expected_size_of_select.as_u8(), pcrSelect: [2, 1, 3, 0], }; let tagged_pcr_select: TaggedPcrSelect = expected_tpms_tagged_pcr_select .try_into() .expect("Failed to convert TPMS_TAGGED_PCR_SELECT into TaggedPcrSelect"); assert_eq!( expected_pcr_property_tag, tagged_pcr_select.pcr_property_tag(), "Converted TaggedPcrSelect did not contain the expected pcr property tag value" ); assert_eq!( expected_size_of_select, tagged_pcr_select.size_of_select(), "Converted TaggedPcrSelect did not contain the expected size of select value" ); assert_eq!( expected_pcr_slots, tagged_pcr_select.selected_pcrs(), "Converted TaggedPcrSelect did not contain the expected PCR slot values" ); let actual_tpms_tagged_pcr_select: TPMS_TAGGED_PCR_SELECT = tagged_pcr_select.into(); crate::common::ensure_tpms_tagged_pcr_select_equality( &expected_tpms_tagged_pcr_select, &actual_tpms_tagged_pcr_select, ); } tss-esapi-7.4.0/tests/integration_tests/structures_tests/tagged_property_tests.rs000064400000000000000000000022721046102023000271120ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use tss_esapi::{ constants::PropertyTag, structures::TaggedProperty, tss2_esys::TPMS_TAGGED_PROPERTY, }; use std::convert::TryInto; #[test] fn test_conversions() { let expected_property = PropertyTag::AlgorithmSet; let expected_value = 1u32; let expected_tpms_tagged_property = TPMS_TAGGED_PROPERTY { property: expected_property.into(), value: expected_value, }; let tagged_property: TaggedProperty = expected_tpms_tagged_property .try_into() .expect("Failed to convert TPMS_TAGGED_PROPERTY"); assert_eq!( tagged_property.property(), expected_property, "Converted TaggedProperty did not contain the expected property value" ); assert_eq!( tagged_property.value(), expected_value, "Converted TaggedProperty did not contain expected value in the value field", ); let actual_tpms_tagged_property: TPMS_TAGGED_PROPERTY = tagged_property.into(); crate::common::ensure_tpms_tagged_property_equality( &expected_tpms_tagged_property, &actual_tpms_tagged_property, ); } tss-esapi-7.4.0/tests/integration_tests/structures_tests/tagged_tests/mod.rs000064400000000000000000000005501046102023000257220ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod parameters_tests; mod public; mod public_ecc_parameters_tests; mod public_rsa_exponent_tests; mod public_rsa_parameters_tests; mod sensitive; mod signature; mod symmetric_definition_object_tests; mod symmetric_definition_tests; mod tagged_signature_scheme_tests; tss-esapi-7.4.0/tests/integration_tests/structures_tests/tagged_tests/parameters_tests.rs000064400000000000000000000141741046102023000305370ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; use tss_esapi::{ constants::AlgorithmIdentifier, interface_types::{ algorithm::{HashingAlgorithm, PublicAlgorithm}, ecc::EccCurve, key_bits::RsaKeyBits, }, structures::{ EccScheme, HmacScheme, KeyDerivationFunctionScheme, KeyedHashScheme, PublicEccParameters, PublicKeyedHashParameters, PublicParameters, PublicRsaParameters, RsaScheme, SymmetricCipherParameters, SymmetricDefinitionObject, }, tss2_esys::{TPMT_PUBLIC_PARMS, TPMU_PUBLIC_PARMS}, Error, WrapperErrorKind, }; #[test] fn test_valid_rsa_parameters_conversions() { let expected_public_rsa_parameters = PublicRsaParameters::builder() .with_restricted(true) .with_is_decryption_key(true) .with_scheme(RsaScheme::Null) .with_symmetric(SymmetricDefinitionObject::AES_128_CFB) .with_key_bits(RsaKeyBits::Rsa1024) .build() .expect("Failed to build public rsa parameters"); let expected_tpmt_public_parms = TPMT_PUBLIC_PARMS { type_: PublicAlgorithm::Rsa.into(), parameters: TPMU_PUBLIC_PARMS { rsaDetail: expected_public_rsa_parameters.into(), }, }; let actual_public_parameters = PublicParameters::try_from(expected_tpmt_public_parms) .expect("Failed to convert TPMT_PUBLIC_PARMS into PublicParameters"); if let PublicParameters::Rsa(actual_public_rsa_parameters) = actual_public_parameters { assert_eq!( expected_public_rsa_parameters, actual_public_rsa_parameters, "PublicRsaParameters converted from TPMT_PUBLIC_PARMS did not contain the expected values" ); } else { panic!("TPMT_PUBLIC_PARMS did not convert into the expected value"); } crate::common::ensure_tpmt_public_parms_equality( &expected_tpmt_public_parms, &actual_public_parameters.into(), ); } #[test] fn test_valid_ecc_parameters_conversion() { let expected_public_ecc_parameters = PublicEccParameters::builder() .with_restricted(true) .with_is_decryption_key(true) .with_ecc_scheme(EccScheme::Null) .with_curve(EccCurve::NistP256) .with_key_derivation_function_scheme(KeyDerivationFunctionScheme::Null) .with_symmetric(SymmetricDefinitionObject::AES_128_CFB) .build() .expect("Failed to build public ECC parameters"); let expected_tpmt_public_parms = TPMT_PUBLIC_PARMS { type_: PublicAlgorithm::Ecc.into(), parameters: TPMU_PUBLIC_PARMS { eccDetail: expected_public_ecc_parameters.into(), }, }; let actual_public_parameters = PublicParameters::try_from(expected_tpmt_public_parms) .expect("Failed to convert TPMT_PUBLIC_PARMS into PublicParameters"); if let PublicParameters::Ecc(actual_public_ecc_parameters) = actual_public_parameters { assert_eq!( expected_public_ecc_parameters, actual_public_ecc_parameters, "PublicEccParameters converted from TPMT_PUBLIC_PARMS did not contain the expected values" ); } else { panic!("TPMT_PUBLIC_PARMS did not convert into the expected value"); } crate::common::ensure_tpmt_public_parms_equality( &expected_tpmt_public_parms, &actual_public_parameters.into(), ); } #[test] fn test_valid_keyed_hash_parameters_conversion() { let expected_public_keyed_hash_parameters = PublicKeyedHashParameters::new(KeyedHashScheme::Hmac { hmac_scheme: HmacScheme::new(HashingAlgorithm::Sha256), }); let expected_tpmt_public_parms = TPMT_PUBLIC_PARMS { type_: PublicAlgorithm::KeyedHash.into(), parameters: TPMU_PUBLIC_PARMS { keyedHashDetail: expected_public_keyed_hash_parameters.into(), }, }; let actual_public_parameters = PublicParameters::try_from(expected_tpmt_public_parms) .expect("Failed to convert TPMT_PUBLIC_PARMS into PublicParameters"); if let PublicParameters::KeyedHash(actual_public_keyed_hash_parameters) = actual_public_parameters { assert_eq!( expected_public_keyed_hash_parameters, actual_public_keyed_hash_parameters, "PublicKeyedHashParameters converted from TPMT_PUBLIC_PARMS did not contain the expected values" ); } else { panic!("TPMT_PUBLIC_PARMS did not convert into the expected value"); } crate::common::ensure_tpmt_public_parms_equality( &expected_tpmt_public_parms, &actual_public_parameters.into(), ); } #[test] fn test_valid_symmetric_cipher_parameters_conversion() { let expected_symmetric_cipher_parameters = SymmetricCipherParameters::new(SymmetricDefinitionObject::AES_128_CFB); let expected_tpmt_public_parms = TPMT_PUBLIC_PARMS { type_: PublicAlgorithm::SymCipher.into(), parameters: TPMU_PUBLIC_PARMS { symDetail: expected_symmetric_cipher_parameters.into(), }, }; let actual_public_parameters = PublicParameters::try_from(expected_tpmt_public_parms) .expect("Failed to convert TPMT_PUBLIC_PARMS into PublicParameters"); if let PublicParameters::SymCipher(actual_public_symmetric_cipher_parameters) = actual_public_parameters { assert_eq!( expected_symmetric_cipher_parameters, actual_public_symmetric_cipher_parameters, "SymmetricCipherParameters converted from TPMT_PUBLIC_PARMS did not contain the expected values" ); } else { panic!("TPMT_PUBLIC_PARMS did not convert into the expected value"); } crate::common::ensure_tpmt_public_parms_equality( &expected_tpmt_public_parms, &actual_public_parameters.into(), ); } #[test] fn test_conversion_failure_due_to_invalid_public_algorithm() { assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), PublicParameters::try_from(TPMT_PUBLIC_PARMS { type_: AlgorithmIdentifier::Sha256.into(), parameters: Default::default(), }) ); } tss-esapi-7.4.0/tests/integration_tests/structures_tests/tagged_tests/public.rs000064400000000000000000000022561046102023000264260ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; use tss_esapi::{ structures::{Public, PublicBuffer}, tss2_esys::TPM2B_PUBLIC, }; #[test] fn marshall_unmarshall() { crate::common::publics() .iter() .for_each(crate::common::check_marshall_unmarshall); } #[test] fn tpm2b_conversion() { crate::common::publics().iter().for_each(|public| { let public = public.clone(); let tpm2b = TPM2B_PUBLIC::try_from(public.clone()) .expect("Failed to convert from Public to TPM2B_PUBLIC"); let buf = PublicBuffer::try_from(public.clone()) .expect("Failed to convert from Public to PublicBuffer"); assert_eq!( buf, PublicBuffer::try_from(tpm2b) .expect("Failed to convert from PublicBuffer to TPM2B_PUBLIC") ); assert_eq!( public, Public::try_from(buf).expect("Failed to convert from PublicBuffer to Public") ); assert_eq!( public, Public::try_from(tpm2b).expect("Failed to convert from TPM2B_PUBLIC to Public") ) }); } tss-esapi-7.4.0/tests/integration_tests/structures_tests/tagged_tests/public_ecc_parameters_tests.rs000064400000000000000000000061141046102023000327020ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use tss_esapi::interface_types::algorithm::*; use tss_esapi::interface_types::ecc::EccCurve; use tss_esapi::structures::*; use tss_esapi::Error; use tss_esapi::WrapperErrorKind; #[test] fn test_restricted_decryption_with_default_symmetric() { assert!(matches!( PublicEccParametersBuilder::new() .with_restricted(true) .with_is_decryption_key(true) .with_ecc_scheme(EccScheme::Null) .with_curve(EccCurve::NistP256) .with_key_derivation_function_scheme(KeyDerivationFunctionScheme::Null) .build(), Err(Error::WrapperError(WrapperErrorKind::ParamsMissing)) )); } #[test] fn test_restricted_decryption_with_null_symmetric() { assert!(matches!( PublicEccParametersBuilder::new() .with_restricted(true) .with_is_decryption_key(true) .with_ecc_scheme(EccScheme::Null) .with_curve(EccCurve::NistP256) .with_key_derivation_function_scheme(KeyDerivationFunctionScheme::Null) .with_symmetric(SymmetricDefinitionObject::Null) .build(), Err(Error::WrapperError(WrapperErrorKind::InconsistentParams)) )); } #[test] fn test_restricted_decryption_with_wrong_symmetric() { assert!(PublicEccParametersBuilder::new() .with_restricted(true) .with_is_decryption_key(true) .with_ecc_scheme(EccScheme::Null) .with_curve(EccCurve::NistP256) .with_key_derivation_function_scheme(KeyDerivationFunctionScheme::Null) .with_symmetric(SymmetricDefinitionObject::AES_128_CFB) .build() .is_ok()); } #[test] fn test_signing_with_default_symmetric() { assert!(PublicEccParametersBuilder::new() .with_restricted(false) .with_is_decryption_key(false) .with_is_signing_key(true) .with_ecc_scheme( EccScheme::create( EccSchemeAlgorithm::EcDsa, Some(HashingAlgorithm::Sha256), None ) .unwrap() ) .with_curve(EccCurve::NistP256) .with_key_derivation_function_scheme(KeyDerivationFunctionScheme::Null) .with_symmetric(SymmetricDefinitionObject::Null) .build() .is_ok()); } #[test] fn test_signing_with_wrong_symmetric() { assert!(matches!( PublicEccParametersBuilder::new() .with_restricted(false) .with_is_decryption_key(false) .with_is_signing_key(true) .with_ecc_scheme( EccScheme::create( EccSchemeAlgorithm::EcDsa, Some(HashingAlgorithm::Sha256), None ) .unwrap() ) .with_curve(EccCurve::NistP256) .with_key_derivation_function_scheme(KeyDerivationFunctionScheme::Null) .with_symmetric(SymmetricDefinitionObject::AES_128_CFB) .build(), Err(Error::WrapperError(WrapperErrorKind::InconsistentParams)) )); } tss-esapi-7.4.0/tests/integration_tests/structures_tests/tagged_tests/public_rsa_exponent_tests.rs000064400000000000000000000007211046102023000324300ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use tss_esapi::structures::RsaExponent; #[test] fn rsa_exponent_value_test() { let expected_value = 97; let rsa_exponent = RsaExponent::create(expected_value).unwrap_or_else(|_| { panic!( "Failed to create a RsaExponent from the value {}", expected_value ) }); assert_eq!(expected_value, rsa_exponent.value()); } tss-esapi-7.4.0/tests/integration_tests/structures_tests/tagged_tests/public_rsa_parameters_tests.rs000064400000000000000000000044231046102023000327360ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use tss_esapi::interface_types::key_bits::RsaKeyBits; use tss_esapi::structures::*; use tss_esapi::Error; use tss_esapi::WrapperErrorKind; #[test] fn test_restricted_decryption_with_default_symmetric() { assert!(matches!( PublicRsaParametersBuilder::new() .with_restricted(true) .with_is_decryption_key(true) .with_scheme(RsaScheme::Null) .with_key_bits(RsaKeyBits::Rsa1024) .build(), Err(Error::WrapperError(WrapperErrorKind::ParamsMissing)) )); } #[test] fn test_restricted_decryption_with_null_symmetric() { assert!(matches!( PublicRsaParametersBuilder::new() .with_restricted(true) .with_is_decryption_key(true) .with_scheme(RsaScheme::Null) .with_symmetric(SymmetricDefinitionObject::Null) .with_key_bits(RsaKeyBits::Rsa1024) .build(), Err(Error::WrapperError(WrapperErrorKind::InconsistentParams)) )); } #[test] fn test_restricted_decryption_with_wrong_symmetric() { assert!(PublicRsaParametersBuilder::new() .with_restricted(true) .with_is_decryption_key(true) .with_scheme(RsaScheme::Null) .with_symmetric(SymmetricDefinitionObject::AES_128_CFB) .with_key_bits(RsaKeyBits::Rsa1024) .build() .is_ok()); } #[test] fn test_signing_with_default_symmetric() { assert!(PublicRsaParametersBuilder::new() .with_restricted(false) .with_is_decryption_key(false) .with_is_signing_key(true) .with_scheme(RsaScheme::Null) .with_symmetric(SymmetricDefinitionObject::Null) .with_key_bits(RsaKeyBits::Rsa1024) .build() .is_ok()); } #[test] fn test_signing_with_wrong_symmetric() { assert!(matches!( PublicRsaParametersBuilder::new() .with_restricted(false) .with_is_decryption_key(false) .with_is_signing_key(true) .with_scheme(RsaScheme::Null) .with_symmetric(SymmetricDefinitionObject::AES_128_CFB) .with_key_bits(RsaKeyBits::Rsa1024) .build(), Err(Error::WrapperError(WrapperErrorKind::InconsistentParams)) )); } tss-esapi-7.4.0/tests/integration_tests/structures_tests/tagged_tests/sensitive.rs000064400000000000000000000024201046102023000271520ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; use tss_esapi::{ structures::{Sensitive, SensitiveBuffer}, tss2_esys::TPM2B_SENSITIVE, }; #[test] fn marshall_unmarshall() { crate::common::sensitives() .iter() .for_each(crate::common::check_marshall_unmarshall); } #[test] fn tpm2b_conversion() { crate::common::sensitives().iter().for_each(|sensitive| { let sensitive = sensitive.clone(); let tpm2b = TPM2B_SENSITIVE::try_from(sensitive.clone()) .expect("Failed to convert from Sensitive to TPM2B_SENSITIVE"); let buf = SensitiveBuffer::try_from(sensitive.clone()) .expect("Failed to convert from Sensitive to SensitiveBuffer"); assert_eq!( buf, SensitiveBuffer::try_from(tpm2b) .expect("Failed to convert from SensitiveBuffer to TPM2B_SENSITIVE") ); assert_eq!( sensitive, Sensitive::try_from(buf).expect("Failed to convert from SensitiveBuffer to Sensitive") ); assert_eq!( sensitive, Sensitive::try_from(tpm2b) .expect("Failed to convert from TPM2B_SENSITIVE to Sensitive") ) }); } tss-esapi-7.4.0/tests/integration_tests/structures_tests/tagged_tests/signature.rs000064400000000000000000000013511046102023000271440ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; use tss_esapi::{structures::Signature, tss2_esys::TPMT_SIGNATURE}; #[test] fn marshall_unmarshall() { crate::common::signatures() .iter() .for_each(crate::common::check_marshall_unmarshall); } #[test] fn tpmt_conversion() { crate::common::signatures().iter().for_each(|signature| { let signature = signature.clone(); let tpmt = TPMT_SIGNATURE::try_from(signature.clone()) .expect("Failed conversion to TPMT_SIGNATURE"); assert_eq!( signature, Signature::try_from(tpmt).expect("Failed conversion from TPMT_SIGNATURE") ); }); } ././@LongLink00006440000000000000000000000153000000000000007772Lustar tss-esapi-7.4.0/tests/integration_tests/structures_tests/tagged_tests/symmetric_definition_object_tests.rstss-esapi-7.4.0/tests/integration_tests/structures_tests/tagged_tests/symmetric_definition_object_te000064400000000000000000000151261046102023000327670ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; use tss_esapi::{ interface_types::{ algorithm::{SymmetricMode, SymmetricObject}, key_bits::{AesKeyBits, CamelliaKeyBits, Sm4KeyBits}, }, structures::SymmetricDefinitionObject, tss2_esys::{TPMT_SYM_DEF_OBJECT, TPMU_SYM_KEY_BITS, TPMU_SYM_MODE}, }; const SYM_MODES: [SymmetricMode; 5] = [ SymmetricMode::Cfb, SymmetricMode::Cbc, SymmetricMode::Ctr, SymmetricMode::Ecb, SymmetricMode::Ofb, ]; #[test] fn test_valid_aes_conversions() { const AES_KEY_BITS: [AesKeyBits; 3] = [AesKeyBits::Aes128, AesKeyBits::Aes192, AesKeyBits::Aes256]; for expected_mode in SYM_MODES { for expected_key_bits in AES_KEY_BITS { let expected_tpmt_sym_def_object = TPMT_SYM_DEF_OBJECT { algorithm: SymmetricObject::Aes.into(), keyBits: TPMU_SYM_KEY_BITS { aes: expected_key_bits.into(), }, mode: TPMU_SYM_MODE { aes: expected_mode.into(), }, }; let sym_def_object = SymmetricDefinitionObject::try_from(expected_tpmt_sym_def_object) .expect("Failed to convert TPMT_SYM_DEF_OBJECT into SymmetricDefinitionObject"); if let SymmetricDefinitionObject::Aes { key_bits, mode } = sym_def_object { assert_eq!( expected_key_bits, key_bits, "TPMT_SYM_DEF_OBJECT converted into SymmetricDefinitionObject did not contain the correct value for 'key_bits'" ); assert_eq!(expected_mode, mode, "TPMT_SYM_DEF_OBJECT converted into SymmetricDefinitionObject did not contain the correct value for 'mode'"); } else { panic!("SymmetricDefinitionObject converted from TPMT_SYM_DEF_OBJECT did not contain the expected algorithm AES"); } let actual_tpmt_sym_def_object = TPMT_SYM_DEF_OBJECT::try_from(sym_def_object) .expect("Failed to Convert SymmetricDefinitionObject into TPMT_SYM_DEF"); crate::common::ensure_tpmt_sym_def_object_equality( &expected_tpmt_sym_def_object, &actual_tpmt_sym_def_object, ); } } } #[test] fn test_valid_sm4_conversions() { for expected_mode in SYM_MODES { let expected_key_bits = Sm4KeyBits::Sm4_128; let expected_tpmt_sym_def_object = TPMT_SYM_DEF_OBJECT { algorithm: SymmetricObject::Sm4.into(), keyBits: TPMU_SYM_KEY_BITS { sm4: expected_key_bits.into(), }, mode: TPMU_SYM_MODE { sm4: expected_mode.into(), }, }; let sym_def_object = SymmetricDefinitionObject::try_from(expected_tpmt_sym_def_object) .expect("Failed to convert TPMT_SYM_DEF_OBJECT into SymmetricDefinitionObject"); if let SymmetricDefinitionObject::Sm4 { key_bits, mode } = sym_def_object { assert_eq!( expected_key_bits, key_bits, "TPMT_SYM_DEF_OBJECT converted into SymmetricDefinitionObject did not contain the correct value for 'key_bits'" ); assert_eq!(expected_mode, mode, "TPMT_SYM_DEF_OBJECT converted into SymmetricDefinitionObject did not contain the correct value for 'mode'"); } else { panic!("SymmetricDefinitionObject converted from TPMT_SYM_DEF_OBJECT did not contain the expected algorithm SM4"); } let actual_tpmt_sym_def_object = TPMT_SYM_DEF_OBJECT::try_from(sym_def_object) .expect("Failed to Convert SymmetricDefinitionObject into TPMT_SYM_DEF_OBJECT"); crate::common::ensure_tpmt_sym_def_object_equality( &expected_tpmt_sym_def_object, &actual_tpmt_sym_def_object, ); } } #[test] fn test_valid_camellia_conversions() { const CAMELLIA_KEY_BITS: [CamelliaKeyBits; 3] = [ CamelliaKeyBits::Camellia128, CamelliaKeyBits::Camellia192, CamelliaKeyBits::Camellia256, ]; for expected_mode in SYM_MODES { for expected_key_bits in CAMELLIA_KEY_BITS { let expected_tpmt_sym_def_object = TPMT_SYM_DEF_OBJECT { algorithm: SymmetricObject::Camellia.into(), keyBits: TPMU_SYM_KEY_BITS { camellia: expected_key_bits.into(), }, mode: TPMU_SYM_MODE { camellia: expected_mode.into(), }, }; let sym_def_object = SymmetricDefinitionObject::try_from(expected_tpmt_sym_def_object) .expect("Failed to convert TPMT_SYM_DEF_OBJECT into SymmetricDefinitionObject"); if let SymmetricDefinitionObject::Camellia { key_bits, mode } = sym_def_object { assert_eq!( expected_key_bits, key_bits, "TPMT_SYM_DEF_OBJECT converted into SymmetricDefinitionObject did not contain the correct value for 'key_bits'" ); assert_eq!(expected_mode, mode, "TPMT_SYM_DEF_OBJECT converted into SymmetricDefinitionObject did not contain the correct value for 'mode'"); } else { panic!("SymmetricDefinitionObject converted from TPMT_SYM_DEF_OBJECT did not contain the expected algorithm CAMELLIA"); } let actual_tpmt_sym_def_object = TPMT_SYM_DEF_OBJECT::try_from(sym_def_object) .expect("Failed to Convert SymmetricDefinition into TPMT_SYM_DEF_OBJECT"); crate::common::ensure_tpmt_sym_def_object_equality( &expected_tpmt_sym_def_object, &actual_tpmt_sym_def_object, ); } } } #[test] fn test_valid_null_conversions() { let expected_tpmt_sym_def_object = TPMT_SYM_DEF_OBJECT { algorithm: SymmetricObject::Null.into(), keyBits: Default::default(), mode: Default::default(), }; let sym_def_object = SymmetricDefinitionObject::try_from(expected_tpmt_sym_def_object) .expect("Failed to convert TPMT_SYM_DEF_OBJECT into SymmetricDefinitionObject"); if sym_def_object != SymmetricDefinitionObject::Null { panic!("SymmetricDefinitionObject converted from TPMT_SYM_DEF_OBJECT did not contain the expected algorithm NULL"); } let actual_tpmt_sym_def_object = TPMT_SYM_DEF_OBJECT::try_from(sym_def_object) .expect("Failed to Convert SymmetricDefinition into TPMT_SYM_DEF_OBJECT"); crate::common::ensure_tpmt_sym_def_object_equality( &expected_tpmt_sym_def_object, &actual_tpmt_sym_def_object, ); } tss-esapi-7.4.0/tests/integration_tests/structures_tests/tagged_tests/symmetric_definition_tests.rs000064400000000000000000000222731046102023000326170ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use tss_esapi::{ constants::AlgorithmIdentifier, interface_types::{ algorithm::{HashingAlgorithm, SymmetricAlgorithm, SymmetricMode}, key_bits::{AesKeyBits, CamelliaKeyBits, Sm4KeyBits}, }, structures::SymmetricDefinition, tss2_esys::{TPMT_SYM_DEF, TPMU_SYM_KEY_BITS, TPMU_SYM_MODE}, Error, WrapperErrorKind, }; use std::convert::TryFrom; const SYM_MODES: [SymmetricMode; 5] = [ SymmetricMode::Cfb, SymmetricMode::Cbc, SymmetricMode::Ctr, SymmetricMode::Ecb, SymmetricMode::Ofb, ]; #[test] fn test_valid_aes_conversions() { const AES_KEY_BITS: [AesKeyBits; 3] = [AesKeyBits::Aes128, AesKeyBits::Aes192, AesKeyBits::Aes256]; for expected_mode in SYM_MODES { for expected_key_bits in AES_KEY_BITS { let expected_tpmt_sym_def = TPMT_SYM_DEF { algorithm: SymmetricAlgorithm::Aes.into(), keyBits: TPMU_SYM_KEY_BITS { aes: expected_key_bits.into(), }, mode: TPMU_SYM_MODE { aes: expected_mode.into(), }, }; let sym_def = SymmetricDefinition::try_from(expected_tpmt_sym_def) .expect("Failed to convert TPMT_SYM_DEF into SymmetricDefinition"); if let SymmetricDefinition::Aes { key_bits, mode } = sym_def { assert_eq!( expected_key_bits, key_bits, "TPMT_SYM_DEF converted into SymmetricDefinition did not contain the correct value for 'key_bits'" ); assert_eq!(expected_mode, mode, "TPMT_SYM_DEF converted into SymmetricDefinition did not contain the correct value for 'mode'"); } else { panic!("SymmetricDefinition converted from TPMT_SYM_DEF did not contain the expected algorithm AES"); } let actual_tpmt_sym_def = TPMT_SYM_DEF::try_from(sym_def) .expect("Failed to Convert SymmetricDefinition into TPMT_SYM_DEF"); crate::common::ensure_tpmt_sym_def_equality( &expected_tpmt_sym_def, &actual_tpmt_sym_def, ); } } } #[test] fn test_valid_sm4_conversions() { for expected_mode in SYM_MODES { let expected_key_bits = Sm4KeyBits::Sm4_128; let expected_tpmt_sym_def = TPMT_SYM_DEF { algorithm: SymmetricAlgorithm::Sm4.into(), keyBits: TPMU_SYM_KEY_BITS { sm4: expected_key_bits.into(), }, mode: TPMU_SYM_MODE { sm4: expected_mode.into(), }, }; let sym_def = SymmetricDefinition::try_from(expected_tpmt_sym_def) .expect("Failed to convert TPMT_SYM_DEF into SymmetricDefinition"); if let SymmetricDefinition::Sm4 { key_bits, mode } = sym_def { assert_eq!( expected_key_bits, key_bits, "TPMT_SYM_DEF converted into SymmetricDefinition did not contain the correct value for 'key_bits'" ); assert_eq!(expected_mode, mode, "TPMT_SYM_DEF converted into SymmetricDefinition did not contain the correct value for 'mode'"); } else { panic!("SymmetricDefinition converted from TPMT_SYM_DEF did not contain the expected algorithm SM4"); } let actual_tpmt_sym_def = TPMT_SYM_DEF::try_from(sym_def) .expect("Failed to Convert SymmetricDefinition into TPMT_SYM_DEF"); crate::common::ensure_tpmt_sym_def_equality(&expected_tpmt_sym_def, &actual_tpmt_sym_def); } } #[test] fn test_valid_camellia_conversions() { const CAMELLIA_KEY_BITS: [CamelliaKeyBits; 3] = [ CamelliaKeyBits::Camellia128, CamelliaKeyBits::Camellia192, CamelliaKeyBits::Camellia256, ]; for expected_mode in SYM_MODES { for expected_key_bits in CAMELLIA_KEY_BITS { let expected_tpmt_sym_def = TPMT_SYM_DEF { algorithm: SymmetricAlgorithm::Camellia.into(), keyBits: TPMU_SYM_KEY_BITS { camellia: expected_key_bits.into(), }, mode: TPMU_SYM_MODE { camellia: expected_mode.into(), }, }; let sym_def = SymmetricDefinition::try_from(expected_tpmt_sym_def) .expect("Failed to convert TPMT_SYM_DEF into SymmetricDefinition"); if let SymmetricDefinition::Camellia { key_bits, mode } = sym_def { assert_eq!( expected_key_bits, key_bits, "TPMT_SYM_DEF converted into SymmetricDefinition did not contain the correct value for 'key_bits'" ); assert_eq!(expected_mode, mode, "TPMT_SYM_DEF converted into SymmetricDefinition did not contain the correct value for 'mode'"); } else { panic!("SymmetricDefinition converted from TPMT_SYM_DEF did not contain the expected algorithm CAMELLIA"); } let actual_tpmt_sym_def = TPMT_SYM_DEF::try_from(sym_def) .expect("Failed to Convert SymmetricDefinition into TPMT_SYM_DEF"); crate::common::ensure_tpmt_sym_def_equality( &expected_tpmt_sym_def, &actual_tpmt_sym_def, ); } } } #[test] fn test_valid_xor_conversions() { const HASHING_ALGORITHMS: [HashingAlgorithm; 8] = [ HashingAlgorithm::Sha1, HashingAlgorithm::Sha256, HashingAlgorithm::Sha384, HashingAlgorithm::Sha512, HashingAlgorithm::Sm3_256, HashingAlgorithm::Sha3_256, HashingAlgorithm::Sha3_384, HashingAlgorithm::Sha3_512, ]; for expected_hashing_algorithm in HASHING_ALGORITHMS { let expected_tpmt_sym_def = TPMT_SYM_DEF { algorithm: SymmetricAlgorithm::Xor.into(), keyBits: TPMU_SYM_KEY_BITS { exclusiveOr: expected_hashing_algorithm.into(), }, mode: Default::default(), }; let sym_def = SymmetricDefinition::try_from(expected_tpmt_sym_def) .expect("Failed to convert TPMT_SYM_DEF into SymmetricDefinition"); if let SymmetricDefinition::Xor { hashing_algorithm } = sym_def { assert_eq!( expected_hashing_algorithm, hashing_algorithm, "TPMT_SYM_DEF converted into SymmetricDefinition did not contain the correct value for 'key_bits'", ); } else { panic!("SymmetricDefinition converted from TPMT_SYM_DEF did not contain the expected algorithm XOR"); } let actual_tpmt_sym_def = TPMT_SYM_DEF::try_from(sym_def) .expect("Failed to Convert SymmetricDefinition into TPMT_SYM_DEF"); crate::common::ensure_tpmt_sym_def_equality(&expected_tpmt_sym_def, &actual_tpmt_sym_def); } } #[test] fn test_valid_null_conversions() { let expected_tpmt_sym_def = TPMT_SYM_DEF { algorithm: SymmetricAlgorithm::Null.into(), keyBits: Default::default(), mode: Default::default(), }; let sym_def = SymmetricDefinition::try_from(expected_tpmt_sym_def) .expect("Failed to convert TPMT_SYM_DEF into SymmetricDefinition"); if sym_def != SymmetricDefinition::Null { panic!("SymmetricDefinition converted from TPMT_SYM_DEF did not contain the expected algorithm NULL"); } let actual_tpmt_sym_def = TPMT_SYM_DEF::try_from(sym_def) .expect("Failed to Convert SymmetricDefinition into TPMT_SYM_DEF"); crate::common::ensure_tpmt_sym_def_equality(&expected_tpmt_sym_def, &actual_tpmt_sym_def); } #[test] fn test_invalid_symmetric_algorithm_conversion() { let invalid_alg_tpmt_sym_def = TPMT_SYM_DEF { algorithm: AlgorithmIdentifier::RsaPss.into(), keyBits: Default::default(), mode: Default::default(), }; assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), SymmetricDefinition::try_from(invalid_alg_tpmt_sym_def), "Converting TPMT_SYM_DEF with an invalid symmetric algorithm did not produce the expected error" ); } #[test] fn test_invalid_xor_with_null_conversions() { let invalid_alg_tpmt_sym_def = TPMT_SYM_DEF { algorithm: SymmetricAlgorithm::Xor.into(), keyBits: TPMU_SYM_KEY_BITS { exclusiveOr: HashingAlgorithm::Null.into(), }, mode: Default::default(), }; assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), SymmetricDefinition::try_from(invalid_alg_tpmt_sym_def), "Converting TPMT_SYM_DEF with an invalid XOR hashing algorithm did not produce the expected error" ); let invalid_sym_def = SymmetricDefinition::Xor { hashing_algorithm: HashingAlgorithm::Null, }; if let Err(actual_error) = TPMT_SYM_DEF::try_from(invalid_sym_def) { assert_eq!( Error::WrapperError(WrapperErrorKind::InvalidParam), actual_error, "Converting SymmetricDefinition with invalid XOR hashing algorithm did not produce the expected error" ); } else { panic!("Converting SymmetricDefinition with invalid XOR hashing algorithm did not produce an error"); } } ././@LongLink00006440000000000000000000000147000000000000007775Lustar tss-esapi-7.4.0/tests/integration_tests/structures_tests/tagged_tests/tagged_signature_scheme_tests.rstss-esapi-7.4.0/tests/integration_tests/structures_tests/tagged_tests/tagged_signature_scheme_tests.000064400000000000000000000152371046102023000326700ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use tss_esapi::{ interface_types::algorithm::{HashingAlgorithm, SignatureSchemeAlgorithm}, structures::{EcDaaScheme, HashScheme, HmacScheme, SignatureScheme}, tss2_esys::{ TPMS_SCHEME_ECDAA, TPMS_SCHEME_HASH, TPMS_SCHEME_HMAC, TPMT_SIG_SCHEME, TPMU_SIG_SCHEME, }, Error, WrapperErrorKind, }; use std::convert::{TryFrom, TryInto}; fn validate_tss_hash_scheme( left: &TPMS_SCHEME_HASH, right: &TPMS_SCHEME_HASH, union_field_name: &str, ) { assert_eq!( left.hashAlg, right.hashAlg, "{} in details, hashAlg did not match", union_field_name ); } fn validate_tss_ecdaa_scheme( left: &TPMS_SCHEME_ECDAA, right: &TPMS_SCHEME_ECDAA, union_field_name: &str, ) { assert_eq!( left.hashAlg, right.hashAlg, "{} in details, hashAlg did not match", union_field_name ); assert_eq!( left.count, right.count, "{} in details, count did not match", union_field_name ); } fn validate_tss_hmac_scheme( left: &TPMS_SCHEME_HMAC, right: &TPMS_SCHEME_HMAC, union_field_name: &str, ) { assert_eq!( left.hashAlg, right.hashAlg, "{} in details, hashAlg did not match", union_field_name ); } macro_rules! test_valid_conversions_generic { (SignatureScheme::$item:ident, $union_field_name:ident, $tss_details_field_validator:expr, $native_scheme_field:ident, $native_scheme:expr) => { let tss_actual: TPMT_SIG_SCHEME = SignatureScheme::$item { $native_scheme_field: $native_scheme } .try_into() .expect(&format!("Failed to convert {} signature scheem into TSS type", stringify!($item))); let tss_expected = TPMT_SIG_SCHEME { scheme: SignatureSchemeAlgorithm::$item.into(), details: TPMU_SIG_SCHEME { $union_field_name: $native_scheme.into(), }, }; assert_eq!( tss_actual.scheme, tss_expected.scheme, "scheme for Actual converted value did not match expected in TSS types for SignatureScheme {}", stringify!($item), ); $tss_details_field_validator( &unsafe { tss_actual.details.$union_field_name }, &unsafe { tss_expected.details.$union_field_name }, stringify!($union_field_name), ); let native_expected = SignatureScheme::$item { $native_scheme_field: $native_scheme }; let native_actual = SignatureScheme::try_from(tss_expected) .expect(&format!("Failed to convert TSS type into {}", stringify!($item))); assert_eq!( native_actual, native_expected, "The actual SignatureScheme did not match expected", ); }; // For a selector that has no data (SignatureScheme::$item:ident) => { let tss_actual: TPMT_SIG_SCHEME = SignatureScheme::$item .try_into() .expect(&format!("Failed to convert {} signature scheem into TSS type", stringify!($item))); let tss_expected = TPMT_SIG_SCHEME { scheme: SignatureSchemeAlgorithm::$item.into(), details: Default::default(), }; assert_eq!( tss_actual.scheme, tss_expected.scheme, "scheme for Actual converted value did not match expected in TSS types for SignatureScheme {}", stringify!($item), ); let native_expected = SignatureScheme::$item; let native_actual = SignatureScheme::try_from(tss_expected) .expect(&format!("Failed to convert TSS type into {}", stringify!($item))); assert_eq!( native_actual, native_expected, "The actual SignatureScheme did not match expected", ); }; } macro_rules! test_valid_conversions { (SignatureScheme::EcDaa, $union_field_name:ident) => { test_valid_conversions_generic!( SignatureScheme::EcDaa, $union_field_name, validate_tss_ecdaa_scheme, ecdaa_scheme, EcDaaScheme::new(HashingAlgorithm::Sha256, 1) ); }; (SignatureScheme::Hmac, $union_field_name:ident) => { test_valid_conversions_generic!( SignatureScheme::Hmac, $union_field_name, validate_tss_hmac_scheme, hmac_scheme, HmacScheme::new(HashingAlgorithm::Sha256) ); }; (SignatureScheme::$item:ident, $union_field_name:ident) => { test_valid_conversions_generic!( SignatureScheme::$item, $union_field_name, validate_tss_hash_scheme, hash_scheme, HashScheme::new(HashingAlgorithm::Sha256) ); }; (SignatureScheme::Null) => { test_valid_conversions_generic!(SignatureScheme::Null); }; } #[test] fn test_conversions() { test_valid_conversions!(SignatureScheme::RsaSsa, rsassa); test_valid_conversions!(SignatureScheme::RsaPss, rsapss); test_valid_conversions!(SignatureScheme::EcDsa, ecdsa); test_valid_conversions!(SignatureScheme::Sm2, sm2); test_valid_conversions!(SignatureScheme::EcSchnorr, ecschnorr); test_valid_conversions!(SignatureScheme::EcDaa, ecdaa); test_valid_conversions!(SignatureScheme::Hmac, hmac); test_valid_conversions!(SignatureScheme::Null); } #[test] fn test_valid_any_sig() { let mut signature_scheme = SignatureScheme::RsaPss { hash_scheme: HashScheme::new(HashingAlgorithm::Sha256), }; assert_eq!( HashingAlgorithm::Sha256, signature_scheme .signing_scheme() .expect("Failed to get signing scheme digest"), "The signing scheme method did not return the correct value" ); signature_scheme .set_signing_scheme(HashingAlgorithm::Sha384) .expect("Failed to change signing scheme digest"); assert_eq!( HashingAlgorithm::Sha384, signature_scheme .signing_scheme() .expect("Failed to get signing key digest"), "The signing scheme method did not return the correct value after change." ); } #[test] fn test_invalid_any_sig() { let mut signature_scheme = SignatureScheme::Null; assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), signature_scheme.signing_scheme(), "Trying to get signing scheme digest from a non signing SignatureScheme did not produce the expected error", ); assert_eq!( Err(Error::WrapperError(WrapperErrorKind::InvalidParam)), signature_scheme.set_signing_scheme(HashingAlgorithm::Sha256), "Trying to set signing scheme digest on a non signing SignatureScheme did not produce the expected error", ) } tss-esapi-7.4.0/tests/integration_tests/structures_tests/time_attest_info_tests.rs000064400000000000000000000032651046102023000272530ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; use tss_esapi::{ interface_types::YesNo, structures::{TimeAttestInfo, TimeInfo}, tss2_esys::{TPMS_CLOCK_INFO, TPMS_TIME_ATTEST_INFO, TPMS_TIME_INFO}, }; #[test] fn test_conversion() { let expected_time_info = TimeInfo::try_from(TPMS_TIME_INFO { time: 12u64, clockInfo: TPMS_CLOCK_INFO { clock: 1u64, resetCount: 2u32, restartCount: 3u32, safe: YesNo::Yes.into(), }, }) .expect("Failed to convert TPMS_TIME_INFO into TimeInfo"); let expected_firmware_version = 0xfffffu64; let expected_tpms_time_attest_info = TPMS_TIME_ATTEST_INFO { time: expected_time_info.into(), firmwareVersion: expected_firmware_version, }; let time_attest_info = TimeAttestInfo::try_from(expected_tpms_time_attest_info) .expect("Unable to convert TPMS_TIME_ATTEST_INFO into TimeAttestInfo"); assert_eq!( &expected_time_info, time_attest_info.time_info(), "The TimeAttestInfo that was converted from TPMS_TIME_ATTEST_INFO, did not contain the expected value for 'time info'", ); assert_eq!( expected_firmware_version, time_attest_info.firmware_version(), "The TimeAttestInfo that was converted from TPMS_TIME_ATTEST_INFO, did not contain the expected value for 'firmware version'", ); let actual_tpms_time_attest_info: TPMS_TIME_ATTEST_INFO = time_attest_info.into(); crate::common::ensure_tpms_time_attest_info_equality( &expected_tpms_time_attest_info, &actual_tpms_time_attest_info, ); } tss-esapi-7.4.0/tests/integration_tests/structures_tests/time_info_tests.rs000064400000000000000000000025051046102023000256630ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use tss_esapi::{ interface_types::YesNo, structures::{ClockInfo, TimeInfo}, tss2_esys::{TPMS_CLOCK_INFO, TPMS_TIME_INFO}, }; use std::convert::TryFrom; #[test] fn test_conversion() { let expected_time = 1u64; let expected_clock_info = ClockInfo::try_from(TPMS_CLOCK_INFO { clock: 1u64, resetCount: 2u32, restartCount: 3u32, safe: YesNo::Yes.into(), }) .expect("Failed to create ClockInfo"); let expected_tpms_time_info = TPMS_TIME_INFO { time: expected_time, clockInfo: expected_clock_info.into(), }; let time_info = TimeInfo::try_from(expected_tpms_time_info) .expect("Failed to convert TPMS_TIME_INFO into TimeInfo"); assert_eq!( expected_time, time_info.time(), "The TimeInfo that was converted from TPMS_TIME_INFO, did not contain the expected value for time", ); assert_eq!( &expected_clock_info, time_info.clock_info(), "The TimeInfo that was converted from TPMS_TIME_INFO, did not contain the expected value for 'clock info'", ); let actual_tpms_time_info = time_info.into(); crate::common::ensure_tpms_time_info_equality(&expected_tpms_time_info, &actual_tpms_time_info); } tss-esapi-7.4.0/tests/integration_tests/tcti_ldr_tests/mod.rs000064400000000000000000000007221046102023000226270ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use std::env; use std::str::FromStr; use tss_esapi::tcti_ldr::TctiNameConf; #[allow(dead_code)] pub fn name_conf() -> TctiNameConf { match env::var("TEST_TCTI") { Err(_) => TctiNameConf::Mssim(Default::default()), Ok(tctistr) => TctiNameConf::from_str(&tctistr).expect("Error parsing TEST_TCTI"), } } mod tcti_context_tests; mod tcti_info_tests; tss-esapi-7.4.0/tests/integration_tests/tcti_ldr_tests/tcti_context_tests.rs000064400000000000000000000003721046102023000260020ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use tss_esapi::tcti_ldr::TctiContext; #[test] fn new_context() { let _context = TctiContext::initialize(crate::tcti_ldr_tests::name_conf()).unwrap(); } tss-esapi-7.4.0/tests/integration_tests/tcti_ldr_tests/tcti_info_tests.rs000064400000000000000000000006011046102023000252440ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use tss_esapi::tcti_ldr::TctiInfo; #[test] fn new_info() { let info = TctiInfo::get_info(crate::tcti_ldr_tests::name_conf()).unwrap(); let _version = info.version(); let _name = info.name(); let _description = info.description(); let _config_help = info.config_help(); } tss-esapi-7.4.0/tests/integration_tests/utils_tests/get_tpm_vendor_test.rs000064400000000000000000000006111046102023000254540ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use tss_esapi::utils; // Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::common::create_ctx_without_session; #[test] fn get_tpm_vendor() { let mut context = create_ctx_without_session(); utils::get_tpm_vendor(&mut context).unwrap(); } tss-esapi-7.4.0/tests/integration_tests/utils_tests/mod.rs000064400000000000000000000001661046102023000221650ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod get_tpm_vendor_test; tss-esapi-7.4.0/tests/pkg-config000075500000000000000000000003321046102023000146560ustar 00000000000000#!/bin/sh export PKG_CONFIG_PATH= export PKG_CONFIG_LIBDIR=${SYSROOT}/usr/lib/pkgconfig:${SYSROOT}/usr/share/pkgconfig:$(SYSROOT)/usr/local/lib/pkgconfig export PKG_CONFIG_SYSROOT_DIR=${SYSROOT} exec pkg-config "$@" tss-esapi-7.4.0/tests/valgrind.sh000075500000000000000000000012451046102023000150550ustar 00000000000000#!/usr/bin/env bash # Copyright 2022 Contributors to the Parsec project. # SPDX-License-Identifier: Apache-2.0 # Script for running valgrind against the set of tests # Intended for running in the Ubuntu container set -euf -o pipefail ################################# # Run the TPM simulation server # ################################# tpm_server & sleep 5 tpm2_startup -c -T mssim ########################## # Install cargo-valgrind # ########################## apt install -y valgrind cargo install cargo-valgrind ################# # Run the tests # ################# TEST_TCTI=mssim: RUST_BACKTRACE=1 RUST_LOG=info cargo valgrind test -- --test-threads=1 --nocapture